[findbugs] 01/02: Imported Upstream version 3.0.1
Sylvestre Ledru
sylvestre at moszumanska.debian.org
Thu May 7 09:47:34 UTC 2015
This is an automated email from the git hooks/post-receive script.
sylvestre pushed a commit to branch master
in repository findbugs.
commit 0a95bade27ece607c89f25ea79f1769c326d7056
Author: Sylvestre Ledru <sylvestre at debian.org>
Date: Thu May 7 11:47:02 2015 +0200
Imported Upstream version 3.0.1
---
.classpath | 23 +-
.settings/de.loskutov.anyedit.AnyEditTools.prefs | 6 +-
.settings/edu.umd.cs.findbugs.core.prefs | 142 +-
.settings/edu.umd.cs.findbugs.plugin.eclipse.prefs | 1 -
.settings/org.eclipse.core.resources.prefs | 2 +
.settings/org.eclipse.core.runtime.prefs | 2 +
.settings/org.eclipse.jdt.core.prefs | 11 +-
.settings/org.eclipse.jdt.ui.prefs | 81 +-
META-INF/MANIFEST.MF | 17 +-
build.xml | 308 +-
design/architecture/mkdep.pl | 0
etc/MANIFEST-findbugs-annotations.MF | 2 +-
etc/MANIFEST-findbugs-internal-annotations.MF | 2 +-
etc/MANIFEST-findbugs.MF | 2 +-
etc/MANIFEST-findbugsGUI.MF | 2 +-
etc/bugcollection.xsd | 1232 ++---
etc/bugrank.txt | 7 +-
etc/diffBugSummaries | 0
etc/doc.properties | 46 +-
etc/docbook/dbpoolx.mod | 3310 ++++++------
etc/findbugs.xml | 125 +-
etc/findbugsfilter.xsd | 400 ++
etc/messagecollection.xsd | 6 +-
etc/messages.xml | 634 ++-
etc/messages_fr.xml | 2 +
etc/messages_ja.xml | 1230 +++--
etc/summarizeBugs | 0
findbugsExclude.xml | 100 +-
jnlp/core.jnlp | 0
pom.xml | 42 +-
runMaven | 5 +
.../cs/findbugs/anttask/AbstractFindBugsTask.java | 32 +-
.../cs/findbugs/anttask/ComputeBugHistoryTask.java | 14 +-
.../cs/findbugs/anttask/ConvertXmlToTextTask.java | 69 +-
.../edu/umd/cs/findbugs/anttask/DataFile.java | 2 +-
.../umd/cs/findbugs/anttask/FilterBugsTask.java | 12 +-
.../edu/umd/cs/findbugs/anttask/FindBugsTask.java | 106 +-
.../cs/findbugs/anttask/FindBugsViewerTask.java | 33 +-
.../cs/findbugs/anttask/MineBugHistoryTask.java | 12 +-
.../findbugs/anttask/SetBugDatabaseInfoTask.java | 14 +-
.../edu/umd/cs/findbugs/anttask/UnionBugs.java | 37 +-
.../edu/umd/cs/findbugs/anttask/UnionBugs2.java | 26 +-
src/doc/Changes.html | 5629 ++++++++++----------
src/doc/FAQ.html | 10 +-
src/doc/contributing.html | 40 +-
src/doc/downloads.html | 5 +-
src/doc/index.html | 171 +-
src/doc/links.html | 5 +-
src/doc/manual.xml | 173 +-
src/doc/manual_ja.xml | 385 +-
src/doc/performance.html | 22 +-
src/doc/reportingBugs.html | 16 +-
.../edu/umd/cs/findbugs/gui/AnnotatedString.java | 19 +-
src/gui/edu/umd/cs/findbugs/gui2/AboutDialog.java | 13 +-
.../cs/findbugs/gui2/AbstractSwingGuiCallback.java | 542 +-
.../edu/umd/cs/findbugs/gui2/AnalyzingDialog.java | 65 +-
.../edu/umd/cs/findbugs/gui2/ApplyNewFilter.java | 14 +-
src/gui/edu/umd/cs/findbugs/gui2/BugAspects.java | 24 +-
src/gui/edu/umd/cs/findbugs/gui2/BugLeafNode.java | 16 +-
src/gui/edu/umd/cs/findbugs/gui2/BugLoader.java | 76 +-
src/gui/edu/umd/cs/findbugs/gui2/BugRenderer.java | 19 +-
src/gui/edu/umd/cs/findbugs/gui2/BugSet.java | 101 +-
src/gui/edu/umd/cs/findbugs/gui2/BugTreeModel.java | 187 +-
src/gui/edu/umd/cs/findbugs/gui2/CheckBoxList.java | 19 +-
.../umd/cs/findbugs/gui2/CloudCommentsPane.java | 2151 ++++----
src/gui/edu/umd/cs/findbugs/gui2/CommentsArea.java | 15 +-
.../edu/umd/cs/findbugs/gui2/CompoundMatcher.java | 8 +-
.../edu/umd/cs/findbugs/gui2/DeadBugFilter.java | 11 -
src/gui/edu/umd/cs/findbugs/gui2/Debug.java | 13 +-
.../cs/findbugs/gui2/DisplayNonmodelMessage.java | 25 +-
src/gui/edu/umd/cs/findbugs/gui2/Driver.java | 145 +-
src/gui/edu/umd/cs/findbugs/gui2/FBDialog.java | 12 +-
.../edu/umd/cs/findbugs/gui2/FBFileChooser.java | 24 +-
src/gui/edu/umd/cs/findbugs/gui2/FBFrame.java | 5 +-
.../edu/umd/cs/findbugs/gui2/FilterActivity.java | 7 +-
.../edu/umd/cs/findbugs/gui2/FilterFactory.java | 34 +-
.../umd/cs/findbugs/gui2/FilterFromBugPicker.java | 30 +-
.../edu/umd/cs/findbugs/gui2/FilterMatcher.java | 69 +-
.../edu/umd/cs/findbugs/gui2/GUI2CommandLine.java | 20 +-
src/gui/edu/umd/cs/findbugs/gui2/GUISaveState.java | 66 +-
src/gui/edu/umd/cs/findbugs/gui2/MainFrame.java | 207 +-
.../findbugs/gui2/MainFrameComponentFactory.java | 70 +-
.../cs/findbugs/gui2/MainFrameLoadSaveHelper.java | 131 +-
.../edu/umd/cs/findbugs/gui2/MainFrameMenu.java | 153 +-
.../edu/umd/cs/findbugs/gui2/MainFrameTree.java | 143 +-
.../edu/umd/cs/findbugs/gui2/NewFilterFrame.java | 32 +-
.../edu/umd/cs/findbugs/gui2/NewFilterFromBug.java | 8 +-
.../edu/umd/cs/findbugs/gui2/NewProjectWizard.java | 163 +-
src/gui/edu/umd/cs/findbugs/gui2/OSXAdapter.java | 4 +-
.../umd/cs/findbugs/gui2/PluginUpdateDialog.java | 413 +-
.../edu/umd/cs/findbugs/gui2/PreferencesFrame.java | 161 +-
.../edu/umd/cs/findbugs/gui2/ProjectSettings.java | 28 +-
.../edu/umd/cs/findbugs/gui2/PropertiesDialog.java | 22 +-
src/gui/edu/umd/cs/findbugs/gui2/RecentMenu.java | 10 +-
src/gui/edu/umd/cs/findbugs/gui2/SaveType.java | 23 +-
.../cs/findbugs/gui2/SortableStringComparator.java | 1 +
src/gui/edu/umd/cs/findbugs/gui2/Sortables.java | 123 +-
src/gui/edu/umd/cs/findbugs/gui2/SorterDialog.java | 20 +-
.../cs/findbugs/gui2/SorterTableColumnModel.java | 98 +-
.../umd/cs/findbugs/gui2/SourceCodeDisplay.java | 81 +-
.../cs/findbugs/gui2/SourceDirectoryWizard.java | 52 +-
src/gui/edu/umd/cs/findbugs/gui2/SplashFrame.java | 20 +-
src/gui/edu/umd/cs/findbugs/gui2/SplitLayout.java | 22 +-
.../edu/umd/cs/findbugs/gui2/SpringUtilities.java | 14 +-
.../umd/cs/findbugs/gui2/StackedFilterMatcher.java | 65 +-
.../umd/cs/findbugs/gui2/SuppressionMatcher.java | 5 +-
src/gui/edu/umd/cs/findbugs/gui2/ViewFilter.java | 86 +-
src/gui/edu/umd/cs/findbugs/gui2/WideComboBox.java | 92 +-
.../sourceViewer/DocumentCharacterIterator.java | 11 +-
.../sourceViewer/HighlightInformation.java | 6 +-
.../umd/cs/findbugs/sourceViewer/JavaScanner.java | 34 +-
.../findbugs/sourceViewer/JavaSourceDocument.java | 21 +-
.../findbugs/sourceViewer/NavigableTextPane.java | 23 +-
.../sourceViewer/NumberedParagraphView.java | 6 +-
.../findbugs/sourceViewer/NumberedViewFactory.java | 14 +-
.../edu/umd/cs/findbugs/AWTEventQueueExecutor.java | 94 +-
.../edu/umd/cs/findbugs/AbstractBugReporter.java | 25 +-
src/java/edu/umd/cs/findbugs/AddAnnotation.java | 10 +-
src/java/edu/umd/cs/findbugs/AddMessages.java | 6 +-
.../findbugs/AnalysisCacheToRepositoryAdapter.java | 28 +-
src/java/edu/umd/cs/findbugs/AnalysisError.java | 51 +-
src/java/edu/umd/cs/findbugs/Analyze.java | 70 +-
src/java/edu/umd/cs/findbugs/AppVersion.java | 20 +-
src/java/edu/umd/cs/findbugs/BugAccumulator.java | 50 +-
src/java/edu/umd/cs/findbugs/BugAnnotation.java | 9 +-
.../edu/umd/cs/findbugs/BugAnnotationUtil.java | 10 +-
.../edu/umd/cs/findbugs/BugAnnotationVisitor.java | 1 -
.../cs/findbugs/BugAnnotationWithSourceLines.java | 3 +-
src/java/edu/umd/cs/findbugs/BugCategory.java | 16 +-
src/java/edu/umd/cs/findbugs/BugCode.java | 5 +-
src/java/edu/umd/cs/findbugs/BugCollection.java | 17 +-
.../umd/cs/findbugs/BugCollectionBugReporter.java | 15 +-
src/java/edu/umd/cs/findbugs/BugDesignation.java | 78 +-
src/java/edu/umd/cs/findbugs/BugInstance.java | 592 +-
src/java/edu/umd/cs/findbugs/BugPattern.java | 83 +-
src/java/edu/umd/cs/findbugs/BugProperty.java | 23 +-
src/java/edu/umd/cs/findbugs/BugRanker.java | 88 +-
src/java/edu/umd/cs/findbugs/BugReporter.java | 13 +-
.../edu/umd/cs/findbugs/BugReporterObserver.java | 5 +-
.../umd/cs/findbugs/ByteCodePatternDetector.java | 21 +-
.../umd/cs/findbugs/BytecodeScanningDetector.java | 9 +-
src/java/edu/umd/cs/findbugs/CallGraph.java | 3 +-
src/java/edu/umd/cs/findbugs/CallGraphEdge.java | 1 -
src/java/edu/umd/cs/findbugs/CallGraphNode.java | 1 -
src/java/edu/umd/cs/findbugs/CallSite.java | 6 +-
.../cs/findbugs/CategoryFilteringBugReporter.java | 5 +-
src/java/edu/umd/cs/findbugs/CheckBcel.java | 10 +-
src/java/edu/umd/cs/findbugs/ClassAnnotation.java | 46 +-
src/java/edu/umd/cs/findbugs/ClassScreener.java | 54 +-
.../umd/cs/findbugs/ClassWarningSuppressor.java | 9 +-
.../edu/umd/cs/findbugs/CommandLineUiCallback.java | 20 +
src/java/edu/umd/cs/findbugs/ComponentPlugin.java | 3 +-
.../edu/umd/cs/findbugs/DeepSubtypeAnalysis.java | 74 +-
.../edu/umd/cs/findbugs/DelegatingBugReporter.java | 20 +-
src/java/edu/umd/cs/findbugs/Detector.java | 3 +-
src/java/edu/umd/cs/findbugs/Detector2.java | 6 +-
src/java/edu/umd/cs/findbugs/DetectorFactory.java | 29 +-
.../umd/cs/findbugs/DetectorFactoryChooser.java | 6 +-
.../umd/cs/findbugs/DetectorFactoryCollection.java | 124 +-
.../cs/findbugs/DetectorToDetector2Adapter.java | 15 +-
.../umd/cs/findbugs/DiscoverSourceDirectories.java | 35 +-
src/java/edu/umd/cs/findbugs/EmacsBugReporter.java | 12 +-
.../umd/cs/findbugs/ErrorCountingBugReporter.java | 14 +-
.../cs/findbugs/ExcludingHashesBugReporter.java | 8 +-
src/java/edu/umd/cs/findbugs/ExitCodes.java | 1 -
src/java/edu/umd/cs/findbugs/FatalException.java | 6 +-
src/java/edu/umd/cs/findbugs/FieldAnnotation.java | 121 +-
.../umd/cs/findbugs/FieldWarningSuppressor.java | 11 +-
.../edu/umd/cs/findbugs/FilterBugReporter.java | 14 +-
src/java/edu/umd/cs/findbugs/FindBugs.java | 168 +-
src/java/edu/umd/cs/findbugs/FindBugs2.java | 533 +-
.../FindBugsAnnotationDescriptions.properties | 5 +-
.../FindBugsAnnotationDescriptions_ja.properties | 206 +-
.../edu/umd/cs/findbugs/FindBugsCommandLine.java | 27 +-
src/java/edu/umd/cs/findbugs/FindBugsMain.java | 16 +-
.../edu/umd/cs/findbugs/FindBugsMessageFormat.java | 27 +-
src/java/edu/umd/cs/findbugs/FindBugsProgress.java | 11 +-
.../edu/umd/cs/findbugs/FirstPassDetector.java | 4 +-
src/java/edu/umd/cs/findbugs/Footprint.java | 12 +-
.../edu/umd/cs/findbugs/FuzzyBugComparator.java | 102 +-
src/java/edu/umd/cs/findbugs/HTMLBugReporter.java | 9 +-
src/java/edu/umd/cs/findbugs/I18N.java | 61 +-
src/java/edu/umd/cs/findbugs/IClassScreener.java | 2 +-
src/java/edu/umd/cs/findbugs/IFindBugsEngine.java | 50 +-
src/java/edu/umd/cs/findbugs/IGuiCallback.java | 12 +-
.../edu/umd/cs/findbugs/InstructionScanner.java | 1 -
.../umd/cs/findbugs/InstructionScannerDriver.java | 18 +-
.../cs/findbugs/InstructionScannerGenerator.java | 1 -
src/java/edu/umd/cs/findbugs/IntAnnotation.java | 56 +-
.../findbugs/InterproceduralFirstPassDetector.java | 2 +-
src/java/edu/umd/cs/findbugs/JavaVersion.java | 15 +-
.../edu/umd/cs/findbugs/JavaVersionException.java | 1 -
src/java/edu/umd/cs/findbugs/L10N.java | 19 +-
.../edu/umd/cs/findbugs/LaunchAppropriateUI.java | 6 +-
.../umd/cs/findbugs/LocalVariableAnnotation.java | 98 +-
src/java/edu/umd/cs/findbugs/Lookup.java | 34 +-
src/java/edu/umd/cs/findbugs/MethodAnnotation.java | 110 +-
.../umd/cs/findbugs/MethodWarningSuppressor.java | 9 +-
src/java/edu/umd/cs/findbugs/NewResults.java | 5 +-
.../findbugs/NoClassesFoundToAnalyzeException.java | 9 +-
.../edu/umd/cs/findbugs/NoOpFindBugsProgress.java | 7 +
.../edu/umd/cs/findbugs/NonReportingDetector.java | 2 +-
src/java/edu/umd/cs/findbugs/Obfuscate.java | 40 +-
src/java/edu/umd/cs/findbugs/OpcodeStack.java | 1264 +++--
.../umd/cs/findbugs/PackageMemberAnnotation.java | 39 +-
src/java/edu/umd/cs/findbugs/PackageStats.java | 57 +-
.../umd/cs/findbugs/PackageWarningSuppressor.java | 6 +-
.../cs/findbugs/ParameterWarningSuppressor.java | 12 +-
src/java/edu/umd/cs/findbugs/Plugin.java | 109 +-
src/java/edu/umd/cs/findbugs/PluginException.java | 7 +-
src/java/edu/umd/cs/findbugs/PluginLoader.java | 161 +-
.../edu/umd/cs/findbugs/PrintingBugReporter.java | 90 +-
src/java/edu/umd/cs/findbugs/ProgramPoint.java | 22 +-
src/java/edu/umd/cs/findbugs/Project.java | 102 +-
.../umd/cs/findbugs/ProjectPackagePrefixes.java | 52 +-
src/java/edu/umd/cs/findbugs/ProjectStats.java | 138 +-
src/java/edu/umd/cs/findbugs/PropertyBundle.java | 33 +-
.../edu/umd/cs/findbugs/QueryBugAnnotations.java | 11 +-
.../edu/umd/cs/findbugs/RecursiveFileSearch.java | 28 +-
.../edu/umd/cs/findbugs/ResourceCollection.java | 13 +-
.../edu/umd/cs/findbugs/ResourceCreationPoint.java | 5 +-
.../umd/cs/findbugs/ResourceTrackingDetector.java | 34 +-
.../umd/cs/findbugs/SAXBugCollectionHandler.java | 303 +-
src/java/edu/umd/cs/findbugs/SelfCalls.java | 39 +-
src/java/edu/umd/cs/findbugs/ShowHelp.java | 43 +-
.../edu/umd/cs/findbugs/SloppyBugComparator.java | 64 +-
.../edu/umd/cs/findbugs/SortedBugCollection.java | 239 +-
.../edu/umd/cs/findbugs/SortingBugReporter.java | 9 +-
.../edu/umd/cs/findbugs/SourceLineAnnotation.java | 202 +-
src/java/edu/umd/cs/findbugs/StackMapAnalyzer.java | 247 +-
.../edu/umd/cs/findbugs/StatelessDetector.java | 6 +-
src/java/edu/umd/cs/findbugs/StringAnnotation.java | 23 +-
.../edu/umd/cs/findbugs/SuppressionMatcher.java | 16 +-
src/java/edu/umd/cs/findbugs/SwitchHandler.java | 42 +-
src/java/edu/umd/cs/findbugs/SystemProperties.java | 34 +-
.../{ba/ComparableMethod.java => Test.java} | 16 +-
.../edu/umd/cs/findbugs/TextUIBugReporter.java | 12 +-
.../edu/umd/cs/findbugs/TextUICommandLine.java | 272 +-
.../umd/cs/findbugs/TextUIProgressCallback.java | 11 +-
src/java/edu/umd/cs/findbugs/Token.java | 11 +-
src/java/edu/umd/cs/findbugs/Tokenizer.java | 57 +-
src/java/edu/umd/cs/findbugs/TrainingDetector.java | 2 +-
src/java/edu/umd/cs/findbugs/TypeAnnotation.java | 48 +-
.../edu/umd/cs/findbugs/UseAnnotationDatabase.java | 2 +-
.../umd/cs/findbugs/UserDesignations_ja.properties | 16 +-
src/java/edu/umd/cs/findbugs/Version.java | 83 +-
.../findbugs/VersionInsensitiveBugComparator.java | 116 +-
.../edu/umd/cs/findbugs/WarningComparator.java | 13 +-
.../edu/umd/cs/findbugs/WarningSuppressor.java | 11 +-
src/java/edu/umd/cs/findbugs/XDocsBugReporter.java | 8 +-
src/java/edu/umd/cs/findbugs/XMLBugReporter.java | 4 +-
.../umd/cs/findbugs/XMLWriteableWithMessages.java | 2 +-
.../umd/cs/findbugs/annotations/CheckForNull.java | 6 +-
.../cs/findbugs/annotations/CheckReturnValue.java | 6 +-
.../cs/findbugs/annotations/CleanupObligation.java | 2 +-
.../cs/findbugs/annotations/CreatesObligation.java | 2 +-
.../cs/findbugs/annotations/DefaultAnnotation.java | 12 +-
.../annotations/DefaultAnnotationForFields.java | 8 +-
.../annotations/DefaultAnnotationForMethods.java | 8 +-
.../DefaultAnnotationForParameters.java | 10 +-
.../cs/findbugs/annotations/DesireNoWarning.java | 4 +-
.../umd/cs/findbugs/annotations/DesireWarning.java | 4 +-
.../findbugs/annotations/DischargesObligation.java | 2 +-
.../edu/umd/cs/findbugs/annotations/NonNull.java | 6 +-
.../edu/umd/cs/findbugs/annotations/Nullable.java | 8 +-
.../findbugs/annotations/OverrideMustInvoke.java | 6 +-
.../umd/cs/findbugs/annotations/PossiblyNull.java | 4 +-
.../ReturnValuesAreNonnullByDefault.java | 2 +-
.../findbugs/annotations/SuppressFBWarnings.java | 6 +-
.../cs/findbugs/annotations/SuppressWarnings.java | 6 +-
.../umd/cs/findbugs/annotations/package-info.java | 4 +-
.../cs/findbugs/asm/AbstractFBMethodVisitor.java | 7 +-
.../edu/umd/cs/findbugs/asm/ClassNodeDetector.java | 17 +-
.../edu/umd/cs/findbugs/asm/FBClassReader.java | 12 +-
.../edu/umd/cs/findbugs/asm/FBMethodVisitor.java | 15 +-
.../edu/umd/cs/findbugs/ba/AbstractBlockOrder.java | 10 +-
.../umd/cs/findbugs/ba/AbstractClassMember.java | 55 +-
.../edu/umd/cs/findbugs/ba/AbstractDataflow.java | 8 +-
.../cs/findbugs/ba/AbstractDataflowAnalysis.java | 24 +-
.../cs/findbugs/ba/AbstractDominatorsAnalysis.java | 40 +-
src/java/edu/umd/cs/findbugs/ba/AbstractField.java | 6 +-
.../findbugs/ba/AbstractFrameModelingVisitor.java | 213 +-
.../edu/umd/cs/findbugs/ba/AbstractMethod.java | 17 +-
.../edu/umd/cs/findbugs/ba/AccessibleEntity.java | 2 +-
.../edu/umd/cs/findbugs/ba/AnalysisContext.java | 301 +-
.../edu/umd/cs/findbugs/ba/AnalysisException.java | 15 +-
.../edu/umd/cs/findbugs/ba/AnalysisFeatures.java | 1 -
.../edu/umd/cs/findbugs/ba/AnnotationDatabase.java | 143 +-
.../umd/cs/findbugs/ba/AnnotationEnumeration.java | 6 +-
.../findbugs/ba/AnnotationRetentionDatabase.java | 8 +-
.../edu/umd/cs/findbugs/ba/AssertionMethods.java | 40 +-
.../edu/umd/cs/findbugs/ba/AssignedFieldMap.java | 33 +-
.../cs/findbugs/ba/BackwardDataflowAnalysis.java | 12 +-
.../findbugs/ba/BasicAbstractDataflowAnalysis.java | 20 +-
src/java/edu/umd/cs/findbugs/ba/BasicBlock.java | 83 +-
.../edu/umd/cs/findbugs/ba/BetterCFGBuilder2.java | 232 +-
src/java/edu/umd/cs/findbugs/ba/BlockOrder.java | 3 +-
src/java/edu/umd/cs/findbugs/ba/BlockType.java | 61 +-
.../edu/umd/cs/findbugs/ba/BlockTypeAnalysis.java | 17 +-
.../edu/umd/cs/findbugs/ba/BytecodeScanner.java | 42 +-
src/java/edu/umd/cs/findbugs/ba/CFG.java | 79 +-
src/java/edu/umd/cs/findbugs/ba/CFGBuilder.java | 5 +-
.../edu/umd/cs/findbugs/ba/CFGBuilderFactory.java | 5 +-
src/java/edu/umd/cs/findbugs/ba/CFGPrinter.java | 10 +-
.../findbugs/ba/CheckReturnAnnotationDatabase.java | 36 +-
.../cs/findbugs/ba/CheckReturnValueAnnotation.java | 18 +-
src/java/edu/umd/cs/findbugs/ba/ClassContext.java | 126 +-
src/java/edu/umd/cs/findbugs/ba/ClassHash.java | 59 +-
src/java/edu/umd/cs/findbugs/ba/ClassMember.java | 4 +-
.../findbugs/ba/ClassNotFoundExceptionParser.java | 1 -
src/java/edu/umd/cs/findbugs/ba/ClassSummary.java | 11 +-
.../cs/findbugs/ba/CompactLocationNumbering.java | 14 +-
.../edu/umd/cs/findbugs/ba/ComparableField.java | 6 +-
.../edu/umd/cs/findbugs/ba/ComparableMethod.java | 6 +-
.../umd/cs/findbugs/ba/CompoundMethodChooser.java | 10 +-
src/java/edu/umd/cs/findbugs/ba/DFSCFGPrinter.java | 2 +-
src/java/edu/umd/cs/findbugs/ba/DFSEdgeTypes.java | 2 +-
src/java/edu/umd/cs/findbugs/ba/Dataflow.java | 174 +-
.../edu/umd/cs/findbugs/ba/DataflowAnalysis.java | 27 +-
.../cs/findbugs/ba/DataflowAnalysisException.java | 11 +-
.../edu/umd/cs/findbugs/ba/DataflowCFGPrinter.java | 9 +-
.../umd/cs/findbugs/ba/DataflowValueChooser.java | 2 +-
src/java/edu/umd/cs/findbugs/ba/Debug.java | 1 -
.../ba/DebugRepositoryLookupFailureCallback.java | 20 +-
.../cs/findbugs/ba/DefaultNullnessAnnotations.java | 250 +-
.../edu/umd/cs/findbugs/ba/DepthFirstSearch.java | 5 +-
.../edu/umd/cs/findbugs/ba/DominatorsAnalysis.java | 9 +-
src/java/edu/umd/cs/findbugs/ba/Edge.java | 54 +-
src/java/edu/umd/cs/findbugs/ba/EdgeChooser.java | 4 +-
src/java/edu/umd/cs/findbugs/ba/EdgeTypes.java | 3 +-
.../umd/cs/findbugs/ba/ExceptionHandlerMap.java | 35 +-
src/java/edu/umd/cs/findbugs/ba/FieldSummary.java | 46 +-
.../cs/findbugs/ba/FileSourceFileDataSource.java | 8 +-
.../cs/findbugs/ba/ForwardDataflowAnalysis.java | 10 +-
src/java/edu/umd/cs/findbugs/ba/Frame.java | 130 +-
.../umd/cs/findbugs/ba/FrameDataflowAnalysis.java | 46 +-
src/java/edu/umd/cs/findbugs/ba/Hierarchy.java | 76 +-
src/java/edu/umd/cs/findbugs/ba/Hierarchy2.java | 104 +-
.../findbugs/ba/INullnessAnnotationDatabase.java | 14 +-
.../edu/umd/cs/findbugs/ba/IncompatibleTypes.java | 92 +-
.../edu/umd/cs/findbugs/ba/InnerClassAccess.java | 10 +-
.../umd/cs/findbugs/ba/InnerClassAccessMap.java | 62 +-
.../umd/cs/findbugs/ba/InstructionHandleMap.java | 4 +-
.../cs/findbugs/ba/InvalidBytecodeException.java | 10 +-
.../edu/umd/cs/findbugs/ba/JavaClassAndMethod.java | 14 +-
src/java/edu/umd/cs/findbugs/ba/LineNumberMap.java | 34 +-
.../umd/cs/findbugs/ba/LiveLocalStoreAnalysis.java | 42 +-
.../umd/cs/findbugs/ba/LiveLocalStoreDataflow.java | 3 +-
src/java/edu/umd/cs/findbugs/ba/Location.java | 23 +-
src/java/edu/umd/cs/findbugs/ba/LockAnalysis.java | 37 +-
src/java/edu/umd/cs/findbugs/ba/LockChecker.java | 25 +-
src/java/edu/umd/cs/findbugs/ba/LockDataflow.java | 3 +-
src/java/edu/umd/cs/findbugs/ba/LockSet.java | 114 +-
.../edu/umd/cs/findbugs/ba/MethodBytecodeSet.java | 2 +-
src/java/edu/umd/cs/findbugs/ba/MethodChooser.java | 4 +-
src/java/edu/umd/cs/findbugs/ba/MethodHash.java | 25 +-
.../findbugs/ba/MethodUnprofitableException.java | 8 +-
.../umd/cs/findbugs/ba/MissingClassException.java | 9 +-
.../edu/umd/cs/findbugs/ba/NullnessAnnotation.java | 6 +-
.../cs/findbugs/ba/NullnessAnnotationDatabase.java | 40 +-
.../edu/umd/cs/findbugs/ba/ObjectTypeFactory.java | 12 +-
.../edu/umd/cs/findbugs/ba/OpcodeStackScanner.java | 8 +-
src/java/edu/umd/cs/findbugs/ba/Path.java | 35 +-
src/java/edu/umd/cs/findbugs/ba/PathVisitor.java | 8 +-
.../umd/cs/findbugs/ba/PostDominatorsAnalysis.java | 9 +-
.../findbugs/ba/PruneInfeasibleExceptionEdges.java | 27 +-
.../PruneUnconditionalExceptionThrowerEdges.java | 83 +-
.../edu/umd/cs/findbugs/ba/PutfieldScanner.java | 6 +-
.../umd/cs/findbugs/ba/RepositoryClassParser.java | 11 +-
.../ba/RepositoryLookupFailureCallback.java | 3 +-
.../edu/umd/cs/findbugs/ba/ResourceTracker.java | 22 +-
src/java/edu/umd/cs/findbugs/ba/ResourceValue.java | 6 +-
.../umd/cs/findbugs/ba/ResourceValueAnalysis.java | 33 +-
.../edu/umd/cs/findbugs/ba/ResourceValueFrame.java | 6 +-
.../ba/ResourceValueFrameModelingVisitor.java | 15 +-
src/java/edu/umd/cs/findbugs/ba/ReturnPath.java | 13 +-
.../edu/umd/cs/findbugs/ba/ReturnPathAnalysis.java | 8 +-
.../edu/umd/cs/findbugs/ba/ReturnPathDataflow.java | 1 -
.../edu/umd/cs/findbugs/ba/ReverseDFSOrder.java | 9 +-
.../cs/findbugs/ba/ReverseDepthFirstSearch.java | 5 +-
.../edu/umd/cs/findbugs/ba/ReversePostOrder.java | 8 +-
.../edu/umd/cs/findbugs/ba/SignatureConverter.java | 32 +-
.../edu/umd/cs/findbugs/ba/SignatureParser.java | 55 +-
.../umd/cs/findbugs/ba/SimplePathEnumerator.java | 37 +-
src/java/edu/umd/cs/findbugs/ba/SourceFile.java | 14 +-
.../umd/cs/findbugs/ba/SourceFileDataSource.java | 1 -
src/java/edu/umd/cs/findbugs/ba/SourceFinder.java | 132 +-
src/java/edu/umd/cs/findbugs/ba/SourceInfoMap.java | 94 +-
src/java/edu/umd/cs/findbugs/ba/StackDepth.java | 12 +-
.../edu/umd/cs/findbugs/ba/StackDepthAnalysis.java | 31 +-
src/java/edu/umd/cs/findbugs/ba/Target.java | 7 +-
.../cs/findbugs/ba/TargetEnumeratingVisitor.java | 19 +-
.../edu/umd/cs/findbugs/ba/TestCaseDetector.java | 6 +-
src/java/edu/umd/cs/findbugs/ba/URLClassPath.java | 94 +-
.../umd/cs/findbugs/ba/URLClassPathRepository.java | 26 +-
.../edu/umd/cs/findbugs/ba/UnresolvedXField.java | 28 +-
.../edu/umd/cs/findbugs/ba/UnresolvedXMethod.java | 48 +-
src/java/edu/umd/cs/findbugs/ba/XClass.java | 2 +
src/java/edu/umd/cs/findbugs/ba/XFactory.java | 153 +-
src/java/edu/umd/cs/findbugs/ba/XField.java | 5 +-
src/java/edu/umd/cs/findbugs/ba/XMethod.java | 14 +-
.../edu/umd/cs/findbugs/ba/XMethodParameter.java | 9 +-
.../cs/findbugs/ba/ZipSourceFileDataSource.java | 16 +-
src/java/edu/umd/cs/findbugs/ba/bcp/Binding.java | 8 +-
.../edu/umd/cs/findbugs/ba/bcp/BindingSet.java | 13 +-
.../umd/cs/findbugs/ba/bcp/ByteCodePattern.java | 25 +-
.../cs/findbugs/ba/bcp/ByteCodePatternMatch.java | 7 +-
.../edu/umd/cs/findbugs/ba/bcp/FieldAccess.java | 21 +-
.../edu/umd/cs/findbugs/ba/bcp/FieldVariable.java | 12 +-
src/java/edu/umd/cs/findbugs/ba/bcp/IfNull.java | 4 +-
src/java/edu/umd/cs/findbugs/ba/bcp/Invoke.java | 36 +-
src/java/edu/umd/cs/findbugs/ba/bcp/Load.java | 8 +-
.../edu/umd/cs/findbugs/ba/bcp/LocalVariable.java | 5 +-
.../findbugs/ba/bcp/LongOrDoubleLocalVariable.java | 7 +-
src/java/edu/umd/cs/findbugs/ba/bcp/MatchAny.java | 13 +-
.../edu/umd/cs/findbugs/ba/bcp/MatchResult.java | 9 +-
.../edu/umd/cs/findbugs/ba/bcp/Monitorenter.java | 8 +-
src/java/edu/umd/cs/findbugs/ba/bcp/New.java | 8 +-
.../cs/findbugs/ba/bcp/OneVariableInstruction.java | 9 +-
src/java/edu/umd/cs/findbugs/ba/bcp/Opcode.java | 12 +-
.../edu/umd/cs/findbugs/ba/bcp/PatternElement.java | 21 +-
.../cs/findbugs/ba/bcp/PatternElementMatch.java | 15 +-
.../edu/umd/cs/findbugs/ba/bcp/PatternMatcher.java | 87 +-
.../umd/cs/findbugs/ba/bcp/SingleInstruction.java | 3 +-
src/java/edu/umd/cs/findbugs/ba/bcp/Store.java | 8 +-
src/java/edu/umd/cs/findbugs/ba/bcp/Variable.java | 1 -
src/java/edu/umd/cs/findbugs/ba/bcp/Wild.java | 9 +-
src/java/edu/umd/cs/findbugs/ba/ca/Call.java | 3 +-
src/java/edu/umd/cs/findbugs/ba/ca/CallList.java | 11 +-
.../umd/cs/findbugs/ba/ca/CallListAnalysis.java | 13 +-
.../umd/cs/findbugs/ba/ca/CallListDataflow.java | 2 +-
.../edu/umd/cs/findbugs/ba/ch/ClassVertex.java | 11 +-
.../edu/umd/cs/findbugs/ba/ch/InheritanceEdge.java | 2 +-
.../umd/cs/findbugs/ba/ch/InheritanceGraph.java | 6 +-
.../cs/findbugs/ba/ch/InheritanceGraphVisitor.java | 6 +-
.../findbugs/ba/ch/InterproceduralCallGraph.java | 10 +-
.../ba/ch/InterproceduralCallGraphEdge.java | 4 +-
.../ba/ch/InterproceduralCallGraphVertex.java | 2 +-
.../findbugs/ba/ch/OverriddenMethodsVisitor.java | 42 +-
src/java/edu/umd/cs/findbugs/ba/ch/Subtypes2.java | 192 +-
...Visitor.java => SupertypeTraversalVisitor.java} | 34 +-
.../edu/umd/cs/findbugs/ba/constant/Constant.java | 32 +-
.../cs/findbugs/ba/constant/ConstantAnalysis.java | 11 +-
.../cs/findbugs/ba/constant/ConstantDataflow.java | 2 +-
.../umd/cs/findbugs/ba/constant/ConstantFrame.java | 2 +-
.../ba/constant/ConstantFrameModelingVisitor.java | 12 +-
.../ba/deref/UnconditionalValueDerefAnalysis.java | 279 +-
.../ba/deref/UnconditionalValueDerefDataflow.java | 6 +-
.../ba/deref/UnconditionalValueDerefSet.java | 54 +-
.../cs/findbugs/ba/generic/GenericObjectType.java | 33 +-
.../ba/generic/GenericSignatureParser.java | 45 +-
.../cs/findbugs/ba/generic/GenericUtilities.java | 183 +-
src/java/edu/umd/cs/findbugs/ba/heap/FieldSet.java | 18 +-
.../umd/cs/findbugs/ba/heap/FieldSetAnalysis.java | 20 +-
.../edu/umd/cs/findbugs/ba/heap/StoreAnalysis.java | 4 +-
.../ba/interproc/FieldPropertyDatabase.java | 6 +-
.../ba/interproc/MethodPropertyDatabase.java | 5 +-
.../findbugs/ba/interproc/ParameterProperty.java | 44 +-
.../cs/findbugs/ba/interproc/PropertyDatabase.java | 11 +-
.../edu/umd/cs/findbugs/ba/jsr305/Analysis.java | 8 +-
.../ba/jsr305/BackwardTypeQualifierDataflow.java | 4 +-
.../BackwardTypeQualifierDataflowAnalysis.java | 8 +-
.../BackwardTypeQualifierDataflowFactory.java | 5 +-
.../DirectlyRelevantTypeQualifiersDatabase.java | 3 +-
.../ba/jsr305/FindBugsDefaultAnnotations.java | 8 +-
.../edu/umd/cs/findbugs/ba/jsr305/FlowValue.java | 26 +-
.../ba/jsr305/ForwardTypeQualifierDataflow.java | 4 +-
.../ForwardTypeQualifierDataflowAnalysis.java | 13 +-
.../ForwardTypeQualifierDataflowFactory.java | 2 +-
.../ba/jsr305/JSR305NullnessAnnotations.java | 2 +-
.../ba/jsr305/ParameterAnnotationLookupResult.java | 4 +-
.../ba/jsr305/ReturnTypeAnnotationAccumulator.java | 8 +-
.../jsr305/ReturnTypeAnnotationLookupResult.java | 4 +-
.../umd/cs/findbugs/ba/jsr305/SourceSinkInfo.java | 55 +-
.../ba/jsr305/TypeQualifierAnnotation.java | 26 +-
.../TypeQualifierAnnotationLookupResult.java | 16 +-
.../ba/jsr305/TypeQualifierApplications.java | 177 +-
.../findbugs/ba/jsr305/TypeQualifierDataflow.java | 6 +-
.../ba/jsr305/TypeQualifierDataflowAnalysis.java | 29 +-
.../findbugs/ba/jsr305/TypeQualifierResolver.java | 30 +-
.../cs/findbugs/ba/jsr305/TypeQualifierValue.java | 43 +-
.../findbugs/ba/jsr305/TypeQualifierValueSet.java | 54 +-
.../ba/jsr305/ValidationSecurityManager.java | 49 +-
.../findbugs/ba/jsr305/ValidatorClassLoader.java | 50 +-
.../edu/umd/cs/findbugs/ba/npe/DerefFinder.java | 37 +-
.../findbugs/ba/npe/IsNullConditionDecision.java | 12 +-
.../edu/umd/cs/findbugs/ba/npe/IsNullValue.java | 117 +-
.../cs/findbugs/ba/npe/IsNullValueAnalysis.java | 187 +-
.../ba/npe/IsNullValueAnalysisFeatures.java | 2 +-
.../cs/findbugs/ba/npe/IsNullValueDataflow.java | 1 -
.../umd/cs/findbugs/ba/npe/IsNullValueFrame.java | 43 +-
.../ba/npe/IsNullValueFrameModelingVisitor.java | 49 +-
.../ba/npe/LocationWhereValueBecomesNull.java | 15 +-
.../ba/npe/MayReturnNullPropertyDatabase.java | 2 +-
.../cs/findbugs/ba/npe/NonNullParamViolation.java | 4 +-
.../npe/NullDerefAndRedundantComparisonFinder.java | 193 +-
.../ba/npe/NullValueUnconditionalDeref.java | 5 +-
.../ba/npe/ParameterNullnessPropertyDatabase.java | 6 +-
.../umd/cs/findbugs/ba/npe/RedundantBranch.java | 6 +-
.../edu/umd/cs/findbugs/ba/npe/ReturnPathType.java | 12 +-
.../cs/findbugs/ba/npe/ReturnPathTypeAnalysis.java | 120 +-
.../cs/findbugs/ba/npe/ReturnPathTypeDataflow.java | 4 +-
.../npe/ReturnValueNullnessPropertyDatabase.java | 6 +-
.../TypeQualifierNullnessAnnotationDatabase.java | 125 +-
.../ba/npe/UsagesRequiringNonNullValues.java | 15 +-
.../cs/findbugs/ba/obl/InstructionActionCache.java | 57 +-
.../umd/cs/findbugs/ba/obl/MatchMethodEntry.java | 14 +-
.../ba/obl/NonexistentObligationException.java | 1 -
.../edu/umd/cs/findbugs/ba/obl/Obligation.java | 5 +-
...bligationAcquiredOrReleasedInLoopException.java | 4 +-
.../umd/cs/findbugs/ba/obl/ObligationAnalysis.java | 95 +-
.../umd/cs/findbugs/ba/obl/ObligationDataflow.java | 2 +-
.../umd/cs/findbugs/ba/obl/ObligationFactory.java | 28 +-
.../findbugs/ba/obl/ObligationPolicyDatabase.java | 33 +-
.../ba/obl/ObligationPolicyDatabaseAction.java | 2 +-
.../ba/obl/ObligationPolicyDatabaseEntry.java | 6 +-
.../ba/obl/ObligationPolicyDatabaseEntryType.java | 2 +-
.../edu/umd/cs/findbugs/ba/obl/ObligationSet.java | 26 +-
src/java/edu/umd/cs/findbugs/ba/obl/State.java | 5 +-
src/java/edu/umd/cs/findbugs/ba/obl/StateSet.java | 60 +-
.../edu/umd/cs/findbugs/ba/type/BottomType.java | 3 +-
.../umd/cs/findbugs/ba/type/DoubleExtraType.java | 3 +-
.../cs/findbugs/ba/type/ExceptionObjectType.java | 26 +-
.../edu/umd/cs/findbugs/ba/type/ExceptionSet.java | 51 +-
.../cs/findbugs/ba/type/ExceptionSetFactory.java | 5 +-
.../edu/umd/cs/findbugs/ba/type/ExtendedTypes.java | 3 +-
.../umd/cs/findbugs/ba/type/FieldStoreType.java | 13 +-
.../findbugs/ba/type/FieldStoreTypeDatabase.java | 3 +-
.../edu/umd/cs/findbugs/ba/type/LongExtraType.java | 3 +-
src/java/edu/umd/cs/findbugs/ba/type/NullType.java | 3 +-
.../cs/findbugs/ba/type/StandardTypeMerger.java | 89 +-
.../umd/cs/findbugs/ba/type/ThrownException.java | 13 +-
src/java/edu/umd/cs/findbugs/ba/type/TopType.java | 3 +-
.../edu/umd/cs/findbugs/ba/type/TypeAnalysis.java | 141 +-
.../edu/umd/cs/findbugs/ba/type/TypeDataflow.java | 1 -
.../edu/umd/cs/findbugs/ba/type/TypeFrame.java | 18 +-
.../findbugs/ba/type/TypeFrameModelingVisitor.java | 190 +-
.../edu/umd/cs/findbugs/ba/type/TypeMerger.java | 5 +-
.../edu/umd/cs/findbugs/ba/vna/AvailableLoad.java | 35 +-
.../edu/umd/cs/findbugs/ba/vna/LoadedFieldSet.java | 23 +-
src/java/edu/umd/cs/findbugs/ba/vna/MergeTree.java | 49 +-
.../edu/umd/cs/findbugs/ba/vna/ValueNumber.java | 25 +-
.../cs/findbugs/ba/vna/ValueNumberAnalysis.java | 94 +-
.../ba/vna/ValueNumberAnalysisFeatures.java | 1 -
.../umd/cs/findbugs/ba/vna/ValueNumberCache.java | 33 +-
.../cs/findbugs/ba/vna/ValueNumberDataflow.java | 5 +-
.../umd/cs/findbugs/ba/vna/ValueNumberFactory.java | 21 +-
.../umd/cs/findbugs/ba/vna/ValueNumberFrame.java | 309 +-
.../ba/vna/ValueNumberFrameModelingVisitor.java | 255 +-
.../cs/findbugs/ba/vna/ValueNumberSourceInfo.java | 35 +-
.../umd/cs/findbugs/bcel/AnnotationDetector.java | 7 +-
src/java/edu/umd/cs/findbugs/bcel/BCELUtil.java | 45 +-
src/java/edu/umd/cs/findbugs/bcel/CFGDetector.java | 13 +-
.../umd/cs/findbugs/bcel/OpcodeStackDetector.java | 14 +-
.../edu/umd/cs/findbugs/bcel/PreorderDetector.java | 7 +-
.../umd/cs/findbugs/bcel/generic/NONNULL2Z.java | 4 +-
.../edu/umd/cs/findbugs/bcel/generic/NULL2Z.java | 6 +-
.../generic/NullnessConversationInstruction.java | 10 +-
.../cs/findbugs/bugReporter/MaxRankDecorator.java | 3 +-
.../findbugs/bugReporter/SuppressionDecorator.java | 50 +-
src/java/edu/umd/cs/findbugs/charsets/UTF8.java | 6 +-
.../classfile/CheckedAnalysisException.java | 6 +-
.../umd/cs/findbugs/classfile/ClassDescriptor.java | 6 +-
.../classfile/ClassNameMismatchException.java | 6 +-
.../cs/findbugs/classfile/DescriptorFactory.java | 32 +-
.../umd/cs/findbugs/classfile/FieldDescriptor.java | 7 +-
.../classfile/FieldOrMethodDescriptor.java | 19 +-
src/java/edu/umd/cs/findbugs/classfile/Global.java | 8 +-
.../umd/cs/findbugs/classfile/IAnalysisCache.java | 30 +-
.../umd/cs/findbugs/classfile/IAnalysisEngine.java | 6 +-
.../classfile/IAnalysisEngineRegistrar.java | 4 +-
.../findbugs/classfile/IClassAnalysisEngine.java | 4 +-
.../umd/cs/findbugs/classfile/IClassObserver.java | 4 +-
.../cs/findbugs/classfile/IClassPathBuilder.java | 12 +-
.../classfile/IClassPathBuilderProgress.java | 2 +-
.../edu/umd/cs/findbugs/classfile/ICodeBase.java | 24 +-
.../umd/cs/findbugs/classfile/ICodeBaseEntry.java | 14 +-
.../cs/findbugs/classfile/ICodeBaseIterator.java | 8 +-
.../cs/findbugs/classfile/ICodeBaseLocator.java | 9 +-
.../cs/findbugs/classfile/IDatabaseFactory.java | 2 +-
.../umd/cs/findbugs/classfile/IErrorLogger.java | 12 +-
.../findbugs/classfile/IMethodAnalysisEngine.java | 2 +-
.../cs/findbugs/classfile/IScannableCodeBase.java | 4 +-
.../classfile/InvalidClassFileFormatException.java | 6 +-
.../cs/findbugs/classfile/MethodDescriptor.java | 20 +-
.../findbugs/classfile/MissingClassException.java | 8 +-
.../classfile/RecomputableClassAnalysisEngine.java | 1 +
.../classfile/ReflectionDatabaseFactory.java | 16 +-
.../classfile/ResourceNotFoundException.java | 10 +-
.../classfile/UncheckedAnalysisException.java | 6 +-
.../classfile/analysis/AnnotationValue.java | 47 +-
.../cs/findbugs/classfile/analysis/ClassData.java | 8 +-
.../cs/findbugs/classfile/analysis/ClassInfo.java | 200 +-
.../analysis/ClassNameAndSuperclassInfo.java | 13 +-
.../cs/findbugs/classfile/analysis/EnumValue.java | 2 +-
.../cs/findbugs/classfile/analysis/FieldInfo.java | 51 +-
.../cs/findbugs/classfile/analysis/MethodInfo.java | 157 +-
.../engine/AbstractFieldAnnotationVisitor.java | 11 +-
.../classfile/engine/AbstractMethodVisitor.java | 76 +-
.../classfile/engine/ClassDataAnalysisEngine.java | 8 +
.../classfile/engine/ClassInfoAnalysisEngine.java | 17 +-
.../ClassNameAndSuperclassInfoAnalysisEngine.java | 11 +-
.../cs/findbugs/classfile/engine/ClassParser.java | 127 +-
.../classfile/engine/ClassParserInterface.java | 6 +-
.../classfile/engine/ClassParserUsingASM.java | 788 +--
.../classfile/engine/ClassParserUsingBCEL.java | 16 +-
.../findbugs/classfile/engine/EngineRegistrar.java | 7 +-
.../findbugs/classfile/engine/SelfMethodCalls.java | 15 +-
.../engine/asm/ClassNodeAnalysisEngine.java | 8 +-
.../engine/asm/ClassReaderAnalysisEngine.java | 8 +-
.../classfile/engine/asm/EngineRegistrar.java | 7 +-
.../engine/asm/FindBugsASM.java} | 14 +-
.../classfile/engine/bcel/AnalysisFactory.java | 9 +-
.../engine/bcel/AssertionMethodsFactory.java | 6 +-
.../engine/bcel/AssignedFieldMapFactory.java | 8 +-
...ackwardTypeQualifierDataflowFactoryFactory.java | 5 +-
.../engine/bcel/BlockTypeAnalysisFactory.java | 5 +-
.../findbugs/classfile/engine/bcel/CFGFactory.java | 22 +-
.../engine/bcel/CallListDataflowFactory.java | 5 +-
.../bcel/ClassContextClassAnalysisEngine.java | 8 +-
.../bcel/CompactLocationNumberingFactory.java | 5 +-
.../engine/bcel/ConstantDataflowFactory.java | 8 +-
.../engine/bcel/ConstantPoolGenFactory.java | 8 +-
.../engine/bcel/DepthFirstSearchFactory.java | 5 +-
.../engine/bcel/DominatorsAnalysisFactory.java | 5 +-
.../classfile/engine/bcel/EngineRegistrar.java | 58 +-
.../engine/bcel/ExceptionSetFactoryFactory.java | 5 +-
.../engine/bcel/FinallyDuplicatesInfoFactory.java | 360 ++
...ForwardTypeQualifierDataflowFactoryFactory.java | 5 +-
.../engine/bcel/IsNullValueDataflowFactory.java | 5 +-
.../engine/bcel/JavaClassAnalysisEngine.java | 3 +
.../engine/bcel/LiveLocalStoreDataflowFactory.java | 5 +-
.../classfile/engine/bcel/LoadDataflowFactory.java | 8 +-
.../engine/bcel/LoadedFieldSetFactory.java | 18 +-
.../classfile/engine/bcel/LockCheckerFactory.java | 5 +-
.../classfile/engine/bcel/LockDataflowFactory.java | 5 +-
.../engine/bcel/MethodBytecodeSetFactory.java | 5 +-
.../classfile/engine/bcel/MethodFactory.java | 7 +-
.../classfile/engine/bcel/MethodGenFactory.java | 22 +-
.../bcel/NonExceptionPostdominatorsAnalysis.java | 4 +-
.../NonExceptionPostdominatorsAnalysisFactory.java | 5 +-
...NonImplicitExceptionPostDominatorsAnalysis.java | 3 +-
...icitExceptionPostDominatorsAnalysisFactory.java | 7 +-
.../engine/bcel/ObligationDataflowFactory.java | 3 +-
.../engine/bcel/ParameterSignatureListFactory.java | 5 +-
.../engine/bcel/ReturnPathDataflowFactory.java | 5 +-
.../engine/bcel/ReturnPathTypeDataflowFactory.java | 5 +-
.../bcel/ReverseDepthFirstSearchFactory.java | 5 +-
.../engine/bcel/StoreDataflowFactory.java | 8 +-
.../classfile/engine/bcel/TypeDataflowFactory.java | 5 +-
.../UnconditionalValueDerefDataflowFactory.java | 5 +-
.../engine/bcel/UnpackedBytecodeCallback.java | 7 +-
.../classfile/engine/bcel/UnpackedCode.java | 4 +-
.../classfile/engine/bcel/UnpackedCodeFactory.java | 8 +-
.../bcel/UsagesRequiringNonNullValuesFactory.java | 3 +-
.../engine/bcel/ValueNumberDataflowFactory.java | 5 +-
.../engine/bcel/ValueRangeAnalysisFactory.java | 972 ++++
.../classfile/impl/AbstractScannableCodeBase.java | 33 +-
.../impl/AbstractScannableCodeBaseEntry.java | 7 +-
.../cs/findbugs/classfile/impl/AnalysisCache.java | 123 +-
.../cs/findbugs/classfile/impl/ClassFactory.java | 17 +-
.../findbugs/classfile/impl/ClassPathBuilder.java | 15 +-
.../cs/findbugs/classfile/impl/ClassPathImpl.java | 13 +-
.../classfile/impl/DelegatingCodeBaseEntry.java | 30 +-
.../classfile/impl/DelegatingCodeBaseIterator.java | 12 +-
.../findbugs/classfile/impl/DirectoryCodeBase.java | 36 +-
.../classfile/impl/DirectoryCodeBaseEntry.java | 21 +-
.../classfile/impl/FilesystemCodeBaseLocator.java | 14 +-
.../classfile/impl/NestedZipFileCodeBase.java | 22 +-
.../impl/NestedZipFileCodeBaseLocator.java | 14 +-
.../classfile/impl/SingleFileCodeBase.java | 52 +-
.../classfile/impl/SingleFileCodeBaseEntry.java | 31 +-
.../classfile/impl/ZipCodeBaseFactory.java | 6 +-
.../findbugs/classfile/impl/ZipFileCodeBase.java | 52 +-
.../classfile/impl/ZipFileCodeBaseEntry.java | 21 +-
.../classfile/impl/ZipInputStreamCodeBase.java | 26 +-
.../impl/ZipInputStreamCodeBaseEntry.java | 21 +-
.../edu/umd/cs/findbugs/cloud/AbstractCloud.java | 217 +-
.../findbugs/cloud/BugCollectionStorageCloud.java | 36 +-
.../cs/findbugs/cloud/BugFilingCommentHelper.java | 39 +-
src/java/edu/umd/cs/findbugs/cloud/Cloud.java | 7 +-
.../edu/umd/cs/findbugs/cloud/CloudFactory.java | 40 +-
.../edu/umd/cs/findbugs/cloud/CloudPlugin.java | 6 +-
.../edu/umd/cs/findbugs/cloud/DoNothingCloud.java | 778 +--
.../umd/cs/findbugs/cloud/MutableCloudTask.java | 209 +-
.../edu/umd/cs/findbugs/cloud/OnlineCloud.java | 6 +-
.../cloud/username/ClearCloudPreferences.java | 22 +-
.../findbugs/cloud/username/LocalNameLookup.java | 2 +
.../umd/cs/findbugs/cloud/username/NameLookup.java | 4 +-
.../cs/findbugs/cloud/username/NoNameLookup.java | 2 +
.../cloud/username/PromptForNameLookup.java | 4 +-
.../cloud/username/WebCloudNameLookup.java | 29 +-
.../cs/findbugs/config/AnalysisFeatureSetting.java | 9 +-
.../edu/umd/cs/findbugs/config/CommandLine.java | 63 +-
.../cs/findbugs/config/ProjectFilterSettings.java | 25 +-
.../umd/cs/findbugs/config/SortedProperties.java | 8 +-
.../umd/cs/findbugs/config/UserPreferences.java | 26 +-
.../detect/AnyMethodReturnValueStreamFactory.java | 10 +-
.../detect/AppendingToAnObjectOutputStream.java | 38 +-
.../umd/cs/findbugs/detect/AtomicityProblem.java | 32 +-
.../cs/findbugs/detect/BadAppletConstructor.java | 23 +-
.../umd/cs/findbugs/detect/BadResultSetAccess.java | 22 +-
.../detect/BadSyntaxForRegularExpression.java | 80 +-
.../cs/findbugs/detect/BadUseOfReturnValue.java | 22 +-
.../cs/findbugs/detect/BadlyOverriddenAdapter.java | 22 +-
.../umd/cs/findbugs/detect/BooleanReturnNull.java | 51 +-
.../detect/BuildCheckReturnAnnotationDatabase.java | 53 +-
.../detect/BuildInterproceduralCallGraph.java | 35 +-
.../detect/BuildNonNullAnnotationDatabase.java | 31 +-
.../detect/BuildNonnullReturnDatabase.java | 33 +-
.../detect/BuildObligationPolicyDatabase.java | 13 +-
.../findbugs/detect/BuildStringPassthruGraph.java | 293 +
.../BuildUnconditionalParamDerefDatabase.java | 67 +-
.../detect/CallToUnconditionalThrower.java | 56 +-
.../findbugs/detect/CallToUnsupportedMethod.java | 40 +-
.../edu/umd/cs/findbugs/detect/CalledMethods.java | 18 +-
.../detect/CbeckMustOverrideSuperAnnotation.java | 24 +-
.../CheckAnalysisContextContainedAnnotation.java | 54 +-
.../edu/umd/cs/findbugs/detect/CheckCalls.java | 19 +-
.../cs/findbugs/detect/CheckExpectedWarnings.java | 152 +-
.../findbugs/detect/CheckImmutableAnnotation.java | 8 +-
.../detect/CheckRelaxingNullnessAnnotation.java | 29 +-
.../cs/findbugs/detect/CheckTypeQualifiers.java | 98 +-
.../edu/umd/cs/findbugs/detect/CloneIdiom.java | 66 +-
.../umd/cs/findbugs/detect/ComparatorIdiom.java | 14 +-
.../cs/findbugs/detect/ConfusedInheritance.java | 4 +-
.../ConfusionBetweenInheritedAndOuterMethod.java | 50 +-
.../findbugs/detect/CovariantArrayAssignment.java | 190 +
.../umd/cs/findbugs/detect/CrossSiteScripting.java | 107 +-
.../cs/findbugs/detect/DeadLocalStoreProperty.java | 2 +-
.../findbugs/detect/DefaultEncodingDetector.java | 5 +-
.../cs/findbugs/detect/DoInsideDoPrivileged.java | 23 +-
.../DontCatchIllegalMonitorStateException.java | 20 +-
.../detect/DontIgnoreResultOfPutIfAbsent.java | 159 +-
.../edu/umd/cs/findbugs/detect/DontUseEnum.java | 4 +-
.../findbugs/detect/DoomedCodeWarningProperty.java | 2 +-
.../umd/cs/findbugs/detect/DroppedException.java | 175 +-
.../cs/findbugs/detect/DumbMethodInvocations.java | 126 +-
.../edu/umd/cs/findbugs/detect/DumbMethods.java | 1038 ++--
.../umd/cs/findbugs/detect/DuplicateBranches.java | 103 +-
.../umd/cs/findbugs/detect/EmptyZipFileEntry.java | 20 +-
...lsOperandShouldHaveClassCompatibleWithThis.java | 26 +-
.../cs/findbugs/detect/ExplicitSerialization.java | 27 +-
.../umd/cs/findbugs/detect/FieldItemSummary.java | 37 +-
.../cs/findbugs/detect/FinalizerNullsFields.java | 13 +-
.../edu/umd/cs/findbugs/detect/FindBadCast2.java | 235 +-
.../edu/umd/cs/findbugs/detect/FindBadForLoop.java | 5 +-
.../cs/findbugs/detect/FindBugsSummaryStats.java | 16 +-
.../findbugs/detect/FindCircularDependencies.java | 38 +-
.../cs/findbugs/detect/FindComparatorProblems.java | 134 +
.../cs/findbugs/detect/FindDeadLocalStores.java | 198 +-
.../umd/cs/findbugs/detect/FindDoubleCheck.java | 120 +-
.../detect/FindEmptySynchronizedBlock.java | 3 +-
.../findbugs/detect/FindFieldSelfAssignment.java | 43 +-
.../findbugs/detect/FindFinalizeInvocations.java | 35 +-
.../umd/cs/findbugs/detect/FindFloatEquality.java | 62 +-
.../edu/umd/cs/findbugs/detect/FindFloatMath.java | 11 +-
.../edu/umd/cs/findbugs/detect/FindHEmismatch.java | 311 +-
.../cs/findbugs/detect/FindInconsistentSync2.java | 200 +-
.../detect/FindJSR166LockMonitorenter.java | 69 +-
.../findbugs/detect/FindLocalSelfAssignment2.java | 24 +-
.../umd/cs/findbugs/detect/FindMaskedFields.java | 87 +-
.../detect/FindMismatchedWaitOrNotify.java | 32 +-
.../umd/cs/findbugs/detect/FindNakedNotify.java | 18 +-
.../findbugs/detect/FindNoSideEffectMethods.java | 1075 ++++
.../FindNonSerializableStoreIntoSession.java | 27 +-
...indNonSerializableValuePassedToWriteObject.java | 36 +-
.../cs/findbugs/detect/FindNonShortCircuit.java | 35 +-
.../edu/umd/cs/findbugs/detect/FindNullDeref.java | 533 +-
...llDerefsInvolvingNonShortCircuitEvaluation.java | 33 +-
.../edu/umd/cs/findbugs/detect/FindOpenStream.java | 60 +-
.../edu/umd/cs/findbugs/detect/FindPuzzlers.java | 303 +-
.../umd/cs/findbugs/detect/FindRefComparison.java | 289 +-
.../edu/umd/cs/findbugs/detect/FindReturnRef.java | 56 +-
.../umd/cs/findbugs/detect/FindRoughConstants.java | 219 +
.../umd/cs/findbugs/detect/FindRunInvocations.java | 16 +-
.../umd/cs/findbugs/detect/FindSelfComparison.java | 117 +-
.../cs/findbugs/detect/FindSelfComparison2.java | 111 +-
.../cs/findbugs/detect/FindSleepWithLockHeld.java | 30 +-
.../edu/umd/cs/findbugs/detect/FindSpinLoop.java | 23 +-
.../umd/cs/findbugs/detect/FindSqlInjection.java | 235 +-
.../umd/cs/findbugs/detect/FindTwoLockWait.java | 28 +-
.../detect/FindUncalledPrivateMethods.java | 59 +-
.../cs/findbugs/detect/FindUnconditionalWait.java | 14 +-
.../cs/findbugs/detect/FindUninitializedGet.java | 44 +-
.../FindUnrelatedTypesInGenericContainer.java | 220 +-
.../umd/cs/findbugs/detect/FindUnreleasedLock.java | 112 +-
.../findbugs/detect/FindUnsatisfiedObligation.java | 60 +-
.../edu/umd/cs/findbugs/detect/FindUnsyncGet.java | 19 +-
.../detect/FindUseOfNonSerializableValue.java | 60 +-
.../cs/findbugs/detect/FindUselessControlFlow.java | 22 +-
.../umd/cs/findbugs/detect/FindUselessObjects.java | 703 +++
.../cs/findbugs/detect/FormatStringChecker.java | 79 +-
.../FunctionsThatMightBeMistakenForProcedures.java | 83 +-
.../findbugs/detect/HugeSharedStringConstants.java | 26 +-
.../cs/findbugs/detect/IDivResultCastToDouble.java | 21 +-
.../umd/cs/findbugs/detect/IOStreamFactory.java | 20 +-
.../edu/umd/cs/findbugs/detect/IncompatMask.java | 45 +-
.../findbugs/detect/InconsistentAnnotations.java | 6 +-
.../detect/InconsistentSyncWarningProperty.java | 2 +-
.../umd/cs/findbugs/detect/InefficientIndexOf.java | 85 +
.../InefficientInitializationInsideLoop.java | 181 +
.../findbugs/detect/InefficientMemberAccess.java | 50 +-
.../umd/cs/findbugs/detect/InefficientToArray.java | 36 +-
.../edu/umd/cs/findbugs/detect/InfiniteLoop.java | 182 +-
.../cs/findbugs/detect/InfiniteRecursiveLoop.java | 64 +-
.../detect/InheritanceUnsafeGetResource.java | 26 +-
.../cs/findbugs/detect/InitializationChain.java | 124 +-
.../InitializeNonnullFieldsInConstructor.java | 51 +-
.../detect/InstanceFieldLoadStreamFactory.java | 22 +-
.../cs/findbugs/detect/InstantiateStaticClass.java | 68 +-
.../cs/findbugs/detect/IntCast2LongAsInstant.java | 2 +-
.../umd/cs/findbugs/detect/InvalidJUnitTest.java | 63 +-
.../edu/umd/cs/findbugs/detect/IteratorIdioms.java | 4 +-
src/java/edu/umd/cs/findbugs/detect/LazyInit.java | 396 +-
.../cs/findbugs/detect/LoadOfKnownNullValue.java | 111 +-
.../detect/LostLoggerDueToWeakReference.java | 59 +-
.../umd/cs/findbugs/detect/MethodReturnCheck.java | 137 +-
.../detect/MethodReturnValueStreamFactory.java | 29 +-
src/java/edu/umd/cs/findbugs/detect/Methods.java | 2 +
.../detect/MultithreadedInstanceAccess.java | 31 +-
.../edu/umd/cs/findbugs/detect/MutableEnum.java | 92 +
.../edu/umd/cs/findbugs/detect/MutableLock.java | 12 +-
.../cs/findbugs/detect/MutableStaticFields.java | 143 +-
src/java/edu/umd/cs/findbugs/detect/Naming.java | 259 +-
src/java/edu/umd/cs/findbugs/detect/Noise.java | 50 +-
.../edu/umd/cs/findbugs/detect/NoiseNullDeref.java | 126 +-
.../findbugs/detect/NoteAnnotationRetention.java | 19 +-
.../detect/NoteCheckReturnValueAnnotations.java | 5 +-
.../detect/NoteDirectlyRelevantTypeQualifiers.java | 11 +-
.../umd/cs/findbugs/detect/NoteJCIPAnnotation.java | 4 +-
.../cs/findbugs/detect/NoteNonNullAnnotations.java | 12 +-
.../findbugs/detect/NoteNonnullReturnValues.java | 10 +-
.../cs/findbugs/detect/NoteSuppressedWarnings.java | 45 +-
.../detect/NoteUnconditionalParamDerefs.java | 3 +-
.../detect/NullArgumentWarningProperty.java | 2 +-
.../umd/cs/findbugs/detect/NumberConstructor.java | 53 +-
.../OptionalReturnNull.java} | 34 +-
.../detect/OverridingEqualsNotSymmetrical.java | 161 +-
.../cs/findbugs/detect/PreferZeroLengthArrays.java | 15 +-
.../umd/cs/findbugs/detect/PublicSemaphores.java | 18 +-
.../detect/QuestionableBooleanAssignment.java | 27 +-
...ldInMethodInvokedByConstructorInSuperclass.java | 62 +-
.../findbugs/detect/ReadReturnShouldBeChecked.java | 35 +-
.../cs/findbugs/detect/RedundantConditions.java | 236 +
.../cs/findbugs/detect/RedundantInterfaces.java | 16 +-
.../detect/RefComparisonWarningProperty.java | 2 +-
.../umd/cs/findbugs/detect/ReflectiveClasses.java | 8 +-
.../cs/findbugs/detect/RepeatedConditionals.java | 205 +-
.../cs/findbugs/detect/ResolveAllReferences.java | 34 +-
.../findbugs/detect/RuntimeExceptionCapture.java | 59 +-
.../umd/cs/findbugs/detect/SerializableIdiom.java | 333 +-
.../umd/cs/findbugs/detect/StartInConstructor.java | 12 +-
.../cs/findbugs/detect/StaticCalendarDetector.java | 66 +-
.../detect/StaticFieldLoadStreamFactory.java | 10 +-
src/java/edu/umd/cs/findbugs/detect/Stream.java | 69 +-
.../cs/findbugs/detect/StreamEquivalenceClass.java | 9 +-
.../edu/umd/cs/findbugs/detect/StreamEscape.java | 10 +-
.../edu/umd/cs/findbugs/detect/StreamFactory.java | 3 +-
.../detect/StreamFrameModelingVisitor.java | 23 +-
.../cs/findbugs/detect/StreamResourceTracker.java | 64 +-
.../cs/findbugs/detect/StringConcatenation.java | 65 +-
.../cs/findbugs/detect/SuperfluousInstanceOf.java | 23 +-
.../detect/SuspiciousThreadInterrupted.java | 42 +-
.../umd/cs/findbugs/detect/SwitchFallthrough.java | 69 +-
.../SynchronizationOnSharedBuiltinConstant.java | 39 +-
.../detect/SynchronizeAndNullCheckField.java | 17 +-
.../SynchronizeOnClassLiteralNotGetClass.java | 43 +-
...nchronizingOnContentsOfFieldToProtectField.java | 36 +-
src/java/edu/umd/cs/findbugs/detect/TestASM.java | 14 +-
.../cs/findbugs/detect/TestDataflowAnalysis.java | 11 +-
.../edu/umd/cs/findbugs/detect/TestingGround.java | 17 +-
.../edu/umd/cs/findbugs/detect/TestingGround2.java | 4 +-
.../cs/findbugs/detect/TrainFieldStoreTypes.java | 33 +-
.../findbugs/detect/TrainLongInstantfParams.java | 19 +-
.../findbugs/detect/TrainNonNullAnnotations.java | 10 +-
.../detect/TrainUnconditionalDerefParams.java | 14 +-
...{BooleanReturnNull.java => TypeReturnNull.java} | 48 +-
.../edu/umd/cs/findbugs/detect/URLProblems.java | 82 +-
.../detect/UncallableMethodOfAnonymousClass.java | 105 +-
.../umd/cs/findbugs/detect/UnnecessaryMath.java | 24 +-
.../edu/umd/cs/findbugs/detect/UnreadFields.java | 392 +-
.../cs/findbugs/detect/UselessSubclassMethod.java | 97 +-
.../umd/cs/findbugs/detect/VarArgsProblems.java | 41 +-
.../edu/umd/cs/findbugs/detect/VolatileUsage.java | 43 +-
.../edu/umd/cs/findbugs/detect/WaitInLoop.java | 38 +-
.../umd/cs/findbugs/detect/WrongMapIterator.java | 338 +-
.../umd/cs/findbugs/detect/XMLFactoryBypass.java | 27 +-
.../edu/umd/cs/findbugs/filter/AndMatcher.java | 12 +-
.../edu/umd/cs/findbugs/filter/BugMatcher.java | 27 +-
.../edu/umd/cs/findbugs/filter/ClassMatcher.java | 32 +-
.../umd/cs/findbugs/filter/CompoundMatcher.java | 19 +-
...PriorityMatcher.java => ConfidenceMatcher.java} | 40 +-
.../umd/cs/findbugs/filter/DesignationMatcher.java | 17 +-
.../edu/umd/cs/findbugs/filter/FieldMatcher.java | 29 +-
src/java/edu/umd/cs/findbugs/filter/Filter.java | 238 +-
.../umd/cs/findbugs/filter/FilterException.java | 1 -
.../cs/findbugs/filter/FirstVersionMatcher.java | 5 +-
.../umd/cs/findbugs/filter/LastVersionMatcher.java | 10 +-
.../edu/umd/cs/findbugs/filter/LocalMatcher.java | 7 +-
src/java/edu/umd/cs/findbugs/filter/Matcher.java | 5 +-
.../edu/umd/cs/findbugs/filter/MemberMatcher.java | 12 +-
.../edu/umd/cs/findbugs/filter/MethodMatcher.java | 45 +-
src/java/edu/umd/cs/findbugs/filter/NameMatch.java | 40 +-
.../edu/umd/cs/findbugs/filter/NotMatcher.java | 12 +-
src/java/edu/umd/cs/findbugs/filter/OrMatcher.java | 12 +-
.../umd/cs/findbugs/filter/PriorityMatcher.java | 14 +-
.../edu/umd/cs/findbugs/filter/RankMatcher.java | 14 +-
.../edu/umd/cs/findbugs/filter/RelationalOp.java | 3 +-
.../edu/umd/cs/findbugs/filter/SignatureUtil.java | 59 +-
.../{ClassMatcher.java => SourceMatcher.java} | 37 +-
.../edu/umd/cs/findbugs/filter/StringSetMatch.java | 19 +-
.../{MethodMatcher.java => TypeMatcher.java} | 70 +-
.../edu/umd/cs/findbugs/filter/VersionMatcher.java | 6 +-
.../findbugs/graph/AbstractDepthFirstSearch.java | 70 +-
.../edu/umd/cs/findbugs/graph/AbstractEdge.java | 22 +-
.../edu/umd/cs/findbugs/graph/AbstractGraph.java | 75 +-
.../edu/umd/cs/findbugs/graph/AbstractVertex.java | 18 +-
.../edu/umd/cs/findbugs/graph/DFSEdgeTypes.java | 3 +-
.../umd/cs/findbugs/graph/DepthFirstSearch.java | 7 +-
src/java/edu/umd/cs/findbugs/graph/Graph.java | 21 +-
src/java/edu/umd/cs/findbugs/graph/GraphEdge.java | 3 +-
.../edu/umd/cs/findbugs/graph/GraphToolkit.java | 7 +-
.../edu/umd/cs/findbugs/graph/GraphVertex.java | 1 -
.../edu/umd/cs/findbugs/graph/MergeVertices.java | 15 +-
.../cs/findbugs/graph/ReverseDepthFirstSearch.java | 7 +-
src/java/edu/umd/cs/findbugs/graph/SearchTree.java | 5 +-
.../umd/cs/findbugs/graph/SearchTreeBuilder.java | 12 +-
.../umd/cs/findbugs/graph/SearchTreeCallback.java | 5 +-
.../graph/StronglyConnectedComponents.java | 25 +-
src/java/edu/umd/cs/findbugs/graph/Transpose.java | 11 +-
.../edu/umd/cs/findbugs/graph/VertexChooser.java | 1 -
.../umd/cs/findbugs/graph/VertexCombinator.java | 3 +-
.../findbugs/graph/VisitationTimeComparator.java | 16 +-
.../cs/findbugs/gui/bundle/findbugs_ja.properties | 561 +-
.../cs/findbugs/gui2/CloudCommentsPaneSwing.java | 145 +-
.../internalAnnotations/DottedClassName.java | 2 +-
.../internalAnnotations/SlashedClassName.java | 10 +-
src/java/edu/umd/cs/findbugs/io/IO.java | 26 +-
.../edu/umd/cs/findbugs/io/SlowInputStream.java | 13 +-
.../edu/umd/cs/findbugs/jaif/JAIFEnumConstant.java | 4 +-
src/java/edu/umd/cs/findbugs/jaif/JAIFEvents.java | 18 +-
src/java/edu/umd/cs/findbugs/jaif/JAIFParser.java | 30 +-
src/java/edu/umd/cs/findbugs/jaif/JAIFScanner.java | 60 +-
src/java/edu/umd/cs/findbugs/jaif/JAIFToken.java | 10 +-
.../edu/umd/cs/findbugs/jaif/JAIFTokenKind.java | 4 +-
.../edu/umd/cs/findbugs/log/ConsoleLogger.java | 11 +-
src/java/edu/umd/cs/findbugs/log/Profiler.java | 49 +-
.../edu/umd/cs/findbugs/log/YourKitController.java | 28 +-
.../edu/umd/cs/findbugs/model/ClassFeatureSet.java | 45 +-
.../umd/cs/findbugs/model/ClassNameRewriter.java | 4 +-
.../cs/findbugs/model/ClassNameRewriterUtil.java | 10 +-
.../findbugs/model/IdentityClassNameRewriter.java | 8 +-
.../edu/umd/cs/findbugs/model/MovedClassMap.java | 21 +-
.../cs/findbugs/model/RegenerateClassFeatures.java | 32 +-
.../umd/cs/findbugs/model/SimilarClassFinder.java | 2 +-
.../edu/umd/cs/findbugs/model/SimilarClassSet.java | 10 +-
.../edu/umd/cs/findbugs/plan/AnalysisPass.java | 24 +-
.../plan/ByInterfaceDetectorFactorySelector.java | 10 +-
.../edu/umd/cs/findbugs/plan/ConstraintEdge.java | 9 +-
.../edu/umd/cs/findbugs/plan/ConstraintGraph.java | 3 +-
.../cs/findbugs/plan/DetectorFactorySelector.java | 4 +-
.../edu/umd/cs/findbugs/plan/DetectorNode.java | 7 +-
.../findbugs/plan/DetectorOrderingConstraint.java | 9 +-
.../edu/umd/cs/findbugs/plan/ExecutionPlan.java | 17 +-
.../findbugs/plan/OrderingConstraintException.java | 5 +-
.../plan/ReportingDetectorFactorySelector.java | 9 +-
.../plan/SingleDetectorFactorySelector.java | 7 +-
.../cs/findbugs/props/AbstractWarningProperty.java | 14 +-
.../cs/findbugs/props/GeneralWarningProperty.java | 2 +-
.../umd/cs/findbugs/props/PriorityAdjustment.java | 4 +-
.../edu/umd/cs/findbugs/props/WarningProperty.java | 6 +-
.../umd/cs/findbugs/props/WarningPropertySet.java | 38 +-
.../umd/cs/findbugs/props/WarningPropertyUtil.java | 21 +-
.../edu/umd/cs/findbugs/updates/UpdateChecker.java | 106 +-
.../edu/umd/cs/findbugs/util/AnyTypeMatcher.java | 3 +-
src/java/edu/umd/cs/findbugs/util/Archive.java | 8 +-
src/java/edu/umd/cs/findbugs/util/Bag.java | 17 +-
src/java/edu/umd/cs/findbugs/util/ClassName.java | 99 +-
.../edu/umd/cs/findbugs/util/ClassPathUtil.java | 6 +-
.../util/ContainsCamelCaseWordStringMatcher.java | 7 +-
.../edu/umd/cs/findbugs/util/DualKeyHashMap.java | 13 +-
.../edu/umd/cs/findbugs/util/EditDistance.java | 27 +-
.../umd/cs/findbugs/util/ExactStringMatcher.java | 5 +-
.../umd/cs/findbugs/util/FractionalMultiset.java | 40 +-
src/java/edu/umd/cs/findbugs/util/FutureValue.java | 68 +-
src/java/edu/umd/cs/findbugs/util/HTML.java | 28 +-
.../edu/umd/cs/findbugs/util/JavaWebStart.java | 17 +-
.../edu/umd/cs/findbugs/util/LaunchBrowser.java | 38 +-
src/java/edu/umd/cs/findbugs/util/MapCache.java | 7 +-
src/java/edu/umd/cs/findbugs/util/MergeMap.java | 9 +-
src/java/edu/umd/cs/findbugs/util/MultiMap.java | 6 +-
src/java/edu/umd/cs/findbugs/util/Multiset.java | 29 +-
.../edu/umd/cs/findbugs/util/NullIterator.java | 11 +-
.../umd/cs/findbugs/util/ProfilingMapCache.java | 6 +-
.../umd/cs/findbugs/util/RegexStringMatcher.java | 7 +-
.../cs/findbugs/util/SplitCamelCaseIdentifier.java | 11 +-
.../edu/umd/cs/findbugs/util/StringMatcher.java | 4 +-
src/java/edu/umd/cs/findbugs/util/Strings.java | 48 +-
.../umd/cs/findbugs/util/SubtypeTypeMatcher.java | 9 +-
.../cs/findbugs/util/TestDesktopIntegration.java | 25 +-
.../edu/umd/cs/findbugs/util/TopologicalSort.java | 58 +-
.../edu/umd/cs/findbugs/util/TripleKeyHashMap.java | 3 +-
src/java/edu/umd/cs/findbugs/util/TypeMatcher.java | 4 +-
src/java/edu/umd/cs/findbugs/util/Util.java | 149 +-
.../umd/cs/findbugs/util/WriteOnceProperties.java | 31 +-
.../cs/findbugs/visitclass/AnnotationVisitor.java | 92 +-
.../umd/cs/findbugs/visitclass/BetterVisitor.java | 35 +-
.../cs/findbugs/visitclass/DismantleBytecode.java | 288 +-
.../edu/umd/cs/findbugs/visitclass/LVTHelper.java | 5 +-
.../cs/findbugs/visitclass/PreorderVisitor.java | 219 +-
.../edu/umd/cs/findbugs/visitclass/PrintClass.java | 87 +-
src/java/edu/umd/cs/findbugs/visitclass/Util.java | 42 +-
.../workflow/BackdateHistoryUsingSource.java | 9 +-
src/java/edu/umd/cs/findbugs/workflow/Churn.java | 60 +-
.../edu/umd/cs/findbugs/workflow/CloudReport.java | 7 +-
.../cs/findbugs/workflow/CloudSyncAndReport.java | 20 +-
.../umd/cs/findbugs/workflow/CopyBuggySource.java | 56 +-
.../cs/findbugs/workflow/CountByPackagePrefix.java | 28 +-
.../cs/findbugs/workflow/CountClassVersions.java | 96 +-
.../umd/cs/findbugs/workflow/DefectDensity.java | 22 +-
src/java/edu/umd/cs/findbugs/workflow/FB.java | 13 +-
.../edu/umd/cs/findbugs/workflow/FileBugHash.java | 46 +-
src/java/edu/umd/cs/findbugs/workflow/Filter.java | 291 +-
.../cs/findbugs/workflow/ListBugDatabaseInfo.java | 21 +-
.../edu/umd/cs/findbugs/workflow/ListErrors.java | 8 +-
.../findbugs/workflow/MergeSummarizeAndView.java | 49 +-
.../umd/cs/findbugs/workflow/MineBugHistory.java | 87 +-
.../umd/cs/findbugs/workflow/ObfuscateBugs.java | 10 +-
.../umd/cs/findbugs/workflow/PrintAppVersion.java | 2 +-
.../edu/umd/cs/findbugs/workflow/RebornIssues.java | 22 +-
.../workflow/RecursiveSearchForJavaFiles.java | 10 +-
.../findbugs/workflow/RejarClassesForAnalysis.java | 197 +-
.../cs/findbugs/workflow/SetBugDatabaseInfo.java | 106 +-
.../umd/cs/findbugs/workflow/SourceSearcher.java | 18 +-
.../umd/cs/findbugs/workflow/TestingGround.java | 23 +-
.../cs/findbugs/workflow/TreemapVisualization.java | 30 +-
.../edu/umd/cs/findbugs/workflow/UnionResults.java | 27 +-
src/java/edu/umd/cs/findbugs/workflow/Update.java | 232 +-
.../edu/umd/cs/findbugs/xml/Dom4JXMLOutput.java | 25 +-
.../edu/umd/cs/findbugs/xml/MetaCharacterMap.java | 11 +-
.../umd/cs/findbugs/xml/OutputStreamXMLOutput.java | 55 +-
.../umd/cs/findbugs/xml/QuoteMetaCharacters.java | 20 +-
.../edu/umd/cs/findbugs/xml/XMLAttributeList.java | 24 +-
src/java/edu/umd/cs/findbugs/xml/XMLOutput.java | 23 +-
.../edu/umd/cs/findbugs/xml/XMLOutputUtil.java | 16 +-
src/java/edu/umd/cs/findbugs/xml/XMLUtil.java | 11 +-
src/java/edu/umd/cs/findbugs/xml/XMLWriteable.java | 5 +-
src/java/edu/umd/cs/findbugs/xml/XPathFind.java | 7 +-
src/junit/edu/umd/cs/findbugs/BugInstanceTest.java | 8 +-
.../edu/umd/cs/findbugs/ClassScreenerTest.java | 1 -
src/junit/edu/umd/cs/findbugs/DetectorsTest.java | 46 +-
.../edu/umd/cs/findbugs/FindBugsTestCase.java | 43 +-
.../edu/umd/cs/findbugs/IntAnnotationTest.java | 10 +-
.../edu/umd/cs/findbugs/JUnitDetectorAdapter.java | 20 +-
.../edu/umd/cs/findbugs/OpcodeStackItemTest.java | 4 +-
.../cs/findbugs/SAXBugCollectionHandlerTest.java | 2 +-
.../edu/umd/cs/findbugs/ba/MethodHashTest.java | 2 +-
.../umd/cs/findbugs/ba/SignatureParserTest.java | 1 -
.../edu/umd/cs/findbugs/ba/ch/Subtypes2Test.java | 43 +-
.../findbugs/ba/generic/GenericUtilitiesTest.java | 2 +-
.../findbugs/ba/generic/TestGenericObjectType.java | 3 +-
.../ba/jsr305/ValidationSecurityManagerTest.java | 9 +-
.../umd/cs/findbugs/ba/npe/ReturnPathTypeTest.java | 4 +-
.../ba/type/TypeFrameModelingVisitorTest.java | 2 +-
.../cs/findbugs/classfile/TestClassDescriptor.java | 55 +
.../umd/cs/findbugs/cloud/AbstractCloudTest.java | 60 +-
.../findbugs/config/ProjectFilterSettingsTest.java | 14 +-
.../edu/umd/cs/findbugs/filter/NotMatcherTest.java | 12 +-
.../umd/cs/findbugs/filter/SourceMatcherTest.java | 129 +
.../umd/cs/findbugs/gui2/FilterFactoryTest.java | 20 +-
.../umd/cs/findbugs/updates/UpdateCheckerTest.java | 583 +-
.../edu/umd/cs/findbugs/util/ClassNameTest.java | 2 +-
.../edu/umd/cs/findbugs/util/StringsTest.java | 38 +-
.../visitclass/GetNumberArgumentsTest.java | 6 +-
.../edu/umd/cs/findbugs/ba/npe2/AcmpCondition.java | 105 -
.../edu/umd/cs/findbugs/ba/npe2/Condition.java | 47 -
.../edu/umd/cs/findbugs/ba/npe2/Decision.java | 42 -
.../umd/cs/findbugs/ba/npe2/DefinitelyNullSet.java | 201 -
.../ba/npe2/DefinitelyNullSetAnalysis.java | 346 --
.../ba/npe2/DefinitelyNullSetDataflow.java | 29 -
.../ba/npe2/DefinitelyNullSetDataflowFactory.java | 62 -
.../umd/cs/findbugs/ba/npe2/IfNullCondition.java | 100 -
.../edu/umd/cs/findbugs/ba/npe2/NullnessValue.java | 144 -
.../cs/findbugs/ba/npe2/TestDefinitelyNullSet.java | 44 -
.../umd/cs/findbugs/ba/npe2/TestNullnessValue.java | 43 -
.../edu/umd/cs/findbugs/ba/npe2/package.html | 23 -
.../edu/umd/cs/findbugs/gui/AboutDialog.form | 115 -
.../edu/umd/cs/findbugs/gui/AboutDialog.java | 255 -
.../umd/cs/findbugs/gui/AnalysisErrorDialog.form | 154 -
.../umd/cs/findbugs/gui/AnalysisErrorDialog.java | 246 -
.../edu/umd/cs/findbugs/gui/AnalysisRun.java | 220 -
.../edu/umd/cs/findbugs/gui/BugCellRenderer.java | 144 -
.../edu/umd/cs/findbugs/gui/BugInstanceGroup.java | 89 -
.../cs/findbugs/gui/ConfigureDetectorsDialog.form | 138 -
.../cs/findbugs/gui/ConfigureDetectorsDialog.java | 382 --
.../cs/findbugs/gui/DefaultSortedTableModel.java | 270 -
.../edu/umd/cs/findbugs/gui/FindBugsFrame.form | 1575 ------
.../edu/umd/cs/findbugs/gui/FindBugsFrame.java | 3981 --------------
src/obsolete/edu/umd/cs/findbugs/gui/Grouper.java | 83 -
.../edu/umd/cs/findbugs/gui/LineNumberer.java | 90 -
.../edu/umd/cs/findbugs/gui/OSXAdapter.java | 108 -
.../edu/umd/cs/findbugs/gui/RunAnalysisDialog.form | 152 -
.../edu/umd/cs/findbugs/gui/RunAnalysisDialog.java | 386 --
.../umd/cs/findbugs/gui/SwingGUIBugReporter.java | 107 -
src/obsolete/edu/umd/cs/findbugs/gui/bug-logo.png | Bin 3714 -> 0 bytes
src/obsolete/edu/umd/cs/findbugs/gui/bug.png | Bin 458 -> 0 bytes
src/obsolete/edu/umd/cs/findbugs/gui/bug2.png | Bin 357 -> 0 bytes
src/obsolete/edu/umd/cs/findbugs/gui/class.png | Bin 355 -> 0 bytes
src/obsolete/edu/umd/cs/findbugs/gui/down.png | Bin 364 -> 0 bytes
src/obsolete/edu/umd/cs/findbugs/gui/field.png | Bin 321 -> 0 bytes
src/obsolete/edu/umd/cs/findbugs/gui/informal.png | Bin 12237 -> 0 bytes
src/obsolete/edu/umd/cs/findbugs/gui/logo_umd.png | Bin 2916 -> 0 bytes
src/obsolete/edu/umd/cs/findbugs/gui/method.png | Bin 216 -> 0 bytes
src/obsolete/edu/umd/cs/findbugs/gui/package.png | Bin 680 -> 0 bytes
.../edu/umd/cs/findbugs/gui/sourcefile.png | Bin 208 -> 0 bytes
src/obsolete/edu/umd/cs/findbugs/gui/up.png | Bin 364 -> 0 bytes
.../edu/umd/cs/findbugs/ml/ConvertToARFF.java | 936 ----
.../edu/umd/cs/findbugs/ml/GenerateUIDs.java | 128 -
src/scripts/deprecated/bugHistory | 0
src/scripts/deprecated/updateBugs | 0
src/scripts/standard/convertXmlToText | 0
src/scripts/standard/defectDensity | 0
src/scripts/standard/fbwrap | 0
src/scripts/standard/filterBugs | 0
src/scripts/standard/findbugs | 0
src/scripts/standard/findbugs-csr | 0
src/scripts/standard/findbugs-dbStats | 0
src/scripts/standard/findbugs-msv | 0
src/scripts/standard/mineBugHistory | 0
src/scripts/standard/printAppVersion | 0
src/scripts/standard/unionBugs | 0
src/scripts/standard/xpathFind | 0
.../cs/findbugs/tools/CheckClassfileVersion.java | 61 +-
.../umd/cs/findbugs/tools/ComparePerfomance.java | 67 +-
.../FilterAndCombineBitfieldPropertyDatabase.java | 29 +-
.../cs/findbugs/tools/FilterPropertyDatabase.java | 16 +-
.../edu/umd/cs/findbugs/tools/FixIndentation.java | 60 +-
.../umd/cs/findbugs/tools/GenerateUpdateXml.java | 12 +-
.../cs/findbugs/tools/html/ColorAlternator.java | 3 +-
.../tools/html/PlainPrintBugDescriptions.java | 7 +-
.../tools/html/PrettyPrintBugDescriptions.java | 15 +-
.../findbugs/tools/html/PrintBugDescriptions.java | 7 +-
.../cs/findbugs/tools/junit/JUnitJarRunner.java | 55 +-
.../umd/cs/findbugs/tools/xml/CheckMessages.java | 32 +-
src/xsl/color.xsl | 351 ++
1146 files changed, 41158 insertions(+), 36777 deletions(-)
diff --git a/.classpath b/.classpath
index 87680be..a0ffe89 100644
--- a/.classpath
+++ b/.classpath
@@ -7,7 +7,7 @@
<classpathentry kind="src" path="src/xsl"/>
<classpathentry kind="src" path="src/junit"/>
<classpathentry kind="src" path="src/gui"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5">
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<accessrules>
<accessrule kind="accessible" pattern="com/sun/management/*"/>
<accessrule kind="nonaccessible" pattern="com/sun/**"/>
@@ -16,11 +16,6 @@
</accessrules>
</classpathentry>
<classpathentry exported="true" kind="lib" path="lib/AppleJavaExtensions.jar"/>
- <classpathentry exported="true" kind="lib" path="lib/bcel.jar">
- <attributes>
- <attribute name="javadoc_location" value="http://jakarta.apache.org/bcel/apidocs/"/>
- </attributes>
- </classpathentry>
<classpathentry exported="true" kind="lib" path="lib/dom4j-1.6.1.jar">
<attributes>
<attribute name="javadoc_location" value="http://dom4j.org/apidocs/"/>
@@ -33,14 +28,14 @@
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry exported="true" kind="lib" path="lib/jsr305.jar" sourcepath="lib/jsr305.jar"/>
<classpathentry exported="true" kind="lib" path="lib/jaxen-1.1.6.jar"/>
- <classpathentry exported="true" kind="lib" path="lib/jFormatString.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jFormatString.jar"/>
<classpathentry exported="true" kind="lib" path="lib/jdepend-2.9.jar"/>
- <classpathentry exported="true" kind="lib" path="lib/asm-3.3.jar" sourcepath="lib/asm-src-3.3.zip"/>
- <classpathentry exported="true" kind="lib" path="lib/asm-commons-3.3.jar" sourcepath="lib/asm-src-3.3.zip"/>
- <classpathentry exported="true" kind="lib" path="lib/asm-tree-3.3.jar" sourcepath="lib/asm-src-3.3.zip"/>
- <classpathentry exported="true" kind="lib" path="lib/ant.jar"/>
- <classpathentry exported="true" kind="lib" path="lib/asm-analysis-3.3.jar" sourcepath="lib/asm-src-3.3.zip"/>
- <classpathentry exported="true" kind="lib" path="lib/asm-util-3.3.jar" sourcepath="lib/asm-src-3.3.zip"/>
- <classpathentry exported="true" kind="lib" path="lib/asm-xml-3.3.jar" sourcepath="lib/asm-src-3.3.zip"/>
+ <classpathentry exported="true" kind="lib" path="lib/ant.jar" sourcepath="lib/apache-ant-1.8.3-src.zip"/>
+ <classpathentry exported="true" kind="lib" path="lib/asm-debug-all-5.0.2.jar" sourcepath="/asm3"/>
+ <classpathentry exported="true" kind="lib" path="lib/bcel-6.0-SNAPSHOT.jar">
+ <attributes>
+ <attribute name="javadoc_location" value="http://commons.apache.org/proper/commons-bcel/apidocs/"/>
+ </attributes>
+ </classpathentry>
<classpathentry kind="output" path="classesEclipse"/>
</classpath>
diff --git a/.settings/de.loskutov.anyedit.AnyEditTools.prefs b/.settings/de.loskutov.anyedit.AnyEditTools.prefs
index b4df669..4959f8c 100644
--- a/.settings/de.loskutov.anyedit.AnyEditTools.prefs
+++ b/.settings/de.loskutov.anyedit.AnyEditTools.prefs
@@ -1,8 +1,9 @@
-#Sun Sep 19 07:41:57 CEST 2010
-activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk
+activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,.classpath,*.properties,.project
addNewLine=true
convertActionOnSaave=AnyEdit.CnvrtTabToSpaces
eclipse.preferences.version=1
+fixLineDelimiters=true
+ignoreBlankLinesWhenTrimming=false
inActiveContentFilterList=
javaTabWidthForJava=true
org.eclipse.jdt.ui.editor.tab.width=4
@@ -12,5 +13,6 @@ replaceAllSpaces=false
replaceAllTabs=false
saveAndAddLine=true
saveAndConvert=true
+saveAndFixLineDelimiters=true
saveAndTrim=true
useModulo4Tabs=false
diff --git a/.settings/edu.umd.cs.findbugs.core.prefs b/.settings/edu.umd.cs.findbugs.core.prefs
index a06a096..67d3265 100644
--- a/.settings/edu.umd.cs.findbugs.core.prefs
+++ b/.settings/edu.umd.cs.findbugs.core.prefs
@@ -1,26 +1,15 @@
#FindBugs User Preferences
-#Thu Nov 07 08:16:06 EST 2013
+#Wed Jun 18 10:04:41 CEST 2014
cloud_id=edu.umd.cs.findbugs.cloud.appengine.findbugs-cloud
-detectorAbnormalFinallyBlockReturn=AbnormalFinallyBlockReturn|true
-detectorAbstractClassEmptyMethods=AbstractClassEmptyMethods|true
-detectorAbstractOverriddenMethod=AbstractOverriddenMethod|true
detectorAppendingToAnObjectOutputStream=AppendingToAnObjectOutputStream|true
-detectorArrayBasedCollections=ArrayBasedCollections|true
-detectorArrayWrappedCallByReference=ArrayWrappedCallByReference|true
detectorAtomicityProblem=AtomicityProblem|true
-detectorBCPMethodReturnCheck=BCPMethodReturnCheck|false
detectorBadAppletConstructor=BadAppletConstructor|false
detectorBadResultSetAccess=BadResultSetAccess|true
detectorBadSyntaxForRegularExpression=BadSyntaxForRegularExpression|true
detectorBadUseOfReturnValue=BadUseOfReturnValue|true
detectorBadlyOverriddenAdapter=BadlyOverriddenAdapter|true
-detectorBogusExceptionDeclaration=BogusExceptionDeclaration|true
detectorBooleanReturnNull=BooleanReturnNull|true
-detectorBuildInterproceduralCallGraph=BuildInterproceduralCallGraph|false
-detectorBuildObligationPolicyDatabase=BuildObligationPolicyDatabase|true
detectorCallToUnsupportedMethod=CallToUnsupportedMethod|true
-detectorCalledMethods=CalledMethods|true
-detectorCheckCalls=CheckCalls|false
detectorCheckExpectedWarnings=CheckExpectedWarnings|false
detectorCheckImmutableAnnotation=CheckImmutableAnnotation|true
detectorCheckRelaxingNullnessAnnotation=CheckRelaxingNullnessAnnotation|true
@@ -28,43 +17,23 @@ detectorCheckTypeQualifiers=CheckTypeQualifiers|true
detectorCloneIdiom=CloneIdiom|true
detectorComparatorIdiom=ComparatorIdiom|true
detectorConfusedInheritance=ConfusedInheritance|true
-detectorConfusingAutoboxedOverloading=ConfusingAutoboxedOverloading|true
-detectorConfusingFunctionSemantics=ConfusingFunctionSemantics|true
detectorConfusionBetweenInheritedAndOuterMethod=ConfusionBetweenInheritedAndOuterMethod|true
-detectorConstantListIndex=ConstantListIndex|true
-detectorCopiedOverriddenMethod=CopiedOverriddenMethod|true
-detectorCrossSiteScripting=CrossSiteScripting|false
-detectorCustomBuiltXML=CustomBuiltXML|true
-detectorCyclomaticComplexity=CyclomaticComplexity|true
-detectorDateComparison=DateComparison|true
-detectorDeclaredRuntimeException=DeclaredRuntimeException|true
+detectorCrossSiteScripting=CrossSiteScripting|true
detectorDefaultEncodingDetector=DefaultEncodingDetector|true
-detectorDeletingWhileIterating=DeletingWhileIterating|true
-detectorDeprecatedTypesafeEnumPattern=DeprecatedTypesafeEnumPattern|true
detectorDoInsideDoPrivileged=DoInsideDoPrivileged|true
detectorDontCatchIllegalMonitorStateException=DontCatchIllegalMonitorStateException|true
detectorDontIgnoreResultOfPutIfAbsent=DontIgnoreResultOfPutIfAbsent|true
detectorDontUseEnum=DontUseEnum|true
detectorDroppedException=DroppedException|true
-detectorDubiousListCollection=DubiousListCollection|true
-detectorDubiousSetOfCollections=DubiousSetOfCollections|true
detectorDumbMethodInvocations=DumbMethodInvocations|true
detectorDumbMethods=DumbMethods|true
detectorDuplicateBranches=DuplicateBranches|true
detectorEmptyZipFileEntry=EmptyZipFileEntry|true
-detectorEqStringTest=EqStringTest|false
detectorEqualsOperandShouldHaveClassCompatibleWithThis=EqualsOperandShouldHaveClassCompatibleWithThis|true
-detectorExceptionSoftening=ExceptionSoftening|true
detectorExplicitSerialization=ExplicitSerialization|true
-detectorFieldCouldBeLocal=FieldCouldBeLocal|true
-detectorFieldItemSummary=FieldItemSummary|true
-detectorFinalParameters=FinalParameters|true
detectorFinalizerNullsFields=FinalizerNullsFields|true
-detectorFindBadCast=FindBadCast|false
detectorFindBadCast2=FindBadCast2|true
-detectorFindBadEqualsImplementation=FindBadEqualsImplementation|false
detectorFindBadForLoop=FindBadForLoop|true
-detectorFindBugsSummaryStats=FindBugsSummaryStats|true
detectorFindCircularDependencies=FindCircularDependencies|false
detectorFindDeadLocalStores=FindDeadLocalStores|true
detectorFindDoubleCheck=FindDoubleCheck|true
@@ -72,7 +41,6 @@ detectorFindEmptySynchronizedBlock=FindEmptySynchronizedBlock|true
detectorFindFieldSelfAssignment=FindFieldSelfAssignment|true
detectorFindFinalizeInvocations=FindFinalizeInvocations|true
detectorFindFloatEquality=FindFloatEquality|true
-detectorFindFloatMath=FindFloatMath|false
detectorFindHEmismatch=FindHEmismatch|true
detectorFindInconsistentSync2=FindInconsistentSync2|true
detectorFindJSR166LockMonitorenter=FindJSR166LockMonitorenter|true
@@ -80,21 +48,19 @@ detectorFindLocalSelfAssignment2=FindLocalSelfAssignment2|true
detectorFindMaskedFields=FindMaskedFields|true
detectorFindMismatchedWaitOrNotify=FindMismatchedWaitOrNotify|true
detectorFindNakedNotify=FindNakedNotify|true
-detectorFindNonSerializableStoreIntoSession=FindNonSerializableStoreIntoSession|true
-detectorFindNonSerializableValuePassedToWriteObject=FindNonSerializableValuePassedToWriteObject|true
detectorFindNonShortCircuit=FindNonShortCircuit|true
detectorFindNullDeref=FindNullDeref|true
detectorFindNullDerefsInvolvingNonShortCircuitEvaluation=FindNullDerefsInvolvingNonShortCircuitEvaluation|true
detectorFindOpenStream=FindOpenStream|true
detectorFindPuzzlers=FindPuzzlers|true
detectorFindRefComparison=FindRefComparison|true
-detectorFindReturnRef=FindReturnRef|false
+detectorFindReturnRef=FindReturnRef|true
detectorFindRunInvocations=FindRunInvocations|true
detectorFindSelfComparison=FindSelfComparison|true
detectorFindSelfComparison2=FindSelfComparison2|true
detectorFindSleepWithLockHeld=FindSleepWithLockHeld|true
detectorFindSpinLoop=FindSpinLoop|true
-detectorFindSqlInjection=FindSqlInjection|false
+detectorFindSqlInjection=FindSqlInjection|true
detectorFindTwoLockWait=FindTwoLockWait|true
detectorFindUncalledPrivateMethods=FindUncalledPrivateMethods|true
detectorFindUnconditionalWait=FindUnconditionalWait|true
@@ -105,23 +71,15 @@ detectorFindUnsatisfiedObligation=FindUnsatisfiedObligation|true
detectorFindUnsyncGet=FindUnsyncGet|true
detectorFindUseOfNonSerializableValue=FindUseOfNonSerializableValue|true
detectorFindUselessControlFlow=FindUselessControlFlow|true
-detectorFloatingPointLoops=FloatingPointLoops|true
-detectorFormatStringChecker=FormatStringChecker|false
+detectorFormatStringChecker=FormatStringChecker|true
detectorHugeSharedStringConstants=HugeSharedStringConstants|true
detectorIDivResultCastToDouble=IDivResultCastToDouble|true
-detectorImproperPropertiesUse=ImproperPropertiesUse|true
-detectorInappropriateToStringUse=InappropriateToStringUse|true
detectorIncompatMask=IncompatMask|true
detectorInconsistentAnnotations=InconsistentAnnotations|true
-detectorInconsistentKeyNameCasing=InconsistentKeyNameCasing|true
-detectorIncorrectInternalClassUse=IncorrectInternalClassUse|true
detectorInefficientMemberAccess=InefficientMemberAccess|false
-detectorInefficientStringBuffering=InefficientStringBuffering|true
detectorInefficientToArray=InefficientToArray|true
detectorInfiniteLoop=InfiniteLoop|true
detectorInfiniteRecursiveLoop=InfiniteRecursiveLoop|true
-detectorInfiniteRecursiveLoop2=InfiniteRecursiveLoop2|false
-detectorInheritanceTypeChecking=InheritanceTypeChecking|true
detectorInheritanceUnsafeGetResource=InheritanceUnsafeGetResource|true
detectorInitializationChain=InitializationChain|true
detectorInitializeNonnullFieldsInConstructor=InitializeNonnullFieldsInConstructor|true
@@ -129,133 +87,49 @@ detectorInstantiateStaticClass=InstantiateStaticClass|true
detectorIntCast2LongAsInstant=IntCast2LongAsInstant|true
detectorInvalidJUnitTest=InvalidJUnitTest|true
detectorIteratorIdioms=IteratorIdioms|true
-detectorJDBCVendorReliance=JDBCVendorReliance|true
-detectorJUnitAssertionOddities=JUnitAssertionOddities|true
detectorLazyInit=LazyInit|true
-detectorListIndexedIterating=ListIndexedIterating|true
-detectorLiteralStringComparison=LiteralStringComparison|true
detectorLoadOfKnownNullValue=LoadOfKnownNullValue|true
-detectorLocalSynchronizedCollection=LocalSynchronizedCollection|true
-detectorLockedFields=LockedFields|false
-detectorLoggerOddities=LoggerOddities|true
-detectorLostExceptionStackTrace=LostExceptionStackTrace|true
detectorLostLoggerDueToWeakReference=LostLoggerDueToWeakReference|true
-detectorManualArrayCopy=ManualArrayCopy|true
detectorMethodReturnCheck=MethodReturnCheck|true
-detectorMethodReturnsConstant=MethodReturnsConstant|true
-detectorMethods=Methods|true
-detectorMisleadingOverloadModel=MisleadingOverloadModel|true
-detectorMoreDumbMethods=MoreDumbMethods|true
detectorMultithreadedInstanceAccess=MultithreadedInstanceAccess|true
detectorMutableLock=MutableLock|true
detectorMutableStaticFields=MutableStaticFields|true
detectorNaming=Naming|true
-detectorNeedlessAutoboxing=NeedlessAutoboxing|true
-detectorNeedlessCustomSerialization=NeedlessCustomSerialization|true
-detectorNeedlessInstanceRetrieval=NeedlessInstanceRetrieval|true
-detectorNeedlessMemberCollectionSynchronization=NeedlessMemberCollectionSynchronization|true
-detectorNonCollectionMethodUse=NonCollectionMethodUse|true
-detectorNonFunctionalField=NonFunctionalField|true
-detectorNonOwnedSynchronization=NonOwnedSynchronization|true
-detectorNonRecycleableTaglibs=NonRecycleableTaglibs|true
-detectorNonSymmetricEquals=NonSymmetricEquals|true
-detectorNoteAnnotationRetention=NoteAnnotationRetention|true
-detectorNoteCheckReturnValue=NoteCheckReturnValue|true
-detectorNoteCheckReturnValueAnnotations=NoteCheckReturnValueAnnotations|true
-detectorNoteDirectlyRelevantTypeQualifiers=NoteDirectlyRelevantTypeQualifiers|true
-detectorNoteJCIPAnnotation=NoteJCIPAnnotation|true
-detectorNoteNonNullAnnotations=NoteNonNullAnnotations|true
-detectorNoteNonnullReturnValues=NoteNonnullReturnValues|true
-detectorNoteSuppressedWarnings=NoteSuppressedWarnings|true
detectorNoteUnconditionalParamDerefs=NoteUnconditionalParamDerefs|true
detectorNumberConstructor=NumberConstructor|true
-detectorOrphanedDOMNode=OrphanedDOMNode|true
-detectorOverlyConcreteParameter=OverlyConcreteParameter|true
+detectorOptionalReturnNull=OptionalReturnNull|true
detectorOverridingEqualsNotSymmetrical=OverridingEqualsNotSymmetrical|true
-detectorOverzealousCasting=OverzealousCasting|true
-detectorParallelLists=ParallelLists|true
-detectorPartiallyConstructedObjectAccess=PartiallyConstructedObjectAccess|true
-detectorPoorlyDefinedParameter=PoorlyDefinedParameter|true
-detectorPossibleConstantAllocationInLoop=PossibleConstantAllocationInLoop|true
-detectorPossibleIncompleteSerialization=PossibleIncompleteSerialization|true
-detectorPossibleMemoryBloat=PossibleMemoryBloat|true
-detectorPossibleUnsuspectedSerialization=PossibleUnsuspectedSerialization|true
-detectorPossiblyRedundantMethodCalls=PossiblyRedundantMethodCalls|true
detectorPreferZeroLengthArrays=PreferZeroLengthArrays|true
detectorPublicSemaphores=PublicSemaphores|true
detectorQuestionableBooleanAssignment=QuestionableBooleanAssignment|true
detectorReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass=ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass|true
detectorReadReturnShouldBeChecked=ReadReturnShouldBeChecked|true
detectorRedundantInterfaces=RedundantInterfaces|true
-detectorReflectionOnObjectMethods=ReflectionOnObjectMethods|true
-detectorReflectiveClasses=ReflectiveClasses|true
detectorRepeatedConditionals=RepeatedConditionals|true
-detectorResolveAllReferences=ResolveAllReferences|false
detectorRuntimeExceptionCapture=RuntimeExceptionCapture|true
-detectorSQLInLoop=SQLInLoop|true
-detectorSection508Compliance=Section508Compliance|true
detectorSerializableIdiom=SerializableIdiom|true
-detectorSideEffectConstructor=SideEffectConstructor|true
-detectorSillynessPotPourri=SillynessPotPourri|true
-detectorSloppyClassReflection=SloppyClassReflection|true
-detectorSluggishGui=SluggishGui|true
-detectorSpoiledChildInterfaceImplementor=SpoiledChildInterfaceImplementor|true
-detectorSpuriousThreadStates=SpuriousThreadStates|true
detectorStartInConstructor=StartInConstructor|true
-detectorStaticArrayCreatedInMethod=StaticArrayCreatedInMethod|true
detectorStaticCalendarDetector=StaticCalendarDetector|true
-detectorStaticMethodInstanceInvocation=StaticMethodInstanceInvocation|true
detectorStringConcatenation=StringConcatenation|true
detectorSuperfluousInstanceOf=SuperfluousInstanceOf|true
-detectorSuspiciousCloneAlgorithm=SuspiciousCloneAlgorithm|true
-detectorSuspiciousClusteredSessionSupport=SuspiciousClusteredSessionSupport|true
-detectorSuspiciousComparatorReturnValues=SuspiciousComparatorReturnValues|true
-detectorSuspiciousGetterSetterUse=SuspiciousGetterSetterUse|true
-detectorSuspiciousJDKVersionUse=SuspiciousJDKVersionUse|false
-detectorSuspiciousNullGuard=SuspiciousNullGuard|true
detectorSuspiciousThreadInterrupted=SuspiciousThreadInterrupted|true
-detectorSuspiciousUninitializedArray=SuspiciousUninitializedArray|true
-detectorSuspiciousWaitOnConcurrentObject=SuspiciousWaitOnConcurrentObject|true
detectorSwitchFallthrough=SwitchFallthrough|true
-detectorSyncCollectionIterators=SyncCollectionIterators|true
-detectorSynchronizationOnSharedBuiltinConstant=SynchronizationOnSharedBuiltinConstant|true
detectorSynchronizeAndNullCheckField=SynchronizeAndNullCheckField|true
detectorSynchronizeOnClassLiteralNotGetClass=SynchronizeOnClassLiteralNotGetClass|true
detectorSynchronizingOnContentsOfFieldToProtectField=SynchronizingOnContentsOfFieldToProtectField|true
-detectorTailRecursion=TailRecursion|true
-detectorTestASM=TestASM|false
-detectorTestDataflowAnalysis=TestDataflowAnalysis|false
-detectorTestingGround=TestingGround|false
-detectorTrainFieldStoreTypes=TrainFieldStoreTypes|true
-detectorTrainNonNullAnnotations=TrainNonNullAnnotations|true
-detectorTrainUnconditionalDerefParams=TrainUnconditionalDerefParams|true
-detectorTristateBooleanPattern=TristateBooleanPattern|true
detectorURLProblems=URLProblems|true
detectorUncallableMethodOfAnonymousClass=UncallableMethodOfAnonymousClass|true
detectorUnnecessaryMath=UnnecessaryMath|true
-detectorUnnecessaryNewNullCheck=UnnecessaryNewNullCheck|true
-detectorUnnecessaryStoreBeforeReturn=UnnecessaryStoreBeforeReturn|true
detectorUnreadFields=UnreadFields|true
-detectorUnrelatedCollectionContents=UnrelatedCollectionContents|true
-detectorUnrelatedReturnValues=UnrelatedReturnValues|true
-detectorUseAddAll=UseAddAll|true
-detectorUseCharacterParameterizedMethod=UseCharacterParameterizedMethod|true
-detectorUseEnumCollections=UseEnumCollections|true
-detectorUseObjectEquals=UseObjectEquals|true
-detectorUseSplit=UseSplit|true
-detectorUseToArray=UseToArray|true
-detectorUseVarArgs=UseVarArgs|true
detectorUselessSubclassMethod=UselessSubclassMethod|true
detectorVarArgsProblems=VarArgsProblems|true
detectorVolatileUsage=VolatileUsage|true
detectorWaitInLoop=WaitInLoop|true
-detectorWeakExceptionMessaging=WeakExceptionMessaging|true
-detectorWriteOnlyCollection=WriteOnlyCollection|true
detectorWrongMapIterator=WrongMapIterator|true
detectorXMLFactoryBypass=XMLFactoryBypass|true
-detector_threshold=2
+detector_threshold=3
effort=default
excludefilter0=findbugsExclude.xml|true
-filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,EXPERIMENTAL,I18N,MT_CORRECTNESS,PERFORMANCE,SECURITY,STYLE|false|15
+filter_settings=Low|BAD_PRACTICE,CORRECTNESS,EXPERIMENTAL,I18N,MT_CORRECTNESS,PERFORMANCE,SECURITY,STYLE|false|20
filter_settings_neg=MALICIOUS_CODE,NOISE|
run_at_full_build=false
diff --git a/.settings/edu.umd.cs.findbugs.plugin.eclipse.prefs b/.settings/edu.umd.cs.findbugs.plugin.eclipse.prefs
index 74b9fa6..476ea87 100644
--- a/.settings/edu.umd.cs.findbugs.plugin.eclipse.prefs
+++ b/.settings/edu.umd.cs.findbugs.plugin.eclipse.prefs
@@ -1,3 +1,2 @@
eclipse.preferences.version=1
-edu.umd.cs.findbugs.plugin.eclipse.findbugsMarkerOfConcern=Info
runAnalysisAsExtraJob=true
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..99f26c0
--- /dev/null
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/.settings/org.eclipse.core.runtime.prefs b/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..5a0ad22
--- /dev/null
+++ b/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index bcd62eb..90a6dcd 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,5 +1,4 @@
eclipse.preferences.version=1
-instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
org.eclipse.jdt.core.builder.invalidClasspath=abort
@@ -27,9 +26,9 @@ org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled
org.eclipse.jdt.core.compiler.annotation.nullable=javax.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -40,7 +39,7 @@ org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=ignore
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
@@ -135,7 +134,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.source=1.7
org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL,HIGH
org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX,MUSTFIX
@@ -222,10 +221,8 @@ org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=4
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
index c68fe73..932c503 100644
--- a/.settings/org.eclipse.jdt.ui.prefs
+++ b/.settings/org.eclipse.jdt.ui.prefs
@@ -1,12 +1,75 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=true
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.make_local_variable_final=false
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup.use_type_arguments=false
+cleanup_profile=_FindBugs
+cleanup_settings_version=2
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_FindBugs
formatter_settings_version=12
org.eclipse.jdt.ui.exception.name=e
org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
org.eclipse.jdt.ui.javadoc=true
org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=2
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return Returns the ${bare_field_name}.\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Commen [...]
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
@@ -15,21 +78,23 @@ sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
-sp_cleanup.add_missing_override_annotations_interface_methods=false
+sp_cleanup.add_missing_override_annotations_interface_methods=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
sp_cleanup.convert_to_enhanced_for_loop=false
-sp_cleanup.correct_indentation=false
+sp_cleanup.correct_indentation=true
sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.insert_inferred_type_arguments=false
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
sp_cleanup.make_type_abstract_if_missing_method=false
-sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.make_variable_declarations_final=true
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=true
@@ -40,9 +105,10 @@ sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=false
sp_cleanup.remove_trailing_whitespaces=true
-sp_cleanup.remove_trailing_whitespaces_all=false
-sp_cleanup.remove_trailing_whitespaces_ignore_empty=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_casts=true
sp_cleanup.remove_unnecessary_nls_tags=false
sp_cleanup.remove_unused_imports=true
@@ -53,10 +119,13 @@ sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
-sp_cleanup.use_blocks=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=true
sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=false
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF
index 1ccf4f9..163c032 100644
--- a/META-INF/MANIFEST.MF
+++ b/META-INF/MANIFEST.MF
@@ -6,20 +6,15 @@ Bundle-SymbolicName: findbugs
Bundle-Version: 1.0.0
Bundle-ClassPath: findbugs.jar,
lib/AppleJavaExtensions.jar,
- lib/bcel.jar,
+ lib/bcel-6.0-SNAPSHOT.jar,
lib/dom4j-1.6.1.jar,
lib/junit.jar,
- lib/asm-3.3.jar,
- lib/asm-tree-3.3.jar,
- lib/asm-commons-3.3.jar,
+ lib/asm-debug-all-5.0.2.jar,
lib/jaxen-1.1.6.jar,
lib/jFormatString.jar,
lib/commons-lang-2.6.jar,
lib/jsr305.jar,
lib/ant.jar,
- lib/asm-analysis-3.3.jar,
- lib/asm-util-3.3.jar,
- lib/asm-xml-3.3.jar,
lib/jcip-annotations.jar,
lib/jdepend-2.9.jar,
lib/yjp-controller-api-redist.jar
@@ -77,6 +72,7 @@ Export-Package: edu.umd.cs.findbugs,
edu.umd.cs.findbugs.tools.html,
edu.umd.cs.findbugs.tools.junit,
edu.umd.cs.findbugs.tools.xml,
+ edu.umd.cs.findbugs.updates,
edu.umd.cs.findbugs.util,
edu.umd.cs.findbugs.visitclass,
edu.umd.cs.findbugs.workflow,
@@ -96,5 +92,8 @@ Export-Package: edu.umd.cs.findbugs,
org.objectweb.asm,
org.objectweb.asm.commons,
org.objectweb.asm.signature,
- org.objectweb.asm.tree
-Bundle-RequiredExecutionEnvironment: J2SE-1.5
+ org.objectweb.asm.tree,
+ org.objectweb.asm.tree.analysis,
+ org.objectweb.asm.util,
+ org.objectweb.asm.xml
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
diff --git a/build.xml b/build.xml
index 0981cc5..698b91f 100644
--- a/build.xml
+++ b/build.xml
@@ -37,7 +37,7 @@
<property name="samplesrc.dir" value="src/sampleXml"/>
<property name="etc.dir" value="etc"/>
<property name="test.dir" value="test"/>
- <property name="doc.dir" value="doc"/>
+ <property name="doc.dir" value="build/doc"/>
<property name="web.dir" value="web"/>
<property name="apiDoc.dir" value="apiJavaDoc"/>
<property name="annotationDoc.dir" value="annotationJavaDoc"/>
@@ -56,22 +56,10 @@
<property name="scripts.stamp" value="${build.dir}/scripts.stamp"/>
<property name="allClassFiles.jar" value="${build.dir}/allClassFiles.jar"/>
<property name="doc.props.file" value="${etc.dir}/doc.properties"/>
- <property name="svnrnum" value="Unknown"/>
<property name="version.props.file" value="${build.dir}/classes/edu/umd/cs/findbugs/version.properties"/>
<path id="findbugs.classpath">
- <pathelement location="${jar.dir}/bcel.jar"/>
- <pathelement location="${jar.dir}/dom4j-1.6.1.jar"/>
- <pathelement location="${jar.dir}/AppleJavaExtensions.jar"/>
- <pathelement location="${jar.dir}/junit.jar"/>
- <pathelement location="${jar.dir}/asm-3.3.jar"/>
- <pathelement location="${jar.dir}/asm-commons-3.3.jar"/>
- <pathelement location="${jar.dir}/asm-tree-3.3.jar"/>
- <pathelement location="${jar.dir}/jaxen-1.1.6.jar"/>
- <pathelement location="${jar.dir}/jsr305.jar"/>
- <pathelement location="${jar.dir}/jFormatString.jar"/>
- <pathelement location="${jar.dir}/commons-lang-2.6.jar"/>
- <pathelement location="${jar.dir}/jcip-annotations.jar"/>
+ <fileset dir="${jar.dir}" includes="*.jar"/>
</path>
<path id="tools.classpath">
@@ -81,13 +69,6 @@
<path refid="findbugs.classpath"/>
</path>
- <path id="svn.classpath">
-
- <fileset dir="${svnant.home}/lib">
- <include name="*.jar"/>
- </fileset>
- </path>
-
<patternset id="codebase.data.pats">
<include name="**/*.properties"/>
@@ -121,51 +102,39 @@
<!-- Rebuild from scratch. -->
<target name="rebuild" depends="clean,build"/>
- <target name="mondo" depends="jars">
- <jar destfile="build/mondo.jar"
- manifest="etc/MANIFEST-findbugs-mondo.MF">
- <zipfileset src="${jar.dir}/bcel.jar"/>
- <zipfileset src="${jar.dir}/dom4j-1.6.1.jar"/>
- <zipfileset src="${jar.dir}/AppleJavaExtensions.jar"/>
- <zipfileset src="${jar.dir}/junit.jar"/>
- <zipfileset src="${jar.dir}/asm-3.3.jar"/>
- <zipfileset src="${jar.dir}/asm-commons-3.3.jar"/>
- <zipfileset src="${jar.dir}/asm-tree-3.3.jar"/>
- <zipfileset src="${jar.dir}/jaxen-1.1.6.jar"/>
- <zipfileset src="${jar.dir}/jsr305.jar"/>
- <zipfileset src="${jar.dir}/jFormatString.jar"/>
- <zipfileset src="${jar.dir}/commons-lang-2.6.jar"/>
- <zipfileset src="${jar.dir}/findbugs.jar"/>
- </jar>
- </target>
-
<!-- Compile Java source files, and copy other files (properties,
images, html, XSL stylesheets) that need to be part of the codebase. -->
<target name="errorprone" depends="clean,init">
<javac
destdir="${classes.dir}"
- source="1.5"
- target="1.5"
+ source="1.7"
+ target="1.7"
includeantruntime="false"
encoding="ISO-8859-1"
deprecation="off"
debug="on"
- compiler="com.google.errorprone.ErrorProneAntCompilerAdapter"
- >
+ compiler="com.google.errorprone.ErrorProneAntCompilerAdapter"
+ >
<compilerarg value="-Xlint:unchecked"/>
<src path="${src.dir}"/>
<src path="${src5.dir}"/>
<classpath refid="findbugs.classpath"/>
</javac>
- </target>
+ </target>
<target name="classes" depends="init">
+ <echo>Requires JDK 7.x (not 8!), using: ${ant.java.version}</echo>
+ <fail message="Requires JDK 7.x (not 8!), using: ${ant.java.version}">
+ <condition>
+ <equals arg1="1.8" arg2="${ant.java.version}"/>
+ </condition>
+ </fail>
<!-- Compile Java source files. -->
<echo level="info" message="compiling findbugs"/>
<javac
destdir="${classes.dir}"
- source="1.5"
- target="1.5"
+ source="1.7"
+ target="1.7"
includeantruntime="false"
encoding="ISO-8859-1"
deprecation="off"
@@ -197,8 +166,8 @@
<echo level="info" message="compiling junit test cases"/>
<javac srcdir="${junitsrc.dir}"
destdir="${junitclasses.dir}"
- source="1.5"
- target="1.5"
+ source="1.7"
+ target="1.7"
includeantruntime="false"
encoding="ISO-8859-1"
deprecation="off"
@@ -209,8 +178,8 @@
<echo level="info" message="compiling tools"/>
<javac srcdir="${toolsrc.dir}"
destdir="${classes.dir}"
- source="1.5"
- target="1.5"
+ source="1.7"
+ target="1.7"
includeantruntime="false"
encoding="ISO-8859-1"
debug="on"
@@ -223,8 +192,8 @@
<echo level="info" message="compiling ant task"/>
<javac srcdir="${anttasksrc.dir}"
destdir="${classes.dir}"
- source="1.5"
- target="1.5"
+ source="1.7"
+ target="1.7"
includeantruntime="false"
encoding="ISO-8859-1"
deprecation="off"
@@ -334,50 +303,6 @@
</jar>
</target>
- <!--
- Create one giant executable Jar file containing
- Findbugs, textui and gui, detectors, and all required
- libraries.
- -->
- <target name="fulljar" depends="classes,validate,version">
- <property name="fullJarName" value="findbugs-full-${release.number}.jar"/>
- <jar destfile="${jar.dir}/${fullJarName}" manifest="etc/MANIFEST-findbugs-full.MF">
- <fileset dir="${classes.dir}">
- <exclude name="${pkg.base}/tools/**"/>
- <exclude name="${pkg.base}/antTask/**"/>
- <include name="**/*.class"/>
- <include name="**/*.properties"/>
- <include name="**/*.db"/>
- <include name="**/*.xsl"/>
- <include name="${pkg.base}/sourceViewer/**/*.class"/>
- <include name="${pkg.base}/gui/**/*.png"/>
- <include name="${pkg.base}/gui/**/*.html"/>
- <include name="${pkg.base}/gui2/**/*.png"/>
- <include name="${pkg.base}/gui2/**/*.html"/>
- </fileset>
- <fileset dir="${etc.dir}">
- <include name="bugrank.txt"/>
- <include name="findbugs.xml"/>
- <include name="bugrank.txt"/>
- <include name="messages*.xml"/>
- </fileset>
-
- <zipfileset src="${jar.dir}/bcel.jar" excludes="META-INF/**"/>
-
- <zipfileset src="${jar.dir}/asm-3.3.jar" excludes="META-INF/**"/>
- <zipfileset src="${jar.dir}/asm-analysis-3.3.jar" excludes="META-INF/**"/>
- <zipfileset src="${jar.dir}/asm-commons-3.3.jar" excludes="META-INF/**"/>
- <zipfileset src="${jar.dir}/asm-tree-3.3.jar" excludes="META-INF/**"/>
- <zipfileset src="${jar.dir}/asm-util-3.3.jar" excludes="META-INF/**"/>
- <zipfileset src="${jar.dir}/asm-xml-3.3.jar" excludes="META-INF/**"/>
-
- <zipfileset src="${jar.dir}/dom4j-1.6.1.jar" excludes="META-INF/**"/>
- <zipfileset src="${jar.dir}/jaxen-1.1.6.jar" excludes="META-INF/**"/>
- <zipfileset src="${jar.dir}/jsr305.jar" excludes="META-INF/**"/>
- <zipfileset src="${jar.dir}/jFormatString.jar" excludes="META-INF/**"/>
- <zipfileset src="${jar.dir}/commons-lang-2.6.jar" excludes="META-INF/**"/>
- </jar>
- </target>
<!-- Generate front-end scripts. -->
@@ -444,7 +369,7 @@
<target name="applystylesheets" depends="jars,runanttask">
- <property name="findbugs.home" value="." />
+ <property name="findbugs.home" value="${basedir}" />
<java classname="edu.umd.cs.findbugs.PrintingBugReporter"
fork="true"
failonerror="true"
@@ -453,8 +378,8 @@
<classpath>
<pathelement location="${jar.dir}/findbugs.jar"/>
</classpath>
- <jvmarg value="-ea"/>
- <jvmarg value="-Dfindbugs.home=${findbugs.home}"/>
+ <jvmarg value="-ea"/>
+ <jvmarg value="-Dfindbugs.home=${findbugs.home}"/>
<arg value="-html:fancy.xsl"/>
<arg value="${sampleoutput.dir}/bcel.xml"/>
</java>
@@ -466,8 +391,8 @@
<classpath>
<pathelement location="${jar.dir}/findbugs.jar"/>
</classpath>
- <jvmarg value="-ea"/>
- <jvmarg value="-Dfindbugs.home=${findbugs.home}"/>
+ <jvmarg value="-ea"/>
+ <jvmarg value="-Dfindbugs.home=${findbugs.home}"/>
<arg value="-html:default.xsl"/>
<arg value="${sampleoutput.dir}/bcel.xml"/>
</java>
@@ -479,8 +404,8 @@
<classpath>
<pathelement location="${jar.dir}/findbugs.jar"/>
</classpath>
- <jvmarg value="-ea"/>
- <jvmarg value="-Dfindbugs.home=${findbugs.home}"/>
+ <jvmarg value="-ea"/>
+ <jvmarg value="-Dfindbugs.home=${findbugs.home}"/>
<arg value="-html:plain.xsl"/>
<arg value="${sampleoutput.dir}/bcel.xml"/>
</java>
@@ -492,66 +417,35 @@
<classpath>
<pathelement location="${jar.dir}/findbugs.jar"/>
</classpath>
- <jvmarg value="-ea"/>
- <jvmarg value="-Dfindbugs.home=${findbugs.home}"/>
+ <jvmarg value="-ea"/>
+ <jvmarg value="-Dfindbugs.home=${findbugs.home}"/>
<arg value="-html:summary.xsl"/>
<arg value="${sampleoutput.dir}/bcel.xml"/>
</java>
-
-
-
-
</target>
+
<target name="runanttask" depends="anttask,jars">
- <property name="findbugs.home" value="." />
+ <property name="findbugs.home" value="${basedir}" />
<taskdef resource="edu/umd/cs/findbugs/anttask/tasks.properties" classpath="${anttask.jar}"/>
- <findbugs home="."
+ <findbugs home="${basedir}"
output="xml:withMessages"
jvmargs="-ea -Xmx1200m"
projectName="Byte code Engineering Library (BCEL)"
outputFile="${sampleoutput.dir}/bcel.xml"
>
- <class location="${jar.dir}/bcel.jar" />
+ <class location="${jar.dir}/bcel-6.0-SNAPSHOT.jar" />
</findbugs>
- <findbugs home="."
+ <findbugs home="${basedir}"
output="xml:withMessages"
cloud="edu.umd.cs.findbugs.cloud.appengine.findbugs-cloud"
jvmargs="-ea -Xmx1200m"
projectName="Byte code Engineering Library (BCEL)"
outputFile="${sampleoutput.dir}/bcel-cloud-appengine.xml" >
- <class location="${jar.dir}/bcel.jar" />
+ <class location="${jar.dir}/bcel-6.0-SNAPSHOT.jar" />
</findbugs>
-<!--
- <findbugs home="."
- output="xml:withMessages"
- cloud="edu.umd.cs.findbugs.cloud.appengine.findbugs-cloud"
- jvmargs="-ea -Xmx1200m"
- projectName="Byte code Engineering Library (BCEL)"
- outputFile="${sampleoutput.dir}/bcel-cloud.xml" >
- <class location="${jar.dir}/bcel.jar" />
- </findbugs>
--->
-
-<!--
-<findbugs home="${findbugs.home}"
- output="xml"
- jvmargs="-ea -Xmx940m"
- outputFile="${sampleoutput.dir}/bcel-3.xml"
- projectFile="${sampleoutput.dir}/bcel.fbp"
- applySuppression="true"
- />
-
-<convertXmlToText
- home="${findbugs.home}"
- jvmargs="-ea -Xmx940m"
- input="${sampleoutput.dir}/bcel-3.xml"
- output="${sampleoutput.dir}/bcel-3.txt"
- applySuppression="true"
- />
--->
-<setBugDatabaseInfo home="."
+<setBugDatabaseInfo home="${basedir}"
withMessages="true"
name="Set name test"
input="${sampleoutput.dir}/bcel.xml"
@@ -573,15 +467,15 @@
<sourcePath path="src/java:src/gui:src/junit:src/tools:src/antTask"/>
<auxClasspath refid="tools.classpath"/>
<auxClasspath path="lib/ant.jar"/>
- </findbugs>
+ </findbugs>
</target>
<target name="findbugscheck" depends="anttask,junittests,jars">
- <property name="findbugs.home" value="." />
+ <property name="findbugs.home" value="${basedir}" />
<ant dir="${pluginsSrc.dir}/findbugsCommunalCloud" target="install" inheritAll="false" />
<taskdef resource="edu/umd/cs/findbugs/anttask/tasks.properties" classpath="${anttask.jar}"/>
- <findbugs home="."
+ <findbugs home="${basedir}"
output="xml:withMessages"
cloud="edu.umd.cs.findbugs.cloud.appengine.findbugs-cloud"
jvmargs="-ea -Xmx1200m -Dfindbugs.failOnCloudError=true -Dfindbugs.cloud.token=238b6fc80cec17ec"
@@ -595,7 +489,7 @@
<auxClasspath refid="tools.classpath"/>
<auxClasspath path="lib/ant.jar"/>
</findbugs>
- <filterBugs home="."
+ <filterBugs home="${basedir}"
withMessages="true"
notAProblem="false"
jvmargs="-ea -Xmx1200m"
@@ -605,10 +499,10 @@
</target>
<target name="findbugscheck-cloud-fails" depends="anttask,junittests,jars">
- <property name="findbugs.home" value="." />
+ <property name="findbugs.home" value="${basedir}" />
<ant dir="${pluginsSrc.dir}/findbugsCommunalCloud" target="install" inheritAll="false" />
<taskdef resource="edu/umd/cs/findbugs/anttask/tasks.properties" classpath="${anttask.jar}"/>
- <findbugs home="."
+ <findbugs home="${basedir}"
output="xml:withMessages"
cloud="edu.umd.cs.findbugs.cloud.appengine.findbugs-cloud"
jvmargs="-ea -Xmx1200m -Dfindbugs.failOnCloudError=true -Dwebcloud.host=example.com"
@@ -630,9 +524,9 @@
</target>
<target name="findbugsTestCases" depends="anttask,junittests,jars,findbugsTestCases.check" if="findbugsTestCases.exists">
- <property name="findbugs.home" value="." />
+ <property name="findbugs.home" value="${basedir}" />
<taskdef resource="edu/umd/cs/findbugs/anttask/tasks.properties" classpath="${anttask.jar}"/>
- <findbugs home="."
+ <findbugs home="${basedir}"
output="xml"
jvmargs="-ea -Xmx1200m"
projectName="FindBugsTestCases"
@@ -647,7 +541,7 @@
interface with plugins. Note that the generated .xml file is
kept in the ${sampleoutput.dir} for later perusal. -->
<target name="plugincheck" depends="anttask">
- <property name="findbugs.home" value="." />
+ <property name="findbugs.home" value="${basedir}" />
<taskdef resource="edu/umd/cs/findbugs/anttask/tasks.properties" classpath="${anttask.jar}"/>
<!-- download the plugin -->
<echo message="curl ${plugincheck.jar} -o ${plugin.dir}/${plugincheck.jar}"/>
@@ -688,12 +582,13 @@
<target name="test" depends="runjunit,foundFindbugsTestCases" description="Run tests"/>
<target name="runjunit" depends="junittests,jars,compileFindbugsTestCases">
- <echo>Running JUnit test cases for FindBugs...</echo>
+ <echo>Running JUnit test cases for FindBugs, results will be in: ${junit.dir}</echo>
<delete dir="${junit.dir}"/>
<mkdir dir="${junit.dir}"/>
- <junit fork="yes" printsummary="true">
+ <junit fork="yes" printsummary="true" haltonfailure="true" haltonerror="true" dir="${basedir}">
<jvmarg value="-ea"/>
- <jvmarg value="-Dfindbugs.home=."/>
+ <jvmarg value="-Xmx1200m"/>
+ <jvmarg value="-Dfindbugs.home=${basedir}"/>
<jvmarg value="-DfindbugsTestCases.home=${findbugsTestCases.dir}"/>
<formatter type="xml"/> <!-- Hudson reads generated xml -->
<classpath refid="tools.classpath"/>
@@ -738,14 +633,26 @@
<!-- Get version properties. -->
- <target name="version" depends="classes,-get-svn-revision" >
- <echo>${svnrnum}</echo>
+
+ <target name="-get-git-revision">
+ <exec executable="git" spawn="false" outputproperty="gitrnum">
+ <arg value="log"/>
+ <arg value="--pretty=format:%h"/>
+ <arg value="-n"/>
+ <arg value="1"/>
+ </exec>
+ <echo>Got git revision ${gitrnum}</echo>
+ </target>
+
+
+ <target name="version" depends="classes,-get-git-revision" >
+ <echo>${gitrnum}</echo>
<java classpathref="tools.classpath"
output="${version.props.file}"
classname="edu.umd.cs.findbugs.Version"
failonerror="true">
<arg value="-props"/>
- <sysproperty key="svn.revision" value="${svnrnum}"/>
+ <sysproperty key="git.revision" value="${gitrnum}"/>
</java>
<loadproperties srcfile="${version.props.file}"/>
@@ -753,15 +660,6 @@
<loadproperties srcfile="${version.props.file}"/>
</target>
- <target name="-get-svn-revision" if="svnant.home">
- <taskdef resource="org/tigris/subversion/svnant/svnantlib.xml"
- classpathref="svn.classpath"/>
- <svn>
- <status path="." revisionProperty="svnrnum"/>
- </svn>
- <echo>${svnrnum}</echo>
- </target>
-
<target name="checkdocs" depends="clean">
<!-- FIXME: check whether docs are up to date -->
@@ -842,6 +740,21 @@
<param name="bugdesc.title" value="FindBugs Bug Descriptions (Unabridged)"/>
<param name="bugdesc.prologue" value="${doc.html.gen.allBugDescriptions.prologue}"/>
<param name="bugdesc.unabridged" value="true"/>
+ <param name="bugdesc.user.language" value="en"/>
+ </antcall>
+ <antcall target="generatebugdesc">
+ <param name="bugdesc.output" value="${docsrc.dir}/bugDescriptions_ja.html"/>
+ <param name="bugdesc.title" value="FindBugs Bug Descriptions"/>
+ <param name="bugdesc.prologue" value="${doc.html.gen.bugDescriptions.prologue}"/>
+ <param name="bugdesc.unabridged" value="false"/>
+ <param name="bugdesc.user.language" value="ja"/>
+ </antcall>
+ <antcall target="generatebugdesc">
+ <param name="bugdesc.output" value="${docsrc.dir}/bugDescriptions_fr.html"/>
+ <param name="bugdesc.title" value="FindBugs Bug Descriptions"/>
+ <param name="bugdesc.prologue" value="${doc.html.gen.bugDescriptions.prologue}"/>
+ <param name="bugdesc.unabridged" value="false"/>
+ <param name="bugdesc.user.language" value="fr"/>
</antcall>
</target>
@@ -861,7 +774,8 @@
logError="true"
output="${bugdesc.output}">
<jvmarg value="-ea"/>
- <jvmarg value="-Dfindbugs.home=."/>
+ <jvmarg value="-Duser.language=${bugdesc.user.language}"/>
+ <jvmarg value="-Dfindbugs.home=${basedir}"/>
<jvmarg value="-Dfindbugs.bugdesc.unabridged=${bugdesc.unabridged}"/>
<classpath refid="tools.classpath"/>
<arg value="${bugdesc.title}"/>
@@ -894,7 +808,7 @@
<filter token="VERSION_BASE" value="${release.base}" />
<filter token="VERSION" value="${release.number}" />
<filter token="RELEASE_DATE" value="${release.date}" />
- <filter token="FINDBUGS_SVN_REVISION" value="${findbugs.svn.revision}" />
+ <filter token="FINDBUGS_GIT_REVISION" value="${findbugs.git.revision}" />
<filter token="ECLIPSE_UI_VERSION" value="${eclipse.ui.version}" />
<filter token="WEBSITE" value="${findbugs.website}"/>
<filter token="DOWNLOADS_WEBSITE" value="${findbugs.downloads.website}"/>
@@ -1150,13 +1064,13 @@
</patternset>
<zip destfile="${build.dir}/findbugs-${release.number}.zip" compress="true">
- <zipfileset prefix="findbugs-${release.number}" dir=".">
+ <zipfileset prefix="findbugs-${release.number}" dir="${basedir}">
<patternset refid="bindist.miscfile.pats"/>
</zipfileset>
- <zipfileset prefix="findbugs-${release.number}" dir="." filemode="555">
+ <zipfileset prefix="findbugs-${release.number}" dir="${basedir}" filemode="555">
<patternset refid="bindist.unixscript.pats"/>
</zipfileset>
- <zipfileset prefix="findbugs-${release.number}" dir=".">
+ <zipfileset prefix="findbugs-${release.number}" dir="${basedir}">
<patternset refid="bindist.jar.pats"/>
</zipfileset>
<zipfileset prefix="findbugs-${release.number}/doc" dir="${doc.dir}">
@@ -1166,13 +1080,13 @@
</zip>
<tar destfile="${build.dir}/findbugs-${release.number}.tar.gz" compression="gzip">
- <tarfileset prefix="findbugs-${release.number}" dir=".">
+ <tarfileset prefix="findbugs-${release.number}" dir="${basedir}">
<patternset refid="bindist.miscfile.pats"/>
</tarfileset>
- <tarfileset prefix="findbugs-${release.number}" dir="." mode="555">
+ <tarfileset prefix="findbugs-${release.number}" dir="${basedir}" mode="555">
<patternset refid="bindist.unixscript.pats"/>
</tarfileset>
- <tarfileset prefix="findbugs-${release.number}" dir=".">
+ <tarfileset prefix="findbugs-${release.number}" dir="${basedir}">
<patternset refid="bindist.jar.pats"/>
</tarfileset>
<tarfileset prefix="findbugs-${release.number}/doc" dir="${doc.dir}">
@@ -1184,13 +1098,13 @@
<move file="optionalPlugin/noUpdateChecks.jar" todir="plugin"/>
<zip destfile="${build.dir}/findbugs-noUpdateChecks-${release.number}.zip" compress="true">
- <zipfileset prefix="findbugs-${release.number}" dir=".">
+ <zipfileset prefix="findbugs-${release.number}" dir="${basedir}">
<patternset refid="bindist.miscfile.pats"/>
</zipfileset>
- <zipfileset prefix="findbugs-${release.number}" dir="." filemode="555">
+ <zipfileset prefix="findbugs-${release.number}" dir="${basedir}" filemode="555">
<patternset refid="bindist.unixscript.pats"/>
</zipfileset>
- <zipfileset prefix="findbugs-${release.number}" dir=".">
+ <zipfileset prefix="findbugs-${release.number}" dir="${basedir}">
<patternset refid="bindist2.jar.pats"/>
</zipfileset>
<zipfileset prefix="findbugs-${release.number}/doc" dir="${doc.dir}">
@@ -1200,13 +1114,13 @@
</zip>
<tar destfile="${build.dir}/findbugs-noUpdateChecks-${release.number}.tar.gz" compression="gzip">
- <tarfileset prefix="findbugs-${release.number}" dir=".">
+ <tarfileset prefix="findbugs-${release.number}" dir="${basedir}">
<patternset refid="bindist.miscfile.pats"/>
</tarfileset>
- <tarfileset prefix="findbugs-${release.number}" dir="." mode="555">
+ <tarfileset prefix="findbugs-${release.number}" dir="${basedir}" mode="555">
<patternset refid="bindist.unixscript.pats"/>
</tarfileset>
- <tarfileset prefix="findbugs-${release.number}" dir=".">
+ <tarfileset prefix="findbugs-${release.number}" dir="${basedir}">
<patternset refid="bindist2.jar.pats"/>
</tarfileset>
<tarfileset prefix="findbugs-${release.number}/doc" dir="${doc.dir}">
@@ -1221,28 +1135,16 @@
<!-- Build source distribution. -->
<target name="srcdist" description="Source distribution" unless="doNotExportSrc" depends="version">
- <echo>
- ${svnant.home}
- </echo>
+ <delete dir="${build.dir}/src"/>
<mkdir dir="${build.dir}/src"/>
- <delete dir="${build.dir}/src/findbugs-${release.number}"/>
- <typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="svn.classpath"/>
-
- <svnSetting username="guest" password="" id="svn.settings" />
- <svn refid="svn.settings" >
- <!-- Use 'export' rather than 'checkout' to exclude the .svn stuff -->
- <export srcUrl="http://findbugs.googlecode.com/svn/trunk/findbugs"
- revision="HEAD"
- destPath="${build.dir}/src/findbugs-${release.number}"/>
- </svn>
-
- <zip destfile="${build.dir}/findbugs-${release.number}-source.zip" compress="true">
- <zipfileset dir="${build.dir}/src" includes="findbugs-${release.number}/**"/>
- <zipfileset prefix="findbugs-${release.number}/doc" dir="${doc.dir}">
- <patternset refid="doc.src.pats"/>
- <patternset refid="doc.img.pats"/>
- </zipfileset>
- </zip>
+ <exec executable="git" spawn="true">
+ <arg value="archive"/>
+ <arg value="-o"/>
+ <arg value="${build.dir}/src/findbugs-${release.number}-source.zip"/>
+ <arg value="--prefix"/>
+ <arg value="findbugs-${release.number}/"/>
+ <arg value="HEAD"/>
+ </exec>
</target>
<!-- Delete generated files. -->
@@ -1355,7 +1257,7 @@
<fileset dir="${toolsrc.dir}"/>
<fileset dir="${anttasksrc.dir}"/>
<fileset dir="${junitsrc.dir}"/>
- <fileset dir=".">
+ <fileset dir="${basedir}">
<include name="LICENSE*.txt"/>
</fileset>
</jar>
diff --git a/design/architecture/mkdep.pl b/design/architecture/mkdep.pl
old mode 100644
new mode 100755
diff --git a/etc/MANIFEST-findbugs-annotations.MF b/etc/MANIFEST-findbugs-annotations.MF
index 4213b2b..18c6120 100644
--- a/etc/MANIFEST-findbugs-annotations.MF
+++ b/etc/MANIFEST-findbugs-annotations.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: FindbugsAnnotations
Bundle-SymbolicName: findbugsAnnotations
-Bundle-Version: 2.0.3
+Bundle-Version: 3.0.1
Export-Package: edu.umd.cs.findbugs.annotations,
javax.annotation,
javax.annotation.concurrent,
diff --git a/etc/MANIFEST-findbugs-internal-annotations.MF b/etc/MANIFEST-findbugs-internal-annotations.MF
index 5f9b9a3..c8e6f40 100644
--- a/etc/MANIFEST-findbugs-internal-annotations.MF
+++ b/etc/MANIFEST-findbugs-internal-annotations.MF
@@ -2,6 +2,6 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: FindbugsInternalAnnotations
Bundle-SymbolicName: findbugsInternalAnnotations
-Bundle-Version: 2.0.3
+Bundle-Version: 3.0.1
Export-Package: edu.umd.cs.findbugs.annotations
Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/etc/MANIFEST-findbugs.MF b/etc/MANIFEST-findbugs.MF
index 9ac9bfc..b29d6f8 100644
--- a/etc/MANIFEST-findbugs.MF
+++ b/etc/MANIFEST-findbugs.MF
@@ -1,3 +1,3 @@
Manifest-Version: 1.0
Main-Class: edu.umd.cs.findbugs.LaunchAppropriateUI
-Class-Path: bcel.jar dom4j-1.6.1.jar jaxen-1.1.6.jar asm-3.3.jar asm-tree-3.3.jar asm-commons-3.3.jar jsr305.jar jFormatString.jar commons-lang-2.6.jar
+Class-Path: bcel-6.0-SNAPSHOT.jar dom4j-1.6.1.jar jaxen-1.1.6.jar asm-debug-all-5.0.2.jar jsr305.jar jFormatString.jar commons-lang-2.6.jar
diff --git a/etc/MANIFEST-findbugsGUI.MF b/etc/MANIFEST-findbugsGUI.MF
index 0837342..cccce16 100644
--- a/etc/MANIFEST-findbugsGUI.MF
+++ b/etc/MANIFEST-findbugsGUI.MF
@@ -1,3 +1,3 @@
Manifest-Version: 1.0
Main-Class: edu.umd.cs.findbugs.LaunchAppropriateUI
-Class-Path: bcel.jar dom4j-1.6.1.jar jaxen-1.1.6.jar asm-3.3.jar asm-tree-3.3.jar asm-commons-3.3.jar jsr305.jar jFormatString.jar commons-lang-2.6.jar plastic.jar
+Class-Path: bcel-6.0-SNAPSHOT.jar dom4j-1.6.1.jar jaxen-1.1.6.jar asm-debug-all-5.0.2.jar jsr305.jar jFormatString.jar commons-lang-2.6.jar plastic.jar
diff --git a/etc/bugcollection.xsd b/etc/bugcollection.xsd
index d46c452..b6d665b 100644
--- a/etc/bugcollection.xsd
+++ b/etc/bugcollection.xsd
@@ -1,471 +1,476 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
- xmlns:xs="http://www.w3.org/2001/XMLSchema">
- <xs:annotation>
- <xs:documentation>This scheme describes the XML format used by FindBugs to store the results
- of analysis.</xs:documentation>
- </xs:annotation>
-
- <xs:element name="FindBugsFilter">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="Matcher" minOccurs="1" maxOccurs="unbounded"/>
- </xs:sequence>
- </xs:complexType>
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:annotation>
+ <xs:documentation>This scheme describes the XML format used by FindBugs to store the results
+ of analysis.</xs:documentation>
+ </xs:annotation>
+
+ <xs:element name="FindBugsFilter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="Matcher" minOccurs="1" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
</xs:element>
-
-
- <xs:element name="BugCollection">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="Project">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="Jar" type="xs:string" minOccurs="0"
- maxOccurs="unbounded"/>
- <xs:element name="AuxClasspathEntry" type="xs:string" minOccurs="0"
- maxOccurs="unbounded"/>
- <xs:element name="SrcDir" type="xs:string" minOccurs="0"
- maxOccurs="unbounded"/>
- <xs:element name="WrkDir" type="xs:string" minOccurs="0"
- maxOccurs="1"/>
- <xs:element name="Plugin" minOccurs="0"
- maxOccurs="unbounded"> <xs:complexType>
- <xs:attribute name="id" type="xs:string"/>
- <xs:attribute name="enabled" type="xs:string"/>
- </xs:complexType></xs:element>
- <xs:element name="SuppressionFilter" minOccurs="0"
- maxOccurs="1"> <xs:complexType>
- <xs:sequence>
- <xs:element ref="Matcher" minOccurs="1" maxOccurs="unbounded"/>
- </xs:sequence>
- </xs:complexType></xs:element>
- <xs:element name="Cloud" minOccurs="0" maxOccurs="1">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="Property" minOccurs="0"
- maxOccurs="unbounded">
- <xs:complexType>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute name="key" type="xs:string"/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="id" type="xs:string"/>
- <xs:attribute name="online" type="xs:boolean" use="optional"/>
- <xs:attribute name="synced" type="xs:boolean" use="optional"/>
- <xs:attribute name="detailsUrl" type="xs:string" use="optional"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="filename" type="xs:string" use="optional"/>
- <xs:attribute name="projectName" type="xs:string" use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="BugInstance" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:annotation>
- <xs:documentation>Each BugInstance can have a sequence of
- annotations</xs:documentation>
- </xs:annotation>
- <xs:sequence>
- <xs:element name="ShortMessage" type="xs:string" minOccurs="0"/>
- <xs:element name="LongMessage" type="xs:string" minOccurs="0"/>
-
- <xs:choice maxOccurs="unbounded">
-
- <xs:element name="Class">
- <xs:annotation>
- <xs:documentation>This annotation describes a
- class</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="SourceLine"/>
- <xs:element ref="Message" minOccurs="0"/>
- </xs:sequence>
- <xs:attribute name="classname" type="xs:string"
- use="required"/>
- <xs:attribute name="role" type="xs:string" use="optional"/>
- <xs:attribute name="primary" type="xs:boolean"
- use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="Type">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="SourceLine" minOccurs="0"/>
- <xs:element ref="Message" minOccurs="0"/>
- </xs:sequence>
- <xs:attribute name="descriptor" type="xs:string"
- use="required"/>
- <xs:attribute name="role" type="xs:string" use="optional"/>
- <xs:attribute name="typeParameters" type="xs:string"
- use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="Method">
- <xs:annotation>
- <xs:documentation>This annotation describes a
- method</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence minOccurs="0">
- <xs:element ref="SourceLine"/>
- <xs:element ref="Message" minOccurs="0"/>
- </xs:sequence>
- <xs:attribute name="classname" type="xs:string"
- use="required"/>
- <xs:attribute name="name" type="xs:string" use="required"/>
- <xs:attribute name="signature" type="xs:string"
- use="required"/>
- <xs:attribute name="isStatic" type="xs:boolean"
- use="required"/>
- <xs:attribute name="role" type="xs:string" use="optional"/>
- <xs:attribute name="primary" type="xs:boolean"
- use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element ref="SourceLine"/>
- <xs:element name="LocalVariable">
- <xs:annotation>
- <xs:documentation>This annotation describes a local
- variable</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="Message" minOccurs="0"/>
- </xs:sequence>
- <xs:attribute name="name" type="xs:string" use="required"/>
- <xs:attribute name="register" type="xs:short" use="required"/>
- <xs:attribute name="pc" type="xs:int" use="required"/>
- <xs:attribute name="role" type="xs:string" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="Field">
- <xs:annotation>
- <xs:documentation>This annotation describes a
- field</xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="SourceLine"/>
- <xs:element ref="Message" minOccurs="0"/>
- </xs:sequence>
- <xs:attribute name="classname" type="xs:string"
- use="required"/>
- <xs:attribute name="name" type="xs:string" use="required"/>
- <xs:attribute name="signature" type="xs:string"
- use="required"/>
- <xs:attribute name="sourceSignature" type="xs:string"
- use="optional"/>
- <xs:attribute name="isStatic" type="xs:boolean"
- use="required"/>
- <xs:attribute name="role" type="xs:string" use="optional"/>
- <xs:attribute name="primary" type="xs:boolean"
- use="optional"/>
-
- </xs:complexType>
- </xs:element>
- <xs:element name="Int">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="Message" minOccurs="0"/>
- </xs:sequence>
- <xs:attribute name="value" type="xs:long" use="required"/>
- <xs:attribute name="role" type="xs:string" use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="String">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="Message" minOccurs="0"/>
- </xs:sequence>
- <xs:attribute name="value" type="xs:string" use="required"/>
- <xs:attribute name="role" type="xs:string" use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="Property">
- <xs:complexType>
- <xs:attribute name="name" type="xs:string" use="required"/>
- <xs:attribute name="value" type="xs:string" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="UserAnnotation" minOccurs="0">
- <xs:complexType>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute name="designation" type="designationType"
- use="optional"/>
- <xs:attribute name="user" type="xs:string"
- use="optional"/>
- <xs:attribute name="needsSync" type="xs:boolean"
+
+
+ <xs:element name="BugCollection">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Project">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Jar" type="xs:string" minOccurs="0"
+ maxOccurs="unbounded"/>
+ <xs:element name="AuxClasspathEntry" type="xs:string" minOccurs="0"
+ maxOccurs="unbounded"/>
+ <xs:element name="SrcDir" type="xs:string" minOccurs="0"
+ maxOccurs="unbounded"/>
+ <xs:element name="WrkDir" type="xs:string" minOccurs="0"
+ maxOccurs="1"/>
+ <xs:element name="Plugin" minOccurs="0"
+ maxOccurs="unbounded"> <xs:complexType>
+ <xs:attribute name="id" type="xs:string"/>
+ <xs:attribute name="enabled" type="xs:string"/>
+ </xs:complexType></xs:element>
+ <xs:element name="SuppressionFilter" minOccurs="0"
+ maxOccurs="1"> <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="Matcher" minOccurs="1" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType></xs:element>
+ <xs:element name="Cloud" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Property" minOccurs="0"
+ maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="key" type="xs:string"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:string"/>
+ <xs:attribute name="online" type="xs:boolean" use="optional"/>
+ <xs:attribute name="synced" type="xs:boolean" use="optional"/>
+ <xs:attribute name="detailsUrl" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="filename" type="xs:string" use="optional"/>
+ <xs:attribute name="projectName" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BugInstance" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:documentation>Each BugInstance can have a sequence of
+ annotations</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="ShortMessage" type="xs:string" minOccurs="0"/>
+ <xs:element name="LongMessage" type="xs:string" minOccurs="0"/>
+
+ <xs:choice maxOccurs="unbounded">
+
+ <xs:element name="Class">
+ <xs:annotation>
+ <xs:documentation>This annotation describes a
+ class</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="SourceLine"/>
+ <xs:element ref="Message" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="classname" type="xs:string"
+ use="required"/>
+ <xs:attribute name="role" type="xs:string" use="optional"/>
+ <xs:attribute name="primary" type="xs:boolean"
+ use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Type">
+ <xs:annotation>
+ <xs:documentation>This annotation describes a
+ type</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="SourceLine" minOccurs="0"/>
+ <xs:element ref="Message" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="descriptor" type="xs:string"
+ use="required"/>
+ <xs:attribute name="role" type="xs:string" use="optional"/>
+ <xs:attribute name="typeParameters" type="xs:string"
+ use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Method">
+ <xs:annotation>
+ <xs:documentation>This annotation describes a
+ method</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence minOccurs="0">
+ <xs:element ref="SourceLine"/>
+ <xs:element ref="Message" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="classname" type="xs:string"
+ use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="signature" type="xs:string"
+ use="required"/>
+ <xs:attribute name="isStatic" type="xs:boolean"
+ use="required"/>
+ <xs:attribute name="role" type="xs:string" use="optional"/>
+ <xs:attribute name="primary" type="xs:boolean"
+ use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element ref="SourceLine"/>
+ <xs:element name="LocalVariable">
+ <xs:annotation>
+ <xs:documentation>This annotation describes a local
+ variable</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="Message" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="register" type="xs:short" use="required"/>
+ <xs:attribute name="pc" type="xs:int" use="required"/>
+ <xs:attribute name="role" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Field">
+ <xs:annotation>
+ <xs:documentation>This annotation describes a
+ field</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="SourceLine"/>
+ <xs:element ref="Message" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="classname" type="xs:string"
+ use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="signature" type="xs:string"
+ use="required"/>
+ <xs:attribute name="sourceSignature" type="xs:string"
+ use="optional"/>
+ <xs:attribute name="isStatic" type="xs:boolean"
+ use="required"/>
+ <xs:attribute name="role" type="xs:string" use="optional"/>
+ <xs:attribute name="primary" type="xs:boolean"
+ use="optional"/>
+
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Int">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="Message" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="value" type="xs:long" use="required"/>
+ <xs:attribute name="role" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="String">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="Message" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ <xs:attribute name="role" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Property">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="UserAnnotation" minOccurs="0">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="designation" type="designationType"
+ use="optional"/>
+ <xs:attribute name="user" type="xs:string"
+ use="optional"/>
+ <xs:attribute name="needsSync" type="xs:boolean"
use="optional"/>
<xs:attribute name="timestamp" type="xs:unsignedLong"
- use="optional"/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- </xs:choice>
-
- </xs:sequence>
- <xs:attribute name="type" type="xs:string" use="required"/>
- <xs:attribute name="priority" type="xs:unsignedByte" use="required"/>
- <xs:attribute name="abbrev" type="xs:string" use="required"/>
- <xs:attribute name="category" type="xs:string" use="required"/>
- <xs:attribute name="uid" type="xs:unsignedLong" use="optional"/>
-
- <xs:attribute name="reviews" type="xs:unsignedInt" use="optional"/>
- <xs:attribute name="firstSeen" type="xs:string" use="optional"/>
- <xs:attribute name="consensus" type="xs:string" use="optional"/>
- <xs:attribute name="isInCloud" type="xs:boolean" use="optional"/>
-
- <!-- The following only appear with multi-version analysis files -->
- <xs:attribute name="last" type="xs:unsignedInt" use="optional"/>
+ use="optional"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+
+ </xs:sequence>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="priority" type="xs:unsignedByte" use="required"/>
+ <xs:attribute name="abbrev" type="xs:string" use="required"/>
+ <xs:attribute name="category" type="xs:string" use="required"/>
+ <xs:attribute name="uid" type="xs:unsignedLong" use="optional"/>
+
+ <xs:attribute name="reviews" type="xs:unsignedInt" use="optional"/>
+ <xs:attribute name="firstSeen" type="xs:string" use="optional"/>
+ <xs:attribute name="consensus" type="xs:string" use="optional"/>
+ <xs:attribute name="isInCloud" type="xs:boolean" use="optional"/>
+
+ <!-- The following only appear with multi-version analysis files -->
+ <xs:attribute name="last" type="xs:unsignedInt" use="optional"/>
<xs:attribute name="removedByChange" type="xs:boolean" use="optional"/>
<xs:attribute name="first" type="xs:unsignedInt" use="optional"/>
<xs:attribute name="introducedByChange" type="xs:boolean" use="optional"/>
-
-
- <!-- The following only appear withMessages -->
- <xs:attribute name="shouldFix" type="xs:boolean" use="optional"/>
- <xs:attribute name="ageInDays" type="xs:unsignedInt" use="optional"/>
+
+
+ <!-- The following only appear withMessages -->
+ <xs:attribute name="shouldFix" type="xs:boolean" use="optional"/>
+ <xs:attribute name="ageInDays" type="xs:unsignedInt" use="optional"/>
<xs:attribute name="notAProblem" type="xs:boolean" use="optional"/>
<xs:attribute name="instanceHash" type="xs:string" use="optional"/>
<xs:attribute name="instanceOccurrenceNum" type="xs:unsignedInt"
use="optional"/>
<xs:attribute name="instanceOccurrenceMax" type="xs:unsignedInt"
use="optional"/>
-
- <xs:attribute name="rank" type="xs:unsignedInt" use="optional"/>
- <xs:attribute name="cweid" type="xs:unsignedInt" use="optional"/>
-
-
- </xs:complexType>
- </xs:element>
- <xs:element name="BugCategory" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="Description" type="xs:string"/>
- <xs:element name="Abbreviation" type="xs:NMTOKEN" minOccurs="0"/>
- <xs:element name="Details" type="xs:string" minOccurs="0"/>
- </xs:sequence>
- <xs:attribute name="category" type="xs:string" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="BugPattern" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="ShortDescription" type="xs:string"/>
- <xs:element name="Details" type="xs:string"/>
- </xs:sequence>
- <xs:attribute name="type" type="xs:string" use="required"/>
- <xs:attribute name="abbrev" type="xs:string" use="required"/>
- <xs:attribute name="category" type="xs:string" use="required"/>
- <xs:attribute name="cweid" type="xs:positiveInteger" use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="BugCode" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="Description" type="xs:string"/>
- </xs:sequence>
- <xs:attribute name="abbrev" type="xs:string" use="required"/>
- <xs:attribute name="cweid" type="xs:positiveInteger" use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="Errors">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="MissingClass" type="xs:string" minOccurs="0"
- maxOccurs="unbounded"/>
- </xs:sequence>
- <xs:attribute name="errors" type="xs:unsignedInt" use="optional"/>
- <xs:attribute name="missingClasses" type="xs:unsignedInt" use="optional"/>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="FindBugsSummary">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="FileStats" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:attribute name="path" type="xs:string" use="required"/>
- <xs:attribute name="bugCount" type="xs:unsignedInt"
- use="required"/>
- <xs:attribute name="size" type="xs:unsignedInt" use="optional"/>
- <xs:attribute name="bugHash" type="xs:string" use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="PackageStats" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="ClassStats" minOccurs="0"
- maxOccurs="unbounded">
- <xs:complexType>
- <xs:attribute name="class" type="xs:string"
- use="required"/>
- <xs:attribute name="sourceFile" type="xs:string"
- use="optional"/>
- <xs:attribute name="interface" type="xs:boolean"
- use="required"/>
- <xs:attribute name="size" type="xs:unsignedLong"
- use="required"/>
- <xs:attribute name="bugs" type="xs:unsignedInt"
- use="required"/>
- <xs:attribute name="priority_1"
- type="xs:unsignedInt" use="optional"/>
- <xs:attribute name="priority_2"
- type="xs:unsignedInt" use="optional"/>
- <xs:attribute name="priority_3"
- type="xs:unsignedInt" use="optional"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="package" type="xs:string" use="required"/>
- <xs:attribute name="total_bugs" type="xs:unsignedInt"
- use="required"/>
- <xs:attribute name="total_types" type="xs:unsignedInt"
- use="required"/>
- <xs:attribute name="total_size" type="xs:unsignedLong"
- use="required"/>
- <xs:attribute name="priority_1" type="xs:unsignedInt"
- use="optional"/>
- <xs:attribute name="priority_2" type="xs:unsignedInt"
- use="optional"/>
- <xs:attribute name="priority_3" type="xs:unsignedInt"
- use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="FindBugsProfile" minOccurs="0" maxOccurs="1">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="ClassProfile" minOccurs="0"
- maxOccurs="unbounded">
- <xs:complexType>
- <xs:attribute name="name" type="xs:string"
- use="required"/>
- <xs:attribute name="totalMilliseconds"
- type="xs:unsignedInt" use="required"/>
- <xs:attribute name="invocations"
- type="xs:unsignedInt" use="required"/>
- <xs:attribute name="avgMicrosecondsPerInvocation"
- type="xs:unsignedInt" use="required"/>
- <xs:attribute name="maxMicrosecondsPerInvocation"
- type="xs:unsignedInt" use="optional"/>
- <xs:attribute name="maxContext" type="xs:string"
- use="optional"/>
- <xs:attribute
- name="standardDeviationMircosecondsPerInvocation"
- type="xs:unsignedInt" use="optional"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="timestamp" type="xs:string" use="required"/>
- <xs:attribute name="total_classes" type="xs:unsignedInt" use="required"/>
- <xs:attribute name="referenced_classes" type="xs:unsignedInt" use="optional"/>
- <xs:attribute name="total_bugs" type="xs:unsignedInt" use="required"/>
- <xs:attribute name="total_size" type="xs:unsignedInt" use="required"/>
- <xs:attribute name="num_packages" type="xs:unsignedInt" use="required"/>
- <xs:attribute name="vm_version" type="xs:string" use="optional"/>
- <xs:attribute name="cpu_seconds" type="xs:float" use="optional"/>
- <!-- could move to xs:duration -->
- <xs:attribute name="clock_seconds" type="xs:float" use="optional"/>
- <xs:attribute name="peak_mbytes" type="xs:float" use="optional"/>
- <xs:attribute name="alloc_mbytes" type="xs:float" use="optional"/>
- <xs:attribute name="gc_seconds" type="xs:float" use="optional"/>
- <xs:attribute name="priority_1" type="xs:unsignedInt" use="optional"/>
- <xs:attribute name="priority_2" type="xs:unsignedInt" use="optional"/>
- <xs:attribute name="priority_3" type="xs:unsignedInt" use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="SummaryHTML" type="xs:string" minOccurs="0"/>
- <xs:element name="ClassFeatures">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="ClassFeatureSet" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="Feature" minOccurs="0"
- maxOccurs="unbounded">
- <xs:complexType>
- <xs:attribute name="value" type="xs:string"
- use="required"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="class" type="xs:string" use="required"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="History">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="AppVersion" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:attribute name="sequence" type="xs:unsignedInt"
- use="required"/>
- <xs:attribute name="timestamp" type="xs:unsignedLong"
- use="required"/>
- <xs:attribute name="release" type="xs:string" use="required"/>
- <xs:attribute name="codeSize" type="xs:unsignedInt"
- use="required"/>
- <xs:attribute name="numClasses" type="xs:unsignedInt"
- use="required"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="version" type="xs:string" use="required"/>
- <xs:attribute name="sequence" type="xs:unsignedInt" use="required"/>
- <xs:attribute name="timestamp" type="xs:unsignedLong" use="required"/>
- <xs:attribute name="analysisTimestamp" type="xs:unsignedLong" use="required"/>
- <xs:attribute name="release" type="xs:string" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="SourceLine">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="Message" minOccurs="0"/>
- </xs:sequence>
- <xs:attribute name="classname" type="xs:string" use="required"/>
- <xs:attribute name="start" type="xs:int" use="optional"/>
- <xs:attribute name="end" type="xs:int" use="optional"/>
- <xs:attribute name="startBytecode" type="xs:int" use="optional"/>
- <xs:attribute name="endBytecode" type="xs:int" use="optional"/>
- <xs:attribute name="sourcefile" type="xs:string" use="optional"/>
- <xs:attribute name="sourcepath" type="xs:string" use="optional"/>
- <xs:attribute name="relSourcepath" type="xs:string" use="optional"/>
- <xs:attribute name="synthetic" type="xs:boolean" use="optional"/>
- <xs:attribute name="role" type="xs:string" use="optional"/>
- <xs:attribute name="primary" type="xs:boolean" use="optional"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="Message" type="xs:string"/>
-
- <xs:simpleType name="designationType">
- <xs:restriction base="xs:token">
- <xs:enumeration value="UNCLASSIFIED"/>
- <xs:enumeration value="BAD_ANALYSIS"/>
- <xs:enumeration value="NOT_A_BUG"/>
- <xs:enumeration value="MOSTLY_HARMLESS"/>
- <xs:enumeration value="SHOULD_FIX"/>
- <xs:enumeration value="MUST_FIX"/>
- <xs:enumeration value="I_WILL_FIX"/>
- <xs:enumeration value="OBSOLETE_CODE"/>
- </xs:restriction>
- </xs:simpleType>
+
+ <xs:attribute name="rank" type="xs:unsignedInt" use="optional"/>
+ <xs:attribute name="cweid" type="xs:unsignedInt" use="optional"/>
+
+
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BugCategory" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Description" type="xs:string"/>
+ <xs:element name="Abbreviation" type="xs:NMTOKEN" minOccurs="0"/>
+ <xs:element name="Details" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="category" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BugPattern" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ShortDescription" type="xs:string"/>
+ <xs:element name="Details" type="xs:string"/>
+ </xs:sequence>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="abbrev" type="xs:string" use="required"/>
+ <xs:attribute name="category" type="xs:string" use="required"/>
+ <xs:attribute name="cweid" type="xs:positiveInteger" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BugCode" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Description" type="xs:string"/>
+ </xs:sequence>
+ <xs:attribute name="abbrev" type="xs:string" use="required"/>
+ <xs:attribute name="cweid" type="xs:positiveInteger" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Errors">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="MissingClass" type="xs:string" minOccurs="0"
+ maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="errors" type="xs:unsignedInt" use="optional"/>
+ <xs:attribute name="missingClasses" type="xs:unsignedInt" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="FindBugsSummary">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="FileStats" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="path" type="xs:string" use="required"/>
+ <xs:attribute name="bugCount" type="xs:unsignedInt"
+ use="required"/>
+ <xs:attribute name="size" type="xs:unsignedInt" use="optional"/>
+ <xs:attribute name="bugHash" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PackageStats" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ClassStats" minOccurs="0"
+ maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="class" type="xs:string"
+ use="required"/>
+ <xs:attribute name="sourceFile" type="xs:string"
+ use="optional"/>
+ <xs:attribute name="interface" type="xs:boolean"
+ use="required"/>
+ <xs:attribute name="size" type="xs:unsignedLong"
+ use="required"/>
+ <xs:attribute name="bugs" type="xs:unsignedInt"
+ use="required"/>
+ <xs:attribute name="priority_1"
+ type="xs:unsignedInt" use="optional"/>
+ <xs:attribute name="priority_2"
+ type="xs:unsignedInt" use="optional"/>
+ <xs:attribute name="priority_3"
+ type="xs:unsignedInt" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="package" type="xs:string" use="required"/>
+ <xs:attribute name="total_bugs" type="xs:unsignedInt"
+ use="required"/>
+ <xs:attribute name="total_types" type="xs:unsignedInt"
+ use="required"/>
+ <xs:attribute name="total_size" type="xs:unsignedLong"
+ use="required"/>
+ <xs:attribute name="priority_1" type="xs:unsignedInt"
+ use="optional"/>
+ <xs:attribute name="priority_2" type="xs:unsignedInt"
+ use="optional"/>
+ <xs:attribute name="priority_3" type="xs:unsignedInt"
+ use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="FindBugsProfile" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ClassProfile" minOccurs="0"
+ maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string"
+ use="required"/>
+ <xs:attribute name="totalMilliseconds"
+ type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="invocations"
+ type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="avgMicrosecondsPerInvocation"
+ type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="maxMicrosecondsPerInvocation"
+ type="xs:unsignedInt" use="optional"/>
+ <xs:attribute name="maxContext" type="xs:string"
+ use="optional"/>
+ <xs:attribute
+ name="standardDeviationMircosecondsPerInvocation"
+ type="xs:unsignedInt" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="timestamp" type="xs:string" use="required"/>
+ <xs:attribute name="total_classes" type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="referenced_classes" type="xs:unsignedInt" use="optional"/>
+ <xs:attribute name="total_bugs" type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="total_size" type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="num_packages" type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="java_version" type="xs:string" use="optional"/>
+ <xs:attribute name="vm_version" type="xs:string" use="optional"/>
+ <xs:attribute name="cpu_seconds" type="xs:float" use="optional"/>
+ <!-- could move to xs:duration -->
+ <xs:attribute name="clock_seconds" type="xs:float" use="optional"/>
+ <xs:attribute name="peak_mbytes" type="xs:float" use="optional"/>
+ <xs:attribute name="alloc_mbytes" type="xs:float" use="optional"/>
+ <xs:attribute name="gc_seconds" type="xs:float" use="optional"/>
+ <xs:attribute name="priority_1" type="xs:unsignedInt" use="optional"/>
+ <xs:attribute name="priority_2" type="xs:unsignedInt" use="optional"/>
+ <xs:attribute name="priority_3" type="xs:unsignedInt" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="SummaryHTML" type="xs:string" minOccurs="0"/>
+ <xs:element name="ClassFeatures">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ClassFeatureSet" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Feature" minOccurs="0"
+ maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="value" type="xs:string"
+ use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="class" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="History">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="AppVersion" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="sequence" type="xs:unsignedInt"
+ use="required"/>
+ <xs:attribute name="timestamp" type="xs:unsignedLong"
+ use="required"/>
+ <xs:attribute name="release" type="xs:string" use="required"/>
+ <xs:attribute name="codeSize" type="xs:unsignedInt"
+ use="required"/>
+ <xs:attribute name="numClasses" type="xs:unsignedInt"
+ use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="version" type="xs:string" use="required"/>
+ <xs:attribute name="sequence" type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="timestamp" type="xs:unsignedLong" use="required"/>
+ <xs:attribute name="analysisTimestamp" type="xs:unsignedLong" use="required"/>
+ <xs:attribute name="release" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="SourceLine">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="Message" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="classname" type="xs:string" use="required"/>
+ <xs:attribute name="start" type="xs:int" use="optional"/>
+ <xs:attribute name="end" type="xs:int" use="optional"/>
+ <xs:attribute name="startBytecode" type="xs:int" use="optional"/>
+ <xs:attribute name="endBytecode" type="xs:int" use="optional"/>
+ <xs:attribute name="sourcefile" type="xs:string" use="optional"/>
+ <xs:attribute name="sourcepath" type="xs:string" use="optional"/>
+ <xs:attribute name="relSourcepath" type="xs:string" use="optional"/>
+ <xs:attribute name="synthetic" type="xs:boolean" use="optional"/>
+ <xs:attribute name="role" type="xs:string" use="optional"/>
+ <xs:attribute name="primary" type="xs:boolean" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Message" type="xs:string"/>
+
+ <xs:simpleType name="designationType">
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="UNCLASSIFIED"/>
+ <xs:enumeration value="BAD_ANALYSIS"/>
+ <xs:enumeration value="NOT_A_BUG"/>
+ <xs:enumeration value="MOSTLY_HARMLESS"/>
+ <xs:enumeration value="SHOULD_FIX"/>
+ <xs:enumeration value="MUST_FIX"/>
+ <xs:enumeration value="I_WILL_FIX"/>
+ <xs:enumeration value="OBSOLETE_CODE"/>
+ </xs:restriction>
+ </xs:simpleType>
@@ -473,6 +478,7 @@
<xs:element name="Bug" substitutionGroup="Matcher" type="BugMatcherType" />
<xs:element name="Class" substitutionGroup="Matcher" type="ClassMatcherType" />
+<xs:element name="Type" substitutionGroup="Matcher" type="TypeMatcherType" />
<xs:element name="FirstVersion" substitutionGroup="Matcher" type="FirstVersionMatcherType" />
<xs:element name="LastVersion" substitutionGroup="Matcher" type="LastVersionMatcherType" />
<xs:element name="Designation" substitutionGroup="Matcher" type="DesignationMatcherType" />
@@ -491,157 +497,169 @@
- <xs:complexType name="MatcherType" abstract="true" ></xs:complexType>
-
- <xs:complexType name="BugMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="code" type="xs:string" use="optional" />
- <xs:attribute name="pattern" type="xs:string" use="optional" />
- <xs:attribute name="category" type="xs:string" use="optional" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="ClassMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="name" type="xs:string" use="required" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="FirstVersionMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="value" type="xs:long" use="required" />
- <xs:attribute name="relOp" type="xs:string" use="required" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="LastVersionMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="value" type="xs:long" use="required" />
- <xs:attribute name="relOp" type="xs:string" use="required" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="DesignationMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="designation" type="xs:string" use="required" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="BugCodeMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="name" type="xs:string" use="required" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="LocalMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="name" type="xs:string" use="required" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="BugPatternMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="name" type="xs:string" use="required" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="PriorityMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="value" type="xs:int" use="required" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="RankMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="value" type="xs:int" use="required" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="PackageMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="name" type="xs:string" use="required" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="MethodMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="name" type="xs:string" use="optional" />
- <xs:attribute name="params" type="xs:string" use="optional" />
- <xs:attribute name="returns" type="xs:string" use="optional" />
- <xs:attribute name="role" type="xs:string" use="optional" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="FieldMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:attribute name="name" type="xs:string" use="optional" />
- <xs:attribute name="type" type="xs:string" use="optional" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="OrMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:sequence>
- <xs:element ref="Matcher" minOccurs="1" maxOccurs="unbounded"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="AndMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:sequence>
- <xs:element ref="Matcher" minOccurs="1" maxOccurs="unbounded" />
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="MatchMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:sequence>
- <xs:element ref="Matcher" minOccurs="1" maxOccurs="unbounded" />
- </xs:sequence>
- <xs:attribute name="classregex" type="xs:string" use="optional" />
- <xs:attribute name="class" type="xs:string" use="optional" />
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
- <xs:complexType name="NotMatcherType">
- <xs:complexContent>
- <xs:extension base="MatcherType">
- <xs:sequence>
- <xs:element ref="Matcher" minOccurs="1" maxOccurs="1" />
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
+ <xs:complexType name="MatcherType" abstract="true" ></xs:complexType>
+
+ <xs:complexType name="BugMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="code" type="xs:string" use="optional" />
+ <xs:attribute name="pattern" type="xs:string" use="optional" />
+ <xs:attribute name="category" type="xs:string" use="optional" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="ClassMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ <xs:attribute name="role" type="xs:string" use="optional" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="TypeMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="descriptor" type="xs:string" use="required" />
+ <xs:attribute name="role" type="xs:string" use="optional" />
+ <xs:attribute name="typeParameters" type="xs:string" use="optional" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="FirstVersionMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="value" type="xs:long" use="required" />
+ <xs:attribute name="relOp" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="LastVersionMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="value" type="xs:long" use="required" />
+ <xs:attribute name="relOp" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="DesignationMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="designation" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="BugCodeMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="LocalMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="BugPatternMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="PriorityMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="value" type="xs:int" use="required" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="RankMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="value" type="xs:int" use="required" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="PackageMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="MethodMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="name" type="xs:string" use="optional" />
+ <xs:attribute name="params" type="xs:string" use="optional" />
+ <xs:attribute name="returns" type="xs:string" use="optional" />
+ <xs:attribute name="role" type="xs:string" use="optional" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="FieldMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:attribute name="name" type="xs:string" use="optional" />
+ <xs:attribute name="type" type="xs:string" use="optional" />
+ <xs:attribute name="role" type="xs:string" use="optional" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="OrMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:sequence>
+ <xs:element ref="Matcher" minOccurs="1" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="AndMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:sequence>
+ <xs:element ref="Matcher" minOccurs="1" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="MatchMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:sequence>
+ <xs:element ref="Matcher" minOccurs="1" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="classregex" type="xs:string" use="optional" />
+ <xs:attribute name="class" type="xs:string" use="optional" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="NotMatcherType">
+ <xs:complexContent>
+ <xs:extension base="MatcherType">
+ <xs:sequence>
+ <xs:element ref="Matcher" minOccurs="1" maxOccurs="1" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
</xs:schema>
diff --git a/etc/bugrank.txt b/etc/bugrank.txt
index e3a1ccb..690a51c 100644
--- a/etc/bugrank.txt
+++ b/etc/bugrank.txt
@@ -1,5 +1,6 @@
+2 BugPattern SF_SWITCH_NO_DEFAULT
-2 BugPattern RV_RETURN_VALUE_IGNORED
+-3 BugPattern DM_INVALID_MIN_MAX
-4 BugPattern RV_EXCEPTION_NOT_THROWN
-2 BugPattern NP_LOAD_OF_KNOWN_NULL_VALUE
+1 BugPattern EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC
@@ -26,6 +27,7 @@
-6 BugPattern NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT
+5 BugPattern SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING
-4 BugPattern ICAST_BAD_SHIFT_AMOUNT
++5 BugPattern BSHIFT_WRONG_ADD_PRIORITY
-2 BugPattern DMI_INVOKING_HASHCODE_ON_ARRAY
+3 BugPattern UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR
+4 BugPattern VA_FORMAT_STRING_ILLEGAL
@@ -53,8 +55,8 @@
+5 BugPattern SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE
+4 BugPattern RE_BAD_SYNTAX_FOR_REGULAR_EXPRESSION
-2 BugPattern NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE
--3 BugPattern INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE
-8 BugPattern LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE
++2 BugPattern RANGE_STRING_INDEX
+2 BugPattern ICAST_INT_CAST_TO_FLOAT_PASSED_TO_ROUND
+2 BugPattern RV_ABSOLUTE_VALUE_OF_HASHCODE
-3 BugPattern RE_POSSIBLE_UNINTENDED_PATTERN
@@ -109,6 +111,9 @@
-2 BugPattern PZ_DONT_REUSE_ENTRY_OBJECTS_IN_ITERATORS
-2 BugPattern DMI_ENTRY_SETS_MAY_REUSE_ENTRY_OBJECTS
+3 BugPattern RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE
++5 BugPattern CAA_COVARIANT_ARRAY_ELEMENT_STORE
+-1 BugPattern UC_USELESS_CONDITION
+-1 BugPattern UC_USELESS_CONDITION_TYPE
-4 BugKind FB
-4 BugKind EC
+1 BugKind RCN
diff --git a/etc/diffBugSummaries b/etc/diffBugSummaries
old mode 100644
new mode 100755
diff --git a/etc/doc.properties b/etc/doc.properties
index 6961fb3..ccdf8d7 100644
--- a/etc/doc.properties
+++ b/etc/doc.properties
@@ -6,18 +6,20 @@ doc.html.sidebar= \n\
<tr><td> </td></tr>\n\
\n\
<tr><td><b>Docs and Info</b></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="findbugs2.html">FindBugs 2.0</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="demo.html">Demo and data</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="users.html">Users and supporters</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="http://findbugs.blogspot.com/">FindBugs blog</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="factSheet.html">Fact sheet</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="manual/index.html">Manual</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="ja/manual/index.html">Manual(ja/日本語)</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="FAQ.html">FAQ</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="bugDescriptions.html">Bug descriptions</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="mailingLists.html">Mailing lists</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="publications.html">Documents and Publications</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="links.html">Links</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="findbugs2.html">FindBugs 2.0</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="demo.html">Demo and data</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="users.html">Users and supporters</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="http://findbugs.blogspot.com/">FindBugs blog</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="factSheet.html">Fact sheet</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="manual/index.html">Manual</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="ja/manual/index.html">Manual(ja/日本語)</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="FAQ.html">FAQ</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="bugDescriptions.html">Bug descriptions</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="bugDescriptions_ja.html">Bug descriptions(ja/日本語)</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="bugDescriptions_fr.html">Bug descriptions(fr)</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="mailingLists.html">Mailing lists</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="publications.html">Documents and Publications</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="links.html">Links</a></font></td></tr> \n\
\n\
<tr><td> </td></tr>\n\
\n\
@@ -30,15 +32,15 @@ doc.html.sidebar= \n\
<tr><td> </td></tr>\n\
\n\
<tr><td><b>Development</b></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="http://sourceforge.net/tracker/?group_id=96405">Open bugs</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="reportingBugs.html">Reporting bugs</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="contributing.html">Contributing</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="team.html">Dev team</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="api/index.html">API</a> <a class="sidebar" href="api/overview-summary.html">[no frames]</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="Changes.html">Change log</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="http://sourceforge.net/projects/findbugs">SF project page</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="http://code.google.com/p/findbugs/source/browse/">Browse source</a></font></td></tr> \n\
- <tr><td><font size="-1"><a class="sidebar" href="http://code.google.com/p/findbugs/source/list">Latest code changes</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="http://sourceforge.net/p/findbugs/bugs/">Open bugs</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="reportingBugs.html">Reporting bugs</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="contributing.html">Contributing</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="team.html">Dev team</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="api/index.html">API</a> <a class="sidebar" href="api/overview-summary.html">[no frames]</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="Changes.html">Change log</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="http://sourceforge.net/projects/findbugs">SF project page</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="http://code.google.com/p/findbugs/source/browse/">Browse source</a></font></td></tr> \n\
+ <tr><td><font size="-1"> <a class="sidebar" href="http://code.google.com/p/findbugs/source/list">Latest code changes</a></font></td></tr> \n\
</table> \n\
</td>
doc.html.footer= \n\
@@ -50,7 +52,7 @@ doc.html.footer= \n\
</script> \n\
<p> Send comments to <a class="sidebar" href="mailto:findbugs at cs.umd.edu">findbugs at cs.umd.edu</a> \n\
<p> \n\
- <A href="http://sourceforge.net"><IMG src="http://sourceforge.net/sflogo.php?group_id=96405&type=5" width="210" height="62" border="0" alt="SourceForge.net Logo" /></A>
+ <a href="http://sourceforge.net/projects/findbugs/"><img src="http://sourceforge.net/sflogo.php?group_id=96405&type=5" width="210" height="62" border="0" alt="FindBugs on SourceForge.net" /></a>
doc.html.googleanalytics= \n\
<script type="text/javascript"> \n\
var _gaq = _gaq || []; \n\
diff --git a/etc/docbook/dbpoolx.mod b/etc/docbook/dbpoolx.mod
index a6ff878..4f11a19 100644
--- a/etc/docbook/dbpoolx.mod
+++ b/etc/docbook/dbpoolx.mod
@@ -77,52 +77,52 @@
<!ENTITY % local.ndxterm.class "">
<!ENTITY % ndxterm.class
- "indexterm %local.ndxterm.class;">
+ "indexterm %local.ndxterm.class;">
<!-- Object-level classes ................................................. -->
<!ENTITY % local.list.class "">
<!ENTITY % list.class
- "calloutlist|glosslist|itemizedlist|orderedlist|segmentedlist
- |simplelist|variablelist %local.list.class;">
+ "calloutlist|glosslist|itemizedlist|orderedlist|segmentedlist
+ |simplelist|variablelist %local.list.class;">
<!ENTITY % local.admon.class "">
<!ENTITY % admon.class
- "caution|important|note|tip|warning %local.admon.class;">
+ "caution|important|note|tip|warning %local.admon.class;">
<!ENTITY % local.linespecific.class "">
<!ENTITY % linespecific.class
- "literallayout|programlisting|programlistingco|screen
- |screenco|screenshot %local.linespecific.class;">
+ "literallayout|programlisting|programlistingco|screen
+ |screenco|screenshot %local.linespecific.class;">
<!ENTITY % local.method.synop.class "">
<!ENTITY % method.synop.class
- "constructorsynopsis
+ "constructorsynopsis
|destructorsynopsis
|methodsynopsis %local.method.synop.class;">
<!ENTITY % local.synop.class "">
<!ENTITY % synop.class
- "synopsis|cmdsynopsis|funcsynopsis
+ "synopsis|cmdsynopsis|funcsynopsis
|classsynopsis|fieldsynopsis
|%method.synop.class; %local.synop.class;">
<!ENTITY % local.para.class "">
<!ENTITY % para.class
- "formalpara|para|simpara %local.para.class;">
+ "formalpara|para|simpara %local.para.class;">
<!ENTITY % local.informal.class "">
<!ENTITY % informal.class
- "address|blockquote
+ "address|blockquote
|graphic|graphicco|mediaobject|mediaobjectco
|informalequation
- |informalexample
+ |informalexample
|informalfigure
|informaltable %local.informal.class;">
<!ENTITY % local.formal.class "">
<!ENTITY % formal.class
- "equation|example|figure|table %local.formal.class;">
+ "equation|example|figure|table %local.formal.class;">
<!-- The DocBook TC may produce an official EBNF module for DocBook. -->
<!-- This PE provides the hook by which it can be inserted into the DTD. -->
@@ -130,35 +130,35 @@
<!ENTITY % local.compound.class "">
<!ENTITY % compound.class
- "msgset|procedure|sidebar|qandaset
+ "msgset|procedure|sidebar|qandaset
%ebnf.block.hook;
%local.compound.class;">
<!ENTITY % local.genobj.class "">
<!ENTITY % genobj.class
- "anchor|bridgehead|remark|highlights
- %local.genobj.class;">
+ "anchor|bridgehead|remark|highlights
+ %local.genobj.class;">
<!ENTITY % local.descobj.class "">
<!ENTITY % descobj.class
- "abstract|authorblurb|epigraph
- %local.descobj.class;">
+ "abstract|authorblurb|epigraph
+ %local.descobj.class;">
<!-- Character-level classes .............................................. -->
<!ENTITY % local.xref.char.class "">
<!ENTITY % xref.char.class
- "footnoteref|xref %local.xref.char.class;">
+ "footnoteref|xref %local.xref.char.class;">
<!ENTITY % local.gen.char.class "">
<!ENTITY % gen.char.class
- "abbrev|acronym|citation|citerefentry|citetitle|emphasis
- |firstterm|foreignphrase|glossterm|footnote|phrase
- |quote|trademark|wordasword|personname %local.gen.char.class;">
+ "abbrev|acronym|citation|citerefentry|citetitle|emphasis
+ |firstterm|foreignphrase|glossterm|footnote|phrase
+ |quote|trademark|wordasword|personname %local.gen.char.class;">
<!ENTITY % local.link.char.class "">
<!ENTITY % link.char.class
- "link|olink|ulink %local.link.char.class;">
+ "link|olink|ulink %local.link.char.class;">
<!-- The DocBook TC may produce an official EBNF module for DocBook. -->
<!-- This PE provides the hook by which it can be inserted into the DTD. -->
@@ -166,37 +166,37 @@
<!ENTITY % local.tech.char.class "">
<!ENTITY % tech.char.class
- "action|application
+ "action|application
|classname|methodname|interfacename|exceptionname
|ooclass|oointerface|ooexception
|command|computeroutput
- |database|email|envar|errorcode|errorname|errortype|errortext|filename
- |function|guibutton|guiicon|guilabel|guimenu|guimenuitem
- |guisubmenu|hardware|interface|keycap
- |keycode|keycombo|keysym|literal|constant|markup|medialabel
- |menuchoice|mousebutton|option|optional|parameter
- |prompt|property|replaceable|returnvalue|sgmltag|structfield
- |structname|symbol|systemitem|token|type|userinput|varname
+ |database|email|envar|errorcode|errorname|errortype|errortext|filename
+ |function|guibutton|guiicon|guilabel|guimenu|guimenuitem
+ |guisubmenu|hardware|interface|keycap
+ |keycode|keycombo|keysym|literal|constant|markup|medialabel
+ |menuchoice|mousebutton|option|optional|parameter
+ |prompt|property|replaceable|returnvalue|sgmltag|structfield
+ |structname|symbol|systemitem|token|type|userinput|varname
%ebnf.inline.hook;
- %local.tech.char.class;">
+ %local.tech.char.class;">
<!ENTITY % local.base.char.class "">
<!ENTITY % base.char.class
- "anchor %local.base.char.class;">
+ "anchor %local.base.char.class;">
<!ENTITY % local.docinfo.char.class "">
<!ENTITY % docinfo.char.class
- "author|authorinitials|corpauthor|modespec|othercredit
- |productname|productnumber|revhistory
- %local.docinfo.char.class;">
+ "author|authorinitials|corpauthor|modespec|othercredit
+ |productname|productnumber|revhistory
+ %local.docinfo.char.class;">
<!ENTITY % local.other.char.class "">
<!ENTITY % other.char.class
- "remark|subscript|superscript %local.other.char.class;">
+ "remark|subscript|superscript %local.other.char.class;">
<!ENTITY % local.inlineobj.char.class "">
<!ENTITY % inlineobj.char.class
- "inlinegraphic|inlinemediaobject|inlineequation %local.inlineobj.char.class;">
+ "inlinegraphic|inlinemediaobject|inlineequation %local.inlineobj.char.class;">
<!-- ...................................................................... -->
<!-- Entities for content models .......................................... -->
@@ -241,137 +241,137 @@ f. Just BlockQuote; no other informal objects.
<!ENTITY % local.component.mix "">
<!ENTITY % component.mix
- "%list.class; |%admon.class;
- |%linespecific.class; |%synop.class;
- |%para.class; |%informal.class;
- |%formal.class; |%compound.class;
- |%genobj.class; |%descobj.class;
- |%ndxterm.class; |beginpage
- %local.component.mix;">
+ "%list.class; |%admon.class;
+ |%linespecific.class; |%synop.class;
+ |%para.class; |%informal.class;
+ |%formal.class; |%compound.class;
+ |%genobj.class; |%descobj.class;
+ |%ndxterm.class; |beginpage
+ %local.component.mix;">
<!ENTITY % local.sidebar.mix "">
<!ENTITY % sidebar.mix
- "%list.class; |%admon.class;
- |%linespecific.class; |%synop.class;
- |%para.class; |%informal.class;
- |%formal.class; |procedure
- |%genobj.class;
- |%ndxterm.class; |beginpage
- %local.sidebar.mix;">
+ "%list.class; |%admon.class;
+ |%linespecific.class; |%synop.class;
+ |%para.class; |%informal.class;
+ |%formal.class; |procedure
+ |%genobj.class;
+ |%ndxterm.class; |beginpage
+ %local.sidebar.mix;">
<!ENTITY % local.qandaset.mix "">
<!ENTITY % qandaset.mix
- "%list.class; |%admon.class;
- |%linespecific.class; |%synop.class;
- |%para.class; |%informal.class;
- |%formal.class; |procedure
- |%genobj.class;
- |%ndxterm.class;
- %local.qandaset.mix;">
+ "%list.class; |%admon.class;
+ |%linespecific.class; |%synop.class;
+ |%para.class; |%informal.class;
+ |%formal.class; |procedure
+ |%genobj.class;
+ |%ndxterm.class;
+ %local.qandaset.mix;">
<!ENTITY % local.revdescription.mix "">
<!ENTITY % revdescription.mix
- "%list.class; |%admon.class;
- |%linespecific.class; |%synop.class;
- |%para.class; |%informal.class;
- |%formal.class; |procedure
- |%genobj.class;
- |%ndxterm.class;
- %local.revdescription.mix;">
+ "%list.class; |%admon.class;
+ |%linespecific.class; |%synop.class;
+ |%para.class; |%informal.class;
+ |%formal.class; |procedure
+ |%genobj.class;
+ |%ndxterm.class;
+ %local.revdescription.mix;">
<!ENTITY % local.footnote.mix "">
<!ENTITY % footnote.mix
- "%list.class;
- |%linespecific.class; |%synop.class;
- |%para.class; |%informal.class;
- %local.footnote.mix;">
+ "%list.class;
+ |%linespecific.class; |%synop.class;
+ |%para.class; |%informal.class;
+ %local.footnote.mix;">
<!ENTITY % local.example.mix "">
<!ENTITY % example.mix
- "%list.class;
- |%linespecific.class; |%synop.class;
- |%para.class; |%informal.class;
- |%ndxterm.class; |beginpage
- %local.example.mix;">
+ "%list.class;
+ |%linespecific.class; |%synop.class;
+ |%para.class; |%informal.class;
+ |%ndxterm.class; |beginpage
+ %local.example.mix;">
<!ENTITY % local.highlights.mix "">
<!ENTITY % highlights.mix
- "%list.class; |%admon.class;
- |%para.class;
- |%ndxterm.class;
- %local.highlights.mix;">
+ "%list.class; |%admon.class;
+ |%para.class;
+ |%ndxterm.class;
+ %local.highlights.mix;">
<!-- %formal.class; is explicitly excluded from many contexts in which
paragraphs are used -->
<!ENTITY % local.para.mix "">
<!ENTITY % para.mix
- "%list.class; |%admon.class;
- |%linespecific.class;
- |%informal.class;
- |%formal.class;
- %local.para.mix;">
+ "%list.class; |%admon.class;
+ |%linespecific.class;
+ |%informal.class;
+ |%formal.class;
+ %local.para.mix;">
<!ENTITY % local.admon.mix "">
<!ENTITY % admon.mix
- "%list.class;
- |%linespecific.class; |%synop.class;
- |%para.class; |%informal.class;
- |%formal.class; |procedure|sidebar
- |anchor|bridgehead|remark
- |%ndxterm.class; |beginpage
- %local.admon.mix;">
+ "%list.class;
+ |%linespecific.class; |%synop.class;
+ |%para.class; |%informal.class;
+ |%formal.class; |procedure|sidebar
+ |anchor|bridgehead|remark
+ |%ndxterm.class; |beginpage
+ %local.admon.mix;">
<!ENTITY % local.figure.mix "">
<!ENTITY % figure.mix
- "%linespecific.class; |%synop.class;
- |%informal.class;
- |%ndxterm.class; |beginpage
- %local.figure.mix;">
+ "%linespecific.class; |%synop.class;
+ |%informal.class;
+ |%ndxterm.class; |beginpage
+ %local.figure.mix;">
<!ENTITY % local.tabentry.mix "">
<!ENTITY % tabentry.mix
- "%list.class; |%admon.class;
- |%linespecific.class;
- |%para.class; |graphic|mediaobject
- %local.tabentry.mix;">
+ "%list.class; |%admon.class;
+ |%linespecific.class;
+ |%para.class; |graphic|mediaobject
+ %local.tabentry.mix;">
<!ENTITY % local.glossdef.mix "">
<!ENTITY % glossdef.mix
- "%list.class;
- |%linespecific.class; |%synop.class;
- |%para.class; |%informal.class;
- |%formal.class;
- |remark
- |%ndxterm.class; |beginpage
- %local.glossdef.mix;">
+ "%list.class;
+ |%linespecific.class; |%synop.class;
+ |%para.class; |%informal.class;
+ |%formal.class;
+ |remark
+ |%ndxterm.class; |beginpage
+ %local.glossdef.mix;">
<!ENTITY % local.legalnotice.mix "">
<!ENTITY % legalnotice.mix
- "%list.class; |%admon.class;
- |%linespecific.class;
- |%para.class; |blockquote
- |%ndxterm.class; |beginpage
- %local.legalnotice.mix;">
+ "%list.class; |%admon.class;
+ |%linespecific.class;
+ |%para.class; |blockquote
+ |%ndxterm.class; |beginpage
+ %local.legalnotice.mix;">
<!ENTITY % local.textobject.mix "">
<!ENTITY % textobject.mix
- "%list.class; |%admon.class;
- |%linespecific.class;
- |%para.class; |blockquote
- %local.textobject.mix;">
+ "%list.class; |%admon.class;
+ |%linespecific.class;
+ |%para.class; |blockquote
+ %local.textobject.mix;">
<!ENTITY % local.mediaobject.mix "">
<!ENTITY % mediaobject.mix
- "videoobject|audioobject|imageobject|textobject %local.mediaobject.mix;">
+ "videoobject|audioobject|imageobject|textobject %local.mediaobject.mix;">
<!ENTITY % local.listpreamble.mix "">
<!ENTITY % listpreamble.mix
- " %admon.class;
- |%linespecific.class; |%synop.class;
- |%para.class; |%informal.class;
- |%genobj.class; |%descobj.class;
- |%ndxterm.class; |beginpage
- %local.listpreamble.mix;">
+ " %admon.class;
+ |%linespecific.class; |%synop.class;
+ |%para.class; |%informal.class;
+ |%genobj.class; |%descobj.class;
+ |%ndxterm.class; |beginpage
+ %local.listpreamble.mix;">
<!-- Character-level mixtures ............................................. -->
@@ -437,71 +437,71 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % local.para.char.mix "">
<!ENTITY % para.char.mix
- "#PCDATA
- |%xref.char.class; |%gen.char.class;
- |%link.char.class; |%tech.char.class;
- |%base.char.class; |%docinfo.char.class;
- |%other.char.class; |%inlineobj.char.class;
- |%synop.class;
- |%ndxterm.class; |beginpage
+ "#PCDATA
+ |%xref.char.class; |%gen.char.class;
+ |%link.char.class; |%tech.char.class;
+ |%base.char.class; |%docinfo.char.class;
+ |%other.char.class; |%inlineobj.char.class;
+ |%synop.class;
+ |%ndxterm.class; |beginpage
%forminlines.hook;
- %local.para.char.mix;">
+ %local.para.char.mix;">
<!ENTITY % local.title.char.mix "">
<!ENTITY % title.char.mix
- "#PCDATA
- |%xref.char.class; |%gen.char.class;
- |%link.char.class; |%tech.char.class;
- |%base.char.class; |%docinfo.char.class;
- |%other.char.class; |%inlineobj.char.class;
- |%ndxterm.class;
- %local.title.char.mix;">
+ "#PCDATA
+ |%xref.char.class; |%gen.char.class;
+ |%link.char.class; |%tech.char.class;
+ |%base.char.class; |%docinfo.char.class;
+ |%other.char.class; |%inlineobj.char.class;
+ |%ndxterm.class;
+ %local.title.char.mix;">
<!ENTITY % local.ndxterm.char.mix "">
<!ENTITY % ndxterm.char.mix
- "#PCDATA
- |%xref.char.class; |%gen.char.class;
- |%link.char.class; |%tech.char.class;
- |%base.char.class; |%docinfo.char.class;
- |%other.char.class; |inlinegraphic|inlinemediaobject
- %local.ndxterm.char.mix;">
+ "#PCDATA
+ |%xref.char.class; |%gen.char.class;
+ |%link.char.class; |%tech.char.class;
+ |%base.char.class; |%docinfo.char.class;
+ |%other.char.class; |inlinegraphic|inlinemediaobject
+ %local.ndxterm.char.mix;">
<!ENTITY % local.cptr.char.mix "">
<!ENTITY % cptr.char.mix
- "#PCDATA
- |%link.char.class; |%tech.char.class;
- |%base.char.class;
- |%other.char.class; |inlinegraphic|inlinemediaobject
- |%ndxterm.class; |beginpage
- %local.cptr.char.mix;">
+ "#PCDATA
+ |%link.char.class; |%tech.char.class;
+ |%base.char.class;
+ |%other.char.class; |inlinegraphic|inlinemediaobject
+ |%ndxterm.class; |beginpage
+ %local.cptr.char.mix;">
<!ENTITY % local.smallcptr.char.mix "">
<!ENTITY % smallcptr.char.mix
- "#PCDATA
- |replaceable
- |inlinegraphic|inlinemediaobject
- |%ndxterm.class; |beginpage
- %local.smallcptr.char.mix;">
+ "#PCDATA
+ |replaceable
+ |inlinegraphic|inlinemediaobject
+ |%ndxterm.class; |beginpage
+ %local.smallcptr.char.mix;">
<!ENTITY % local.word.char.mix "">
<!ENTITY % word.char.mix
- "#PCDATA
- |acronym|emphasis|trademark
- |%link.char.class;
- |%base.char.class;
- |%other.char.class; |inlinegraphic|inlinemediaobject
- |%ndxterm.class; |beginpage
- %local.word.char.mix;">
+ "#PCDATA
+ |acronym|emphasis|trademark
+ |%link.char.class;
+ |%base.char.class;
+ |%other.char.class; |inlinegraphic|inlinemediaobject
+ |%ndxterm.class; |beginpage
+ %local.word.char.mix;">
<!ENTITY % local.docinfo.char.mix "">
<!ENTITY % docinfo.char.mix
- "#PCDATA
- |%link.char.class;
- |emphasis|trademark
- |replaceable
- |%other.char.class; |inlinegraphic|inlinemediaobject
- |%ndxterm.class;
- %local.docinfo.char.mix;">
+ "#PCDATA
+ |%link.char.class;
+ |emphasis|trademark
+ |replaceable
+ |%other.char.class; |inlinegraphic|inlinemediaobject
+ |%ndxterm.class;
+ %local.docinfo.char.mix;">
<!--ENTITY % bibliocomponent.mix (see Bibliographic section, below)-->
<!--ENTITY % person.ident.mix (see Bibliographic section, below)-->
@@ -512,61 +512,61 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!-- Arch: Computer or chip architecture to which element applies; no
- default -->
+ default -->
<!ENTITY % arch.attrib
- "arch CDATA #IMPLIED">
+ "arch CDATA #IMPLIED">
<!-- Condition: General-purpose effectivity attribute -->
<!ENTITY % condition.attrib
- "condition CDATA #IMPLIED">
+ "condition CDATA #IMPLIED">
<!-- Conformance: Standards conformance characteristics -->
<!ENTITY % conformance.attrib
- "conformance NMTOKENS #IMPLIED">
+ "conformance NMTOKENS #IMPLIED">
<!-- OS: Operating system to which element applies; no default -->
<!ENTITY % os.attrib
- "os CDATA #IMPLIED">
+ "os CDATA #IMPLIED">
<!-- Revision: Editorial revision to which element belongs; no default -->
<!ENTITY % revision.attrib
- "revision CDATA #IMPLIED">
+ "revision CDATA #IMPLIED">
<!-- Security: Security classification; no default -->
<!ENTITY % security.attrib
- "security CDATA #IMPLIED">
+ "security CDATA #IMPLIED">
<!-- UserLevel: Level of user experience to which element applies; no
- default -->
+ default -->
<!ENTITY % userlevel.attrib
- "userlevel CDATA #IMPLIED">
+ "userlevel CDATA #IMPLIED">
<!-- Vendor: Computer vendor to which element applies; no default -->
<!ENTITY % vendor.attrib
- "vendor CDATA #IMPLIED">
+ "vendor CDATA #IMPLIED">
<!ENTITY % local.effectivity.attrib "">
<!ENTITY % effectivity.attrib
- "%arch.attrib;
+ "%arch.attrib;
%condition.attrib;
- %conformance.attrib;
- %os.attrib;
- %revision.attrib;
+ %conformance.attrib;
+ %os.attrib;
+ %revision.attrib;
%security.attrib;
- %userlevel.attrib;
- %vendor.attrib;
- %local.effectivity.attrib;"
+ %userlevel.attrib;
+ %vendor.attrib;
+ %local.effectivity.attrib;"
>
<!-- Common attributes .................................................... -->
@@ -575,77 +575,77 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!-- Id: Unique identifier of element; no default -->
<!ENTITY % id.attrib
- "id ID #IMPLIED">
+ "id ID #IMPLIED">
<!-- Id: Unique identifier of element; a value must be supplied; no
- default -->
+ default -->
<!ENTITY % idreq.attrib
- "id ID #REQUIRED">
+ "id ID #REQUIRED">
<!-- Lang: Indicator of language in which element is written, for
- translation, character set management, etc.; no default -->
+ translation, character set management, etc.; no default -->
<!ENTITY % lang.attrib
- "lang CDATA #IMPLIED">
+ "lang CDATA #IMPLIED">
<!-- Remap: Previous role of element before conversion; no default -->
<!ENTITY % remap.attrib
- "remap CDATA #IMPLIED">
+ "remap CDATA #IMPLIED">
<!-- Role: New role of element in local environment; no default -->
<!ENTITY % role.attrib
- "role CDATA #IMPLIED">
+ "role CDATA #IMPLIED">
<!-- XRefLabel: Alternate labeling string for XRef text generation;
- default is usually title or other appropriate label text already
- contained in element -->
+ default is usually title or other appropriate label text already
+ contained in element -->
<!ENTITY % xreflabel.attrib
- "xreflabel CDATA #IMPLIED">
+ "xreflabel CDATA #IMPLIED">
<!-- RevisionFlag: Revision status of element; default is that element
- wasn't revised -->
+ wasn't revised -->
<!ENTITY % revisionflag.attrib
- "revisionflag (changed
- |added
- |deleted
- |off) #IMPLIED">
+ "revisionflag (changed
+ |added
+ |deleted
+ |off) #IMPLIED">
<!ENTITY % local.common.attrib "">
<!-- Role is included explicitly on each element -->
<!ENTITY % common.attrib
- "%id.attrib;
- %lang.attrib;
- %remap.attrib;
- %xreflabel.attrib;
- %revisionflag.attrib;
- %effectivity.attrib;
- %local.common.attrib;"
+ "%id.attrib;
+ %lang.attrib;
+ %remap.attrib;
+ %xreflabel.attrib;
+ %revisionflag.attrib;
+ %effectivity.attrib;
+ %local.common.attrib;"
>
<!-- Role is included explicitly on each element -->
<!ENTITY % idreq.common.attrib
- "%idreq.attrib;
- %lang.attrib;
- %remap.attrib;
- %xreflabel.attrib;
- %revisionflag.attrib;
- %effectivity.attrib;
- %local.common.attrib;"
+ "%idreq.attrib;
+ %lang.attrib;
+ %remap.attrib;
+ %xreflabel.attrib;
+ %revisionflag.attrib;
+ %effectivity.attrib;
+ %local.common.attrib;"
>
<!-- Semi-common attributes and other attribute entities .................. -->
@@ -653,129 +653,129 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % local.graphics.attrib "">
<!-- EntityRef: Name of an external entity containing the content
- of the graphic -->
+ of the graphic -->
<!-- FileRef: Filename, qualified by a pathname if desired,
- designating the file containing the content of the graphic -->
+ designating the file containing the content of the graphic -->
<!-- Format: Notation of the element content, if any -->
<!-- SrcCredit: Information about the source of the Graphic -->
<!-- Width: Same as CALS reprowid (desired width) -->
<!-- Depth: Same as CALS reprodep (desired depth) -->
<!-- Align: Same as CALS hplace with 'none' removed; #IMPLIED means
- application-specific -->
+ application-specific -->
<!-- Scale: Conflation of CALS hscale and vscale -->
<!-- Scalefit: Same as CALS scalefit -->
<!ENTITY % graphics.attrib
- "
- entityref ENTITY #IMPLIED
- fileref CDATA #IMPLIED
- format (%notation.class;) #IMPLIED
- srccredit CDATA #IMPLIED
- width CDATA #IMPLIED
- contentwidth CDATA #IMPLIED
- depth CDATA #IMPLIED
- contentdepth CDATA #IMPLIED
- align (left
- |right
- |center) #IMPLIED
- valign (top
- |middle
- |bottom) #IMPLIED
- scale CDATA #IMPLIED
- scalefit %yesorno.attvals;
- #IMPLIED
- %local.graphics.attrib;"
+ "
+ entityref ENTITY #IMPLIED
+ fileref CDATA #IMPLIED
+ format (%notation.class;) #IMPLIED
+ srccredit CDATA #IMPLIED
+ width CDATA #IMPLIED
+ contentwidth CDATA #IMPLIED
+ depth CDATA #IMPLIED
+ contentdepth CDATA #IMPLIED
+ align (left
+ |right
+ |center) #IMPLIED
+ valign (top
+ |middle
+ |bottom) #IMPLIED
+ scale CDATA #IMPLIED
+ scalefit %yesorno.attvals;
+ #IMPLIED
+ %local.graphics.attrib;"
>
<!ENTITY % local.keyaction.attrib "">
<!-- Action: Key combination type; default is unspecified if one
- child element, Simul if there is more than one; if value is
- Other, the OtherAction attribute must have a nonempty value -->
+ child element, Simul if there is more than one; if value is
+ Other, the OtherAction attribute must have a nonempty value -->
<!-- OtherAction: User-defined key combination type -->
<!ENTITY % keyaction.attrib
- "
- action (click
- |double-click
- |press
- |seq
- |simul
- |other) #IMPLIED
- otheraction CDATA #IMPLIED
- %local.keyaction.attrib;"
+ "
+ action (click
+ |double-click
+ |press
+ |seq
+ |simul
+ |other) #IMPLIED
+ otheraction CDATA #IMPLIED
+ %local.keyaction.attrib;"
>
<!-- Label: Identifying number or string; default is usually the
- appropriate number or string autogenerated by a formatter -->
+ appropriate number or string autogenerated by a formatter -->
<!ENTITY % label.attrib
- "label CDATA #IMPLIED">
+ "label CDATA #IMPLIED">
<!-- Format: whether element is assumed to contain significant white
- space -->
+ space -->
<!ENTITY % linespecific.attrib
- "format NOTATION
- (linespecific) 'linespecific'
+ "format NOTATION
+ (linespecific) 'linespecific'
linenumbering (numbered|unnumbered) #IMPLIED">
<!-- Linkend: link to related information; no default -->
<!ENTITY % linkend.attrib
- "linkend IDREF #IMPLIED">
+ "linkend IDREF #IMPLIED">
<!-- Linkend: required link to related information -->
<!ENTITY % linkendreq.attrib
- "linkend IDREF #REQUIRED">
+ "linkend IDREF #REQUIRED">
<!-- Linkends: link to one or more sets of related information; no
- default -->
+ default -->
<!ENTITY % linkends.attrib
- "linkends IDREFS #IMPLIED">
+ "linkends IDREFS #IMPLIED">
<!ENTITY % local.mark.attrib "">
<!ENTITY % mark.attrib
- "mark CDATA #IMPLIED
- %local.mark.attrib;"
+ "mark CDATA #IMPLIED
+ %local.mark.attrib;"
>
<!-- MoreInfo: whether element's content has an associated RefEntry -->
<!ENTITY % moreinfo.attrib
- "moreinfo (refentry|none) 'none'">
+ "moreinfo (refentry|none) 'none'">
<!-- Pagenum: number of page on which element appears; no default -->
<!ENTITY % pagenum.attrib
- "pagenum CDATA #IMPLIED">
+ "pagenum CDATA #IMPLIED">
<!ENTITY % local.status.attrib "">
<!-- Status: Editorial or publication status of the element
- it applies to, such as "in review" or "approved for distribution" -->
+ it applies to, such as "in review" or "approved for distribution" -->
<!ENTITY % status.attrib
- "status CDATA #IMPLIED
- %local.status.attrib;"
+ "status CDATA #IMPLIED
+ %local.status.attrib;"
>
<!-- Width: width of the longest line in the element to which it
- pertains, in number of characters -->
+ pertains, in number of characters -->
<!ENTITY % width.attrib
- "width CDATA #IMPLIED">
+ "width CDATA #IMPLIED">
<!-- ...................................................................... -->
<!-- Title elements ....................................................... -->
@@ -793,10 +793,10 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % title.attlist "INCLUDE">
<![%title.attlist;[
<!ATTLIST title
- %pagenum.attrib;
- %common.attrib;
- %title.role.attrib;
- %local.title.attrib;
+ %pagenum.attrib;
+ %common.attrib;
+ %title.role.attrib;
+ %local.title.attrib;
>
<!--end of title.attlist-->]]>
<!--end of title.module-->]]>
@@ -814,9 +814,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % titleabbrev.attlist "INCLUDE">
<![%titleabbrev.attlist;[
<!ATTLIST titleabbrev
- %common.attrib;
- %titleabbrev.role.attrib;
- %local.titleabbrev.attrib;
+ %common.attrib;
+ %titleabbrev.role.attrib;
+ %local.titleabbrev.attrib;
>
<!--end of titleabbrev.attlist-->]]>
<!--end of titleabbrev.module-->]]>
@@ -834,9 +834,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % subtitle.attlist "INCLUDE">
<![%subtitle.attlist;[
<!ATTLIST subtitle
- %common.attrib;
- %subtitle.role.attrib;
- %local.subtitle.attrib;
+ %common.attrib;
+ %subtitle.role.attrib;
+ %local.subtitle.attrib;
>
<!--end of subtitle.attlist-->]]>
<!--end of subtitle.module-->]]>
@@ -851,31 +851,31 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % local.person.ident.mix "">
<!ENTITY % person.ident.mix
- "honorific|firstname|surname|lineage|othername|affiliation
- |authorblurb|contrib %local.person.ident.mix;">
+ "honorific|firstname|surname|lineage|othername|affiliation
+ |authorblurb|contrib %local.person.ident.mix;">
<!ENTITY % local.bibliocomponent.mix "">
<!ENTITY % bibliocomponent.mix
- "abbrev|abstract|address|artpagenums|author
- |authorgroup|authorinitials|bibliomisc|biblioset
- |collab|confgroup|contractnum|contractsponsor
- |copyright|corpauthor|corpname|date|edition
- |editor|invpartnumber|isbn|issn|issuenum|orgname
- |biblioid|citebiblioid|bibliosource|bibliorelation|bibliocoverage
- |othercredit|pagenums|printhistory|productname
- |productnumber|pubdate|publisher|publishername
- |pubsnumber|releaseinfo|revhistory|seriesvolnums
- |subtitle|title|titleabbrev|volumenum|citetitle
- |personname|%person.ident.mix;
- |%ndxterm.class;
- %local.bibliocomponent.mix;">
+ "abbrev|abstract|address|artpagenums|author
+ |authorgroup|authorinitials|bibliomisc|biblioset
+ |collab|confgroup|contractnum|contractsponsor
+ |copyright|corpauthor|corpname|date|edition
+ |editor|invpartnumber|isbn|issn|issuenum|orgname
+ |biblioid|citebiblioid|bibliosource|bibliorelation|bibliocoverage
+ |othercredit|pagenums|printhistory|productname
+ |productnumber|pubdate|publisher|publishername
+ |pubsnumber|releaseinfo|revhistory|seriesvolnums
+ |subtitle|title|titleabbrev|volumenum|citetitle
+ |personname|%person.ident.mix;
+ |%ndxterm.class;
+ %local.bibliocomponent.mix;">
<!-- I don't think this is well placed, but it needs to be here because of -->
<!-- the reference to bibliocomponent.mix -->
<!ENTITY % local.info.class "">
<!ENTITY % info.class
- "graphic | mediaobject | legalnotice | modespec
- | subjectset | keywordset | itermset | %bibliocomponent.mix;
+ "graphic | mediaobject | legalnotice | modespec
+ | subjectset | keywordset | itermset | %bibliocomponent.mix;
%local.info.class;">
<!ENTITY % biblioentry.module "INCLUDE">
@@ -892,9 +892,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % biblioentry.attlist "INCLUDE">
<![%biblioentry.attlist;[
<!ATTLIST biblioentry
- %common.attrib;
- %biblioentry.role.attrib;
- %local.biblioentry.attrib;
+ %common.attrib;
+ %biblioentry.role.attrib;
+ %local.biblioentry.attrib;
>
<!--end of biblioentry.attlist-->]]>
<!--end of biblioentry.module-->]]>
@@ -913,9 +913,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % bibliomixed.attlist "INCLUDE">
<![%bibliomixed.attlist;[
<!ATTLIST bibliomixed
- %common.attrib;
- %bibliomixed.role.attrib;
- %local.bibliomixed.attrib;
+ %common.attrib;
+ %bibliomixed.role.attrib;
+ %local.bibliomixed.attrib;
>
<!--end of bibliomixed.attlist-->]]>
<!--end of bibliomixed.module-->]]>
@@ -928,15 +928,15 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % articleinfo.element "INCLUDE">
<![%articleinfo.element;[
<!ELEMENT articleinfo %ho; ((%info.class;)+)
- %beginpage.exclusion;>
+ %beginpage.exclusion;>
<!--end of articleinfo.element-->]]>
<!ENTITY % articleinfo.attlist "INCLUDE">
<![%articleinfo.attlist;[
<!ATTLIST articleinfo
- %common.attrib;
- %articleinfo.role.attrib;
- %local.articleinfo.attrib;
+ %common.attrib;
+ %articleinfo.role.attrib;
+ %local.articleinfo.attrib;
>
<!--end of articleinfo.attlist-->]]>
<!--end of articleinfo.module-->]]>
@@ -958,10 +958,10 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % biblioset.attlist "INCLUDE">
<![%biblioset.attlist;[
<!ATTLIST biblioset
- relation CDATA #IMPLIED
- %common.attrib;
- %biblioset.role.attrib;
- %local.biblioset.attrib;
+ relation CDATA #IMPLIED
+ %common.attrib;
+ %biblioset.role.attrib;
+ %local.biblioset.attrib;
>
<!--end of biblioset.attlist-->]]>
<!--end of biblioset.module-->]]>
@@ -983,10 +983,10 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % bibliomset.attlist "INCLUDE">
<![%bibliomset.attlist;[
<!ATTLIST bibliomset
- relation CDATA #IMPLIED
- %common.attrib;
- %bibliomset.role.attrib;
- %local.bibliomset.attrib;
+ relation CDATA #IMPLIED
+ %common.attrib;
+ %bibliomset.role.attrib;
+ %local.bibliomset.attrib;
>
<!--end of bibliomset.attlist-->]]>
<!--end of bibliomset.module-->]]>
@@ -1004,9 +1004,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % bibliomisc.attlist "INCLUDE">
<![%bibliomisc.attlist;[
<!ATTLIST bibliomisc
- %common.attrib;
- %bibliomisc.role.attrib;
- %local.bibliomisc.attrib;
+ %common.attrib;
+ %bibliomisc.role.attrib;
+ %local.bibliomisc.attrib;
>
<!--end of bibliomisc.attlist-->]]>
<!--end of bibliomisc.module-->]]>
@@ -1032,10 +1032,10 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % subjectset.attlist "INCLUDE">
<![%subjectset.attlist;[
<!ATTLIST subjectset
- scheme NMTOKEN #IMPLIED
- %common.attrib;
- %subjectset.role.attrib;
- %local.subjectset.attrib;
+ scheme NMTOKEN #IMPLIED
+ %common.attrib;
+ %subjectset.role.attrib;
+ %local.subjectset.attrib;
>
<!--end of subjectset.attlist-->]]>
<!--end of subjectset.module-->]]>
@@ -1051,16 +1051,16 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!--end of subject.element-->]]>
<!-- Weight: Ranking of this group of SubjectTerms relative
- to others, 0 is low, no highest value specified -->
+ to others, 0 is low, no highest value specified -->
<!ENTITY % subject.attlist "INCLUDE">
<![%subject.attlist;[
<!ATTLIST subject
- weight CDATA #IMPLIED
- %common.attrib;
- %subject.role.attrib;
- %local.subject.attrib;
+ weight CDATA #IMPLIED
+ %common.attrib;
+ %subject.role.attrib;
+ %local.subject.attrib;
>
<!--end of subject.attlist-->]]>
<!--end of subject.module-->]]>
@@ -1078,9 +1078,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % subjectterm.attlist "INCLUDE">
<![%subjectterm.attlist;[
<!ATTLIST subjectterm
- %common.attrib;
- %subjectterm.role.attrib;
- %local.subjectterm.attrib;
+ %common.attrib;
+ %subjectterm.role.attrib;
+ %local.subjectterm.attrib;
>
<!--end of subjectterm.attlist-->]]>
<!--end of subjectterm.module-->]]>
@@ -1101,9 +1101,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % keywordset.attlist "INCLUDE">
<![%keywordset.attlist;[
<!ATTLIST keywordset
- %common.attrib;
- %keywordset.role.attrib;
- %local.keywordset.attrib;
+ %common.attrib;
+ %keywordset.role.attrib;
+ %local.keywordset.attrib;
>
<!--end of keywordset.attlist-->]]>
<!--end of keywordset.module-->]]>
@@ -1121,9 +1121,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % keyword.attlist "INCLUDE">
<![%keyword.attlist;[
<!ATTLIST keyword
- %common.attrib;
- %keyword.role.attrib;
- %local.keyword.attrib;
+ %common.attrib;
+ %keyword.role.attrib;
+ %local.keyword.attrib;
>
<!--end of keyword.attlist-->]]>
<!--end of keyword.module-->]]>
@@ -1142,9 +1142,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % itermset.attlist "INCLUDE">
<![%itermset.attlist;[
<!ATTLIST itermset
- %common.attrib;
- %itermset.role.attrib;
- %local.itermset.attrib;
+ %common.attrib;
+ %itermset.role.attrib;
+ %local.itermset.attrib;
>
<!--end of itermset.attlist-->]]>
<!--end of itermset.module-->]]>
@@ -1159,15 +1159,15 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % blockinfo.element "INCLUDE">
<![ %blockinfo.element; [
<!ELEMENT blockinfo %ho; ((%info.class;)+)
- %beginpage.exclusion;>
+ %beginpage.exclusion;>
<!--end of blockinfo.element-->]]>
<!ENTITY % blockinfo.attlist "INCLUDE">
<![ %blockinfo.attlist; [
<!ATTLIST blockinfo
- %common.attrib;
- %blockinfo.role.attrib;
- %local.blockinfo.attrib;
+ %common.attrib;
+ %blockinfo.role.attrib;
+ %local.blockinfo.attrib;
>
<!--end of blockinfo.attlist-->]]>
<!--end of blockinfo.module-->]]>
@@ -1193,9 +1193,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msgset.attlist "INCLUDE">
<![%msgset.attlist;[
<!ATTLIST msgset
- %common.attrib;
- %msgset.role.attrib;
- %local.msgset.attrib;
+ %common.attrib;
+ %msgset.role.attrib;
+ %local.msgset.attrib;
>
<!--end of msgset.attlist-->]]>
<!--end of msgset.module-->]]>
@@ -1213,9 +1213,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msgentry.attlist "INCLUDE">
<![%msgentry.attlist;[
<!ATTLIST msgentry
- %common.attrib;
- %msgentry.role.attrib;
- %local.msgentry.attrib;
+ %common.attrib;
+ %msgentry.role.attrib;
+ %local.msgentry.attrib;
>
<!--end of msgentry.attlist-->]]>
<!--end of msgentry.module-->]]>
@@ -1233,12 +1233,12 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % simplemsgentry.attlist "INCLUDE">
<![ %simplemsgentry.attlist; [
<!ATTLIST simplemsgentry
- audience CDATA #IMPLIED
- level CDATA #IMPLIED
- origin CDATA #IMPLIED
- %common.attrib;
- %simplemsgentry.role.attrib;
- %local.simplemsgentry.attrib;
+ audience CDATA #IMPLIED
+ level CDATA #IMPLIED
+ origin CDATA #IMPLIED
+ %common.attrib;
+ %simplemsgentry.role.attrib;
+ %local.simplemsgentry.attrib;
>
<!--end of simplemsgentry.attlist-->]]>
<!--end of simplemsgentry.module-->]]>
@@ -1256,9 +1256,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msg.attlist "INCLUDE">
<![%msg.attlist;[
<!ATTLIST msg
- %common.attrib;
- %msg.role.attrib;
- %local.msg.attrib;
+ %common.attrib;
+ %msg.role.attrib;
+ %local.msg.attrib;
>
<!--end of msg.attlist-->]]>
<!--end of msg.module-->]]>
@@ -1276,9 +1276,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msgmain.attlist "INCLUDE">
<![%msgmain.attlist;[
<!ATTLIST msgmain
- %common.attrib;
- %msgmain.role.attrib;
- %local.msgmain.attrib;
+ %common.attrib;
+ %msgmain.role.attrib;
+ %local.msgmain.attrib;
>
<!--end of msgmain.attlist-->]]>
<!--end of msgmain.module-->]]>
@@ -1296,9 +1296,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msgsub.attlist "INCLUDE">
<![%msgsub.attlist;[
<!ATTLIST msgsub
- %common.attrib;
- %msgsub.role.attrib;
- %local.msgsub.attrib;
+ %common.attrib;
+ %msgsub.role.attrib;
+ %local.msgsub.attrib;
>
<!--end of msgsub.attlist-->]]>
<!--end of msgsub.module-->]]>
@@ -1316,9 +1316,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msgrel.attlist "INCLUDE">
<![%msgrel.attlist;[
<!ATTLIST msgrel
- %common.attrib;
- %msgrel.role.attrib;
- %local.msgrel.attrib;
+ %common.attrib;
+ %msgrel.role.attrib;
+ %local.msgrel.attrib;
>
<!--end of msgrel.attlist-->]]>
<!--end of msgrel.module-->]]>
@@ -1338,9 +1338,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msginfo.attlist "INCLUDE">
<![%msginfo.attlist;[
<!ATTLIST msginfo
- %common.attrib;
- %msginfo.role.attrib;
- %local.msginfo.attrib;
+ %common.attrib;
+ %msginfo.role.attrib;
+ %local.msginfo.attrib;
>
<!--end of msginfo.attlist-->]]>
<!--end of msginfo.module-->]]>
@@ -1358,9 +1358,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msglevel.attlist "INCLUDE">
<![%msglevel.attlist;[
<!ATTLIST msglevel
- %common.attrib;
- %msglevel.role.attrib;
- %local.msglevel.attrib;
+ %common.attrib;
+ %msglevel.role.attrib;
+ %local.msglevel.attrib;
>
<!--end of msglevel.attlist-->]]>
<!--end of msglevel.module-->]]>
@@ -1378,9 +1378,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msgorig.attlist "INCLUDE">
<![%msgorig.attlist;[
<!ATTLIST msgorig
- %common.attrib;
- %msgorig.role.attrib;
- %local.msgorig.attrib;
+ %common.attrib;
+ %msgorig.role.attrib;
+ %local.msgorig.attrib;
>
<!--end of msgorig.attlist-->]]>
<!--end of msgorig.module-->]]>
@@ -1398,9 +1398,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msgaud.attlist "INCLUDE">
<![%msgaud.attlist;[
<!ATTLIST msgaud
- %common.attrib;
- %msgaud.role.attrib;
- %local.msgaud.attrib;
+ %common.attrib;
+ %msgaud.role.attrib;
+ %local.msgaud.attrib;
>
<!--end of msgaud.attlist-->]]>
<!--end of msgaud.module-->]]>
@@ -1418,9 +1418,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % msgexplan.attlist "INCLUDE">
<![%msgexplan.attlist;[
<!ATTLIST msgexplan
- %common.attrib;
- %msgexplan.role.attrib;
- %local.msgexplan.attrib;
+ %common.attrib;
+ %msgexplan.role.attrib;
+ %local.msgexplan.attrib;
>
<!--end of msgexplan.attlist-->]]>
<!--end of msgexplan.module-->]]>
@@ -1437,17 +1437,17 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % qandaset.element "INCLUDE">
<![ %qandaset.element; [
<!ELEMENT qandaset %ho; (blockinfo?, (%formalobject.title.content;)?,
- (%qandaset.mix;)*,
+ (%qandaset.mix;)*,
(qandadiv+|qandaentry+))>
<!--end of qandaset.element-->]]>
<!ENTITY % qandaset.attlist "INCLUDE">
<![ %qandaset.attlist; [
<!ATTLIST qandaset
- defaultlabel (qanda|number|none) #IMPLIED
- %common.attrib;
- %qandaset.role.attrib;
- %local.qandaset.attrib;>
+ defaultlabel (qanda|number|none) #IMPLIED
+ %common.attrib;
+ %qandaset.role.attrib;
+ %local.qandaset.attrib;>
<!--end of qandaset.attlist-->]]>
<!--end of qandaset.module-->]]>
@@ -1459,16 +1459,16 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % qandadiv.element "INCLUDE">
<![ %qandadiv.element; [
<!ELEMENT qandadiv %ho; (blockinfo?, (%formalobject.title.content;)?,
- (%qandaset.mix;)*,
- (qandadiv+|qandaentry+))>
+ (%qandaset.mix;)*,
+ (qandadiv+|qandaentry+))>
<!--end of qandadiv.element-->]]>
<!ENTITY % qandadiv.attlist "INCLUDE">
<![ %qandadiv.attlist; [
<!ATTLIST qandadiv
- %common.attrib;
- %qandadiv.role.attrib;
- %local.qandadiv.attrib;>
+ %common.attrib;
+ %qandadiv.role.attrib;
+ %local.qandadiv.attrib;>
<!--end of qandadiv.attlist-->]]>
<!--end of qandadiv.module-->]]>
@@ -1485,9 +1485,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % qandaentry.attlist "INCLUDE">
<![ %qandaentry.attlist; [
<!ATTLIST qandaentry
- %common.attrib;
- %qandaentry.role.attrib;
- %local.qandaentry.attrib;>
+ %common.attrib;
+ %qandaentry.role.attrib;
+ %local.qandaentry.attrib;>
<!--end of qandaentry.attlist-->]]>
<!--end of qandaentry.module-->]]>
@@ -1504,9 +1504,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % question.attlist "INCLUDE">
<![ %question.attlist; [
<!ATTLIST question
- %common.attrib;
- %question.role.attrib;
- %local.question.attrib;
+ %common.attrib;
+ %question.role.attrib;
+ %local.question.attrib;
>
<!--end of question.attlist-->]]>
<!--end of question.module-->]]>
@@ -1524,9 +1524,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % answer.attlist "INCLUDE">
<![ %answer.attlist; [
<!ATTLIST answer
- %common.attrib;
- %answer.role.attrib;
- %local.answer.attrib;
+ %common.attrib;
+ %answer.role.attrib;
+ %local.answer.attrib;
>
<!--end of answer.attlist-->]]>
<!--end of answer.module-->]]>
@@ -1544,9 +1544,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % label.attlist "INCLUDE">
<![ %label.attlist; [
<!ATTLIST label
- %common.attrib;
- %label.role.attrib;
- %local.label.attrib;
+ %common.attrib;
+ %label.role.attrib;
+ %local.label.attrib;
>
<!--end of label.attlist-->]]>
<!--end of label.module-->]]>
@@ -1570,9 +1570,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % procedure.attlist "INCLUDE">
<![%procedure.attlist;[
<!ATTLIST procedure
- %common.attrib;
- %procedure.role.attrib;
- %local.procedure.attrib;
+ %common.attrib;
+ %procedure.role.attrib;
+ %local.procedure.attrib;
>
<!--end of procedure.attlist-->]]>
<!--end of procedure.module-->]]>
@@ -1585,7 +1585,7 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % step.element "INCLUDE">
<![%step.element;[
<!ELEMENT step %ho; (title?, (((%component.mix;)+, (substeps,
- (%component.mix;)*)?) | (substeps, (%component.mix;)*)))>
+ (%component.mix;)*)?) | (substeps, (%component.mix;)*)))>
<!--end of step.element-->]]>
<!-- Performance: Whether the Step must be performed -->
@@ -1595,11 +1595,11 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % step.attlist "INCLUDE">
<![%step.attlist;[
<!ATTLIST step
- performance (optional
- |required) "required"
- %common.attrib;
- %step.role.attrib;
- %local.step.attrib;
+ performance (optional
+ |required) "required"
+ %common.attrib;
+ %step.role.attrib;
+ %local.step.attrib;
>
<!--end of step.attlist-->]]>
<!--end of step.module-->]]>
@@ -1621,11 +1621,11 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % substeps.attlist "INCLUDE">
<![%substeps.attlist;[
<!ATTLIST substeps
- performance (optional
- |required) "required"
- %common.attrib;
- %substeps.role.attrib;
- %local.substeps.attrib;
+ performance (optional
+ |required) "required"
+ %common.attrib;
+ %substeps.role.attrib;
+ %local.substeps.attrib;
>
<!--end of substeps.attlist-->]]>
<!--end of substeps.module-->]]>
@@ -1644,15 +1644,15 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % sidebarinfo.element "INCLUDE">
<![ %sidebarinfo.element; [
<!ELEMENT sidebarinfo %ho; ((%info.class;)+)
- %beginpage.exclusion;>
+ %beginpage.exclusion;>
<!--end of sidebarinfo.element-->]]>
<!ENTITY % sidebarinfo.attlist "INCLUDE">
<![ %sidebarinfo.attlist; [
<!ATTLIST sidebarinfo
- %common.attrib;
- %sidebarinfo.role.attrib;
- %local.sidebarinfo.attrib;
+ %common.attrib;
+ %sidebarinfo.role.attrib;
+ %local.sidebarinfo.attrib;
>
<!--end of sidebarinfo.attlist-->]]>
<!--end of sidebarinfo.module-->]]>
@@ -1672,9 +1672,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % sidebar.attlist "INCLUDE">
<![%sidebar.attlist;[
<!ATTLIST sidebar
- %common.attrib;
- %sidebar.role.attrib;
- %local.sidebar.attrib;
+ %common.attrib;
+ %sidebar.role.attrib;
+ %local.sidebar.attrib;
>
<!--end of sidebar.attlist-->]]>
<!--end of sidebar.module-->]]>
@@ -1696,9 +1696,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % abstract.attlist "INCLUDE">
<![%abstract.attlist;[
<!ATTLIST abstract
- %common.attrib;
- %abstract.role.attrib;
- %local.abstract.attrib;
+ %common.attrib;
+ %abstract.role.attrib;
+ %local.abstract.attrib;
>
<!--end of abstract.attlist-->]]>
<!--end of abstract.module-->]]>
@@ -1716,9 +1716,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % authorblurb.attlist "INCLUDE">
<![%authorblurb.attlist;[
<!ATTLIST authorblurb
- %common.attrib;
- %authorblurb.role.attrib;
- %local.authorblurb.attrib;
+ %common.attrib;
+ %authorblurb.role.attrib;
+ %local.authorblurb.attrib;
>
<!--end of authorblurb.attlist-->]]>
<!--end of authorblurb.module-->]]>
@@ -1736,9 +1736,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % personblurb.attlist "INCLUDE">
<![%personblurb.attlist;[
<!ATTLIST personblurb
- %common.attrib;
- %personblurb.role.attrib;
- %local.personblurb.attrib;
+ %common.attrib;
+ %personblurb.role.attrib;
+ %local.personblurb.attrib;
>
<!--end of personblurb.attlist-->]]>
<!--end of personblurb.module-->]]>
@@ -1758,9 +1758,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % blockquote.attlist "INCLUDE">
<![%blockquote.attlist;[
<!ATTLIST blockquote
- %common.attrib;
- %blockquote.role.attrib;
- %local.blockquote.attrib;
+ %common.attrib;
+ %blockquote.role.attrib;
+ %local.blockquote.attrib;
>
<!--end of blockquote.attlist-->]]>
<!--end of blockquote.module-->]]>
@@ -1778,9 +1778,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % attribution.attlist "INCLUDE">
<![%attribution.attlist;[
<!ATTLIST attribution
- %common.attrib;
- %attribution.role.attrib;
- %local.attribution.attrib;
+ %common.attrib;
+ %attribution.role.attrib;
+ %local.attribution.attrib;
>
<!--end of attribution.attlist-->]]>
<!--end of attribution.module-->]]>
@@ -1796,21 +1796,21 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!--end of bridgehead.element-->]]>
<!-- Renderas: Indicates the format in which the BridgeHead
- should appear -->
+ should appear -->
<!ENTITY % bridgehead.attlist "INCLUDE">
<![%bridgehead.attlist;[
<!ATTLIST bridgehead
- renderas (other
- |sect1
- |sect2
- |sect3
- |sect4
- |sect5) #IMPLIED
- %common.attrib;
- %bridgehead.role.attrib;
- %local.bridgehead.attrib;
+ renderas (other
+ |sect1
+ |sect2
+ |sect3
+ |sect4
+ |sect5) #IMPLIED
+ %common.attrib;
+ %bridgehead.role.attrib;
+ %local.bridgehead.attrib;
>
<!--end of bridgehead.attlist-->]]>
<!--end of bridgehead.module-->]]>
@@ -1829,9 +1829,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % remark.attlist "INCLUDE">
<![%remark.attlist;[
<!ATTLIST remark
- %common.attrib;
- %remark.role.attrib;
- %local.remark.attrib;
+ %common.attrib;
+ %remark.role.attrib;
+ %local.remark.attrib;
>
<!--end of remark.attlist-->]]>
<!--end of remark.module-->]]>
@@ -1849,9 +1849,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % epigraph.attlist "INCLUDE">
<![%epigraph.attlist;[
<!ATTLIST epigraph
- %common.attrib;
- %epigraph.role.attrib;
- %local.epigraph.attrib;
+ %common.attrib;
+ %epigraph.role.attrib;
+ %local.epigraph.attrib;
>
<!--end of epigraph.attlist-->]]>
<!-- Attribution (defined above)-->
@@ -1871,10 +1871,10 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % footnote.attlist "INCLUDE">
<![%footnote.attlist;[
<!ATTLIST footnote
- %label.attrib;
- %common.attrib;
- %footnote.role.attrib;
- %local.footnote.attrib;
+ %label.attrib;
+ %common.attrib;
+ %footnote.role.attrib;
+ %local.footnote.attrib;
>
<!--end of footnote.attlist-->]]>
<!--end of footnote.module-->]]>
@@ -1893,9 +1893,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % highlights.attlist "INCLUDE">
<![%highlights.attlist;[
<!ATTLIST highlights
- %common.attrib;
- %highlights.role.attrib;
- %local.highlights.attrib;
+ %common.attrib;
+ %highlights.role.attrib;
+ %local.highlights.attrib;
>
<!--end of highlights.attlist-->]]>
<!--end of highlights.module-->]]>
@@ -1913,9 +1913,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % formalpara.attlist "INCLUDE">
<![%formalpara.attlist;[
<!ATTLIST formalpara
- %common.attrib;
- %formalpara.role.attrib;
- %local.formalpara.attrib;
+ %common.attrib;
+ %formalpara.role.attrib;
+ %local.formalpara.attrib;
>
<!--end of formalpara.attlist-->]]>
<!--end of formalpara.module-->]]>
@@ -1933,9 +1933,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % para.attlist "INCLUDE">
<![%para.attlist;[
<!ATTLIST para
- %common.attrib;
- %para.role.attrib;
- %local.para.attrib;
+ %common.attrib;
+ %para.role.attrib;
+ %local.para.attrib;
>
<!--end of para.attlist-->]]>
<!--end of para.module-->]]>
@@ -1953,9 +1953,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % simpara.attlist "INCLUDE">
<![%simpara.attlist;[
<!ATTLIST simpara
- %common.attrib;
- %simpara.role.attrib;
- %local.simpara.attrib;
+ %common.attrib;
+ %simpara.role.attrib;
+ %local.simpara.attrib;
>
<!--end of simpara.attlist-->]]>
<!--end of simpara.module-->]]>
@@ -1975,9 +1975,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % caution.attlist "INCLUDE">
<![%caution.attlist;[
<!ATTLIST caution
- %common.attrib;
- %admon.role.attrib;
- %local.admon.attrib;
+ %common.attrib;
+ %admon.role.attrib;
+ %local.admon.attrib;
>
<!--end of caution.attlist-->]]>
@@ -1991,9 +1991,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % important.attlist "INCLUDE">
<![%important.attlist;[
<!ATTLIST important
- %common.attrib;
- %admon.role.attrib;
- %local.admon.attrib;
+ %common.attrib;
+ %admon.role.attrib;
+ %local.admon.attrib;
>
<!--end of important.attlist-->]]>
@@ -2007,9 +2007,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % note.attlist "INCLUDE">
<![%note.attlist;[
<!ATTLIST note
- %common.attrib;
- %admon.role.attrib;
- %local.admon.attrib;
+ %common.attrib;
+ %admon.role.attrib;
+ %local.admon.attrib;
>
<!--end of note.attlist-->]]>
@@ -2022,9 +2022,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % tip.attlist "INCLUDE">
<![%tip.attlist;[
<!ATTLIST tip
- %common.attrib;
- %admon.role.attrib;
- %local.admon.attrib;
+ %common.attrib;
+ %admon.role.attrib;
+ %local.admon.attrib;
>
<!--end of tip.attlist-->]]>
@@ -2038,9 +2038,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % warning.attlist "INCLUDE">
<![%warning.attlist;[
<!ATTLIST warning
- %common.attrib;
- %admon.role.attrib;
- %local.admon.attrib;
+ %common.attrib;
+ %admon.role.attrib;
+ %local.admon.attrib;
>
<!--end of warning.attlist-->]]>
@@ -2064,9 +2064,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % glosslist.attlist "INCLUDE">
<![%glosslist.attlist;[
<!ATTLIST glosslist
- %common.attrib;
- %glosslist.role.attrib;
- %local.glosslist.attrib;
+ %common.attrib;
+ %glosslist.role.attrib;
+ %local.glosslist.attrib;
>
<!--end of glosslist.attlist-->]]>
<!--end of glosslist.module-->]]>
@@ -2086,16 +2086,16 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!--end of glossentry.element-->]]>
<!-- SortAs: String by which the GlossEntry is to be sorted
- (alphabetized) in lieu of its proper content -->
+ (alphabetized) in lieu of its proper content -->
<!ENTITY % glossentry.attlist "INCLUDE">
<![%glossentry.attlist;[
<!ATTLIST glossentry
- sortas CDATA #IMPLIED
- %common.attrib;
- %glossentry.role.attrib;
- %local.glossentry.attrib;
+ sortas CDATA #IMPLIED
+ %common.attrib;
+ %glossentry.role.attrib;
+ %local.glossentry.attrib;
>
<!--end of glossentry.attlist-->]]>
<!--end of glossentry.module-->]]>
@@ -2117,10 +2117,10 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % glossdef.attlist "INCLUDE">
<![%glossdef.attlist;[
<!ATTLIST glossdef
- subject CDATA #IMPLIED
- %common.attrib;
- %glossdef.role.attrib;
- %local.glossdef.attrib;
+ subject CDATA #IMPLIED
+ %common.attrib;
+ %glossdef.role.attrib;
+ %local.glossdef.attrib;
>
<!--end of glossdef.attlist-->]]>
<!--end of glossdef.module-->]]>
@@ -2136,16 +2136,16 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!--end of glosssee.element-->]]>
<!-- OtherTerm: Reference to the GlossEntry whose GlossTerm
- should be displayed at the point of the GlossSee -->
+ should be displayed at the point of the GlossSee -->
<!ENTITY % glosssee.attlist "INCLUDE">
<![%glosssee.attlist;[
<!ATTLIST glosssee
- otherterm IDREF #IMPLIED
- %common.attrib;
- %glosssee.role.attrib;
- %local.glosssee.attrib;
+ otherterm IDREF #IMPLIED
+ %common.attrib;
+ %glosssee.role.attrib;
+ %local.glosssee.attrib;
>
<!--end of glosssee.attlist-->]]>
<!--end of glosssee.module-->]]>
@@ -2161,16 +2161,16 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!--end of glossseealso.element-->]]>
<!-- OtherTerm: Reference to the GlossEntry whose GlossTerm
- should be displayed at the point of the GlossSeeAlso -->
+ should be displayed at the point of the GlossSeeAlso -->
<!ENTITY % glossseealso.attlist "INCLUDE">
<![%glossseealso.attlist;[
<!ATTLIST glossseealso
- otherterm IDREF #IMPLIED
- %common.attrib;
- %glossseealso.role.attrib;
- %local.glossseealso.attrib;
+ otherterm IDREF #IMPLIED
+ %common.attrib;
+ %glossseealso.role.attrib;
+ %local.glossseealso.attrib;
>
<!--end of glossseealso.attlist-->]]>
<!--end of glossseealso.module-->]]>
@@ -2186,24 +2186,24 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % itemizedlist.element "INCLUDE">
<![%itemizedlist.element;[
<!ELEMENT itemizedlist %ho; (blockinfo?, (%formalobject.title.content;)?,
- (%listpreamble.mix;)*, listitem+)>
+ (%listpreamble.mix;)*, listitem+)>
<!--end of itemizedlist.element-->]]>
<!-- Spacing: Whether the vertical space in the list should be
- compressed -->
+ compressed -->
<!-- Mark: Keyword, e.g., bullet, dash, checkbox, none;
- list of keywords and defaults are implementation specific -->
+ list of keywords and defaults are implementation specific -->
<!ENTITY % itemizedlist.attlist "INCLUDE">
<![%itemizedlist.attlist;[
<!ATTLIST itemizedlist spacing (normal
- |compact) #IMPLIED
- %mark.attrib;
- %common.attrib;
- %itemizedlist.role.attrib;
- %local.itemizedlist.attrib;
+ |compact) #IMPLIED
+ %mark.attrib;
+ %common.attrib;
+ %itemizedlist.role.attrib;
+ %local.itemizedlist.attrib;
>
<!--end of itemizedlist.attlist-->]]>
<!--end of itemizedlist.module-->]]>
@@ -2216,40 +2216,40 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % orderedlist.element "INCLUDE">
<![%orderedlist.element;[
<!ELEMENT orderedlist %ho; (blockinfo?, (%formalobject.title.content;)?,
- (%listpreamble.mix;)*, listitem+)>
+ (%listpreamble.mix;)*, listitem+)>
<!--end of orderedlist.element-->]]>
<!-- Numeration: Style of ListItem numbered; default is expected
- to be Arabic -->
+ to be Arabic -->
<!-- InheritNum: Specifies for a nested list that the numbering
- of ListItems should include the number of the item
- within which they are nested (e.g., 1a and 1b within 1,
- rather than a and b) -->
+ of ListItems should include the number of the item
+ within which they are nested (e.g., 1a and 1b within 1,
+ rather than a and b) -->
<!-- Continuation: Where list numbering begins afresh (Restarts,
- the default) or continues that of the immediately preceding
- list (Continues) -->
+ the default) or continues that of the immediately preceding
+ list (Continues) -->
<!-- Spacing: Whether the vertical space in the list should be
- compressed -->
+ compressed -->
<!ENTITY % orderedlist.attlist "INCLUDE">
<![%orderedlist.attlist;[
<!ATTLIST orderedlist
- numeration (arabic
- |upperalpha
- |loweralpha
- |upperroman
- |lowerroman) #IMPLIED
- inheritnum (inherit
- |ignore) "ignore"
- continuation (continues
- |restarts) "restarts"
- spacing (normal
- |compact) #IMPLIED
- %common.attrib;
- %orderedlist.role.attrib;
- %local.orderedlist.attrib;
+ numeration (arabic
+ |upperalpha
+ |loweralpha
+ |upperroman
+ |lowerroman) #IMPLIED
+ inheritnum (inherit
+ |ignore) "ignore"
+ continuation (continues
+ |restarts) "restarts"
+ spacing (normal
+ |compact) #IMPLIED
+ %common.attrib;
+ %orderedlist.role.attrib;
+ %local.orderedlist.attrib;
>
<!--end of orderedlist.attlist-->]]>
<!--end of orderedlist.module-->]]>
@@ -2265,17 +2265,17 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!--end of listitem.element-->]]>
<!-- Override: Indicates the mark to be used for this ListItem
- instead of the default mark or the mark specified by
- the Mark attribute on the enclosing ItemizedList -->
+ instead of the default mark or the mark specified by
+ the Mark attribute on the enclosing ItemizedList -->
<!ENTITY % listitem.attlist "INCLUDE">
<![%listitem.attlist;[
<!ATTLIST listitem
- override CDATA #IMPLIED
- %common.attrib;
- %listitem.role.attrib;
- %local.listitem.attrib;
+ override CDATA #IMPLIED
+ %common.attrib;
+ %listitem.role.attrib;
+ %local.listitem.attrib;
>
<!--end of listitem.attlist-->]]>
<!--end of listitem.module-->]]>
@@ -2298,9 +2298,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % segmentedlist.attlist "INCLUDE">
<![%segmentedlist.attlist;[
<!ATTLIST segmentedlist
- %common.attrib;
- %segmentedlist.role.attrib;
- %local.segmentedlist.attrib;
+ %common.attrib;
+ %segmentedlist.role.attrib;
+ %local.segmentedlist.attrib;
>
<!--end of segmentedlist.attlist-->]]>
<!--end of segmentedlist.module-->]]>
@@ -2318,9 +2318,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % segtitle.attlist "INCLUDE">
<![%segtitle.attlist;[
<!ATTLIST segtitle
- %common.attrib;
- %segtitle.role.attrib;
- %local.segtitle.attrib;
+ %common.attrib;
+ %segtitle.role.attrib;
+ %local.segtitle.attrib;
>
<!--end of segtitle.attlist-->]]>
<!--end of segtitle.module-->]]>
@@ -2338,9 +2338,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % seglistitem.attlist "INCLUDE">
<![%seglistitem.attlist;[
<!ATTLIST seglistitem
- %common.attrib;
- %seglistitem.role.attrib;
- %local.seglistitem.attrib;
+ %common.attrib;
+ %seglistitem.role.attrib;
+ %local.seglistitem.attrib;
>
<!--end of seglistitem.attlist-->]]>
<!--end of seglistitem.module-->]]>
@@ -2358,9 +2358,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % seg.attlist "INCLUDE">
<![%seg.attlist;[
<!ATTLIST seg
- %common.attrib;
- %seg.role.attrib;
- %local.seg.attrib;
+ %common.attrib;
+ %seg.role.attrib;
+ %local.seg.attrib;
>
<!--end of seg.attlist-->]]>
<!--end of seg.module-->]]>
@@ -2382,23 +2382,23 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!-- Columns: The number of columns the array should contain -->
<!-- Type: How the Members of the SimpleList should be
- formatted: Inline (members separated with commas etc.
- inline), Vert (top to bottom in n Columns), or Horiz (in
- the direction of text flow) in n Columns. If Column
- is 1 or implied, Type=Vert and Type=Horiz give the same
- results. -->
+ formatted: Inline (members separated with commas etc.
+ inline), Vert (top to bottom in n Columns), or Horiz (in
+ the direction of text flow) in n Columns. If Column
+ is 1 or implied, Type=Vert and Type=Horiz give the same
+ results. -->
<!ENTITY % simplelist.attlist "INCLUDE">
<![%simplelist.attlist;[
<!ATTLIST simplelist
- columns CDATA #IMPLIED
- type (inline
- |vert
- |horiz) "vert"
- %common.attrib;
- %simplelist.role.attrib;
- %local.simplelist.attrib;
+ columns CDATA #IMPLIED
+ type (inline
+ |vert
+ |horiz) "vert"
+ %common.attrib;
+ %simplelist.role.attrib;
+ %local.simplelist.attrib;
>
<!--end of simplelist.attlist-->]]>
<!--end of simplelist.module-->]]>
@@ -2416,9 +2416,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % member.attlist "INCLUDE">
<![%member.attlist;[
<!ATTLIST member
- %common.attrib;
- %member.role.attrib;
- %local.member.attrib;
+ %common.attrib;
+ %member.role.attrib;
+ %local.member.attrib;
>
<!--end of member.attlist-->]]>
<!--end of member.module-->]]>
@@ -2436,21 +2436,21 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % variablelist.element "INCLUDE">
<![%variablelist.element;[
<!ELEMENT variablelist %ho; (blockinfo?, (%formalobject.title.content;)?,
- (%listpreamble.mix;)*, varlistentry+)>
+ (%listpreamble.mix;)*, varlistentry+)>
<!--end of variablelist.element-->]]>
<!-- TermLength: Length beyond which the presentation engine
- may consider the Term too long and select an alternate
- presentation of the Term and, or, its associated ListItem. -->
+ may consider the Term too long and select an alternate
+ presentation of the Term and, or, its associated ListItem. -->
<!ENTITY % variablelist.attlist "INCLUDE">
<![%variablelist.attlist;[
<!ATTLIST variablelist
- termlength CDATA #IMPLIED
- %common.attrib;
- %variablelist.role.attrib;
- %local.variablelist.attrib;
+ termlength CDATA #IMPLIED
+ %common.attrib;
+ %variablelist.role.attrib;
+ %local.variablelist.attrib;
>
<!--end of variablelist.attlist-->]]>
<!--end of variablelist.module-->]]>
@@ -2462,15 +2462,15 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % varlistentry.element "INCLUDE">
<![%varlistentry.element;[
-<!ELEMENT varlistentry %ho; (term+, listitem)>
+<!ELEMENT varlistentry %ho; (term+, listitem+)>
<!--end of varlistentry.element-->]]>
<!ENTITY % varlistentry.attlist "INCLUDE">
<![%varlistentry.attlist;[
<!ATTLIST varlistentry
- %common.attrib;
- %varlistentry.role.attrib;
- %local.varlistentry.attrib;
+ %common.attrib;
+ %varlistentry.role.attrib;
+ %local.varlistentry.attrib;
>
<!--end of varlistentry.attlist-->]]>
<!--end of varlistentry.module-->]]>
@@ -2488,9 +2488,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % term.attlist "INCLUDE">
<![%term.attlist;[
<!ATTLIST term
- %common.attrib;
- %term.role.attrib;
- %local.term.attrib;
+ %common.attrib;
+ %term.role.attrib;
+ %local.term.attrib;
>
<!--end of term.attlist-->]]>
<!--end of term.module-->]]>
@@ -2515,9 +2515,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % calloutlist.attlist "INCLUDE">
<![%calloutlist.attlist;[
<!ATTLIST calloutlist
- %common.attrib;
- %calloutlist.role.attrib;
- %local.calloutlist.attrib;
+ %common.attrib;
+ %calloutlist.role.attrib;
+ %local.calloutlist.attrib;
>
<!--end of calloutlist.attlist-->]]>
<!--end of calloutlist.module-->]]>
@@ -2533,16 +2533,16 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!--end of callout.element-->]]>
<!-- AreaRefs: IDs of one or more Areas or AreaSets described
- by this Callout -->
+ by this Callout -->
<!ENTITY % callout.attlist "INCLUDE">
<![%callout.attlist;[
<!ATTLIST callout
- arearefs IDREFS #REQUIRED
- %common.attrib;
- %callout.role.attrib;
- %local.callout.attrib;
+ arearefs IDREFS #REQUIRED
+ %common.attrib;
+ %callout.role.attrib;
+ %local.callout.attrib;
>
<!--end of callout.attlist-->]]>
<!--end of callout.module-->]]>
@@ -2561,17 +2561,17 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % example.element "INCLUDE">
<![%example.element;[
<!ELEMENT example %ho; (blockinfo?, (%formalobject.title.content;), (%example.mix;)+)
- %formal.exclusion;>
+ %formal.exclusion;>
<!--end of example.element-->]]>
<!ENTITY % example.attlist "INCLUDE">
<![%example.attlist;[
<!ATTLIST example
- %label.attrib;
- %width.attrib;
- %common.attrib;
- %example.role.attrib;
- %local.example.attrib;
+ %label.attrib;
+ %width.attrib;
+ %common.attrib;
+ %example.role.attrib;
+ %local.example.attrib;
>
<!--end of example.attlist-->]]>
<!--end of example.module-->]]>
@@ -2589,10 +2589,10 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % informalexample.attlist "INCLUDE">
<![%informalexample.attlist;[
<!ATTLIST informalexample
- %width.attrib;
- %common.attrib;
- %informalexample.role.attrib;
- %local.informalexample.attrib;
+ %width.attrib;
+ %common.attrib;
+ %informalexample.role.attrib;
+ %local.informalexample.attrib;
>
<!--end of informalexample.attlist-->]]>
<!--end of informalexample.module-->]]>
@@ -2610,9 +2610,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % programlistingco.attlist "INCLUDE">
<![%programlistingco.attlist;[
<!ATTLIST programlistingco
- %common.attrib;
- %programlistingco.role.attrib;
- %local.programlistingco.attrib;
+ %common.attrib;
+ %programlistingco.role.attrib;
+ %local.programlistingco.attrib;
>
<!--end of programlistingco.attlist-->]]>
<!-- CalloutList (defined above in Lists)-->
@@ -2631,45 +2631,45 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!--end of areaspec.element-->]]>
<!-- Units: global unit of measure in which coordinates in
- this spec are expressed:
+ this spec are expressed:
- - CALSPair "x1,y1 x2,y2": lower-left and upper-right
- coordinates in a rectangle describing repro area in which
- graphic is placed, where X and Y dimensions are each some
- number 0..10000 (taken from CALS graphic attributes)
+ - CALSPair "x1,y1 x2,y2": lower-left and upper-right
+ coordinates in a rectangle describing repro area in which
+ graphic is placed, where X and Y dimensions are each some
+ number 0..10000 (taken from CALS graphic attributes)
- - LineColumn "line column": line number and column number
- at which to start callout text in "linespecific" content
+ - LineColumn "line column": line number and column number
+ at which to start callout text in "linespecific" content
- - LineRange "startline endline": whole lines from startline
- to endline in "linespecific" content
+ - LineRange "startline endline": whole lines from startline
+ to endline in "linespecific" content
- - LineColumnPair "line1 col1 line2 col2": starting and ending
- points of area in "linespecific" content that starts at
- first position and ends at second position (including the
- beginnings of any intervening lines)
+ - LineColumnPair "line1 col1 line2 col2": starting and ending
+ points of area in "linespecific" content that starts at
+ first position and ends at second position (including the
+ beginnings of any intervening lines)
- - Other: directive to look at value of OtherUnits attribute
- to get implementation-specific keyword
+ - Other: directive to look at value of OtherUnits attribute
+ to get implementation-specific keyword
- The default is implementation-specific; usually dependent on
- the parent element (GraphicCO gets CALSPair, ProgramListingCO
- and ScreenCO get LineColumn) -->
+ The default is implementation-specific; usually dependent on
+ the parent element (GraphicCO gets CALSPair, ProgramListingCO
+ and ScreenCO get LineColumn) -->
<!-- OtherUnits: User-defined units -->
<!ENTITY % areaspec.attlist "INCLUDE">
<![%areaspec.attlist;[
<!ATTLIST areaspec
- units (calspair
- |linecolumn
- |linerange
- |linecolumnpair
- |other) #IMPLIED
- otherunits NMTOKEN #IMPLIED
- %common.attrib;
- %areaspec.role.attrib;
- %local.areaspec.attrib;
+ units (calspair
+ |linecolumn
+ |linerange
+ |linecolumnpair
+ |other) #IMPLIED
+ otherunits NMTOKEN #IMPLIED
+ %common.attrib;
+ %areaspec.role.attrib;
+ %local.areaspec.attrib;
>
<!--end of areaspec.attlist-->]]>
<!--end of areaspec.module-->]]>
@@ -2687,25 +2687,25 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!-- bug number/symbol override or initialization -->
<!-- to any related information -->
<!-- Units: unit of measure in which coordinates in this
- area are expressed; inherits from AreaSet and AreaSpec -->
+ area are expressed; inherits from AreaSet and AreaSpec -->
<!-- OtherUnits: User-defined units -->
<!ENTITY % area.attlist "INCLUDE">
<![%area.attlist;[
<!ATTLIST area
- %label.attrib;
- %linkends.attrib;
- units (calspair
- |linecolumn
- |linerange
- |linecolumnpair
- |other) #IMPLIED
- otherunits NMTOKEN #IMPLIED
- coords CDATA #REQUIRED
- %idreq.common.attrib;
- %area.role.attrib;
- %local.area.attrib;
+ %label.attrib;
+ %linkends.attrib;
+ units (calspair
+ |linecolumn
+ |linerange
+ |linecolumnpair
+ |other) #IMPLIED
+ otherunits NMTOKEN #IMPLIED
+ coords CDATA #REQUIRED
+ %idreq.common.attrib;
+ %area.role.attrib;
+ %local.area.attrib;
>
<!--end of area.attlist-->]]>
<!--end of area.module-->]]>
@@ -2722,23 +2722,23 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!-- bug number/symbol override or initialization -->
<!-- Units: unit of measure in which coordinates in this
- area are expressed; inherits from AreaSpec -->
+ area are expressed; inherits from AreaSpec -->
<!ENTITY % areaset.attlist "INCLUDE">
<![%areaset.attlist;[
<!ATTLIST areaset
- %label.attrib;
- units (calspair
- |linecolumn
- |linerange
- |linecolumnpair
- |other) #IMPLIED
- otherunits NMTOKEN #IMPLIED
- coords CDATA #REQUIRED
- %idreq.common.attrib;
- %areaset.role.attrib;
- %local.areaset.attrib;
+ %label.attrib;
+ units (calspair
+ |linecolumn
+ |linerange
+ |linecolumnpair
+ |other) #IMPLIED
+ otherunits NMTOKEN #IMPLIED
+ coords CDATA #REQUIRED
+ %idreq.common.attrib;
+ %areaset.role.attrib;
+ %local.areaset.attrib;
>
<!--end of areaset.attlist-->]]>
<!--end of areaset.module-->]]>
@@ -2757,11 +2757,11 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % programlisting.attlist "INCLUDE">
<![%programlisting.attlist;[
<!ATTLIST programlisting
- %width.attrib;
- %linespecific.attrib;
- %common.attrib;
- %programlisting.role.attrib;
- %local.programlisting.attrib;
+ %width.attrib;
+ %linespecific.attrib;
+ %common.attrib;
+ %programlisting.role.attrib;
+ %local.programlisting.attrib;
>
<!--end of programlisting.attlist-->]]>
<!--end of programlisting.module-->]]>
@@ -2779,12 +2779,12 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % literallayout.attlist "INCLUDE">
<![%literallayout.attlist;[
<!ATTLIST literallayout
- %width.attrib;
- %linespecific.attrib;
- class (monospaced|normal) "normal"
- %common.attrib;
- %literallayout.role.attrib;
- %local.literallayout.attrib;
+ %width.attrib;
+ %linespecific.attrib;
+ class (monospaced|normal) "normal"
+ %common.attrib;
+ %literallayout.role.attrib;
+ %local.literallayout.attrib;
>
<!--end of literallayout.attlist-->]]>
<!-- LineAnnotation (defined in the Inlines section, below)-->
@@ -2803,9 +2803,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % screenco.attlist "INCLUDE">
<![%screenco.attlist;[
<!ATTLIST screenco
- %common.attrib;
- %screenco.role.attrib;
- %local.screenco.attrib;
+ %common.attrib;
+ %screenco.role.attrib;
+ %local.screenco.attrib;
>
<!--end of screenco.attlist-->]]>
<!-- AreaSpec (defined above)-->
@@ -2825,11 +2825,11 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % screen.attlist "INCLUDE">
<![%screen.attlist;[
<!ATTLIST screen
- %width.attrib;
- %linespecific.attrib;
- %common.attrib;
- %screen.role.attrib;
- %local.screen.attrib;
+ %width.attrib;
+ %linespecific.attrib;
+ %common.attrib;
+ %screen.role.attrib;
+ %local.screen.attrib;
>
<!--end of screen.attlist-->]]>
<!--end of screen.module-->]]>
@@ -2851,9 +2851,9 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % screenshot.attlist "INCLUDE">
<![%screenshot.attlist;[
<!ATTLIST screenshot
- %common.attrib;
- %screenshot.role.attrib;
- %local.screenshot.attrib;
+ %common.attrib;
+ %screenshot.role.attrib;
+ %local.screenshot.attrib;
>
<!--end of screenshot.attlist-->]]>
<!--end of screenshot.module-->]]>
@@ -2866,15 +2866,15 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!ENTITY % screeninfo.element "INCLUDE">
<![%screeninfo.element;[
<!ELEMENT screeninfo %ho; (%para.char.mix;)*
- %ubiq.exclusion;>
+ %ubiq.exclusion;>
<!--end of screeninfo.element-->]]>
<!ENTITY % screeninfo.attlist "INCLUDE">
<![%screeninfo.attlist;[
<!ATTLIST screeninfo
- %common.attrib;
- %screeninfo.role.attrib;
- %local.screeninfo.attrib;
+ %common.attrib;
+ %screeninfo.role.attrib;
+ %local.screeninfo.attrib;
>
<!--end of screeninfo.attlist-->]]>
<!--end of screeninfo.module-->]]>
@@ -2894,19 +2894,19 @@ d. Just Acronym, Emphasis, and Trademark; no other word elements.
<!--end of figure.element-->]]>
<!-- Float: Whether the Figure is supposed to be rendered
- where convenient (yes (1) value) or at the place it occurs
- in the text (no (0) value, the default) -->
+ where convenient (yes (1) value) or at the place it occurs
+ in the text (no (0) value, the default) -->
<!ENTITY % figure.attlist "INCLUDE">
<![%figure.attlist;[
<!ATTLIST figure
- float %yesorno.attvals; '0'
- pgwide %yesorno.attvals; #IMPLIED
- %label.attrib;
- %common.attrib;
- %figure.role.attrib;
- %local.figure.attrib;
+ float %yesorno.attvals; '0'
+ pgwide %yesorno.attvals; #IMPLIED
+ %label.attrib;
+ %common.attrib;
+ %figure.role.attrib;
+ %local.figure.attrib;
>
<!--end of figure.attlist-->]]>
<!--end of figure.module-->]]>
@@ -2929,12 +2929,12 @@ where convenient (yes (1) value) or at the place it occurs
in the text (no (0) value, the default)
-->
<!ATTLIST informalfigure
- float %yesorno.attvals; "0"
- pgwide %yesorno.attvals; #IMPLIED
- %label.attrib;
- %common.attrib;
- %informalfigure.role.attrib;
- %local.informalfigure.attrib;
+ float %yesorno.attvals; "0"
+ pgwide %yesorno.attvals; #IMPLIED
+ %label.attrib;
+ %common.attrib;
+ %informalfigure.role.attrib;
+ %local.informalfigure.attrib;
>
<!--end of informalfigure.attlist-->]]>
<!--end of informalfigure.module-->]]>
@@ -2952,9 +2952,9 @@ in the text (no (0) value, the default)
<!ENTITY % graphicco.attlist "INCLUDE">
<![%graphicco.attlist;[
<!ATTLIST graphicco
- %common.attrib;
- %graphicco.role.attrib;
- %local.graphicco.attrib;
+ %common.attrib;
+ %graphicco.role.attrib;
+ %local.graphicco.attrib;
>
<!--end of graphicco.attlist-->]]>
<!-- AreaSpec (defined above in Examples)-->
@@ -2978,10 +2978,10 @@ in the text (no (0) value, the default)
<!ENTITY % graphic.attlist "INCLUDE">
<![%graphic.attlist;[
<!ATTLIST graphic
- %graphics.attrib;
- %common.attrib;
- %graphic.role.attrib;
- %local.graphic.attrib;
+ %graphics.attrib;
+ %common.attrib;
+ %graphic.role.attrib;
+ %local.graphic.attrib;
>
<!--end of graphic.attlist-->]]>
<!--end of graphic.module-->]]>
@@ -2999,10 +2999,10 @@ in the text (no (0) value, the default)
<!ENTITY % inlinegraphic.attlist "INCLUDE">
<![%inlinegraphic.attlist;[
<!ATTLIST inlinegraphic
- %graphics.attrib;
- %common.attrib;
- %inlinegraphic.role.attrib;
- %local.inlinegraphic.attrib;
+ %graphics.attrib;
+ %common.attrib;
+ %inlinegraphic.role.attrib;
+ %local.inlinegraphic.attrib;
>
<!--end of inlinegraphic.attlist-->]]>
<!--end of inlinegraphic.module-->]]>
@@ -3019,15 +3019,15 @@ in the text (no (0) value, the default)
<![ %mediaobject.element; [
<!ELEMENT mediaobject %ho; (objectinfo?,
(%mediaobject.mix;)+,
- caption?)>
+ caption?)>
<!--end of mediaobject.element-->]]>
<!ENTITY % mediaobject.attlist "INCLUDE">
<![ %mediaobject.attlist; [
<!ATTLIST mediaobject
- %common.attrib;
- %mediaobject.role.attrib;
- %local.mediaobject.attrib;
+ %common.attrib;
+ %mediaobject.role.attrib;
+ %local.mediaobject.attrib;
>
<!--end of mediaobject.attlist-->]]>
<!--end of mediaobject.module-->]]>
@@ -3040,15 +3040,15 @@ in the text (no (0) value, the default)
<!ENTITY % inlinemediaobject.element "INCLUDE">
<![ %inlinemediaobject.element; [
<!ELEMENT inlinemediaobject %ho; (objectinfo?,
- (%mediaobject.mix;)+)>
+ (%mediaobject.mix;)+)>
<!--end of inlinemediaobject.element-->]]>
<!ENTITY % inlinemediaobject.attlist "INCLUDE">
<![ %inlinemediaobject.attlist; [
<!ATTLIST inlinemediaobject
- %common.attrib;
- %inlinemediaobject.role.attrib;
- %local.inlinemediaobject.attrib;
+ %common.attrib;
+ %inlinemediaobject.role.attrib;
+ %local.inlinemediaobject.attrib;
>
<!--end of inlinemediaobject.attlist-->]]>
<!--end of inlinemediaobject.module-->]]>
@@ -3066,9 +3066,9 @@ in the text (no (0) value, the default)
<!ENTITY % videoobject.attlist "INCLUDE">
<![ %videoobject.attlist; [
<!ATTLIST videoobject
- %common.attrib;
- %videoobject.role.attrib;
- %local.videoobject.attrib;
+ %common.attrib;
+ %videoobject.role.attrib;
+ %local.videoobject.attrib;
>
<!--end of videoobject.attlist-->]]>
<!--end of videoobject.module-->]]>
@@ -3086,9 +3086,9 @@ in the text (no (0) value, the default)
<!ENTITY % audioobject.attlist "INCLUDE">
<![ %audioobject.attlist; [
<!ATTLIST audioobject
- %common.attrib;
- %audioobject.role.attrib;
- %local.audioobject.attrib;
+ %common.attrib;
+ %audioobject.role.attrib;
+ %local.audioobject.attrib;
>
<!--end of audioobject.attlist-->]]>
<!--end of audioobject.module-->]]>
@@ -3106,9 +3106,9 @@ in the text (no (0) value, the default)
<!ENTITY % imageobject.attlist "INCLUDE">
<![ %imageobject.attlist; [
<!ATTLIST imageobject
- %common.attrib;
- %imageobject.role.attrib;
- %local.imageobject.attrib;
+ %common.attrib;
+ %imageobject.role.attrib;
+ %local.imageobject.attrib;
>
<!--end of imageobject.attlist-->]]>
<!--end of imageobject.module-->]]>
@@ -3126,9 +3126,9 @@ in the text (no (0) value, the default)
<!ENTITY % textobject.attlist "INCLUDE">
<![ %textobject.attlist; [
<!ATTLIST textobject
- %common.attrib;
- %textobject.role.attrib;
- %local.textobject.attrib;
+ %common.attrib;
+ %textobject.role.attrib;
+ %local.textobject.attrib;
>
<!--end of textobject.attlist-->]]>
<!--end of textobject.module-->]]>
@@ -3141,34 +3141,34 @@ in the text (no (0) value, the default)
<!ENTITY % objectinfo.element "INCLUDE">
<![ %objectinfo.element; [
<!ELEMENT objectinfo %ho; ((%info.class;)+)
- %beginpage.exclusion;>
+ %beginpage.exclusion;>
<!--end of objectinfo.element-->]]>
<!ENTITY % objectinfo.attlist "INCLUDE">
<![ %objectinfo.attlist; [
<!ATTLIST objectinfo
- %common.attrib;
- %objectinfo.role.attrib;
- %local.objectinfo.attrib;
+ %common.attrib;
+ %objectinfo.role.attrib;
+ %local.objectinfo.attrib;
>
<!--end of objectinfo.attlist-->]]>
<!--end of objectinfo.module-->]]>
<!--EntityRef: Name of an external entity containing the content
- of the object data-->
+ of the object data-->
<!--FileRef: Filename, qualified by a pathname if desired,
- designating the file containing the content of the object data-->
+ designating the file containing the content of the object data-->
<!--Format: Notation of the element content, if any-->
<!--SrcCredit: Information about the source of the image-->
<!ENTITY % local.objectdata.attrib "">
<!ENTITY % objectdata.attrib
- "
- entityref ENTITY #IMPLIED
- fileref CDATA #IMPLIED
- format (%notation.class;)
- #IMPLIED
- srccredit CDATA #IMPLIED
- %local.objectdata.attrib;"
+ "
+ entityref ENTITY #IMPLIED
+ fileref CDATA #IMPLIED
+ format (%notation.class;)
+ #IMPLIED
+ srccredit CDATA #IMPLIED
+ %local.objectdata.attrib;"
>
<!ENTITY % videodata.module "INCLUDE">
@@ -3187,27 +3187,27 @@ in the text (no (0) value, the default)
<!--Width: Same as CALS reprowid (desired width)-->
<!--Depth: Same as CALS reprodep (desired depth)-->
<!--Align: Same as CALS hplace with 'none' removed; #IMPLIED means
- application-specific-->
+ application-specific-->
<!--Scale: Conflation of CALS hscale and vscale-->
<!--Scalefit: Same as CALS scalefit-->
<!ATTLIST videodata
- width CDATA #IMPLIED
- contentwidth CDATA #IMPLIED
- depth CDATA #IMPLIED
- contentdepth CDATA #IMPLIED
- align (left
- |right
- |center) #IMPLIED
- valign (top
- |middle
- |bottom) #IMPLIED
- scale CDATA #IMPLIED
- scalefit %yesorno.attvals;
- #IMPLIED
- %objectdata.attrib;
- %common.attrib;
- %videodata.role.attrib;
- %local.videodata.attrib;
+ width CDATA #IMPLIED
+ contentwidth CDATA #IMPLIED
+ depth CDATA #IMPLIED
+ contentdepth CDATA #IMPLIED
+ align (left
+ |right
+ |center) #IMPLIED
+ valign (top
+ |middle
+ |bottom) #IMPLIED
+ scale CDATA #IMPLIED
+ scalefit %yesorno.attvals;
+ #IMPLIED
+ %objectdata.attrib;
+ %common.attrib;
+ %videodata.role.attrib;
+ %local.videodata.attrib;
>
<!--end of videodata.attlist-->]]>
<!--end of videodata.module-->]]>
@@ -3225,10 +3225,10 @@ in the text (no (0) value, the default)
<!ENTITY % audiodata.attlist "INCLUDE">
<![ %audiodata.attlist; [
<!ATTLIST audiodata
- %objectdata.attrib;
- %common.attrib;
- %audiodata.role.attrib;
- %local.audiodata.attrib;
+ %objectdata.attrib;
+ %common.attrib;
+ %audiodata.role.attrib;
+ %local.audiodata.attrib;
>
<!--end of audiodata.attlist-->]]>
<!--end of audiodata.module-->]]>
@@ -3249,27 +3249,27 @@ in the text (no (0) value, the default)
<!--Width: Same as CALS reprowid (desired width)-->
<!--Depth: Same as CALS reprodep (desired depth)-->
<!--Align: Same as CALS hplace with 'none' removed; #IMPLIED means
- application-specific-->
+ application-specific-->
<!--Scale: Conflation of CALS hscale and vscale-->
<!--Scalefit: Same as CALS scalefit-->
<!ATTLIST imagedata
- width CDATA #IMPLIED
- contentwidth CDATA #IMPLIED
- depth CDATA #IMPLIED
- contentdepth CDATA #IMPLIED
- align (left
- |right
- |center) #IMPLIED
- valign (top
- |middle
- |bottom) #IMPLIED
- scale CDATA #IMPLIED
- scalefit %yesorno.attvals;
- #IMPLIED
- %objectdata.attrib;
- %common.attrib;
- %imagedata.role.attrib;
- %local.imagedata.attrib;
+ width CDATA #IMPLIED
+ contentwidth CDATA #IMPLIED
+ depth CDATA #IMPLIED
+ contentdepth CDATA #IMPLIED
+ align (left
+ |right
+ |center) #IMPLIED
+ valign (top
+ |middle
+ |bottom) #IMPLIED
+ scale CDATA #IMPLIED
+ scalefit %yesorno.attvals;
+ #IMPLIED
+ %objectdata.attrib;
+ %common.attrib;
+ %imagedata.role.attrib;
+ %local.imagedata.attrib;
>
<!--end of imagedata.attlist-->]]>
<!--end of imagedata.module-->]]>
@@ -3287,11 +3287,11 @@ in the text (no (0) value, the default)
<!ENTITY % textdata.attlist "INCLUDE">
<![ %textdata.attlist; [
<!ATTLIST textdata
- encoding CDATA #IMPLIED
- %objectdata.attrib;
- %common.attrib;
- %textdata.role.attrib;
- %local.textdata.attrib;
+ encoding CDATA #IMPLIED
+ %objectdata.attrib;
+ %common.attrib;
+ %textdata.role.attrib;
+ %local.textdata.attrib;
>
<!--end of textdata.attlist-->]]>
<!--end of textdata.module-->]]>
@@ -3309,9 +3309,9 @@ in the text (no (0) value, the default)
<!ENTITY % caption.attlist "INCLUDE">
<![ %caption.attlist; [
<!ATTLIST caption
- %common.attrib;
- %caption.role.attrib;
- %local.caption.attrib;
+ %common.attrib;
+ %caption.role.attrib;
+ %local.caption.attrib;
>
<!--end of caption.attlist-->]]>
<!--end of caption.module-->]]>
@@ -3324,15 +3324,15 @@ in the text (no (0) value, the default)
<!ENTITY % mediaobjectco.element "INCLUDE">
<![ %mediaobjectco.element; [
<!ELEMENT mediaobjectco %ho; (objectinfo?, imageobjectco,
- (imageobjectco|textobject)*)>
+ (imageobjectco|textobject)*)>
<!--end of mediaobjectco.element-->]]>
<!ENTITY % mediaobjectco.attlist "INCLUDE">
<![ %mediaobjectco.attlist; [
<!ATTLIST mediaobjectco
- %common.attrib;
- %mediaobjectco.role.attrib;
- %local.mediaobjectco.attrib;
+ %common.attrib;
+ %mediaobjectco.role.attrib;
+ %local.mediaobjectco.attrib;
>
<!--end of mediaobjectco.attlist-->]]>
<!--end of mediaobjectco.module-->]]>
@@ -3350,9 +3350,9 @@ in the text (no (0) value, the default)
<!ENTITY % imageobjectco.attlist "INCLUDE">
<![ %imageobjectco.attlist; [
<!ATTLIST imageobjectco
- %common.attrib;
- %imageobjectco.role.attrib;
- %local.imageobjectco.attrib;
+ %common.attrib;
+ %imageobjectco.role.attrib;
+ %local.imageobjectco.attrib;
>
<!--end of imageobjectco.attlist-->]]>
<!--end of imageobjectco.module-->]]>
@@ -3379,10 +3379,10 @@ in the text (no (0) value, the default)
<!ENTITY % equation.attlist "INCLUDE">
<![%equation.attlist;[
<!ATTLIST equation
- %label.attrib;
- %common.attrib;
- %equation.role.attrib;
- %local.equation.attrib;
+ %label.attrib;
+ %common.attrib;
+ %equation.role.attrib;
+ %local.equation.attrib;
>
<!--end of equation.attlist-->]]>
<!--end of equation.module-->]]>
@@ -3400,9 +3400,9 @@ in the text (no (0) value, the default)
<!ENTITY % informalequation.attlist "INCLUDE">
<![%informalequation.attlist;[
<!ATTLIST informalequation
- %common.attrib;
- %informalequation.role.attrib;
- %local.informalequation.attrib;
+ %common.attrib;
+ %informalequation.role.attrib;
+ %local.informalequation.attrib;
>
<!--end of informalequation.attlist-->]]>
<!--end of informalequation.module-->]]>
@@ -3420,9 +3420,9 @@ in the text (no (0) value, the default)
<!ENTITY % inlineequation.attlist "INCLUDE">
<![%inlineequation.attlist;[
<!ATTLIST inlineequation
- %common.attrib;
- %inlineequation.role.attrib;
- %local.inlineequation.attrib;
+ %common.attrib;
+ %inlineequation.role.attrib;
+ %local.inlineequation.attrib;
>
<!--end of inlineequation.attlist-->]]>
<!--end of inlineequation.module-->]]>
@@ -3440,9 +3440,9 @@ in the text (no (0) value, the default)
<!ENTITY % alt.attlist "INCLUDE">
<![%alt.attlist;[
<!ATTLIST alt
- %common.attrib;
- %alt.role.attrib;
- %local.alt.attrib;
+ %common.attrib;
+ %alt.role.attrib;
+ %local.alt.attrib;
>
<!--end of alt.attlist-->]]>
<!--end of alt.module-->]]>
@@ -3469,17 +3469,17 @@ in the text (no (0) value, the default)
<!-- Add common attributes to Table, TGroup, TBody, THead, TFoot, Row,
EntryTbl, and Entry (and InformalTable element). -->
<!ENTITY % secur
- "%common.attrib;
- %tables.role.attrib;">
+ "%common.attrib;
+ %tables.role.attrib;">
<!ENTITY % common.table.attribs
- "%bodyatt;
- %secur;">
+ "%bodyatt;
+ %secur;">
<!-- Content model for Table. -->
<!ENTITY % tbl.table.mdl
- "(blockinfo?, (%formalobject.title.content;), (%ndxterm.class;)*,
- textobject*,
+ "(blockinfo?, (%formalobject.title.content;), (%ndxterm.class;)*,
+ textobject*,
(graphic+|mediaobject+|tgroup+))">
<!-- Allow either objects or inlines; beware of REs between elements. -->
@@ -3495,12 +3495,12 @@ in the text (no (0) value, the default)
<!-- Add common attributes and the Label attribute to Table and -->
<!-- InformalTable. -->
<!ENTITY % bodyatt
- "%common.attrib;
- %label.attrib;
- %tables.role.attrib;">
+ "%common.attrib;
+ %label.attrib;
+ %tables.role.attrib;">
<!ENTITY % common.table.attribs
- "%bodyatt;">
+ "%bodyatt;">
<!-- Add common attributes to TGroup, ColSpec, TBody, THead, Row, Entry -->
@@ -3513,8 +3513,8 @@ in the text (no (0) value, the default)
<!-- Content model for Table. -->
<!ENTITY % tbl.table.mdl
- "(blockinfo?, (%formalobject.title.content;), (%ndxterm.class;)*,
- textobject*,
+ "(blockinfo?, (%formalobject.title.content;), (%ndxterm.class;)*,
+ textobject*,
(graphic+|mediaobject+|tgroup+))">
<!-- Allow either objects or inlines; beware of REs between elements. -->
@@ -3544,9 +3544,9 @@ in the text (no (0) value, the default)
<!--end of informaltable.element-->]]>
<!-- Frame, Colsep, and Rowsep must be repeated because
- they are not in entities in the table module. -->
+ they are not in entities in the table module. -->
<!-- includes TabStyle, ToCentry, ShortEntry,
- Orient, PgWide -->
+ Orient, PgWide -->
<!-- includes Label -->
<!-- includes common attributes -->
@@ -3554,17 +3554,17 @@ in the text (no (0) value, the default)
<!ENTITY % informaltable.attlist "INCLUDE">
<![%informaltable.attlist;[
<!ATTLIST informaltable
- frame (top
- |bottom
- |topbot
- |all
- |sides
- |none) #IMPLIED
- colsep %yesorno.attvals; #IMPLIED
- rowsep %yesorno.attvals; #IMPLIED
- %common.table.attribs;
- %tbl.table.att;
- %local.informaltable.attrib;
+ frame (top
+ |bottom
+ |topbot
+ |all
+ |sides
+ |none) #IMPLIED
+ colsep %yesorno.attvals; #IMPLIED
+ rowsep %yesorno.attvals; #IMPLIED
+ %common.table.attribs;
+ %tbl.table.att;
+ %local.informaltable.attrib;
>
<!--end of informaltable.attlist-->]]>
<!--end of informaltable.module-->]]>
@@ -3587,11 +3587,11 @@ in the text (no (0) value, the default)
<!ENTITY % synopsis.attlist "INCLUDE">
<![%synopsis.attlist;[
<!ATTLIST synopsis
- %label.attrib;
- %linespecific.attrib;
- %common.attrib;
- %synopsis.role.attrib;
- %local.synopsis.attrib;
+ %label.attrib;
+ %linespecific.attrib;
+ %common.attrib;
+ %synopsis.role.attrib;
+ %local.synopsis.attrib;
>
<!--end of synopsis.attlist-->]]>
@@ -3613,18 +3613,18 @@ in the text (no (0) value, the default)
<!--end of cmdsynopsis.element-->]]>
<!-- Sepchar: Character that should separate command and all
- top-level arguments; alternate value might be e.g., Δ -->
+ top-level arguments; alternate value might be e.g., Δ -->
<!ENTITY % cmdsynopsis.attlist "INCLUDE">
<![%cmdsynopsis.attlist;[
<!ATTLIST cmdsynopsis
- %label.attrib;
- sepchar CDATA " "
- cmdlength CDATA #IMPLIED
- %common.attrib;
- %cmdsynopsis.role.attrib;
- %local.cmdsynopsis.attrib;
+ %label.attrib;
+ sepchar CDATA " "
+ cmdlength CDATA #IMPLIED
+ %common.attrib;
+ %cmdsynopsis.role.attrib;
+ %local.cmdsynopsis.attrib;
>
<!--end of cmdsynopsis.attlist-->]]>
<!--end of cmdsynopsis.module-->]]>
@@ -3637,32 +3637,32 @@ in the text (no (0) value, the default)
<!ENTITY % arg.element "INCLUDE">
<![%arg.element;[
<!ELEMENT arg %ho; (#PCDATA
- | arg
- | group
- | option
- | synopfragmentref
- | replaceable
- | sbr)*>
+ | arg
+ | group
+ | option
+ | synopfragmentref
+ | replaceable
+ | sbr)*>
<!--end of arg.element-->]]>
<!-- Choice: Whether Arg must be supplied: Opt (optional to
- supply, e.g. [arg]; the default), Req (required to supply,
- e.g. {arg}), or Plain (required to supply, e.g. arg) -->
+ supply, e.g. [arg]; the default), Req (required to supply,
+ e.g. {arg}), or Plain (required to supply, e.g. arg) -->
<!-- Rep: whether Arg is repeatable: Norepeat (e.g. arg without
- ellipsis; the default), or Repeat (e.g. arg...) -->
+ ellipsis; the default), or Repeat (e.g. arg...) -->
<!ENTITY % arg.attlist "INCLUDE">
<![%arg.attlist;[
<!ATTLIST arg
- choice (opt
- |req
- |plain) 'opt'
- rep (norepeat
- |repeat) 'norepeat'
- %common.attrib;
- %arg.role.attrib;
- %local.arg.attrib;
+ choice (opt
+ |req
+ |plain) 'opt'
+ rep (norepeat
+ |repeat) 'norepeat'
+ %common.attrib;
+ %arg.role.attrib;
+ %local.arg.attrib;
>
<!--end of arg.attlist-->]]>
<!--end of arg.module-->]]>
@@ -3676,30 +3676,30 @@ in the text (no (0) value, the default)
<!ENTITY % group.element "INCLUDE">
<![%group.element;[
<!ELEMENT group %ho; ((arg | group | option | synopfragmentref
- | replaceable | sbr)+)>
+ | replaceable | sbr)+)>
<!--end of group.element-->]]>
<!-- Choice: Whether Group must be supplied: Opt (optional to
- supply, e.g. [g1|g2|g3]; the default), Req (required to
- supply, e.g. {g1|g2|g3}), Plain (required to supply,
- e.g. g1|g2|g3), OptMult (can supply zero or more, e.g.
- [[g1|g2|g3]]), or ReqMult (must supply one or more, e.g.
- {{g1|g2|g3}}) -->
+ supply, e.g. [g1|g2|g3]; the default), Req (required to
+ supply, e.g. {g1|g2|g3}), Plain (required to supply,
+ e.g. g1|g2|g3), OptMult (can supply zero or more, e.g.
+ [[g1|g2|g3]]), or ReqMult (must supply one or more, e.g.
+ {{g1|g2|g3}}) -->
<!-- Rep: whether Group is repeatable: Norepeat (e.g. group
- without ellipsis; the default), or Repeat (e.g. group...) -->
+ without ellipsis; the default), or Repeat (e.g. group...) -->
<!ENTITY % group.attlist "INCLUDE">
<![%group.attlist;[
<!ATTLIST group
- choice (opt
- |req
- |plain) 'opt'
- rep (norepeat
- |repeat) 'norepeat'
- %common.attrib;
- %group.role.attrib;
- %local.group.attrib;
+ choice (opt
+ |req
+ |plain) 'opt'
+ rep (norepeat
+ |repeat) 'norepeat'
+ %common.attrib;
+ %group.role.attrib;
+ %local.group.attrib;
>
<!--end of group.attlist-->]]>
<!--end of group.module-->]]>
@@ -3718,9 +3718,9 @@ in the text (no (0) value, the default)
<!ENTITY % sbr.attlist "INCLUDE">
<![%sbr.attlist;[
<!ATTLIST sbr
- %common.attrib;
- %sbr.role.attrib;
- %local.sbr.attrib;
+ %common.attrib;
+ %sbr.role.attrib;
+ %local.sbr.attrib;
>
<!--end of sbr.attlist-->]]>
<!--end of sbr.module-->]]>
@@ -3736,15 +3736,15 @@ in the text (no (0) value, the default)
<!--end of synopfragmentref.element-->]]>
<!-- to SynopFragment of complex synopsis
- material for separate referencing -->
+ material for separate referencing -->
<!ENTITY % synopfragmentref.attlist "INCLUDE">
<![%synopfragmentref.attlist;[
<!ATTLIST synopfragmentref
- %linkendreq.attrib; %common.attrib;
- %synopfragmentref.role.attrib;
- %local.synopfragmentref.attrib;
+ %linkendreq.attrib; %common.attrib;
+ %synopfragmentref.role.attrib;
+ %local.synopfragmentref.attrib;
>
<!--end of synopfragmentref.attlist-->]]>
<!--end of synopfragmentref.module-->]]>
@@ -3762,9 +3762,9 @@ in the text (no (0) value, the default)
<!ENTITY % synopfragment.attlist "INCLUDE">
<![%synopfragment.attlist;[
<!ATTLIST synopfragment
- %idreq.common.attrib;
- %synopfragment.role.attrib;
- %local.synopfragment.attrib;
+ %idreq.common.attrib;
+ %synopfragment.role.attrib;
+ %local.synopfragment.attrib;
>
<!--end of synopfragment.attlist-->]]>
<!--end of synopfragment.module-->]]>
@@ -3792,10 +3792,10 @@ in the text (no (0) value, the default)
<!ENTITY % funcsynopsis.attlist "INCLUDE">
<![%funcsynopsis.attlist;[
<!ATTLIST funcsynopsis
- %label.attrib;
- %common.attrib;
- %funcsynopsis.role.attrib;
- %local.funcsynopsis.attrib;
+ %label.attrib;
+ %common.attrib;
+ %funcsynopsis.role.attrib;
+ %local.funcsynopsis.attrib;
>
<!--end of funcsynopsis.attlist-->]]>
<!--end of funcsynopsis.module-->]]>
@@ -3813,10 +3813,10 @@ in the text (no (0) value, the default)
<!ENTITY % funcsynopsisinfo.attlist "INCLUDE">
<![%funcsynopsisinfo.attlist;[
<!ATTLIST funcsynopsisinfo
- %linespecific.attrib;
- %common.attrib;
- %funcsynopsisinfo.role.attrib;
- %local.funcsynopsisinfo.attrib;
+ %linespecific.attrib;
+ %common.attrib;
+ %funcsynopsisinfo.role.attrib;
+ %local.funcsynopsisinfo.attrib;
>
<!--end of funcsynopsisinfo.attlist-->]]>
<!--end of funcsynopsisinfo.module-->]]>
@@ -3834,9 +3834,9 @@ in the text (no (0) value, the default)
<!ENTITY % funcprototype.attlist "INCLUDE">
<![%funcprototype.attlist;[
<!ATTLIST funcprototype
- %common.attrib;
- %funcprototype.role.attrib;
- %local.funcprototype.attrib;
+ %common.attrib;
+ %funcprototype.role.attrib;
+ %local.funcprototype.attrib;
>
<!--end of funcprototype.attlist-->]]>
<!--end of funcprototype.module-->]]>
@@ -3849,17 +3849,17 @@ in the text (no (0) value, the default)
<!ENTITY % funcdef.element "INCLUDE">
<![%funcdef.element;[
<!ELEMENT funcdef %ho; (#PCDATA
- | type
- | replaceable
- | function)*>
+ | type
+ | replaceable
+ | function)*>
<!--end of funcdef.element-->]]>
<!ENTITY % funcdef.attlist "INCLUDE">
<![%funcdef.attlist;[
<!ATTLIST funcdef
- %common.attrib;
- %funcdef.role.attrib;
- %local.funcdef.attrib;
+ %common.attrib;
+ %funcdef.role.attrib;
+ %local.funcdef.attrib;
>
<!--end of funcdef.attlist-->]]>
<!--end of funcdef.module-->]]>
@@ -3877,9 +3877,9 @@ in the text (no (0) value, the default)
<!ENTITY % void.attlist "INCLUDE">
<![%void.attlist;[
<!ATTLIST void
- %common.attrib;
- %void.role.attrib;
- %local.void.attrib;
+ %common.attrib;
+ %void.role.attrib;
+ %local.void.attrib;
>
<!--end of void.attlist-->]]>
<!--end of void.module-->]]>
@@ -3897,9 +3897,9 @@ in the text (no (0) value, the default)
<!ENTITY % varargs.attlist "INCLUDE">
<![%varargs.attlist;[
<!ATTLIST varargs
- %common.attrib;
- %varargs.role.attrib;
- %local.varargs.attrib;
+ %common.attrib;
+ %varargs.role.attrib;
+ %local.varargs.attrib;
>
<!--end of varargs.attlist-->]]>
<!--end of varargs.module-->]]>
@@ -3917,18 +3917,18 @@ in the text (no (0) value, the default)
<!ENTITY % paramdef.element "INCLUDE">
<![%paramdef.element;[
<!ELEMENT paramdef %ho; (#PCDATA
- | type
- | replaceable
- | parameter
- | funcparams)*>
+ | type
+ | replaceable
+ | parameter
+ | funcparams)*>
<!--end of paramdef.element-->]]>
<!ENTITY % paramdef.attlist "INCLUDE">
<![%paramdef.attlist;[
<!ATTLIST paramdef
- %common.attrib;
- %paramdef.role.attrib;
- %local.paramdef.attrib;
+ %common.attrib;
+ %paramdef.role.attrib;
+ %local.paramdef.attrib;
>
<!--end of paramdef.attlist-->]]>
<!--end of paramdef.module-->]]>
@@ -3946,9 +3946,9 @@ in the text (no (0) value, the default)
<!ENTITY % funcparams.attlist "INCLUDE">
<![%funcparams.attlist;[
<!ATTLIST funcparams
- %common.attrib;
- %funcparams.role.attrib;
- %local.funcparams.attrib;
+ %common.attrib;
+ %funcparams.role.attrib;
+ %local.funcparams.attrib;
>
<!--end of funcparams.attlist-->]]>
<!--end of funcparams.module-->]]>
@@ -3979,11 +3979,11 @@ in the text (no (0) value, the default)
<!ENTITY % classsynopsis.attlist "INCLUDE">
<![%classsynopsis.attlist;[
<!ATTLIST classsynopsis
- language CDATA #IMPLIED
- class (class|interface) "class"
- %common.attrib;
- %classsynopsis.role.attrib;
- %local.classsynopsis.attrib;
+ language CDATA #IMPLIED
+ class (class|interface) "class"
+ %common.attrib;
+ %classsynopsis.role.attrib;
+ %local.classsynopsis.attrib;
>
<!--end of classsynopsis.attlist-->]]>
<!--end of classsynopsis.module-->]]>
@@ -4001,10 +4001,10 @@ in the text (no (0) value, the default)
<!ENTITY % classsynopsisinfo.attlist "INCLUDE">
<![ %classsynopsisinfo.attlist; [
<!ATTLIST classsynopsisinfo
- %linespecific.attrib;
- %common.attrib;
- %classsynopsisinfo.role.attrib;
- %local.classsynopsisinfo.attrib;
+ %linespecific.attrib;
+ %common.attrib;
+ %classsynopsisinfo.role.attrib;
+ %local.classsynopsisinfo.attrib;
>
<!--end of classsynopsisinfo.attlist-->]]>
<!--end of classsynopsisinfo.module-->]]>
@@ -4022,9 +4022,9 @@ in the text (no (0) value, the default)
<!ENTITY % ooclass.attlist "INCLUDE">
<![%ooclass.attlist;[
<!ATTLIST ooclass
- %common.attrib;
- %ooclass.role.attrib;
- %local.ooclass.attrib;
+ %common.attrib;
+ %ooclass.role.attrib;
+ %local.ooclass.attrib;
>
<!--end of ooclass.attlist-->]]>
<!--end of ooclass.module-->]]>
@@ -4042,9 +4042,9 @@ in the text (no (0) value, the default)
<!ENTITY % oointerface.attlist "INCLUDE">
<![%oointerface.attlist;[
<!ATTLIST oointerface
- %common.attrib;
- %oointerface.role.attrib;
- %local.oointerface.attrib;
+ %common.attrib;
+ %oointerface.role.attrib;
+ %local.oointerface.attrib;
>
<!--end of oointerface.attlist-->]]>
<!--end of oointerface.module-->]]>
@@ -4062,9 +4062,9 @@ in the text (no (0) value, the default)
<!ENTITY % ooexception.attlist "INCLUDE">
<![%ooexception.attlist;[
<!ATTLIST ooexception
- %common.attrib;
- %ooexception.role.attrib;
- %local.ooexception.attrib;
+ %common.attrib;
+ %ooexception.role.attrib;
+ %local.ooexception.attrib;
>
<!--end of ooexception.attlist-->]]>
<!--end of ooexception.module-->]]>
@@ -4082,9 +4082,9 @@ in the text (no (0) value, the default)
<!ENTITY % modifier.attlist "INCLUDE">
<![%modifier.attlist;[
<!ATTLIST modifier
- %common.attrib;
- %modifier.role.attrib;
- %local.modifier.attrib;
+ %common.attrib;
+ %modifier.role.attrib;
+ %local.modifier.attrib;
>
<!--end of modifier.attlist-->]]>
<!--end of modifier.module-->]]>
@@ -4102,9 +4102,9 @@ in the text (no (0) value, the default)
<!ENTITY % interfacename.attlist "INCLUDE">
<![%interfacename.attlist;[
<!ATTLIST interfacename
- %common.attrib;
- %interfacename.role.attrib;
- %local.interfacename.attrib;
+ %common.attrib;
+ %interfacename.role.attrib;
+ %local.interfacename.attrib;
>
<!--end of interfacename.attlist-->]]>
<!--end of interfacename.module-->]]>
@@ -4122,9 +4122,9 @@ in the text (no (0) value, the default)
<!ENTITY % exceptionname.attlist "INCLUDE">
<![%exceptionname.attlist;[
<!ATTLIST exceptionname
- %common.attrib;
- %exceptionname.role.attrib;
- %local.exceptionname.attrib;
+ %common.attrib;
+ %exceptionname.role.attrib;
+ %local.exceptionname.attrib;
>
<!--end of exceptionname.attlist-->]]>
<!--end of exceptionname.module-->]]>
@@ -4142,10 +4142,10 @@ in the text (no (0) value, the default)
<!ENTITY % fieldsynopsis.attlist "INCLUDE">
<![%fieldsynopsis.attlist;[
<!ATTLIST fieldsynopsis
- language CDATA #IMPLIED
- %common.attrib;
- %fieldsynopsis.role.attrib;
- %local.fieldsynopsis.attrib;
+ language CDATA #IMPLIED
+ %common.attrib;
+ %fieldsynopsis.role.attrib;
+ %local.fieldsynopsis.attrib;
>
<!--end of fieldsynopsis.attlist-->]]>
<!--end of fieldsynopsis.module-->]]>
@@ -4163,9 +4163,9 @@ in the text (no (0) value, the default)
<!ENTITY % initializer.attlist "INCLUDE">
<![%initializer.attlist;[
<!ATTLIST initializer
- %common.attrib;
- %initializer.role.attrib;
- %local.initializer.attrib;
+ %common.attrib;
+ %initializer.role.attrib;
+ %local.initializer.attrib;
>
<!--end of initializer.attlist-->]]>
<!--end of initializer.module-->]]>
@@ -4186,10 +4186,10 @@ in the text (no (0) value, the default)
<!ENTITY % constructorsynopsis.attlist "INCLUDE">
<![%constructorsynopsis.attlist;[
<!ATTLIST constructorsynopsis
- language CDATA #IMPLIED
- %common.attrib;
- %constructorsynopsis.role.attrib;
- %local.constructorsynopsis.attrib;
+ language CDATA #IMPLIED
+ %common.attrib;
+ %constructorsynopsis.role.attrib;
+ %local.constructorsynopsis.attrib;
>
<!--end of constructorsynopsis.attlist-->]]>
<!--end of constructorsynopsis.module-->]]>
@@ -4210,10 +4210,10 @@ in the text (no (0) value, the default)
<!ENTITY % destructorsynopsis.attlist "INCLUDE">
<![%destructorsynopsis.attlist;[
<!ATTLIST destructorsynopsis
- language CDATA #IMPLIED
- %common.attrib;
- %destructorsynopsis.role.attrib;
- %local.destructorsynopsis.attrib;
+ language CDATA #IMPLIED
+ %common.attrib;
+ %destructorsynopsis.role.attrib;
+ %local.destructorsynopsis.attrib;
>
<!--end of destructorsynopsis.attlist-->]]>
<!--end of destructorsynopsis.module-->]]>
@@ -4236,10 +4236,10 @@ in the text (no (0) value, the default)
<!ENTITY % methodsynopsis.attlist "INCLUDE">
<![%methodsynopsis.attlist;[
<!ATTLIST methodsynopsis
- language CDATA #IMPLIED
- %common.attrib;
- %methodsynopsis.role.attrib;
- %local.methodsynopsis.attrib;
+ language CDATA #IMPLIED
+ %common.attrib;
+ %methodsynopsis.role.attrib;
+ %local.methodsynopsis.attrib;
>
<!--end of methodsynopsis.attlist-->]]>
<!--end of methodsynopsis.module-->]]>
@@ -4257,9 +4257,9 @@ in the text (no (0) value, the default)
<!ENTITY % methodname.attlist "INCLUDE">
<![%methodname.attlist;[
<!ATTLIST methodname
- %common.attrib;
- %methodname.role.attrib;
- %local.methodname.attrib;
+ %common.attrib;
+ %methodname.role.attrib;
+ %local.methodname.attrib;
>
<!--end of methodname.attlist-->]]>
<!--end of methodname.module-->]]>
@@ -4280,14 +4280,14 @@ in the text (no (0) value, the default)
<!ENTITY % methodparam.attlist "INCLUDE">
<![%methodparam.attlist;[
<!ATTLIST methodparam
- choice (opt
- |req
- |plain) "req"
- rep (norepeat
- |repeat) "norepeat"
- %common.attrib;
- %methodparam.role.attrib;
- %local.methodparam.attrib;
+ choice (opt
+ |req
+ |plain) "req"
+ rep (norepeat
+ |repeat) "norepeat"
+ %common.attrib;
+ %methodparam.role.attrib;
+ %local.methodparam.attrib;
>
<!--end of methodparam.attlist-->]]>
<!--end of methodparam.module-->]]>
@@ -4321,9 +4321,9 @@ in the text (no (0) value, the default)
<!ENTITY % ackno.attlist "INCLUDE">
<![%ackno.attlist;[
<!ATTLIST ackno
- %common.attrib;
- %ackno.role.attrib;
- %local.ackno.attrib;
+ %common.attrib;
+ %ackno.role.attrib;
+ %local.ackno.attrib;
>
<!--end of ackno.attlist-->]]>
<!--end of ackno.module-->]]>
@@ -4340,17 +4340,17 @@ in the text (no (0) value, the default)
<!ENTITY % address.element "INCLUDE">
<![%address.element;[
<!ELEMENT address %ho; (#PCDATA|personname|%person.ident.mix;
- |street|pob|postcode|city|state|country|phone
- |fax|email|otheraddr)*>
+ |street|pob|postcode|city|state|country|phone
+ |fax|email|otheraddr)*>
<!--end of address.element-->]]>
<!ENTITY % address.attlist "INCLUDE">
<![%address.attlist;[
<!ATTLIST address
- %linespecific.attrib;
- %common.attrib;
- %address.role.attrib;
- %local.address.attrib;
+ %linespecific.attrib;
+ %common.attrib;
+ %address.role.attrib;
+ %local.address.attrib;
>
<!--end of address.attlist-->]]>
<!--end of address.module-->]]>
@@ -4368,9 +4368,9 @@ in the text (no (0) value, the default)
<!ENTITY % street.attlist "INCLUDE">
<![%street.attlist;[
<!ATTLIST street
- %common.attrib;
- %street.role.attrib;
- %local.street.attrib;
+ %common.attrib;
+ %street.role.attrib;
+ %local.street.attrib;
>
<!--end of street.attlist-->]]>
<!--end of street.module-->]]>
@@ -4388,9 +4388,9 @@ in the text (no (0) value, the default)
<!ENTITY % pob.attlist "INCLUDE">
<![%pob.attlist;[
<!ATTLIST pob
- %common.attrib;
- %pob.role.attrib;
- %local.pob.attrib;
+ %common.attrib;
+ %pob.role.attrib;
+ %local.pob.attrib;
>
<!--end of pob.attlist-->]]>
<!--end of pob.module-->]]>
@@ -4408,9 +4408,9 @@ in the text (no (0) value, the default)
<!ENTITY % postcode.attlist "INCLUDE">
<![%postcode.attlist;[
<!ATTLIST postcode
- %common.attrib;
- %postcode.role.attrib;
- %local.postcode.attrib;
+ %common.attrib;
+ %postcode.role.attrib;
+ %local.postcode.attrib;
>
<!--end of postcode.attlist-->]]>
<!--end of postcode.module-->]]>
@@ -4428,9 +4428,9 @@ in the text (no (0) value, the default)
<!ENTITY % city.attlist "INCLUDE">
<![%city.attlist;[
<!ATTLIST city
- %common.attrib;
- %city.role.attrib;
- %local.city.attrib;
+ %common.attrib;
+ %city.role.attrib;
+ %local.city.attrib;
>
<!--end of city.attlist-->]]>
<!--end of city.module-->]]>
@@ -4448,9 +4448,9 @@ in the text (no (0) value, the default)
<!ENTITY % state.attlist "INCLUDE">
<![%state.attlist;[
<!ATTLIST state
- %common.attrib;
- %state.role.attrib;
- %local.state.attrib;
+ %common.attrib;
+ %state.role.attrib;
+ %local.state.attrib;
>
<!--end of state.attlist-->]]>
<!--end of state.module-->]]>
@@ -4468,9 +4468,9 @@ in the text (no (0) value, the default)
<!ENTITY % country.attlist "INCLUDE">
<![%country.attlist;[
<!ATTLIST country
- %common.attrib;
- %country.role.attrib;
- %local.country.attrib;
+ %common.attrib;
+ %country.role.attrib;
+ %local.country.attrib;
>
<!--end of country.attlist-->]]>
<!--end of country.module-->]]>
@@ -4488,9 +4488,9 @@ in the text (no (0) value, the default)
<!ENTITY % phone.attlist "INCLUDE">
<![%phone.attlist;[
<!ATTLIST phone
- %common.attrib;
- %phone.role.attrib;
- %local.phone.attrib;
+ %common.attrib;
+ %phone.role.attrib;
+ %local.phone.attrib;
>
<!--end of phone.attlist-->]]>
<!--end of phone.module-->]]>
@@ -4508,9 +4508,9 @@ in the text (no (0) value, the default)
<!ENTITY % fax.attlist "INCLUDE">
<![%fax.attlist;[
<!ATTLIST fax
- %common.attrib;
- %fax.role.attrib;
- %local.fax.attrib;
+ %common.attrib;
+ %fax.role.attrib;
+ %local.fax.attrib;
>
<!--end of fax.attlist-->]]>
<!--end of fax.module-->]]>
@@ -4530,9 +4530,9 @@ in the text (no (0) value, the default)
<!ENTITY % otheraddr.attlist "INCLUDE">
<![%otheraddr.attlist;[
<!ATTLIST otheraddr
- %common.attrib;
- %otheraddr.role.attrib;
- %local.otheraddr.attrib;
+ %common.attrib;
+ %otheraddr.role.attrib;
+ %local.otheraddr.attrib;
>
<!--end of otheraddr.attlist-->]]>
<!--end of otheraddr.module-->]]>
@@ -4550,15 +4550,15 @@ in the text (no (0) value, the default)
<!ENTITY % affiliation.element "INCLUDE">
<![%affiliation.element;[
<!ELEMENT affiliation %ho; (shortaffil?, jobtitle*, orgname?, orgdiv*,
- address*)>
+ address*)>
<!--end of affiliation.element-->]]>
<!ENTITY % affiliation.attlist "INCLUDE">
<![%affiliation.attlist;[
<!ATTLIST affiliation
- %common.attrib;
- %affiliation.role.attrib;
- %local.affiliation.attrib;
+ %common.attrib;
+ %affiliation.role.attrib;
+ %local.affiliation.attrib;
>
<!--end of affiliation.attlist-->]]>
<!--end of affiliation.module-->]]>
@@ -4576,9 +4576,9 @@ in the text (no (0) value, the default)
<!ENTITY % shortaffil.attlist "INCLUDE">
<![%shortaffil.attlist;[
<!ATTLIST shortaffil
- %common.attrib;
- %shortaffil.role.attrib;
- %local.shortaffil.attrib;
+ %common.attrib;
+ %shortaffil.role.attrib;
+ %local.shortaffil.attrib;
>
<!--end of shortaffil.attlist-->]]>
<!--end of shortaffil.module-->]]>
@@ -4596,9 +4596,9 @@ in the text (no (0) value, the default)
<!ENTITY % jobtitle.attlist "INCLUDE">
<![%jobtitle.attlist;[
<!ATTLIST jobtitle
- %common.attrib;
- %jobtitle.role.attrib;
- %local.jobtitle.attrib;
+ %common.attrib;
+ %jobtitle.role.attrib;
+ %local.jobtitle.attrib;
>
<!--end of jobtitle.attlist-->]]>
<!--end of jobtitle.module-->]]>
@@ -4618,9 +4618,9 @@ in the text (no (0) value, the default)
<!ENTITY % orgdiv.attlist "INCLUDE">
<![%orgdiv.attlist;[
<!ATTLIST orgdiv
- %common.attrib;
- %orgdiv.role.attrib;
- %local.orgdiv.attrib;
+ %common.attrib;
+ %orgdiv.role.attrib;
+ %local.orgdiv.attrib;
>
<!--end of orgdiv.attlist-->]]>
<!--end of orgdiv.module-->]]>
@@ -4643,9 +4643,9 @@ in the text (no (0) value, the default)
<!ENTITY % artpagenums.attlist "INCLUDE">
<![%artpagenums.attlist;[
<!ATTLIST artpagenums
- %common.attrib;
- %artpagenums.role.attrib;
- %local.artpagenums.attrib;
+ %common.attrib;
+ %artpagenums.role.attrib;
+ %local.artpagenums.attrib;
>
<!--end of artpagenums.attlist-->]]>
<!--end of artpagenums.module-->]]>
@@ -4665,9 +4665,9 @@ in the text (no (0) value, the default)
<!ENTITY % personname.attlist "INCLUDE">
<![%personname.attlist;[
<!ATTLIST personname
- %common.attrib;
- %personname.role.attrib;
- %local.personname.attrib;
+ %common.attrib;
+ %personname.role.attrib;
+ %local.personname.attrib;
>
<!--end of personname.attlist-->]]>
<!--end of personname.module-->]]>
@@ -4687,9 +4687,9 @@ in the text (no (0) value, the default)
<!ENTITY % author.attlist "INCLUDE">
<![%author.attlist;[
<!ATTLIST author
- %common.attrib;
- %author.role.attrib;
- %local.author.attrib;
+ %common.attrib;
+ %author.role.attrib;
+ %local.author.attrib;
>
<!--end of author.attlist-->]]>
<!--(see "Personal identity elements" for %person.ident.mix;)-->
@@ -4712,9 +4712,9 @@ in the text (no (0) value, the default)
<!ENTITY % authorgroup.attlist "INCLUDE">
<![%authorgroup.attlist;[
<!ATTLIST authorgroup
- %common.attrib;
- %authorgroup.role.attrib;
- %local.authorgroup.attrib;
+ %common.attrib;
+ %authorgroup.role.attrib;
+ %local.authorgroup.attrib;
>
<!--end of authorgroup.attlist-->]]>
<!--end of authorgroup.module-->]]>
@@ -4737,9 +4737,9 @@ in the text (no (0) value, the default)
<!ENTITY % collab.attlist "INCLUDE">
<![%collab.attlist;[
<!ATTLIST collab
- %common.attrib;
- %collab.role.attrib;
- %local.collab.attrib;
+ %common.attrib;
+ %collab.role.attrib;
+ %local.collab.attrib;
>
<!--end of collab.attlist-->]]>
<!--end of collab.module-->]]>
@@ -4757,9 +4757,9 @@ in the text (no (0) value, the default)
<!ENTITY % collabname.attlist "INCLUDE">
<![%collabname.attlist;[
<!ATTLIST collabname
- %common.attrib;
- %collabname.role.attrib;
- %local.collabname.attrib;
+ %common.attrib;
+ %collabname.role.attrib;
+ %local.collabname.attrib;
>
<!--end of collabname.attlist-->]]>
<!--end of collabname.module-->]]>
@@ -4787,9 +4787,9 @@ in the text (no (0) value, the default)
<!ENTITY % authorinitials.attlist "INCLUDE">
<![%authorinitials.attlist;[
<!ATTLIST authorinitials
- %common.attrib;
- %authorinitials.role.attrib;
- %local.authorinitials.attrib;
+ %common.attrib;
+ %authorinitials.role.attrib;
+ %local.authorinitials.attrib;
>
<!--end of authorinitials.attlist-->]]>
<!--end of authorinitials.module-->]]>
@@ -4811,9 +4811,9 @@ in the text (no (0) value, the default)
<!ENTITY % confgroup.attlist "INCLUDE">
<![%confgroup.attlist;[
<!ATTLIST confgroup
- %common.attrib;
- %confgroup.role.attrib;
- %local.confgroup.attrib;
+ %common.attrib;
+ %confgroup.role.attrib;
+ %local.confgroup.attrib;
>
<!--end of confgroup.attlist-->]]>
<!--end of confgroup.module-->]]>
@@ -4831,9 +4831,9 @@ in the text (no (0) value, the default)
<!ENTITY % confdates.attlist "INCLUDE">
<![%confdates.attlist;[
<!ATTLIST confdates
- %common.attrib;
- %confdates.role.attrib;
- %local.confdates.attrib;
+ %common.attrib;
+ %confdates.role.attrib;
+ %local.confdates.attrib;
>
<!--end of confdates.attlist-->]]>
<!--end of confdates.module-->]]>
@@ -4851,9 +4851,9 @@ in the text (no (0) value, the default)
<!ENTITY % conftitle.attlist "INCLUDE">
<![%conftitle.attlist;[
<!ATTLIST conftitle
- %common.attrib;
- %conftitle.role.attrib;
- %local.conftitle.attrib;
+ %common.attrib;
+ %conftitle.role.attrib;
+ %local.conftitle.attrib;
>
<!--end of conftitle.attlist-->]]>
<!--end of conftitle.module-->]]>
@@ -4871,9 +4871,9 @@ in the text (no (0) value, the default)
<!ENTITY % confnum.attlist "INCLUDE">
<![%confnum.attlist;[
<!ATTLIST confnum
- %common.attrib;
- %confnum.role.attrib;
- %local.confnum.attrib;
+ %common.attrib;
+ %confnum.role.attrib;
+ %local.confnum.attrib;
>
<!--end of confnum.attlist-->]]>
<!--end of confnum.module-->]]>
@@ -4893,9 +4893,9 @@ in the text (no (0) value, the default)
<!ENTITY % confsponsor.attlist "INCLUDE">
<![%confsponsor.attlist;[
<!ATTLIST confsponsor
- %common.attrib;
- %confsponsor.role.attrib;
- %local.confsponsor.attrib;
+ %common.attrib;
+ %confsponsor.role.attrib;
+ %local.confsponsor.attrib;
>
<!--end of confsponsor.attlist-->]]>
<!--end of confsponsor.module-->]]>
@@ -4916,9 +4916,9 @@ in the text (no (0) value, the default)
<!ENTITY % contractnum.attlist "INCLUDE">
<![%contractnum.attlist;[
<!ATTLIST contractnum
- %common.attrib;
- %contractnum.role.attrib;
- %local.contractnum.attrib;
+ %common.attrib;
+ %contractnum.role.attrib;
+ %local.contractnum.attrib;
>
<!--end of contractnum.attlist-->]]>
<!--end of contractnum.module-->]]>
@@ -4938,9 +4938,9 @@ in the text (no (0) value, the default)
<!ENTITY % contractsponsor.attlist "INCLUDE">
<![%contractsponsor.attlist;[
<!ATTLIST contractsponsor
- %common.attrib;
- %contractsponsor.role.attrib;
- %local.contractsponsor.attrib;
+ %common.attrib;
+ %contractsponsor.role.attrib;
+ %local.contractsponsor.attrib;
>
<!--end of contractsponsor.attlist-->]]>
<!--end of contractsponsor.module-->]]>
@@ -4962,9 +4962,9 @@ in the text (no (0) value, the default)
<!ENTITY % copyright.attlist "INCLUDE">
<![%copyright.attlist;[
<!ATTLIST copyright
- %common.attrib;
- %copyright.role.attrib;
- %local.copyright.attrib;
+ %common.attrib;
+ %copyright.role.attrib;
+ %local.copyright.attrib;
>
<!--end of copyright.attlist-->]]>
<!--end of copyright.module-->]]>
@@ -4982,9 +4982,9 @@ in the text (no (0) value, the default)
<!ENTITY % year.attlist "INCLUDE">
<![%year.attlist;[
<!ATTLIST year
- %common.attrib;
- %year.role.attrib;
- %local.year.attrib;
+ %common.attrib;
+ %year.role.attrib;
+ %local.year.attrib;
>
<!--end of year.attlist-->]]>
<!--end of year.module-->]]>
@@ -5002,9 +5002,9 @@ in the text (no (0) value, the default)
<!ENTITY % holder.attlist "INCLUDE">
<![%holder.attlist;[
<!ATTLIST holder
- %common.attrib;
- %holder.role.attrib;
- %local.holder.attrib;
+ %common.attrib;
+ %holder.role.attrib;
+ %local.holder.attrib;
>
<!--end of holder.attlist-->]]>
<!--end of holder.module-->]]>
@@ -5025,9 +5025,9 @@ in the text (no (0) value, the default)
<!ENTITY % corpauthor.attlist "INCLUDE">
<![%corpauthor.attlist;[
<!ATTLIST corpauthor
- %common.attrib;
- %corpauthor.role.attrib;
- %local.corpauthor.attrib;
+ %common.attrib;
+ %corpauthor.role.attrib;
+ %local.corpauthor.attrib;
>
<!--end of corpauthor.attlist-->]]>
<!--end of corpauthor.module-->]]>
@@ -5047,9 +5047,9 @@ in the text (no (0) value, the default)
<!ENTITY % corpname.attlist "INCLUDE">
<![%corpname.attlist;[
<!ATTLIST corpname
- %common.attrib;
- %corpname.role.attrib;
- %local.corpname.attrib;
+ %common.attrib;
+ %corpname.role.attrib;
+ %local.corpname.attrib;
>
<!--end of corpname.attlist-->]]>
<!--end of corpname.module-->]]>
@@ -5069,9 +5069,9 @@ in the text (no (0) value, the default)
<!ENTITY % date.attlist "INCLUDE">
<![%date.attlist;[
<!ATTLIST date
- %common.attrib;
- %date.role.attrib;
- %local.date.attrib;
+ %common.attrib;
+ %date.role.attrib;
+ %local.date.attrib;
>
<!--end of date.attlist-->]]>
<!--end of date.module-->]]>
@@ -5091,9 +5091,9 @@ in the text (no (0) value, the default)
<!ENTITY % edition.attlist "INCLUDE">
<![%edition.attlist;[
<!ATTLIST edition
- %common.attrib;
- %edition.role.attrib;
- %local.edition.attrib;
+ %common.attrib;
+ %edition.role.attrib;
+ %local.edition.attrib;
>
<!--end of edition.attlist-->]]>
<!--end of edition.module-->]]>
@@ -5113,9 +5113,9 @@ in the text (no (0) value, the default)
<!ENTITY % editor.attlist "INCLUDE">
<![%editor.attlist;[
<!ATTLIST editor
- %common.attrib;
- %editor.role.attrib;
- %local.editor.attrib;
+ %common.attrib;
+ %editor.role.attrib;
+ %local.editor.attrib;
>
<!--end of editor.attlist-->]]>
<!--(see "Personal identity elements" for %person.ident.mix;)-->
@@ -5136,9 +5136,9 @@ in the text (no (0) value, the default)
<!ENTITY % isbn.attlist "INCLUDE">
<![%isbn.attlist;[
<!ATTLIST isbn
- %common.attrib;
- %isbn.role.attrib;
- %local.isbn.attrib;
+ %common.attrib;
+ %isbn.role.attrib;
+ %local.isbn.attrib;
>
<!--end of isbn.attlist-->]]>
<!--end of isbn.module-->]]>
@@ -5158,23 +5158,23 @@ in the text (no (0) value, the default)
<!ENTITY % issn.attlist "INCLUDE">
<![%issn.attlist;[
<!ATTLIST issn
- %common.attrib;
- %issn.role.attrib;
- %local.issn.attrib;
+ %common.attrib;
+ %issn.role.attrib;
+ %local.issn.attrib;
>
<!--end of issn.attlist-->]]>
<!--end of issn.module-->]]>
<!-- BiblioId ................. -->
<!ENTITY % biblio.class.attrib
- "class (uri
+ "class (uri
|doi
|isbn
|issn
|libraryofcongress
|pubnumber
|other) #IMPLIED
- otherclass CDATA #IMPLIED"
+ otherclass CDATA #IMPLIED"
>
<!ENTITY % biblioid.module "INCLUDE">
@@ -5190,10 +5190,10 @@ in the text (no (0) value, the default)
<!ENTITY % biblioid.attlist "INCLUDE">
<![%biblioid.attlist;[
<!ATTLIST biblioid
- %biblio.class.attrib;
- %common.attrib;
- %biblioid.role.attrib;
- %local.biblioid.attrib;
+ %biblio.class.attrib;
+ %common.attrib;
+ %biblioid.role.attrib;
+ %local.biblioid.attrib;
>
<!--end of biblioid.attlist-->]]>
<!--end of biblioid.module-->]]>
@@ -5213,10 +5213,10 @@ in the text (no (0) value, the default)
<!ENTITY % citebiblioid.attlist "INCLUDE">
<![%citebiblioid.attlist;[
<!ATTLIST citebiblioid
- %biblio.class.attrib;
- %common.attrib;
- %citebiblioid.role.attrib;
- %local.citebiblioid.attrib;
+ %biblio.class.attrib;
+ %common.attrib;
+ %citebiblioid.role.attrib;
+ %local.citebiblioid.attrib;
>
<!--end of citebiblioid.attlist-->]]>
<!--end of citebiblioid.module-->]]>
@@ -5236,10 +5236,10 @@ in the text (no (0) value, the default)
<!ENTITY % bibliosource.attlist "INCLUDE">
<![%bibliosource.attlist;[
<!ATTLIST bibliosource
- %biblio.class.attrib;
- %common.attrib;
- %bibliosource.role.attrib;
- %local.bibliosource.attrib;
+ %biblio.class.attrib;
+ %common.attrib;
+ %bibliosource.role.attrib;
+ %local.bibliosource.attrib;
>
<!--end of bibliosource.attlist-->]]>
<!--end of bibliosource.module-->]]>
@@ -5266,7 +5266,7 @@ in the text (no (0) value, the default)
|hasformat
|othertype
%local.bibliorelation.types;) #IMPLIED
- othertype CDATA #IMPLIED
+ othertype CDATA #IMPLIED
">
<!ENTITY % bibliorelation.role.attrib "%role.attrib;">
@@ -5279,11 +5279,11 @@ in the text (no (0) value, the default)
<!ENTITY % bibliorelation.attlist "INCLUDE">
<![%bibliorelation.attlist;[
<!ATTLIST bibliorelation
- %biblio.class.attrib;
- %bibliorelation.type.attrib;
- %common.attrib;
- %bibliorelation.role.attrib;
- %local.bibliorelation.attrib;
+ %biblio.class.attrib;
+ %bibliorelation.type.attrib;
+ %common.attrib;
+ %bibliorelation.role.attrib;
+ %local.bibliorelation.attrib;
>
<!--end of bibliorelation.attlist-->]]>
<!--end of bibliorelation.module-->]]>
@@ -5303,13 +5303,13 @@ in the text (no (0) value, the default)
<!ENTITY % bibliocoverage.attlist "INCLUDE">
<![%bibliocoverage.attlist;[
<!ATTLIST bibliocoverage
- spatial (dcmipoint|iso3166|dcmibox|tgn|otherspatial) #IMPLIED
- otherspatial CDATA #IMPLIED
- temporal (dcmiperiod|w3c-dtf|othertemporal) #IMPLIED
- othertemporal CDATA #IMPLIED
- %common.attrib;
- %bibliocoverage.role.attrib;
- %local.bibliocoverage.attrib;
+ spatial (dcmipoint|iso3166|dcmibox|tgn|otherspatial) #IMPLIED
+ otherspatial CDATA #IMPLIED
+ temporal (dcmiperiod|w3c-dtf|othertemporal) #IMPLIED
+ othertemporal CDATA #IMPLIED
+ %common.attrib;
+ %bibliocoverage.role.attrib;
+ %local.bibliocoverage.attrib;
>
<!--end of bibliocoverage.attlist-->]]>
<!--end of bibliocoverage.module-->]]>
@@ -5329,9 +5329,9 @@ in the text (no (0) value, the default)
<!ENTITY % invpartnumber.attlist "INCLUDE">
<![%invpartnumber.attlist;[
<!ATTLIST invpartnumber
- %common.attrib;
- %invpartnumber.role.attrib;
- %local.invpartnumber.attrib;
+ %common.attrib;
+ %invpartnumber.role.attrib;
+ %local.invpartnumber.attrib;
>
<!--end of invpartnumber.attlist-->]]>
<!--end of invpartnumber.module-->]]>
@@ -5351,9 +5351,9 @@ in the text (no (0) value, the default)
<!ENTITY % issuenum.attlist "INCLUDE">
<![%issuenum.attlist;[
<!ATTLIST issuenum
- %common.attrib;
- %issuenum.role.attrib;
- %local.issuenum.attrib;
+ %common.attrib;
+ %issuenum.role.attrib;
+ %local.issuenum.attrib;
>
<!--end of issuenum.attlist-->]]>
<!--end of issuenum.module-->]]>
@@ -5368,15 +5368,15 @@ in the text (no (0) value, the default)
<!ENTITY % legalnotice.element "INCLUDE">
<![%legalnotice.element;[
<!ELEMENT legalnotice %ho; (blockinfo?, title?, (%legalnotice.mix;)+)
- %formal.exclusion;>
+ %formal.exclusion;>
<!--end of legalnotice.element-->]]>
<!ENTITY % legalnotice.attlist "INCLUDE">
<![%legalnotice.attlist;[
<!ATTLIST legalnotice
- %common.attrib;
- %legalnotice.role.attrib;
- %local.legalnotice.attrib;
+ %common.attrib;
+ %legalnotice.role.attrib;
+ %local.legalnotice.attrib;
>
<!--end of legalnotice.attlist-->]]>
<!--end of legalnotice.module-->]]>
@@ -5391,22 +5391,22 @@ in the text (no (0) value, the default)
<!ENTITY % modespec.element "INCLUDE">
<![%modespec.element;[
<!ELEMENT modespec %ho; (%docinfo.char.mix;)*
- %ubiq.exclusion;>
+ %ubiq.exclusion;>
<!--end of modespec.element-->]]>
<!-- Application: Type of action required for completion
- of the links to which the ModeSpec is relevant (e.g.,
- retrieval query) -->
+ of the links to which the ModeSpec is relevant (e.g.,
+ retrieval query) -->
<!ENTITY % modespec.attlist "INCLUDE">
<![%modespec.attlist;[
<!ATTLIST modespec
- application NOTATION
- (%notation.class;) #IMPLIED
- %common.attrib;
- %modespec.role.attrib;
- %local.modespec.attrib;
+ application NOTATION
+ (%notation.class;) #IMPLIED
+ %common.attrib;
+ %modespec.role.attrib;
+ %local.modespec.attrib;
>
<!--end of modespec.attlist-->]]>
<!--end of modespec.module-->]]>
@@ -5426,11 +5426,11 @@ in the text (no (0) value, the default)
<!ENTITY % orgname.attlist "INCLUDE">
<![%orgname.attlist;[
<!ATTLIST orgname
- %common.attrib;
- class (corporation|nonprofit|consortium|informal|other) #IMPLIED
- otherclass CDATA #IMPLIED
- %orgname.role.attrib;
- %local.orgname.attrib;
+ %common.attrib;
+ class (corporation|nonprofit|consortium|informal|other) #IMPLIED
+ otherclass CDATA #IMPLIED
+ %orgname.role.attrib;
+ %local.orgname.attrib;
>
<!--end of orgname.attlist-->]]>
<!--end of orgname.module-->]]>
@@ -5451,9 +5451,9 @@ in the text (no (0) value, the default)
<!ENTITY % othercredit.attlist "INCLUDE">
<![%othercredit.attlist;[
<!ATTLIST othercredit
- %common.attrib;
- %othercredit.role.attrib;
- %local.othercredit.attrib;
+ %common.attrib;
+ %othercredit.role.attrib;
+ %local.othercredit.attrib;
>
<!--end of othercredit.attlist-->]]>
<!--(see "Personal identity elements" for %person.ident.mix;)-->
@@ -5474,9 +5474,9 @@ in the text (no (0) value, the default)
<!ENTITY % pagenums.attlist "INCLUDE">
<![%pagenums.attlist;[
<!ATTLIST pagenums
- %common.attrib;
- %pagenums.role.attrib;
- %local.pagenums.attrib;
+ %common.attrib;
+ %pagenums.role.attrib;
+ %local.pagenums.attrib;
>
<!--end of pagenums.attlist-->]]>
<!--end of pagenums.module-->]]>
@@ -5501,9 +5501,9 @@ OtherCredit. -->
<!ENTITY % contrib.attlist "INCLUDE">
<![%contrib.attlist;[
<!ATTLIST contrib
- %common.attrib;
- %contrib.role.attrib;
- %local.contrib.attrib;
+ %common.attrib;
+ %contrib.role.attrib;
+ %local.contrib.attrib;
>
<!--end of contrib.attlist-->]]>
<!--end of contrib.module-->]]>
@@ -5521,9 +5521,9 @@ OtherCredit. -->
<!ENTITY % firstname.attlist "INCLUDE">
<![%firstname.attlist;[
<!ATTLIST firstname
- %common.attrib;
- %firstname.role.attrib;
- %local.firstname.attrib;
+ %common.attrib;
+ %firstname.role.attrib;
+ %local.firstname.attrib;
>
<!--end of firstname.attlist-->]]>
<!--end of firstname.module-->]]>
@@ -5541,9 +5541,9 @@ OtherCredit. -->
<!ENTITY % honorific.attlist "INCLUDE">
<![%honorific.attlist;[
<!ATTLIST honorific
- %common.attrib;
- %honorific.role.attrib;
- %local.honorific.attrib;
+ %common.attrib;
+ %honorific.role.attrib;
+ %local.honorific.attrib;
>
<!--end of honorific.attlist-->]]>
<!--end of honorific.module-->]]>
@@ -5561,9 +5561,9 @@ OtherCredit. -->
<!ENTITY % lineage.attlist "INCLUDE">
<![%lineage.attlist;[
<!ATTLIST lineage
- %common.attrib;
- %lineage.role.attrib;
- %local.lineage.attrib;
+ %common.attrib;
+ %lineage.role.attrib;
+ %local.lineage.attrib;
>
<!--end of lineage.attlist-->]]>
<!--end of lineage.module-->]]>
@@ -5581,9 +5581,9 @@ OtherCredit. -->
<!ENTITY % othername.attlist "INCLUDE">
<![%othername.attlist;[
<!ATTLIST othername
- %common.attrib;
- %othername.role.attrib;
- %local.othername.attrib;
+ %common.attrib;
+ %othername.role.attrib;
+ %local.othername.attrib;
>
<!--end of othername.attlist-->]]>
<!--end of othername.module-->]]>
@@ -5601,9 +5601,9 @@ OtherCredit. -->
<!ENTITY % surname.attlist "INCLUDE">
<![%surname.attlist;[
<!ATTLIST surname
- %common.attrib;
- %surname.role.attrib;
- %local.surname.attrib;
+ %common.attrib;
+ %surname.role.attrib;
+ %local.surname.attrib;
>
<!--end of surname.attlist-->]]>
<!--end of surname.module-->]]>
@@ -5624,9 +5624,9 @@ OtherCredit. -->
<!ENTITY % printhistory.attlist "INCLUDE">
<![%printhistory.attlist;[
<!ATTLIST printhistory
- %common.attrib;
- %printhistory.role.attrib;
- %local.printhistory.attrib;
+ %common.attrib;
+ %printhistory.role.attrib;
+ %local.printhistory.attrib;
>
<!--end of printhistory.attlist-->]]>
<!--end of printhistory.module-->]]>
@@ -5649,13 +5649,13 @@ OtherCredit. -->
<!ENTITY % productname.attlist "INCLUDE">
<![%productname.attlist;[
<!ATTLIST productname
- class (service
- |trade
- |registered
- |copyright) 'trade'
- %common.attrib;
- %productname.role.attrib;
- %local.productname.attrib;
+ class (service
+ |trade
+ |registered
+ |copyright) 'trade'
+ %common.attrib;
+ %productname.role.attrib;
+ %local.productname.attrib;
>
<!--end of productname.attlist-->]]>
<!--end of productname.module-->]]>
@@ -5675,9 +5675,9 @@ OtherCredit. -->
<!ENTITY % productnumber.attlist "INCLUDE">
<![%productnumber.attlist;[
<!ATTLIST productnumber
- %common.attrib;
- %productnumber.role.attrib;
- %local.productnumber.attrib;
+ %common.attrib;
+ %productnumber.role.attrib;
+ %local.productnumber.attrib;
>
<!--end of productnumber.attlist-->]]>
<!--end of productnumber.module-->]]>
@@ -5697,9 +5697,9 @@ OtherCredit. -->
<!ENTITY % pubdate.attlist "INCLUDE">
<![%pubdate.attlist;[
<!ATTLIST pubdate
- %common.attrib;
- %pubdate.role.attrib;
- %local.pubdate.attrib;
+ %common.attrib;
+ %pubdate.role.attrib;
+ %local.pubdate.attrib;
>
<!--end of pubdate.attlist-->]]>
<!--end of pubdate.module-->]]>
@@ -5721,9 +5721,9 @@ OtherCredit. -->
<!ENTITY % publisher.attlist "INCLUDE">
<![%publisher.attlist;[
<!ATTLIST publisher
- %common.attrib;
- %publisher.role.attrib;
- %local.publisher.attrib;
+ %common.attrib;
+ %publisher.role.attrib;
+ %local.publisher.attrib;
>
<!--end of publisher.attlist-->]]>
<!--end of publisher.module-->]]>
@@ -5741,9 +5741,9 @@ OtherCredit. -->
<!ENTITY % publishername.attlist "INCLUDE">
<![%publishername.attlist;[
<!ATTLIST publishername
- %common.attrib;
- %publishername.role.attrib;
- %local.publishername.attrib;
+ %common.attrib;
+ %publishername.role.attrib;
+ %local.publishername.attrib;
>
<!--end of publishername.attlist-->]]>
<!--end of publishername.module-->]]>
@@ -5766,9 +5766,9 @@ OtherCredit. -->
<!ENTITY % pubsnumber.attlist "INCLUDE">
<![%pubsnumber.attlist;[
<!ATTLIST pubsnumber
- %common.attrib;
- %pubsnumber.role.attrib;
- %local.pubsnumber.attrib;
+ %common.attrib;
+ %pubsnumber.role.attrib;
+ %local.pubsnumber.attrib;
>
<!--end of pubsnumber.attlist-->]]>
<!--end of pubsnumber.module-->]]>
@@ -5788,9 +5788,9 @@ OtherCredit. -->
<!ENTITY % releaseinfo.attlist "INCLUDE">
<![%releaseinfo.attlist;[
<!ATTLIST releaseinfo
- %common.attrib;
- %releaseinfo.role.attrib;
- %local.releaseinfo.attrib;
+ %common.attrib;
+ %releaseinfo.role.attrib;
+ %local.releaseinfo.attrib;
>
<!--end of releaseinfo.attlist-->]]>
<!--end of releaseinfo.module-->]]>
@@ -5812,9 +5812,9 @@ OtherCredit. -->
<!ENTITY % revhistory.attlist "INCLUDE">
<![%revhistory.attlist;[
<!ATTLIST revhistory
- %common.attrib;
- %revhistory.role.attrib;
- %local.revhistory.attrib;
+ %common.attrib;
+ %revhistory.role.attrib;
+ %local.revhistory.attrib;
>
<!--end of revhistory.attlist-->]]>
<!--end of revhistory.module-->]]>
@@ -5833,9 +5833,9 @@ OtherCredit. -->
<!ENTITY % revision.attlist "INCLUDE">
<![%revision.attlist;[
<!ATTLIST revision
- %common.attrib;
- %revision.role.attrib;
- %local.revision.attrib;
+ %common.attrib;
+ %revision.role.attrib;
+ %local.revision.attrib;
>
<!--end of revision.attlist-->]]>
<!--end of revision.module-->]]>
@@ -5853,9 +5853,9 @@ OtherCredit. -->
<!ENTITY % revnumber.attlist "INCLUDE">
<![%revnumber.attlist;[
<!ATTLIST revnumber
- %common.attrib;
- %revnumber.role.attrib;
- %local.revnumber.attrib;
+ %common.attrib;
+ %revnumber.role.attrib;
+ %local.revnumber.attrib;
>
<!--end of revnumber.attlist-->]]>
<!--end of revnumber.module-->]]>
@@ -5876,9 +5876,9 @@ OtherCredit. -->
<!ENTITY % revremark.attlist "INCLUDE">
<![%revremark.attlist;[
<!ATTLIST revremark
- %common.attrib;
- %revremark.role.attrib;
- %local.revremark.attrib;
+ %common.attrib;
+ %revremark.role.attrib;
+ %local.revremark.attrib;
>
<!--end of revremark.attlist-->]]>
<!--end of revremark.module-->]]>
@@ -5896,9 +5896,9 @@ OtherCredit. -->
<!ENTITY % revdescription.attlist "INCLUDE">
<![ %revdescription.attlist; [
<!ATTLIST revdescription
- %common.attrib;
- %revdescription.role.attrib;
- %local.revdescription.attrib;
+ %common.attrib;
+ %revdescription.role.attrib;
+ %local.revdescription.attrib;
>
<!--end of revdescription.attlist-->]]>
<!--end of revdescription.module-->]]>
@@ -5919,9 +5919,9 @@ OtherCredit. -->
<!ENTITY % seriesvolnums.attlist "INCLUDE">
<![%seriesvolnums.attlist;[
<!ATTLIST seriesvolnums
- %common.attrib;
- %seriesvolnums.role.attrib;
- %local.seriesvolnums.attrib;
+ %common.attrib;
+ %seriesvolnums.role.attrib;
+ %local.seriesvolnums.attrib;
>
<!--end of seriesvolnums.attlist-->]]>
<!--end of seriesvolnums.module-->]]>
@@ -5941,9 +5941,9 @@ OtherCredit. -->
<!ENTITY % volumenum.attlist "INCLUDE">
<![%volumenum.attlist;[
<!ATTLIST volumenum
- %common.attrib;
- %volumenum.role.attrib;
- %local.volumenum.attrib;
+ %common.attrib;
+ %volumenum.role.attrib;
+ %local.volumenum.attrib;
>
<!--end of volumenum.attlist-->]]>
<!--end of volumenum.module-->]]>
@@ -5970,9 +5970,9 @@ OtherCredit. -->
<!ENTITY % accel.attlist "INCLUDE">
<![%accel.attlist;[
<!ATTLIST accel
- %common.attrib;
- %accel.role.attrib;
- %local.accel.attrib;
+ %common.attrib;
+ %accel.role.attrib;
+ %local.accel.attrib;
>
<!--end of accel.attlist-->]]>
<!--end of accel.module-->]]>
@@ -5990,10 +5990,10 @@ OtherCredit. -->
<!ENTITY % action.attlist "INCLUDE">
<![%action.attlist;[
<!ATTLIST action
- %moreinfo.attrib;
- %common.attrib;
- %action.role.attrib;
- %local.action.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %action.role.attrib;
+ %local.action.attrib;
>
<!--end of action.attlist-->]]>
<!--end of action.module-->]]>
@@ -6011,12 +6011,12 @@ OtherCredit. -->
<!ENTITY % application.attlist "INCLUDE">
<![%application.attlist;[
<!ATTLIST application
- class (hardware
- |software) #IMPLIED
- %moreinfo.attrib;
- %common.attrib;
- %application.role.attrib;
- %local.application.attrib;
+ class (hardware
+ |software) #IMPLIED
+ %moreinfo.attrib;
+ %common.attrib;
+ %application.role.attrib;
+ %local.application.attrib;
>
<!--end of application.attlist-->]]>
<!--end of application.module-->]]>
@@ -6034,9 +6034,9 @@ OtherCredit. -->
<!ENTITY % classname.attlist "INCLUDE">
<![%classname.attlist;[
<!ATTLIST classname
- %common.attrib;
- %classname.role.attrib;
- %local.classname.attrib;
+ %common.attrib;
+ %classname.role.attrib;
+ %local.classname.attrib;
>
<!--end of classname.attlist-->]]>
<!--end of classname.module-->]]>
@@ -6060,11 +6060,11 @@ OtherCredit. -->
<!ENTITY % co.attlist "INCLUDE">
<![%co.attlist;[
<!ATTLIST co
- %label.attrib;
- %linkends.attrib;
- %idreq.common.attrib;
- %co.role.attrib;
- %local.co.attrib;
+ %label.attrib;
+ %linkends.attrib;
+ %idreq.common.attrib;
+ %co.role.attrib;
+ %local.co.attrib;
>
<!--end of co.attlist-->]]>
<!--end of co.module-->]]>
@@ -6086,11 +6086,11 @@ OtherCredit. -->
<!ENTITY % coref.attlist "INCLUDE">
<![%coref.attlist;[
<!ATTLIST coref
- %label.attrib;
- %linkendreq.attrib;
- %common.attrib;
- %coref.role.attrib;
- %local.coref.attrib;
+ %label.attrib;
+ %linkendreq.attrib;
+ %common.attrib;
+ %coref.role.attrib;
+ %local.coref.attrib;
>
<!--end of coref.attlist-->]]>
<!--end of coref.module-->]]>
@@ -6108,10 +6108,10 @@ OtherCredit. -->
<!ENTITY % command.attlist "INCLUDE">
<![%command.attlist;[
<!ATTLIST command
- %moreinfo.attrib;
- %common.attrib;
- %command.role.attrib;
- %local.command.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %command.role.attrib;
+ %local.command.attrib;
>
<!--end of command.attlist-->]]>
<!--end of command.module-->]]>
@@ -6129,10 +6129,10 @@ OtherCredit. -->
<!ENTITY % computeroutput.attlist "INCLUDE">
<![%computeroutput.attlist;[
<!ATTLIST computeroutput
- %moreinfo.attrib;
- %common.attrib;
- %computeroutput.role.attrib;
- %local.computeroutput.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %computeroutput.role.attrib;
+ %local.computeroutput.attrib;
>
<!--end of computeroutput.attlist-->]]>
<!--end of computeroutput.module-->]]>
@@ -6153,16 +6153,16 @@ OtherCredit. -->
<!ENTITY % database.attlist "INCLUDE">
<![%database.attlist;[
<!ATTLIST database
- class (name
- |table
- |field
- |key1
- |key2
- |record) #IMPLIED
- %moreinfo.attrib;
- %common.attrib;
- %database.role.attrib;
- %local.database.attrib;
+ class (name
+ |table
+ |field
+ |key1
+ |key2
+ |record) #IMPLIED
+ %moreinfo.attrib;
+ %common.attrib;
+ %database.role.attrib;
+ %local.database.attrib;
>
<!--end of database.attlist-->]]>
<!--end of database.module-->]]>
@@ -6180,9 +6180,9 @@ OtherCredit. -->
<!ENTITY % email.attlist "INCLUDE">
<![%email.attlist;[
<!ATTLIST email
- %common.attrib;
- %email.role.attrib;
- %local.email.attrib;
+ %common.attrib;
+ %email.role.attrib;
+ %local.email.attrib;
>
<!--end of email.attlist-->]]>
<!--end of email.module-->]]>
@@ -6200,9 +6200,9 @@ OtherCredit. -->
<!ENTITY % envar.attlist "INCLUDE">
<![%envar.attlist;[
<!ATTLIST envar
- %common.attrib;
- %envar.role.attrib;
- %local.envar.attrib;
+ %common.attrib;
+ %envar.role.attrib;
+ %local.envar.attrib;
>
<!--end of envar.attlist-->]]>
<!--end of envar.module-->]]>
@@ -6221,10 +6221,10 @@ OtherCredit. -->
<!ENTITY % errorcode.attlist "INCLUDE">
<![%errorcode.attlist;[
<!ATTLIST errorcode
- %moreinfo.attrib;
- %common.attrib;
- %errorcode.role.attrib;
- %local.errorcode.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %errorcode.role.attrib;
+ %local.errorcode.attrib;
>
<!--end of errorcode.attlist-->]]>
<!--end of errorcode.module-->]]>
@@ -6242,9 +6242,9 @@ OtherCredit. -->
<!ENTITY % errorname.attlist "INCLUDE">
<![%errorname.attlist;[
<!ATTLIST errorname
- %common.attrib;
- %errorname.role.attrib;
- %local.errorname.attrib;
+ %common.attrib;
+ %errorname.role.attrib;
+ %local.errorname.attrib;
>
<!--end of errorname.attlist-->]]>
<!--end of errorname.module-->]]>
@@ -6262,9 +6262,9 @@ OtherCredit. -->
<!ENTITY % errortext.attlist "INCLUDE">
<![%errortext.attlist;[
<!ATTLIST errortext
- %common.attrib;
- %errortext.role.attrib;
- %local.errortext.attrib;
+ %common.attrib;
+ %errortext.role.attrib;
+ %local.errortext.attrib;
>
<!--end of errortext.attlist-->]]>
<!--end of errortext.module-->]]>
@@ -6282,9 +6282,9 @@ OtherCredit. -->
<!ENTITY % errortype.attlist "INCLUDE">
<![%errortype.attlist;[
<!ATTLIST errortype
- %common.attrib;
- %errortype.role.attrib;
- %local.errortype.attrib;
+ %common.attrib;
+ %errortype.role.attrib;
+ %local.errortype.attrib;
>
<!--end of errortype.attlist-->]]>
<!--end of errortype.module-->]]>
@@ -6301,24 +6301,24 @@ OtherCredit. -->
<!-- Class: Type of filename the element names; no default -->
<!-- Path: Search path (possibly system-specific) in which
- file can be found -->
+ file can be found -->
<!ENTITY % filename.attlist "INCLUDE">
<![%filename.attlist;[
<!ATTLIST filename
- class (headerfile
+ class (headerfile
|partition
|devicefile
|libraryfile
|directory
|extension
- |symlink) #IMPLIED
- path CDATA #IMPLIED
- %moreinfo.attrib;
- %common.attrib;
- %filename.role.attrib;
- %local.filename.attrib;
+ |symlink) #IMPLIED
+ path CDATA #IMPLIED
+ %moreinfo.attrib;
+ %common.attrib;
+ %filename.role.attrib;
+ %local.filename.attrib;
>
<!--end of filename.attlist-->]]>
<!--end of filename.module-->]]>
@@ -6336,10 +6336,10 @@ OtherCredit. -->
<!ENTITY % function.attlist "INCLUDE">
<![%function.attlist;[
<!ATTLIST function
- %moreinfo.attrib;
- %common.attrib;
- %function.role.attrib;
- %local.function.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %function.role.attrib;
+ %local.function.attrib;
>
<!--end of function.attlist-->]]>
<!--end of function.module-->]]>
@@ -6357,10 +6357,10 @@ OtherCredit. -->
<!ENTITY % guibutton.attlist "INCLUDE">
<![%guibutton.attlist;[
<!ATTLIST guibutton
- %moreinfo.attrib;
- %common.attrib;
- %guibutton.role.attrib;
- %local.guibutton.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %guibutton.role.attrib;
+ %local.guibutton.attrib;
>
<!--end of guibutton.attlist-->]]>
<!--end of guibutton.module-->]]>
@@ -6378,10 +6378,10 @@ OtherCredit. -->
<!ENTITY % guiicon.attlist "INCLUDE">
<![%guiicon.attlist;[
<!ATTLIST guiicon
- %moreinfo.attrib;
- %common.attrib;
- %guiicon.role.attrib;
- %local.guiicon.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %guiicon.role.attrib;
+ %local.guiicon.attrib;
>
<!--end of guiicon.attlist-->]]>
<!--end of guiicon.module-->]]>
@@ -6399,10 +6399,10 @@ OtherCredit. -->
<!ENTITY % guilabel.attlist "INCLUDE">
<![%guilabel.attlist;[
<!ATTLIST guilabel
- %moreinfo.attrib;
- %common.attrib;
- %guilabel.role.attrib;
- %local.guilabel.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %guilabel.role.attrib;
+ %local.guilabel.attrib;
>
<!--end of guilabel.attlist-->]]>
<!--end of guilabel.module-->]]>
@@ -6420,10 +6420,10 @@ OtherCredit. -->
<!ENTITY % guimenu.attlist "INCLUDE">
<![%guimenu.attlist;[
<!ATTLIST guimenu
- %moreinfo.attrib;
- %common.attrib;
- %guimenu.role.attrib;
- %local.guimenu.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %guimenu.role.attrib;
+ %local.guimenu.attrib;
>
<!--end of guimenu.attlist-->]]>
<!--end of guimenu.module-->]]>
@@ -6441,10 +6441,10 @@ OtherCredit. -->
<!ENTITY % guimenuitem.attlist "INCLUDE">
<![%guimenuitem.attlist;[
<!ATTLIST guimenuitem
- %moreinfo.attrib;
- %common.attrib;
- %guimenuitem.role.attrib;
- %local.guimenuitem.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %guimenuitem.role.attrib;
+ %local.guimenuitem.attrib;
>
<!--end of guimenuitem.attlist-->]]>
<!--end of guimenuitem.module-->]]>
@@ -6462,10 +6462,10 @@ OtherCredit. -->
<!ENTITY % guisubmenu.attlist "INCLUDE">
<![%guisubmenu.attlist;[
<!ATTLIST guisubmenu
- %moreinfo.attrib;
- %common.attrib;
- %guisubmenu.role.attrib;
- %local.guisubmenu.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %guisubmenu.role.attrib;
+ %local.guisubmenu.attrib;
>
<!--end of guisubmenu.attlist-->]]>
<!--end of guisubmenu.module-->]]>
@@ -6483,10 +6483,10 @@ OtherCredit. -->
<!ENTITY % hardware.attlist "INCLUDE">
<![%hardware.attlist;[
<!ATTLIST hardware
- %moreinfo.attrib;
- %common.attrib;
- %hardware.role.attrib;
- %local.hardware.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %hardware.role.attrib;
+ %local.hardware.attrib;
>
<!--end of hardware.attlist-->]]>
<!--end of hardware.module-->]]>
@@ -6507,10 +6507,10 @@ OtherCredit. -->
<!ENTITY % interface.attlist "INCLUDE">
<![%interface.attlist;[
<!ATTLIST interface
- %moreinfo.attrib;
- %common.attrib;
- %interface.role.attrib;
- %local.interface.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %interface.role.attrib;
+ %local.interface.attrib;
>
<!--end of interface.attlist-->]]>
<!--end of interface.module-->]]>
@@ -6528,10 +6528,10 @@ OtherCredit. -->
<!ENTITY % keycap.attlist "INCLUDE">
<![%keycap.attlist;[
<!ATTLIST keycap
- %moreinfo.attrib;
- %common.attrib;
- %keycap.role.attrib;
- %local.keycap.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %keycap.role.attrib;
+ %local.keycap.attrib;
>
<!--end of keycap.attlist-->]]>
<!--end of keycap.module-->]]>
@@ -6549,9 +6549,9 @@ OtherCredit. -->
<!ENTITY % keycode.attlist "INCLUDE">
<![%keycode.attlist;[
<!ATTLIST keycode
- %common.attrib;
- %keycode.role.attrib;
- %local.keycode.attrib;
+ %common.attrib;
+ %keycode.role.attrib;
+ %local.keycode.attrib;
>
<!--end of keycode.attlist-->]]>
<!--end of keycode.module-->]]>
@@ -6569,11 +6569,11 @@ OtherCredit. -->
<!ENTITY % keycombo.attlist "INCLUDE">
<![%keycombo.attlist;[
<!ATTLIST keycombo
- %keyaction.attrib;
- %moreinfo.attrib;
- %common.attrib;
- %keycombo.role.attrib;
- %local.keycombo.attrib;
+ %keyaction.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %keycombo.role.attrib;
+ %local.keycombo.attrib;
>
<!--end of keycombo.attlist-->]]>
<!--end of keycombo.module-->]]>
@@ -6591,9 +6591,9 @@ OtherCredit. -->
<!ENTITY % keysym.attlist "INCLUDE">
<![%keysym.attlist;[
<!ATTLIST keysym
- %common.attrib;
- %keysysm.role.attrib;
- %local.keysym.attrib;
+ %common.attrib;
+ %keysysm.role.attrib;
+ %local.keysym.attrib;
>
<!--end of keysym.attlist-->]]>
<!--end of keysym.module-->]]>
@@ -6611,9 +6611,9 @@ OtherCredit. -->
<!ENTITY % lineannotation.attlist "INCLUDE">
<![%lineannotation.attlist;[
<!ATTLIST lineannotation
- %common.attrib;
- %lineannotation.role.attrib;
- %local.lineannotation.attrib;
+ %common.attrib;
+ %lineannotation.role.attrib;
+ %local.lineannotation.attrib;
>
<!--end of lineannotation.attlist-->]]>
<!--end of lineannotation.module-->]]>
@@ -6631,10 +6631,10 @@ OtherCredit. -->
<!ENTITY % literal.attlist "INCLUDE">
<![%literal.attlist;[
<!ATTLIST literal
- %moreinfo.attrib;
- %common.attrib;
- %literal.role.attrib;
- %local.literal.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %literal.role.attrib;
+ %local.literal.attrib;
>
<!--end of literal.attlist-->]]>
<!--end of literal.module-->]]>
@@ -6652,10 +6652,10 @@ OtherCredit. -->
<!ENTITY % constant.attlist "INCLUDE">
<![ %constant.attlist; [
<!ATTLIST constant
- class (limit) #IMPLIED
- %common.attrib;
- %constant.role.attrib;
- %local.constant.attrib;
+ class (limit) #IMPLIED
+ %common.attrib;
+ %constant.role.attrib;
+ %local.constant.attrib;
>
<!--end of constant.attlist-->]]>
<!--end of constant.module-->]]>
@@ -6673,9 +6673,9 @@ OtherCredit. -->
<!ENTITY % varname.attlist "INCLUDE">
<![ %varname.attlist; [
<!ATTLIST varname
- %common.attrib;
- %varname.role.attrib;
- %local.varname.attrib;
+ %common.attrib;
+ %varname.role.attrib;
+ %local.varname.attrib;
>
<!--end of varname.attlist-->]]>
<!--end of varname.module-->]]>
@@ -6693,9 +6693,9 @@ OtherCredit. -->
<!ENTITY % markup.attlist "INCLUDE">
<![%markup.attlist;[
<!ATTLIST markup
- %common.attrib;
- %markup.role.attrib;
- %local.markup.attrib;
+ %common.attrib;
+ %markup.role.attrib;
+ %local.markup.attrib;
>
<!--end of markup.attlist-->]]>
<!--end of markup.module-->]]>
@@ -6716,13 +6716,13 @@ OtherCredit. -->
<!ENTITY % medialabel.attlist "INCLUDE">
<![%medialabel.attlist;[
<!ATTLIST medialabel
- class (cartridge
- |cdrom
- |disk
- |tape) #IMPLIED
- %common.attrib;
- %medialabel.role.attrib;
- %local.medialabel.attrib;
+ class (cartridge
+ |cdrom
+ |disk
+ |tape) #IMPLIED
+ %common.attrib;
+ %medialabel.role.attrib;
+ %local.medialabel.attrib;
>
<!--end of medialabel.attlist-->]]>
<!--end of medialabel.module-->]]>
@@ -6737,16 +6737,16 @@ OtherCredit. -->
<!ENTITY % menuchoice.element "INCLUDE">
<![%menuchoice.element;[
<!ELEMENT menuchoice %ho; (shortcut?, (guibutton|guiicon|guilabel
- |guimenu|guimenuitem|guisubmenu|interface)+)>
+ |guimenu|guimenuitem|guisubmenu|interface)+)>
<!--end of menuchoice.element-->]]>
<!ENTITY % menuchoice.attlist "INCLUDE">
<![%menuchoice.attlist;[
<!ATTLIST menuchoice
- %moreinfo.attrib;
- %common.attrib;
- %menuchoice.role.attrib;
- %local.menuchoice.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %menuchoice.role.attrib;
+ %local.menuchoice.attrib;
>
<!--end of menuchoice.attlist-->]]>
<!--end of menuchoice.module-->]]>
@@ -6765,11 +6765,11 @@ OtherCredit. -->
<!ENTITY % shortcut.attlist "INCLUDE">
<![%shortcut.attlist;[
<!ATTLIST shortcut
- %keyaction.attrib;
- %moreinfo.attrib;
- %common.attrib;
- %shortcut.role.attrib;
- %local.shortcut.attrib;
+ %keyaction.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %shortcut.role.attrib;
+ %local.shortcut.attrib;
>
<!--end of shortcut.attlist-->]]>
<!--end of shortcut.module-->]]>
@@ -6788,10 +6788,10 @@ OtherCredit. -->
<!ENTITY % mousebutton.attlist "INCLUDE">
<![%mousebutton.attlist;[
<!ATTLIST mousebutton
- %moreinfo.attrib;
- %common.attrib;
- %mousebutton.role.attrib;
- %local.mousebutton.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %mousebutton.role.attrib;
+ %local.mousebutton.attrib;
>
<!--end of mousebutton.attlist-->]]>
<!--end of mousebutton.module-->]]>
@@ -6809,9 +6809,9 @@ OtherCredit. -->
<!ENTITY % msgtext.attlist "INCLUDE">
<![%msgtext.attlist;[
<!ATTLIST msgtext
- %common.attrib;
- %msgtext.role.attrib;
- %local.msgtext.attrib;
+ %common.attrib;
+ %msgtext.role.attrib;
+ %local.msgtext.attrib;
>
<!--end of msgtext.attlist-->]]>
<!--end of msgtext.module-->]]>
@@ -6829,9 +6829,9 @@ OtherCredit. -->
<!ENTITY % option.attlist "INCLUDE">
<![%option.attlist;[
<!ATTLIST option
- %common.attrib;
- %option.role.attrib;
- %local.option.attrib;
+ %common.attrib;
+ %option.role.attrib;
+ %local.option.attrib;
>
<!--end of option.attlist-->]]>
<!--end of option.module-->]]>
@@ -6849,9 +6849,9 @@ OtherCredit. -->
<!ENTITY % optional.attlist "INCLUDE">
<![%optional.attlist;[
<!ATTLIST optional
- %common.attrib;
- %optional.role.attrib;
- %local.optional.attrib;
+ %common.attrib;
+ %optional.role.attrib;
+ %local.optional.attrib;
>
<!--end of optional.attlist-->]]>
<!--end of optional.module-->]]>
@@ -6872,13 +6872,13 @@ OtherCredit. -->
<!ENTITY % parameter.attlist "INCLUDE">
<![%parameter.attlist;[
<!ATTLIST parameter
- class (command
- |function
- |option) #IMPLIED
- %moreinfo.attrib;
- %common.attrib;
- %parameter.role.attrib;
- %local.parameter.attrib;
+ class (command
+ |function
+ |option) #IMPLIED
+ %moreinfo.attrib;
+ %common.attrib;
+ %parameter.role.attrib;
+ %local.parameter.attrib;
>
<!--end of parameter.attlist-->]]>
<!--end of parameter.module-->]]>
@@ -6896,10 +6896,10 @@ OtherCredit. -->
<!ENTITY % prompt.attlist "INCLUDE">
<![%prompt.attlist;[
<!ATTLIST prompt
- %moreinfo.attrib;
- %common.attrib;
- %prompt.role.attrib;
- %local.prompt.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %prompt.role.attrib;
+ %local.prompt.attrib;
>
<!--end of prompt.attlist-->]]>
<!--end of prompt.module-->]]>
@@ -6917,10 +6917,10 @@ OtherCredit. -->
<!ENTITY % property.attlist "INCLUDE">
<![%property.attlist;[
<!ATTLIST property
- %moreinfo.attrib;
- %common.attrib;
- %property.role.attrib;
- %local.property.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %property.role.attrib;
+ %local.property.attrib;
>
<!--end of property.attlist-->]]>
<!--end of property.module-->]]>
@@ -6933,29 +6933,29 @@ OtherCredit. -->
<!ENTITY % replaceable.element "INCLUDE">
<![%replaceable.element;[
<!ELEMENT replaceable %ho; (#PCDATA
- | %link.char.class;
- | optional
- | %base.char.class;
- | %other.char.class;
- | inlinegraphic
+ | %link.char.class;
+ | optional
+ | %base.char.class;
+ | %other.char.class;
+ | inlinegraphic
| inlinemediaobject
- | co)*>
+ | co)*>
<!--end of replaceable.element-->]]>
<!-- Class: Type of information the element represents; no
- default -->
+ default -->
<!ENTITY % replaceable.attlist "INCLUDE">
<![%replaceable.attlist;[
<!ATTLIST replaceable
- class (command
- |function
- |option
- |parameter) #IMPLIED
- %common.attrib;
- %replaceable.role.attrib;
- %local.replaceable.attrib;
+ class (command
+ |function
+ |option
+ |parameter) #IMPLIED
+ %common.attrib;
+ %replaceable.role.attrib;
+ %local.replaceable.attrib;
>
<!--end of replaceable.attlist-->]]>
<!--end of replaceable.module-->]]>
@@ -6973,9 +6973,9 @@ OtherCredit. -->
<!ENTITY % returnvalue.attlist "INCLUDE">
<![%returnvalue.attlist;[
<!ATTLIST returnvalue
- %common.attrib;
- %returnvalue.role.attrib;
- %local.returnvalue.attrib;
+ %common.attrib;
+ %returnvalue.role.attrib;
+ %local.returnvalue.attrib;
>
<!--end of returnvalue.attlist-->]]>
<!--end of returnvalue.module-->]]>
@@ -6996,21 +6996,21 @@ OtherCredit. -->
<!ENTITY % sgmltag.attlist "INCLUDE">
<![%sgmltag.attlist;[
<!ATTLIST sgmltag
- class (attribute
- |attvalue
- |element
- |endtag
+ class (attribute
+ |attvalue
+ |element
+ |endtag
|emptytag
- |genentity
- |numcharref
- |paramentity
- |pi
+ |genentity
+ |numcharref
+ |paramentity
+ |pi
|xmlpi
- |starttag
- |sgmlcomment) #IMPLIED
- %common.attrib;
- %sgmltag.role.attrib;
- %local.sgmltag.attrib;
+ |starttag
+ |sgmlcomment) #IMPLIED
+ %common.attrib;
+ %sgmltag.role.attrib;
+ %local.sgmltag.attrib;
>
<!--end of sgmltag.attlist-->]]>
<!--end of sgmltag.module-->]]>
@@ -7028,9 +7028,9 @@ OtherCredit. -->
<!ENTITY % structfield.attlist "INCLUDE">
<![%structfield.attlist;[
<!ATTLIST structfield
- %common.attrib;
- %structfield.role.attrib;
- %local.structfield.attrib;
+ %common.attrib;
+ %structfield.role.attrib;
+ %local.structfield.attrib;
>
<!--end of structfield.attlist-->]]>
<!--end of structfield.module-->]]>
@@ -7048,9 +7048,9 @@ OtherCredit. -->
<!ENTITY % structname.attlist "INCLUDE">
<![%structname.attlist;[
<!ATTLIST structname
- %common.attrib;
- %structname.role.attrib;
- %local.structname.attrib;
+ %common.attrib;
+ %structname.role.attrib;
+ %local.structname.attrib;
>
<!--end of structname.attlist-->]]>
<!--end of structname.module-->]]>
@@ -7071,10 +7071,10 @@ OtherCredit. -->
<!ENTITY % symbol.attlist "INCLUDE">
<![%symbol.attlist;[
<!ATTLIST symbol
- class (limit) #IMPLIED
- %common.attrib;
- %symbol.role.attrib;
- %local.symbol.attrib;
+ class (limit) #IMPLIED
+ %common.attrib;
+ %symbol.role.attrib;
+ %local.symbol.attrib;
>
<!--end of symbol.attlist-->]]>
<!--end of symbol.module-->]]>
@@ -7094,27 +7094,27 @@ OtherCredit. -->
<!ENTITY % systemitem.attlist "INCLUDE">
<![%systemitem.attlist;[
<!ATTLIST systemitem
- class (constant
- |event
- |eventhandler
- |domainname
- |fqdomainname
- |ipaddress
- |netmask
- |etheraddress
- |groupname
- |library
- |macro
- |osname
- |filesystem
- |resource
- |systemname
- |username
- |newsgroup) #IMPLIED
- %moreinfo.attrib;
- %common.attrib;
- %systemitem.role.attrib;
- %local.systemitem.attrib;
+ class (constant
+ |event
+ |eventhandler
+ |domainname
+ |fqdomainname
+ |ipaddress
+ |netmask
+ |etheraddress
+ |groupname
+ |library
+ |macro
+ |osname
+ |filesystem
+ |resource
+ |systemname
+ |username
+ |newsgroup) #IMPLIED
+ %moreinfo.attrib;
+ %common.attrib;
+ %systemitem.role.attrib;
+ %local.systemitem.attrib;
>
<!--end of systemitem.attlist-->]]>
<!--end of systemitem.module-->]]>
@@ -7133,9 +7133,9 @@ OtherCredit. -->
<!ENTITY % token.attlist "INCLUDE">
<![%token.attlist;[
<!ATTLIST token
- %common.attrib;
- %token.role.attrib;
- %local.token.attrib;
+ %common.attrib;
+ %token.role.attrib;
+ %local.token.attrib;
>
<!--end of token.attlist-->]]>
<!--end of token.module-->]]>
@@ -7153,9 +7153,9 @@ OtherCredit. -->
<!ENTITY % type.attlist "INCLUDE">
<![%type.attlist;[
<!ATTLIST type
- %common.attrib;
- %type.role.attrib;
- %local.type.attrib;
+ %common.attrib;
+ %type.role.attrib;
+ %local.type.attrib;
>
<!--end of type.attlist-->]]>
<!--end of type.module-->]]>
@@ -7173,10 +7173,10 @@ OtherCredit. -->
<!ENTITY % userinput.attlist "INCLUDE">
<![%userinput.attlist;[
<!ATTLIST userinput
- %moreinfo.attrib;
- %common.attrib;
- %userinput.role.attrib;
- %local.userinput.attrib;
+ %moreinfo.attrib;
+ %common.attrib;
+ %userinput.role.attrib;
+ %local.userinput.attrib;
>
<!--end of userinput.attlist-->]]>
<!--end of userinput.module-->]]>
@@ -7196,9 +7196,9 @@ OtherCredit. -->
<!ENTITY % abbrev.attlist "INCLUDE">
<![%abbrev.attlist;[
<!ATTLIST abbrev
- %common.attrib;
- %abbrev.role.attrib;
- %local.abbrev.attrib;
+ %common.attrib;
+ %abbrev.role.attrib;
+ %local.abbrev.attrib;
>
<!--end of abbrev.attlist-->]]>
<!--end of abbrev.module-->]]>
@@ -7211,15 +7211,15 @@ OtherCredit. -->
<!ENTITY % acronym.element "INCLUDE">
<![%acronym.element;[
<!ELEMENT acronym %ho; (%word.char.mix;)*
- %acronym.exclusion;>
+ %acronym.exclusion;>
<!--end of acronym.element-->]]>
<!ENTITY % acronym.attlist "INCLUDE">
<![%acronym.attlist;[
<!ATTLIST acronym
- %common.attrib;
- %acronym.role.attrib;
- %local.acronym.attrib;
+ %common.attrib;
+ %acronym.role.attrib;
+ %local.acronym.attrib;
>
<!--end of acronym.attlist-->]]>
<!--end of acronym.module-->]]>
@@ -7237,9 +7237,9 @@ OtherCredit. -->
<!ENTITY % citation.attlist "INCLUDE">
<![%citation.attlist;[
<!ATTLIST citation
- %common.attrib;
- %citation.role.attrib;
- %local.citation.attrib;
+ %common.attrib;
+ %citation.role.attrib;
+ %local.citation.attrib;
>
<!--end of citation.attlist-->]]>
<!--end of citation.module-->]]>
@@ -7257,9 +7257,9 @@ OtherCredit. -->
<!ENTITY % citerefentry.attlist "INCLUDE">
<![%citerefentry.attlist;[
<!ATTLIST citerefentry
- %common.attrib;
- %citerefentry.role.attrib;
- %local.citerefentry.attrib;
+ %common.attrib;
+ %citerefentry.role.attrib;
+ %local.citerefentry.attrib;
>
<!--end of citerefentry.attlist-->]]>
<!--end of citerefentry.module-->]]>
@@ -7277,9 +7277,9 @@ OtherCredit. -->
<!ENTITY % refentrytitle.attlist "INCLUDE">
<![%refentrytitle.attlist;[
<!ATTLIST refentrytitle
- %common.attrib;
- %refentrytitle.role.attrib;
- %local.refentrytitle.attrib;
+ %common.attrib;
+ %refentrytitle.role.attrib;
+ %local.refentrytitle.attrib;
>
<!--end of refentrytitle.attlist-->]]>
<!--end of refentrytitle.module-->]]>
@@ -7297,9 +7297,9 @@ OtherCredit. -->
<!ENTITY % manvolnum.attlist "INCLUDE">
<![%manvolnum.attlist;[
<!ATTLIST manvolnum
- %common.attrib;
- %namvolnum.role.attrib;
- %local.manvolnum.attrib;
+ %common.attrib;
+ %namvolnum.role.attrib;
+ %local.manvolnum.attrib;
>
<!--end of manvolnum.attlist-->]]>
<!--end of manvolnum.module-->]]>
@@ -7320,19 +7320,19 @@ OtherCredit. -->
<!ENTITY % citetitle.attlist "INCLUDE">
<![%citetitle.attlist;[
<!ATTLIST citetitle
- pubwork (article
- |book
- |chapter
- |part
- |refentry
- |section
- |journal
- |series
- |set
- |manuscript) #IMPLIED
- %common.attrib;
- %citetitle.role.attrib;
- %local.citetitle.attrib;
+ pubwork (article
+ |book
+ |chapter
+ |part
+ |refentry
+ |section
+ |journal
+ |series
+ |set
+ |manuscript) #IMPLIED
+ %common.attrib;
+ %citetitle.role.attrib;
+ %local.citetitle.attrib;
>
<!--end of citetitle.attlist-->]]>
<!--end of citetitle.module-->]]>
@@ -7350,9 +7350,9 @@ OtherCredit. -->
<!ENTITY % emphasis.attlist "INCLUDE">
<![%emphasis.attlist;[
<!ATTLIST emphasis
- %common.attrib;
- %emphasis.role.attrib;
- %local.emphasis.attrib;
+ %common.attrib;
+ %emphasis.role.attrib;
+ %local.emphasis.attrib;
>
<!--end of emphasis.attlist-->]]>
<!--end of emphasis.module-->]]>
@@ -7373,9 +7373,9 @@ OtherCredit. -->
<!ENTITY % firstterm.attlist "INCLUDE">
<![%firstterm.attlist;[
<!ATTLIST firstterm
- %linkend.attrib; %common.attrib;
- %firstterm.role.attrib;
- %local.firstterm.attrib;
+ %linkend.attrib; %common.attrib;
+ %firstterm.role.attrib;
+ %local.firstterm.attrib;
>
<!--end of firstterm.attlist-->]]>
<!--end of firstterm.module-->]]>
@@ -7393,9 +7393,9 @@ OtherCredit. -->
<!ENTITY % foreignphrase.attlist "INCLUDE">
<![%foreignphrase.attlist;[
<!ATTLIST foreignphrase
- %common.attrib;
- %foreignphrase.role.attrib;
- %local.foreignphrase.attrib;
+ %common.attrib;
+ %foreignphrase.role.attrib;
+ %local.foreignphrase.attrib;
>
<!--end of foreignphrase.attlist-->]]>
<!--end of foreignphrase.module-->]]>
@@ -7408,21 +7408,21 @@ OtherCredit. -->
<!ENTITY % glossterm.element "INCLUDE">
<![%glossterm.element;[
<!ELEMENT glossterm %ho; (%para.char.mix;)*
- %glossterm.exclusion;>
+ %glossterm.exclusion;>
<!--end of glossterm.element-->]]>
<!-- to GlossEntry if Glossterm used in text -->
<!-- BaseForm: Provides the form of GlossTerm to be used
- for indexing -->
+ for indexing -->
<!ENTITY % glossterm.attlist "INCLUDE">
<![%glossterm.attlist;[
<!ATTLIST glossterm
- %linkend.attrib; baseform CDATA #IMPLIED
- %common.attrib;
- %glossterm.role.attrib;
- %local.glossterm.attrib;
+ %linkend.attrib; baseform CDATA #IMPLIED
+ %common.attrib;
+ %glossterm.role.attrib;
+ %local.glossterm.attrib;
>
<!--end of glossterm.attlist-->]]>
<!--end of glossterm.module-->]]>
@@ -7440,9 +7440,9 @@ OtherCredit. -->
<!ENTITY % phrase.attlist "INCLUDE">
<![%phrase.attlist;[
<!ATTLIST phrase
- %common.attrib;
- %phrase.role.attrib;
- %local.phrase.attrib;
+ %common.attrib;
+ %phrase.role.attrib;
+ %local.phrase.attrib;
>
<!--end of phrase.attlist-->]]>
<!--end of phrase.module-->]]>
@@ -7460,9 +7460,9 @@ OtherCredit. -->
<!ENTITY % quote.attlist "INCLUDE">
<![%quote.attlist;[
<!ATTLIST quote
- %common.attrib;
- %quote.role.attrib;
- %local.quote.attrib;
+ %common.attrib;
+ %quote.role.attrib;
+ %local.quote.attrib;
>
<!--end of quote.attlist-->]]>
<!--end of quote.module-->]]>
@@ -7475,46 +7475,46 @@ OtherCredit. -->
<!ENTITY % subscript.element "INCLUDE">
<![%subscript.element;[
<!ELEMENT subscript %ho; (#PCDATA
- | %link.char.class;
- | emphasis
- | replaceable
- | symbol
- | inlinegraphic
+ | %link.char.class;
+ | emphasis
+ | replaceable
+ | symbol
+ | inlinegraphic
| inlinemediaobject
- | %base.char.class;
- | %other.char.class;)*
- %ubiq.exclusion;>
+ | %base.char.class;
+ | %other.char.class;)*
+ %ubiq.exclusion;>
<!--end of subscript.element-->]]>
<!ENTITY % subscript.attlist "INCLUDE">
<![%subscript.attlist;[
<!ATTLIST subscript
- %common.attrib;
- %ssscript.role.attrib;
- %local.ssscript.attrib;
+ %common.attrib;
+ %ssscript.role.attrib;
+ %local.ssscript.attrib;
>
<!--end of subscript.attlist-->]]>
<!ENTITY % superscript.element "INCLUDE">
<![%superscript.element;[
<!ELEMENT superscript %ho; (#PCDATA
- | %link.char.class;
- | emphasis
- | replaceable
- | symbol
- | inlinegraphic
+ | %link.char.class;
+ | emphasis
+ | replaceable
+ | symbol
+ | inlinegraphic
| inlinemediaobject
- | %base.char.class;
- | %other.char.class;)*
- %ubiq.exclusion;>
+ | %base.char.class;
+ | %other.char.class;)*
+ %ubiq.exclusion;>
<!--end of superscript.element-->]]>
<!ENTITY % superscript.attlist "INCLUDE">
<![%superscript.attlist;[
<!ATTLIST superscript
- %common.attrib;
- %ssscript.role.attrib;
- %local.ssscript.attrib;
+ %common.attrib;
+ %ssscript.role.attrib;
+ %local.ssscript.attrib;
>
<!--end of superscript.attlist-->]]>
<!--end of ssscript.module-->]]>
@@ -7527,13 +7527,13 @@ OtherCredit. -->
<!ENTITY % trademark.element "INCLUDE">
<![%trademark.element;[
<!ELEMENT trademark %ho; (#PCDATA
- | %link.char.class;
- | %tech.char.class;
- | %base.char.class;
- | %other.char.class;
- | inlinegraphic
+ | %link.char.class;
+ | %tech.char.class;
+ | %base.char.class;
+ | %other.char.class;
+ | inlinegraphic
| inlinemediaobject
- | emphasis)*>
+ | emphasis)*>
<!--end of trademark.element-->]]>
<!-- Class: More precisely identifies the item the element names -->
@@ -7542,13 +7542,13 @@ OtherCredit. -->
<!ENTITY % trademark.attlist "INCLUDE">
<![%trademark.attlist;[
<!ATTLIST trademark
- class (service
- |trade
- |registered
- |copyright) 'trade'
- %common.attrib;
- %trademark.role.attrib;
- %local.trademark.attrib;
+ class (service
+ |trade
+ |registered
+ |copyright) 'trade'
+ %common.attrib;
+ %trademark.role.attrib;
+ %local.trademark.attrib;
>
<!--end of trademark.attlist-->]]>
<!--end of trademark.module-->]]>
@@ -7566,9 +7566,9 @@ OtherCredit. -->
<!ENTITY % wordasword.attlist "INCLUDE">
<![%wordasword.attlist;[
<!ATTLIST wordasword
- %common.attrib;
- %wordasword.role.attrib;
- %local.wordasword.attrib;
+ %common.attrib;
+ %wordasword.role.attrib;
+ %local.wordasword.attrib;
>
<!--end of wordasword.attlist-->]]>
<!--end of wordasword.module-->]]>
@@ -7583,12 +7583,12 @@ OtherCredit. -->
<!ENTITY % link.element "INCLUDE">
<![%link.element;[
<!ELEMENT link %ho; (%para.char.mix;)*
- %links.exclusion;>
+ %links.exclusion;>
<!--end of link.element-->]]>
<!-- Endterm: ID of element containing text that is to be
- fetched from elsewhere in the document to appear as
- the content of this element -->
+ fetched from elsewhere in the document to appear as
+ the content of this element -->
<!-- to linked-to object -->
<!-- Type: Freely assignable parameter -->
@@ -7596,11 +7596,11 @@ OtherCredit. -->
<!ENTITY % link.attlist "INCLUDE">
<![%link.attlist;[
<!ATTLIST link
- endterm IDREF #IMPLIED
- %linkendreq.attrib; type CDATA #IMPLIED
- %common.attrib;
- %link.role.attrib;
- %local.link.attrib;
+ endterm IDREF #IMPLIED
+ %linkendreq.attrib; type CDATA #IMPLIED
+ %common.attrib;
+ %link.role.attrib;
+ %local.link.attrib;
>
<!--end of link.attlist-->]]>
<!--end of link.module-->]]>
@@ -7613,12 +7613,12 @@ OtherCredit. -->
<!ENTITY % olink.element "INCLUDE">
<![%olink.element;[
<!ELEMENT olink %ho; (%para.char.mix;)*
- %links.exclusion;>
+ %links.exclusion;>
<!--end of olink.element-->]]>
<!-- TargetDocEnt: Name of an entity to be the target of the link -->
<!-- LinkMode: ID of a ModeSpec containing instructions for
- operating on the entity named by TargetDocEnt -->
+ operating on the entity named by TargetDocEnt -->
<!-- LocalInfo: Information that may be passed to ModeSpec -->
<!-- Type: Freely assignable parameter -->
@@ -7626,15 +7626,15 @@ OtherCredit. -->
<!ENTITY % olink.attlist "INCLUDE">
<![%olink.attlist;[
<!ATTLIST olink
- targetdocent ENTITY #IMPLIED
- linkmode IDREF #IMPLIED
- localinfo CDATA #IMPLIED
- type CDATA #IMPLIED
- targetdoc CDATA #IMPLIED
- targetptr CDATA #IMPLIED
- %common.attrib;
- %olink.role.attrib;
- %local.olink.attrib;
+ targetdocent ENTITY #IMPLIED
+ linkmode IDREF #IMPLIED
+ localinfo CDATA #IMPLIED
+ type CDATA #IMPLIED
+ targetdoc CDATA #IMPLIED
+ targetptr CDATA #IMPLIED
+ %common.attrib;
+ %olink.role.attrib;
+ %local.olink.attrib;
>
<!--end of olink.attlist-->]]>
<!--end of olink.module-->]]>
@@ -7647,7 +7647,7 @@ OtherCredit. -->
<!ENTITY % ulink.element "INCLUDE">
<![%ulink.element;[
<!ELEMENT ulink %ho; (%para.char.mix;)*
- %links.exclusion;>
+ %links.exclusion;>
<!--end of ulink.element-->]]>
<!-- URL: uniform resource locator; the target of the ULink -->
@@ -7657,11 +7657,11 @@ OtherCredit. -->
<!ENTITY % ulink.attlist "INCLUDE">
<![%ulink.attlist;[
<!ATTLIST ulink
- url CDATA #REQUIRED
- type CDATA #IMPLIED
- %common.attrib;
- %ulink.role.attrib;
- %local.ulink.attrib;
+ url CDATA #REQUIRED
+ type CDATA #IMPLIED
+ %common.attrib;
+ %ulink.role.attrib;
+ %local.ulink.attrib;
>
<!--end of ulink.attlist-->]]>
<!--end of ulink.module-->]]>
@@ -7682,10 +7682,10 @@ OtherCredit. -->
<!ENTITY % footnoteref.attlist "INCLUDE">
<![%footnoteref.attlist;[
<!ATTLIST footnoteref
- %linkendreq.attrib; %label.attrib;
- %common.attrib;
- %footnoteref.role.attrib;
- %local.footnoteref.attrib;
+ %linkendreq.attrib; %label.attrib;
+ %common.attrib;
+ %footnoteref.role.attrib;
+ %local.footnoteref.attrib;
>
<!--end of footnoteref.attlist-->]]>
<!--end of footnoteref.module-->]]>
@@ -7701,18 +7701,18 @@ OtherCredit. -->
<!--end of xref.element-->]]>
<!-- Endterm: ID of element containing text that is to be
- fetched from elsewhere in the document to appear as
- the content of this element -->
+ fetched from elsewhere in the document to appear as
+ the content of this element -->
<!-- to linked-to object -->
<!ENTITY % xref.attlist "INCLUDE">
<![%xref.attlist;[
<!ATTLIST xref
- endterm IDREF #IMPLIED
- %linkendreq.attrib; %common.attrib;
- %xref.role.attrib;
- %local.xref.attrib;
+ endterm IDREF #IMPLIED
+ %linkendreq.attrib; %common.attrib;
+ %xref.role.attrib;
+ %local.xref.attrib;
>
<!--end of xref.attlist-->]]>
<!--end of xref.module-->]]>
@@ -7736,12 +7736,12 @@ OtherCredit. -->
<!ENTITY % anchor.attlist "INCLUDE">
<![%anchor.attlist;[
<!ATTLIST anchor
- %idreq.attrib; %pagenum.attrib; %remap.attrib;
- %xreflabel.attrib;
- %revisionflag.attrib;
- %effectivity.attrib;
- %anchor.role.attrib;
- %local.anchor.attrib;
+ %idreq.attrib; %pagenum.attrib; %remap.attrib;
+ %xreflabel.attrib;
+ %revisionflag.attrib;
+ %effectivity.attrib;
+ %anchor.role.attrib;
+ %local.anchor.attrib;
>
<!--end of anchor.attlist-->]]>
<!--end of anchor.module-->]]>
@@ -7762,10 +7762,10 @@ OtherCredit. -->
<!ENTITY % beginpage.attlist "INCLUDE">
<![%beginpage.attlist;[
<!ATTLIST beginpage
- %pagenum.attrib;
- %common.attrib;
- %beginpage.role.attrib;
- %local.beginpage.attrib;
+ %pagenum.attrib;
+ %common.attrib;
+ %beginpage.role.attrib;
+ %local.beginpage.attrib;
>
<!--end of beginpage.attlist-->]]>
<!--end of beginpage.module-->]]>
@@ -7783,43 +7783,43 @@ OtherCredit. -->
<!ENTITY % indexterm.element "INCLUDE">
<![%indexterm.element;[
<!ELEMENT indexterm %ho; (primary?, ((secondary, ((tertiary, (see|seealso+)?)
- | see | seealso+)?) | see | seealso+)?)
- %ubiq.exclusion;>
+ | see | seealso+)?) | see | seealso+)?)
+ %ubiq.exclusion;>
<!--end of indexterm.element-->]]>
<!-- Scope: Indicates which generated indices the IndexTerm
- should appear in: Global (whole document set), Local (this
- document only), or All (both) -->
+ should appear in: Global (whole document set), Local (this
+ document only), or All (both) -->
<!-- Significance: Whether this IndexTerm is the most pertinent
- of its series (Preferred) or not (Normal, the default) -->
+ of its series (Preferred) or not (Normal, the default) -->
<!-- Class: Indicates type of IndexTerm; default is Singular,
- or EndOfRange if StartRef is supplied; StartOfRange value
- must be supplied explicitly on starts of ranges -->
+ or EndOfRange if StartRef is supplied; StartOfRange value
+ must be supplied explicitly on starts of ranges -->
<!-- StartRef: ID of the IndexTerm that starts the indexing
- range ended by this IndexTerm -->
+ range ended by this IndexTerm -->
<!-- Zone: IDs of the elements to which the IndexTerm applies,
- and indicates that the IndexTerm applies to those entire
- elements rather than the point at which the IndexTerm
- occurs -->
+ and indicates that the IndexTerm applies to those entire
+ elements rather than the point at which the IndexTerm
+ occurs -->
<!ENTITY % indexterm.attlist "INCLUDE">
<![%indexterm.attlist;[
<!ATTLIST indexterm
- %pagenum.attrib;
- scope (all
- |global
- |local) #IMPLIED
- significance (preferred
- |normal) "normal"
- class (singular
- |startofrange
- |endofrange) #IMPLIED
- startref IDREF #IMPLIED
- zone IDREFS #IMPLIED
- %common.attrib;
- %indexterm.role.attrib;
- %local.indexterm.attrib;
+ %pagenum.attrib;
+ scope (all
+ |global
+ |local) #IMPLIED
+ significance (preferred
+ |normal) "normal"
+ class (singular
+ |startofrange
+ |endofrange) #IMPLIED
+ startref IDREF #IMPLIED
+ zone IDREFS #IMPLIED
+ %common.attrib;
+ %indexterm.role.attrib;
+ %local.indexterm.attrib;
>
<!--end of indexterm.attlist-->]]>
<!--end of indexterm.module-->]]>
@@ -7835,15 +7835,15 @@ OtherCredit. -->
<!ELEMENT primary %ho; (%ndxterm.char.mix;)*>
<!--end of primary.element-->]]>
<!-- SortAs: Alternate sort string for index sorting, e.g.,
- "fourteen" for an element containing "14" -->
+ "fourteen" for an element containing "14" -->
<!ENTITY % primary.attlist "INCLUDE">
<![%primary.attlist;[
<!ATTLIST primary
- sortas CDATA #IMPLIED
- %common.attrib;
- %primsecter.role.attrib;
- %local.primsecter.attrib;
+ sortas CDATA #IMPLIED
+ %common.attrib;
+ %primsecter.role.attrib;
+ %local.primsecter.attrib;
>
<!--end of primary.attlist-->]]>
@@ -7853,15 +7853,15 @@ OtherCredit. -->
<!ELEMENT secondary %ho; (%ndxterm.char.mix;)*>
<!--end of secondary.element-->]]>
<!-- SortAs: Alternate sort string for index sorting, e.g.,
- "fourteen" for an element containing "14" -->
+ "fourteen" for an element containing "14" -->
<!ENTITY % secondary.attlist "INCLUDE">
<![%secondary.attlist;[
<!ATTLIST secondary
- sortas CDATA #IMPLIED
- %common.attrib;
- %primsecter.role.attrib;
- %local.primsecter.attrib;
+ sortas CDATA #IMPLIED
+ %common.attrib;
+ %primsecter.role.attrib;
+ %local.primsecter.attrib;
>
<!--end of secondary.attlist-->]]>
@@ -7871,15 +7871,15 @@ OtherCredit. -->
<!ELEMENT tertiary %ho; (%ndxterm.char.mix;)*>
<!--end of tertiary.element-->]]>
<!-- SortAs: Alternate sort string for index sorting, e.g.,
- "fourteen" for an element containing "14" -->
+ "fourteen" for an element containing "14" -->
<!ENTITY % tertiary.attlist "INCLUDE">
<![%tertiary.attlist;[
<!ATTLIST tertiary
- sortas CDATA #IMPLIED
- %common.attrib;
- %primsecter.role.attrib;
- %local.primsecter.attrib;
+ sortas CDATA #IMPLIED
+ %common.attrib;
+ %primsecter.role.attrib;
+ %local.primsecter.attrib;
>
<!--end of tertiary.attlist-->]]>
@@ -7898,9 +7898,9 @@ OtherCredit. -->
<!ENTITY % see.attlist "INCLUDE">
<![%see.attlist;[
<!ATTLIST see
- %common.attrib;
- %seeseealso.role.attrib;
- %local.seeseealso.attrib;
+ %common.attrib;
+ %seeseealso.role.attrib;
+ %local.seeseealso.attrib;
>
<!--end of see.attlist-->]]>
@@ -7912,9 +7912,9 @@ OtherCredit. -->
<!ENTITY % seealso.attlist "INCLUDE">
<![%seealso.attlist;[
<!ATTLIST seealso
- %common.attrib;
- %seeseealso.role.attrib;
- %local.seeseealso.attrib;
+ %common.attrib;
+ %seeseealso.role.attrib;
+ %local.seeseealso.attrib;
>
<!--end of seealso.attlist-->]]>
<!--end of seeseealso.module-->]]>
diff --git a/etc/findbugs.xml b/etc/findbugs.xml
index 185dcd5..2b49e10 100644
--- a/etc/findbugs.xml
+++ b/etc/findbugs.xml
@@ -171,6 +171,42 @@
/>
</SplitPass>
<SplitPass>
+ <Earlier class="edu.umd.cs.findbugs.detect.FindNoSideEffectMethods"/>
+ <Later
+ class="edu.umd.cs.findbugs.detect.MethodReturnCheck"
+ />
+ </SplitPass>
+ <SplitPass>
+ <Earlier class="edu.umd.cs.findbugs.detect.FindNoSideEffectMethods"/>
+ <Later
+ class="edu.umd.cs.findbugs.detect.FindUselessObjects"
+ />
+ </SplitPass>
+ <SplitPass>
+ <Earlier class="edu.umd.cs.findbugs.detect.FindNoSideEffectMethods"/>
+ <Later
+ class="edu.umd.cs.findbugs.detect.FindDoubleCheck"
+ />
+ </SplitPass>
+ <SplitPass>
+ <Earlier class="edu.umd.cs.findbugs.detect.FindNoSideEffectMethods"/>
+ <Later
+ class="edu.umd.cs.findbugs.detect.RepeatedConditionals"
+ />
+ </SplitPass>
+ <SplitPass>
+ <Earlier class="edu.umd.cs.findbugs.detect.BuildStringPassthruGraph"/>
+ <Later class="edu.umd.cs.findbugs.detect.DumbMethodInvocations"/>
+ </SplitPass>
+ <SplitPass>
+ <Earlier class="edu.umd.cs.findbugs.detect.BuildStringPassthruGraph"/>
+ <Later class="edu.umd.cs.findbugs.detect.CrossSiteScripting"/>
+ </SplitPass>
+ <SplitPass>
+ <Earlier class="edu.umd.cs.findbugs.detect.BuildStringPassthruGraph"/>
+ <Later class="edu.umd.cs.findbugs.detect.FindSqlInjection"/>
+ </SplitPass>
+ <SplitPass>
<Earlier class="edu.umd.cs.findbugs.detect.CalledMethods"/>
<Later class="edu.umd.cs.findbugs.detect.FindNullDeref"/>
</SplitPass>
@@ -253,6 +289,9 @@
<Later class="edu.umd.cs.findbugs.detect.CheckExpectedWarnings"/>
</SplitPass>
</OrderingConstraints>
+ <Detector class="edu.umd.cs.findbugs.detect.FindRoughConstants"
+ reports="CNT_ROUGH_CONSTANT_VALUE" speed="fast" hidden="false"/>
+
<Detector class="edu.umd.cs.findbugs.detect.FunctionsThatMightBeMistakenForProcedures" speed="fast"
reports="" hidden="true"/>
<Detector class="edu.umd.cs.findbugs.detect.NoteSuppressedWarnings" speed="fast"
@@ -271,6 +310,8 @@
reports="NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" hidden="false"/>
<Detector class="edu.umd.cs.findbugs.detect.BooleanReturnNull"
reports="NP_BOOLEAN_RETURN_NULL" hidden="false"/>
+ <Detector class="edu.umd.cs.findbugs.detect.OptionalReturnNull"
+ reports="NP_OPTIONAL_RETURN_NULL" hidden="false"/>
<Detector class="edu.umd.cs.findbugs.detect.NoteJCIPAnnotation" speed="fast" reports=""
hidden="true"/>
<Detector class="edu.umd.cs.findbugs.detect.Methods" speed="fast" reports=""
@@ -279,13 +320,17 @@
disabled="false" hidden="true"/>
<Detector class="edu.umd.cs.findbugs.detect.CalledMethods" speed="fast" reports=""
disabled="false" hidden="true"/>
+ <Detector class="edu.umd.cs.findbugs.detect.FindNoSideEffectMethods" speed="moderate" reports=""
+ disabled="false" hidden="true"/>
+ <Detector class="edu.umd.cs.findbugs.detect.BuildStringPassthruGraph" speed="fast" reports=""
+ disabled="false" hidden="true"/>
<Detector class="edu.umd.cs.findbugs.detect.ConfusionBetweenInheritedAndOuterMethod"
speed="moderate" reports="IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD"
disabled="false" hidden="false"/>
<Detector class="edu.umd.cs.findbugs.detect.SynchronizationOnSharedBuiltinConstant"
speed="fast"
reports="DL_SYNCHRONIZATION_ON_BOOLEAN,DL_SYNCHRONIZATION_ON_UNSHARED_BOXED_PRIMITIVE,DL_SYNCHRONIZATION_ON_BOXED_PRIMITIVE,DL_SYNCHRONIZATION_ON_SHARED_CONSTANT"
- hidden="true"/>
+ hidden="false"/>
<Detector class="edu.umd.cs.findbugs.detect.NoteCheckReturnValueAnnotations" speed="fast"
reports="" requirejre="1.5" hidden="true"/>
<Detector class="edu.umd.cs.findbugs.detect.FieldItemSummary" speed="fast" reports=""
@@ -315,10 +360,14 @@
reports="HSC_HUGE_SHARED_STRING_CONSTANT"/>
<Detector class="edu.umd.cs.findbugs.detect.FinalizerNullsFields" speed="fast"
reports="FI_FINALIZER_NULLS_FIELDS,FI_FINALIZER_ONLY_NULLS_FIELDS"/>
+ <Detector class="edu.umd.cs.findbugs.detect.MutableEnum" speed="fast"
+ reports="ME_MUTABLE_ENUM_FIELD,ME_ENUM_FIELD_SETTER"/>
<Detector class="edu.umd.cs.findbugs.detect.InconsistentAnnotations" speed="fast"
reports="NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE"/>
<Detector class="edu.umd.cs.findbugs.detect.RepeatedConditionals" speed="fast"
reports="RpC_REPEATED_CONDITIONAL_TEST"/>
+ <Detector class="edu.umd.cs.findbugs.detect.RedundantConditions" speed="fast"
+ reports="UC_USELESS_CONDITION,UC_USELESS_CONDITION_TYPE"/>
<Detector class="edu.umd.cs.findbugs.detect.CallToUnsupportedMethod" speed="fast"
disabled="true" reports="DMI_UNSUPPORTED_METHOD"/>
<Detector class="edu.umd.cs.findbugs.detect.FormatStringChecker" speed="fast"
@@ -364,15 +413,18 @@
reports="DMI_EMPTY_DB_PASSWORD,DMI_CONSTANT_DB_PASSWORD,DMI_USELESS_SUBSTRING,DMI_HARDCODED_ABSOLUTE_FILENAME"/>
<Detector class="edu.umd.cs.findbugs.detect.URLProblems" speed="fast"
reports="DMI_BLOCKING_METHODS_ON_URL,DMI_COLLECTION_OF_URLS"/>
+ <Detector class="edu.umd.cs.findbugs.detect.CovariantArrayAssignment" speed="fast" disabled="true"
+ reports="CAA_COVARIANT_ARRAY_FIELD,CAA_COVARIANT_ARRAY_RETURN,CAA_COVARIANT_ARRAY_LOCAL,CAA_COVARIANT_ARRAY_ELEMENT_STORE"/>
<Detector class="edu.umd.cs.findbugs.detect.DumbMethods" speed="fast"
- reports="NP_IMMEDIATE_DEREFERENCE_OF_READLINE,RV_01_TO_INT,DM_RUN_FINALIZERS_ON_EXIT,DM_STRING_CTOR,DM_STRING_VOID_CTOR,DM_STRING_TOSTRING,DM_GC,DM_BOOLEAN_CTOR,DM_EXIT,DM_CONVERT_CASE,SW_SWING_METHODS_INVOKED_IN_SWING_THREAD,DM_BOXED_PRIMITIVE_TOSTRING,DM_BOXED_PRIMITIVE_FOR_PARSING,DM_NEW_FOR_GETCLASS,DM_NEXTINT_VIA_NEXTDOUBLE,DM_USELESS_THREAD,DM_MONITOR_WAIT_ON_CONDITION,DMI_CALLING_NEXT_FROM_HASNEXT,RV_REM_OF_HASHCODE,RV_REM_OF_RANDOM_INT,RV_ABSOLUTE_VALUE_OF_RAN [...]
+ reports="NP_IMMEDIATE_DEREFERENCE_OF_READLINE,RV_01_TO_INT,DM_INVALID_MIN_MAX,DM_RUN_FINALIZERS_ON_EXIT,DM_STRING_CTOR,DM_STRING_VOID_CTOR,DM_STRING_TOSTRING,DM_GC,DM_BOOLEAN_CTOR,DM_EXIT,DM_CONVERT_CASE,SW_SWING_METHODS_INVOKED_IN_SWING_THREAD,DM_BOXED_PRIMITIVE_TOSTRING,DM_BOXED_PRIMITIVE_FOR_PARSING,DM_BOXED_PRIMITIVE_FOR_COMPARE,DM_NEW_FOR_GETCLASS,DM_NEXTINT_VIA_NEXTDOUBLE,DM_USELESS_THREAD,DM_MONITOR_WAIT_ON_CONDITION,DMI_CALLING_NEXT_FROM_HASNEXT,RV_REM_OF_HASH [...]
+ "/>
<Detector class="edu.umd.cs.findbugs.detect.NumberConstructor" speed="fast"
disabled="false" reports="DM_NUMBER_CTOR,DM_FP_NUMBER_CTOR"/>
<Detector class="edu.umd.cs.findbugs.detect.FindSqlInjection" speed="moderate"
reports="SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE,SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING"
disabled="false"/>
<Detector class="edu.umd.cs.findbugs.detect.FindDoubleCheck" speed="fast"
- reports="DC_DOUBLECHECK"/>
+ reports="DC_DOUBLECHECK,DC_PARTIALLY_CONSTRUCTED"/>
<Detector class="edu.umd.cs.findbugs.detect.FindFinalizeInvocations" speed="fast"
reports="FI_PUBLIC_SHOULD_BE_PROTECTED,FI_EMPTY,FI_NULLIFY_SUPER,FI_USELESS,FI_MISSING_SUPER_CALL,FI_EXPLICIT_INVOCATION"/>
<Detector class="edu.umd.cs.findbugs.detect.FindHEmismatch" speed="fast"
@@ -411,8 +463,10 @@
speed="fast" reports="ML_SYNC_ON_FIELD_TO_GUARD_CHANGING_THAT_FIELD"/>
<Detector class="edu.umd.cs.findbugs.detect.MutableLock" speed="fast"
reports="ML_SYNC_ON_UPDATED_FIELD"/>
+ <Detector class="edu.umd.cs.findbugs.detect.FindUselessObjects" speed="fast"
+ reports="UC_USELESS_OBJECT,UC_USELESS_OBJECT_STACK"/>
<Detector class="edu.umd.cs.findbugs.detect.MutableStaticFields" speed="fast"
- reports="MS_OOI_PKGPROTECT,MS_FINAL_PKGPROTECT,MS_SHOULD_BE_REFACTORED_TO_BE_FINAL,MS_SHOULD_BE_FINAL,MS_PKGPROTECT,MS_MUTABLE_HASHTABLE,MS_MUTABLE_ARRAY,MS_CANNOT_BE_FINAL"/>
+ reports="MS_OOI_PKGPROTECT,MS_FINAL_PKGPROTECT,MS_SHOULD_BE_REFACTORED_TO_BE_FINAL,MS_SHOULD_BE_FINAL,MS_PKGPROTECT,MS_MUTABLE_HASHTABLE,MS_MUTABLE_ARRAY,MS_CANNOT_BE_FINAL,MS_MUTABLE_COLLECTION,MS_MUTABLE_COLLECTION_PKGPROTECT"/>
<Detector class="edu.umd.cs.findbugs.detect.Naming" speed="fast"
reports="NM_WRONG_PACKAGE,NM_WRONG_PACKAGE_INTENTIONAL,NM_VERY_CONFUSING,NM_VERY_CONFUSING_INTENTIONAL,NM_CONFUSING,NM_METHOD_CONSTRUCTOR_CONFUSION,NM_LCASE_HASHCODE,NM_LCASE_TOSTRING,NM_BAD_EQUAL,NM_CLASS_NAMING_CONVENTION,NM_FIELD_NAMING_CONVENTION,NM_METHOD_NAMING_CONVENTION,NM_CLASS_NOT_EXCEPTION,NM_SAME_SIMPLE_NAME_AS_SUPERCLASS,NM_SAME_SIMPLE_NAME_AS_INTERFACE"/>
<Detector class="edu.umd.cs.findbugs.detect.ReadReturnShouldBeChecked" speed="fast"
@@ -429,6 +483,8 @@
reports="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD,NP_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD,NP_UNWRITTEN_FIELD,UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR,UWF_NULL_FIELD,UWF_UNWRITTEN_FIELD,SS_SHOULD_BE_STATIC,UUF_UNUSED_FIELD,URF_UNREAD_FIELD,SIC_INNER_SHOULD_BE_STATIC,SIC_INNER_SHOULD_BE_STATIC_ANON,SIC_INNER_SHOULD_BE_STATIC_NEEDS_THIS,SIC_THREADLOCAL_DEADLY_EMBRACE,UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD,UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD,URF_UNREAD_PUBLIC_OR_PROTECTED [...]
<Detector class="edu.umd.cs.findbugs.detect.WaitInLoop" speed="fast"
reports="WA_NOT_IN_LOOP,WA_AWAIT_NOT_IN_LOOP,NO_NOTIFY_NOT_NOTIFYALL"/>
+ <Detector class="edu.umd.cs.findbugs.detect.FindComparatorProblems" speed="fast"
+ reports="CO_COMPARETO_RESULTS_MIN_VALUE,CO_COMPARETO_INCORRECT_FLOATING"/>
<Detector class="edu.umd.cs.findbugs.detect.FindNullDeref" speed="slow"
reports="NP_DEREFERENCE_OF_READLINE_VALUE,NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE,NP_TOSTRING_COULD_RETURN_NULL,NP_CLONE_COULD_RETURN_NULL,NP_ALWAYS_NULL_EXCEPTION,NP_ALWAYS_NULL,NP_STORE_INTO_NONNULL_FIELD,NP_NULL_ON_SOME_PATH_EXCEPTION,NP_NULL_ON_SOME_PATH,NP_NULL_PARAM_DEREF_NONVIRTUAL,NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS,NP_NULL_PARAM_DEREF,RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE,RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE,RCN_REDUNDANT_NULLCHECK_OF_NONNULL_ [...]
<Detector
@@ -463,7 +519,11 @@
reports="UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS"/>
<Detector class="edu.umd.cs.findbugs.detect.StringConcatenation" speed="fast"
reports="SBSC_USE_STRINGBUFFER_CONCATENATION"/>
- <Detector class="edu.umd.cs.findbugs.detect.InefficientToArray" speed="fast"
+ <Detector class="edu.umd.cs.findbugs.detect.InefficientInitializationInsideLoop" speed="fast" disabled="true"
+ reports="IIL_PREPARE_STATEMENT_IN_LOOP,IIL_PATTERN_COMPILE_IN_LOOP,IIL_PATTERN_COMPILE_IN_LOOP_INDIRECT,IIL_ELEMENTS_GET_LENGTH_IN_LOOP"/>
+ <Detector class="edu.umd.cs.findbugs.detect.InefficientIndexOf" speed="fast" disabled="true"
+ reports="IIO_INEFFICIENT_INDEX_OF,IIO_INEFFICIENT_LAST_INDEX_OF"/>
+ <Detector class="edu.umd.cs.findbugs.detect.InefficientToArray" speed="fast" disabled="true"
reports="ITA_INEFFICIENT_TO_ARRAY"/>
<Detector class="edu.umd.cs.findbugs.detect.InvalidJUnitTest" speed="fast"
reports="IJU_SETUP_NO_SUPER,IJU_TEARDOWN_NO_SUPER,IJU_SUITE_NOT_STATIC,IJU_NO_TESTS,IJU_BAD_SUITE_METHOD"/>
@@ -504,7 +564,7 @@
<Detector class="edu.umd.cs.findbugs.detect.BadUseOfReturnValue" speed="fast"
reports="RV_CHECK_FOR_POSITIVE_INDEXOF,RV_DONT_JUST_NULL_CHECK_READLINE"/>
<Detector class="edu.umd.cs.findbugs.detect.MethodReturnCheck" speed="fast"
- reports="RV_RETURN_VALUE_IGNORED,RV_RETURN_VALUE_IGNORED_BAD_PRACTICE,RV_EXCEPTION_NOT_THROWN,RV_CHECK_COMPARETO_FOR_SPECIFIC_RETURN_VALUE,RV_RETURN_VALUE_IGNORED_INFERRED"/>
+ reports="RV_RETURN_VALUE_IGNORED,RV_RETURN_VALUE_IGNORED_BAD_PRACTICE,RV_EXCEPTION_NOT_THROWN,RV_CHECK_COMPARETO_FOR_SPECIFIC_RETURN_VALUE,RV_RETURN_VALUE_IGNORED_INFERRED,RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT,UC_USELESS_VOID_METHOD"/>
<Detector class="edu.umd.cs.findbugs.detect.IDivResultCastToDouble" speed="fast"
reports="ICAST_IDIV_CAST_TO_DOUBLE,ICAST_INT_CAST_TO_DOUBLE_PASSED_TO_CEIL,ICAST_INT_CAST_TO_FLOAT_PASSED_TO_ROUND"/>
<Detector class="edu.umd.cs.findbugs.detect.FindBadCast2" speed="fast"
@@ -525,7 +585,7 @@
<Detector class="edu.umd.cs.findbugs.detect.VarArgsProblems" speed="fast"
reports="VA_PRIMITIVE_ARRAY_PASSED_TO_OBJECT_VARARG"/>
<Detector class="edu.umd.cs.findbugs.detect.FindPuzzlers" speed="fast"
- reports="DLS_DEAD_LOCAL_STORE_IN_RETURN,EC_BAD_ARRAY_COMPARE,DLS_OVERWRITTEN_INCREMENT,ICAST_BAD_SHIFT_AMOUNT,ICAST_QUESTIONABLE_UNSIGNED_RIGHT_SHIFT,DMI_BAD_MONTH,IM_MULTIPLYING_RESULT_OF_IREM,IM_BAD_CHECK_FOR_ODD,DMI_INVOKING_TOSTRING_ON_ARRAY,DMI_INVOKING_TOSTRING_ON_ANONYMOUS_ARRAY,IM_AVERAGE_COMPUTATION_COULD_OVERFLOW,IC_SUPERCLASS_USES_SUBCLASS_DURING_INITIALIZATION,ICAST_INTEGER_MULTIPLY_CAST_TO_LONG,BX_UNBOXED_AND_COERCED_FOR_TERNARY_OPERATOR,BX_BOXING_IMMEDIA [...]
+ reports="DLS_DEAD_LOCAL_STORE_IN_RETURN,EC_BAD_ARRAY_COMPARE,DLS_OVERWRITTEN_INCREMENT,ICAST_BAD_SHIFT_AMOUNT,BSHIFT_WRONG_ADD_PRIORITY,ICAST_QUESTIONABLE_UNSIGNED_RIGHT_SHIFT,DMI_BAD_MONTH,IM_MULTIPLYING_RESULT_OF_IREM,IM_BAD_CHECK_FOR_ODD,DMI_INVOKING_TOSTRING_ON_ARRAY,DMI_INVOKING_TOSTRING_ON_ANONYMOUS_ARRAY,IM_AVERAGE_COMPUTATION_COULD_OVERFLOW,IC_SUPERCLASS_USES_SUBCLASS_DURING_INITIALIZATION,ICAST_INTEGER_MULTIPLY_CAST_TO_LONG,BX_UNBOXED_AND_COERCED_FOR_TERNARY_ [...]
<Detector class="edu.umd.cs.findbugs.detect.IntCast2LongAsInstant" speed="fast"
reports="ICAST_INT_2_LONG_AS_INSTANT"/>
<Detector class="edu.umd.cs.findbugs.detect.FindSleepWithLockHeld" speed="slow"
@@ -613,6 +673,8 @@
<BugCode abbrev="FB"/>
<BugCode abbrev="AT"/>
<!-- Bug patterns -->
+ <BugPattern abbrev="CNT" type="CNT_ROUGH_CONSTANT_VALUE" category="BAD_PRACTICE"/>
+
<BugPattern abbrev="AT" type="AT_OPERATION_SEQUENCE_ON_CONCURRENT_ABSTRACTION"
category="MT_CORRECTNESS"/>
<BugPattern abbrev="XSS" type="XSS_REQUEST_PARAMETER_TO_SEND_ERROR" category="SECURITY" cweid="81"/>
@@ -634,7 +696,8 @@
<BugPattern abbrev="NP" type="NP_SYNC_AND_NULL_CHECK_FIELD" category="MT_CORRECTNESS"
cweid="585"/>
<BugPattern abbrev="NP" type="NP_BOOLEAN_RETURN_NULL" category="BAD_PRACTICE"/>
- <BugPattern abbrev="NP" type="NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" category="CORRECTNESS"/>
+ <BugPattern abbrev="NP" type="NP_OPTIONAL_RETURN_NULL" category="CORRECTNESS"/>
+ <BugPattern abbrev="NP" type="NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" category="CORRECTNESS"/>
<BugPattern abbrev="VR" type="VR_UNRESOLVABLE_REFERENCE" category="CORRECTNESS"
experimental="true"/>
<BugPattern abbrev="SW" type="SW_SWING_METHODS_INVOKED_IN_SWING_THREAD"
@@ -667,6 +730,14 @@
category="MALICIOUS_CODE"/>
<BugPattern abbrev="IMSE" type="IMSE_DONT_CATCH_IMSE" category="BAD_PRACTICE"/>
<BugPattern abbrev="FL" type="FL_MATH_USING_FLOAT_PRECISION" category="CORRECTNESS"/>
+ <BugPattern abbrev="CAA" type="CAA_COVARIANT_ARRAY_FIELD" category="STYLE"
+ experimental="true"/>
+ <BugPattern abbrev="CAA" type="CAA_COVARIANT_ARRAY_RETURN" category="STYLE"
+ experimental="true"/>
+ <BugPattern abbrev="CAA" type="CAA_COVARIANT_ARRAY_LOCAL" category="STYLE"
+ experimental="true"/>
+ <BugPattern abbrev="CAA" type="CAA_COVARIANT_ARRAY_ELEMENT_STORE" category="CORRECTNESS"
+ experimental="true"/>
<BugPattern abbrev="CN" type="CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE"
category="BAD_PRACTICE"/>
<BugPattern abbrev="CN" type="CN_IDIOM" category="BAD_PRACTICE"/>
@@ -706,8 +777,9 @@
<BugPattern abbrev="Dm" type="DM_CONVERT_CASE" category="I18N"/>
<BugPattern abbrev="Bx" type="DM_BOXED_PRIMITIVE_TOSTRING" category="PERFORMANCE"/>
<BugPattern abbrev="Bx" type="DM_BOXED_PRIMITIVE_FOR_PARSING" category="PERFORMANCE"/>
+ <BugPattern abbrev="Bx" type="DM_BOXED_PRIMITIVE_FOR_COMPARE" category="PERFORMANCE"/>
<BugPattern abbrev="Bx" type="BX_UNBOXED_AND_COERCED_FOR_TERNARY_OPERATOR"
- category="CORRECTNESS"/>
+ category="PERFORMANCE"/>
<BugPattern abbrev="Bx" type="BX_UNBOXING_IMMEDIATELY_REBOXED" category="PERFORMANCE"/>
<BugPattern abbrev="Bx" type="BX_BOXING_IMMEDIATELY_UNBOXED" category="PERFORMANCE"/>
<BugPattern abbrev="Bx" type="BX_BOXING_IMMEDIATELY_UNBOXED_TO_PERFORM_COERCION"
@@ -724,6 +796,7 @@
<BugPattern abbrev="RV" type="RV_REM_OF_RANDOM_INT" category="STYLE"/>
<BugPattern abbrev="RV" type="RV_REM_OF_HASHCODE" category="STYLE"/>
<BugPattern abbrev="RV" type="RV_01_TO_INT" category="CORRECTNESS"/>
+ <BugPattern abbrev="Dm" type="DM_INVALID_MIN_MAX" category="CORRECTNESS"/>
<BugPattern abbrev="Dm" type="DM_NEXTINT_VIA_NEXTDOUBLE" category="PERFORMANCE"/>
<BugPattern abbrev="Dm" type="DM_USELESS_THREAD" category="MT_CORRECTNESS"/>
<BugPattern abbrev="SQL" type="SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE"
@@ -731,6 +804,7 @@
<BugPattern abbrev="SQL" type="SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING"
category="SECURITY" cweid="89"/>
<BugPattern abbrev="DC" type="DC_DOUBLECHECK" category="MT_CORRECTNESS" cweid="609"/>
+ <BugPattern abbrev="DC" type="DC_PARTIALLY_CONSTRUCTED" category="MT_CORRECTNESS" cweid="609"/>
<BugPattern abbrev="FI" type="FI_PUBLIC_SHOULD_BE_PROTECTED" category="MALICIOUS_CODE"
cweid="583"/>
<BugPattern abbrev="FI" type="FI_EMPTY" category="BAD_PRACTICE"/>
@@ -753,7 +827,8 @@
<BugPattern abbrev="Eq" type="EQ_OTHER_NO_OBJECT" category="CORRECTNESS"/>
<BugPattern abbrev="Eq" type="EQ_SELF_NO_OBJECT" category="BAD_PRACTICE"/>
<BugPattern abbrev="Co" type="CO_SELF_NO_OBJECT" category="BAD_PRACTICE"/>
- <BugPattern abbrev="Co" type="CO_COMPARETO_RESULTS_MIN_VALUE" category="CORRECTNESS"/>
+ <BugPattern abbrev="Co" type="CO_COMPARETO_RESULTS_MIN_VALUE" category="BAD_PRACTICE"/>
+ <BugPattern abbrev="Co" type="CO_COMPARETO_INCORRECT_FLOATING" category="BAD_PRACTICE"/>
<BugPattern abbrev="RV" type="RV_NEGATING_RESULT_OF_COMPARETO" category="BAD_PRACTICE"/>
<BugPattern abbrev="ES" type="ES_COMPARING_STRINGS_WITH_EQ" category="BAD_PRACTICE"/>
<BugPattern abbrev="ES" type="ES_COMPARING_PARAMETER_STRING_WITH_EQ"
@@ -816,7 +891,11 @@
<BugPattern abbrev="MS" type="MS_PKGPROTECT" category="MALICIOUS_CODE"/>
<BugPattern abbrev="MS" type="MS_MUTABLE_HASHTABLE" category="MALICIOUS_CODE"/>
<BugPattern abbrev="MS" type="MS_MUTABLE_ARRAY" category="MALICIOUS_CODE"/>
+ <BugPattern abbrev="MS" type="MS_MUTABLE_COLLECTION" category="MALICIOUS_CODE"/>
+ <BugPattern abbrev="MS" type="MS_MUTABLE_COLLECTION_PKGPROTECT" category="MALICIOUS_CODE"/>
<BugPattern abbrev="MS" type="MS_CANNOT_BE_FINAL" category="MALICIOUS_CODE"/>
+ <BugPattern abbrev="ME" type="ME_MUTABLE_ENUM_FIELD" category="BAD_PRACTICE"/>
+ <BugPattern abbrev="ME" type="ME_ENUM_FIELD_SETTER" category="BAD_PRACTICE"/>
<BugPattern abbrev="Nm" type="NM_METHOD_NAMING_CONVENTION" category="BAD_PRACTICE"/>
<BugPattern abbrev="Nm" type="NM_FIELD_NAMING_CONVENTION" category="BAD_PRACTICE"/>
<BugPattern abbrev="Nm" type="NM_SAME_SIMPLE_NAME_AS_INTERFACE" category="BAD_PRACTICE"/>
@@ -885,8 +964,18 @@
<BugPattern abbrev="Wa" type="WA_NOT_IN_LOOP" category="MT_CORRECTNESS"/>
<BugPattern abbrev="Wa" type="WA_AWAIT_NOT_IN_LOOP" category="MT_CORRECTNESS"/>
<BugPattern abbrev="No" type="NO_NOTIFY_NOT_NOTIFYALL" category="MT_CORRECTNESS"/>
+ <BugPattern abbrev="UC" type="UC_USELESS_VOID_METHOD" category="STYLE"/>
+ <BugPattern abbrev="UC" type="UC_USELESS_CONDITION" category="STYLE"/>
+ <BugPattern abbrev="UC" type="UC_USELESS_CONDITION_TYPE" category="STYLE"/>
+ <BugPattern abbrev="UC" type="UC_USELESS_OBJECT" category="STYLE"/>
+ <BugPattern abbrev="UC" type="UC_USELESS_OBJECT_STACK" category="STYLE"/>
+ <BugPattern abbrev="RANGE" type="RANGE_ARRAY_INDEX" category="CORRECTNESS"/>
+ <BugPattern abbrev="RANGE" type="RANGE_ARRAY_OFFSET" category="CORRECTNESS"/>
+ <BugPattern abbrev="RANGE" type="RANGE_ARRAY_LENGTH" category="CORRECTNESS"/>
+ <BugPattern abbrev="RANGE" type="RANGE_STRING_INDEX" category="CORRECTNESS"/>
<BugPattern abbrev="RV" type="RV_RETURN_VALUE_IGNORED" category="CORRECTNESS"/>
<BugPattern abbrev="RV" type="RV_RETURN_VALUE_IGNORED_INFERRED" category="STYLE"/>
+ <BugPattern abbrev="RV" type="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT" category="STYLE"/>
<BugPattern abbrev="RV" type="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE"
category="BAD_PRACTICE" cweid="253"/>
<BugPattern abbrev="RV" type="RV_EXCEPTION_NOT_THROWN" category="CORRECTNESS"/>
@@ -1002,7 +1091,20 @@
category="BAD_PRACTICE"/>
<BugPattern abbrev="SBSC" type="SBSC_USE_STRINGBUFFER_CONCATENATION"
category="PERFORMANCE"/>
- <BugPattern abbrev="ITA" type="ITA_INEFFICIENT_TO_ARRAY" category="PERFORMANCE"/>
+ <BugPattern abbrev="IIL" type="IIL_ELEMENTS_GET_LENGTH_IN_LOOP" category="PERFORMANCE"
+ experimental="true"/>
+ <BugPattern abbrev="IIL" type="IIL_PREPARE_STATEMENT_IN_LOOP" category="PERFORMANCE"
+ experimental="true"/>
+ <BugPattern abbrev="IIL" type="IIL_PATTERN_COMPILE_IN_LOOP" category="PERFORMANCE"
+ experimental="true"/>
+ <BugPattern abbrev="IIL" type="IIL_PATTERN_COMPILE_IN_LOOP_INDIRECT" category="PERFORMANCE"
+ experimental="true"/>
+ <BugPattern abbrev="IIO" type="IIO_INEFFICIENT_INDEX_OF" category="PERFORMANCE"
+ experimental="true"/>
+ <BugPattern abbrev="IIO" type="IIO_INEFFICIENT_LAST_INDEX_OF" category="PERFORMANCE"
+ experimental="true"/>
+ <BugPattern abbrev="ITA" type="ITA_INEFFICIENT_TO_ARRAY" category="PERFORMANCE"
+ experimental="true"/>
<BugPattern abbrev="IJU" type="IJU_ASSERT_METHOD_INVOKED_FROM_RUN_METHOD"
category="CORRECTNESS"/>
<BugPattern abbrev="IJU" type="IJU_BAD_SUITE_METHOD" category="CORRECTNESS"/>
@@ -1080,6 +1182,7 @@
category="CORRECTNESS"/>
<BugPattern abbrev="DLS" type="DLS_OVERWRITTEN_INCREMENT" category="CORRECTNESS"/>
<BugPattern abbrev="BSHIFT" type="ICAST_BAD_SHIFT_AMOUNT" category="CORRECTNESS"/>
+ <BugPattern abbrev="BSHIFT" type="BSHIFT_WRONG_ADD_PRIORITY" category="CORRECTNESS"/>
<BugPattern abbrev="IM" type="IM_MULTIPLYING_RESULT_OF_IREM" category="CORRECTNESS"/>
<BugPattern abbrev="IM" type="IM_BAD_CHECK_FOR_ODD" category="STYLE"/>
<BugPattern abbrev="IM" type="IM_AVERAGE_COMPUTATION_COULD_OVERFLOW" category="STYLE"/>
diff --git a/etc/findbugsfilter.xsd b/etc/findbugsfilter.xsd
new file mode 100644
index 0000000..6fe5586
--- /dev/null
+++ b/etc/findbugsfilter.xsd
@@ -0,0 +1,400 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schema targetNamespace="http://findbugs.sourceforge.net/filter/3.0.0" elementFormDefault="unqualified"
+ xmlns="http://www.w3.org/2001/XMLSchema" xmlns:fb="http://findbugs.sourceforge.net/filter/3.0.0">
+
+ <element name="FindBugsFilter" type="fb:FindBugsFilterType"></element>
+
+ <element name="Match" type="fb:MatchType"></element>
+
+ <element name="Bug" type="fb:BugType">
+ <annotation>
+ <documentation>This element specifies a particular bug pattern or patterns to match.
+ If more than one attribute is specified on the same Bug element, all bug patterns that match either one of specified
+ pattern names, abbreviations, or categories will be matched.</documentation>
+ </annotation>
+ </element>
+
+ <element name="BugCode" type="fb:BugCodeType">
+ <annotation>
+ <documentation>This element specifies a particular bug code or multiple bug codes to match.
+ </documentation>
+ </annotation>
+ </element>
+
+ <element name="BugPattern" type="fb:BugPatternType">
+ <annotation>
+ <documentation>This element specifies a particular bug pattern or multiple patterns to match.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Priority" type="fb:PriorityType">
+ <annotation>
+ <documentation>This element matches warnings with a particular priority.
+ This is deprecated, 'Confidence' should be used instead</documentation>
+ </annotation>
+ </element>
+
+ <element name="Confidence" type="fb:ConfidenceType">
+ <annotation>
+ <documentation>This element matches warnings with a particular confidence.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Rank" type="fb:RankType">
+ <annotation>
+ <documentation>This element matches warnings with a particular rank.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Package" type="fb:PackageType">
+ <annotation>
+ <documentation>This element matches warnings associated with classes within the package specified using name
+ attribute.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Class" type="fb:ClassType">
+ <annotation>
+ <documentation>This element matches warnings associated with a particular class.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Type" type="fb:TypeType">
+ <annotation>
+ <documentation>This element matches warnings associated with a particular type.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Source" type="fb:SourceType">
+ <annotation>
+ <documentation>This element matches warnings associated with a particular source file name.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Method" type="fb:MethodType">
+ <annotation>
+ <documentation>This element specifies a method.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Field" type="fb:FieldType">
+ <annotation>
+ <documentation>This element specifies a field.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Local" type="fb:LocalType">
+ <annotation>
+ <documentation>This element specifies a local variable.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Or" type="fb:OrType">
+ <annotation>
+ <documentation>This element combines Match clauses as disjuncts.
+ I.e., you can put two Method elements in an Or clause in order to match either method.</documentation>
+ </annotation>
+ </element>
+
+ <element name="And" type="fb:AndType">
+ <annotation>
+ <documentation>This element combines Match clauses which both must evaluate to true.
+ I.e., you can put Bug and Confidence elements in an And clause in order to match specific bugs with given confidence only.</documentation>
+ </annotation>
+ </element>
+
+ <element name="Not" type="fb:NotType">
+ <annotation>
+ <documentation>This element inverts the included child Match.
+ I.e., you can put a Bug element in a Not clause in order to match any bug excluding the given one.</documentation>
+ </annotation>
+ </element>
+
+ <complexType name="FindBugsFilterType">
+ <sequence>
+ <element ref="fb:Match" maxOccurs="unbounded" minOccurs="0"></element>
+ </sequence>
+ </complexType>
+
+
+ <complexType name="BugCodeType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>A comma-separated list of bug code types. You can find the bug code types for particular warnings by looking at the output produced by the -xml output option (the type attribute of BugInstance elements), or from the bug descriptions document.</documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+
+ <complexType name="BugPatternType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>A comma-separated list of bug pattern types. You can find the bug pattern types for particular warnings by looking at the output produced by the -xml output option (the type attribute of BugInstance elements), or from the bug descriptions document.</documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+
+ <complexType name="BugType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="pattern" type="string">
+ <annotation>
+ <documentation>A comma-separated list of bug pattern types. You can find the bug pattern types for particular warnings by looking at the output produced by the -xml output option (the type attribute of BugInstance elements), or from the bug descriptions document.</documentation>
+ </annotation></attribute>
+ <attribute name="code" type="string">
+ <annotation>
+ <documentation>A comma-separated list of bug abbreviations.</documentation>
+ </annotation></attribute>
+ <attribute name="category" type="string">
+ <annotation>
+ <documentation>A comma separated list of bug category names.</documentation>
+ </annotation></attribute>
+ </complexType>
+
+ <complexType name="ClassType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>The exact or regex match pattern for a class name. If the name starts with the ~ character the rest of attribute content is interpreted as a Java regular expression.</documentation>
+ </annotation></attribute>
+ <attribute name="role" type="string">
+ <annotation>
+ <documentation>The class role</documentation>
+ </annotation></attribute>
+ </complexType>
+
+ <complexType name="TypeType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="descriptor" type="string">
+ <annotation>
+ <documentation>The exact or regex match pattern for type descriptor. If the descriptor starts with the ~ character the rest of attribute content is interpreted as a Java regular expression.</documentation>
+ </annotation></attribute>
+ <attribute name="role" type="string">
+ <annotation>
+ <documentation>The type role</documentation>
+ </annotation></attribute>
+ <attribute name="typeParameters" type="string">
+ <annotation>
+ <documentation>The type parameters</documentation>
+ </annotation></attribute>
+ </complexType>
+
+ <complexType name="SourceType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>The exact or regex match pattern for a source file name. If the name starts with the ~ character the rest of attribute content is interpreted as a Java regular expression.</documentation>
+ </annotation></attribute>
+ </complexType>
+
+ <complexType name="FieldType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>The exact or regex match pattern for a field name. If the name starts with the ~ character the rest of attribute content is interpreted as a Java regular expression.</documentation>
+ </annotation></attribute>
+ <attribute name="type" type="string">
+ <annotation>
+ <documentation>Fully qualified type of the field</documentation>
+ </annotation></attribute>
+ <attribute name="role" type="string">
+ <annotation>
+ <documentation>The field's role</documentation>
+ </annotation></attribute>
+ </complexType>
+
+ <complexType name="LocalType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>The exact or regex match pattern for a local variable name. If the name starts with the ~ character the rest of attribute content is interpreted as a Java regular expression.</documentation></annotation></attribute>
+ </complexType>
+
+ <complexType name="MethodType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>The exact or regex match pattern for a method name.. If the name starts with the ~ character the rest of attribute content is interpreted as a Java regular expression.</documentation>
+ </annotation></attribute>
+ <attribute name="params" type="string">
+ <annotation>
+ <documentation>A comma-separated list of the fully qualified types of the method's parameters.</documentation>
+ </annotation></attribute>
+ <attribute name="returns" type="string">
+ <annotation>
+ <documentation>The method's fully qualified return type</documentation>
+ </annotation></attribute>
+ <attribute name="role" type="string">
+ <annotation>
+ <documentation>The method's role</documentation>
+ </annotation></attribute>
+ </complexType>
+
+ <complexType name="PackageType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>The exact or regex match pattern for a package name. Nested packages are not included (along the lines of Java import statement). If the name starts with the ~ character the rest of attribute content is interpreted as a Java regular expression.</documentation>
+ </annotation></attribute>
+ </complexType>
+
+ <complexType name="PriorityType">
+ <annotation>
+ <documentation>Deprecated. Use ConfidenceType instead</documentation>
+ </annotation>
+ <attribute name="value" type="fb:PriorityValueType">
+ <annotation>
+ <documentation>1: high-priority warnings, 2: medium-priority warnings, 3: low-priority warnings</documentation>
+ </annotation></attribute>
+ </complexType>
+
+ <complexType name="ConfidenceType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="value" type="fb:ConfidenceValueType">
+ <annotation>
+ <documentation>1: high-priority warnings, 2: medium-priority warnings, 3: low-priority warnings</documentation>
+ </annotation></attribute>
+ </complexType>
+
+ <complexType name="RankType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <attribute name="value" type="fb:RankValueType">
+ <annotation>
+ <documentation>1 to 4 are scariest, 5 to 9 scary, 10 to 14 troubling, and 15 to 20 of concern bugs.</documentation>
+ </annotation></attribute>
+ </complexType>
+
+ <simpleType name="PriorityValueType">
+ <restriction base="int">
+ <minInclusive value="1"></minInclusive>
+ <maxInclusive value="3"></maxInclusive>
+ </restriction>
+ </simpleType>
+
+ <simpleType name="ConfidenceValueType">
+ <restriction base="int">
+ <minInclusive value="1"></minInclusive>
+ <maxInclusive value="3"></maxInclusive>
+ </restriction>
+ </simpleType>
+
+ <simpleType name="RankValueType">
+ <restriction base="int">
+ <minInclusive value="1"></minInclusive>
+ <maxInclusive value="20"></maxInclusive>
+ </restriction>
+ </simpleType>
+
+ <complexType name="MatchType">
+ <sequence maxOccurs="unbounded" minOccurs="0">
+ <element ref="fb:Bug" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Class" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Source" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Field" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Local" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Method" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Or" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:And" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Package" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Priority" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Confidence" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Rank" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Not" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:BugCode" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:BugPattern" maxOccurs="unbounded" minOccurs="0"></element>
+ </sequence>
+ </complexType>
+
+ <complexType name="NotType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <sequence maxOccurs="unbounded" minOccurs="0">
+ <element ref="fb:And" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Bug" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:BugCode" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:BugPattern" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Class" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Confidence" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Field" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Local" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Method" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Not" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Or" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Package" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Priority" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Rank" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Source" maxOccurs="unbounded" minOccurs="0"></element>
+ </sequence>
+ </complexType>
+
+ <complexType name="OrType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <sequence maxOccurs="unbounded" minOccurs="0">
+ <element ref="fb:And" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Bug" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:BugCode" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:BugPattern" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Class" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Confidence" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Field" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Local" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Method" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Not" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Or" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Package" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Priority" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Rank" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Source" maxOccurs="unbounded" minOccurs="0"></element>
+ </sequence>
+ </complexType>
+
+ <complexType name="AndType">
+ <annotation>
+ <documentation></documentation>
+ </annotation>
+ <sequence maxOccurs="unbounded" minOccurs="0">
+ <element ref="fb:And" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Bug" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:BugCode" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:BugPattern" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Class" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Confidence" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Field" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Local" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Method" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Not" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Or" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Package" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Priority" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Rank" maxOccurs="unbounded" minOccurs="0"></element>
+ <element ref="fb:Source" maxOccurs="unbounded" minOccurs="0"></element>
+ </sequence>
+ </complexType>
+</schema>
diff --git a/etc/messagecollection.xsd b/etc/messagecollection.xsd
index 8962934..a516417 100644
--- a/etc/messagecollection.xsd
+++ b/etc/messagecollection.xsd
@@ -15,8 +15,10 @@
<xsd:complexType name="PluginType">
<xsd:sequence>
- <xsd:element name="ShortDescription" type="xsd:string"/>
+ <xsd:element name="ShortDescription" type="xsd:string" />
<xsd:element name="Details" type="xsd:string" />
+ <xsd:element name="BugsUrl" type="xsd:string" maxOccurs="1" minOccurs="0"></xsd:element>
+ <xsd:element name="AllBugsUrl" type="xsd:string" maxOccurs="1" minOccurs="0"></xsd:element>
</xsd:sequence>
</xsd:complexType>
@@ -80,7 +82,7 @@
<xsd:element name="Plugin" type="PluginType"/>
<xsd:element name="FindBugsMain" type="FindBugsMainType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Cloud" type="CloudType" minOccurs="0" maxOccurs="unbounded"/>
- <xsd:element name="PluginComponent" type="PluginComponentType" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="PluginComponent" type="PluginComponentType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="BugCategory" type="BugCategoryType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Detector" type="DetectorType" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="BugPattern" type="BugPatternType" minOccurs="1" maxOccurs="unbounded"/>
diff --git a/etc/messages.xml b/etc/messages.xml
index 9090701..42369e3 100644
--- a/etc/messages.xml
+++ b/etc/messages.xml
@@ -16,10 +16,11 @@ This plugin contains all of the standard FindBugs detectors.
</p>
]]>
</Details>
+ <BugsUrl>http://findbugs.sourceforge.net/bugDescriptions.html</BugsUrl>
+ <AllBugsUrl>http://findbugs.sourceforge.net/allBugDescriptions.html</AllBugsUrl>
</Plugin>
<FindBugsMain cmd="addMessages" class="edu.umd.cs.findbugs.AddMessages">
- <Description>add msgs (e.g., textual descriptions of bugs) to analysis results
- </Description>
+ <Description>Add msgs (e.g., textual descriptions of bugs) to analysis results</Description>
</FindBugsMain>
<FindBugsMain cmd="analyze" class="edu.umd.cs.findbugs.FindBugs2">
<Description>Perform FindBugs Analysis</Description>
@@ -43,21 +44,20 @@ This plugin contains all of the standard FindBugs detectors.
<Description>Set project configuration/options</Description>
</FindBugsMain>
<FindBugsMain cmd="history" class="edu.umd.cs.findbugs.workflow.MineBugHistory">
- <Description>List details from multi-version analysis results</Description>
+ <Description>List details from multi-version analysis results</Description>
</FindBugsMain>
<FindBugsMain cmd="union" class="edu.umd.cs.findbugs.workflow.UnionResults">
<Description>Merge analysis results from disjoint components</Description>
</FindBugsMain>
<FindBugsMain cmd="merge" class="edu.umd.cs.findbugs.workflow.Update">
- <Description>Combine analysis results from different versions of software to produce multi-version analysis results </Description>
+ <Description>Combine analysis results from different versions of software to produce multi-version analysis results</Description>
</FindBugsMain>
<FindBugsMain cmd="dis" class="edu.umd.cs.findbugs.workflow.PrintClass">
<Description>Disassemble a class file</Description>
</FindBugsMain>
<FindBugsMain cmd="errors" class="edu.umd.cs.findbugs.workflowListErrors">
- <Description>List analysis errors stored in results file
- </Description>
+ <Description>List analysis errors stored in results file</Description>
</FindBugsMain>
<!-- On changing this, please also update default cloud id in FindbugsPlugin -->
@@ -165,10 +165,18 @@ This plugin contains all of the standard FindBugs detectors.
Detectors
**********************************************************************
-->
+ <Detector class="edu.umd.cs.findbugs.detect.FindRoughConstants">
+ <Details>
+<![CDATA[
+<p> Finds constants which roughly (but not precisely) equal to known values like Math.PI.
+</p>
+]]>
+ </Details>
+ </Detector>
<Detector class="edu.umd.cs.findbugs.detect.InitializeNonnullFieldsInConstructor">
<Details>
<![CDATA[
-<p> Finds nonnull fields that are not written to in constructors.
+<p> Finds non-null fields that are not written to in constructors.
</p>
]]>
</Details>
@@ -176,7 +184,7 @@ This plugin contains all of the standard FindBugs detectors.
<Detector class="edu.umd.cs.findbugs.detect.IntCast2LongAsInstant">
<Details>
<![CDATA[
-<p> Finds uses of 32-bit values to describe milliseconds since the epoc.
+<p> Finds uses of 32-bit values to describe milliseconds since the epoch.
</p>
]]>
</Details>
@@ -185,7 +193,7 @@ This plugin contains all of the standard FindBugs detectors.
<Details>
<![CDATA[
<p> Builds database of parameters that take a 64 bit value describing
-milliseconds since the epoc.</p>
+milliseconds since the epoch.</p>
]]>
</Details>
</Detector>
@@ -286,7 +294,7 @@ applied to method parameters and uses of those method parameters. </p>
<Detector class="edu.umd.cs.findbugs.detect.Methods">
<Details>
<![CDATA[
-<p> Builds of database of all methods defined in analyzed classes, for use
+<p> Builds a database of all methods defined in analyzed classes, for use
by other detectors.</p>
]]>
</Details>
@@ -301,16 +309,30 @@ by other detectors.</p>
<Detector class="edu.umd.cs.findbugs.detect.CalledMethods">
<Details>
<![CDATA[
-<p> Builds of database of all methods invoked in analyzed classes, for use
+<p> Builds a database of all methods invoked in analyzed classes, for use
by other detectors.</p>
]]>
</Details>
</Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.FindNoSideEffectMethods">
+ <Details>
+<![CDATA[
+<p> Looks for the methods which have no side effect, just return some value.</p>
+]]>
+ </Details>
+ </Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.BuildStringPassthruGraph">
+ <Details>
+<![CDATA[
+<p> Builds the database of string parameters passed from method to method unchanged.</p>
+]]>
+ </Details>
+ </Detector>
<Detector class="edu.umd.cs.findbugs.detect.FunctionsThatMightBeMistakenForProcedures">
<Details>
<![CDATA[
<p> Looks for immutable classes with methods that return new instances of that class,
-where people might accidently think those methods mutate the instance they are invoked on.
+where people might accidentally think those methods mutate the instance they are invoked on.
</p>
]]>
</Details>
@@ -333,7 +355,7 @@ where people might accidently think those methods mutate the instance they are i
<Detector class="edu.umd.cs.findbugs.detect.SynchronizeOnClassLiteralNotGetClass">
<Details>
<![CDATA[
-<p> Look for code that synchronizes on the results of getClass rather than on class
+<p> Looks for code that synchronizes on the results of getClass rather than on class
literals.
</p>
]]>
@@ -353,7 +375,7 @@ literals.
<Details>
<![CDATA[
<p>
- Looks for @NonNull annotations on methods, fields, and parameters.
+ Looks for @Nonnull annotations on methods, fields, and parameters.
These can be used by the FindNullDeref detector to generate warnings
when a possibly-null value is used in a context where only
non-null values should be used.
@@ -381,7 +403,7 @@ literals.
<![CDATA[
<p>
Analyze all methods in the application to determine which
- methods always return nonnull values.
+ methods always return non-null values.
</p>
]]>
</Details>
@@ -394,6 +416,29 @@ literals.
]]>
</Details>
</Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.OptionalReturnNull">
+ <Details>
+<![CDATA[
+<p> Looks for methods with Optional return type that return explicit null values.</p>
+
+]]>
+ </Details>
+ </Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.FindUselessObjects">
+ <Details>
+<![CDATA[
+<p> Looks for useless objects.</p>
+
+]]>
+ </Details>
+ </Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.MutableEnum">
+ <Details>
+ <![CDATA[
+<p> Looks and warns about mutable enum fields.</p>
+ ]]>
+ </Details>
+ </Detector>
<Detector class="edu.umd.cs.findbugs.detect.BadUseOfReturnValue">
<Details>
<![CDATA[
@@ -490,6 +535,13 @@ This does not help the garbage collector in any way, the nulling out of fields h
]]>
</Details>
</Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.RedundantConditions">
+ <Details>
+<![CDATA[
+<p> This detector looks for code containing useless conditions like the second condition in this expression: (x >= 10 && x >= 5).
+]]>
+ </Details>
+ </Detector>
<Detector class="edu.umd.cs.findbugs.detect.CallToUnsupportedMethod">
<Details>
<![CDATA[
@@ -694,6 +746,14 @@ such as the no-argument String constructor.
]]>
</Details>
</Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.CovariantArrayAssignment">
+ <Details>
+<![CDATA[
+<p> This detector looks for covariant array assignments like Object[] array = new String[10] which may cause ArrayStoreException at runtime.
+</p>
+]]>
+ </Details>
+ </Detector>
<Detector class="edu.umd.cs.findbugs.detect.NumberConstructor">
<Details>
<![CDATA[
@@ -926,6 +986,13 @@ is suspiciously ignored. It is a slow detector.</p>
]]>
</Details>
</Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.FindComparatorProblems">
+ <Details>
+<![CDATA[
+<p> This detector looks for problems in Comparator.compare or Comparable.compareTo implementation.</p>
+]]>
+ </Details>
+ </Detector>
<Detector class="edu.umd.cs.findbugs.detect.FindNullDeref">
<Details>
<![CDATA[
@@ -1063,6 +1130,24 @@ on JSR166 locks. It is a moderately fast detector.</p>
]]>
</Details>
</Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.InefficientInitializationInsideLoop">
+ <Details>
+<![CDATA[
+<p> This detector looks for objects initialized within loop which can be moved outside for better performance.
+</p>
+]]>
+ </Details>
+ </Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.InefficientIndexOf">
+ <Details>
+<![CDATA[
+<p> This detector looks for code that uses String.indexOf(String) or String.lastIndexOf(String),
+passing a constant string of length 1. It is recommended to use the more efficient integer implementations.
+A fast detector.
+</p>
+]]>
+ </Details>
+ </Detector>
<Detector class="edu.umd.cs.findbugs.detect.InefficientToArray">
<Details>
<![CDATA[
@@ -1448,7 +1533,7 @@ factory pattern to create these objects.</p>
<Details>
<![CDATA[
<p>
- TrainNonNullAnnotations collects @NonNull and @PossiblyNull annotations
+ TrainNonNullAnnotations collects @Nonnull and @PossiblyNull annotations
and stores them to database files. This is a fast detector.
</p>
]]>
@@ -1571,6 +1656,15 @@ factory pattern to create these objects.</p>
BugPatterns
**********************************************************************
-->
+ <BugPattern type="CNT_ROUGH_CONSTANT_VALUE">
+ <ShortDescription>Rough value of known constant found</ShortDescription>
+ <LongDescription>Rough value of {3} found: {2}</LongDescription>
+ <Details>
+ <![CDATA[
+ <p>It's recommended to use the predefined library constant for code clarity and better precision.</p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="SKIPPED_CLASS_TOO_BIG">
<ShortDescription>Class too big for analysis</ShortDescription>
<LongDescription>{0} is too big for analysis</LongDescription>
@@ -1945,12 +2039,25 @@ another package.</p>
]]>
</Details>
</BugPattern>
+ <BugPattern type="NP_OPTIONAL_RETURN_NULL">
+ <ShortDescription>Method with Optional return type returns explicit null</ShortDescription>
+ <LongDescription>{1} has Optional return type and returns explicit null</LongDescription>
+ <Details>
+ <![CDATA[
+ <p>
+ The usage of Optional return type (java.util.Optional or com.google.common.base.Optiona)
+ always mean that explicit null returns were not desired by design.
+ Returning a null value in such case is a contract violation and will most likely break clients code.
+ </p>
+ ]]>
+ </Details>
+ </BugPattern>
<BugPattern type="NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR">
- <ShortDescription>Nonnull field is not initialized</ShortDescription>
- <LongDescription>Nonnull field {2.name} is not initialized by {1}</LongDescription>
+ <ShortDescription>Non-null field is not initialized</ShortDescription>
+ <LongDescription>Non-null field {2.name} is not initialized by {1}</LongDescription>
<Details>
<![CDATA[
- <p> The field is marked as nonnull, but isn't written to by the constructor.
+ <p> The field is marked as non-null, but isn't written to by the constructor.
The field might be initialized elsewhere during constructor, or might always
be initialized before use.
</p>
@@ -2085,6 +2192,61 @@ should be written to the JarFile between the calls to
]]>
</Details>
</BugPattern>
+ <BugPattern type="CAA_COVARIANT_ARRAY_FIELD">
+ <ShortDescription>Covariant array assignment to a field</ShortDescription>
+ <LongDescription>Array of type {2} is assigned to the field of type {3}</LongDescription>
+ <Details>
+<![CDATA[
+<p>Array of covariant type is assigned to a field. This is confusing and may lead to ArrayStoreException at runtime
+if the reference of some other type will be stored in this array later like in the following code:
+</p>
+<p><code>Number[] arr = new Integer[10];
+arr[0] = 1.0;
+</code></p>
+<p>Consider changing the type of created array or the field type.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="CAA_COVARIANT_ARRAY_LOCAL">
+ <ShortDescription>Covariant array assignment to a local variable</ShortDescription>
+ <LongDescription>Array of type {2} is assigned to the variable of type {3}</LongDescription>
+ <Details>
+<![CDATA[
+<p>Array of covariant type is assigned to a local variable. This is confusing and may lead to ArrayStoreException at runtime
+if the reference of some other type will be stored in this array later like in the following code:
+</p>
+<p><code>Number[] arr = new Integer[10];
+arr[0] = 1.0;
+</code></p>
+<p>Consider changing the type of created array or the local variable type.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="CAA_COVARIANT_ARRAY_RETURN">
+ <ShortDescription>Covariant array is returned from the method</ShortDescription>
+ <LongDescription>Array of type {2} is returned from the method which return type is {3}</LongDescription>
+ <Details>
+<![CDATA[
+<p>Array of covariant type is returned from the method. This is confusing and may lead to ArrayStoreException at runtime
+if the calling code will try to store the reference of some other type in the returned array.
+</p>
+<p>Consider changing the type of created array or the method return type.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="CAA_COVARIANT_ARRAY_ELEMENT_STORE">
+ <ShortDescription>Possibly incompatible element is stored in covariant array</ShortDescription>
+ <LongDescription>Value of type {2} is stored into array which element type is {3}</LongDescription>
+ <Details>
+<![CDATA[
+<p>Value is stored into the array and the value type doesn't match the array type.
+It's known from the analysis that actual array type is narrower than the declared type of its variable or field
+and this assignment doesn't satisfy the original array type. This assignment may cause ArrayStoreException
+at runtime.
+</p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="CN_IDIOM">
<ShortDescription>Class implements Cloneable but does not define or use clone method</ShortDescription>
<LongDescription>Class {0} implements Cloneable but does not define or use clone method</LongDescription>
@@ -2482,6 +2644,17 @@ to immediately undo the work of the boxing.
]]>
</Details>
</BugPattern>
+ <BugPattern type="DM_BOXED_PRIMITIVE_FOR_COMPARE">
+ <ShortDescription>Boxing a primitive to compare</ShortDescription>
+ <LongDescription>Primitive is boxed to call {2}: use {3} instead</LongDescription>
+ <Details>
+<![CDATA[
+ <p>A boxed primitive is created just to call compareTo method. It's more efficient to use static compare method
+ (for double and float since Java 1.4, for other primitive types since Java 1.7) which works on primitives directly.
+ </p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="DM_NEW_FOR_GETCLASS">
<ShortDescription>Method allocates an object, only to get the class object</ShortDescription>
<LongDescription>{1} allocates an object, only to get the class object</LongDescription>
@@ -2517,6 +2690,17 @@ want to multiple the random value by something else before coercing it to an int
]]>
</Details>
</BugPattern>
+ <BugPattern type="DM_INVALID_MIN_MAX">
+ <ShortDescription>Incorrect combination of Math.max and Math.min</ShortDescription>
+ <LongDescription>Incorrect combination of Math.max and Math.min: this code always returns {2}</LongDescription>
+ <Details>
+<![CDATA[
+ <p>This code tries to limit the value bounds using the construct like Math.min(0, Math.max(100, value)). However the order of
+ the constants is incorrect: it should be Math.min(100, Math.max(0, value)). As the result this code always produces the same result
+ (or NaN if the value is NaN).</p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="DM_NEXTINT_VIA_NEXTDOUBLE">
<ShortDescription>Use the nextInt method of Random rather than nextDouble to generate a random integer</ShortDescription>
<LongDescription>{1} uses the nextDouble method of Random to generate a random integer; using nextInt is more efficient</LongDescription>
@@ -2532,11 +2716,11 @@ value from -99 to 0, use <code>-r.nextInt(100)</code>.
</Details>
</BugPattern>
<BugPattern type="SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE">
- <ShortDescription>Nonconstant string passed to execute method on an SQL statement</ShortDescription>
- <LongDescription>{1} passes a nonconstant String to an execute method on an SQL statement</LongDescription>
+ <ShortDescription>Nonconstant string passed to execute or addBatch method on an SQL statement</ShortDescription>
+ <LongDescription>{1} passes a nonconstant String to an execute or addBatch method on an SQL statement</LongDescription>
<Details>
<![CDATA[
- <p>The method invokes the execute method on an SQL statement with a String that seems
+ <p>The method invokes the execute or addBatch method on an SQL statement with a String that seems
to be dynamically generated. Consider using
a prepared statement instead. It is more efficient and less vulnerable to
SQL injection attacks.
@@ -2580,13 +2764,27 @@ be used to make the prepared statement do something unexpected and undesirable.
]]>
</Details>
</BugPattern>
+ <BugPattern type="DC_PARTIALLY_CONSTRUCTED">
+ <ShortDescription>Possible exposure of partially initialized object</ShortDescription>
+ <LongDescription>Possible exposure of partially initialized object in {1}</LongDescription>
+ <Details>
+<![CDATA[
+ <p>Looks like this method uses lazy field initialization with double-checked locking.
+ While the field is correctly declared as volatile, it's possible that the internal structure of
+ the object is changed after the field assignment, thus another thread may see the partially initialized object.</p>
+ <p>To fix this problem consider storing the object into the local variable first
+ and save it to the volatile field only after it's fully constructed.
+ </p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="FI_FINALIZER_NULLS_FIELDS">
<ShortDescription>Finalizer nulls fields</ShortDescription>
<LongDescription>{3} is set to null inside finalize method in {1.class}</LongDescription>
<Details>
<![CDATA[
<p> This finalizer nulls out fields. This is usually an error, as it does not aid garbage collection,
- and the object is going to be garbage collected anyway.
+ and the object is going to be garbage collected anyway.</p>
]]>
</Details>
</BugPattern>
@@ -2597,7 +2795,7 @@ be used to make the prepared statement do something unexpected and undesirable.
<![CDATA[
<p> This finalizer does nothing except null out fields. This is completely pointless, and requires that
the object be garbage collected, finalized, and then garbage collected again. You should just remove the finalize
-method.
+method.</p>
]]>
</Details>
</BugPattern>
@@ -2667,7 +2865,7 @@ method.
<p>If a connected set of objects beings finalizable, then the VM will invoke the
finalize method on all the finalizable object, possibly at the same time in different threads.
Thus, it is a particularly bad idea, in the finalize method for a class X, invoke finalize
-on objects referenced by X, because they may already be getting finalized in a separate thread.
+on objects referenced by X, because they may already be getting finalized in a separate thread.</p>
]]>
</Details>
</BugPattern>
@@ -2753,7 +2951,7 @@ Don't do it.
</BugPattern>
<BugPattern type="EQ_DOESNT_OVERRIDE_EQUALS">
<ShortDescription>Class doesn't override equals in superclass</ShortDescription>
- <LongDescription>{0} doesn't override {1.givenClass}</LongDescription>
+ <LongDescription>{0} doesn't override {2.givenClass}</LongDescription>
<Details>
<![CDATA[
<p> This class extends a class that defines an equals method and adds fields, but doesn't
@@ -2928,6 +3126,18 @@ the constant Integer.MIN_VALUE, which is an exceptionally bad practice.
]]>
</Details>
</BugPattern>
+ <BugPattern type="CO_COMPARETO_INCORRECT_FLOATING">
+ <ShortDescription>compareTo()/compare() incorrectly handles float or double value</ShortDescription>
+ <LongDescription>{1} incorrectly handles {2} value</LongDescription>
+ <Details>
+<![CDATA[
+ <p>This method compares double or float values using pattern like this: val1 > val2 ? 1 : val1 < val2 ? -1 : 0.
+This pattern works incorrectly for -0.0 and NaN values which may result in incorrect sorting result or broken collection
+(if compared values are used as keys). Consider using Double.compare or Float.compare static methods which handle all
+the special cases correctly.</p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="CO_SELF_NO_OBJECT">
<ShortDescription>Covariant compareTo() method defined</ShortDescription>
<LongDescription>{0} defines compareTo({0.givenClass}) method but not compareTo(Object)</LongDescription>
@@ -2999,7 +3209,7 @@ the recommended <code>hashCode</code> implementation to use is:</p>
equals returns true. If this is violated, weird and unpredictable
failures will occur in classes such as PriorityQueue.
In Java 5 the PriorityQueue.remove method uses the compareTo method,
- while in Java 6 it uses the equals method.
+ while in Java 6 it uses the equals method.</p>
<p>From the JavaDoc for the compareTo method in the Comparable interface:
<blockquote>
@@ -3007,7 +3217,7 @@ It is strongly recommended, but not strictly required that <code>(x.compareTo(y)
Generally speaking, any class that implements the Comparable interface and violates this condition
should clearly indicate this fact. The recommended language
is "Note: this class has a natural ordering that is inconsistent with equals."
-</blockquote>
+</blockquote></p>
]]>
</Details>
</BugPattern>
@@ -3736,6 +3946,31 @@ could be changed by malicious code or
]]>
</Details>
</BugPattern>
+ <BugPattern type="MS_MUTABLE_COLLECTION">
+ <ShortDescription>Field is a mutable collection</ShortDescription>
+ <LongDescription>{1} is a mutable collection</LongDescription>
+ <Details>
+<![CDATA[
+ <p>A mutable collection instance is assigned to a final static field,
+ thus can be changed by malicious code or by accident from another package.
+ Consider wrapping this field into Collections.unmodifiableSet/List/Map/etc.
+ to avoid this vulnerability.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="MS_MUTABLE_COLLECTION_PKGPROTECT">
+ <ShortDescription>Field is a mutable collection which should be package protected</ShortDescription>
+ <LongDescription>{1} is a mutable collection which should be package protected</LongDescription>
+ <Details>
+<![CDATA[
+ <p>A mutable collection instance is assigned to a final static field,
+ thus can be changed by malicious code or by accident from another package.
+ The field could be made package protected to avoid this vulnerability.
+ Alternatively you may wrap this field into Collections.unmodifiableSet/List/Map/etc.
+ to avoid this vulnerability.</p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="MS_MUTABLE_ARRAY">
<ShortDescription>Field is a mutable array</ShortDescription>
<LongDescription>{1} is a mutable array</LongDescription>
@@ -3761,17 +3996,39 @@ could be changed by malicious code or
]]>
</Details>
</BugPattern>
+ <BugPattern type="ME_MUTABLE_ENUM_FIELD">
+ <ShortDescription>Enum field is public and mutable</ShortDescription>
+ <LongDescription>{1} field is public and mutable</LongDescription>
+ <Details>
+<![CDATA[
+ <p>A mutable public field is defined inside a public enum, thus can be changed by malicious code or by accident from another package.
+ Though mutable enum fields may be used for lazy initialization, it's a bad practice to expose them to the outer world.
+ Consider declaring this field final and/or package-private.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="ME_ENUM_FIELD_SETTER">
+ <ShortDescription>Public enum method unconditionally sets its field</ShortDescription>
+ <LongDescription>{1} unconditionally sets the field {2.name}</LongDescription>
+ <Details>
+<![CDATA[
+ <p>This public method declared in public enum unconditionally sets enum field, thus this field can be changed by malicious code
+ or by accident from another package. Though mutable enum fields may be used for lazy initialization, it's a bad practice to expose them to the outer world.
+ Consider removing this method or declaring it package-private.</p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD">
<ShortDescription>Potentially ambiguous invocation of either an inherited or outer method</ShortDescription>
<LongDescription>Potentially ambiguous invocation of either an outer or inherited method {2} in {1}</LongDescription>
<Details>
<![CDATA[
- <p>
-An inner class is invoking a method that could be resolved to either a inherited method or a method defined in an outer class.
+ <p>
+An inner class is invoking a method that could be resolved to either a inherited method or a method defined in an outer class.
For example, you invoke <code>foo(17)</code>, which is defined in both a superclass and in an outer method.
By the Java semantics,
it will be resolved to invoke the inherited method, but this may not be want
-you intend.
+you intend.
</p>
<p>If you really intend to invoke the inherited method,
invoke it by invoking the method on super (e.g., invoke super.foo(17)), and
@@ -3779,7 +4036,7 @@ thus it will be clear to other readers of your code and to FindBugs
that you want to invoke the inherited method, not the method in the outer class.
</p>
<p>If you call <code>this.foo(17)</code>, then the inherited method will be invoked. However, since FindBugs only looks at
-classfiles, it
+classfiles, it
can't tell the difference between an invocation of <code>this.foo(17)</code> and <code>foo(17)</code>, it will still
complain about a potential ambiguous invocation.
</p>
@@ -3795,7 +4052,7 @@ complain about a potential ambiguous invocation.
that its superclass is in a different package (e.g., <code>alpha.Foo</code> extends <code>beta.Foo</code>).
This can be exceptionally confusing, create lots of situations in which you have to look at import statements
to resolve references and creates many
-opportunities to accidently define methods that do not override methods in their superclasses.
+opportunities to accidentally define methods that do not override methods in their superclasses.
</p>
]]>
</Details>
@@ -3809,7 +4066,7 @@ opportunities to accidently define methods that do not override methods in their
that the interface is in a different package (e.g., <code>alpha.Foo</code> extends <code>beta.Foo</code>).
This can be exceptionally confusing, create lots of situations in which you have to look at import statements
to resolve references and creates many
-opportunities to accidently define methods that do not override methods in their superclasses.
+opportunities to accidentally define methods that do not override methods in their superclasses.
</p>
]]>
</Details>
@@ -3954,7 +4211,7 @@ removing or deprecating the method with the similar but not identical signature.
<![CDATA[
<p> This regular method has the same name as the class it is defined in. It is likely that this was intended to be a constructor.
If it was intended to be a constructor, remove the declaration of a void return value.
- If you had accidently defined this method, realized the mistake, defined a proper constructor
+ If you had accidentally defined this method, realized the mistake, defined a proper constructor
but can't get rid of this method due to backwards compatibility, deprecate the method.
</p>
]]>
@@ -4184,7 +4441,8 @@ is generally easy and good defensive programming.
<p> This method contains a switch statement where default case is missing.
Usually you need to provide a default case.</p>
<p>Because the analysis only looks at the generated bytecode, this warning can be incorrect triggered if
-the default case is at the end of the switch statement and doesn't end with a break statement.
+the default case is at the end of the switch statement and the switch statement doesn't contain break statements for other
+cases.
]]>
</Details>
</BugPattern>
@@ -4451,7 +4709,7 @@ and generally bad practice.
<p> The variable referenced at this point is known to be null due to an earlier
check against null. Although this is valid, it might be a mistake (perhaps you
intended to refer to a different variable, or perhaps the earlier check to see if the
-variable is null should have been a check to see if it was nonnull).
+variable is null should have been a check to see if it was non-null).
</p>
]]>
</Details>
@@ -4617,6 +4875,102 @@ inner object. This reference makes the instances
]]>
</Details>
</BugPattern>
+ <BugPattern type="UC_USELESS_VOID_METHOD">
+ <ShortDescription>Useless non-empty void method</ShortDescription>
+ <LongDescription>Method {1} seems to be useless</LongDescription>
+ <Details>
+<![CDATA[
+<p>Our analysis shows that this non-empty void method does not actually perform any useful work.
+Please check it: probably there's a mistake in its code or its body can be fully removed.
+</p>
+<p>We are trying to reduce the false positives as much as possible, but in some cases this warning might be wrong.
+Common false-positive cases include:</p>
+<p>- The method is intended to trigger loading of some class which may have a side effect.</p>
+<p>- The method is intended to implicitly throw some obscure exception.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="UC_USELESS_CONDITION">
+ <ShortDescription>Condition has no effect</ShortDescription>
+ <LongDescription>Useless condition: it's known that {2} at this point</LongDescription>
+ <Details>
+<![CDATA[
+<p>This condition always produces the same result as the value of the involved variable was narrowed before.
+Probably something else was meant or condition can be removed.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="UC_USELESS_CONDITION_TYPE">
+ <ShortDescription>Condition has no effect due to the variable type</ShortDescription>
+ <LongDescription>Useless condition: it's always {2} because variable type is {3}</LongDescription>
+ <Details>
+<![CDATA[
+<p>This condition always produces the same result due to the type range of the involved variable.
+Probably something else was meant or condition can be removed.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="UC_USELESS_OBJECT">
+ <ShortDescription>Useless object created</ShortDescription>
+ <LongDescription>Useless object stored in variable {2} of method {1}</LongDescription>
+ <Details>
+<![CDATA[
+<p>Our analysis shows that this object is useless.
+It's created and modified, but its value never go outside of the method or produce any side-effect.
+Either there is a mistake and object was intended to be used or it can be removed.</p>
+<p>This analysis rarely produces false-positives. Common false-positive cases include:</p>
+<p>- This object used to implicitly throw some obscure exception.</p>
+<p>- This object used as a stub to generalize the code.</p>
+<p>- This object used to hold strong references to weak/soft-referenced objects.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="UC_USELESS_OBJECT_STACK">
+ <ShortDescription>Useless object created on stack</ShortDescription>
+ <LongDescription>Useless object created in method {1}</LongDescription>
+ <Details>
+<![CDATA[
+<p>This object is created just to perform some modifications which don't have any side-effect.
+Probably something else was meant or the object can be removed.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="RANGE_ARRAY_INDEX">
+ <ShortDescription>Array index is out of bounds</ShortDescription>
+ <LongDescription>Array index is out of bounds: {3}</LongDescription>
+ <Details>
+<![CDATA[
+ <p> Array operation is performed, but array index is out of bounds, which will result in ArrayIndexOutOfBoundsException at runtime.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="RANGE_ARRAY_OFFSET">
+ <ShortDescription>Array offset is out of bounds</ShortDescription>
+ <LongDescription>Array offset is out of bounds: {3}</LongDescription>
+ <Details>
+<![CDATA[
+ <p> Method is called with array parameter and offset parameter, but the offset is out of bounds. This will result in IndexOutOfBoundsException at runtime. </p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="RANGE_ARRAY_LENGTH">
+ <ShortDescription>Array length is out of bounds</ShortDescription>
+ <LongDescription>Array length is out of bounds: {3}</LongDescription>
+ <Details>
+<![CDATA[
+ <p> Method is called with array parameter and length parameter, but the length is out of bounds. This will result in IndexOutOfBoundsException at runtime. </p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="RANGE_STRING_INDEX">
+ <ShortDescription>String index is out of bounds</ShortDescription>
+ <LongDescription>String index is out of bounds when calling {5}: {3}</LongDescription>
+ <Details>
+<![CDATA[
+ <p> String method is called and specified string index is out of bounds. This will result in StringIndexOutOfBoundsException at runtime. </p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="RV_CHECK_FOR_POSITIVE_INDEXOF">
<ShortDescription>Method checks to see if result of String.indexOf is positive</ShortDescription>
<LongDescription>{1} checks to see if result of String.indexOf is positive</LongDescription>
@@ -4630,8 +4984,8 @@ inner object. This reference makes the instances
</Details>
</BugPattern>
<BugPattern type="RV_DONT_JUST_NULL_CHECK_READLINE">
- <ShortDescription>Method discards result of readLine after checking if it is nonnull</ShortDescription>
- <LongDescription>{1} discards result of readLine after checking if it is nonnull</LongDescription>
+ <ShortDescription>Method discards result of readLine after checking if it is non-null</ShortDescription>
+ <LongDescription>{1} discards result of readLine after checking if it is non-null</LongDescription>
<Details>
<![CDATA[
<p> The value returned by readLine is discarded after checking to see if the return
@@ -4662,6 +5016,27 @@ is important or acceptable.
</Details>
</BugPattern>
+ <BugPattern type="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT">
+ <ShortDescription>Return value of method without side effect is ignored</ShortDescription>
+ <LongDescription>Return value of {2.givenClass} ignored, but method has no side effect</LongDescription>
+ <Details>
+<![CDATA[
+<p>This code calls a method and ignores the return value. However our analysis shows that
+the method (including its implementations in subclasses if any) does not produce any effect
+other than return value. Thus this call can be removed.
+</p>
+<p>We are trying to reduce the false positives as much as possible, but in some cases this warning might be wrong.
+Common false-positive cases include:</p>
+<p>- The method is designed to be overridden and produce a side effect in other projects which are out of the scope of the analysis.</p>
+<p>- The method is called to trigger the class loading which may have a side effect.</p>
+<p>- The method is called just to get some exception.</p>
+<p>If you feel that our assumption is incorrect, you can use a @CheckReturnValue annotation
+to instruct FindBugs that ignoring the return value of this method is acceptable.
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="RV_RETURN_VALUE_IGNORED">
<ShortDescription>Method ignores return value</ShortDescription>
<LongDescription>Return value of {2.givenClass} ignored in {1}</LongDescription>
@@ -4765,11 +5140,11 @@ something that should be closed.
</Details>
</BugPattern>
<BugPattern type="NP_STORE_INTO_NONNULL_FIELD">
- <ShortDescription>Store of null value into field annotated NonNull</ShortDescription>
- <LongDescription>Store of null value into field {2.givenClass} annotated NonNull in {1}</LongDescription>
+ <ShortDescription>Store of null value into field annotated @Nonnull</ShortDescription>
+ <LongDescription>Store of null value into field {2.givenClass} annotated @Nonnull in {1}</LongDescription>
<Details>
<![CDATA[
-<p> A value that could be null is stored into a field that has been annotated as NonNull. </p>
+<p> A value that could be null is stored into a field that has been annotated as @Nonnull. </p>
]]>
</Details>
</BugPattern>
@@ -4789,11 +5164,11 @@ be an exception path, since the default case is often infeasible.</p>
</Details>
</BugPattern>
<BugPattern type="NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE">
- <ShortDescription>Parameter must be nonnull but is marked as nullable</ShortDescription>
- <LongDescription>{2} must be nonnull but is marked as nullable</LongDescription>
+ <ShortDescription>Parameter must be non-null but is marked as nullable</ShortDescription>
+ <LongDescription>{2} must be non-null but is marked as nullable</LongDescription>
<Details>
<![CDATA[
-<p> This parameter is always used in a way that requires it to be nonnull,
+<p> This parameter is always used in a way that requires it to be non-null,
but the parameter is explicitly annotated as being Nullable. Either the use
of the parameter or the annotation is wrong.
</p>
@@ -4859,56 +5234,56 @@ for null. This may lead to a <code>NullPointerException</code> when the code is
</Details>
</BugPattern>
<BugPattern type="NP_NULL_PARAM_DEREF_NONVIRTUAL">
- <ShortDescription>Non-virtual method call passes null for nonnull parameter</ShortDescription>
- <LongDescription>Non-virtual method call in {1} passes null for nonnull parameter of {2.givenClass}</LongDescription>
+ <ShortDescription>Non-virtual method call passes null for non-null parameter</ShortDescription>
+ <LongDescription>Non-virtual method call in {1} passes null for non-null parameter of {2.givenClass}</LongDescription>
<Details>
<![CDATA[
<p>
- A possibly-null value is passed to a nonnull method parameter.
+ A possibly-null value is passed to a non-null method parameter.
Either the parameter is annotated as a parameter that should
- always be nonnull, or analysis has shown that it will always be
+ always be non-null, or analysis has shown that it will always be
dereferenced.
</p>
]]>
</Details>
</BugPattern>
<BugPattern type="NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS">
- <ShortDescription>Method call passes null for nonnull parameter</ShortDescription>
- <LongDescription>Null passed for nonnull parameter of {2.givenClass} in {1}</LongDescription>
+ <ShortDescription>Method call passes null for non-null parameter</ShortDescription>
+ <LongDescription>Null passed for non-null parameter of {2.givenClass} in {1}</LongDescription>
<Details>
<![CDATA[
<p>
A possibly-null value is passed at a call site where all known
- target methods require the parameter to be nonnull.
+ target methods require the parameter to be non-null.
Either the parameter is annotated as a parameter that should
- always be nonnull, or analysis has shown that it will always be
+ always be non-null, or analysis has shown that it will always be
dereferenced.
</p>
]]>
</Details>
</BugPattern>
<BugPattern type="NP_NULL_PARAM_DEREF">
- <ShortDescription>Method call passes null for nonnull parameter</ShortDescription>
- <LongDescription>Null passed for nonnull parameter of {2.givenClass} in {1}</LongDescription>
+ <ShortDescription>Method call passes null for non-null parameter</ShortDescription>
+ <LongDescription>Null passed for non-null parameter of {2.givenClass} in {1}</LongDescription>
<Details>
<![CDATA[
<p>
- This method call passes a null value for a nonnull method parameter.
+ This method call passes a null value for a non-null method parameter.
Either the parameter is annotated as a parameter that should
- always be nonnull, or analysis has shown that it will always be
+ always be non-null, or analysis has shown that it will always be
dereferenced.
</p>
]]>
</Details>
</BugPattern>
<BugPattern type="NP_NONNULL_PARAM_VIOLATION">
- <ShortDescription>Method call passes null to a nonnull parameter </ShortDescription>
- <LongDescription>Null passed for nonnull parameter of {2.givenClass} in {1}</LongDescription>
+ <ShortDescription>Method call passes null to a non-null parameter </ShortDescription>
+ <LongDescription>Null passed for non-null parameter of {2.givenClass} in {1}</LongDescription>
<Details>
<![CDATA[
<p>
This method passes a null value as the parameter of a method which
- must be nonnull. Either this parameter has been explicitly marked
+ must be non-null. Either this parameter has been explicitly marked
as @Nonnull, or analysis has determined that this parameter is
always dereferenced.
</p>
@@ -4916,13 +5291,13 @@ for null. This may lead to a <code>NullPointerException</code> when the code is
</Details>
</BugPattern>
<BugPattern type="NP_NONNULL_RETURN_VIOLATION">
- <ShortDescription>Method may return null, but is declared @NonNull</ShortDescription>
- <LongDescription>{1} may return null, but is declared @NonNull</LongDescription>
+ <ShortDescription>Method may return null, but is declared @Nonnull</ShortDescription>
+ <LongDescription>{1} may return null, but is declared @Nonnull</LongDescription>
<Details>
<![CDATA[
<p>
This method may return a null value, but the method (or a superclass method
- which it overrides) is declared to return @NonNull.
+ which it overrides) is declared to return @Nonnull.
</p>
]]>
</Details>
@@ -4966,7 +5341,7 @@ for null. This may lead to a <code>NullPointerException</code> when the code is
</p>
<p>Note that a check such as
<code>if (x == null) throw new NullPointerException();</code>
- is treated as a dereference of <code>x</code>.
+ is treated as a dereference of <code>x</code>.</p>
]]>
</Details>
</BugPattern>
@@ -5256,16 +5631,11 @@ different types. The result of this comparison will always be false at runtime.
<Details>
<![CDATA[
<p> This method calls equals(Object) on two references of different
-class types with no common subclasses.
-Therefore, the objects being compared
-are unlikely to be members of the same class at runtime
-(unless some application classes were not analyzed, or dynamic class
-loading can occur at runtime).
-According to the contract of equals(),
-objects of different
-classes should always compare as unequal; therefore, according to the
-contract defined by java.lang.Object.equals(Object),
-the result of this comparison will always be false at runtime.
+class types and analysis suggests they will be to objects of different classes
+at runtime. Further, examination of the equals methods that would be invoked suggest that either
+this call will always return false, or else the equals method is not be symmetric (which is
+a property required by the contract
+for equals in class Object).
</p>
]]>
</Details>
@@ -5591,11 +5961,11 @@ value of the result of the remainder operation (i.e., use
</Details>
</BugPattern>
<BugPattern type="INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE">
- <ShortDescription>Bad comparison of nonnegative value with negative constant</ShortDescription>
+ <ShortDescription>Bad comparison of nonnegative value with negative constant or zero</ShortDescription>
<LongDescription>Bad comparison of nonnegative value with {2} in {1}</LongDescription>
<Details>
<![CDATA[
-<p> This code compares a value that is guaranteed to be non-negative with a negative constant.
+<p> This code compares a value that is guaranteed to be non-negative with a negative constant or zero.
</p>
]]>
</Details>
@@ -5996,6 +6366,72 @@ a StringBuffer (or StringBuilder in Java 1.5) explicitly.</p>
]]>
</Details>
</BugPattern>
+ <BugPattern type="IIL_PREPARE_STATEMENT_IN_LOOP">
+ <ShortDescription>Method calls prepareStatement in a loop</ShortDescription>
+ <LongDescription>{1} calls prepareStatement with the constant arguments in a loop</LongDescription>
+ <Details>
+<![CDATA[
+<p> The method calls Connection.prepareStatement inside the loop passing the constant arguments.
+If the PreparedStatement should be executed several times there's no reason to recreate it for each loop iteration.
+Move this call outside of the loop.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="IIL_ELEMENTS_GET_LENGTH_IN_LOOP">
+ <ShortDescription>NodeList.getLength() called in a loop</ShortDescription>
+ <LongDescription>{1} calls NodeList.getLength() in a loop for getElementsByTagName return value</LongDescription>
+ <Details>
+<![CDATA[
+<p> The method calls NodeList.getLength() inside the loop and NodeList was produced by getElementsByTagName call.
+This NodeList doesn't store its length, but computes it every time in not very optimal way.
+Consider storing the length to the variable before the loop.
+</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="IIL_PATTERN_COMPILE_IN_LOOP">
+ <ShortDescription>Method calls Pattern.compile in a loop</ShortDescription>
+ <LongDescription>{1} calls Pattern.compile with the constant arguments in a loop</LongDescription>
+ <Details>
+<![CDATA[
+<p> The method calls Pattern.compile inside the loop passing the constant arguments.
+If the Pattern should be used several times there's no reason to compile it for each loop iteration.
+Move this call outside of the loop or even into static final field.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="IIL_PATTERN_COMPILE_IN_LOOP_INDIRECT">
+ <ShortDescription>Method compiles the regular expression in a loop</ShortDescription>
+ <LongDescription>{1} compiles the regular expression in a loop</LongDescription>
+ <Details>
+<![CDATA[
+<p> The method creates the same regular expression inside the loop, so it will be compiled every iteration.
+It would be more optimal to precompile this regular expression using Pattern.compile outside of the loop.</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="IIO_INEFFICIENT_INDEX_OF">
+ <ShortDescription>Inefficient use of String.indexOf(String)</ShortDescription>
+ <LongDescription>{1} uses String.indexOf(String) instead of String.indexOf(int)</LongDescription>
+ <Details>
+<![CDATA[
+<p> This code passes a constant string of length 1 to String.indexOf().
+It is more efficient to use the integer implementations of String.indexOf().
+f. e. call <code>myString.indexOf('.')</code> instead of <code>myString.indexOf(".")</code></p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="IIO_INEFFICIENT_LAST_INDEX_OF">
+ <ShortDescription>Inefficient use of String.lastIndexOf(String)</ShortDescription>
+ <LongDescription>{1} uses String.lastIndexOf(String) instead of String.lastIndexOf(int)</LongDescription>
+ <Details>
+<![CDATA[
+<p> This code passes a constant string of length 1 to String.lastIndexOf().
+It is more efficient to use the integer implementations of String.lastIndexOf().
+f. e. call <code>myString.lastIndexOf('.')</code> instead of <code>myString.lastIndexOf(".")</code></p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="ITA_INEFFICIENT_TO_ARRAY">
<ShortDescription>Method uses toArray() with zero-length array argument</ShortDescription>
<LongDescription>{1} uses Collection.toArray() with zero-length array argument</LongDescription>
@@ -6278,9 +6714,9 @@ has effect. Please verify that this statement does the right thing.
<LongDescription>Useless increment in return from {1}</LongDescription>
<Details>
<![CDATA[
-<p>This statement has a return such as <code>return x++;</code>.
+<p>This statement has a return such as <code>return x++;</code>.
A postfix increment/decrement does not impact the value of the expression,
-so this increment/decrement has no effect.
+so this increment/decrement has no effect.
Please verify that this statement does the right thing.
</p>
]]>
@@ -6622,7 +7058,7 @@ This code converts a 32-bit int value to a 64-bit long value, and then
passes that value for a method parameter that requires an absolute time value.
An absolute time value is the number
of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
-For example, the following method, intended to convert seconds since the epoc into a Date, is badly
+For example, the following method, intended to convert seconds since the epoch into a Date, is badly
broken:</p>
<pre>
Date getDate(int seconds) { return new Date(seconds * 1000); }
@@ -6785,7 +7221,7 @@ the String "1" is incompatible with the format specifier %d.
<![CDATA[
<p>
An argument not of type Boolean is being formatted with a %b format specifier. This won't throw an
-exception; instead, it will print true for any nonnull value, and false for null.
+exception; instead, it will print true for any non-null value, and false for null.
This feature of format strings is strange, and may not be what you intended.
</p>
]]>
@@ -7047,7 +7483,7 @@ an indication of some misunderstanding or some other logic error.
</BugPattern>
<BugPattern type="BC_VACUOUS_INSTANCEOF">
<ShortDescription>instanceof will always return true</ShortDescription>
- <LongDescription>instanceof will always return true for all nonnull values in {1}, since all {2} are instances of {3}</LongDescription>
+ <LongDescription>instanceof will always return true for all non-null values in {1}, since all {2} are instances of {3}</LongDescription>
<Details>
<![CDATA[
<p>
@@ -7177,6 +7613,19 @@ a signed and unsigned right shift (depending upon the size of the shift).
]]>
</Details>
</BugPattern>
+ <BugPattern type="BSHIFT_WRONG_ADD_PRIORITY">
+ <ShortDescription>Possible bad parsing of shift operation</ShortDescription>
+ <LongDescription>Possible bad parsing of shift operation in {1}</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+The code performs an operation like (x << 8 + y). Although this might be correct, probably it was meant
+to perform (x << 8) + y, but shift operation has
+a lower precedence, so it's actually parsed as x << (8 + y).
+</p>
+]]>
+ </Details>
+ </BugPattern>
<BugPattern type="ICAST_BAD_SHIFT_AMOUNT">
<ShortDescription>32 bit int shifted by an amount not in the range -31..31</ShortDescription>
<LongDescription>32 bit int shifted by {2} bits in {1}</LongDescription>
@@ -8068,8 +8517,8 @@ after the call to initLogging, the logger configuration is lost
<Details>
<![CDATA[<p>
A method should always implement the contract of a method it overrides. Thus, if a method takes a parameter
- that is marked as @Nullable, you shouldn't override that method in a subclass with a method where that parameter is @Nonnull.
- Doing so violates the contract that the method should handle a null parameter.
+ that is marked as @Nullable, you shouldn't override that method in a subclass with a method where that parameter is @Nonnull.
+ Doing so violates the contract that the method should handle a null parameter.
</p>]]>
</Details>
</BugPattern>
@@ -8079,8 +8528,8 @@ after the call to initLogging, the logger configuration is lost
<Details>
<![CDATA[<p>
A method should always implement the contract of a method it overrides. Thus, if a method takes a parameter
- that is marked as @Nullable, you shouldn't override that method in a subclass with a method where that parameter is @Nonnull.
- Doing so violates the contract that the method should handle a null parameter.
+ that is marked as @Nullable, you shouldn't override that method in a subclass with a method where that parameter is @Nonnull.
+ Doing so violates the contract that the method should handle a null parameter.
</p>]]>
</Details>
</BugPattern>
@@ -8091,9 +8540,9 @@ after the call to initLogging, the logger configuration is lost
<Details>
<![CDATA[<p>
A method should always implement the contract of a method it overrides. Thus, if a method takes is annotated
- as returning a @Nonnull value,
- you shouldn't override that method in a subclass with a method annotated as returning a @Nullable or @CheckForNull value.
- Doing so violates the contract that the method shouldn't return null.
+ as returning a @Nonnull value,
+ you shouldn't override that method in a subclass with a method annotated as returning a @Nullable or @CheckForNull value.
+ Doing so violates the contract that the method shouldn't return null.
</p>]]>
</Details>
</BugPattern>
@@ -8111,6 +8560,7 @@ after the call to initLogging, the logger configuration is lost
<BugCode abbrev="TEST">Testing prototype and incomplete bug pattern</BugCode>
<BugCode abbrev="IMSE">Dubious catching of IllegalMonitorStateException</BugCode>
<BugCode abbrev="CN">Bad implementation of cloneable idiom</BugCode>
+ <BugCode abbrev="CAA">Covariant array assignment</BugCode>
<BugCode abbrev="AT">Possible atomicity violation</BugCode>
<BugCode abbrev="FI">Incorrect use of finalizers</BugCode>
<BugCode abbrev="ES">Checking String equality using == or !=</BugCode>
@@ -8132,7 +8582,7 @@ after the call to initLogging, the logger configuration is lost
<BugCode abbrev="NN">Naked notify</BugCode>
<BugCode abbrev="UW">Unconditional wait</BugCode>
<BugCode abbrev="SP">Method spins on field</BugCode>
- <BugCode abbrev="DC">Possible double check of field</BugCode>
+ <BugCode abbrev="DC">Double check pattern</BugCode>
<BugCode abbrev="Wa">Wait not in loop</BugCode>
<BugCode abbrev="No">Using notify() rather than notifyAll()</BugCode>
<BugCode abbrev="DE">Dropped or ignored exception</BugCode>
@@ -8144,6 +8594,7 @@ after the call to initLogging, the logger configuration is lost
<BugCode abbrev="RS">Class's readObject() method is synchronized</BugCode>
<BugCode abbrev="SC">Constructor invokes Thread.start()</BugCode>
<BugCode abbrev="MS">Mutable static field</BugCode>
+ <BugCode abbrev="ME">Mutable enum field</BugCode>
<BugCode abbrev="EI">Method returning array may expose internal representation</BugCode>
<BugCode abbrev="Nm">Confusing method name</BugCode>
<BugCode abbrev="SS">Unread field should be static</BugCode>
@@ -8152,6 +8603,7 @@ after the call to initLogging, the logger configuration is lost
<BugCode abbrev="UwF">Unwritten field</BugCode>
<BugCode abbrev="SIC">Inner class could be made static</BugCode>
<BugCode abbrev="TLW">Wait with two locks held</BugCode>
+ <BugCode abbrev="RANGE">Range checks</BugCode>
<BugCode abbrev="RV">Bad use of return value from method</BugCode>
<BugCode abbrev="LG">Logger problem</BugCode>
<BugCode abbrev="IA">Ambiguous invocation</BugCode>
@@ -8181,6 +8633,8 @@ after the call to initLogging, the logger configuration is lost
<BugCode abbrev="NS">Suspicious use of non-short-circuit boolean operator</BugCode>
<BugCode abbrev="ODR">Database resource not closed on all paths</BugCode>
<BugCode abbrev="SBSC">String concatenation in loop using + operator</BugCode>
+ <BugCode abbrev="IIL">Inefficient code which can be moved outside of the loop</BugCode>
+ <BugCode abbrev="IIO">Inefficient use of String.indexOf(String) or String.lastIndexOf(String)</BugCode>
<BugCode abbrev="ITA">Inefficient use of collection.toArray(new Foo[0])</BugCode>
<BugCode abbrev="SW">Swing coding rules</BugCode>
<BugCode abbrev="IJU">Improperly implemented JUnit TestCase</BugCode>
@@ -8198,6 +8652,8 @@ after the call to initLogging, the logger configuration is lost
<BugCode abbrev="REC">RuntimeException capture</BugCode>
<BugCode abbrev="FE">Test for floating point equality</BugCode>
<BugCode abbrev="UM">Unnecessary Math on constants</BugCode>
+ <BugCode abbrev="UC">Useless code</BugCode>
+ <BugCode abbrev="CNT">Rough value of known constant</BugCode>
<BugCode abbrev="CD">Circular Dependencies</BugCode>
<BugCode abbrev="RI">Redundant Interfaces</BugCode>
<BugCode abbrev="MTIA">Multithreaded Instance Access</BugCode>
diff --git a/etc/messages_fr.xml b/etc/messages_fr.xml
index 45f0a46..e6bb956 100644
--- a/etc/messages_fr.xml
+++ b/etc/messages_fr.xml
@@ -10,6 +10,8 @@
<p>Ce plugin contient tous les détecteurs standards de FindBugs.</p>
]]>
</Details>
+ <BugsUrl>http://findbugs.sourceforge.net/bugDescriptions_fr.html</BugsUrl>
+ <AllBugsUrl>http://findbugs.sourceforge.net/bugDescriptions_fr.html</AllBugsUrl>
</Plugin>
diff --git a/etc/messages_ja.xml b/etc/messages_ja.xml
index 84f9c5f..85510bd 100644
--- a/etc/messages_ja.xml
+++ b/etc/messages_ja.xml
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
-
<MessageCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="messagecollection.xsd">
<!--
@@ -16,6 +15,8 @@
</p>
]]>
</Details>
+ <BugsUrl>http://findbugs.sourceforge.net/bugDescriptions_ja.html</BugsUrl>
+ <AllBugsUrl>http://findbugs.sourceforge.net/bugDescriptions_ja.html</AllBugsUrl>
</Plugin>
<FindBugsMain cmd="addMessages" class="edu.umd.cs.findbugs.AddMessages">
@@ -61,39 +62,34 @@
<!-- これを変えたら FindbugsPlugin のデフォルト ID も更新して下さい -->
<Cloud id="edu.umd.cs.findbugs.cloud.doNothingCloud">
<Description>(クラウド無効)</Description>
- <Details>このプラグインを使用すると、バグレビューは無効になります。</Details>
+ <Details>このプラグインを使うとバグレビューは無効になります。</Details>
</Cloud>
- <PluginComponent
- id="edu.umd.cs.findbugs.bugReporter.SuppressMultithreaded">
+ <PluginComponent id="edu.umd.cs.findbugs.bugReporter.SuppressMultithreaded">
<Description>マルチスレッドの正確性問題を抑止する</Description>
<Details>すべてのマルチスレッドの正確性問題を抑止します</Details>
- </PluginComponent>
+ </PluginComponent>
- <PluginComponent
- id="edu.umd.cs.findbugs.bugReporter.SuppressI18N">
+ <PluginComponent id="edu.umd.cs.findbugs.bugReporter.SuppressI18N">
<Description>国際化問題を抑止する</Description>
<Details>すべての国際化問題を抑止します</Details>
- </PluginComponent>
-
- <PluginComponent
- id="edu.umd.cs.findbugs.bugReporter.SelectivelySuppressI18N">
+ </PluginComponent>
+
+ <PluginComponent id="edu.umd.cs.findbugs.bugReporter.SelectivelySuppressI18N">
<Description>選択したパッケージ以外のすべての国際化問題を抑止する</Description>
<Details>i18n.properties リソースで指定した以外のすべての国際化問題を抑止します</Details>
</PluginComponent>
- <PluginComponent
- id="edu.umd.cs.findbugs.bugReporter.MaxRank14">
+ <PluginComponent id="edu.umd.cs.findbugs.bugReporter.MaxRank14">
<Description>ランク14を越えるすべての問題を抑止する</Description>
<Details>ランク14を越えるすべての問題を抑止します</Details>
</PluginComponent>
- <PluginComponent
- id="edu.umd.cs.findbugs.bugReporter.SuppressMalicious">
- <Description>悪質なコード脆弱性について警告を抑止する</Description>
- <Details>悪質なコード脆弱性について警告を抑止します</Details>
- </PluginComponent>
-
+ <PluginComponent id="edu.umd.cs.findbugs.bugReporter.SuppressMalicious">
+ <Description>悪意のあるコード脆弱性について警告を抑止する</Description>
+ <Details>悪意のあるコード脆弱性について警告を抑止します</Details>
+ </PluginComponent>
+
<!--
**********************************************************************
Categories (replacing the BugCategoryDescriptions.properties file)
@@ -104,7 +100,7 @@
<Description>正確性</Description>
<Abbreviation>C</Abbreviation>
<Details>バグの可能性 - おそらく、開発者が意図していなかったコードになっている明らかなコーディング間違いです。
- 我々は、低い誤検出率のために努力します。
+ 我々は低い誤検出率のために努力します。
</Details>
</BugCategory>
@@ -126,7 +122,7 @@
<Description>バッドプラクティス</Description>
<Abbreviation>B</Abbreviation>
<Details>推奨または必須のコーディングプラクティスの違反です。たとえば、hashCode と equals の問題、cloneable イディオム、捨てられた例外、Serializable の問題、finalize の誤用などです。
- いくつかのグループは、バッドプラクティスを気にしないかもしれないが、我々は正確な解析をしようと努力します。
+ いくつかのグループはバッドプラクティスを気にしないかもしれないが、我々は正確な解析をしようと努力します。
</Details>
</BugCategory>
@@ -147,7 +143,7 @@
</BugCategory>
<BugCategory category="MALICIOUS_CODE">
- <Description>悪質なコード脆弱性</Description>
+ <Description>悪意のあるコード脆弱性</Description>
<Abbreviation>V</Abbreviation>
<Details>信頼できないコードからの攻撃に脆弱であるコード</Details>
</BugCategory>
@@ -178,11 +174,20 @@
Detectors
**********************************************************************
-->
+ <Detector class="edu.umd.cs.findbugs.detect.FindRoughConstants">
+ <Details>
+<![CDATA[
+<p>
+このディテクタは、ほぼ (しかし、正確ではなく) 同じである Math.PI のような既知の定数を見つけます。
+</p>
+]]>
+ </Details>
+ </Detector>
<Detector class="edu.umd.cs.findbugs.detect.InitializeNonnullFieldsInConstructor">
<Details>
<![CDATA[
<p> Finds nonnull fields that are not written to in constructors.
-このディテクタは、コンストラクタで書き込まれない非 null フィールドを発券します。
+このディテクタは、コンストラクタで書き込まれない非 null フィールドを見つけます。
</p>
]]>
</Details>
@@ -191,7 +196,7 @@
<Details>
<![CDATA[
<p>
-このディテクタは、エポックからミリ秒を記述する32ビット値の使い方を発見します。
+このディテクタは、エポックからミリ秒を記述する32ビット値の使い方を見つけます。
</p>
]]>
</Details>
@@ -211,7 +216,7 @@
<Details>
<![CDATA[
<p>
-このディテクタは、型修飾子が直接適用されるメソッドパラメータとそれらのメソッドパラメータの使い方との間で矛盾を発見します。
+このディテクタは、型修飾子が直接適用されるメソッドパラメータとそれらのメソッドパラメータの使い方との間で矛盾を見つけます。
</p>
]]>
</Details>
@@ -221,7 +226,7 @@
<Details>
<![CDATA[
<p>
-このディテクタは、原子的に実行されない並行抽象化に関して、演算(たとえば、get/put)のシーケンスを発見します。
+このディテクタは、原子的に実行されない並行抽象化に関して、演算(たとえば、get/put)のシーケンスを見つけます。
</p>
]]>
</Details>
@@ -336,7 +341,7 @@
<Details>
<![CDATA[
<p>
-このディテクタは、他のディテクタが使用するために、解析されたクラスで定義されているすべてのメソッドのデータベースを構築します。
+このディテクタは、他のディテクタが使用するための解析されたクラスで定義されているすべてのメソッドのデータベースを構築します。
</p>
]]>
</Details>
@@ -354,7 +359,25 @@
<Details>
<![CDATA[
<p>
-このディテクタは、他のディテクタが使用するために、解析されたクラスで呼び出されるすべてのメソッドのデータベースを構築します。
+このディテクタは、他のディテクタが使用するための解析されたクラスで呼び出されるすべてのメソッドのデータベースを構築します。
+</p>
+]]>
+ </Details>
+ </Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.FindNoSideEffectMethods">
+ <Details>
+<![CDATA[
+<p>
+値を返すだけの副作用を持たないメソッドを探します。
+</p>
+]]>
+ </Details>
+ </Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.BuildStringPassthruGraph">
+ <Details>
+<![CDATA[
+<p>
+このディテクタは、メソッドから変化していないメソッドに渡された文字列パラメータのデータベースを構築します。
</p>
]]>
</Details>
@@ -364,7 +387,7 @@
<![CDATA[
<p>
このディテクタは、クラスの新しいインスタンスを返すメソッドがある不変クラスを探します。
-それらのメソッドが呼び出されるところでインスタンスを変化させると事故が起きるかもしれません。
+メソッドが呼び出されるとインスタンスが変化させられると思います。
</p>
]]>
</Details>
@@ -410,8 +433,8 @@
<Details>
<![CDATA[
<p>
-このディテクタは、メソッド、フィールド、パラメータで @NonNull アノテーションを探します。
-null かもしれない値が null でない値だけが使われるべき文脈で使われたときに FindNullDeref ディテクタが警告を生成するために使われます。
+このディテクタは、メソッド、フィールド、パラメータで @Nonnull アノテーションを探します。
+null かもしれない値が null でない値だけが使われるべき文脈で使われたとき警告を生成するために FindNullDeref ディテクタはこれらを使用できます。
</p>
]]>
</Details>
@@ -421,7 +444,7 @@ null かもしれない値が null でない値だけが使われるべき文脈
<Details>
<![CDATA[
<p>
-このディテクタは、無条件でパラメータの null 値が利用されるのか判定するためにアプリケーションのすべてのメソッドを解析します。
+このディテクタは、無条件にパラメータの参照外しが行われるのかを決定するためにアプリケーションのすべてのメソッドを解析します。
この情報は、null 値がメソッドに渡されるかもしれない呼び出し場所を発見するために後の解析パスで使われます。
</p>
<p>
@@ -435,7 +458,7 @@ null かもしれない値が null でない値だけが使われるべき文脈
<Details>
<![CDATA[
<p>
-このディテクタは、どのメソッドが常に非 null 値を返すのか判定するためにアプリケーションで、すべてのメソッドを解析します。
+このディテクタは、どのメソッドが常に非 null 値を返すのかを決定するためにアプリケーションのすべてのメソッドを解析します。
</p>
]]>
</Details>
@@ -451,12 +474,39 @@ null かもしれない値が null でない値だけが使われるべき文脈
]]>
</Details>
</Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.OptionalReturnNull">
+ <Details>
+<![CDATA[
+<p>
+このディテクタは、Optional の戻り型が明示的に null 値を返すメソッドを探します。
+</p>
+]]>
+ </Details>
+ </Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.FindUselessObjects">
+ <Details>
+<![CDATA[
+<p>
+このディテクタは役に立たないオブジェクトを探します。
+</p>
+]]>
+ </Details>
+ </Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.MutableEnum">
+ <Details>
+<![CDATA[
+<p>
+このディテクタは、可変列挙型フィールドを探して警告します。
+</p>
+]]>
+ </Details>
+ </Detector>
<Detector class="edu.umd.cs.findbugs.detect.BadUseOfReturnValue">
<Details>
<![CDATA[
<p>
-このディテクタは、メソッドの戻り値が null でないのかチェックされた後に捨てられるケースを探します。
+このディテクタは、メソッドの戻り値を null でないのかチェックした後で捨てるケースを探します。
</p>
]]>
@@ -494,7 +544,7 @@ null かもしれない値が null でない値だけが使われるべき文脈
<Details>
<![CDATA[
<p>
-このディテクタは、volatile フィールドの使い方でバグパターンを探します。
+このディテクタは、volatile フィールドの使い方のバグパターンを探します。
</p>
]]>
</Details>
@@ -538,7 +588,7 @@ null かもしれない値が null でない値だけが使われるべき文脈
<![CDATA[
<p>
<code>java.net.URL</code> の equals と hashCode メソッドはドメイン名の解決をします。
-その結果、これらの演算は非常に高くつく可能性があります。このディテクタは、メソッドが呼び出されるかもしれない場所を探します。
+その結果、これらの演算はかなり高くつきます。このディテクタは、メソッドが呼び出されるかもしれない場所を探します。
</p>
]]>
</Details>
@@ -575,6 +625,16 @@ null かもしれない値が null でない値だけが使われるべき文脈
</Details>
</Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.RedundantConditions">
+ <Details>
+<![CDATA[
+<p>
+このディテクタは、この式の2番目の条件のような役に立たない条件を含んでいるコードを探します (x >= 10 && x >= 5).
+</p>
+]]>
+ </Details>
+ </Detector>
+
<Detector class="edu.umd.cs.findbugs.detect.CallToUnsupportedMethod">
<Details>
<![CDATA[
@@ -608,7 +668,7 @@ null かもしれない値が null でない値だけが使われるべき文脈
<Details>
<![CDATA[
<p>
-このディテクタは、新しいディテクタをテストするためのフックです。一般に、このディテクタは何もしません。
+このディテクタは、新しいディテクタをテストするためのフックです。通常このディテクタは何もしません。
</p>
]]>
</Details>
@@ -618,7 +678,7 @@ null かもしれない値が null でない値だけが使われるべき文脈
<Details>
<![CDATA[
<p>
-このディテクタは、新しいディテクタをテストするためのフックです。一般に、このディテクタは何もしません。
+このディテクタは、新しいディテクタをテストするためのフックです。通常このディテクタは何もしません。
</p>
]]>
</Details>
@@ -638,7 +698,7 @@ null かもしれない値が null でない値だけが使われるべき文脈
<Details>
<![CDATA[
<p>
-このディテクタは、新しいディテクタをテストするためのフックです。一般に、このディテクタは何もしません。
+このディテクタは、新しいディテクタをテストするためのフックです。通常このディテクタは何もしません。
</p>
]]>
</Details>
@@ -652,7 +712,7 @@ null かもしれない値が null でない値だけが使われるべき文脈
これらの警告はソフトウェアで実際のバグを発見するのではなく、データマイニング実験のコントロールとして役に立つことを目的とした偽のランダムノイズです。
</p>
<p>
-このディテクタは、新しいディテクタをテストするためのフックです。一般に、このディテクタは何もしません。
+このディテクタは、新しいディテクタをテストするためのフックです。通常このディテクタは何もしません。
</p>
]]>
</Details>
@@ -828,6 +888,16 @@ null の参照解除のためのノイズが多いディテクタです。コー
</Details>
</Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.CovariantArrayAssignment">
+ <Details>
+<![CDATA[
+<p>
+このディテクタは、実行時に ArrayStoreException を引き起こすかもしれない Object[] array = new String[10] のような共変配列代入を探します。
+</p>
+]]>
+ </Details>
+ </Detector>
+
<Detector class="edu.umd.cs.findbugs.detect.NumberConstructor">
<Details>
<![CDATA[
@@ -1008,7 +1078,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<Details>
<![CDATA[
<p>
-このディテクタは、変更されたフィールドから読み込まれるオブジェクトで同期化を探します。
+このディテクタは、変更されたフィールドから読み込まれるオブジェクトの同期化を探します。
</p>
]]>
</Details>
@@ -1028,7 +1098,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<Details>
<![CDATA[
<p>
-このディテクタは、悪質なコードによって変更されるかもしれない static フィールドを探します。
+このディテクタは、悪意のあるコードによって変更されるかもしれない static フィールドを探します。
</p>
]]>
</Details>
@@ -1058,7 +1128,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<Details>
<![CDATA[
<p>
-このディテクタは、Serializable クラスの実装で潜在的な問題を探します。
+このディテクタは、Serializable クラスの実装の潜在的な問題を探します。
</p>
]]>
</Details>
@@ -1083,7 +1153,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
]]>
</Details>
</Detector>
- <Detector class="edu.umd.cs.findbugs.detect.ExplicitSerialization" >
+ <Detector class="edu.umd.cs.findbugs.detect.ExplicitSerialization">
<Details>
<![CDATA[
<p>
@@ -1125,6 +1195,16 @@ null の参照解除のためのノイズが多いディテクタです。コー
</Details>
</Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.FindComparatorProblems">
+ <Details>
+<![CDATA[
+<p>
+このディテクタは、Comparator.compare または Comparable.compareTo の実装における問題を探します。
+ </p>
+]]>
+ </Details>
+ </Detector>
+
<Detector class="edu.umd.cs.findbugs.detect.FindNullDeref">
<Details>
<![CDATA[
@@ -1193,7 +1273,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
中速ディテクタです。
</p>
<p>
-このディテクタを使用するために、補助クラスパスに java.util.concurrent パッケージ (またはパッケージ自体を解析している) が必要であることに注意してください。
+補助クラスパスに java.util.concurrent パッケージ (またはパッケージ自体を解析している) が必要であることに注意してこのディテクタを使用してください
</p>
]]>
</Details>
@@ -1204,7 +1284,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<![CDATA[
<p>
このディテクタは、2つの参照値を == や != 演算子で比較している場所を探します。
-<code>java.lang.String</code> のような型のクラスで参照値を比較することは、一般に誤りです。
+<code>java.lang.String</code> のような型のクラスの参照値を比較することは一般的に誤りです。
</p>
</p>
低速ディテクタです。
@@ -1288,7 +1368,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<Details>
<![CDATA[
<p>
-このディテクタは、JSR-166のロックで実行される一般にの同期化を探します。
+このディテクタは、JSR-166のロックで実行される通常の同期化を探します。
</p>
<p>
中速ディテクタです。
@@ -1316,7 +1396,26 @@ null の参照解除のためのノイズが多いディテクタです。コー
]]>
</Details>
</Detector>
-
+ <Detector class="edu.umd.cs.findbugs.detect.InefficientInitializationInsideLoop">
+ <Details>
+<![CDATA[
+<p>
+このディテクタは、パフォーマンスを向上させるために外側に移せるループ内で初期化しているオブジェクトを探します。
+</p>
+]]>
+ </Details>
+ </Detector>
+ <Detector class="edu.umd.cs.findbugs.detect.InefficientIndexOf">
+ <Details>
+<![CDATA[
+<p>
+このディテクタは、String.indexOf(String) または String.lastIndexOf(String) を使用して定数に長さ1の文字列を渡すコードを探します。
+より効率的な整数実装を使用することを推奨します。
+高速ディテクタです。
+</p>
+]]>
+ </Details>
+ </Detector>
<Detector class="edu.umd.cs.findbugs.detect.InefficientToArray">
<Details>
<![CDATA[
@@ -1361,7 +1460,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<Details>
<![CDATA[
<p>
-このディテクタは、判定が静的に行われる可能性がある instanceof 演算子を使用している型チェックを探します。
+このディテクタは、静的に判定される instanceof 演算子を使用している型チェックを探します。
</p>
]]>
</Details>
@@ -1573,7 +1672,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
]]>
</Details>
</Detector>
-
+
<Detector class="edu.umd.cs.findbugs.detect.FindUseOfNonSerializableValue">
<Details>
<![CDATA[
@@ -1583,7 +1682,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
]]>
</Details>
</Detector>
-
+
<Detector class="edu.umd.cs.findbugs.detect.FindNonSerializableValuePassedToWriteObject">
<Details>
<![CDATA[
@@ -1665,7 +1764,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<![CDATA[
<p>
このディテクタは、スーパークラスで定義されたメソッドを実装して、スーパークラスのメソッドにパラメータをそのまま渡しているだけのサブクラスを探します。
-これらのメソッドは削除できます。
+これらのメソッドは除去できます。
</p>
]]>
</Details>
@@ -1677,7 +1776,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<p>
このディテクタは、protected メンバを宣言する final クラスを探します。
このクラスは派生させることができないので、protected メンバの使用は正しくありません。
-アクセス権は、メンバの正しい意図を表すために、public か private に変更するべきです。
+アクセス権は、メンバの正しい意図を表すために public か private に変更するべきです。
</p>
<p>
おそらく、新しいパラダイムにクラスのすべてを完全に変更することではなく、クラスの使用中の変化が原因となりました。
@@ -1700,7 +1799,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<![CDATA[
<p>
このディテクタは、どのメソッドが null を返すのかを決定してファイルに保存します。
-結果ファイルは、null 間接参照ディテクタの精度を向上させるために後続のパスで使われるかもしれません。
+結果ファイルは、null 間接参照ディテクタの精度を向上させるために後続のパスで使われることがあります。
これはトレーニングパスなので警告は報告されません。
</p>
<p>
@@ -1714,8 +1813,8 @@ null の参照解除のためのノイズが多いディテクタです。コー
<Details>
<![CDATA[
<p>
-このディテクタは、どのメソッドが null 値のパラメータを無条件で利用するのかを決定してファイルに保存します。
-結果ファイルは、 null 間接参照ディテクタの精度を向上させるために後続のパスで使われるかもしれません。
+このディテクタは、どのメソッドが無条件に null の参照外しを行うのかを決定してファイルに保存します。
+結果ファイルは、 null 間接参照ディテクタの精度を向上させるために後続のパスで使われることがあります。
これはトレーニングパスなので警告は報告されません。
</p>
<p>
@@ -1730,7 +1829,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<![CDATA[
<p>
このディテクタは、フィールドに格納される型を解析してデータベースに保存します。
-データベースは、型解析をより正確にするために後続のパスで使われるかもしれません。
+データベースは、型解析をより正確にするために後続のパスで使われることがあります。
</p>
<p>
低速ディテクタです。
@@ -1743,7 +1842,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<Details>
<![CDATA[
<p>
-このディテクタは、@NonNull と @PossiblyNull アノテーションを集めて、データベースに保存します。
+このディテクタは、@Nonnull と @PossiblyNull アノテーションを集めて、データベースに保存します。
</p>
<p>
高速ディテクタです。
@@ -1788,7 +1887,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<Details>
<![CDATA[
<p>
-このディテクタは、引数の型がコレクションのパラメータに関連しているかどうか確かめるために、<code>java.lang.Object</code> を受け取る総称型コレクションメソッドへの呼び出しの引数を見ます。
+このディテクタは、引数の型がコレクションのパラメータに関連しているかどうか確かめるために <code>java.lang.Object</code> を受け取る総称型コレクションメソッドへの呼び出しの引数を見ます。
無関係なクラス型による引数は決してコレクションの中に格納されることはありません。
たとえば、<code>foo</code> が <code>List<String></code> で、<code>bar</code> が <code>StringBuffer</code> なら <code>foo.contains(bar)</code> の呼び出しは常に false を返すことになります。
</p>
@@ -1876,7 +1975,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<![CDATA[
<p>
このディテクタは、ユーザのデフォルトプラットホームエンコーディングを使用して、バイトから String (またはString からバイト) に変換するメソッドの呼び出しをチェックします。
-これは、アプリケーションの振る舞いがプラットホーム間で異なる原因となります。
+これはアプリケーションの振る舞いがプラットホーム間で異なる原因となります。
</p>
]]>
</Details>
@@ -1886,7 +1985,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<Details>
<![CDATA[
<p>
-このディテクタは、オーバライドメソッドが 戻り値またはパラメータの @CheckForNull (@Nonnullで作られた) で @Nonnull (@CheckForNull で作られた) を緩和していないことをチェックします。
+このディテクタは、オーバライドメソッドが 戻り値またはパラメータの @CheckForNull (@Nonnull で作られた) で @Nonnull (@CheckForNull で作られた) を緩和していないことをチェックします。
</p>
]]>
</Details>
@@ -1898,13 +1997,25 @@ null の参照解除のためのノイズが多いディテクタです。コー
**********************************************************************
-->
+ <BugPattern type="CNT_ROUGH_CONSTANT_VALUE">
+ <ShortDescription>既知の定数の雑な値を見つける</ShortDescription>
+ <LongDescription>{3} の雑な値を見つけました: {2}</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+コードの明確さともっと良い正確さのために定義済みライブラリ定数を使用することを推奨します。
+</p>
+]]>
+</Details>
+ </BugPattern>
+
<BugPattern type="SKIPPED_CLASS_TOO_BIG">
<ShortDescription>解析するにはあまりにも大きいクラス</ShortDescription>
<LongDescription>{0} は、解析するにはあまりにも大きいです。</LongDescription>
<Details>
<![CDATA[
<p>
-このクラスは有効に処理することができないほど大きいです。また、エラーのために完全に解析されませんでした。
+このクラスは効率的に処理できないほど大きいです。また、エラーのために完全に解析されませんでした。
</p>
]]>
</Details>
@@ -1965,7 +2076,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
<![CDATA[
<p>
このコードは、10進数の数にうまく変換されない double 値から BigDecimal を作成しています。
-たとえば、Java で <code>new BigDecimal(0.1)</code> と書くと、0.1と正確に等しい BigDecimal (スケールが1でスケールなしの値が1) が作成されると思うかもしれませんが
+たとえば、Java で <code>new BigDecimal(0.1)</code> と書くと、0.1と正確に等しい BigDecimal (スケールが1でスケールなしの値が1) が作成されると思うかもしれませんが、
実際には0.1000000000000000055511151231257827021181583404541015625と等しくなります。
</p>
<p>
@@ -1984,7 +2095,7 @@ null の参照解除のためのノイズが多いディテクタです。コー
この部分的なメソッド呼び出しは、検査から明らかな理由で意味がありません。
</p>
]]>
- </Details>
+ </Details>
</BugPattern>
<BugPattern type="DMI_VACUOUS_CALL_TO_EASYMOCK_METHOD">
@@ -2019,8 +2130,8 @@ null の参照解除のためのノイズが多いディテクタです。コー
<Details>
<![CDATA[
<p>
-<code>ScheduledThreadPoolExecutor</code> は <code>ThreadPoolExecutor</code> から継承されますが継承されたチューニングメソッドの一部は有効ではありません。
-特に、corePoolSize スレッドとアンバウンド形式のキューを使用する固定サイズプールとして動作するので、maximumPoolSize の調整は有効な効果がありません。<br>
+<code>ScheduledThreadPoolExecutor</code> は <code>ThreadPoolExecutor</code> から継承されますが継承されたチューニングメソッドの一部は有用ではありません。
+特に、corePoolSize スレッドとアンバウンド形式のキューを使用する固定サイズプールとして動作するので、maximumPoolSize の調整は有用な効果がありません。<br>
(<a href="http://java.sun.com/javase/ja/6/docs/ja/api/java/util/concurrent/ScheduledThreadPoolExecutor.html">Javadoc</a>)
</p>
]]>
@@ -2197,7 +2308,7 @@ XSS に関して心配しているなら商用の静的解析ツールかペネ
<![CDATA[
<p>
(<a href="http://web.archive.org/web/20090526170426/http://java.sun.com/developer/JDCTechTips/2003/tt1208.html">From JDC Tech Tip</a>)<br>
-に解説されているとおり、Swing のメソッド、<code>show</code> メソッド、<code>setVisible</code> メソッド、<code>pack</code> メソッドは、フレームのために関連したピアを作成します。
+に解説されているとおり、Swing のメソッド、<code>show</code> メソッド、<code>setVisible</code> メソッド、<code>pack</code> メソッドは、フレームのための関連したピアを作成します。
ピアの作成で、システムはイベントディスパッチスレッドを作成します。
これが問題になることがあります。なぜなら <code>pack</code> メソッドと <code>validate</code> メソッドがまだ処理中でもイベントディスパッチスレッドがリスナに通知できるからです。
この状況は、2つのスレッドが Swing コンポーネントにアクセスする可能性があり、デッドロックや、その他のスレッドに関する問題になる可能性がある重大な欠陥です。
@@ -2225,7 +2336,7 @@ XSS に関して心配しているなら商用の静的解析ツールかペネ
<Details>
<![CDATA[
<p>
-このメソッドは、無条件で自分自身を呼び出します。これは、スタックオーバーフローになる無限再帰ループを示しています。
+このメソッドは、無条件で自分自身を呼び出します。これはスタックオーバーフローになる無限再帰ループを示しています。
</p>
]]>
</Details>
@@ -2290,7 +2401,7 @@ volatile フィールドのインクリメントはアトミックではあり
<![CDATA[
<p>
Boolean.TRUE、Boolean.FALSE、null を返すメソッドはいつ事故が起きてもおかしくないです。
-まるで論理型の値を返すかのように、このメソッドは呼び出される可能性があります。
+このメソッドは、まるで論理型の値を返すかのように呼び出されます。
コンパイラは Boolean 値のオートアンボクシングを挿入します。
null 値が返されるなら NullPointerException が発生することになります。
</p>
@@ -2298,6 +2409,19 @@ null 値が返されるなら NullPointerException が発生することにな
</Details>
</BugPattern>
+ <BugPattern type="NP_OPTIONAL_RETURN_NULL">
+ <ShortDescription>Optional の戻り型を持つメソッドが明示的に null を返す</ShortDescription>
+ <LongDescription>{1} は、Optional の戻り型を持っていて、 明示的に null を返しています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+Optional の戻り型の使い方は、常に明示的に null を返すのは設計が望ましくないことを意味します。
+null 値をこのようなケースで返すことは契約違反で、多分クライアントコードを破壊するでしょう。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR">
<ShortDescription>非 null フィールドは初期化されていない</ShortDescription>
<LongDescription>非 null フィールド {2.name} は {1} によって初期化されていません。</LongDescription>
@@ -2435,7 +2559,7 @@ null のフィールドを同期化すると NullPointerException がスロー
<Details>
<![CDATA[
<p>
-<code>IllegalMonitorStateException</code> は、一般に設計上の欠陥 (ロックを保持していないオブジェクトで <code>wait</code> メソッドまたは <code>notify</code> メソッドを呼び出す) の場合にだけスローされます。
+<code>IllegalMonitorStateException</code> は、一般的に設計上の欠陥 (ロックを保持していないオブジェクトで <code>wait</code> メソッドまたは <code>notify</code> メソッドを呼び出す) の場合にだけスローされます。
</p>
]]>
</Details>
@@ -2456,6 +2580,76 @@ null のフィールドを同期化すると NullPointerException がスロー
</Details>
</BugPattern>
+ <BugPattern type="CAA_COVARIANT_ARRAY_FIELD">
+ <ShortDescription>フィールドへの共変配列代入</ShortDescription>
+ <LongDescription>型 {2} の配列が型 {3} のフィールドに割り当てられています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+共変型の配列がフィールドに割り当てられています。
+紛らわしくて、次のコードのように他の型の参照が後で配列に格納されるなら、実行時に ArrayStoreException を引き起こすことがあります。
+</p>
+<blockquote><pre>
+Number[] arr = new Integer[10];
+arr[0] = 1.0;
+</pre></blockquote>
+<p>
+作成した配列の型またはフィールド型を変更することを検討してください。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="CAA_COVARIANT_ARRAY_LOCAL">
+ <ShortDescription>ローカル変数への共変配列代入</ShortDescription>
+ <LongDescription>型 {2} の配列が型 {3} の変数に割り当てられています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+共変型の配列がローカル変数に割り当てられています。
+紛らわしくて、次のコードのように他の型の参照が後で配列に格納されるなら、実行時に ArrayStoreException を引き起こすことがあります。
+</p>
+<blockquote><pre>
+Number[] arr = new Integer[10];
+arr[0] = 1.0;
+</pre></blockquote>
+<p>
+作成した配列の型またはローカル変数型を変更することを検討してください。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="CAA_COVARIANT_ARRAY_RETURN">
+ <ShortDescription>共変配列がメソッドから返される</ShortDescription>
+ <LongDescription>型 {2} の配列が戻り型 {3} であるメソッドから返されます。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+共変型の配列がメソッドから返されます。
+呼び出し元のコードが返された配列に他の型の参照を格納しようとするなら、実行時に ArrayStoreException を引き起こすことがあります。
+</p>
+<p>
+作成した配列の型またはメソッドの戻り型を変更することを検討してください。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="CAA_COVARIANT_ARRAY_ELEMENT_STORE">
+ <ShortDescription>おそら互換性のない要素をく共変配列に格納している</ShortDescription>
+ <LongDescription>型 {2} の値を要素の型が {3} の配列に格納しています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+配列に格納していてる値の型が配列型と一致していません。
+実際の配列型が宣言された変数またはフィールドの型よりも狭くなっていて、この割り当てがオリジナルの配列型を満たしていないことが解析でわかっています。
+この割り当ては実行時に ArrayStoreException を引き起こすことがあります。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="CN_IDIOM">
<ShortDescription>Cloneable を実装したクラスが clone メソッドを定義していないか、使用していない</ShortDescription>
<LongDescription>クラス {0} は、Cloneable を実装していますが、clone メソッドを定義していないか使用していません。</LongDescription>
@@ -2531,7 +2725,7 @@ null のフィールドを同期化すると NullPointerException がスロー
<![CDATA[
<p>
このメソッドは、例外を捨てているかもしれません。
-一般にキャッチした例外は何らかの方法で処理、または報告するべきです、あるいはメソッドからスローするべきです。
+一般的にキャッチした例外は何らかの方法で処理、または報告するべきです、またはメソッドからスローするべきです。
</p>
]]>
</Details>
@@ -2544,7 +2738,7 @@ null のフィールドを同期化すると NullPointerException がスロー
<![CDATA[
<p>
このメソッドは例外を無視しているかもしれません。
-一般に例外は何らかの方法で処理、または報告するべきです、あるいはメソッドからスローするべきです。
+一般的に例外は何らかの方法で処理、または報告するべきです、またはメソッドからスローするべきです。
</p>
]]>
</Details>
@@ -2608,22 +2802,22 @@ null のフィールドを同期化すると NullPointerException がスロー
<![CDATA[
<p>
Threadオブジェクトが Runnable が期待されているメソッドへのパラメータとして渡されています。
-これはかなり異常で、論理エラーを示すか、予想外の振る舞いの原因になるかもしれません。
+これはかなり異常で、論理エラーを示すか、予想外の振る舞いの原因になることがあります。
</p>
]]>
</Details>
</BugPattern>
<BugPattern type="DMI_COLLECTION_OF_URLS">
- <ShortDescription>URL の Map や Set はひどい性能になる可能性がある</ShortDescription>
- <LongDescription>{1} は、URL の Map か Set を使用しているので、ひどい性能になる可能性があります。</LongDescription>
+ <ShortDescription>URL の Map や Set はひどい性能になる</ShortDescription>
+ <LongDescription>{1} は、URL の Map か Set を使用しているので、ひどい性能になります。</LongDescription>
<Details>
<![CDATA[
<p>
このメソッドまたはフィールドは、URL の <code>Map</code> か <code>Set</code> を使用しています。
-URL の <code>equals</code> と <code>hashCode</code> は、ドメイン名の解決を行うので、ひどい性能になる可能性があります。<br>
+URL の <code>equals</code> と <code>hashCode</code> は、ドメイン名の解決を行うので、ひどい性能になります。<br>
詳細は、<a href="http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html">http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html</a> を参照してください。<br>
-その代わりに <code>java.net.URI</code> を使うことをを検討してください。
+その代わりに <code>java.net.URI</code> を使用することを検討してください。
</p>
]]>
</Details>
@@ -2637,7 +2831,7 @@ URL の <code>equals</code> と <code>hashCode</code> は、ドメイン名の
<p>
URL の <code>equals</code> メソッドと <code>hashCode</code> メソッドは、ドメイン名の解決を行うので、ひどい性能になる可能性があります。<br>
詳細は、<a href="http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html">http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html</a> を参照してください。<br>
-その代わりに <code>java.net.URI</code> を使うことを検討してください。
+その代わりに <code>java.net.URI</code> を使用することを検討してください。
</p>
]]>
</Details>
@@ -2663,7 +2857,7 @@ URL の <code>equals</code> メソッドと <code>hashCode</code> メソッド
<p>
<code>System.exit(...)</code> を呼び出すことは、Java 仮想マシン全体をシャットダウンさせてしまいます。
それが適切な場合にだけ使用するべきです。
-<code>System.exit(...)</code> の呼び出しはコードが他のコードによって呼び出されることを困難か不可能にします。
+<code>System.exit(...)</code> の呼び出しは、他のコードによる呼び出しを困難か不可能にします。
その代わりに RuntimeException をスローすることを検討してください。
</p>
]]>
@@ -2734,7 +2928,7 @@ Javaは、同一の文字列定数が同じ <code>String</code> オブジェク
</p>
<p>
過去に、<code>close</code> メソッドや <code>finalize</code> メソッドでガベージコレクタを明示的に呼び出していた状況は、巨大なパフォーマンスブラックホールの原因となりました。
-ガベージコレクションは、高くつく可能性があります。何百、何千ものガベージコレクションを強制する状況は、システムの停滞をもたらすでしょう。
+ガベージコレクションは高くつきます。何百、何千ものガベージコレクションを強制する状況は、システムの停滞をもたらすでしょう。
</p>
]]>
</Details>
@@ -2747,8 +2941,8 @@ Javaは、同一の文字列定数が同じ <code>String</code> オブジェク
<![CDATA[
<p>
<code>java.lang.Boolean</code> の新しいインスタンスを作成するとメモリを浪費します。
-<code>Boolean</code> オブジェクトは不変で、2つの有効な値 (<code>Boolean.TRUE</code> と <code>Boolean.FALSE</code>) があります。
-その代わりに <code>Boolean</code> オブジェクトを作成するために、<code>Boolean.valueOf</code> メソッド (または J2SE 5.0 のオートボクシング) を使用してください。
+<code>Boolean</code> オブジェクトは不変で、2つの有用な値 (<code>Boolean.TRUE</code> と <code>Boolean.FALSE</code>) があります。
+その代わりに <code>Boolean.valueOf</code> メソッド (または J2SE 5.0 のオートボクシング) を使用して <code>Boolean</code> オブジェクトを作成してください。
</p>
]]>
</Details>
@@ -2762,7 +2956,7 @@ Javaは、同一の文字列定数が同じ <code>String</code> オブジェク
<p>
<code>new Integer(int)</code> の使用は、常に新しいブジェクトになることが保証されています。
これに対して、<code>Integer.valueOf(int)</code> は、コンパイラ、クラスライブラリ、Java 仮想マシンで値がキャッシュされます。
-キャッシュに格納された値を使うことはインスタンスの作成を回避し、コードはより高速になります。
+キャッシュに格納された値を使用することはインスタンスの作成を回避し、コードはより高速になります。
</p>
<p>
-128から127までの値は対応するキャッシュされたインスタンスを持つことが保証されています。
@@ -2783,7 +2977,7 @@ Javaは、同一の文字列定数が同じ <code>String</code> オブジェク
<p>
<code>new Double(double)</code> の使用は、常に新しいブジェクトになることが保証されています。
これに対して、<code>Double.valueOf(double)</code> は、コンパイラ、クラスライブラリ、Java 仮想マシンで値がキャッシュされます。
-キャッシュに格納された値を使うことはインスタンス生成を回避し、コードはより高速になります。
+キャッシュに格納された値を使用することはインスタンス生成を回避し、コードはより高速になります。
</p>
<p>
クラスが J2SE 5.0より前の Java 仮想マシンとの互換性が不要なら、オートボクシングか <code>Double</code>、<code>Float</code> の <code>valueOf</code> メソッドを使用してください。
@@ -2799,7 +2993,7 @@ Javaは、同一の文字列定数が同じ <code>String</code> オブジェク
<![CDATA[
<p>
文字列がプラットホームのデフォルトエンコーディングを使用して大文字、小文字に変換されています。
-国際文字で使われると不適切な変換になるかもしれません。
+国際文字で使われると不適切な変換になることがあります。
</p>
<ul>
<li>String.toUpperCase(Locale l)</li>
@@ -2831,7 +3025,7 @@ JLS セクション15.25を参照してください。
<![CDATA[
<p>
プリミティブ値がボクシングされて、すぐにアンボクシングされます。
-おそらくアンボクシングされた値が必要な場所で、手動でボクシングをしているためです。
+おそらくアンボクシングされた値が必要な場所で手動でボクシングをしているためです。
その結果、コンパイラにボクシングの機能を取り消すことを強制しています。
</p>
]]>
@@ -2868,7 +3062,7 @@ JLS セクション15.25を参照してください。
<Details>
<![CDATA[
<p>
-<code>toString</code> メソッドを呼び出すために、プリミティブ型のラッパクラスのインスタンスを作成しています。
+<code>toString</code> メソッドを呼び出すためにプリミティブ型のラッパクラスのインスタンスを作成しています。
それよりもプリミティブ値を引数にとる static な <code>toString</code> メソッドを使用したほうが効率的です。
</p>
<table>
@@ -2898,13 +3092,26 @@ static parseXXX メソッドを呼び出す方が効率的です。
</Details>
</BugPattern>
+ <BugPattern type="DM_BOXED_PRIMITIVE_FOR_COMPARE">
+ <ShortDescription>プリミティブが比較でボクシングされている</ShortDescription>
+ <LongDescription>プリミティブが {2} を呼び出すためにボクシングされています: 代わりに {3} を使用してください。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+ボクシングされたプリミティブが単に compareTo メソッドを呼び出すために作られています。
+直接プリミティブで働く static compare メソッド (double と float は Java 1.4から、他のプリミティブ型は Java 1.7から) を使うほうがより効率的です。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="DM_NEW_FOR_GETCLASS">
<ShortDescription>クラスオブジェクトを得るためだけにインスタンスを作成しているメソッド</ShortDescription>
<LongDescription>{1} は、クラスオブジェクトを得るためだけにインスタンスを作成しています。</LongDescription>
<Details>
<![CDATA[
<p>
-メソッドは、クラスオブジェクトを得るために、インスタンスを生成して <code>getClass</code> メソッドを呼び出しています。
+メソッドは、クラスオブジェクトを得るためにインスタンスを生成して <code>getClass</code> メソッドを呼び出しています。
クラスリテラル (<code>Foo.class</code>) を使うほうが簡単です。
</p>
]]>
@@ -2937,6 +3144,31 @@ static parseXXX メソッドを呼び出す方が効率的です。
</Details>
</BugPattern>
+ <BugPattern type="DM_INVALID_MIN_MAX">
+ <ShortDescription>Math.max と Math.min の間違った組み合わせ</ShortDescription>
+ <LongDescription>Math.max と Math.min の組み合わせが間違っています: このコードは常に {2} を返します。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+このコードは、<code>Math.min(0, Math.max(100, value))</code> のような構文を使用して境界値を制限しようとしています。
+しかしながら、定数の順序が間違っています。 <code>Math.min(100, Math.max(0, value))</code> とすべきです。
+結果としてこのコードは常に同じ結果 (もし値が NaN なら NaN) を作り出します。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="DM_INVALID_MIN_MAX">
+ <ShortDescription>Incorrect combination of Math.max and Math.min</ShortDescription>
+ <LongDescription>Incorrect combination of Math.max and Math.min: this code always returns {2}</LongDescription>
+ <Details>
+<![CDATA[
+ <p>This code tries to limit the value bounds using the construct like Math.min(0, Math.max(100, value)). However the order of
+ the constants is incorrect: it should be Math.min(100, Math.max(0, value)). As the result this code always produces the same result
+ (or NaN if the value is NaN).</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="DM_NEXTINT_VIA_NEXTDOUBLE">
<ShortDescription>整数の乱数を生成するためには nextDouble メソッド ではなく nextInt メソッドを使用する</ShortDescription>
<LongDescription>{1} は、整数の乱数を生成するために nextDouble メソッドを使用しています。nextInt メソッドを使用した方が効率的です。</LongDescription>
@@ -2954,13 +3186,13 @@ static parseXXX メソッドを呼び出す方が効率的です。
</BugPattern>
<BugPattern type="SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE">
- <ShortDescription>SQL の Statement の execute メソッドに定数でない文字列を渡している</ShortDescription>
- <LongDescription>{1} は、SQL の Statement の execute メソッドに定数でない文字列を渡しています。</LongDescription>
+ <ShortDescription>SQL の Statement の execute または addBatch メソッドに定数でない文字列を渡している</ShortDescription>
+ <LongDescription>{1} は、SQL の Statement の execute または addBatch メソッドに定数でない文字列を渡しています。</LongDescription>
<Details>
<![CDATA[
<p>
-このメソッドは、動的に生成されるように思われる文字列で、 SQL の <code>Statement</code> の <code>execute</code> メソッドを呼び出しています。
-その代わりに <code>PreparedStatement</code> を使うことを検討してください。
+このメソッドは、動的に生成されるように思われる文字列で、 SQL 文 の <code>execute</code> または <code>addBatch</code> メソッドを呼び出しています。
+その代わりに <code>PreparedStatement</code> を使用することを検討してください。
効率的で、SQL インジェクション攻撃に強いです。
</p>
]]>
@@ -2974,7 +3206,7 @@ static parseXXX メソッドを呼び出す方が効率的です。
<![CDATA[
<p>
このコードは、定数でない文字列から SQL の <code>PreparedStatement</code> を作成しています。
-ユーザからのチェックされていない汚染されたデータがこの文字列を作る際に使われるなら、PreparedStatement で予想外で望ましくない何かをするために SQL インジェクションが使われる可能性があります。
+ユーザからのチェックされていない汚染されたデータがこの文字列を作る際に使われるなら、<code>PreparedStatement</code> で予想外で望ましくない何かをするために SQL インジェクションが使われる可能性があります。
</p>
]]>
</Details>
@@ -3006,6 +3238,23 @@ static parseXXX メソッドを呼び出す方が効率的です。
</Details>
</BugPattern>
+ <BugPattern type="DC_PARTIALLY_CONSTRUCTED">
+ <ShortDescription>部分的に初期化されたオブジェクトを暴露する可能性がある</ShortDescription>
+ <LongDescription>部分的に初期化されたオブジェクトを暴露する可能性があります。{1}</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+ダブルチェックロッキングと共に遅延初期化フィールドを使用するメソッドのようです。
+フィールドが正しく volatile として宣言される間にオブジェクトの内部構造がフィールドに割り当てられた後で変更される可能性があります。
+したがって、他のスレッドが部分的に初期化されたオブジェクトを見るかもしれません。
+</p>
+<p>
+この問題を直すために、最初にローカル変数をオブジェクトに格納して、完全に構築した後で volatile フィールドを保存することを考えてください。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="FI_FINALIZER_NULLS_FIELDS">
<ShortDescription>ファイナライザはフィールドを null にする</ShortDescription>
<LongDescription>{3} は、finalize メソッドの中で null を設定しています。{1.class}</LongDescription>
@@ -3026,7 +3275,7 @@ static parseXXX メソッドを呼び出す方が効率的です。
<p>
このファイナライザは、フィールドを null にすること以外に何もしません。
これはまったく無意味であり、オブジェクトがガベージされ、ファイナライズされ、再びガベージされることを要求しています。
-<code>finalize</code> メソッドを削除するべきです。
+<code>finalize</code> メソッドを除去するべきです。
</p>
]]>
</Details>
@@ -3058,7 +3307,7 @@ static parseXXX メソッドを呼び出す方が効率的です。
<BugPattern type="FI_NULLIFY_SUPER">
<ShortDescription>ファイナライザはスーパークラスのファイナライザを無効にしている</ShortDescription>
- <LongDescription>{1} は、{2}.finalize() を無効にしています。これは、意図したことですか?</LongDescription>
+ <LongDescription>{1} は、{2}.finalize() を無効にしています。これは意図したことですか?</LongDescription>
<Details>
<![CDATA[
<p>
@@ -3110,7 +3359,7 @@ static parseXXX メソッドを呼び出す方が効率的です。
参照によってつながった複数のオブジェクトがファイナライズ可能になると、Java 仮想マシンはすべてのオブジェクトの <code>finalize</code> メソッドを呼び出します。
おそらく異なるスレッドで同時にです。
したがって、クラス <i>X</i> の <code>finalize</code> メソッドの中から <i>X</i> によって参照されているオブジェクトの <code>finalize</code> メソッドを呼び出すのは、とりわけ間違った考えです。
-なぜなら、オブジェクトがすでに別のスレッドによってファイナライズされているかもしれないからです。
+なぜなら、オブジェクトが既に別のスレッドによってファイナライズされているかもしれないからです。
</p>
]]>
</Details>
@@ -3135,7 +3384,7 @@ public boolean equals(Object o) {
}
</pre></blockquote>
<p>
-これは対称的で推移的である <code>equals</code> メソッドを実現するのはとても難しいので、間違ったプラクティスと見なされています。
+これは対称的で推移的である <code>equals</code> メソッドを実現するのはとても難しいので、バッドプラクティスと見なされています。
プロパティがなければまったく予想していない振る舞いが起こりえます。
</p>
]]>
@@ -3149,8 +3398,8 @@ public boolean equals(Object o) {
<![CDATA[
<p>
このクラスは列挙を定義していて、列挙の等価性はオブジェクト同一性を使用して定義されています。
-列挙値のために共変な <code>equals</code> メソッドを定義することは、非常に間違ったプラクティスです。
-2つの異なる列挙値が一般にの <code>equals</code> メソッドでは「等価ではない」と判定され、共変な <code>equals</code> メソッドでは「等価」と判定されるからです。
+列挙値のために共変な <code>equals</code> メソッドを定義することは、ひどいバッドプラクティスです。
+2つの異なる列挙値が <code>equals</code> メソッドでは「等価ではない」と判定され、共変な <code>equals</code> メソッドでは「等価」と判定されるからです。
共変な <code>equals</code> メソッドを定義しないでください。
</p>
]]>
@@ -3197,14 +3446,14 @@ public boolean equals(Object o) {
<BugPattern type="EQ_DOESNT_OVERRIDE_EQUALS">
<ShortDescription>スーパークラスの equals メソッドをオーバーライドしていないクラス</ShortDescription>
- <LongDescription>{0} は、{1.givenClass} をオーバーライドしていません。</LongDescription>
+ <LongDescription>{0} は、{2.givenClass} をオーバーライドしていません。</LongDescription>
<Details>
<![CDATA[
<p>
このクラスは、<code>equals</code> メソッドを定義しているクラスを拡張してフィールドを追加していますが、<code>equals</code> メソッドを定義していません。
したがって、このクラスのインスタンスの等価性は、サブクラスと追加されたフィールドの同一性を無視します。
これが意図したことで、しかも、<code>equals</code> メソッドをオーバーライドする必要がないことを確実にしてください。
-たとえ <code>equals</code> メソッドをオーバーライドする必要がないとしても、サブクラスのための <code>equals</code> メソッドが <code>super.equals(o)</code> を呼び出して結果を返すという事実を実証するために、いずれにしろ、<code>equals</code> メソッドをオーバーライドすることを検討してください。
+たとえ <code>equals</code> メソッドをオーバーライドする必要がないとしても、サブクラスのための <code>equals</code> メソッドが <code>super.equals(o)</code> を呼び出して結果を返すという事実を実証するためにいずれにしろ、<code>equals</code> メソッドをオーバーライドすることを検討してください。
</p>
]]>
</Details>
@@ -3259,7 +3508,7 @@ public boolean equals(Object o) {
<Details>
<![CDATA[
<p>
-このクラスの <code>equals</code> メソッドは、引数の型が <code>this</code> オブジェクトの型と互換性があるこをチェックするために、我々が認識しているパターンで何もしていません。
+このクラスの <code>equals</code> メソッドは、引数の型が <code>this</code> オブジェクトの型と互換性があるこをチェックするために我々が認識しているパターンで何もしていません。
このコードは何も間違っていないかもしれませんが、レビューする価値があります。
</p>
]]>
@@ -3300,7 +3549,7 @@ public boolean equals(Object o) {
<![CDATA[
<p>
このクラスでは、常に false を返す <code>equlas</code> メソッドを定義しています。
-これは、オブジェクトがそれ自身と等価ではないことを意味していて、このクラスの有効な Map や Set を作成できません。
+これはオブジェクトがそれ自身と等価ではないことを意味していて、このクラスの有用な Map や Set を作成できません。
より根本的に、<code>equals</code> メソッドの要件の一つである反射性を満たしていないことになります。
</p>
<p>
@@ -3367,7 +3616,7 @@ JDK はこのバグを解決してサイズを1MB減らすことができまし
<![CDATA[
<p>
このコードは、<code>compareTo</code> または <code>compare</code> メソッドの戻り値を無効にしています。
-これは疑わしいか間違ったプログラミングプラクティスです。戻り値が Integer.MIN_VALUE なので、戻り値を無効にすることは結果の符号を無効にしません。
+これは疑わしいかバッドプログラミングプラクティスです。戻り値が Integer.MIN_VALUE なので、戻り値を無効にすることは結果の符号を無効にしません。
結果を無効にするのではなくオペランドの順序を逆にすることによって、同じ意図した結果を得ることができます。
</p>
]]>
@@ -3380,15 +3629,29 @@ JDK はこのバグを解決してサイズを1MB減らすことができまし
<Details>
<![CDATA[
<p>
-いくつかの状況下では、この <code>compareTo</code> または <code>compare</code> メソッドは Integer.MIN_VALUE を返します。それは、非常に間違ったプラクティスです。
+いくつかの状況下では、この <code>compareTo</code> または <code>compare</code> メソッドは Integer.MIN_VALUE を返します。ひどいバッドプラクティスです。
<code>compareTo</code> メソッドの戻り値で重要なことは結果の符号だけです。
しかし、結果の符号を無効にすることを期待して、<code>compareTo</code> メソッドの戻り値を無効にすることがあります。
-戻り値が Integer.MIN_VALUE である場合を除き、Integer.MIN_VALUE よりも-1を返します。
+返された値が Integer.MIN_VALUE の場合を除いてです。 Integer.MIN_VALUE よりも-1を返してください。
</p>
]]>
</Details>
</BugPattern>
-
+
+ <BugPattern type="CO_COMPARETO_INCORRECT_FLOATING">
+ <ShortDescription>compareTo()/compare() は間違って float または double 値を処理する</ShortDescription>
+ <LongDescription>{1} は、間違って {2} 値を処理します。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+このメソッドはこのようなパターンを使用して double または float 値を比較しています : val1 > val2 ? 1 : val1 < val2 ? -1 : 0。
+このパターンは 正しくないソート結果や壊れたコレクションの原因になるかもしれない -0.0 や NaN 値のために間違って働きます (もし比較された値がキーとして使われるなら)。
+すべての特殊なケースを正確に処理するために Double.compare または Float.compare メソッドの使用を検討してください。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="CO_SELF_NO_OBJECT">
<ShortDescription>共変な compareTo メソッドの定義</ShortDescription>
<LongDescription>{0} は、compareTo(Object) ではなく compareTo({0.givenClass}) メソッドを定義しています。</LongDescription>
@@ -3460,7 +3723,7 @@ public int hashCode() {
<![CDATA[
<p>
このクラスは、<code>compareTo(...)</code> メソッドを定義していますが、<code>equals</code> メソッドは <code>java.lang.Object</code> から継承しています。
-一般に、<code>equals</code> メソッドが true を返す場合に限り、<code>compareTo</code> メソッドは0を返すべきです。
+一般的に<code>equals</code> メソッドが true を返す場合に限り、<code>compareTo</code> メソッドは0を返すべきです。
これが違反されるなら奇妙で予測できない失敗が PriorityQueue などのクラスで発生します。
J2SE 5.0では、<code>PriorityQueue.remove()</code> は <code>compareTo</code> メソッドを使用しますが、Java SE 6では、<code>equals</code> メソッドを使用します。
</p>
@@ -3469,9 +3732,9 @@ Comparable インタフェースの compareTo メソッドの JavaDoc を以下
</p>
<blockquote><p>
必須というわけではありませんが、<code>(x.compareTo(y)==0) == (x.equals(y))</code> であることが強く推奨されます。
-一般に、<code>Comparable</code> インタフェースを実装しているクラスで、この条件に違反するクラスは明確にこの事実を示す必要があります。
+一般的に<code>Comparable</code> インタフェースを実装しているクラスで、この条件に違反するクラスは明確にこの事実を示す必要があります。
「注:このクラスは <code>equals</code> と一貫性のない自然順序付けを持ちます」などと明示することをお勧めします。
-</p></blockquote>
+</blockquote></p>
]]>
</Details>
</BugPattern>
@@ -3559,7 +3822,7 @@ public int hashCode() {
<p>
このコードは、参照等価性のために == や != を使用して <code>java.lang.String</code> オブジェクトを比較しています。
両方の文字列がソースファイルの定数か、<code>String.intern()</code> を使用して正準化されていないかぎり、同じ文字列は2つの異なる String オブジェクトによって表されるかもしれません。
-その代わりに <code>equals(Object)</code> メソッドを使うことを検討してください。
+その代わりに <code>equals(Object)</code> メソッドを使用することを検討してください。
</p>
]]>
</Details>
@@ -3573,7 +3836,7 @@ public int hashCode() {
<p>
このコードは、参照等価性のために == や != を使用して <code>java.lang.String</code> パラメータを比較しています。
文字列定数または正準化された文字列だけをメソッドに渡すことを呼び出し元に要求することは必要以上に脆弱で測定可能な性能の向上をもたらしません。
-その代わりに <code>equals(Object)</code> メソッドを使うことを検討してください。
+その代わりに <code>equals(Object)</code> メソッドを使用することを検討してください。
</p>
]]>
</Details>
@@ -3612,8 +3875,8 @@ public int hashCode() {
<![CDATA[
<p>
Web サーバは、一般的にサーブレットや JSP クラスのインスタンスを1つだけ作成します (すなわち、シングルトンとして扱います)。
-複数のスレッドが複数同時に発生するリクエストを処理するためにインスタンスのメソッドを呼び出します。
-したがって、可変インスタンスフィールドは一般に競合状態を作成します。
+複数のスレッドが複数同時のリクエストに応えるためにそのインスタンスでメソッドを呼び出します。
+したがって、一般に可変インスタンスフィールドは競合状態を作ります。
</p>
]]>
</Details>
@@ -3642,7 +3905,7 @@ Web サーバは、一般的にサーブレットや JSP クラスのインス
</p>
<p>
不正確ないろいろな原因がこのディテクタにあることに注意してください。
-たとえば、ディテクタはロックを保持されるすべての状況を静的に検出できるというわけではありません。
+たとえば、ディテクタはロックを保持されるすべての状況を静的に検出できるわけではありません。
また、ディテクタがロックされたアクセスとアンロックされたアクセスの区別が正確なときでも、問題のコードは依然として正しいかもしれません。
</p>
]]>
@@ -3656,8 +3919,8 @@ Web サーバは、一般的にサーブレットや JSP クラスのインス
<![CDATA[
<p>
<code>notify</code> メソッドまたは <code>notifyAll</code> メソッドへの呼び出しは可変オブジェクト状態にどんな (明らかな) 付随的な変更ももたらされませんでした。
-一般に、別のスレッドが期待しているいくつかの条件が真になったので、モニタで <code>notify</code> メソッドが呼び出されます。
-しかしながら、意味がある条件のために、両方のスレッドに見えるヒープオブジェクトを含まなければなりません。
+一般的に別のスレッドが期待しているいくつかの条件が真になったので、モニタで <code>notify</code> メソッドが呼び出されます。
+しかしながら、意味がある条件のために両方のスレッドに見えるヒープオブジェクトを含まなければなりません。
</p>
<p>
可変オブジェクトの状態変更が通知があるメソッドを呼び出したメソッドで起こったかもしれないので、このバグが必ずしもエラーを示すというわけではありません。
@@ -3728,7 +3991,7 @@ public static メソッドは、クラスの 静的な状態の一部である
<![CDATA[
<p>
このメソッドは、スレッドで 明示的に <code>run</code> メソッドを呼び出しています。
-一般に、クラスは新しいスレッドで自己の <code>run</code> メソッドを呼び出してもらうために <code>Runnable</code> インタフェースを実装します。
+一般的にクラスは新しいスレッドで自己の <code>run</code> メソッドを呼び出してもらうために <code>Runnable</code> インタフェースを実装します。
その場合は、<code>Thread.start()</code> を呼び出すのが正しいです。
</p>
]]>
@@ -3756,7 +4019,7 @@ public static メソッドは、クラスの 静的な状態の一部である
<p>
このコードは、短絡論理 (&& や ||) ではなく非短絡論理 (& や |) を使用していると思われます。
さらに、左辺値によって右辺を評価したくない (例外のスローや演算が高くつく副作用があるため) と思っているのかもしれません。
-非短絡論理は、左辺の結果がわかっていて推論できるときでも、両側の式が評価されます。
+非短絡論理は、左辺を知ることによって結果を推論できたとしても両側の式が評価されます。
これは効率が悪く、右辺の評価でエラーが発生するケースを左辺でガードしているなら、結果としてエラーになる可能性があります。
</p>
<p>
@@ -3772,7 +4035,7 @@ public static メソッドは、クラスの 静的な状態の一部である
<![CDATA[
<p>
このコードは、短絡論理 (&& や ||) ではなく非短絡論理 (& や |) を使用していると思われます。
-非短絡論理は、左辺の結果がわかっていて推論できるときでも、両側の式が評価されます。
+非短絡論理は、左辺を知ることによって結果を推論できたとしても両側の式が評価されます。
これは効率が悪く、右辺の評価でエラーが発生するケースを左辺でガードしているなら、結果としてエラーになる可能性があります。
</p>
<p>
@@ -3788,7 +4051,7 @@ public static メソッドは、クラスの 静的な状態の一部である
<Details>
<![CDATA[
<p>
-2つ以上のロックを保持して、モニタで待機させるとデッドロックの原因になる場合があります。
+2つ以上のロックを保持して、モニタで待機させるとデッドロックを引き起こすことがあります。
<code>wait</code> メソッドを呼び出すと、待機しているオブジェクトのロックを解除するだけで、その他のロックは解除しません。
これは必ずしもバグではありませんが厳密に調べる価値があります。
</p>
@@ -3820,7 +4083,7 @@ public static メソッドは、クラスの 静的な状態の一部である
<![CDATA[
<p>
このメソッドには条件制御フローによってガードされない <code>java.lang.Object.wait()</code> の呼び出しがあります。
-このコードは、<code>wait</code> メソッドを呼び出す前に待機するつもりだった条件がすでに満たされていないことを確かめるべきです。
+このコードは、<code>wait</code> メソッドを呼び出す前に待機するつもりだった条件が既に満たされていないことを確かめるべきです。
どんな前の通知も無視されます。
</p>
]]>
@@ -3834,7 +4097,7 @@ public static メソッドは、クラスの 静的な状態の一部である
<![CDATA[
<p>
このコンストラクタは、まだ値が代入されていないフィールドを読み出しています。
-多くの場合、プログラマがコンストラクタのパラメータの代わりに誤ってフィールドを使用するときに起きます。
+多くの場合、プログラマがコンストラクタのパラメータの代わりに誤ってフィールドを使うときに起きます。
</p>
]]>
</Details>
@@ -3889,7 +4152,7 @@ class B extends A {
<![CDATA[
<p>
このクラスには類似した名前の get メソッドと set メソッドがあり、set メソッドは同期化していて、get メソッドは同期化していません。
-get メソッドの呼び出し元がオブジェクトの一貫した状態を必ずしも見るというわけではないので、実行時に間違った振る舞いになるかもしれません。
+get メソッドの呼び出し元がオブジェクトの一貫した状態を必ずしも見るというわけではないので、実行時に間違った振る舞いの原因になることがあります。
get メソッドは同期化するべきです。
</p>
]]>
@@ -3903,7 +4166,7 @@ get メソッドは同期化するべきです。
<![CDATA[
<p>
バグインスタンスによって参照される2つのクラスのスタティックイニシャライザで循環が検出されました。
-多くの種類の予想外の振る舞いは、そのような循環に起因するかもしれません。
+さまざまな予想外の振る舞いはそのような循環に起因することがあります。
</p>
]]>
</Details>
@@ -4018,7 +4281,7 @@ synchronized(fileLock) {
private static final Object fileLock = new Object();
</pre></blockquote>
<p>
-既存のコードとしては間違っていないのかもしれませんが、紛らわしいので将来リファクタリングするべきかもしれません。
+既存のコードとしては間違っていないかもしれないが、紛らわしいので将来リファクタリングするべきかもしれません。
たとえば、IntelliJ の "Remove Boxing" のようなリファクタリングは Java 仮想マシンを通して共有される正準化された <code>Integer</code> オブジェクトを使用するように置き換えてしまい、非常に紛らわしい振る舞いと潜在的デッドロックの原因になります。
</p>
]]>
@@ -4041,7 +4304,7 @@ synchronized(count) {
}
</pre></blockquote>
<p>
-<code>Integer</code> オブジェクトはキャッシュして共有される可能性があります。
+<code>Integer</code> オブジェクトはキャッシュして共有できます。
他の無関係なコードと同じオブジェクトで同期化している可能性があるので、無応答やデッドロックの原因になります。
</p>
<p>
@@ -4078,7 +4341,7 @@ synchronized() {
<![CDATA[
<p>
このクラスのフィールドは、同期化に関して一貫性のないアクセスをしているように見えます。
-このバグレポートは、バグパターンディテクタが以下のように判断したことをを示します。
+このバグレポートは、バグパターンディテクタが以下のように判断したことを示します。
</p>
<ul>
<li>クラスにはロックされたアクセスとアンロックされたアクセスが混在していて</li>
@@ -4090,8 +4353,8 @@ synchronized() {
</p>
<p>
不正確のいろいろなソースがこのディテクタにあることに注意してください。
-たとえば、ディテクタはロックを保持されるすべての状況を静的に検出できるというわけではありません。
-また、ディテクタがロックされたアクセスとアンロックされたアクセスの区別が正確なときでも、問題のコードは依然として正しいかもしれません。
+たとえば、ディテクタはロックを保持されるすべての状況を静的に検出できるわけではありません。
+また、ディテクタがロックされたアクセスとアンロックされたアクセスの区別が正確なときでも、問題のコードはまだ正しいかもしれません。
</p>
]]>
</Details>
@@ -4104,7 +4367,7 @@ synchronized() {
<![CDATA[
<p>
このメソッドは、フィールドの同時更新に対して同期化でガードしようとしています。しかし、フィールドをガードするとフィールドではなく、フィールドが参照するオブジェクトのロックを獲得します。
-これはあなたが必要とする相互排除を提供しないかもしれません。
+これはあなたが必要とする相互排除ができないかもしれません。
他のスレッドは (他の目的のための) 参照されたオブジェクトのロックを獲得するかもしれません。<br>
このパターンの例は以下のようになります。
</p>
@@ -4130,7 +4393,7 @@ private Long getNotificationSequenceNumber() {
<![CDATA[
<p>
このメソッドは、可変フィールドから参照されたオブジェクトで同期化しています。
-異なるスレッドが異なるオブジェクトで同期化しているかもしれないので、これは有効な意味を持っている可能性が低いです。
+異なるスレッドが異なるオブジェクトで同期化しているかもしれないので、有用な意味を持っている可能性が低いです。
</p>
]]>
</Details>
@@ -4142,9 +4405,9 @@ private Long getNotificationSequenceNumber() {
<Details>
<![CDATA[
<p>
-インタフェースに定義された final static フィールドが、配列や Hashtable などの可変オブジェクトを参照しています。
-この可変オブジェクトは、悪質なコードや偶然別のパッケージによって変更される可能性があります。
-これを解決するために、フィールドはクラスへ移動する必要があり、脆弱性を回避するためにパッケージプロテクテッドにします。
+インタフェースに定義された final static フィールドが配列や Hashtable などの可変オブジェクトを参照しています。
+この可変オブジェクトは悪意のあるコードや偶然別のパッケージによって変更できます。
+これを解決するためにフィールドはクラスへ移動する必要があり、脆弱性を回避するためにパッケージプロテクテッドにします。
</p>
]]>
</Details>
@@ -4156,7 +4419,7 @@ private Long getNotificationSequenceNumber() {
<Details>
<![CDATA[
<p>
-この可変 static フィールドは、悪質なコードや偶然別のパッケージによって変更される可能性があります。
+この可変 static フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。
フィールドは、脆弱性を回避するために final および/またはパッケージプロテクテッドにします。
</p>
]]>
@@ -4169,21 +4432,21 @@ private Long getNotificationSequenceNumber() {
<Details>
<![CDATA[
<p>
-final でない public static フィールドは、悪質なコードや偶然別のパッケージによって変更される可能性があります。
+final でない public static フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。
フィールドは、脆弱性を回避するために final にします。
しかしながら、スタティックイニシャライザには複数のフィールドへの書き込みがあるので、何らかのリファクタリングを必要とするでしょう。
</p>
]]>
</Details>
</BugPattern>
-
+
<BugPattern type="MS_SHOULD_BE_FINAL">
<ShortDescription>final にすべきフィールド</ShortDescription>
- <LongDescription>{1} は、final ではありませんが、final にすべきです。</LongDescription>
+ <LongDescription>{1} は、final ではありませんが final にすべきです。</LongDescription>
<Details>
<![CDATA[
<p>
-final でない public static フィールドは、悪質なコードや偶然別のパッケージによって変更される可能性があります。
+final でない public static フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。
フィールドは、脆弱性を回避するために final にします。
</p>
]]>
@@ -4196,7 +4459,7 @@ final でない public static フィールドは、悪質なコードや偶然
<Details>
<![CDATA[
<p>
-この可変 static フィールドは、悪質なコードや偶然別のパッケージによって変更される可能性があります。
+この可変 static フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。
フィールドは、脆弱性を回避するためにパッケージプロテクテッドにします。
</p>
]]>
@@ -4209,20 +4472,49 @@ final でない public static フィールドは、悪質なコードや偶然
<Details>
<![CDATA[
<p>
-この final static フィールドは、Hashtable を参照しているので、悪質なコードや偶然別のパッケージによってアクセスされる可能性があります。
+この final static フィールドは Hashtable を参照しているので、悪意のあるコードや偶然別のパッケージによってアクセスできます。
このコードは、Hashtable のコンテンツを自由に変更できます。
</p>
]]>
</Details>
</BugPattern>
+ <BugPattern type="MS_MUTABLE_COLLECTION">
+ <ShortDescription>可変コレクションのフィールド</ShortDescription>
+ <LongDescription>{1} は可変コレクションです。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+可変コレクションのインスタンスが final static フィールドに割り当てられています。
+したがって、 悪意のあるコードや偶然別のパッケージによって変更できます。
+脆弱性を避けるために Collections.unmodifiableSet/List/Map などでこのフィールドをラップすることを検討してください。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="MS_MUTABLE_COLLECTION_PKGPROTECT">
+ <ShortDescription>パッケージプロテクテッドにすべき可変コレクションのフィールド</ShortDescription>
+ <LongDescription>{1} は、パッケージプロテクテッドにすべき可変コレクションです。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+可変コレクションのインスタンスが final static フィールドに割り当てられています。
+したがって、悪意のあるコードや偶然別のパッケージによって変更できます。
+フィールドは脆弱性を避けるためにパッケージプロテクテッドにできます。
+代わりに Collections.unmodifiableSet/List/Map などでこのフィールドをラップしても脆弱性を避けることができます。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="MS_MUTABLE_ARRAY">
<ShortDescription>可変配列のフィールド</ShortDescription>
<LongDescription>{1} は、可変配列です。</LongDescription>
<Details>
<![CDATA[
<p>
-この final static フィールドは、配列を参照しているので、悪質なコードや偶然別のパッケージによってアクセスされる可能性があります。
+この final static フィールドは配列を参照しているので、悪意のあるコードや偶然別のパッケージによってアクセスできます。
このコードは、配列のコンテンツを自由に変更できます。
</p>
]]>
@@ -4230,18 +4522,48 @@ final でない public static フィールドは、悪質なコードや偶然
</BugPattern>
<BugPattern type="MS_CANNOT_BE_FINAL">
- <ShortDescription>final でないフィールドは悪質なコードから保護できない</ShortDescription>
- <LongDescription>{1} は、final でないので、悪質なコードから保護できません。 </LongDescription>
+ <ShortDescription>final でないフィールドは悪意のあるコードから保護できない</ShortDescription>
+ <LongDescription>{1} は、final でないので、悪意のあるコードから保護できません。 </LongDescription>
<Details>
<![CDATA[
<p>
-この可変 static フィールドは、悪質なコードや偶然別のパッケージによって変更される可能性があります。
+この可変 static フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。
残念ながらこのような使い方は簡単に解決できません。
</p>
]]>
</Details>
</BugPattern>
+ <BugPattern type="ME_MUTABLE_ENUM_FIELD">
+ <ShortDescription>列挙型フィールドは public で可変である</ShortDescription>
+ <LongDescription>{1} フィールドは public で可変です。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+可変 public フィールドが public 列挙型の中に定義されています。
+したがって、フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。
+可変列挙型フィールドが遅延初期化で使用されるかもしれないとしても外界へ暴露するバッドプラクティスです。
+このメソッドを final およびパッケージプライベートとして宣言することを考えてください。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="ME_ENUM_FIELD_SETTER">
+ <ShortDescription>public 列挙型メソッドが無条件にフィールドを設定するPublic enum method unconditionally sets its field</ShortDescription>
+ <LongDescription>{1} は無条件にフィールド {2.name} を設定しています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+無条件に列挙型フィールドを設定している public 列挙型で public メソッドを宣言しています。
+したがって、フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。
+可変列挙型フィールドが遅延初期化で使用されるかもしれないとしても外界へ暴露するバッドプラクティスです。
+このメソッドを除去するかパッケージプライベートとして宣言することを考えてください。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD">
<ShortDescription>潜在的な継承されたメソッドなのか外部のメソッドなのかあいまいなメソッドの呼び出し</ShortDescription>
<LongDescription>潜在的な継承されたメソッドなのか外部のメソッドなのかあいまいなメソッド {2} を呼び出しています。{1}</LongDescription>
@@ -4250,7 +4572,7 @@ final でない public static フィールドは、悪質なコードや偶然
<p>
内部クラスは、継承されたメソッドか外部クラスで定義されたメソッドなのかどちらとも解釈できるメソッドを呼び出しています。
たとえば、<code>foo(17)</code> を呼び出します。それはスーパークラスと外部のメソッドの両方で定義されています。
-Java のセマンティックスでは、継承したメソッドを呼び出しますが、これは意図したことではないかもしれません。
+Java のセマンティックスでは、継承したメソッドを呼び出しますが、これはあなたが意図したことではないかもしれません。
</p>
<p>
本当に継承されたメソッドを呼び出すつもりなら super を付けて (例:super.foo(17)) 呼び出してください。
@@ -4272,7 +4594,7 @@ Java のセマンティックスでは、継承したメソッドを呼び出し
<![CDATA[
<p>
このクラスは、スーパークラスが異なるパッケージであるということを除いて、スーパークラスと同一の単純名をです (たとえば、<code>alpha.Foo</code> が <code>beta.Foo</code> を拡張します)。
-これは非常に紛らわしく、参照関係を解決するために import 文を見なければならなかったり、スーパークラスに存在するメソッドを誤ってオーバーライドしてしまったりする状況を作り出します。
+これは非常に紛らわしく、参照関係を解決するために import 文を見なければならなかったり、スーパークラスのメソッドをオーバーライドしないで誤ってメソッドを定義する状況を作り出します。
</p>
]]>
</Details>
@@ -4284,8 +4606,8 @@ Java のセマンティックスでは、継承したメソッドを呼び出し
<Details>
<![CDATA[
<p>
-このクラスまたはインタフェースは、、インタフェースが異なるパッケージであるということを除いて実装された/拡張されたインタフェースと同一の単純名です (たとえば、<code>alpha.Foo</code> が <code>beta.Foo</code> を継承しているような状況です)。
-これは非常に紛らわしく、参照関係を解決するために import 文を見なければならなかったり、スーパークラスに存在するメソッドを誤ってオーバーライドしてしまったりする状況を作り出します。
+このクラスまたはインタフェースは、インタフェースが異なるパッケージであるということを除いて実装された/拡張されたインタフェースと同一の単純名です (たとえば、<code>alpha.Foo</code> が <code>beta.Foo</code> を継承しているような状況です)。
+これは非常に紛らわしく、参照関係を解決するために import 文を見なければならなかったり、スーパークラスのメソッドをオーバーライドしないで誤ってメソッドを定義する状況を作り出します。
</p>
]]>
</Details>
@@ -4351,14 +4673,14 @@ final でないフィールドの名前は、最初の文字は小文字にし
参照されたメソッドは、大文字の使い方だけによって異なる名前があります。
大文字の使い方が同一ならメソッドの1つが他のメソッドをオーバーライドするので、非常に紛らわしいです。
他のメソッドの存在から、これらのメソッドの両方の存在が意図的で、確実に混乱させていると思われます。
-APIの凍結によって両方とも持たざるを得ない場合を除き、それらのうちの1つを削除しようと努力するべきです。
+APIの凍結によって両方とも持たざるを得ない場合を除き、それらのうちの1つを除去しようと努力するべきです。
</p>
]]>
</Details>
</BugPattern>
<BugPattern type="NM_WRONG_PACKAGE">
- <ShortDescription>パラメータの間違ったパッケージのために、スーパークラスのメソッドをオーバーライドしていないメソッド</ShortDescription>
+ <ShortDescription>パラメータの間違ったパッケージのためにスーパークラスのメソッドをオーバーライドしていないメソッド</ShortDescription>
<LongDescription>パラメータの型 {4} がスーパークラスのパラメータの型 {5} と合致していないので、{1} はスーパークラスのメソッドをオーバーライドしていません。</LongDescription>
<Details>
<![CDATA[
@@ -4442,12 +4764,12 @@ public class B extends A {
<p>
この正規のメソッドは定義しているクラスと同じ名前です。
これはコンストラクタを意図していた可能性が高いです。もしそうなら void 戻り値の宣言を除去してください。
-このメソッドを定義したことが偶然間違っているとわかり、正しいコンストラクタを定義したが、下位互換性のためにこのメソッドを取り除くことができないなら、メソッドを非推奨にしてください。
+偶然メソッドを定義したことが間違いだとわかり、適切なコンストラクタを定義したが、後方互換性のためにこのメソッドを除去できないならメソッドを非推奨にしてください。
</p>
]]>
</Details>
</BugPattern>
-
+
<BugPattern type="NM_LCASE_HASHCODE">
<ShortDescription>クラスは hashcode() を定義しています。hashCode() にすべきですか?</ShortDescription>
<LongDescription>クラス {0} は、hashcode() を定義しています。hashCode() にすべきですか?</LongDescription>
@@ -4460,7 +4782,7 @@ public class B extends A {
]]>
</Details>
</BugPattern>
-
+
<BugPattern type="NM_LCASE_TOSTRING">
<ShortDescription>クラスは tostring() を定義しています。toString() にすべきですか?</ShortDescription>
<LongDescription>クラス {0} は、tostring() を定義しています。toString() にすべきですか?</LongDescription>
@@ -4494,7 +4816,7 @@ public class B extends A {
<![CDATA[
<p>
このクラスは、例外クラスから派生されていないのにクラス名が「Exception」で終わっています。
-これは、このクラスのユーザに紛らわしいです。
+これはこのクラスのユーザに紛らわしいです。
</p>
]]>
</Details>
@@ -4574,7 +4896,7 @@ public class B extends A {
<![CDATA[
<p>
フィールドは、transient と宣言していますが、クラスは直列化可能ではないので、まったく効果がありません。
-クラスが transient だったときの名残かもしれません、あるいは直列化機構を誤解しているのかもしれません。
+クラスが transient だったときの名残かもしれません、または直列化機構を誤解しているのかもしれません。
</p>
]]>
</Details>
@@ -4586,7 +4908,7 @@ public class B extends A {
<Details>
<![CDATA[
<p>
-このクラスには複数の場所で更新されるフィールドがあります。したがって、このクラスの状態の一部であると思われます。
+このクラスには複数の場所で更新されるフィールドがあります。したがって、このクラスの状態の一部だと思われます。
しかしながら、フィールドは transient と宣言しているので、 readObject/readResolve で値が設定されません。
クラスの直列化復元されたインスタンスにはデフォルト値が設定されます。
</p>
@@ -4644,8 +4966,8 @@ public class B extends A {
このクラスは <code>Serializable</code> インタフェースを実装していますが、<code>serialVersionUID</code> フィールドを定義していません。
.class オブジェクトへの参照を追加するのと同じくらい簡単な変更でクラスに合成フィールドを追加します。
それは、残念ながら暗黙の <code>serialVersionUID</code> を変えます (たとえば、<code>String.class</code> への参照を追加すると、<code>class$java$lang$String</code> という static フィールドを生成します)。
-また、バイトコードコンパイラへの異なるソースコードは、クラスオブジェクトまたは内部クラスに参照のために生成される合成変数のために異なる命名規則を使用するかもしれません。
-バージョンを横断する Serializable の相互運用性を保証するために、明示的に、serialVersionUID を追加することを検討してください。
+また、バイトコードコンパイラへの異なるソースコードは、クラスオブジェクトまたは内部クラスを参照するために生成される合成変数のために異なる命名規則を使用するかもしれません。
+バージョンを横断する Serializable の相互運用性を保証するために明示的に serialVersionUID を追加することを検討してください。
</p>
]]>
</Details>
@@ -4673,7 +4995,7 @@ public class B extends A {
<![CDATA[
<p>
このメソッドには1つの case が次の case へと通り抜ける switch 文があります。
-通常、break か return でこの case を終わらせる必要があります。
+通常は、break か return でこの case を終わらせる必要があります。
</p>
]]>
</Details>
@@ -4686,10 +5008,10 @@ public class B extends A {
<![CDATA[
<p>
このメソッドにはdefault がない switch 文があります。
-通常、default を用意する必要があります。
+通常は、default を用意する必要があります。
</p>
<p>
-解析は生成されたバイトコードを見るだけなので、default が switch 文の終わりにあって、break 文で終わらないならば、誤警告のトリガーとなります。
+解析は生成されたバイトコードを見るだけなので、default が switch 文の終わりにあって、他のケースに break 文が含まれていないなら誤検出のトリガーとなります。
</p>
]]>
</Details>
@@ -4710,7 +5032,7 @@ public class B extends A {
<BugPattern type="SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH_TO_THROW">
<ShortDescription>スローする switch 文のフォールスルーのために格納が無効になっている</ShortDescription>
- <LongDescription>前の case からの値 {2.givenClass} が、スローする switch 文のフォールスルーのためにここで失われています。</LongDescription>
+ <LongDescription>前の case からの値 {2.givenClass} がスローする switch 文のフォールスルーのためにここで失われています。</LongDescription>
<Details>
<![CDATA[
<p>
@@ -4828,7 +5150,7 @@ public class B extends A {
<![CDATA[
<p>
この直列化可能なクラスは内部クラスです。内部クラスを直列化しようとすると関連した外部クラスのインスタンスも直列化します。
-外部クラスのインスタンスは直列化可能なので失敗しませんが、意図したことよりもっとずっと多くのデータを直列化するかもしれません。
+外部クラスのインスタンスは直列化可能なので失敗しません。しかし、意図していたよりももっと多くのデータを直列化するかもしれません。
できれば、内部クラスを static にして問題を解決するべきです。
</p>
]]>
@@ -4854,7 +5176,7 @@ public class B extends A {
<![CDATA[
<p>
コンストラクタがスレッドを開始しています。クラスが拡張され、サブクラスが作られるなら間違っていそうです。
-なぜなら、サブクラスのコンストラクタでスレッドが開始される前に、スーパークラスのスレッドが開始してしまうためです。
+なぜなら、サブクラスのコンストラクタでスレッドが開始される前にスーパークラスのスレッドが開始されてしまうためです。
</p>
]]>
</Details>
@@ -4945,7 +5267,7 @@ static フィールドにすることを検討してください。
<![CDATA[
<p>
このフィールドに定数値 null を書き込みます。したがって、フィールドの読み出しは null を返します。
-誤りをチェックしてください。使わないなら除去してください。
+誤りをチェックしてください。役に立たないなら除去してください。
</p>
]]>
</Details>
@@ -4958,7 +5280,7 @@ static フィールドにすることを検討してください。
<![CDATA[
<p>
この public または protected フィールドは書き込まれていません。このフィールドからの読み出しはデフォルト値を返します。
-誤りをチェックしてください (フィールドは初期化するべきでしたか?)。使わないなら除去してください。
+誤りをチェックしてください (フィールドは初期化するべきでしたか?)。役に立たないなら除去してください。
</p>
]]>
</Details>
@@ -4971,7 +5293,7 @@ static フィールドにすることを検討してください。
<![CDATA[
<p>
このフィールドは決して書き込まれません。このフィールドからの読み出しはデフォルト値を返します。
-誤りをチェックしてください (フィールドは初期化するべきでしたか?)。使わないなら除去してください。
+誤りをチェックしてください (フィールドは初期化するべきでしたか?)。役に立たないなら除去してください。
</p>
]]>
</Details>
@@ -4984,7 +5306,7 @@ static フィールドにすることを検討してください。
<![CDATA[
<p>
このインスタンスメソッドは、static フィールドに書き込みをしています。
-複数のインスタンスが操作されているなら、正しくさせるのは難しいです。一般的に間違ったプラクティスです。
+複数のインスタンスが操作されているなら、正しくさせるのは難しいです。一般的にバッドプラクティスです。
</p>
]]>
</Details>
@@ -4997,7 +5319,7 @@ static フィールドにすることを検討してください。
<![CDATA[
<p>
ここで参照されている変数は、以前に null なのかチェックしているため null であることがわかっています。
-これは有効かもしれないが、間違いかもしれません (多分異なる変数を参照することを意図してました、あるいは以前の null チェックで null でないのか確かめるべきでした)。
+これは有効ですが、間違いかもしれません (多分異なる変数を参照することを意図してました、または以前の null チェックで null でないのか確かめるべきでした)。
</p>
]]>
</Details>
@@ -5077,7 +5399,7 @@ static フィールドにすることを検討してください。
<![CDATA[
<p>
このクラスは内部クラスなのにそれを作成したオブジェクトへの埋め込まれた参照を使用していません。
-この参照はより大きなクラスのインスタンスを作成して、必要以上に長い間作成オブジェクトへの参照を存続しておくかもしれません。
+この参照はより大きなクラスのインスタンスを作成して、必要以上に作成オブジェクトへの参照を存続しておくことがあります。
できれば、クラスは static にすべきです。
</p>
]]>
@@ -5105,7 +5427,7 @@ static フィールドにすることを検討してください。
<![CDATA[
<p>
このクラスは内部クラスなのにそれを作成したオブジェクトへの埋め込まれた参照を使用していません。
-この参照はより大きなクラスのインスタンスを作成して、必要以上に長く作成オブジェクトへの参照を存続しておくかもしれません。
+この参照はより大きなクラスのインスタンスを作成して、必要以上に作成オブジェクトへの参照を存続しておくことがあります。
できれば、クラスは static 内部クラスにすべきです。
無名内部クラスは static にできないので、名前付き内部クラスにリファクタリングする必要があります。
</p>
@@ -5168,6 +5490,139 @@ static フィールドにすることを検討してください。
</Details>
</BugPattern>
+ <BugPattern type="UC_USELESS_VOID_METHOD">
+ <ShortDescription>役に立たない空ではない void メソッド</ShortDescription>
+ <LongDescription>メソッド {1} は、役に立たないようです。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+我々の解析は、この空ではない void メソッドが実際に有用な仕事を行わないことを示しています。
+確認してください。おそらくそのコードが間違っているか、またはボディを完全に除去できます。
+</p>
+<p>
+我々はできる限り誤検出を減らそうと努力しているが、いくつかのケースでは警告は間違っているかもしれません。
+よくある誤検出例です。
+</p>
+<p>
+- メソッドは、副作用を持つかもしれないクラスのロードをトリガすることを意図している
+</p>
+<p>
+- メソッドは、暗黙のわかりにくい例外をスローするように意図されている
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="UC_USELESS_CONDITION">
+ <ShortDescription>条件は効果がない</ShortDescription>
+ <LongDescription>役に立たない条件: この時点 {2} で知られていました。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+この条件は常に関係している変数の値が前に絞られたのと同じ結果を作り出します。
+おそらく何かほかのことを意味していたのか、あるいは条件を除去できます。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="UC_USELESS_CONDITION_TYPE">
+ <ShortDescription>条件は変数型のために効果がない</ShortDescription>
+ <LongDescription>役に立たない条件: 変数型が {3} なので、常に {2} です。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+この条件は関係している変数の型範囲のために常に同じ結果を作り出します。
+おそらく何かほかのことを意味していたのか、あるいは条件を除去できます。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="UC_USELESS_OBJECT">
+ <ShortDescription>役に立たないオブジェクトを作成した</ShortDescription>
+ <LongDescription>役に立たないオブジェクトをメソッド {1} の変数 {2} で格納しました。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+我々の解析でオブジェクトが役に立たないことを示しています。
+作成され、変更されていますが、値はメソッドの外に出ないし、副作用をもたらしません。
+間違いかオブジェクトが使われることを意図していたかのどちらか、あるいは除去できます。
+</p>
+<p>
+この解析はめったに誤検出することはありません。よくある誤検出のケースです。
+</p>
+<p>- 暗黙のうちに曖昧な例外をスローした</p>
+<p>- コードを一般化してスタブとして使用された</p>
+<p>- 弱/ソフト参照オブジェクトへの強い参照を持っていた</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="UC_USELESS_OBJECT_STACK">
+ <ShortDescription>役に立たないオブジェクトをスタックで作成した</ShortDescription>
+ <LongDescription>役に立たないオブジェクトをメソッド {1} で作成しました。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+このオブジェクトは副作用を持たない修正を行うために作成されています。
+おそらく何かほかのことを意味していたのか、あるいはオブジェクトを除去できます。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="RANGE_ARRAY_INDEX">
+ <ShortDescription>配列インデックスは範囲外</ShortDescription>
+ <LongDescription>配列インデックスは範囲外です: {3}</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+配列演算が行なわれますが、配列インデックスが範囲外なので実行時に ArrayIndexOutOfBoundsException が発生するでしょう。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="RANGE_ARRAY_OFFSET">
+ <ShortDescription>配列オフセットは範囲外</ShortDescription>
+ <LongDescription>配列オフセットは範囲外です: {3}</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+メソッドは、配列パラメータとオフセットパラメータで呼び出されますが、オフセットは範囲外です。
+実行時に IndexOutOfBoundsException が発生するでしょう。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="RANGE_ARRAY_LENGTH">
+ <ShortDescription>配列の長さは範囲外</ShortDescription>
+ <LongDescription>配列の長さは範囲外です: {3}</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+メソッドは、配列パラメータと長さパラメータで呼び出されますが、長さは範囲外です。
+実行時に IndexOutOfBoundsException が発生するでしょう。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="RANGE_STRING_INDEX">
+ <ShortDescription>文字列インデックスは範囲外</ShortDescription>
+ <LongDescription>文字列インデックスは {5} を呼び出すときに範囲外です: {3}</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+文字列メソッドが呼び出されます。指定された文字列インデックスは範囲外です。
+実行時に StringIndexOutOfBoundsException が発生するでしょう。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="RV_CHECK_FOR_POSITIVE_INDEXOF">
<ShortDescription>String.indexOf の結果が正かどうか確かめている</ShortDescription>
<LongDescription>String.indexOf の結果が正かどうか確かめています。{1}</LongDescription>
@@ -5195,6 +5650,36 @@ static フィールドにすることを検討してください。
</Details>
</BugPattern>
+ <BugPattern type="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT">
+ <ShortDescription>副作用がないメソッドの戻り値は無視される</ShortDescription>
+ <LongDescription>副作用がない {2.givenClass} の戻り値は無視されます。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+このコードは、メソッドを呼び出して戻り値を無視しています。
+しかしながら、解析はメソッド (もしあればサブクラスの実装も含む) が戻り値以外の効果をもたらさないことを示しています。
+この呼び出しは除去できます。
+</p>
+<p>
+我々は、できる限り誤検出を減らそうとしていますが、いくつかのケースではこの警告が間違っているかもしれません。
+よくある誤検出です。
+</p>
+<p>
+- メソッドは、オーバライドされ解析対象外の他のプロジェクトで副作用がもたらされるように設計されている
+<p>
+<p>
+- メソッドは、副作用をもたらすかもしれないクラスローダをトリガーするように呼び出されている
+</p>
+<p>
+- メソッドは、例外を取得するために呼び出されている
+</p>
+<p>
+我々の仮定が正しくないと感じるなら、FindBugs にこのメソッドの戻り値が無視されることを許容するように指示する @CheckReturnValue アノテーションを使用することができます。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="RV_RETURN_VALUE_IGNORED_INFERRED">
<ShortDescription>メソッドは戻り値を無視しています、これは間違いではないですか?</ShortDescription>
<LongDescription>{2.givenClass} の戻り値を無視しています、これは間違いではないですか? {1}</LongDescription>
@@ -5209,7 +5694,7 @@ static フィールドにすることを検討してください。
このメソッドの戻り値を無視することが重要であるか許容できるかどうかに関して、FindBugs に指示する @CheckReturnValue アノテーションが使えます。
</p>
<p>
-戻り値を無視することが間違いではないか決めるために、厳密に調査してください。
+戻り値を無視することが間違いではないか決めるために厳密に調査してください。
</p>
]]>
</Details>
@@ -5270,7 +5755,7 @@ dateString = dateString.trim();
]]>
</Details>
</BugPattern>
-
+
<BugPattern type="RV_EXCEPTION_NOT_THROWN">
<ShortDescription>作成した例外をスローするのではなく捨てている</ShortDescription>
<LongDescription>{2.givenClass} をスローしていません。{1}</LongDescription>
@@ -5325,12 +5810,12 @@ if (x < 0) {
</BugPattern>
<BugPattern type="NP_STORE_INTO_NONNULL_FIELD">
- <ShortDescription>@NonNull でアノテートされたフィールドに null を格納している</ShortDescription>
- <LongDescription>@NonNull でアノテートされたフィールド {2.givenClass} に null を格納しています。{1}</LongDescription>
+ <ShortDescription>@Nonnull でアノテートされたフィールドに null を格納している</ShortDescription>
+ <LongDescription>@Nonnull でアノテートされたフィールド {2.givenClass} に null を格納しています。{1}</LongDescription>
<Details>
<![CDATA[
<p>
- at NonNull でアノテートされたフィールドに null かもしれない値を格納しています。
+ at Nonnull としてアノテートされたフィールドに null かもしれない値を格納しています。
</p>
]]>
</Details>
@@ -5343,7 +5828,7 @@ if (x < 0) {
<![CDATA[
<p>
例外経路上のここで null 値を利用しています。コードが実行されると NullPointerException が発生します。
-現在の FindBugs は実行不可能な例外経路を取り除いていないので、誤検出かもしれないことに注意してください。
+現在の FindBugs は実行不可能な例外経路を刈り取れていないので、誤検出かもしれないことに注意してください。
</p>
<p>
switch 文の default が多くの場合実行不可能なので FindBugs が例外経路である default を検討することに注意して下さい。
@@ -5354,7 +5839,7 @@ switch 文の default が多くの場合実行不可能なので FindBugs が例
<BugPattern type="NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE">
<ShortDescription>パラメータは 非 null でなければならないが null 可能としてアノテートされている</ShortDescription>
- <LongDescription>{2} は、非 null でなければならないが、null 可能としてアノテートされています。</LongDescription>
+ <LongDescription>{2} は、非 null でなければならないが null 可能としてアノテートされています。</LongDescription>
<Details>
<![CDATA[
<p>
@@ -5364,7 +5849,7 @@ switch 文の default が多くの場合実行不可能なので FindBugs が例
]]>
</Details>
</BugPattern>
-
+
<BugPattern type="NP_NULL_ON_SOME_PATH">
<ShortDescription>null 値を利用している可能性がある</ShortDescription>
<LongDescription>{2.givenClass} の null 値を利用している可能性があります。{1}</LongDescription>
@@ -5388,7 +5873,7 @@ switch 文の default が多くの場合実行不可能なので FindBugs が例
分岐または文が実行されるなら、null 値が利用されて NullPointerException が発生します。
もちろん、問題は分岐または文が実行不可能で、NullPointerException が決して発生する可能性がないということかもしれません。
それを決めるのは FindBugs の能力を超えています。
-この値がすでに null であることを検査したという事実からこれは明確な可能性です。
+この値が既に null であることを検査したという事実からこれは明確な可能性です。
</p>
]]>
</Details>
@@ -5400,8 +5885,8 @@ switch 文の default が多くの場合実行不可能なので FindBugs が例
<Details>
<![CDATA[
<p>
-例外経路上のここで null 値が利用されています。コードが実行されると NullPointerException が発生するかもしれません。
-現在の FindBugs は実行不可能な例外経路を取り除かないので、誤検出かもしれないことに注意してください。
+例外経路上のここで null 値が利用されています。コードが実行されると NullPointerException を引き起こすことがあります。
+現在の FindBugs は実行不可能な例外経路を刈り取れていないので、誤検出かもしれないことに注意してください。
</p>
<p>
switch 文の default が多くの場合実行不可能なので FindBugs が例外経路である default を検討することに注意して下さい。
@@ -5417,7 +5902,7 @@ switch 文の default が多くの場合実行不可能なので FindBugs が例
<![CDATA[
<p>
メソッドからの戻り値を null チェックしないで利用しています。メソッドの戻り値は null なのかチェックするべきです。
-コードが実行されると NullPointerException が発生するかもしれません。
+コードが実行されると NullPointerException を引き起こすことがあります。
</p>
]]>
</Details>
@@ -5429,7 +5914,7 @@ switch 文の default が多くの場合実行不可能なので FindBugs が例
<Details>
<![CDATA[
<p>
-null の可能性がある値が、非 null メソッドパラメータに渡されています。
+null の可能性がある値が 非 null メソッドパラメータに渡されています。
パラメータは、常に非 null とすべきパラメータとしてアノテートされていたか、または解析が常に null 値を利用すると示していました。
</p>
]]>
@@ -5476,12 +5961,12 @@ null の可能性がある値が、非 null メソッドパラメータに渡さ
</BugPattern>
<BugPattern type="NP_NONNULL_RETURN_VIOLATION">
- <ShortDescription>null を返すかもしれないメソッドが @NonNull 宣言されている</ShortDescription>
- <LongDescription>{1} は、null を返すかもしれないのに @NonNull 宣言されています。</LongDescription>
+ <ShortDescription>null を返すかもしれないメソッドが @Nonnull 宣言されている</ShortDescription>
+ <LongDescription>{1} は、null を返すかもしれないのに @Nonnull 宣言されています。</LongDescription>
<Details>
<![CDATA[
<p>
-このメソッドは、null 値を返すかもしれないのにメソッド (またはスーパークラスのメソッド) の戻り値に @NonNull が宣言されています。
+このメソッドは、null 値を返すかもしれないのにメソッド (またはスーパークラスのメソッド) の戻り値に @Nonnull が宣言されています。
</p>
]]>
</Details>
@@ -5548,7 +6033,7 @@ null ではなく空の文字列または、いくつかの他の適切な文字
<Details>
<![CDATA[
<p>
-すべての static final フィールドが初期化される前に、スタティックイニシャライザがクラスのインスタンスを作成します。
+すべての static final フィールドが初期化される前にスタティックイニシャライザがクラスのインスタンスを作成します。
</p>
]]>
</Details>
@@ -5561,8 +6046,8 @@ null ではなく空の文字列または、いくつかの他の適切な文字
<![CDATA[
<p>
このメソッドは、入出力ストリームオブジェクトを作成していますが、どんなフィールドにも代入していないしクローズするかもしれない別のメソッドにも渡していなくて、戻り値にしてもいません。そして、メソッドからのすべての経路でクローズするように見えません。
-これは、ファイルディスクリプタリークになるかもしれません。
-ストリームがクローズされることを確実にするために <code>finally</code> ブロックを使うことは、一般に良い考えです。
+これはファイルディスクリプタリークの原因になることがあります。
+ストリームがクローズされることを確実にするために <code>finally</code> ブロックを使用することは一般的に良い考えです。
</p>
]]>
</Details>
@@ -5575,8 +6060,8 @@ null ではなく空の文字列または、いくつかの他の適切な文字
<![CDATA[
<p>
このメソッドは、入出力ストリームオブジェクトを作成していますが、どんなフィールドにも代入していないしクローズするかもしれない別のメソッドにも渡していないくて、戻り値にしてもいません。そして、メソッドからのすべての可能性がある例外経路でクローズするように見えません。
-これはファイルディスクリプターリークになるかもしれません。
-ストリームがクローズされることを確実にするために <code>finally</code> ブロックを使うことは、一般に良い考えです。
+これはファイルディスクリプターリークの原因になることがあります。
+ストリームがクローズされることを確実にするために <code>finally</code> ブロックを使用することは一般的に良い考えです。
</p>
]]>
</Details>
@@ -5591,7 +6076,7 @@ null ではなく空の文字列または、いくつかの他の適切な文字
結果がないこと (すなわち、結果の空のリスト) を示すために null 参照ではなく長さが0の配列 を返すことは、多くの場合より良い設計です。
</p>
<p>
-他方では、「この質問に対する答えがない」ことを示すために、null を使うことはおそらく適切です。
+他方では、「この質問に対する答えがない」ことを示すために null を使用することはおそらく適切です。
たとえば、<code>File.listFiles()</code> は、ファイルがないディレクトリを与えられた場合は空のリストを返し、ファイルがディレクトリでないなら null を返します。
</p>
]]>
@@ -5634,12 +6119,12 @@ if (argv.length == 1);
</BugPattern>
<BugPattern type="RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE">
- <ShortDescription>すでに利用していた値の null チェック</ShortDescription>
- <LongDescription>すでに利用していた {2.givenClass} の値を {4.lineNumber} で null チェックしています。{1}</LongDescription>
+ <ShortDescription>既に利用していた値の null チェック</ShortDescription>
+ <LongDescription>既に利用していた {2.givenClass} の値を {4.lineNumber} で null チェックしています。{1}</LongDescription>
<Details>
<![CDATA[
<p>
-ここで値が null なのかチェックしていますが、すでに値を利用していたので null である可能性はありません。
+ここで値が null なのかチェックしていますが、既に値を利用していたので null である可能性はありません。
値が null なら以前の利用で NullPointerException が発生していたでしょう。
基本的に、値が null であることを許すのかどうかに関係なく、このコードと以前の値の利用は一致しません。
チェックは冗長か、または以前の値の利用は誤りです。
@@ -5724,7 +6209,7 @@ of defensive programming.</p>
<![CDATA[
<p>
このメソッドは、JSR-166(<code>java.util.concurrent</code>) のロックを獲得していますが、メソッドからのすべての経路で解除していません。
-一般に、JSR-166のロックを使用するための正しいイディオムは以下のようになります。
+一般的に JSR-166のロックを使用するための正しいイディオムは以下のようになります。
</p>
<blockquote><pre>
Lock l = ...;
@@ -5746,7 +6231,7 @@ try {
<![CDATA[
<p>
このメソッドは、JSR-166(<code>java.util.concurrent</code>) のロックを獲得していますが、メソッドからのすべての例外経路で解除していません。
-一般に、JSR-166のロックを使用するための正しいイディオムは以下のようになります。
+一般的に JSR-166のロックを使用するための正しいイディオムは以下のようになります。
</p>
<blockquote><pre>
Lock l = ...;
@@ -5768,7 +6253,7 @@ try {
<![CDATA[
<p>
このメソッドは、 == または != 演算子を使用して2つの参照値を比較しています。
-この型のインスタンスを比較する正しい方法は、一般に <code>equals</code> メソッドです。
+一般的にこの型のインスタンスを比較する正しい方法は <code>equals</code> メソッドです。
等価で識別可能なインスタンスを作成する可能性がありますが異なるオブジェクトなので == で比較しないでください。
参照によって一般に比較されるべきでないクラスの例は、<code>java.lang.Integer</code> 、<code>java.lang.Float</code> などです。
</p>
@@ -5783,9 +6268,9 @@ try {
<![CDATA[
<p>
このメソッドは、 参照値を == または != 演算子を使用して定数と比較しています。
-この型のインスタンスを比較する正しい方法は、一般に <code>equals</code> メソッドです。
+一般的にこの型のインスタンスを比較する正しい方法は <code>equals</code> メソッドです。
等価で識別可能なインスタンスを作成する可能性がありますが異なるオブジェクトなので == で比較しないでください。
-参照によって一般に比較されるべきではないクラスの例は、<code>java.lang.Integer</code> 、<code>java.lang.Float</code> などです。
+一般的に参照によって比較されるべきではないクラスの例は、<code>java.lang.Integer</code> 、<code>java.lang.Float</code> などです。
</p>
]]>
</Details>
@@ -5798,7 +6283,7 @@ try {
<![CDATA[
<p>
このメソッドは、== または != 演算子を使用して2つの Boolean 値を比較しています。
-一般には2つの Boolean 値 (<code>Boolean.TRUE</code> と <code>Boolean.FALSE</code>) だけですが、
+一般的には2つの Boolean 値 (<code>Boolean.TRUE</code> と <code>Boolean.FALSE</code>) だけですが、
<code>new Boolean(b)</code> コンストラクタを使用して他の Boolean オブジェクトを作成する可能性があります。
そのようなオブジェクトを回避することは最高です。
しかし、それらが存在するなら、Boolean オブジェクトの等価性をチェックするために <code>.equals(...)</code> ではなく == または != を使用しているなら異なる結果をもたらします。
@@ -5826,10 +6311,9 @@ try {
<Details>
<![CDATA[
<p>
-このメソッドは、共通のサブクラスがない異なるクラス型の2つのオブジェクト参照で <code>equals(Object)</code> メソッドを呼び出しています。
-したがって比較されている2つのオブジェクトは実行時に同じクラスのメンバである可能性が低いです (いくつかのアプリケーションクラスが解析できなかったか、動的クラスローディングが実行時に起こることができた場合を除く)。
-<code>equals</code> メソッドの規約によると、異なるクラスのオブジェクトは常に不等として比較するべきです。
-したがって、<code>java.lang.Object.equals(Object)</code> によって定義される規約によれば、この比較の結果は実行時に常に false になります。
+このメソッドは、異なるクラス型の2つの参照で <code>equals(Object)</code> メソッドを呼び出していて、解析が実行時に異なるクラスのオブジェクトになることを示唆しています。
+さらに、呼び出されるであろう equals メソッドの検査では、この呼び出しは常に false を返すか、
+あるいは equals メソッドが対称 (Object クラスの equals のための契約に必要な性質) ではないことのどちらかを示唆しています。
</p>
]]>
</Details>
@@ -5844,7 +6328,7 @@ try {
このメソッドは、どちらも他方のサブタイプでない無関係なインタフェース型の2つの参照で <code>equals(Object)</code> メソッドを呼び出しています。
そして、両方のインタフェースを実装する既知の非抽象クラスがありません。
したがって比較されている2つのオブジェクトは実行時に同じクラスのメンバである可能性が低いです (いくつかのアプリケーションクラスが解析できなかったか、動的クラスローディングが実行時に起こることができた場合を除く)。
-<code>equals</code> メソッドの規約によると、異なるクラスのオブジェクトは常に不等として比較するべきです。
+<code>equals</code> メソッドの規約によると、異なるクラスのオブジェクトは常に等しくないとして比較するべきです。
したがって、<code>java.lang.Object.equals(Object)</code> によって定義される規約によれば、この比較の結果は実行時に常に false になります。
</p>
]]>
@@ -5860,7 +6344,7 @@ try {
このメソッドは、一方がクラスで他方がインタフェースである2つの参照で <code>equals(Object)</code> メソッドを呼び出しています。
クラスは、そのクラスの非抽象サブクラスも含めてインタフェースを実装していません。
したがって比較されている2つのオブジェクトは実行時に同じクラスのメンバである可能性が低いです (いくつかのアプリケーションクラスが解析できなかったか、動的クラスローディングが実行時に起こることができた場合を除く)。
-<code>equals</code> メソッドの規約によると、異なるクラスのオブジェクトは常に不等として比較するべきです。
+<code>equals</code> メソッドの規約によると、異なるクラスのオブジェクトは常に等しくないとして比較するべきです。
したがって、<code>java.lang.Object.equals(Object)</code> によって定義される規約によれば、この比較の結果は実行時に常に false になります。
</p>
]]>
@@ -6095,7 +6579,7 @@ public void foo() {
]]>
</Details>
</BugPattern>
-
+
<BugPattern type="DMI_RANDOM_USED_ONLY_ONCE">
<ShortDescription>Random オブジェクトが作成され1度しか使われない</ShortDescription>
<LongDescription>Random オブジェクトが生成され、1度しか使われていません。{1}</LongDescription>
@@ -6105,7 +6589,7 @@ public void foo() {
このコードは、<code>java.util.Random</code> オブジェクトを作成して1つの乱数を生成するために使用して捨てています。
これはあまり良くない品質の乱数を作り出し、効率が悪いです。
できれば、<code>Random</code> オブジェクトを1つだけ作成して保存されるようにコードを書き直してください。
-そして、新しい乱数が必要なたびに既存の <code>Random</code> オブジェクトでメソッドを呼び出してください。
+そして、毎回新しい乱数は既存の <code>Random</code> オブジェクトを呼び出して取得することが必要です。
</p>
<p>
生成された乱数が推測可能でないことが重要なら、乱数ごとに新しい <code>Random</code> オブジェクトを作成してはいけません (値はあまりに簡単に推測可能です)。
@@ -6152,7 +6636,7 @@ public void foo() {
<![CDATA[
<p>
このコードは符号付き整数の乱数を生成して別の値を法とする剰余を計算しています。
-乱数が負かもしれないので、剰余演算の結果も負かもしれません。これが意図したことであることを確実にしてください。
+乱数は負になり、剰余演算の結果も負になります。これが意図したことであることを確実にしてください。
その代わりに <code>Random.nextInt(int)</code> の使用を強く検討してください。
</p>
]]>
@@ -6166,7 +6650,7 @@ public void foo() {
<![CDATA[
<p>
このコードは、ハッシュコードを計算して別の値を法とする剰余を計算しています。
-ハッシュコードが負かもしれないので、剰余演算の結果も負かもしれません。
+ハッシュコードは負になり、剰余演算の結果も負なります。
</p>
<p>
計算結果が負ではないことを確認したいなら、コードを変更する必要があるかもしれません。
@@ -6179,12 +6663,12 @@ public void foo() {
</BugPattern>
<BugPattern type="INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE">
- <ShortDescription>負でない値と負の定数との間違った比較</ShortDescription>
+ <ShortDescription>負でない値と負の定数またはゼロとの間違った比較</ShortDescription>
<LongDescription>負でない値 と {2} との間違った比較です。{1}</LongDescription>
<Details>
<![CDATA[
<p>
-このコードは、負でないことが保証されている値と負の定数とを比較しています。
+このコードは、負でないことが保証されている値と負の定数またはゼロとを比較しています。
</p>
]]>
</Details>
@@ -6209,20 +6693,20 @@ public void foo() {
<Details>
<![CDATA[
<p>
-このコードは、int 値と int 値として表現できる値の範囲外にある long 定数を比較しています。
+このコードは、int 値と int 値として表される値の範囲外の long 定数を比較しています。
この比較は無意味で、おそらく間違っています。
</p>
]]>
</Details>
</BugPattern>
-
+
<BugPattern type="INT_VACUOUS_BIT_OPERATION">
<ShortDescription>整数値の無意味なビットマスク演算</ShortDescription>
<LongDescription>{3} の無意味な {2} 演算です。{1}</LongDescription>
<Details>
<![CDATA[
<p>
-これはどんな有効な働きもしない整数ビット演算 (AND、OR、XOR) です (たとえば <code>v & 0xffffffff</code>)。
+どんな有用な仕事もしない整数ビット演算 (AND、OR、XOR) です (たとえば <code>v & 0xffffffff</code>)。
</p>
]]>
</Details>
@@ -6319,12 +6803,12 @@ for(int i = 0; i < 4; i++)
<BugPattern type="BIT_AND">
<ShortDescription>互換性のないビットマスク</ShortDescription>
- <LongDescription>(e & {2} == {3}) の互換性のないビットマスクは、一定の結果をもたらします。{1}</LongDescription>
+ <LongDescription>(e & {2} == {3}) の互換性のないビットマスクは、不変の結果をもたらします。{1}</LongDescription>
<Details>
<![CDATA[
<p>
このメソッドは、<i>(e & C)</i> 形式の式を <i>D</i> と比較しています。
-定数 <i>C</i> と <i>D</i> の特定の値と常に等しくないことを比較します。論理エラーかタイプミスかもしれません。
+定数 <i>C</i> の特定の値と <i>D</i> ために常に等しくないことを比較します。論理エラーかタイプミスかもしれません。
</p>
]]>
</Details>
@@ -6339,7 +6823,7 @@ for(int i = 0; i < 4; i++)
このメソッドは、<code>((event.detail & SWT.SELECTED) > 0)</code> のような式を比較しています。
ビット演算をより大きい演算子で比較することは、予想外の結果 (もちろん、<code>SWT.SELECTED</code> の値による) の原因になる可能性があります。
<code>SWT.SELECTED</code> が負数であるなら、これはバグの候補です。
-<code>SWT.SELECTED</code> が負ではないとしても、'> 0' の代わりに '!= 0' を使うことは良いプラクティスと思われます。
+<code>SWT.SELECTED</code> が負ではないとしても、'> 0' の代わりに '!= 0' を使用することは良いプラクティスと思われます。
</p>
<p>
Boris Bokowski
@@ -6357,7 +6841,7 @@ Boris Bokowski
このメソッドは、<code>((event.detail & SWT.SELECTED) > 0)</code> のような式を比較しています。
ビット演算をより大きい演算子で比較することは、予想外の結果 (もちろん、<code>SWT.SELECTED</code> の値による) の原因になる可能性があります。
<code>SWT.SELECTED</code> が負数であるなら、これはバグの候補です。
-<code>SWT.SELECTED</code> が負ではないとしても、'> 0' の代わりに '!= 0' を使うことは良いプラクティスと思われます。
+<code>SWT.SELECTED</code> が負ではないとしても、'> 0' の代わりに '!= 0' を使用することは良いプラクティスと思われます。
</p>
<p>
Boris Bokowski
@@ -6380,12 +6864,12 @@ Boris Bokowski
<BugPattern type="BIT_IOR">
<ShortDescription>互換性のないビットマスク</ShortDescription>
- <LongDescription>(e | {2} == {3}) の互換性のないビットマスクは、一定の結果をもたらします。{1}</LongDescription>
+ <LongDescription>(e | {2} == {3}) の互換性のないビットマスクは、不変の結果をもたらします。{1}</LongDescription>
<Details>
<![CDATA[
<p>
このメソッドは、<code>(e | C)</code> 形式の式を <code>D</code> と比較しています。
-定数 <i>C</i> と <i>D</i> の特定の値と常に等しくないことを比較します。論理エラーかタイプミスかもしれません。
+定数 <i>C</i> の特定の値と <i>D</i> のために常に等しくないことを比較します。論理エラーかタイプミスかもしれません。
</p>
<p>
典型的に、このバグは、ビットセットで帰属関係のテストを実行したいコードで発生します。
@@ -6419,10 +6903,10 @@ For more information, see the
<![CDATA[
<p>
このメソッドにはvolatile でない static フィールドの非同期な遅延初期化があります。
-コンパイラやプロセッサが命令を並べ替えるかもしれないので、メソッドが複数のスレッドによって呼び出されるかもしれないなら、
+コンパイラやプロセッサが命令を並べ替えるかもしれないので、メソッドが複数のスレッドによって呼び出されるなら、
スレッドは完全に初期化されたオブジェクトを見るとは保証されていません。
フィールドにアクセスした際に、中途半端に初期化されたインスタンスが見えてしまう危険があります。
-この問題を修正するために、フィールドを volatile にできます。<br>
+この問題を修正するためにフィールドを volatile にできます。<br>
詳細は、<a href="http://www.cs.umd.edu/~pugh/java/memoryModel/">Java Memory Model web site</a> を参照してください。
</p>
]]>
@@ -6437,7 +6921,7 @@ For more information, see the
<p>
このメソッドにはstatic フィールドの非同期な遅延初期化があります。
フィールドが設定された後で、その場所に格納されるオブジェクトはさらに更新されるかアクセスされます。
-それが設定されるとすぐに、フィールドの設定は他のスレッドに見えます。
+それが設定されるとすぐに、フィールドを設定することは他のスレッドに見えます。
フィールドを設定するさらなるアクセスがオブジェクトを初期化するのに役に立つなら、
それが完全に初期化されるまでどんな他のスレッドも格納されたオブジェクトにアクセスするのを防がないかぎり、非常に深刻なマルチスレッドバグがあります。
</p>
@@ -6465,7 +6949,7 @@ For more information, see the
<BugPattern type="JML_JSR166_CALLING_WAIT_RATHER_THAN_AWAIT">
<ShortDescription>util.concurrent 抽象でモニタスタイルの wait メソッドを使用している</ShortDescription>
<LongDescription>{3.name} ではなく {2.name} を呼び出しています。{1}</LongDescription>
-<Details>
+ <Details>
<![CDATA[
<p>
このメソッドは、<code>await()</code> メソッド、<code>signal</code> メソッド、<code>signalAll</code> メソッドを提供するオブジェクト
@@ -6513,9 +6997,9 @@ For more information, see the
<![CDATA[
<p>
この無名クラスは、直接呼び出されないスーパークラスのメソッドをオーバーライドしていないメソッドを定義しています。
-他のクラスのメソッドが無名クラスで宣言されたメソッドを直接呼び出せないので、このメソッドは呼び出し不可能であると思われます。
+他のクラスのメソッドが無名クラスで宣言されたメソッドを直接呼び出せないので、このメソッドは呼び出し不可能だと思われます。
メソッドは単にデッドコードであるかもしれません。しかし、メソッドがスーパークラスで宣言されるメソッドをオーバーライドすることを意図した可能性もあります。
-そして、タイプミスまたは他の誤りのために、メソッドは、実際、それが意図されるメソッドをオーバーライドしません。
+そして、タイプミスまたは他の誤りのためにメソッドは、実際には意図しているメソッドをオーバーライドしません。
</p>
]]>
</Details>
@@ -6529,7 +7013,7 @@ For more information, see the
<p>
このメソッドは、データベースリソース (たとえば、データベースコネクションや行セット) を作成していますが、どんなフィールドにも代入していないか、他のメソッドにも渡していないか、戻り値にもしていません。
そして、メソッドからのすべての経路でオブジェクトをクローズするように見えません。
-メソッドからのすべての経路でデータベースリソースのクローズ失敗は良くない性能になるかもしれません。
+メソッドからのすべての経路でデータベースリソースのクローズが失敗すると性能低下になることがあります。
データベースとの通信で問題があるアプリケーションの原因になる可能性があります。
</p>
]]>
@@ -6544,7 +7028,7 @@ For more information, see the
<p>
このメソッドは、データベースリソース (たとえば、データベースコネクションや行セット) を作成していますが、どんなフィールドにも代入していないか、他のメソッドにも渡していないか、戻り値にもしていません。
そして、メソッドからのすべての例外経路でオブジェクトをクローズするように見えません。
-メソッドからのすべての経路でデータベースリソースのクローズ失敗は良くない性能になるかもしれません。
+メソッドからのすべての経路でデータベースリソースのクローズが失敗すると性能低下になることがあります。
データベースとの通信で問題があるアプリケーションの原因になる可能性があります。
</p>
]]>
@@ -6562,7 +7046,7 @@ For more information, see the
各々の繰り返しで文字列が再コピーされ、増大すると繰り返しの数で二次コストの原因になる可能性があります。
</p>
<p>
-明示的に、<code>StringBuffer</code> (または J2SE 5.0の <code>StringBuilder</code>) を使うことで、より良い性能を得られるかもしれません。
+<code>StringBuffer</code> (または J2SE 5.0の <code>StringBuilder</code>) を明示的に使うとより良い性能を得られます。
</p>
<p>
たとえば、
@@ -6585,6 +7069,85 @@ String s = buf.toString();
</Details>
</BugPattern>
+ <BugPattern type="IIL_PREPARE_STATEMENT_IN_LOOP">
+ <ShortDescription>ループの中で prepareStatement を呼び出しているメソッド</ShortDescription>
+ <LongDescription>{1} は、ループの中で不変の引数で prepareStatement を呼び出しています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+メソッドは、ループの中で <code>Connection.prepareStatement</code> に不変の引数を渡して呼び出しています。
+<code>PreparedStatement</code> を複数回実行する必要があるなら、それぞれのループの繰り返しで再生成する理由がありません。
+ループの外に呼び出しを移動します。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="IIL_ELEMENTS_GET_LENGTH_IN_LOOP">
+ <ShortDescription>ループの中で NodeList.getLength() を呼び出しているメソッド</ShortDescription>
+ <LongDescription>{1} は、ループの中で getElementsByTagName の戻り値のために NodeList.getLength() を呼び出しています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+メソッドは、ループの中で <code>NodeList.getLength()</code> を呼び出し、<code>NodeList</code> は、<code>getElementsByTagName</code> の呼び出しによって作られます。
+<code>NodeList</code> は長さを格納しませんが、毎回とても最適ではない方法で計算されます。
+ループの前に変数に長さを格納することを検討してください。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+ <BugPattern type="IIL_PATTERN_COMPILE_IN_LOOP">
+ <ShortDescription>ループの中で Pattern.compile を呼び出しているメソッド</ShortDescription>
+ <LongDescription>{1} は、ループの中で不変の定数で Pattern.compile を呼び出しています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+メソッドは、ループの中で <code>Pattern.compile</code> に不変の定数を渡して呼び出しています。
+<code>Pattern</code> を複数回使用する必要があるなら、それぞれのループの繰り返しでコンパイルする理由がありません。
+ループの外に呼び出しを移動するか static final フィールドにします。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="IIL_PATTERN_COMPILE_IN_LOOP_INDIRECT">
+ <ShortDescription>ループの中で正規表現をコンパイルしているメソッド</ShortDescription>
+ <LongDescription>{1} は、ループの中で正規表現のコンパイルをしています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+メソッドは、ループの中で同じ正規表現を生成しているので、繰り返しごとにコンパイルされます。
+ループの外で <code>Pattern.compile</code> を使用して正規表現をプリコンパイルするのが最適でしょう。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="IIO_INEFFICIENT_INDEX_OF">
+ <ShortDescription>String.indexOf(String) の非効率的な使用</ShortDescription>
+ <LongDescription>{1} は、String.indexOf(int) の代わりに String.indexOf(String) を使用しています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+このコードは、String.indexOf() に長さ1の文字列定数を渡しています。String.indexOf() の整数実装を使うほうが効率的です。
+たとえば、<code>myString.indexOf(".")</code> の代わりに <code>myString.indexOf('.')</code> を呼び出します。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="IIO_INEFFICIENT_LAST_INDEX_OF">
+ <ShortDescription>String.lastIndexOf(String) の非効率的な使用</ShortDescription>
+ <LongDescription>{1} は、String.lastIndexOf(int) の代わりに String.lastIndexOf(String) を使用しています。</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+このコードは、String.lastIndexOf() に長さ1の文字列定数を渡しています。String.lastIndexOf() の整数実装を使うほうが効率的です。
+たとえば、<code>myString.lastIndexOf(".")</code> の代わりに <code>myString.lastIndexOf('.')</code> を呼び出します。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
<BugPattern type="ITA_INEFFICIENT_TO_ARRAY">
<ShortDescription>長さが0の配列の引数で toArray メソッドを使用しているメソッド</ShortDescription>
<LongDescription>{1} は、長さが0の配列の引数で Collection.toArray() を使用しています。</LongDescription>
@@ -6594,7 +7157,7 @@ String s = buf.toString();
このメソッドは、Collection 派生クラスの </code>toArray</code> メソッドを使用して長さが0の配列の引数を渡しています。
<code>myCollection.toArray(new Foo[myCollection.size()])</code> を使用するほうがより効率的です。
渡される配列がコレクションの要素のすべてを格納できるくらいの大きさなら、データが読み込まれて、そのまま返されます。
-これは、結果として返す2番目の配列 (リフレクションによって) を作成する必要を回避します。
+これは結果として返す2番目の配列 (リフレクションによって) を作成する必要を回避します。
</p>
]]>
</Details>
@@ -6739,11 +7302,11 @@ field index is 0. As ResultSet fields start at index 1, this is always a mistake
<BugPattern type="SIO_SUPERFLUOUS_INSTANCEOF">
<ShortDescription>instanceof 演算子を使用した不必要な型チェック</ShortDescription>
- <LongDescription>{1} は、静的に確定している可能性があるのに instanceof 演算子を使用して不必要な型チェックをしています。</LongDescription>
+ <LongDescription>{1} は、静的に判定される instanceof 演算子を使用して不必要な型チェックをしています。</LongDescription>
<Details>
<![CDATA[
<p>
-オブジェクトが要求する型であるかどうかにかかわらず、静的に確定している可能性があるのに instanceof 演算子を使用して型チェックをしています。
+オブジェクトが要求する型であるかどうかにかかわらず、静的に判定される instanceof 演算子を使用して型チェックをしています。
</p>
]]>
</Details>
@@ -6768,9 +7331,9 @@ field index is 0. As ResultSet fields start at index 1, this is always a mistake
<Details>
<![CDATA[
<p>
-このメソッドは、配列と配列であると思われない参照を比較するために <code>.equals(Object o)</code> を呼び出しています。
-比較されているものが違う型なら不等であることが保証されているので、比較はほぼ間違いなく誤りです。
-たとえそれらが両方とも配列であるとしても、配列の <code>equals</code> メソッドは2つの配列が同じオブジェクトであると決定するだけです。
+このメソッドは、配列と配列だと思われない参照を比較するために <code>.equals(Object o)</code> を呼び出しています。
+比較されているものが違う型なら等しくないことであることが保証されているので、比較はほぼ間違いなく誤りです。
+たとえそれらが両方とも配列だったとしても、配列の <code>equals</code> メソッドは2つの配列が同じオブジェクトだと決定するだけです。
配列のコンテンツを比較するためには <code>java.util.Arrays.equals(Object[], Object[])</code> を使用してください。
</p>
]]>
@@ -6786,7 +7349,7 @@ field index is 0. As ResultSet fields start at index 1, this is always a mistake
このメソッドは、配列で <code>.equals(Object o)</code> を呼び出しています。
配列は、<code>Object</code> の <code>equals</code> メソッドをオーバーライドしないので、配列で <code>equals</code> メソッドを呼び出すことはアドレスを比較することと同じです。
配列のコンテンツを比較するためには <code>java.util.Arrays.equals(Object[], Object[])</code> を使用してください。
-配列のアドレスを比較するために、明示的に、<code>==</code> を使用して参照等価性をチェックすることは、それほど紛らわしくないでしょう。
+配列のアドレスを比較するために明示的に <code>==</code> を使用して参照等価性をチェックすることは、それほど紛らわしくないでしょう。
</p>
]]>
</Details>
@@ -6889,8 +7452,8 @@ FindBugs は、バイトコードベースのツールなので誤検出をな
</BugPattern>
<BugPattern type="DLS_DEAD_LOCAL_INCREMENT_IN_RETURN">
- <ShortDescription>return 文に役に立たないインクリメントがある</ShortDescription>
- <LongDescription>{1} からの return に役に立たないインクリメントがあります。</LongDescription>
+ <ShortDescription>return 文に無駄なインクリメントがある</ShortDescription>
+ <LongDescription>{1} からの return に無駄なインクリメントがあります。</LongDescription>
<Details>
<![CDATA[
<p>
@@ -6901,7 +7464,7 @@ FindBugs は、バイトコードベースのツールなので誤検出をな
]]>
</Details>
</BugPattern>
-
+
<BugPattern type="DLS_DEAD_STORE_OF_CLASS_LITERAL">
<ShortDescription>クラスリテラルの無効な代入</ShortDescription>
<LongDescription>{3}.class の無効な代入です。{1}</LongDescription>
@@ -6910,7 +7473,7 @@ FindBugs は、バイトコードベースのツールなので誤検出をな
<p>
この命令は変数にクラスリテラルを代入していますが、決して使われません。<br>
<a href="//java.sun.com/j2se/1.5.0/compatibility.html#literal">The behavior of this differs in Java 1.4 and in Java 5</a><br>
-J2SE 1.4 およびそれ以前のバージョンでは、<code>Foo.class</code> への参照は <code>Foo</code> のためのスタティックイニシャライザがすでに実行されていないなら実行することを強制します。
+J2SE 1.4 およびそれ以前のバージョンでは、<code>Foo.class</code> への参照は <code>Foo</code> のためのスタティックイニシャライザが既に実行されていないなら実行することを強制します。
J2SE 5.0 ではそうしません。
</p>
<p>
@@ -6927,7 +7490,7 @@ J2SE 5.0 ではそうしません。
<![CDATA[
<p>
このコードはローカル変数に null を代入していますが代入された値は読み出されていません。
-この代入はガベージコレクタを手伝うために導入されたのかもしれませんが、Java SE 6 ではもはや必要とされないか有効ではありません。
+この代入はガベージコレクタを手伝うために導入されたのかもしれませんが、Java SE 6 ではもはや必要とされないか有用ではありません。
</p>
]]>
</Details>
@@ -6940,7 +7503,7 @@ J2SE 5.0 ではそうしません。
<![CDATA[
<p>
このメソッドは、このクラスまたはスーパークラスのフィールドと同じ名前でローカル変数を定義しています。
-これはフィールドから初期化されていない値を読み出したり初期化されていないフィールドをそのままにしておくメソッドの原因になるかもしれません。
+フィールドから初期化されていない値を読み出す、初期化されていないフィールドをそのままにしておくか、または両方を引き起こすかもしれません。
</p>
]]>
</Details>
@@ -7021,7 +7584,7 @@ try {
このコードは、浮動小数点が特別な非数値と等価であるか確かめています (たとえば <code>if (x == Double.NaN)</code>)。
しかしながら、<code>NaN</code> の特別な意味のため、値は <code>NaN</code> と等価ではありません。
したがって、<code>x == Double.NaN</code> は常に false と評価します。
-<code>x</code> という値が特別な非数値であるかどうか確かめるためには <code>Double.isNaN(x)</code> を使用します (あるいは <code>x</code> が浮動小数点精度であるなら <code>Float.isNaN(x)</code>)。
+<code>x</code> という値が特別な非数値であるかどうか確かめるためには <code>Double.isNaN(x)</code> を使用します (または <code>x</code> が浮動小数点精度であるなら <code>Float.isNaN(x)</code>)。
</p>
]]>
</Details>
@@ -7035,7 +7598,7 @@ try {
<p>
この演算は、等価性のために2つの浮動小数点値を比較しています。
浮動小数点の計算は丸めを伴うかもしれないので計算された float と double の値は正確ではないかもしれません。
-通貨のような正確でなければならない値のために、<code>BigDecimal</code> のような固定精度型を使うことを検討してください。
+通貨のような正確でなければならない値のために <code>BigDecimal</code> のような固定精度型を使用することを検討してください。
正確である必要がない値のためにいくつかの範囲の中で等価性のために比較することを検討してください。
たとえば、<code>if (Math.abs(x - y) < .0000001)</code>。<br>
詳細は Java 言語仕様4.2.4を参照してください。
@@ -7051,7 +7614,7 @@ try {
<![CDATA[
<p>
このメソッドは、定数値で <code>java.lang.Math</code> の static メソッドを呼び出しています。
-このメソッドの結果は、静的に確定している可能性があり、より高速で、ときには定数を使用するほうがより正確です。<br>
+このメソッドの結果は静的に判定でき、より高速で、ときには定数を使用するほうがより正確です。<br>
検出されるメソッドは、以下のとおりです。
</p>
<table>
@@ -7140,7 +7703,7 @@ try {
<p>
このクラスは、他のクラスと循環依存関係があります。
それぞれが他のクラスの正確な構築に依存していて、クラスの構築を難しくしています。
-難しい依存関係を断つために、インタフェースの使用を検討してください。
+難しい依存関係を断つためにインタフェースの使用を検討してください。
</p>
]]>
</Details>
@@ -7168,7 +7731,7 @@ try {
<p>
Struts Action クラスを拡張したクラスで、インスタンス変数を使用しています。
Struts Action クラスの1つのインスタンスだけが Struts フレームワークによって作成され、マルチスレッドによって使われるので、このパラダイムは極めて問題があり、推奨できません。
-ローカル変数を使うことだけを検討してください。
+ローカル変数を使用することだけを検討してください。
モニタを除いて書き込まれるインスタンスフィールドだけが報告されます。
</p>
]]>
@@ -7183,7 +7746,7 @@ Struts Action クラスの1つのインスタンスだけが Struts フレーム
<p>
Servletクラスを拡張したクラスで、インスタンス変数を使用しています。
Servlet クラスの1つのインスタンスだけが Java EE フレームワークによって作成され、マルチスレッドによって使われるので、このパラダイムは極めて問題があり、推奨できません。
-ローカル変数を使うことだけを検討してください。
+ローカル変数を使用することだけを検討してください。
</p>
]]>
</Details>
@@ -7199,7 +7762,7 @@ Servlet クラスの1つのインスタンスだけが Java EE フレームワ
このクラスを使用するクライアントクラスは、同期化のためのオブジェクトとしてこのクラスのインスタンスをさらに使用するかもしれません。
2つのクラスが同期化のために同じオブジェクトを使用するので、マルチスレッドの正確性は疑わしいです。
同期化するべきでもないし、公開参照でセマフォメソッドも呼び出すべきではありません。
-同期化の制御には内部の公開されないメンバ変数を使うことを検討してください。
+同期化の制御には内部の公開されないメンバ変数を使用することを検討してください。
</p>
]]>
</Details>
@@ -7242,7 +7805,7 @@ long convertDaysToMilliseconds(int days) { return days * MILLISECONDS_PER_DAY; }
<p>
このコードは、32ビット int 値を64ビット long 値に変換して、絶対時間値を必要とするメソッドパラメータに渡しています。
絶対時間値は、「エポック」(すなわち、1970年1月1日、00:00:00 GMT)としてわかっている標準的な基準時間からのミリ秒数です。<br>
-たとえば、次のメソッド(Date にエポックから秒を変換することを意図した)は、ひどく壊れています。
+たとえば、次のメソッド (エポックからの秒を Date へ変換することを意図した) はひどく壊れています。
</p>
<blockquote><pre>
Date getDate(int seconds) { return new Date(seconds * 1000); }
@@ -7252,7 +7815,7 @@ Date getDate(int seconds) { return new Date(seconds * 1000); }
32ビット値は、64ビットに変換されて、絶対時間値を表すために使用されるとき、1969年12月と1970年1月の日付しか表せません。
</p>
<p>
-上記のメソッドのための正しい実装は、以下のとおりです。
+上記のメソッドの正しい実装は以下のとおりです。
</p>
<blockquote><pre>
// 失敗、2037年後の日付
@@ -7365,7 +7928,7 @@ double value2 = x / (double) y;
<![CDATA[
<p>
この書式文字列には改行文字 (\n) が含まれています。
-一般に書式文字列には %n を使用することがより望ましいです。%n は、プラットホーム特有の行セパレータを作り出します。
+一般的に書式文字列には %n を使用することがより望ましいです。%n は、プラットホーム特有の行セパレータを作り出します。
</p>
]]>
</Details>
@@ -7405,7 +7968,7 @@ Boolean 型でない引数を %b 書式指示子でフォーマットしてい
<![CDATA[
<p>
書式文字列でフォーマットされている引数の1つは配列です。
-これは [I at 304282 のようなかなり役に立たない書式を使用してフォーマットされます。それは配列のコンテンツを表示しません。
+[I at 304282 のように配列のコンテンツを表示しないかなり役に立たない書式を使用してフォーマットされます。
フォーマットで扱う前に <code>Arrays.asList(...)</code> を使用して配列をラップすることを検討してください。
</p>
]]>
@@ -7498,14 +8061,14 @@ printf スタイルの書式文字列が必要なときに、MessageFormat の
<![CDATA[
<p>
このコードは可変長引数をとるメソッドにプリミティブ型の配列を渡しています。
-これは、プリミティブ型の配列を保持するために長さが1の配列を作成してメソッドに渡します。
+これはプリミティブ型の配列を保持するために長さが1の配列を作成してメソッドに渡します。
</p>
]]>
</Details>
</BugPattern>
<BugPattern type="BC_EQUALS_METHOD_SHOULD_WORK_FOR_ALL_OBJECTS">
<ShortDescription>equals メソッドは引数の型を仮定するべきではない</ShortDescription>
- <LongDescription>{0} のための equals メソッドは、引数の型が {0.givenClass} であると仮定しています。</LongDescription>
+ <LongDescription>{0} のための equals メソッドは、引数の型が {0.givenClass} だと仮定しています。</LongDescription>
<Details>
<![CDATA[
<p>
@@ -7523,7 +8086,7 @@ printf スタイルの書式文字列が必要なときに、MessageFormat の
<![CDATA[
<p>
このコードは、Collection を抽象コレクションにキャストしています (たとえば <code>List</code>、<code>Set</code>、<code>Map</code>)。
-オブジェクトがキャストする型であると保証されることを確認してください。
+オブジェクトがキャストする型であるということが保証されていることを確認してください。
必要とするコレクションの反復処理ができるなら Set または List にキャストする必要はありません。
</p>
]]>
@@ -7551,7 +8114,7 @@ printf スタイルの書式文字列が必要なときに、MessageFormat の
このキャストは、常に ClassCastException をスローします。
FindBugs は、instanceof チェックから型情報を調査して、メソッドからの戻り値とフィールドからロードされた値の型について、より多くの正確な情報を使用します。
したがって、宣言された変数の型にはより多くの正確な情報があるかもしれないしれません。
-そして、キャストが常に実行時例外をスローするのか判定するために使用する可能性があります。
+また、キャストが常に実行時例外をスローするのかを決定するために利用する可能性があります。
</p>
]]>
</Details>
@@ -7585,14 +8148,14 @@ String[] getAsArray(Collection<String> c) {
}
</pre></blockquote>
<p>
-これは通常、ClassCastException をスローして失敗します。
+これは通常 ClassCastException をスローして失敗します。
ほとんどすべてのコレクションの <code>toArray</code> メソッドは、<code>Object[]</code> を返します。
Collection オブジェクトは宣言された総称型コレクションの参照がないので、本当に何もできません。
-コレクションから特定の型の配列を得る正しい方法は、<code>c.toArray(new String[]);</code> または <code>c.toArray(new String[c.size()]);</code> (後者はわずかにより効率的です) を使うことです。
+コレクションから特定の型の配列を得る正しい方法は、<code>c.toArray(new String[]);</code> または <code>c.toArray(new String[c.size()]);</code> (後者はわずかにより効率的です) を使用することです。
これに対する1つの共通の知られている例外があります。
-<code>Arrays.asList(...)</code>によって返されるリストの <code>toArray()</code> メソッドは、共変な配列を返します。
+<code>Arrays.asList(...)</code>によって返されるリストの <code>toArray()</code> メソッドは共変型配列を返します。
たとえば、<code>Arrays.asArray(new String[] { "a" }).toArray()</code> は <code>String []</code> を返します。
-FindBugs はそのようなケースを検出して抑止しようとしますが、いくつか見落とすかもしれません。
+FindBugs はそのようなケースを検出して抑止しようとしますが、見落としているかもしれません。
</p>
]]>
</Details>
@@ -7657,14 +8220,14 @@ an indication of some misunderstanding or some other logic error.
<Details>
<![CDATA[
<p>
-このキャストはチェックされていません。すべての型のインスタンスがキャストした型にキャストできるというわけではありません。
+このキャストはチェックされていません。すべての型のインスタンスをキャストする型へキャストできるわけではありません。
プログラムのロジックがこのキャストが失敗しないことを確実に確認してください。
</p>
]]>
</Details>
</BugPattern>
- <BugPattern type="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE">
+ <BugPattern type="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE">
<ShortDescription>メソッドからの戻り値の未チェック/未確認のキャスト</ShortDescription>
<LongDescription>{2} からの {3} 戻り値への未チェック/未確認のキャストです。{1}</LongDescription>
<Details>
@@ -7686,7 +8249,7 @@ an indication of some misunderstanding or some other logic error.
<p>
このコードは抽象コレクション (たとえば、Collection、List、Set) を特定の具象実装 (たとえば、ArrayList、HashSet) にキャストしています。
これは正しくないかもしれません。そして、将来の時点で他の具象実装への切り替えをとても困難にするので、脆弱なコードになるかもしれません。
-そうするために特別な理由がないかぎり抽象コレクションクラスを使用してください。
+そうするための特別な理由がないかぎり抽象コレクションクラスを使用してください。
</p>
]]>
</Details>
@@ -7699,7 +8262,7 @@ an indication of some misunderstanding or some other logic error.
<![CDATA[
<p>
String 機能が呼び出されていて、"." または "|" が引数として正規表現を取るパラメータに渡されています。
-これは、意図したことですか?
+これは意図したことですか?
たとえば
</p>
<ul>
@@ -7731,7 +8294,7 @@ String 機能が呼び出されていて、"." または "|" が引数として
<Details>
<![CDATA[
<p>
-このコードは、正規表現が必要とされる場所で、<code>File.separator</code> を使用しています。
+このコードは、正規表現が必要な場所で、<code>File.separator</code> を使用しています。
これは <code>File.separator</code> がバックスラッシュである Windows プラットホームでは失敗します。
バックスラッシュは正規表現ではエスケープ文字として解釈されます。
その他の選択肢としては、<code>File.separator</code> の代わりに <code>File.separatorChar=='\\' ? "\\\\" : File.separator</code> を使用できます。
@@ -7760,7 +8323,21 @@ String 機能が呼び出されていて、"." または "|" が引数として
<![CDATA[
<p>
このコードは、符号なしキャストの実行結果を short または byte にキャストしています。結果の上位ビットは捨てられます。
-上位ビットが捨てられるので、符号付き、符号なし右シフトの (シフトのサイズによって) 違いがないかもしれません。
+上位ビットが捨てられるので、符号付きと符号なし右シフト (シフトのサイズによって) との違いがないかもしれません。
+</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugPattern type="BSHIFT_WRONG_ADD_PRIORITY">
+ <ShortDescription>シフト演算の正しくない構文解析の可能性がある</ShortDescription>
+ <LongDescription>シフト演算の正しくない構文解析の可能性があります。{1}</LongDescription>
+ <Details>
+<![CDATA[
+<p>
+コードは (x << 8 + y) のような操作を行います。
+これは正しいかもしれませんが、おそらく (x << 8) + y を行うことを意図していました。
+しかし、シフト演算は優先順位が低いので、実際には x << (8 + y) として構文解析されます。
</p>
]]>
</Details>
@@ -7773,8 +8350,8 @@ String 機能が呼び出されていて、"." または "|" が引数として
<![CDATA[
<p>
このコードは、32ビット int の-31から31の範囲を超えた量でシフトを実行しています。
-これの効果は、どのくらいシフトするのかを決めるために整数値の下位5ビット (32で割った余り) を使うことです (たとえば、40ビットでシフトすることは8ビットでシフトすることと同じで、32ビットでシフトすることは0ビットでシフトすることと同じです)。
-これは、おそらく期待されたことではなく、少なくとも紛らわしいです。
+これの効果は、どのくらいシフトするのかを決めるために整数値の下位5ビット (32で割った余り) を使用することです (たとえば、40ビットでシフトすることは8ビットでシフトすることと同じで、32ビットでシフトすることは0ビットでシフトすることと同じです)。
+これはおそらく期待されたことではなく、少なくとも紛らわしいです。
</p>
]]>
</Details>
@@ -7815,7 +8392,7 @@ String 機能が呼び出されていて、"." または "|" が引数として
<![CDATA[
<p>
このコードは、配列で <code>toString</code> メソッドを呼び出しています。「[C at 16f0472」のようなかなり役に立たない結果を生成します。
-配列のコンテンツを与え、読める文字列に変換するために、<code>Arrays.toString()</code> を使うことを検討してください。<br>
+配列のコンテンツを与え、読める文字列に変換するために <code>Arrays.toString()</code> を使用することを検討してください。<br>
『Programming Puzzlers』の第3章、パズル12を参照してください。
</p>
]]>
@@ -7829,7 +8406,7 @@ String 機能が呼び出されていて、"." または "|" が引数として
<![CDATA[
<p>
このコードは、無名の配列で <code>toString</code> メソッドを呼び出しています。「[C at 16f0472」のようなかなり役に立たない結果を生成します。
-配列のコンテンツを与え、読める文字列に変換するために、<code>Arrays.toString()</code> を使うことを検討してください。<br>
+配列のコンテンツを与え、読める文字列に変換するために <code>Arrays.toString()</code> を使用することを検討してください。<br>
『Programming Puzzlers』の第3章、パズル12を参照してください。
</p>
]]>
@@ -7849,7 +8426,7 @@ String 機能が呼び出されていて、"." または "|" が引数として
</p>
<p>
このバグは、二分探索とマージソートの多くの以前の実装で存在します。
-Martin Buchholz が <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6412541">JDK ライブラリでバグを発見し、修正しています</a>。
+Martin Buchholz が <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6412541">JDK ライブラリのバグを発見して修正しています</a>。
Joshua Bloch が <a href="http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html">バグパターンとして公表しました</a>。
</p>
]]>
@@ -7863,7 +8440,7 @@ Joshua Bloch が <a href="http://googleresearch.blogspot.com/2006/06/extra-extra
<![CDATA[
<p>
このコードは、<code>x % 2 == 1</code> を使用して値が負数なのか確かめていますが、負数 (たとえば、<code>(-5) % 2 == -1</code>) なので機能しません。
-奇数チェックを意図しているなら、<code>x & 1 == 1</code> または <code>x % 2 != 0</code> を使うことを検討してください。
+奇数チェックを意図しているなら、<code>x & 1 == 1</code> または <code>x % 2 != 0</code> を使用することを検討してください。
</p>
]]>
</Details>
@@ -7926,7 +8503,7 @@ Joshua Bloch が <a href="http://googleresearch.blogspot.com/2006/06/extra-extra
<![CDATA[
<p>
このメソッドは、ロックを保持して、<code>Thread.sleep()</code> を呼び出しています。
-他のスレッドがロックを獲得するために待機しているかもしれないので、ひどい性能とスケーラビリティ、またはデッドロックになるかもしれません。
+他のスレッドがロックを獲得するために待機しているかもしれないので、ひどい性能とスケーラビリティ、またはデッドロックの原因になるかもしれません。
ロックで <code>wait</code> メソッドを呼び出すことはかなり良い考えで、ロックを解除して他のスレッドが実行するのを許可します。
</p>
]]>
@@ -7952,7 +8529,7 @@ Joshua Bloch が <a href="http://googleresearch.blogspot.com/2006/06/extra-extra
<![CDATA[
<p>
このメソッドは、switch 文の2つの case を実装するために同じコードを使用しています。
-複製コードの case かもしれないしコーディングミスかもしれません。
+複製コードの case かもしれないし、コーディングミスかもしれません。
</p>
]]>
</Details>
@@ -7965,8 +8542,8 @@ Joshua Bloch が <a href="http://googleresearch.blogspot.com/2006/06/extra-extra
<![CDATA[
<p>
この内部クラスのメソッドは、所有クラスの private メンバー変数への読み書きか、所有クラスの private メソッドを呼び出しています。
-コンパイラはこの private メンバーにアクセスするために特別なメソッドを生成しなければなりないので、効率を悪化させる原因になります。
-メンバー変数またはメソッドの保護を緩和することは、コンパイラが一般にのアクセスとして扱うのを許可します。
+コンパイラはこの private メンバーにアクセスするための特別なメソッドを生成しなければなりないので、効率を悪化させる原因になります。
+メンバー変数またはメソッドの保護を緩和することは、コンパイラが正常なアクセスとして扱うのを許可します。
</p>
]]>
</Details>
@@ -7979,7 +8556,7 @@ Joshua Bloch が <a href="http://googleresearch.blogspot.com/2006/06/extra-extra
<![CDATA[
<p>
このメソッドは、XMLインタフェースの特定の実装のインスタンスを作成しています。
-実装が実行時に変更できるように、これらのオブジェクトを作成するために提供されたファクトリクラスを使うことが望ましいです。<br>
+提供されたファクトリクラスを使用してオブジェクトを作成して実行時に実装を変更できるようにすることが望ましいです。<br>
詳細は、以下を参照してください。
</p>
<ul>
@@ -8006,12 +8583,12 @@ Joshua Bloch が <a href="http://googleresearch.blogspot.com/2006/06/extra-extra
</BugPattern>
<BugPattern type="USM_USELESS_ABSTRACT_METHOD">
- <ShortDescription>実装されたインタフェースですでに定義された抽象メソッド</ShortDescription>
- <LongDescription>抽象メソッド {1} は、実装されたインタフェースですでに定義されています。</LongDescription>
+ <ShortDescription>実装されたインタフェースで既に定義された抽象メソッド</ShortDescription>
+ <LongDescription>抽象メソッド {1} は、実装されたインタフェースで既に定義されています。</LongDescription>
<Details>
<![CDATA[
<p>
-この抽象メソッドは、この抽象クラスによって実装されるインタフェースですでに定義されています。
+この抽象メソッドは、この抽象クラスによって実装されるインタフェースで既に定義されています。
このメソッドは、付加価値が与えられないので除去できます。
</p>
]]>
@@ -8064,7 +8641,7 @@ Joshua Bloch が <a href="http://googleresearch.blogspot.com/2006/06/extra-extra
<![CDATA[
<p>
総称型パラメータからの特定の型が予想される Object 型をコンパイルするとき、総称型コレクションメソッドへの呼び出しは引数を渡します。
-したがって、標準の Java 型システムも静的解析もパラメータとして渡されているオブジェクトが適切な型かどうかに関する有効な情報を提供できません。
+したがって、標準の Java 型システムも静的解析もパラメータとして渡されているオブジェクトが適切な型かどうかに関する有用な情報を提供できません。
</p>
]]>
</Details>
@@ -8079,7 +8656,7 @@ Joshua Bloch が <a href="http://googleresearch.blogspot.com/2006/06/extra-extra
総称型コレクションメソッドへの呼び出しにコレクションのパラメータとは互換性のないクラスの引数があります (すなわち、引数の型は総称型引数に対応するスーパタイプでもサブタイプでもありません)。
したがって、コレクションにはここで使用されたメソッド引数と等価であるどんなオブジェクトも含まれていません。
多分間違った値がメソッドに渡されています。
-一般に、2つの無関係なクラスのインスタンスは等価ではありません。
+一般的に2つの無関係なクラスのインスタンスは等価ではありません。
たとえば、<code>Foo</code> と <code>Bar</code> クラスがサブタイプによって関係がないなら、<code>Foo</code> のインスタンスは <code>Bar</code> のインスタンスと等価のはずがありません。
その他の問題で対称的ではない <code>equals</code> メソッドになる可能性が高いです。
たとえば、<code>Foo</code> が <code>String</code> と等価であるように <code>Foo</code> クラスを定義するなら、<code>String</code> は <code>String</code> だけと等価であるので、<code>equals</code> メソッドは対称的ではありません。
@@ -8099,8 +8676,8 @@ APIのどれも文書化していないか、保証もしていないが、<code
<Details>
<![CDATA[
<p>
-この総称型コレクションメソッドへの呼び出しはコレクションに自分自身が含まれている (たとえば、<code>s.contains(s)</code> が true だとして) 場合にだけ意味があります。
-これは true である可能性が低くて、もし true なら問題の原因になります (たとえば、無限再帰になっているハッシュコードの計算)。
+この総称型コレクションメソッドへの呼び出しはコレクションに自分自身が含まれている場合 (たとえば、<code>s.contains(s)</code> が true) にだけ意味があります。
+これが本当だとは思えないし、もし本当なら問題の原因になります (たとえば、無限再帰になっているハッシュコードの計算)。
間違ったパラメータが渡されている可能性が高いです。
</p>
]]>
@@ -8150,7 +8727,7 @@ Java 1.6 の時点で、IdentityHashMap と EnumMap の両方がそうしまし
]]>
</Details>
</BugPattern>
-
+
<BugPattern type="DMI_USING_REMOVEALL_TO_CLEAR_COLLECTION">
<ShortDescription>コレクションを消去するために removeAll メソッドを使用しない</ShortDescription>
<LongDescription>コレクションを消去するために removeAll メソッドを使用しています。{1}</LongDescription>
@@ -8173,7 +8750,7 @@ Java 1.6 の時点で、IdentityHashMap と EnumMap の両方がそうしまし
たとえ JavaDoc にそれに関する手がかりがないとしても、Calendar はマルチスレッドでの使用は本質的に安全でありません。
正しい同期化をしないでスレッド境界の向こうで1つのインスタンスを共有することは、アプリケーションの誤動作になります。
JDK 5.0に比べて JDK 1.4 のほうが問題が表面化するように思われ、おそらく sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate() の ArrayIndexOutOfBoundsExceptions や IndexOutOfBoundsExceptions がランダムに発生します。
-直列化問題も経験するかもしれません。インスタンスフィールドを使うことを推奨します。<br>
+直列化問題も経験するかもしれません。インスタンスフィールドを使用することを推奨します。<br>
詳細については、<a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6231579">Sun Bug #6231579</a> や <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6178997">Sun Bug #6178997</a> を参照してください。
</p>
]]>
@@ -8201,10 +8778,10 @@ JDK 5.0に比べて JDK 1.4 のほうが問題が表面化するように思わ
<Details>
<![CDATA[
<p>
-JavaDoc に書かれているように、DateFormat はマルチスレッドでの使用は本質的に安全ではありません。
+JavaDoc に書かれているように DateFormat はマルチスレッドでの使用は本質的に安全ではありません。
正しい同期化をしないでスレッド境界の向こうで1つのインスタンスを共有することは、アプリケーションの誤動作になります。
JDK 5.0に比べて JDK 1.4 のほうが問題が表面化するように思われ、おそらく sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate() の ArrayIndexOutOfBoundsExceptions や IndexOutOfBoundsExceptions がランダムに発生します。
-直列化問題も経験するかもしれません。インスタンスフィールドを使うことを推奨します。<br>
+直列化問題も経験するかもしれません。インスタンスフィールドを使用することを推奨します。<br>
詳細については、<a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6231579">Sun Bug #6231579</a> や <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6178997">Sun Bug #6178997</a> を参照してください。
</p>
]]>
@@ -8217,7 +8794,7 @@ JDK 5.0に比べて JDK 1.4 のほうが問題が表面化するように思わ
<Details>
<![CDATA[
<p>
-JavaDoc に書かれているように、DateFormat はマルチスレッドでの使用は本質的に安全ではありません。
+JavaDoc に書かれているように DateFormat はマルチスレッドでの使用は本質的に安全ではありません。
ディテクタは、static フィールドから得られた DateFormat のインスタンスの呼び出しを発見しました。
これは疑わしく見えます。
詳細については、<a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6231579">Sun Bug #6231579</a> や <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6178997">Sun Bug #6178997</a> を参照してください。
@@ -8238,7 +8815,7 @@ JavaDoc に書かれているように、DateFormat はマルチスレッドで
より正確に、when=ALWAYS を指定した型修飾子でアノテートされた値が同じ型修飾子で when=NEVER を指定する値と比較しています。
</p>
<p>
-たとえば、@NonNegative が型修飾子アノテーション @Negative(when=When.NEVER) の略称だとします。
+たとえば、@NonNegative は型修飾子アノテーション @Negative(when=When.NEVER) の略称とします。
以下のコードは、return 文が @NonNegative 値を要求するが、@Negative としてマークされている値を受け取るのでこの警告を生成します。
</p>
<blockquote><pre>
@@ -8256,13 +8833,13 @@ public boolean example(@Negative Integer value1, @NonNegative Integer value2) {
<Details>
<![CDATA[
<p>
-型修飾子であのてーとされた値がその修飾子を付けてはならない値を必要とする場所で使われています。
+型修飾子でアノテートされた値がその修飾子を付けてはならない値を必要とする場所で使われています。
</p>
<p>
より正確に、when=ALWAYS を指定した型修飾子でアノテートされた値が到達することが保証されているか同じ型修飾子で when=NEVER を指定する場所で使用しています。
</p>
<p>
-たとえば、@NonNegative が型修飾子アノテーション @Negative(when=When.NEVER) の略称だとします。
+たとえば、@NonNegative は型修飾子アノテーション @Negative(when=When.NEVER) の略称とします。
以下のコードは、return 文が @NonNegative 値を要求するが @Negative としてマークされている値を受け取るのでこの警告を生成します。
</p>
<blockquote><pre>
@@ -8284,7 +8861,7 @@ public @NonNegative Integer example(@Negative Integer value) {
</p>
<p>
厳密なアノテーションを指定しているので値を型変換します。戻り値が厳密なアノテーションでアノテートされる同一性機能を定義してください。
-これは、厳密な型修飾子アノテーションで非アノテート値を値に変える唯一の方法です。
+これは厳密な型修飾子アノテーションで非アノテート値を値に変える唯一の方法です。
</p>
]]>
</Details>
@@ -8366,7 +8943,7 @@ public @NonNegative Integer example(@Negative Integer value) {
<![CDATA[
<p>
このコードは、ファイルを追加モードで開いて、オブジェクト出力ストリームの中で結果をラップしています。
-これは、ファイルに格納された既存のオブジェクト出力ストリームに追加できないでしょう。
+これはファイルに格納された既存のオブジェクト出力ストリームに追加できないでしょう。
オブジェクト出力ストリームに追加したいなら、オブジェクト出力ストリームを開いておく必要があります。
</p>
<p>
@@ -8424,10 +9001,10 @@ Jason Mehrens によって寄贈されたバグパターン
<Details>
<![CDATA[
<p>
-このメソッドは、ストリーム、データベースオブジェクト、または明示的にクリーンアップ操作を必要としている他のリソースのクリーンアップ (クローズする、片付ける) に失敗するかもしれません。
+このメソッドは、ストリーム、データベースオブジェクト、またはクリーンアップ操作を明示的に必要としている他のリソースのクリーンアップ (クローズする、片付ける) に失敗するかもしれません。
</p>
<p>
-一般に、メソッドがストリープや他のリソースを開いたなら、メソッドはストリームやリソースがメソッドが戻る前にクリーンアップされることを確認するために、try/finally ブロックを使用するべきです。
+一般的にメソッドがストリープや他のリソースを開いたなら、メソッドはストリームやリソースがメソッドが戻る前にクリーンアップされることを確認するために try/finally ブロックを使用するべきです。
</p>
<p>
このバグパターンは、OS_OPEN_STREAM と ODR_OPEN_DATABASE_RESOURCE と基本的に同じですが異なる (そして、うまくいけばより良い) 静的解析技術に基づいています。
@@ -8454,10 +9031,10 @@ Jason Mehrens によって寄贈されたバグパターン
<Details>
<![CDATA[
<p>
-このメソッドは、ストリーム、データベースオブジェクト、または明示的にクリーンアップ操作を必要としている他のリソースのクリーンアップ (クローズする、片付ける) に失敗するかもしれません。
+このメソッドは、ストリーム、データベースオブジェクト、またはクリーンアップ操作を明示的必要としている他のリソースのクリーンアップ (クローズする、片付ける) に失敗するかもしれません。
</p>
<p>
-一般に、メソッドがストリープや他のリソースを開いたなら、メソッドはストリームやリソースがメソッドが戻る前にクリーンアップされることを確認するために、try/finally ブロックを使用するべきです。
+一般的にメソッドがストリープや他のリソースを開いたなら、メソッドはストリームやリソースがメソッドが戻る前にクリーンアップされることを確認するために try/finally ブロックを使用するべきです。
</p>
<p>
このバグパターンは、OS_OPEN_STREAM と ODR_OPEN_DATABASE_RESOURCE と基本的に同じですが異なる (そして、うまくいけばより良い) 静的解析技術に基づいています。
@@ -8477,7 +9054,7 @@ Jason Mehrens によって寄贈されたバグパターン
]]>
</Details>
</BugPattern>
-
+
<BugPattern type="FB_UNEXPECTED_WARNING">
<ShortDescription>FindBugs からの予期しない/望ましくない警告</ShortDescription>
<LongDescription>予期しない/望ましくない {2} FindBugs 警告。{1}</LongDescription>
@@ -8508,9 +9085,9 @@ FindBugs は、@ExpectedWarning でアノテートされたことにより予期
<Details>
<![CDATA[
<p>
-<code>putIfAbsent</code> メソッドは、一般に1つの値が与えられたキー (非存在が成功するかどうかの第一の値) と関連することを確認するために使われます。
+<code>putIfAbsent</code> メソッドは、1つの値が与えられたキー (非存在が成功するかどうかの第一の値) と関連することを確認するために使われます。
戻り値を無視して中で渡される値への参照を保持するなら、マップのキーと関連する1つではない値を保持する危険性を冒します。
-どれを使用するかが重要であり、マップに格納できないものを使用すると、プログラムは誤った振る舞いをします。
+どれを使用するかが重要であり、マップに格納できないものを使うとプログラムは誤った振る舞いをします。
</p>
]]>
</Details>
@@ -8523,7 +9100,7 @@ FindBugs は、@ExpectedWarning でアノテートされたことにより予期
<![CDATA[
<p>
OpenJDK は、潜在的非互換性を取り入れました。特に、<code>java.util.logging.Logger</code> は振る舞いが変更されています。
-強参照を使用する代わりに、現在、内部的に弱参照を使用しています。
+強参照を使用する代わりに弱参照を内部的に使用しています。
それは理にかなった変更ですが、残念ながらいくつかのコードは古い振る舞いに依存しています。
ロガーの構成を変更するとき、ロガーへの参照を捨てます。
つまり、ガベージコレクタはそのメモリを回収できます。それは、ロガーの構成が失われることを意味します。<br>
@@ -8573,50 +9150,50 @@ Ulf Ochsenfahrt と Eric Fellheimer
<Details>
<![CDATA[
<p>
-byte から String (または String から byte) への変換で、デフォルトプラットホームエンコーディングが適切であると仮定するメソッドの呼び出しを発見しました。
-これは、アプリケーションの振る舞いがプラットホーム間で異なる原因となります。代替 API を使用して、明示的に文字セット名または Charset オブジェクトを指定して下さい。
+byte から String (または String から byte) への変換で、デフォルトプラットホームエンコーディングが適切だと仮定するメソッドの呼び出しを発見しました。
+これはアプリケーションの振る舞いがプラットホーム間で異なる原因となります。代替 API を使用して、文字セット名または Charset オブジェクトを明示的に指定して下さい。
</p>
]]>
</Details>
</BugPattern>
<BugPattern type="NP_METHOD_PARAMETER_RELAXING_ANNOTATION">
- <ShortDescription>メソッドはパラメータで nullness アノテーションを強化する</ShortDescription>
- <LongDescription>メソッド {1} は、パラメータで祖先メソッドの要件を緩和している nullness アノテーションをオーバライドしています。</LongDescription>
+ <ShortDescription>メソッドはパラメータに nullness アノテーションを強化している</ShortDescription>
+ <LongDescription>メソッド {1} は、祖先メソッドの要件を緩和する nullness アノテーションをオーバーライドしています。</LongDescription>
<Details>
<![CDATA[
<p>
-メソッドは、オーバライドするメソッドの規約を常に実装するべきです。
+メソッドは、オーバーライドするメソッドの契約を常に実装するべきです。
したがって、メソッドが @Nullable としてマークされるパラメーターを取るならば、サブクラスでパラメーターを @Nonnull にしてメソッドをオーバーライドするべきでありません。
-そうするこによって、メソッドが null パラメーターを扱うべきである規約に違反します。
+そうするとメソッドが null パラメータを処理すべき契約を破ります。
</p>
]]>
</Details>
</BugPattern>
<BugPattern type="NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION">
- <ShortDescription>メソッドはパラメータで nullness アノテーションを強化する</ShortDescription>
- <LongDescription>メソッド {1} は、互換性のない方法でパラメーター {2} の nullness アノテーションをオーバーライドしています。</LongDescription>
+ <ShortDescription>メソッドはパラメータに nullness アノテーションを強化している</ShortDescription>
+ <LongDescription>メソッド {1} は、互換性がない方法で nullness アノテーションのパラメータ {2} をオーバーライドしています。</LongDescription>
<Details>
<![CDATA[
<p>
-メソッドは、オーバライドするメソッドの規約を常に実装するべきです。
+メソッドは、オーバーライドするメソッドの契約を常に実装するべきです。
したがって、メソッドが @Nullable としてマークされるパラメーターを取るならば、サブクラスでパラメーターを @Nonnull にしてメソッドをオーバーライドするべきでありません。
-そうするこによって、メソッドが null パラメーターを扱うべきである規約に違反します。
+そうするとメソッドが null パラメータを処理すべき契約を破ります。
</p>
]]>
</Details>
</BugPattern>
<BugPattern type="NP_METHOD_RETURN_RELAXING_ANNOTATION">
- <ShortDescription>メソッドは戻り値で nullness アノテーションを緩和させる</ShortDescription>
- <LongDescription>メソッド {1} は、互換性のない方法で戻り値の nullness アノテーションをオーバーライドしています。</LongDescription>
+ <ShortDescription>メソッドは戻り値の nullness アノテーションを緩和している</ShortDescription>
+ <LongDescription>メソッド {1} は、互換性がない方法で戻り値の nullness アノテーションをオーバーライドしています。</LongDescription>
<Details>
<![CDATA[
<p>
-メソッドは、オーバライドするメソッドの規約を常に実装するべきです。
+メソッドは、オーバーライドするメソッドの契約を常に実装するべきです。
したがって、メソッドが @Nonnull 値を返すようにアノテートしているならば、サブクラスでメソッドが @Nullable または @CheckForNull 値を返すようにアノテートしてメソッドをオーバーライドするべきでありません。
-そうするこによって、メソッドが null を返すべきでない規約に違反します。
+そうするとメソッドが null を返すべできではない契約を破ります。
</p>
]]>
</Details>
@@ -8636,6 +9213,7 @@ byte から String (または String から byte) への変換で、デフォル
<BugCode abbrev="TEST">プロトタイプと未完成のバグパターンのテスト</BugCode>
<BugCode abbrev="IMSE">疑わしい IllegalMonitorStateException のキャッチ</BugCode>
<BugCode abbrev="CN">クローン可能イディオムの間違った実装</BugCode>
+ <BugCode abbrev="CAA">共変配列代入</BugCode>
<BugCode abbrev="AT">原子性違反の可能性</BugCode>
<BugCode abbrev="FI">ファイナライザの間違った使用</BugCode>
<BugCode abbrev="ES">== や != を使用している文字列の等価性チェック</BugCode>
@@ -8657,7 +9235,7 @@ byte から String (または String から byte) への変換で、デフォル
<BugCode abbrev="NN">裸の notify()</BugCode>
<BugCode abbrev="UW">無条件の wait()</BugCode>
<BugCode abbrev="SP">スピンロック</BugCode>
- <BugCode abbrev="DC">フィールドのダブルチェックの可能性</BugCode>
+ <BugCode abbrev="DC">ダブルチェックパターン</BugCode>
<BugCode abbrev="Wa">ループの中にない wait()</BugCode>
<BugCode abbrev="No">notifyAll() ではなく notify() を使用している</BugCode>
<BugCode abbrev="DE">捨てられたか無視された例外</BugCode>
@@ -8669,6 +9247,7 @@ byte から String (または String から byte) への変換で、デフォル
<BugCode abbrev="RS">readObject() を同期化している</BugCode>
<BugCode abbrev="SC">Thread.start() を呼び出すコンストラクタ</BugCode>
<BugCode abbrev="MS">可変 static フィールド</BugCode>
+ <BugCode abbrev="ME">可変列挙型フィールド</BugCode>
<BugCode abbrev="EI">内部表現を暴露するかもしれない配列を返すメソッド</BugCode>
<BugCode abbrev="Nm">紛らわしいメソッド名</BugCode>
<BugCode abbrev="SS">読み出されないフィールドは static にすべき</BugCode>
@@ -8677,6 +9256,7 @@ byte から String (または String から byte) への変換で、デフォル
<BugCode abbrev="UwF">書き込まれないフィールド</BugCode>
<BugCode abbrev="SIC">static にできる内部クラス</BugCode>
<BugCode abbrev="TLW">2つのロックを保持する wait()</BugCode>
+ <BugCode abbrev="RANGE">範囲チェック</BugCode>
<BugCode abbrev="RV">メソッドからの戻り値の間違った使用</BugCode>
<BugCode abbrev="LG">Logger の問題</BugCode>
<BugCode abbrev="IA">あいまいな呼び出し</BugCode>
@@ -8706,6 +9286,8 @@ byte から String (または String から byte) への変換で、デフォル
<BugCode abbrev="NS">疑わしい非短絡論理演算子の使用</BugCode>
<BugCode abbrev="ODR">すべての経路でクローズされないデータベースリソース</BugCode>
<BugCode abbrev="SBSC">ループの中で + 演算子を使用した文字列連結</BugCode>
+ <BugCode abbrev="IIL">ループの外に移動できる非効率なコード</BugCode>
+ <BugCode abbrev="IIO">非効率な String.indexOf(String) または String.lastIndexOf(String) の使用</BugCode>
<BugCode abbrev="ITA">効率が悪い collection.toArray(new Foo[0]) の使用</BugCode>
<BugCode abbrev="SW">Swing コーディング規約</BugCode>
<BugCode abbrev="IJU">誤って実装された JUnit TestCase</BugCode>
@@ -8723,6 +9305,8 @@ byte から String (または String から byte) への変換で、デフォル
<BugCode abbrev="REC">RuntimeException の捕捉</BugCode>
<BugCode abbrev="FE">浮動小数点の等価性テスト</BugCode>
<BugCode abbrev="UM">定数に関する不必要な Math</BugCode>
+ <BugCode abbrev="UC">役に立たないコード</BugCode>
+ <BugCode abbrev="CNT">既知の定数の雑な値</BugCode>
<BugCode abbrev="CD">循環依存関係</BugCode>
<BugCode abbrev="RI">冗長なインタフェース</BugCode>
<BugCode abbrev="MTIA">マルチスレッドでのインスタンスアクセス</BugCode>
diff --git a/etc/summarizeBugs b/etc/summarizeBugs
old mode 100644
new mode 100755
diff --git a/findbugsExclude.xml b/findbugsExclude.xml
index 3b49417..c155659 100644
--- a/findbugsExclude.xml
+++ b/findbugsExclude.xml
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<FindBugsFilter>
+<FindBugsFilter xmlns="http://findbugs.sourceforge.net/filter/3.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://findbugs.sourceforge.net/filter/3.0.0 https://findbugs.googlecode.com/git/findbugs/etc/findbugsfilter.xsd">
+
<Match>
<Bug pattern="DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED,NM_CLASS_NOT_EXCEPTION,EI_EXPOSE_REP,EI_EXPOSE_REP2,MS_PKGPROTECT,MS_MUTABLE_ARRAY"/>
</Match>
@@ -20,85 +23,50 @@
<Bug pattern="DM_EXIT"/>
</Match>
<Match>
- <Priority value="3"/>
- </Match>
- <Match>
<BugCode name="Se"/>
<Class name="~edu.umd.cs.findbugs.gui.*"/>
</Match>
<Match>
<Class name="~edu.umd.cs.findbugs.*Test"/>
</Match>
+
<Match>
- <BugCode name="Se"/>
+ <Or>
+ <BugCode name="Se"/>
+ <Bug pattern="SE_NO_SERIALVERSIONID"/>
+ </Or>
<Class name="~edu.umd.cs.findbugs.gui2.*"/>
</Match>
- <Match>
- <Class name="edu.umd.cs.findbugs.ba.DFSEdgeTypes"/>
- <Bug pattern="NM_SAME_SIMPLE_NAME_AS_INTERFACE"/>
- </Match>
- <Match>
- <Class name="edu.umd.cs.findbugs.ba.DepthFirstSearch"/>
- <Bug pattern="NM_SAME_SIMPLE_NAME_AS_SUPERCLASS"/>
- </Match>
- <Match>
- <Class name="edu.umd.cs.findbugs.ba.ReverseDepthFirstSearch"/>
- <Bug pattern="NM_SAME_SIMPLE_NAME_AS_SUPERCLASS"/>
- </Match>
- <Match>
- <Class name="edu.umd.cs.findbugs.detect.IncompatMask"/>
- <Bug pattern="SF_SWITCH_FALLTHROUGH"/>
- </Match>
- <Match>
- <Class name="edu.umd.cs.findbugs.detect.TestingGround"/>
- <Bug pattern="URF_UNREAD_FIELD"/>
- </Match>
- <Match>
- <Class name="edu.umd.cs.findbugs.jaif.JAIFToken"/>
- <Bug pattern="URF_UNREAD_FIELD"/>
- </Match>
- <Match>
- <Bug pattern="OS_OPEN_STREAM"/>
- <Class name="edu.umd.cs.findbugs.util.Util"/>
- </Match>
- <Match>
- <Bug pattern="URF_UNREAD_FIELD"/>
- <Class name="edu.umd.cs.findbugs.classfile.engine.ClassParser"/>
- </Match>
- <Match>
- <Bug pattern="URF_UNREAD_FIELD"/>
- <Class name="edu.umd.cs.findbugs.classfile.engine.ClassParserUsingASM$1$2"/>
- </Match>
- <And>
- <Bug pattern="OBL_UNSATISFIED_OBLIGATION"/>
- <Class name="edu.umd.cs.findbugs.gui2.MainFrame"/>
- </And>
- <And>
- <Bug pattern="OBL_UNSATISFIED_OBLIGATION"/>
- <Class name="edu.umd.cs.findbugs.ml.GenerateUIDs"/>
- </And>
- <And>
- <Bug pattern="OBL_UNSATISFIED_OBLIGATION"/>
- <Class name="edu.umd.cs.findbugs.userAnnotations.ri.XMLFileUserAnnotationPlugin"/>
- </And>
- <Match>
- <Bug pattern="OBL_UNSATISFIED_OBLIGATION"/>
- <Class name="edu.umd.cs.findbugs.util.Util"/>
- </Match>
+
<Match>
- <Bug pattern="OBL_UNSATISFIED_OBLIGATION"/>
- <Class name="edu.umd.cs.findbugs.workflow.RejarClassesForAnalysis"/>
+ <Class name="edu.umd.cs.findbugs.ba.DFSEdgeTypes" />
+ <Bug pattern="NM_SAME_SIMPLE_NAME_AS_INTERFACE" />
</Match>
<Match>
- <Bug pattern="OBL_UNSATISFIED_OBLIGATION"/>
- <Class name="edu.umd.cs.findbugs.xml.OutputStreamXMLOutput"/>
+ <Class name="edu.umd.cs.findbugs.ba.DepthFirstSearch" />
+ <Bug pattern="NM_SAME_SIMPLE_NAME_AS_SUPERCLASS" />
</Match>
<Match>
- <Bug pattern="URF_UNREAD_FIELD"/>
- <Class name="edu.umd.cs.findbugs.classfile.engine.ClassParserUsingASM$1"/>
+ <Class name="edu.umd.cs.findbugs.ba.ReverseDepthFirstSearch" />
+ <Bug pattern="NM_SAME_SIMPLE_NAME_AS_SUPERCLASS" />
</Match>
- <Match>
- <Bug pattern="URF_UNREAD_FIELD"/>
- <Class name="edu.umd.cs.findbugs.userAnnotations.SimpleWebPlugin"/>
+
+ <Match>
+ <And>
+ <Priority value="3"/>
+ <Or>
+ <Bug pattern="DM_CONVERT_CASE"/>
+ <Bug pattern="SE_COMPARATOR_SHOULD_BE_SERIALIZABLE"/>
+ <Bug pattern="SE_NO_SERIALVERSIONID" />
+ <Bug pattern="URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD"/>
+ <Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON" />
+ <Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE" />
+ <Bug pattern="BC_UNCONFIRMED_CAST" />
+ <Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" />
+ <Bug pattern="NM_CONFUSING" />
+ <Rank value="20"/>
+ </Or>
+ </And>
</Match>
+
</FindBugsFilter>
diff --git a/jnlp/core.jnlp b/jnlp/core.jnlp
old mode 100644
new mode 100755
diff --git a/pom.xml b/pom.xml
index 15b39c7..f791d07 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,11 +4,12 @@
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>7</version>
+ <relativePath></relativePath>
</parent>
<groupId>com.google.code.findbugs</groupId>
<artifactId>findbugs</artifactId>
- <version>2.0.3-SNAPSHOT</version>
+ <version>3.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<url>http://findbugs.sourceforge.net/</url>
@@ -29,9 +30,9 @@
<scm>
- <connection>scm:svn:http://findbugs.googlecode.com/svn/trunk/</connection>
- <developerConnection>scm:svn:https://findbugs.googlecode.com/svn/trunk/</developerConnection>
- <url>http://findbugs.googlecode.com/svn/trunk/</url>
+ <connection>scm:git:http://code.google.com/p/findbugs/</connection>
+ <developerConnection>scm:git:https://code.google.com/p/findbugs/</developerConnection>
+ <url>https://code.google.com/p/findbugs/</url>
</scm>
<developers>
@@ -158,10 +159,19 @@
</roles>
<timezone>-5</timezone>
</contributor>
+ <contributor>
+ <name>Tagir Valeev</name>
+ <email></email>
+ <url></url>
+ <roles>
+ <role></role>
+ </roles>
+ <timezone>+6</timezone>
+ </contributor>
</contributors>
<properties>
- <asmVersion>3.3</asmVersion>
+ <asmVersion>5.0.2</asmVersion>
<junitVersion>4.11</junitVersion>
</properties>
@@ -178,8 +188,8 @@
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
- <artifactId>bcel</artifactId>
- <version>2.0.1</version>
+ <artifactId>bcel-findbugs</artifactId>
+ <version>6.0</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
@@ -198,12 +208,12 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>asm</groupId>
- <artifactId>asm</artifactId>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-debug-all</artifactId>
<version>${asmVersion}</version>
</dependency>
<dependency>
- <groupId>asm</groupId>
+ <groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
<version>${asmVersion}</version>
</dependency>
@@ -298,11 +308,19 @@
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ <configuration>
+ <sourcepath>src/java</sourcepath>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
- <source>1.5</source>
- <target>1.5</target>
+ <source>1.7</source>
+ <target>1.7</target>
<excludes>
<exclude>**/junit/**</exclude>
<exclude>**/infonodeJava/**</exclude>
diff --git a/runMaven b/runMaven
new file mode 100755
index 0000000..d002795
--- /dev/null
+++ b/runMaven
@@ -0,0 +1,5 @@
+#! /bin/sh
+mvn install:install-file -Dfile=lib/bcel-6.0-SNAPSHOT.jar -DgroupId=com.google.code.findbugs -DartifactId=bcel -Dversion=6.0-SNAPSHOT -Dpackaging=jar
+mvn install:install-file -Dfile=lib/asm-debug-all-5.0.2.jar -DgroupId=org.ow2.asm -DartifactId=asm-debug-all -Dversion=5.0.2 -Dpackaging=jar
+mvn clean
+mvn package
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/AbstractFindBugsTask.java b/src/antTask/edu/umd/cs/findbugs/anttask/AbstractFindBugsTask.java
index 4a0714d..70af8ef 100644
--- a/src/antTask/edu/umd/cs/findbugs/anttask/AbstractFindBugsTask.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/AbstractFindBugsTask.java
@@ -33,7 +33,7 @@ import org.apache.tools.ant.types.Reference;
/**
* Abstract base class for Ant tasks that run programs (main() methods) in
* findbugs.jar or findbugsGUI.jar.
- *
+ *
* @author David Hovemeyer
*/
public abstract class AbstractFindBugsTask extends Task {
@@ -69,7 +69,7 @@ public abstract class AbstractFindBugsTask extends Task {
}
}
- private String mainClass;
+ private final String mainClass;
private boolean debug = false;
@@ -83,9 +83,9 @@ public abstract class AbstractFindBugsTask extends Task {
private boolean failOnError = false;
- private String errorProperty = null;
+ protected String errorProperty = null;
- private List<SystemProperty> systemPropertyList = new ArrayList<SystemProperty>();
+ private final List<SystemProperty> systemPropertyList = new ArrayList<SystemProperty>();
private Path classpath = null;
@@ -140,7 +140,7 @@ public abstract class AbstractFindBugsTask extends Task {
/**
* Set timeout in milliseconds.
- *
+ *
* @param timeout
* the timeout
*/
@@ -200,7 +200,7 @@ public abstract class AbstractFindBugsTask extends Task {
Path path = createClasspath();
path.setRefid(r);
path.toString(); // Evaluated for its side-effects (throwing a
- // BuildException)
+ // BuildException)
}
/**
@@ -268,8 +268,9 @@ public abstract class AbstractFindBugsTask extends Task {
}
for (SystemProperty systemProperty : systemPropertyList) {
- if (systemProperty.getName() == null || systemProperty.getValue() == null)
+ if (systemProperty.getName() == null || systemProperty.getValue() == null) {
throw new BuildException("systemProperty elements must have name and value attributes");
+ }
}
}
@@ -282,8 +283,9 @@ public abstract class AbstractFindBugsTask extends Task {
findbugsEngine.setProject(getProject());
findbugsEngine.setTaskName(getTaskName());
findbugsEngine.setFork(true);
- if (jvm.length() > 0)
+ if (jvm.length() > 0) {
findbugsEngine.setJvm(jvm);
+ }
findbugsEngine.setTimeout(timeout);
if (debug) {
@@ -302,16 +304,17 @@ public abstract class AbstractFindBugsTask extends Task {
// Use findbugs.home to locate findbugs.jar and the standard
// plugins. This is the usual means of initialization.
File findbugsLib = new File(homeDir, "lib");
- if (!findbugsLib.exists() && homeDir.getName().equals("lib")) {
+ if (!findbugsLib.exists() && "lib".equals(homeDir.getName())) {
findbugsLib = homeDir;
homeDir = homeDir.getParentFile();
}
File findbugsLibFindBugs = new File(findbugsLib, "findbugs.jar");
// log("executing using home dir [" + homeDir + "]");
- if (findbugsLibFindBugs.exists())
+ if (findbugsLibFindBugs.exists()) {
findbugsEngine.setClasspath(new Path(getProject(), findbugsLibFindBugs.getPath()));
- else
+ } else {
throw new IllegalArgumentException("Can't find findbugs.jar in " + findbugsLib);
+ }
findbugsEngine.createJvmarg().setValue("-Dfindbugs.home=" + homeDir.getPath());
} else {
// Use an explicitly specified classpath and list of plugin Jars
@@ -338,7 +341,7 @@ public abstract class AbstractFindBugsTask extends Task {
/**
* Add an argument to the JVM used to execute FindBugs.
- *
+ *
* @param arg
* the argument
*/
@@ -356,7 +359,7 @@ public abstract class AbstractFindBugsTask extends Task {
/**
* Create a new JVM to do the work.
- *
+ *
* @since Ant 1.5
*/
private void execFindbugs() throws BuildException {
@@ -404,8 +407,9 @@ public abstract class AbstractFindBugsTask extends Task {
protected abstract void beforeExecuteJavaProcess();
protected void afterExecuteJavaProcess(int rc) {
- if (rc != 0)
+ if (rc != 0) {
throw new BuildException("execution of " + getTaskName() + " failed");
+ }
}
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/ComputeBugHistoryTask.java b/src/antTask/edu/umd/cs/findbugs/anttask/ComputeBugHistoryTask.java
index a64d809..8e78e73 100644
--- a/src/antTask/edu/umd/cs/findbugs/anttask/ComputeBugHistoryTask.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/ComputeBugHistoryTask.java
@@ -27,7 +27,7 @@ import org.apache.tools.ant.BuildException;
/**
* Ant task to create/update a bug history database.
- *
+ *
* @author David Hovemeyer
*/
public class ComputeBugHistoryTask extends AbstractFindBugsTask {
@@ -46,7 +46,7 @@ public class ComputeBugHistoryTask extends AbstractFindBugsTask {
private boolean withMessages;
- private List<DataFile> dataFileList;
+ private final List<DataFile> dataFileList;
public ComputeBugHistoryTask() {
super("edu.umd.cs.findbugs.workflow.Update");
@@ -86,7 +86,7 @@ public class ComputeBugHistoryTask extends AbstractFindBugsTask {
/**
* Called to create DataFile objects in response to nested <DataFile>
* elements.
- *
+ *
* @return new DataFile object specifying the location of an input data file
*/
public DataFile createDataFile() {
@@ -97,7 +97,7 @@ public class ComputeBugHistoryTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#checkParameters()
*/
@Override
@@ -111,7 +111,7 @@ public class ComputeBugHistoryTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#configureFindbugsEngine
* ()
@@ -146,7 +146,7 @@ public class ComputeBugHistoryTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#beforeExecuteJavaProcess
* ()
@@ -158,7 +158,7 @@ public class ComputeBugHistoryTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#afterExecuteJavaProcess
* (int)
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/ConvertXmlToTextTask.java b/src/antTask/edu/umd/cs/findbugs/anttask/ConvertXmlToTextTask.java
old mode 100644
new mode 100755
index 00f98dd..055ce59
--- a/src/antTask/edu/umd/cs/findbugs/anttask/ConvertXmlToTextTask.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/ConvertXmlToTextTask.java
@@ -20,11 +20,14 @@
package edu.umd.cs.findbugs.anttask;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+
+import edu.umd.cs.findbugs.ExitCodes;
/**
* Ant task to generate HTML or plain text from a saved XML analysis results
* file.
- *
+ *
* @author David Hovemeyer
*/
public class ConvertXmlToTextTask extends AbstractFindBugsTask {
@@ -33,6 +36,8 @@ public class ConvertXmlToTextTask extends AbstractFindBugsTask {
private boolean applySuppression;
+ private boolean failIfBugFound;
+
private String input;
private String output;
@@ -101,31 +106,27 @@ public class ConvertXmlToTextTask extends AbstractFindBugsTask {
this.format = format;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#checkParameters()
+ /**
+ * @param failIfBugFound true to 'fail' at the end if at least one bug is reported
*/
+ public void setFailIfBugFound(boolean failIfBugFound) {
+ this.failIfBugFound = failIfBugFound;
+ }
+
@Override
protected void checkParameters() {
if (input == null) {
throw new BuildException("input attribute is required", getLocation());
}
- if (!format.equals("text") && !(format.equals("html") || format.startsWith("html:"))) {
+ if (!"text".equals(format) && !("html".equals(format) || format.startsWith("html:"))) {
throw new BuildException("invalid value " + format + " for format attribute", getLocation());
}
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#configureFindbugsEngine
- * ()
- */
@Override
protected void configureFindbugsEngine() {
+ addArg("-exitcode");
if (format.startsWith("html")) {
addArg("-" + format);
}
@@ -136,36 +137,44 @@ public class ConvertXmlToTextTask extends AbstractFindBugsTask {
addArg("-applySuppression");
}
addArg(input);
- if (output != null)
+ if (output != null) {
addArg(output);
+ }
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#beforeExecuteJavaProcess
- * ()
- */
@Override
protected void beforeExecuteJavaProcess() {
- if (output != null)
+ if (output != null) {
log("Converting " + input + " to " + output + " using format " + format);
- else
+ } else {
log("Converting " + input + " using format " + format);
+ }
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#afterExecuteJavaProcess
- * (int)
- */
@Override
protected void afterExecuteJavaProcess(int rc) {
if (rc == 0) {
log("Success");
+ } else {
+ if (errorProperty != null) {
+ getProject().setProperty(errorProperty, "true");
+ }
+ if ((rc & ExitCodes.ERROR_FLAG) != 0) {
+ String message = "At least one error occured!";
+ if (failIfBugFound) {
+ throw new BuildException(message);
+ } else {
+ log(message, Project.MSG_ERR);
+ }
+ }
+ if ((rc & ExitCodes.BUGS_FOUND_FLAG) != 0) {
+ String message = "At least one unexpected bug is reported!";
+ if (failIfBugFound) {
+ throw new BuildException(message);
+ } else {
+ log(message, Project.MSG_ERR);
+ }
+ }
}
}
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/DataFile.java b/src/antTask/edu/umd/cs/findbugs/anttask/DataFile.java
index e7c1331..78587de 100644
--- a/src/antTask/edu/umd/cs/findbugs/anttask/DataFile.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/DataFile.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.anttask;
/**
* Input file used with ComputeBugHistoryTask or FilterBugsTask.
- *
+ *
* @author David Hovemeyer
*/
public class DataFile {
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/FilterBugsTask.java b/src/antTask/edu/umd/cs/findbugs/anttask/FilterBugsTask.java
index bf92e20..f803638 100644
--- a/src/antTask/edu/umd/cs/findbugs/anttask/FilterBugsTask.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/FilterBugsTask.java
@@ -26,7 +26,7 @@ import org.apache.tools.ant.BuildException;
/**
* Ant task to invoke the FilterBugs program in the workflow package (a.k.a. the
* filterBugs script.)
- *
+ *
* @author David Hovemeyer
*/
public class FilterBugsTask extends AbstractFindBugsTask {
@@ -234,14 +234,14 @@ public class FilterBugsTask extends AbstractFindBugsTask {
return;
}
attrVal = attrVal.toLowerCase();
- if (!attrVal.equals("true") && !attrVal.equals("false")) {
+ if (!"true".equals(attrVal) && !"false".equals(attrVal)) {
throw new BuildException("attribute " + attrName + " requires boolean value", getLocation());
}
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#checkParameters()
*/
@Override
@@ -282,7 +282,7 @@ public class FilterBugsTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#configureFindbugsEngine
* ()
@@ -329,7 +329,7 @@ public class FilterBugsTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#beforeExecuteJavaProcess
* ()
@@ -341,7 +341,7 @@ public class FilterBugsTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#afterExecuteJavaProcess
* (int)
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/FindBugsTask.java b/src/antTask/edu/umd/cs/findbugs/anttask/FindBugsTask.java
index 88083cc..406db86 100644
--- a/src/antTask/edu/umd/cs/findbugs/anttask/FindBugsTask.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/FindBugsTask.java
@@ -62,6 +62,7 @@ import edu.umd.cs.findbugs.ExitCodes;
* of classes and packages - See the textui argument description for details)
* <li>output (enum text|xml|xml:withMessages|html - default xml)
* <li>outputFile (name of output file to create)
+ * <li>nested (boolean default true)
* <li>noClassOk (boolean default false)
* <li>pluginList (list of plugin Jar files to load)
* <li>projectFile (project filename)
@@ -78,6 +79,7 @@ import edu.umd.cs.findbugs.ExitCodes;
* <li>visitors (collection - comma seperated)
* <li>chooseVisitors (selectively enable/disable visitors)
* <li>workHard (boolean default false)
+ * <li>setSetExitCode (boolean default true)
* </ul>
* Of these arguments, the <b>home</b> is required. <b>projectFile</b> is
* required if nested <class> or <auxAnalyzepath> elements are not
@@ -162,6 +164,10 @@ public class FindBugsTask extends AbstractFindBugsTask {
private boolean noClassOk;
+ private boolean nested = true;
+
+ private boolean setExitCode = true;
+
private final List<FileSet> filesets = new ArrayList<FileSet>();
public FindBugsTask() {
@@ -198,6 +204,30 @@ public class FindBugsTask extends AbstractFindBugsTask {
}
/**
+ * Set the exit code flag.
+ *
+ * @param setExitCode
+ * If true then the exit code will be returned to
+ * the main ant job
+ */
+ public void setSetExitCode(boolean setExitCode) {
+ this.setExitCode = setExitCode;
+ }
+
+ /**
+ * Set the nested flag.
+ *
+ * @param nested
+ * This option enables or disables scanning of
+ * nested jar and zip files found in the list of files
+ * and directories to be analyzed. By default, scanning
+ * of nested jar/zip files is enabled
+ */
+ public void setNested(boolean nested) {
+ this.nested = nested;
+ }
+
+ /**
* Set the noClassOk flag.
*
* @param noClassOk
@@ -350,31 +380,33 @@ public class FindBugsTask extends AbstractFindBugsTask {
* Set the exclude filter file
*/
public void setExcludeFilter(File filterFile) {
- if (filterFile != null && filterFile.length() > 0)
-
+ if (filterFile != null && filterFile.length() > 0) {
this.excludeFile = filterFile;
- else
+ } else {
this.excludeFile = null;
+ }
}
/**
* Set the exclude filter file
*/
public void setIncludeFilter(File filterFile) {
- if (filterFile != null && filterFile.length() > 0)
+ if (filterFile != null && filterFile.length() > 0) {
this.includeFile = filterFile;
- else
+ } else {
this.includeFile = null;
+ }
}
/**
* Set the exclude filter file
*/
public void setBaselineBugs(File baselineBugs) {
- if (baselineBugs != null && baselineBugs.length() > 0)
+ if (baselineBugs != null && baselineBugs.length() > 0) {
this.baselineBugs = baselineBugs;
- else
+ } else {
this.baselineBugs = null;
+ }
}
/**
@@ -399,7 +431,7 @@ public class FindBugsTask extends AbstractFindBugsTask {
String[] elementList = src.list();
for (String anElementList : elementList) {
- if (!anElementList.equals("")) {
+ if (!"".equals(anElementList)) {
nonEmpty = true;
break;
}
@@ -431,7 +463,7 @@ public class FindBugsTask extends AbstractFindBugsTask {
Path path = createAuxClasspath();
path.setRefid(r);
path.toString(); // Evaluated for its side-effects (throwing a
- // BuildException)
+ // BuildException)
}
/**
@@ -442,7 +474,7 @@ public class FindBugsTask extends AbstractFindBugsTask {
String[] elementList = src.list();
for (String anElementList : elementList) {
- if (!anElementList.equals("")) {
+ if (!"".equals(anElementList)) {
nonEmpty = true;
break;
}
@@ -515,8 +547,9 @@ public class FindBugsTask extends AbstractFindBugsTask {
* Set name of output file.
*/
public void setOutputFile(String outputFileName) {
- if (outputFileName != null && outputFileName.length() > 0)
+ if (outputFileName != null && outputFileName.length() > 0) {
this.outputFileName = outputFileName;
+ }
}
/**
@@ -545,20 +578,21 @@ public class FindBugsTask extends AbstractFindBugsTask {
+ "elements must be defined for task <" + getTaskName() + "/>", getLocation());
}
- if (cloudId != null && cloudId.contains(" "))
+ if (cloudId != null && cloudId.contains(" ")) {
throw new BuildException("cloudId must not contain spaces: '" + cloudId + "'");
+ }
if (outputFormat != null
- && !(outputFormat.trim().equalsIgnoreCase("xml") || outputFormat.trim().equalsIgnoreCase("xml:withMessages")
- || outputFormat.trim().equalsIgnoreCase("html") || outputFormat.trim().equalsIgnoreCase("text")
- || outputFormat.trim().equalsIgnoreCase("xdocs") || outputFormat.trim().equalsIgnoreCase("emacs"))) {
+ && !("xml".equalsIgnoreCase(outputFormat.trim()) || "xml:withMessages".equalsIgnoreCase(outputFormat.trim())
+ || "html".equalsIgnoreCase(outputFormat.trim()) || "text".equalsIgnoreCase(outputFormat.trim())
+ || "xdocs".equalsIgnoreCase(outputFormat.trim()) || "emacs".equalsIgnoreCase(outputFormat.trim()))) {
throw new BuildException("output attribute must be either " + "'text', 'xml', 'html', 'xdocs' or 'emacs' for task <"
+ getTaskName() + "/>", getLocation());
}
if (reportLevel != null
- && !(reportLevel.trim().equalsIgnoreCase("experimental") || reportLevel.trim().equalsIgnoreCase("low")
- || reportLevel.trim().equalsIgnoreCase("medium") || reportLevel.trim().equalsIgnoreCase("high"))) {
+ && !("experimental".equalsIgnoreCase(reportLevel.trim()) || "low".equalsIgnoreCase(reportLevel.trim())
+ || "medium".equalsIgnoreCase(reportLevel.trim()) || "high".equalsIgnoreCase(reportLevel.trim()))) {
throw new BuildException("reportlevel attribute must be either "
+ "'experimental' or 'low' or 'medium' or 'high' for task <" + getTaskName() + "/>", getLocation());
}
@@ -644,12 +678,14 @@ public class FindBugsTask extends AbstractFindBugsTask {
addArg(adjustPriority);
}
- if (sorted)
+ if (sorted) {
addArg("-sortByClass");
- if (timestampNow)
+ }
+ if (timestampNow) {
addArg("-timestampNow");
+ }
- if (outputFormat != null && !outputFormat.trim().equalsIgnoreCase("text")) {
+ if (outputFormat != null && !"text".equalsIgnoreCase(outputFormat.trim())) {
outputFormat = outputFormat.trim();
String outputArg = "-";
int colon = outputFormat.indexOf(':');
@@ -666,10 +702,12 @@ public class FindBugsTask extends AbstractFindBugsTask {
}
addArg(outputArg);
}
- if (quietErrors)
+ if (quietErrors) {
addArg("-quiet");
- if (reportLevel != null)
+ }
+ if (reportLevel != null) {
addArg("-" + reportLevel.trim().toLowerCase());
+ }
if (projectFile != null) {
addArg("-project");
addArg(projectFile.getPath());
@@ -716,12 +754,14 @@ public class FindBugsTask extends AbstractFindBugsTask {
@SuppressWarnings("unused")
String unreadReference = auxClasspath.toString();
String auxClasspathString = auxClasspath.toString();
- if (auxClasspathString.length() > 100) {
- addArg("-auxclasspathFromInput");
- setInputString(auxClasspathString);
- } else {
- addArg("-auxclasspath");
- addArg(auxClasspathString);
+ if (!auxClasspathString.isEmpty()) {
+ if (auxClasspathString.length() > 100) {
+ addArg("-auxclasspathFromInput");
+ setInputString(auxClasspathString);
+ } else {
+ addArg("-auxclasspath");
+ addArg(auxClasspathString);
+ }
}
} catch (Throwable t) {
log("Warning: auxClasspath " + t + " not found.");
@@ -738,15 +778,22 @@ public class FindBugsTask extends AbstractFindBugsTask {
if (relaxed) {
addArg("-relaxed");
}
+ if (!nested) {
+ addArg("-nested:false");
+ }
if (noClassOk) {
addArg("-noClassOk");
}
+
if (onlyAnalyze != null) {
addArg("-onlyAnalyze");
addArg(onlyAnalyze);
}
- addArg("-exitcode");
+ if (setExitCode) {
+ addArg("-exitcode");
+ }
+
for (ClassLocation classLocation : classLocations) {
addArg(classLocation.toString());
}
@@ -768,4 +815,3 @@ public class FindBugsTask extends AbstractFindBugsTask {
}
}
-// vim:ts=4
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/FindBugsViewerTask.java b/src/antTask/edu/umd/cs/findbugs/anttask/FindBugsViewerTask.java
index 10ceed0..9ba5aa4 100644
--- a/src/antTask/edu/umd/cs/findbugs/anttask/FindBugsViewerTask.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/FindBugsViewerTask.java
@@ -31,36 +31,36 @@ import edu.umd.cs.findbugs.ExitCodes;
/**
* FindBugsViewerTask.java -- Ant Task to launch the FindBugsFrame
- *
+ *
* To use, create a new task that refrences the ant task (such as
* "findbugs-viewer"). Then call this task while passing in parameters to modify
* it's behaviour. It supports several options that are the same as the findbugs
* task:
- *
+ *
* -projectFile -debug -jvmargs -home -classpath -pluginList -timeout
- *
+ *
* It also adds some new options:
- *
+ *
* -look: string name representing look and feel. Can be "native", "plastic" or
* "gtk" -loadbugs: file name of bug report to load
- *
+ *
* The below is an example of how this could be done in an ant script:
- *
+ *
* <taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask"
* classpath="C:\dev\cvs.sourceforge.net\findbugs\lib\findbugs-ant.jar" />
* <taskdef name="findbugs-viewer"
* classname="edu.umd.cs.findbugs.anttask.FindBugsViewerTask"
* classpath="C:\dev\cvs.sourceforge.net\findbugs\lib\findbugs-ant.jar" />
- *
+ *
* <property name="findbugs.home" location="C:\dev\cvs.sourceforge.net\findbugs"
* /> <property name="findbugs.bugReport" location="bcel-fb.xml" />
- *
+ *
* <target name="findbugs-viewer" depends="jar"> <findbugs-viewer
* home="${findbugs.home}" look="native" loadbugs="${findbugs.bugReport}"/>
* </target>
- *
+ *
* Created on March 21, 2006, 12:57 PM
- *
+ *
* @author Mark McKay, mark at kitfox.com
*/
public class FindBugsViewerTask extends Task {
@@ -94,7 +94,7 @@ public class FindBugsViewerTask extends Task {
/**
* Sets the file that contains the XML output of a findbugs report.
- *
+ *
* @param loadbugs
* XML output from a findbugs session
*/
@@ -184,7 +184,7 @@ public class FindBugsViewerTask extends Task {
/**
* Set timeout in milliseconds.
- *
+ *
* @param timeout
* the timeout
*/
@@ -194,7 +194,7 @@ public class FindBugsViewerTask extends Task {
/**
* Add an argument to the JVM used to execute FindBugs.
- *
+ *
* @param arg
* the argument
*/
@@ -226,12 +226,13 @@ public class FindBugsViewerTask extends Task {
File findbugsLibFindBugs = new File(findbugsLib, "findbugs.jar");
File findBugsFindBugs = new File(homeDir, "findbugs.jar");
// log("executing using home dir [" + homeDir + "]");
- if (findbugsLibFindBugs.exists())
+ if (findbugsLibFindBugs.exists()) {
findbugsEngine.setClasspath(new Path(getProject(), findbugsLibFindBugs.getPath()));
- else if (findBugsFindBugs.exists())
+ } else if (findBugsFindBugs.exists()) {
findbugsEngine.setClasspath(new Path(getProject(), findBugsFindBugs.getPath()));
- else
+ } else {
throw new IllegalArgumentException("Can't find findbugs.jar in " + homeDir);
+ }
findbugsEngine.setClassname("edu.umd.cs.findbugs.LaunchAppropriateUI");
findbugsEngine.createJvmarg().setValue("-Dfindbugs.home=" + homeDir.getPath());
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/MineBugHistoryTask.java b/src/antTask/edu/umd/cs/findbugs/anttask/MineBugHistoryTask.java
index 080782f..9770739 100644
--- a/src/antTask/edu/umd/cs/findbugs/anttask/MineBugHistoryTask.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/MineBugHistoryTask.java
@@ -25,7 +25,7 @@ import org.apache.tools.ant.BuildException;
/**
* Ant task to invoke the MineBugHistory program in the workflow package
- *
+ *
* @author David Hovemeyer
* @author Ben Langmead
*/
@@ -80,14 +80,14 @@ public class MineBugHistoryTask extends AbstractFindBugsTask {
return;
}
attrVal = attrVal.toLowerCase();
- if (!attrVal.equals("true") && !attrVal.equals("false")) {
+ if (!"true".equals(attrVal) && !"false".equals(attrVal)) {
throw new BuildException("attribute " + attrName + " requires boolean value", getLocation());
}
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#checkParameters()
*/
@Override
@@ -111,7 +111,7 @@ public class MineBugHistoryTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#configureFindbugsEngine
* ()
@@ -130,7 +130,7 @@ public class MineBugHistoryTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#beforeExecuteJavaProcess
* ()
@@ -142,7 +142,7 @@ public class MineBugHistoryTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#afterExecuteJavaProcess
* (int)
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/SetBugDatabaseInfoTask.java b/src/antTask/edu/umd/cs/findbugs/anttask/SetBugDatabaseInfoTask.java
index 948b70b..79953d8 100644
--- a/src/antTask/edu/umd/cs/findbugs/anttask/SetBugDatabaseInfoTask.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/SetBugDatabaseInfoTask.java
@@ -23,7 +23,7 @@ import org.apache.tools.ant.BuildException;
/**
* Ant task to invoke the SetBugDatabaseInfo program in the workflow package
- *
+ *
* @author David Hovemeyer
* @author Ben Langmead
*/
@@ -93,14 +93,14 @@ public class SetBugDatabaseInfoTask extends AbstractFindBugsTask {
return;
}
attrVal = attrVal.toLowerCase();
- if (!attrVal.equals("true") && !attrVal.equals("false")) {
+ if (!"true".equals(attrVal) && !"false".equals(attrVal)) {
throw new BuildException("attribute " + attrName + " requires boolean value", getLocation());
}
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#checkParameters()
*/
@Override
@@ -134,7 +134,7 @@ public class SetBugDatabaseInfoTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#configureFindbugsEngine
* ()
@@ -147,7 +147,7 @@ public class SetBugDatabaseInfoTask extends AbstractFindBugsTask {
addOption("-findSource", findSource);
addOption("-suppress", suppress);
addBoolOption("-withMessages", withMessages);
- if (resetSource != null && resetSource.equals("true")) {
+ if (resetSource != null && "true".equals(resetSource)) {
addArg("-resetSource");
}
addArg(inputFile);
@@ -158,7 +158,7 @@ public class SetBugDatabaseInfoTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#beforeExecuteJavaProcess
* ()
@@ -170,7 +170,7 @@ public class SetBugDatabaseInfoTask extends AbstractFindBugsTask {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.anttask.AbstractFindBugsTask#afterExecuteJavaProcess
* (int)
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/UnionBugs.java b/src/antTask/edu/umd/cs/findbugs/anttask/UnionBugs.java
index f68acc8..3810075 100644
--- a/src/antTask/edu/umd/cs/findbugs/anttask/UnionBugs.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/UnionBugs.java
@@ -36,29 +36,29 @@ import edu.umd.cs.findbugs.workflow.UnionResults;
/**
* An ant task that is wraps the behavior of the UnionResults executable into an
* ant task.
- *
+ *
* <taskdef name="UnionBugs" classname="edu.umd.cs.findbugs.anttask.UnionBugs"
* classpath="...">
- *
+ *
* <UnionBugs to="${basedir}/findbugs.xml" > <fileset dir="plugins"> <include
* name="*_findbugs_partial.xml" /> </fileset> </UnionBugs>
- *
+ *
* @author Peter Franza <a href="mailto:pfranza at gmail.com">pfranza at gmail.com</a>
* @version 1.0
- *
+ *
* @ant.task category="utility"
- *
+ *
*/
@Deprecated
public class UnionBugs extends Task {
- private List<FileSet> fileSets = new ArrayList<FileSet>();
+ private final List<FileSet> fileSets = new ArrayList<FileSet>();
private String into;
/**
* The fileset containing all the findbugs xml files that need to be merged
- *
+ *
* @param arg
*/
public void addFileset(FileSet arg) {
@@ -67,7 +67,7 @@ public class UnionBugs extends Task {
/**
* The File everything should get merged into
- *
+ *
* @param file
*/
public void setTo(String file) {
@@ -137,25 +137,18 @@ public class UnionBugs extends Task {
/**
* Copy a File
- *
- * @param File
+ *
+ * @param in
* to Copy From
- * @param File
+ * @param out
* to Copy To
* @throws IOException
*/
private static void copyFile(File in, File out) throws IOException {
- FileChannel inChannel = new FileInputStream(in).getChannel();
- FileChannel outChannel = new FileOutputStream(out).getChannel();
- try {
- inChannel.transferTo(0, inChannel.size(), outChannel);
- } catch (IOException e) {
- throw e;
- } finally {
- if (inChannel != null)
- inChannel.close();
- if (outChannel != null)
- outChannel.close();
+ try (FileInputStream inStream = new FileInputStream(in);
+ FileOutputStream outStream = new FileOutputStream(out);) {
+ FileChannel inChannel = inStream.getChannel();
+ inChannel.transferTo(0, inChannel.size(), outStream.getChannel());
}
}
diff --git a/src/antTask/edu/umd/cs/findbugs/anttask/UnionBugs2.java b/src/antTask/edu/umd/cs/findbugs/anttask/UnionBugs2.java
index 3fdb558..f4ed326 100644
--- a/src/antTask/edu/umd/cs/findbugs/anttask/UnionBugs2.java
+++ b/src/antTask/edu/umd/cs/findbugs/anttask/UnionBugs2.java
@@ -28,23 +28,23 @@ import org.apache.tools.ant.types.FileSet;
/**
* An ant task that is wraps the behavior of the UnionResults executable into an
* ant task.
- *
+ *
* <taskdef name="UnionBugs2" classname="edu.umd.cs.findbugs.anttask.UnionBugs2"
* classpath="...">
- *
+ *
* <UnionBugs2 to="${basedir}/findbugs.xml" > <fileset dir="plugins"> <include
* name="*_findbugs_partial.xml" /> </fileset> </UnionBugs>
- *
- *
+ *
+ *
* @ant.task category="utility"
- *
+ *
*/
public class UnionBugs2 extends AbstractFindBugsTask {
private String to;
- private ArrayList<FileSet> fileSets = new ArrayList<FileSet>();
+ private final ArrayList<FileSet> fileSets = new ArrayList<FileSet>();
public UnionBugs2() {
super("edu.umd.cs.findbugs.workflow.UnionResults");
@@ -53,16 +53,16 @@ public class UnionBugs2 extends AbstractFindBugsTask {
/**
* The fileset containing all the findbugs xml files that need to be merged
- *
+ *
* @param arg
*/
public void addFileset(FileSet arg) {
this.fileSets.add(arg);
}
-
+
/**
* The File everything should get merged into
- *
+ *
* @param arg
*/
public void setTo(String arg) {
@@ -73,14 +73,16 @@ public class UnionBugs2 extends AbstractFindBugsTask {
protected void checkParameters() {
super.checkParameters();
- if (to == null)
+ if (to == null) {
throw new BuildException("to attribute is required", getLocation());
+ }
- if (fileSets.size() < 1)
+ if (fileSets.size() < 1) {
throw new BuildException("fileset is required");
+ }
}
-
+
@Override
protected void beforeExecuteJavaProcess() {
log("unioning bugs...");
diff --git a/src/doc/Changes.html b/src/doc/Changes.html
index 2695fb5..232aa38 100644
--- a/src/doc/Changes.html
+++ b/src/doc/Changes.html
@@ -8,1437 +8,1640 @@
<body>
- <table width="100%">
- <tr>
-
- @HTML_SIDEBAR@
-
- <td align="left" valign="top">
-
-
- <h1>FindBugs Change Log, Version @VERSION@</h1>
- <ul>
- <li>New Bug patterns: <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#DM_BOXED_PRIMITIVE_FOR_PARSING">DM_BOXED_PRIMITIVE_FOR_PARSING</a>,
- <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_METHOD_RETURN_RELAXING_ANNOTATION">NP_METHOD_RETURN_RELAXING_ANNOTATION</a>,
- and
- <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION">NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION</a>
- </li>
- <li>Add the ability in the GUI to save the currently viewable/filtered bugs to HTML output.
- <li>When dataflow does't terminate, make sure we continue with
- analysis.
-
- <li>Fix some problems that resulting in dataflow analysis not
- terminating
-
- <li>Get parameter annotations from default parameters
- annotations applied to the method.
- <li>Add subversion change number to eclipse plugin qualifier.
-
- <li>Disabled detector for <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#AM_CREATES_EMPTY_JAR_FILE_ENTRY">AM_CREATES_EMPTY_JAR_FILE_ENTRY</a>;
- it complaints inappropriately about code that creates directory
- entries.
-
- <li>Add warnings about incompatible types passed to
- org.testng.Assert.assertEquals</li>
- <li>Add logic that understands more of the Google Guava APIs.
- <li>Disable type qualifier validator execution within Eclipse plugin;
- too many problems with class loading and security manager (see #1154 Random obscure Eclipse failures)
- <li>Consistently check both access flags and attributes to see if something is synthetic. Compiler is
- inconsistent about where synthetic elements are marked.
-
- <li>Fixed false positives for the following bug patterns (17
- occurrences in findbugsTestCases):
- <ul>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BC">BC</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_IMPOSSIBLE_INSTANCEOF">BC_IMPOSSIBLE_INSTANCEOF</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_UNCONFIRMED_CAST">BC_UNCONFIRMED_CAST</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_UNRELATED_TYPES">EC_UNRELATED_TYPES</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE">INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#IS2_INCONSISTENT_SYNC">IS2_INCONSISTENT_SYNC</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS">NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#OBL_UNSATISFIED_OBLIGATION">OBL_UNSATISFIED_OBLIGATION</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE">RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#SA_FIELD_SELF_COMPARISON">SA_FIELD_SELF_COMPARISON</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED">TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED</a>
- </li>
- </ul>
- <li>Fixed false negatives for the following bug patterns (45
- occurrences in findbugsTestCases):
- <ul>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_UNCONFIRMED_CAST">BC_UNCONFIRMED_CAST</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#DM_NUMBER_CTOR">DM_NUMBER_CTOR</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_ARRAY_AND_NONARRAY">EC_ARRAY_AND_NONARRAY</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_INCOMPATIBLE_ARRAY_COMPARE">EC_INCOMPATIBLE_ARRAY_COMPARE</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_UNRELATED_TYPES">EC_UNRELATED_TYPES</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#GC_UNRELATED_TYPES">GC_UNRELATED_TYPES</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#IS_FIELD_NOT_GUARDED">IS_FIELD_NOT_GUARDED</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#IT_NO_SUCH_ELEMENT">IT_NO_SUCH_ELEMENT</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS">JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NULL_ON_SOME_PATH">NP_NULL_ON_SOME_PATH</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NONNULL_PARAM_VIOLATION">NP_NONNULL_PARAM_VIOLATION</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE">NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE">NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_STORE_INTO_NONNULL_FIELD">NP_STORE_INTO_NONNULL_FIELD</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#RE_POSSIBLE_UNINTENDED_PATTERN">RE_POSSIBLE_UNINTENDED_PATTERN</a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#SA_FIELD_SELF_COMPARISON">SA_FIELD_SELF_COMPARISON</a>
- </ul>
- </ul>
- <h1>FindBugs Change Log, Version 2.0.2</h1>
-
- <ul>
- <li>Fix false positions for <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR">NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR</a>
- - fixing <a
- href="https://sourceforge.net/tracker/?func=detail&aid=3547559&group_id=96405&atid=614693">Bug3547559</a>,
- <a
- href="https://sourceforge.net/tracker/?func=detail&aid=3555408&group_id=96405&atid=614693">Bug3555408</a>,
- <a
- href="https://sourceforge.net/tracker/?func=detail&aid=3580266&group_id=96405&atid=614693">Bug3580266</a>
- and <a
- href="https://sourceforge.net/tracker/?func=detail&aid=3587164&group_id=96405&atid=614693">Bug3587164</a>.
-
-
- </li>
- <li>Fix false positives for <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#SF_SWITCH_NO_DEFAULT">SF_SWITCH_NO_DEFAULT</a>
- <li>Inline access methods for private fields,
+ <table width="100%">
+ <tr>
+
+ @HTML_SIDEBAR@
+
+ <td align="left" valign="top">
+
+
+ <h1>FindBugs Change Log, Version @VERSION@</h1>
+ <ul>
+ <li>New Bug patterns:
+<ul>
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BSHIFT_WRONG_ADD_PRIORITY">BSHIFT_WRONG_ADD_PRIORITY</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#CO_COMPARETO_INCORRECT_FLOATING">CO_COMPARETO_INCORRECT_FLOATING</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DC_PARTIALLY_CONSTRUCTED">DC_PARTIALLY_CONSTRUCTED</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DM_BOXED_PRIMITIVE_FOR_COMPARE">DM_BOXED_PRIMITIVE_FOR_COMPARE</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DM_INVALID_MIN_MAX">DM_INVALID_MIN_MAX</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#ME_MUTABLE_ENUM_FIELD">ME_MUTABLE_ENUM_FIELD</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#ME_ENUM_FIELD_SETTER">ME_ENUM_FIELD_SETTER</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#MS_MUTABLE_COLLECTION">MS_MUTABLE_COLLECTION</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#MS_MUTABLE_COLLECTION_PKGPROTECT">MS_MUTABLE_COLLECTION_PKGPROTECT</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RANGE_ARRAY_INDEX">RANGE_ARRAY_INDEX</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RANGE_ARRAY_OFFSET">RANGE_ARRAY_OFFSET</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RANGE_ARRAY_LENGTH">RANGE_ARRAY_LENGTH</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RANGE_STRING_INDEX">RANGE_STRING_INDEX</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT">RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UC_USELESS_CONDITION">UC_USELESS_CONDITION</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UC_USELESS_CONDITION_TYPE">UC_USELESS_CONDITION_TYPE</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UC_USELESS_OBJECT">UC_USELESS_OBJECT</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UC_USELESS_OBJECT_STACK">UC_USELESS_OBJECT_STACK</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UC_USELESS_VOID_METHOD">UC_USELESS_VOID_METHOD</a>
+ </ul>
+ </li>
+ <li>Improved Bug patterns:
+ <ul>
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE">INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RpC_REPEATED_CONDITIONAL_TEST">RpC_REPEATED_CONDITIONAL_TEST</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#WMI_WRONG_MAP_ITERATOR">WMI_WRONG_MAP_ITERATOR</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DMI_HARDCODED_ABSOLUTE_FILENAME">DMI_HARDCODED_ABSOLUTE_FILENAME</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DMI_EMPTY_DB_PASSWORD">DMI_EMPTY_DB_PASSWORD</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DMI_CONSTANT_DB_PASSWORD">DMI_CONSTANT_DB_PASSWORD</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#PT_ABSOLUTE_PATH_TRAVERSAL">PT_ABSOLUTE_PATH_TRAVERSAL</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#PT_RELATIVE_PATH_TRAVERSAL">PT_RELATIVE_PATH_TRAVERSAL</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD">IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE">SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING">SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING</a>
+ </ul>
+ </li>
+ <li> Bug patterns under evaluation:
+<ul>
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#CAA_COVARIANT_ARRAY_FIELD">CAA_COVARIANT_ARRAY_FIELD</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#CAA_COVARIANT_ARRAY_RETURN">CAA_COVARIANT_ARRAY_RETURN</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#CAA_COVARIANT_ARRAY_LOCAL">CAA_COVARIANT_ARRAY_LOCAL</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#CAA_COVARIANT_ARRAY_ELEMENT_STORE">CAA_COVARIANT_ARRAY_ELEMENT_STORE</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IIL_PREPARE_STATEMENT_IN_LOOP">IIL_PREPARE_STATEMENT_IN_LOOP</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IIL_PATTERN_COMPILE_IN_LOOP">IIL_PATTERN_COMPILE_IN_LOOP</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IIL_PATTERN_COMPILE_IN_LOOP_INDIRECT">IIL_PATTERN_COMPILE_IN_LOOP_INDIRECT</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IIL_ELEMENTS_GET_LENGTH_IN_LOOP">IIL_ELEMENTS_GET_LENGTH_IN_LOOP</a>,
+</ul>
+
+ </li>
+
+ <!--
+ <li>Fixed false positives for the following bug patterns (XXX occurrences in findbugsTestCases):
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#XXX">XXX</a>
+ </ul>
+ </li>
+
+ <li>Fixed false negatives for the following bug patterns (XXX occurrences in findbugsTestCases):
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#XXX">XXX</a>
+ </ul>
+ </li>
+ -->
+
+ <li>Various bug fixes, also many patches from community. Thanks for your contributions!
+ </li>
+ </ul>
+
+ <h1>FindBugs Change Log, Version 3.0.0</h1>
+ <ul>
+ <li>FindBugs supports Java 8 now (both as runtime and target platform).
+ <li>FindBugs requires minimum Java 7 as runtime environment!
+ <li>FindBugs uses ASM 5 now which means that some 3rd party detectors based on FindBugs 2.x/ASM 3 has to be upgraded.
+ See details in <a href="http://download.forge.objectweb.org/asm/asm4-guide.pdf#chapter.5">ASM documentation</a>.
+ <li>New Bug patterns:
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_OPTIONAL_RETURN_NULL">NP_OPTIONAL_RETURN_NULL</a>,
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IIO_INEFFICIENT_INDEX_OF">IIO_INEFFICIENT_INDEX_OF</a>,
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IIO_INEFFICIENT_LAST_INDEX_OF">IIO_INEFFICIENT_LAST_INDEX_OF</a>,
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#CNT_ROUGH_CONSTANT_VALUE">CNT_ROUGH_CONSTANT_VALUE</a>
+ </li>
+ <li>New "Source" filter which can be used to filter out classes generated from other languages:
+ <pre>
+ <?xml version="1.0" encoding="UTF-8"?>
+ <FindBugsFilter>
+ <Match>
+ <Source name="~.*\.groovy" />
+ </Match>
+ </FindBugsFilter>
+ </pre>
+ </li>
+ <li>New "-auxclasspathFromFile" and "-analyzeFromFile" command line options.
+ </li>
+ <li>New "nested" ant task attribute.
+ </li>
+
+
+ <!--
+ <li>Fixed false positives for the following bug patterns (XXX occurrences in findbugsTestCases):
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#XXX">XXX</a>
+ </ul>
+ </li>
+
+ <li>Fixed false negatives for the following bug patterns (XXX occurrences in findbugsTestCases):
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#XXX">XXX</a>
+ </ul>
+ </li>
+ -->
+
+ <li>Various bug fixes, also many patches from community. Thanks for your contributions!
+ </li>
+ </ul>
+
+
+ <h1>FindBugs Change Log, Version 2.0.3</h1>
+ <ul>
+ <li>New Bug patterns: <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DM_BOXED_PRIMITIVE_FOR_PARSING">DM_BOXED_PRIMITIVE_FOR_PARSING</a>,
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_METHOD_RETURN_RELAXING_ANNOTATION">NP_METHOD_RETURN_RELAXING_ANNOTATION</a>,
+ and
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION">NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION</a>
+ </li>
+ <li>Add the ability in the GUI to save the currently viewable/filtered bugs to HTML output.
+ <li>When dataflow does't terminate, make sure we continue with
+ analysis.
+
+ <li>Fix some problems that resulting in dataflow analysis not
+ terminating
+
+ <li>Get parameter annotations from default parameters
+ annotations applied to the method.
+ <li>Add subversion change number to eclipse plugin qualifier.
+
+ <li>Disabled detector for <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#AM_CREATES_EMPTY_JAR_FILE_ENTRY">AM_CREATES_EMPTY_JAR_FILE_ENTRY</a>;
+ it complaints inappropriately about code that creates directory
+ entries.
+
+ <li>Add warnings about incompatible types passed to
+ org.testng.Assert.assertEquals</li>
+ <li>Add logic that understands more of the Google Guava APIs.
+ <li>Disable type qualifier validator execution within Eclipse plugin;
+ too many problems with class loading and security manager (see #1154 Random obscure Eclipse failures)
+ <li>Consistently check both access flags and attributes to see if something is synthetic. Compiler is
+ inconsistent about where synthetic elements are marked.
+
+ <li>Fixed false positives for the following bug patterns (17
+ occurrences in findbugsTestCases):
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BC">BC</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_IMPOSSIBLE_INSTANCEOF">BC_IMPOSSIBLE_INSTANCEOF</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_UNCONFIRMED_CAST">BC_UNCONFIRMED_CAST</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_UNRELATED_TYPES">EC_UNRELATED_TYPES</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE">INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IS2_INCONSISTENT_SYNC">IS2_INCONSISTENT_SYNC</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS">NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#OBL_UNSATISFIED_OBLIGATION">OBL_UNSATISFIED_OBLIGATION</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE">RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#SA_FIELD_SELF_COMPARISON">SA_FIELD_SELF_COMPARISON</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED">TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED</a>
+ </li>
+ </ul>
+ <li>Fixed false negatives for the following bug patterns (45
+ occurrences in findbugsTestCases):
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_UNCONFIRMED_CAST">BC_UNCONFIRMED_CAST</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DM_NUMBER_CTOR">DM_NUMBER_CTOR</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_ARRAY_AND_NONARRAY">EC_ARRAY_AND_NONARRAY</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_INCOMPATIBLE_ARRAY_COMPARE">EC_INCOMPATIBLE_ARRAY_COMPARE</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_UNRELATED_TYPES">EC_UNRELATED_TYPES</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#GC_UNRELATED_TYPES">GC_UNRELATED_TYPES</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IS_FIELD_NOT_GUARDED">IS_FIELD_NOT_GUARDED</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IT_NO_SUCH_ELEMENT">IT_NO_SUCH_ELEMENT</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS">JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NULL_ON_SOME_PATH">NP_NULL_ON_SOME_PATH</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NONNULL_PARAM_VIOLATION">NP_NONNULL_PARAM_VIOLATION</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE">NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE">NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_STORE_INTO_NONNULL_FIELD">NP_STORE_INTO_NONNULL_FIELD</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RE_POSSIBLE_UNINTENDED_PATTERN">RE_POSSIBLE_UNINTENDED_PATTERN</a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#SA_FIELD_SELF_COMPARISON">SA_FIELD_SELF_COMPARISON</a>
+ </ul>
+ </ul>
+ <h1>FindBugs Change Log, Version 2.0.2</h1>
+
+ <ul>
+ <li>Fix false positions for <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR">NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR</a>
+ - fixing <a
+ href="https://sourceforge.net/tracker/?func=detail&aid=3547559&group_id=96405&atid=614693">Bug3547559</a>,
+ <a
+ href="https://sourceforge.net/tracker/?func=detail&aid=3555408&group_id=96405&atid=614693">Bug3555408</a>,
+ <a
+ href="https://sourceforge.net/tracker/?func=detail&aid=3580266&group_id=96405&atid=614693">Bug3580266</a>
+ and <a
+ href="https://sourceforge.net/tracker/?func=detail&aid=3587164&group_id=96405&atid=614693">Bug3587164</a>.
+
+
+ </li>
+ <li>Fix false positives for <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#SF_SWITCH_NO_DEFAULT">SF_SWITCH_NO_DEFAULT</a>
+ <li>Inline access methods for private fields,
fixing false positive in <a
href="https://sourceforge.net/tracker/?func=detail&aid=3484713&group_id=96405&atid=614693">Bug3484713</a>.
-
+
<li>Type qualifier annotations, including nullness
- annotations, are now ignored on vararg parameters (including
- default and inherited annotations), awaiting JSR308.
- <li>Defined new bug pattern to give better explanations of
- issues involving strict type qualifiers <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED">TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED</a>
- <li>Adjusted analysis of type qualifiers, now giving warnings
- where a computed value is used in a place where a value with a
- strict type qualifier is required.
- <li>Complain about missing classes only if they are
- encountered while analyzing application classes; ignore missing
- classes that are encounted while analyzing classes loaded from the
- auxclasspath. Fix for <a
- href="https://sourceforge.net/tracker/?func=detail&aid=3588379&group_id=96405&atid=614693">Bug3588379</a>
- <li>Fixed false positive null pointer warning coming from
- synthetic bridge methods, fixing <a
- href="https://sourceforge.net/tracker/?func=detail&aid=3589328&group_id=96405&atid=614693">Bug3589328</a>
- <li>In general, suppress warnings in synthetic methods.
- <li>Fix some false positives involving <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#GC_UNRELATED_TYPES">GC_UNRELATED_TYPES</a>
- on classes that extend generic collection classes.
-
- </li>
- <li>Combine multiple identical warnings about
+ annotations, are now ignored on vararg parameters (including
+ default and inherited annotations), awaiting JSR308.
+ <li>Defined new bug pattern to give better explanations of
+ issues involving strict type qualifiers <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED">TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED</a>
+ <li>Adjusted analysis of type qualifiers, now giving warnings
+ where a computed value is used in a place where a value with a
+ strict type qualifier is required.
+ <li>Complain about missing classes only if they are
+ encountered while analyzing application classes; ignore missing
+ classes that are encounted while analyzing classes loaded from the
+ auxclasspath. Fix for <a
+ href="https://sourceforge.net/tracker/?func=detail&aid=3588379&group_id=96405&atid=614693">Bug3588379</a>
+ <li>Fixed false positive null pointer warning coming from
+ synthetic bridge methods, fixing <a
+ href="https://sourceforge.net/tracker/?func=detail&aid=3589328&group_id=96405&atid=614693">Bug3589328</a>
+ <li>In general, suppress warnings in synthetic methods.
+ <li>Fix some false positives involving <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#GC_UNRELATED_TYPES">GC_UNRELATED_TYPES</a>
+ on classes that extend generic collection classes.
+
+ </li>
+ <li>Combine multiple identical warnings about
<a
href="http://findbugs.sourceforge.net/bugDescriptions.html#DM_DEFAULT_ENCODING">DM_DEFAULT_ENCODING</a>
that occur in the same method,
simplifying issue triage.
-
- <li>Changes by Andrey Loskutov
- <ul>
- <li>fixed job scheduling errors in 3.8/4.2 Eclipse <a
- href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=393748">bug
- report</a>
- <li>more realistic progress bar updates for jobs
- <li>added nullness annotations for some common Eclipse API
- methods known to usually return null values
- <li>Added support for org.eclipse.jdt.annotation.Nullable,
- NonNull and NonNullByDefault annotations (introduced with
- Eclipse 3.8/4.2)</li>
- </ul>
- <li>Documentation improvements
- <li><a href="http://code.google.com/p/findbugs/source/list">lots
- of other small changes</a>
- </ul>
- <h1>FindBugs Change Log, Version 2.0.1</h1>
-
- <ul>
- <li>New bug patterns; in some cases, bugs previous reported as
- other bug patterns are reported as instances of these new bug
- patterns in order to make it easier for developers to understand
- the bug reports
- <ul>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#PT_ABSOLUTE_PATH_TRAVERSAL">PT_ABSOLUTE_PATH_TRAVERSAL</a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#PT_RELATIVE_PATH_TRAVERSAL">PT_RELATIVE_PATH_TRAVERSAL</a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR">NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR</a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#MS_SHOULD_BE_REFACTORED_TO_BE_FINAL">MS_SHOULD_BE_REFACTORED_TO_BE_FINAL</a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_UNCONFIRMED_CAST_OF_RETURN_VALUE">BC_UNCONFIRMED_CAST_OF_RETURN_VALUE</a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#PT_ABSOLUTE_PATH_TRAVERSAL">PT_ABSOLUTE_PATH_TRAVERSAL</a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#TQ_COMPARING_VALUES_WITH_INCOMPATIBLE_TYPE_QUALIFIERS">TQ_COMPARING_VALUES_WITH_INCOMPATIBLE_TYPE_QUALIFIERS</a></li>
- </ul>
- </li>
-
- <li>Changes to fix false negatives for the following bug
- patterns: <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_UNCONFIRMED_CAST">BC_UNCONFIRMED_CAST</a>,
- <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_BAD_ARRAY_COMPARE">EC_BAD_ARRAY_COMPARE</a>,
- <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#EQ_UNUSUAL">EQ_UNUSUAL</a>,
- <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#GC_UNRELATED_TYPES">GC_UNRELATED_TYPES</a>,
- and <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE">NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE</a>.
- </li>
-
- <li>Changes to fix false positions for the following bug
- patterns: <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#DMI_DOH">DMI_DOH</a>,
- <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_UNRELATED_TYPES">EC_UNRELATED_TYPES</a>,
- and <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#SE_BAD_FIELD">SE_BAD_FIELD</a>.
- </li>
- </ul>
-
- <h1>FindBugs Change Log, Version 2.0.0</h1>
-
- <h2>Changes since version 1.3.8</h2>
- <ul>
- <li>New bug patterns; in some cases, bugs previous reported as
- other bug patterns are reported as instances of these new bug
- patterns in order to make it easier for developers to understand
- the bug reports
- <ul>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_IMPOSSIBLE_DOWNCAST ">BC_IMPOSSIBLE_DOWNCAST
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY ">BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_INCOMPATIBLE_ARRAY_COMPARE ">EC_INCOMPATIBLE_ARRAY_COMPARE
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#JLM_JSR166_UTILCONCURRENT_MONITORENTER ">JLM_JSR166_UTILCONCURRENT_MONITORENTER
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE ">LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_CLOSING_NULL ">NP_CLOSING_NULL
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#RC_REF_COMPARISON_BAD_PRACTICE ">RC_REF_COMPARISON_BAD_PRACTICE
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN ">RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED ">RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#SIC_THREADLOCAL_DEADLY_EMBRACE ">SIC_THREADLOCAL_DEADLY_EMBRACE
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR ">UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR
- </a></li>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED ">VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED
- </a></li>
- </ul>
- </li>
- <li>Providing a bug rank (1-20), and the ability to filter by
- bug rank. Eventually, it will be possible to specify your own
- rules for ranking bugs, but the procedure for doing so hasn't been
- specified yet.</li>
- <li>Fixed about <a
- href="https://sourceforge.net/search/index.php?group_id=96405&search_summary=1&search_details=1&type_of_search=artifact&group_artifact_id%5B%5D=614693&open_date_start=2009-03-16&open_date_end=2009-08-20&form_submit=Search">45
- bugs filed</a> through SourceForge
- </li>
- <li>Various reclassifications and priority tweaks</li>
- <li>Added more bug annotations to a variety of bug reports.
- This provides more context for understanding bug reports (e.g., if
- the value in question was is the return value of a method, the
- method is described as the source of the value in a bug
- annotation). This also provide more accurate tracking of issues
- across versions of the code being analyzed, but has the downside
- that when comparing results from FindBugs 1.3.8 and FindBugs 1.3.9
- on the same version of code being analyzed, FindBugs may think
- that mistakenly believe that the issue reported by 1.3.8 was fixed
- and a new issue was introduced that was reported by FindBugs
- 1.3.9. While annoying, it would be unusual for more than a dozen
- issues per million lines of codes to be mistracked.</li>
- <li>Lots of internal changes moving towards FindBugs 2.0, but
- these features are undocumented, not yet officially supported, and
- subject to radical changes before FindBugs 2.0 is released.</li>
- </ul>
-
- <p>Changes since version 1.3.8</p>
- <ul>
- <li>New bug patterns; in some cases, bugs previous reported as
- other bug patterns are reported as instances of these new bug
- patterns in order to make it easier for developers to understand
- the bug reports
- <ul>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_IMPOSSIBLE_DOWNCAST ">BC_IMPOSSIBLE_DOWNCAST
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY ">BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_INCOMPATIBLE_ARRAY_COMPARE ">EC_INCOMPATIBLE_ARRAY_COMPARE
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#JLM_JSR166_UTILCONCURRENT_MONITORENTER ">JLM_JSR166_UTILCONCURRENT_MONITORENTER
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE ">LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_CLOSING_NULL ">NP_CLOSING_NULL
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#RC_REF_COMPARISON_BAD_PRACTICE ">RC_REF_COMPARISON_BAD_PRACTICE
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN ">RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED ">RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#SIC_THREADLOCAL_DEADLY_EMBRACE ">SIC_THREADLOCAL_DEADLY_EMBRACE
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR ">UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR
- </a>
- <li><a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED ">VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED
- </a>
- </ul>
- </li>
- <li>Providing a bug rank (1-20), and the ability to filter by
- bug rank. Eventually, it will be possible to specify your own
- rules for ranking bugs, but the procedure for doing so hasn't been
- specified yet.</li>
- <li>Fixed about <a
- href="https://sourceforge.net/search/index.php?group_id=96405&search_summary=1&search_details=1&type_of_search=artifact&group_artifact_id%5B%5D=614693&open_date_start=2009-03-16&open_date_end=2009-08-20&form_submit=Search">45
- bugs filed</a> through SourceForge
- </li>
- <li>Various reclassifications and priority tweaks</li>
- <li>Added more bug annotations to a variety of bug reports.
- This provides more context for understanding bug reports (e.g., if
- the value in question was is the return value of a method, the
- method is described as the source of the value in a bug
- annotation). This also provide more accurate tracking of issues
- across versions of the code being analyzed, but has the downside
- that when comparing results from FindBugs 1.3.8 and FindBugs 1.3.9
- on the same version of code being analyzed, FindBugs may think
- that mistakenly believe that the issue reported by 1.3.8 was fixed
- and a new issue was introduced that was reported by FindBugs
- 1.3.9. While annoying, it would be unusual for more than a dozen
- issues per million lines of codes to be mistracked.</li>
- <li>Lots of internal changes moving towards FindBugs 2.0, but
- these features are undocumented, not yet officially supported, and
- subject to radical changes before FindBugs 2.0 is released.</li>
- </ul>
-
- <p>Changes since version 1.3.7</p>
- <ul>
- <li>Primarily another small bugfix release.</li>
- <li>FindBugs base:
- <ul>
- <li>New Reports:
- <ul>
- <li>SF_SWITCH_NO_DEFAULT: missing default case in switch
- statement.</li>
- <li>SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH_TO_THROW:
- value ignored when switch fallthrough leads to thrown
- exception.</li>
- <li>INT_VACUOUS_BIT_OPERATION: bit operations that don't
- do any meaningful work.</li>
- <li>FB_UNEXPECTED_WARNING: warning generated that
- conflicts with @NoWarning FindBugs annotation.</li>
- <li>FB_MISSING_EXPECTED_WARNING: warning not generated
- despite presence of @ExpectedWarning FindBugs annotation.</li>
- <li>NOISE category: intended for use in data mining
- experiments.
- <ul>
- <li>NOISE_NULL_DEREFERENCE: fake null point dereference
- warning.</li>
- <li>NOISE_METHOD_CALL: fake method call warning.</li>
- <li>NOISE_FIELD_REFERENCE: fake field dereference
- warning.</li>
- <li>NOISE_OPERATION: fake operation warning.</li>
- </ul>
- </li>
- </ul>
- </li>
- <li>Other:
- <ul>
- <li>Garvin Leclaire has created a new Apache Maven
- repository for FindBugs at <a
- href="http://code.google.com/p/findbugs/">the Google Code
- FindBugs SVN repository</a>. (Thanks Garvin!)
- </li>
- </ul>
- </li>
- <li>Fixes:
- <ul>
- <li>[ 2317842 ] Highlighting broken in Windows</li>
- <li>[ 2515908 ] check for oddness should track sign of
- argument</li>
- <li>[ 2487936 ] "L B GC" false pos cast from
- Map.Entry.getKey() to Map.get()</li>
- <li>[ 2528264 ] Ant tasks not compatible with Ant 1.7.1</li>
- <li>[ 2539590 ] SF_SWITCH_FALLTHROUGH wrong message
- reported</li>
- <li>[ 2020066 ] Bug history displayed in fancy-hist.xsl is
- incorrect</li>
- <li>[ 2545098 ] Invalid character in analysis results file</li>
- <li>[ 2492673 ] Plugin sites should specify "requires
- Eclipse 3.3 or newer"</li>
- <li>[ 2588044 ] a tiny typing error</li>
- <li>[ 2589048 ] Documentation for convertXmlToText
- insufficient</li>
- <li>[ 2638739 ] NullPointerException when building</li>
- </ul>
- </li>
- <li>Patches:
- <ul>
- <li>[ 2538184 ] Make BugCollection implement
- Iterable<BugInstance> (thanks to Tomas Pollak)</li>
- <li>[ 2249771 ] Add Maven2 Findbugs plugin link to the
- Links page (thanks to Garvin Leclaire)</li>
- <li>[ 2609526 ] Japanese manual update (thanks to K.
- Hashimoto)</li>
- <li>[ 2119482 ] CheckBcel checks for nonexistent classes
- (thanks to Jerry James)</li>
- </ul>
- </li>
- </ul>
- </li>
- <li>FindBugs Eclipse plugin:
- <ul>
- <li>Major feature enhancements (thanks to Andrey Loskutov).
- See <a href="http://andrei.gmxhome.de/findbugs/index.html">this
- overview</a> for more information.
- </li>
- <li>Major test improvements (thanks to Tomas Pollak).</li>
- <li>Fixes:
- <ul>
- <li>[ 2532365 ] Compiler warning</li>
- <li>[ 2522989 ] Fix filter files selection</li>
- <li>[ 2504068 ] NullPointerException</li>
- <li>[ 2640849 ] NPE in Eclipse plugin 1.3.7 and Eclipse
- 3.5 M5</li>
- </ul>
- </li>
- <li>Patches:
- <ul>
- <li>[ 2143140 ] Unchecked conversion fixes for Eclipse
- plugin (thanks to Jerry James)
- </ul>
- </li>
- </ul>
- </li>
- </ul>
-
- <p>Changes since version 1.3.6</p>
- <ul>
- <li>Overall, a small bugfix release.
- <li>New detection of accidental vacuous/useless calls to
- EasyMock methods, and of generic signatures that proclaim the use
- of unhashable classes in ways that require that they be hashed.
- <li>Eliminate some false positives where we were warning about
- a useless call (e.g., comparing two incompatible types for
- equality), but the only thing the code was doing with the result
- was passing it to assertFalse.
- <li>Japanese localization and manual by K.Hashimoto. (Thanks!)
-
- <li>Added -exclude and -outputDir command line options to
- rejarForAnalysis
- <li>Extended -adjustPriorities option to FindBugs analysis
- textui so that you can modify the priorities of individual bug
- patterns as well as visitors, and also completely suppress
- individual bug patterns or visitors.
- <ul>
- <li>e.g., -adjustPriority
- MS_SHOULD_BE_FINAL=suppress,MS_PKGPROTECT=suppress,EI_EXPOSE_REP=suppress,EI_EXPOSE_REP2=suppress,PZLA_PREFER_ZERO_LENGTH_ARRAYS=raise
-
- </ul>
- </ul>
-
-
- <p>Changes since version 1.3.5</p>
- <ul>
- <li>Added fairly exhaustive static analysis of uses of format
- strings, checking for missing or extra arguements, invalid format
- specifiers, or mismatched format specifiers and arguments (e.g,
- passing a String value for a %d format specifier). The logic for
- doing so is derived from Sun's java.util.Formatter class, and
- available separately from FindBugs as part of the <a
- href="https://jformatstring.dev.java.net/">jFormatString</a>
- project.
- <li>More tuning of the unsatisfied obligation detector. Since
- this detector is still rather noisy and an unfinished research
- project, I've moved the generated issues to a new category:
- EXPERIMENTAL.
- <li>Added check for <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BIT_ADD_OF_SIGNED_BYTE">BIT_ADD_OF_SIGNED_BYTE</a>;
- similar to <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#BIT_IOR_OF_SIGNED_BYTE">BIT_IOR_OF_SIGNED_BYTE</a>,
- except that addition is being used to combine shifted signed
- bytes.
- <li>Changed detection of EI_EXPOSE_REP2, so we only report it
- if the value stored is guaranteed to be the same value that was
- passed in as a parameter.
- <li>Added <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS">EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS</a>,
- a warning when an equals method checks to see if an operand is an
- instance of a class not compatible with itself. For example, if
- the Foo class checks to see if the argument is an instance of
- String. This is either a questionable design decision or a coding
- mistake.
- <li>Added <a
- href="http://findbugs.sourceforge.net/bugDescriptions.html#DMI_INVOKING_HASHCODE_ON_ARRAY">DMI_INVOKING_HASHCODE_ON_ARRAY</a>,
- which checks for invoking <code>hashCode()</code> on an array,
- which returns a hash code that ignores the contents of the array.
-
- <li>Added checks for using <code>x.removeAll(x)</code> to
- rather than <code>x.clear()</code> to clear an array.
- <li>Add checks for calls such as <code>x.contains(x)</code>, <code>x.remove(x)</code>
- and <code>x.containsAll(x)</code>.
- <li>Improvements to Eclipse plugin (thanks to Andrey
- Loskutov):
- <ul>
- <li>Report separate markers for each occurrence of an issue
- that appears multiple times in a method
- <li>fine tuning for reported markers: add only one marker
- for fields, add marker on right position
- <li>link bugs selected in bug explorer view to the opened
- editor and vice versa
- <li>select bugs selected in editor ruler in the opened bug
- explorer view
- <li>consistent abbreviations used in both bug explorer and
- bug details view
- <li>added "Expand All" button to the bug explorer view
- <li>added "Go Into/Go Up" buttons to the bug explorer view
- <li>added "Copy to clipboard" menu/functionality to the
- details view list widget
- <li>fix for CNF exception if loading the backup solution for
- broken browser widget
- </ul>
- </ul>
-
-
-
- <p>Changes since version 1.3.4</p>
- <ul>
- <li>Analysis about 15% faster
- <li><a
- href="http://sourceforge.net/tracker/?atid=614693&group_id=96405&func=browse&status=closed">38
- bugs closed</a></li>
- <li>New defect warnings:
- <ul>
- <li>calls to methods that always throw
- UnsupportedOperationException (DMI_UNSUPPORTED_METHOD)
- <li>repeated conditional tests (e.g., <code>if (x
- < 0 || x < 0) ...</code>) (RpC_REPEATED_CONDITIONAL_TEST)
- <li>Complete rewrite of detector for format string problems.
- More accurate, finds more problems, generates more descriptive
- reports, several different bug pattern
- (VA_FORMAT_STRING_EXTRA_ARGUMENTS_PASSED,
- VA_FORMAT_STRING_ILLEGAL, VA_FORMAT_STRING_MISSING_ARGUMENT,
- VA_FORMAT_STRING_BAD_ARGUMENT,
- VA_FORMAT_STRING_NO_PREVIOUS_ARGUMENT)
- <li>Fairly complete implementation of JSR-305 custom type
- qualifier analysis (no support for custom validators yet).
- (TQ_MAYBE_SOURCE_VALUE_REACHES_NEVER_SINK
- TQ_EXPLICIT_UNKNOWN_SOURCE_VALUE_REACHES_ALWAYS_SINK
- TQ_EXPLICIT_UNKNOWN_SOURCE_VALUE_REACHES_NEVER_SINK)
- <li>New detector for unsatisfied obligations such forgetting
- to close a file (OBL_UNSATISFIED_OBLIGATION).
- <li>Warning when a parameter is marked as nullable, but is
- always dereferenced.
- (NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE)
- <lI>Separate warning for dereference the result of readLine
- (NP_DEREFERENCE_OF_READLINE_VALUE)
- </ul>
- <li>When XML is generated with messages, the project stats now
- include <FileStat> elements. For each source file, this
- gives the path for the file, the total number of warnings for that
- file, and a bugHash for the file. While the instanceHash for a bug
- is intended to be version invariant (ignoring line numbers, etc),
- the bugHash for a file is intended to reflect all the information
- about the warnings in that file. The intended use case is that if
- the bugHash for a file is the same in two analysis runs, then <em>nothing</em>
- has changed about any of the warnings reported for that file
- between the two analysis runs.
- <li>More merging of similar issues within a method. For
- example, if the result of readLine() is dereferences multiple
- times within a method, it will be reported as a single warning
- with occurrences at multiple source lines.
- </ul>
- <p>Changes since version 1.3.3</p>
-
- <ul>
- <li>FindBugs base
- <ul>
- <li>New Reports:
- <ul>
- <li>EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC: equals method
- overrides equals in superclass and may not be symmetric</li>
- <li>EQ_ALWAYS_TRUE: equals method always returns true</li>
- <li>EQ_ALWAYS_FALSE: equals method always returns false</li>
- <li>EQ_COMPARING_CLASS_NAMES: equals method compares class
- names rather than class objects</li>
- <li>EQ_UNUSUAL: Unusual equals method</li>
- <li>EQ_GETCLASS_AND_CLASS_CONSTANT: equals method fails
- for subtypes</li>
- <li>SE_READ_RESOLVE_IS_STATIC: The readResolve method must
- not be declared as a static method.</li>
- <li>SE_PRIVATE_READ_RESOLVE_NOT_INHERITED: private
- readResolve method not inherited by subclasses</li>
- <li>MSF_MUTABLE_SERVLET_FIELD: Mutable servlet field</li>
- <li>XSS_REQUEST_PARAMETER_TO_SEND_ERROR: Servlet reflected
- cross site scripting vulnerability</li>
- <li>SKIPPED_CLASS_TOO_BIG: Class too big for analysis</li>
- </ul>
- </li>
- <li>Other:
- <ul>
- <li>Value-number analysis now more space-efficient</li>
- <li>Enhancements to reduce memory overhead when analyzing
- very large classes</li>
- <li>Now skips very large classes that would otherwise take
- too much time and memory to analyze</li>
- <li>Infrastructure for tracking effectively-constant/
- effectively-final fields</li>
- <li>Added more cweids</li>
- <li>Enhanced taint tracking for taint-based detectors</li>
- <li>Ignore doomed calls to equals if result is used as an
- argument to assertFalse</li>
- <li>EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC handles compareTo</li>
- <li>Priority tweak for ICAST_INTEGER_MULTIPLY_CAST_TO_LONG
- (only low priority if multiplying by 1000)</li>
- <li>Improved tracking of fields across method calls</li>
- </ul>
- </li>
- <li>Fixes:
- <ul>
- <li>[ 1941450 ] DLS_DEAD_LOCAL_STORE not reported</li>
- <li>[ 1953323 ] Omitted break statement in
- SynchronizeAndNullCheckField</li>
- <li>[ 1942620 ] Source Directories selection dialog
- interface confusion (partial)</li>
- <li>[ 1948275 ] Unhelpful "Load of known null"</li>
- <li>[ 1933922 ] MWM error in findbugs</li>
- <li>[ 1934772 ] 1.3.3 appears to rely on JDK 1.6, JNLP
- still specifies 1.5</li>
- <li>[ 1933945 ] -loadbugs doesn't work</li>
- <li>Fixed problems for class names starting with '$'</li>
- <li>Fixed bugs and incomplete handling of annotations in
- VersionInsensitiveBugComparator</li>
- </ul>
- </li>
- <li>Patches:
- <ul>
- <li>[ 1955106 ] Javadoc fixes</li>
- <li>[ 1951930 ] Superfluous import statements (thanks to
- Jerry James)</li>
- <li>[ 1951907 ] Missing @Deprecated annotations (thanks to
- Jerry James)</li>
- <li>[ 1951876 ] Infonode Docking Windows compile fix
- (thanks to Jerry James)</li>
- <li>[ 1936055 ] bugfix for findbugs.de.comment not working
- (thanks to Peter Fokkinga)
- </ul>
- </li>
- </ul>
- <li>FindBugs BlueJ plugin
- <ul>
- <li>Updated to use FindBugs 1.3.4 (first new release since
- 1.1.3)</li>
- </ul>
- </li>
- </ul>
-
- <p>Changes since version 1.3.2</p>
-
- <ul>
- <li>FindBugs base
- <ul>
- <li>New Detectors:
- <ul>
- <li>FieldItemSummary: Produces summary information for
- what is stored into fields</li>
- <li>SynchronizeOnClassLiteralNotGetClass: Look for code
- that synchronizes on the results of getClass rather than on
- class literals</li>
- <li>SynchronizingOnContentsOfFieldToProtectField: This
- detector looks for code that seems to be synchronizing on a
- field in order to guard updates of that field</li>
- </ul>
- </li>
- <li>New BugCode:
- <ul>
- <li>HRS: HTTP Response splitting vulnerability</li>
- <li>WL: Possible locking on wrong object</li>
- </ul>
- </li>
- <li>New Reports:
- <ul>
- <li>DMI_CONSTANT_DB_PASSWORD: This code creates a database
- connect using a hard coded, constant password</li>
- <li>HRS_REQUEST_PARAMETER_TO_COOKIE: HTTP cookie formed
- from untrusted input</li>
- <li>HRS_REQUEST_PARAMETER_TO_HTTP_HEADER: HTTP parameter
- directly written to HTTP header output</li>
- <li>CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE: Class defines
- clone() but doesn't implement Cloneable</li>
- <li>DL_SYNCHRONIZATION_ON_BOXED_PRIMITIVE: Synchronization
- on boxed primitive could lead to deadlock</li>
- <li>DL_SYNCHRONIZATION_ON_BOOLEAN: Synchronization on
- Boolean could lead to deadlock</li>
- <li>ML_SYNC_ON_FIELD_TO_GUARD_CHANGING_THAT_FIELD:
- Synchronization on field in futile attempt to guard that field
- </li>
- <li>DLS_DEAD_LOCAL_STORE_IN_RETURN: Useless assignment in
- return statement</li>
- <li>WL_USING_GETCLASS_RATHER_THAN_CLASS_LITERAL:
- Synchronization on getClass rather than class literal</li>
- </ul>
- </li>
- <li>Other:
- <ul>
- <li>Many enhancements to cross-site scripting detector and
- its documentation</li>
- <li>Enhanced switch fall through handling</li>
- <li>Enhanced unread field handling (look for IF_ACMPEQ and
- IF_ACMPNE)</li>
- <li>Clarified documentation for @Nullable in manual</li>
- <li>Fewer DeadLocalStore false positives</li>
- <li>Fewer UnreadField false positives</li>
- <li>Fewer StaticCalendarDetector false positives</li>
- <li>Performance fix for slow file system IO e.g. Clearcase
- repositories (thanks, Andrei!)</li>
- <li>Other, general performance enhancements (thanks,
- Andrei!)</li>
- <li>Enhancements for using FindBugs scripts with MKS on
- Windows (thanks, Kelly O'Hair!)</li>
- <li>Noted in the manual that jsr305.jar must be present
- for annotations to compile</li>
- <li>Added and fine-tuned default-nullness annotations</li>
- <li>More CWE IDs added</li>
- <li>Check and warning for unexpected BCEL version in
- classpath</li>
- </ul>
- </li>
- <li>Fixes:
- <ul>
- <li>Bug fix to handling of local variable tables in BCEL</li>
- <li>Refined documentation for
- MTIA_SUSPECT_STRUTS_INSTANCE_FIELD</li>
- <li>[ 1927295 ] NPE when called on project root</li>
- <li>[ 1926405 ] Incorrect dead store warning</li>
- <li>[ 1926409 ] Incorrect redundant nullcheck warning</li>
- <li>[ 1926389 ] Wrong line number printed/highlighted in
- bug</li>
- <li>[ 1927040 ] typo in bug description</li>
- <li>[ 1926263 ] Minor glitch in HTML output</li>
- <li>[ 1926240 ] Minor error in standard options in manual</li>
- <li>[ 1926236 ] Minor bug in installation section of
- manual</li>
- <li>[ 1925539 ] ZIP is default file system code base</li>
- <li>[ 1894701 ] Livelock / memory leak in
- ObjectTypeFactory (thanks, Andrei!)</li>
- <li>[ 1867491 ] Doesn't reload annotations after code
- changes in IDE (thanks, Andrei!)</li>
- <li>[ 1921399 ] -project option not supported</li>
- <li>[ 1913834 ] "Dead" store to variable with method call</li>
- <li>[ 1917352 ] H B se:...field in serializable class</li>
- <li>[ 1911617 ] CloneIdiom relies on
- getNameConstantOperand for INSTANCEOF</li>
- <li>[ 1911620 ] False +: DLS predecrement before return</li>
- <li>[ 1871376 ] False negative: non-serializable Map field</li>
- <li>[ 1871051 ] non standard clone() method</li>
- <li>[ 1908854 ] Error in TestASM</li>
- <li>[ 1907539 ] 22 minor errors in bug checker
- documentation</li>
- <li>[ 1897323 ] EJB implementation class false positives</li>
- <li>[ 1899648 ] Crash on startup on Vista with Java
- 1.6.0_04</li>
- </ul>
- </li>
- </ul>
- </li>
- <li>FindBugs Eclipse plugin (change log by Andrey Loskutov)
- <ul>
- <li>new feature: export basic FindBugs numbers for projects
- via File->Export->Java->BugCounts (Andrey Loskutov)</li>
- <li>new feature: jobs for different projects will be run in
- parallel per default if running on a multi-core PC
- ("fb.allowParallelBuild" system property not used anymore)
- (Andrey Loskutov)</li>
- <li>fixed performance slowdown in the multi-threaded build,
- caused by workspace operation locks during assigning marker
- attributes (Andrey Loskutov)</li>
- </ul>
- </li>
- </ul>
-
- <p>Changes since version 1.3.1</p>
-
- <ul>
- <li>FindBugs base
- <ul>
- <li>New Bug Category:
- <ul>
- <li>SECURITY (Abbrev: S), A use of untrusted input in a
- way that could create a remotely exploitable security
- vulnerability</li>
- </ul>
- </li>
- <li>New Detectors:
- <ul>
- <li>CrossSiteScripting: This detector looks for
- obvious/blatant cases of cross site scripting vulnerabilities</li>
- </ul>
- </li>
- <li>New BugCode:
- <ul>
- <li>XSS: Cross site scripting</li>
- </ul>
- </li>
- <li>New Reports:
- <ul>
- <li>XSS_REQUEST_PARAMETER_TO_SERVLET_WRITER: HTTP
- parameter directly written to Servlet output, giving XSS
- vulnerability</li>
- <li>XSS_REQUEST_PARAMETER_TO_JSP_WRITER: HTTP parameter
- directly written to JSP output, giving XSS vulnerability</li>
- <li>EQ_OTHER_USE_OBJECT: equals() method defined that
- doesn't override Object.equals(Object)</li>
- <li>EQ_OTHER_NO_OBJECT: equals() method inherits rather
- than overrides equals(Object)</li>
- <li>NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE: Possible
- null pointer dereference on path that might be infeasible</li>
- </ul>
- </li>
- <li>Other:
- <ul>
- <li>Added -noClassOk command-line parameter to
- command-line and ant interfaces; when -noClassOk is specified
- and no classfiles are given, FindBugs will print a warning
- message and output a well- formed file with no warnings</li>
- <li>Fewer false positives for null pointer bugs</li>
- <li>Suppress dead-local-store false positives in .jsp code</li>
- <li>Type fixes in warning messages</li>
- <li>Better warning message for NP_NULL_ON_SOME_PATH</li>
- <li>"WMI" bug code description renamed from "Wrong Map
- Iterator" to "Inefficient Map Iterator"</li>
- </ul>
- </li>
- <li>Fixes:
- <ul>
- <li>[ 1893048 ] FindBugs confused by a findbugs.xml file</li>
- <li>[ 1878528 ] XSL xforms don't support history features</li>
- <li>[ 1876584 ] two default.xsl flaws</li>
- <li>[ 1874856 ] Format string bug detector doesn't handle
- special operators</li>
- <li>[ 1872645 ] computeBugHistory -
- java.lang.IllegalArgumentException</li>
- <li>[ 1872237 ] Ant task fails when no .class files</li>
- <li>[ 1868670 ] Filters: include AND exclude don't allowed</li>
- <li>[ 1868666 ] check-for-oddness reported, but array
- length can never be negative</li>
- <li>[ 1866108 ] SetBugDatabaseInfoTask strips dir from
- output filename</li>
- <li>[ 1866021 ] MineBugHistoryTask strips dir of output
- filename</li>
- <li>[ 1865265 ] code doesn't handle
- StringBuffer.append([CII) right</li>
- <li>[ 1864793 ] Warning when casting a null reference
- compared to a String</li>
- <li>[ 1863376 ] Typo in manual chap 8: Filter Files</li>
- <li>[ 1862705 ] Transient fields that default to null</li>
- <li>[ 1842545 ] DLS on catch variable (with priority
- tweaking)</li>
- <li>[ 1816258 ] false positive BC_IMPOSSIBLE_CAST</li>
- <li>[ 1551732 ] Get erroneous DLS with while loop</li>
- </ul>
- </li>
- </ul>
- </li>
- <li>FindBugs Eclipse plugin (change log by Andrey Loskutov)
- <ul>
- <li>new feature: added Bug explorer view (replacing Bug tree
- view), based on Common Navigator framework (Andrey Loskutov)</li>
- <li>bug 1873860 fixed: empty projects are no longer shown in
- Bug tree view (Andrey Loskutov)</li>
- <li>new feature: bug counts decorators for projects, folders
- and files (has to be activated via Preferences -> general
- -> appearance -> label decorations)(Andrey Loskutov)</li>
- <li>patch 1746499: better icons (Alessandro Nistico)</li>
- <li>patch 1893685: Find bug actions on change sets bug
- (Alessandro Nistico)</li>
- <li>fixed bug 1855384: Bug configuration is broken in
- Eclipse (Andrey Loskutov)</li>
- <li>refactored FindBugs properties page (Andrey Loskutov)</li>
- <li>refactored FindBugs worker/builder/run action (Andrey
- Loskutov)</li>
- <li>FB detects now only bugs from classes on project's
- classpath (no double work on duplicated class files) (Andrey
- Loskutov)</li>
- <li>fixed bug introduced by the bad patch for 1867951: FB
- cannot be executed incrementally on a folder of file (Andrey
- Loskutov)</li>
- <li>fixed job rule: now jobs for different projects may run
- in parallel if running on a multi-core PC and
- "fb.allowParallelBuild" system property is set to true (Andrey
- Loskutov)</li>
- <li>fixed FB auto-build not started if .fbprefs or
- .classpath was changed (Andrey Loskutov)</li>
- <li>fixed not reporting bugs on secondary types (classes
- defined in java files with different name) (Andrey Loskutov)</li>
- </ul>
- </li>
- </ul>
-
- <p>Changes since version 1.3.0</p>
- <ul>
- <li>New Reports
- <ul>
- <li>VA_FORMAT_STRING_ARG_MISMATCH: A format-string method
- with a variable number of arguments is called, but the number of
- arguments passed does not match with the number of %
- placeholders in the format string. This is probably not what the
- author intended.
- <li>IO_APPENDING_TO_OBJECT_OUTPUT_STREAM: This code opens a
- file in append mode and that wraps the result in an object
- output stream. This won't allow you to append to an existing
- object output stream stored in a file. If you want to be able to
- append to an object output stream, you need to keep the object
- output stream open. The only situation in which opening a file
- in append mode and the writing an object output stream could
- work is if on reading the file you plan to open it in random
- access mode and seek to the byte offset where the append
- started.
- <li>NP_BOOLEAN_RETURN_NULL: A method that returns either
- Boolean.TRUE, Boolean.FALSE or null is an accident waiting to
- happen. This method can be invoked as though it returned a value
- of type boolean, and the compiler will insert automatic unboxing
- of the Boolean value. If a null value is returned, this will
- result in a NullPointerException.
- </ul>
- </li>
- <li>Changes to Existing Reports
- <ul>
- <li>RV_DONT_JUST_NULL_CHECK_READLINE: CORRECTNESS ->
- STYLE</li>
- <li>DMI_INVOKING_TOSTRING_ON_ARRAY: Long description
- mentions array name whenever possible</li>
- </ul>
- </li>
- <li>Fixes:
- <ul>
- <li>Updated manual to mention that Java 1.5 is now a
- requirement for running FindBugs
- <li>Applied patch 1840206 fixing issue "Ant task does not
- work when presetdef is used" - thanks to phejl
- <li>Applied patch 1778690 fixing issue "Ant task: tolerate
- but complain about invalid auxClasspath" - thanks to David
- Schmidt
- <li>Applied patch 1852125 adding a Chinese-language GUI
- bundle props file - thanks to fifi
- <li>Applied patch 1845903 adding ability to load XML results
- with the Eclipse plugin - thanks to Alex Mont
- <li>Fixed issue 1844671 - "FP for "reversed" null check in
- catch for stream close"
- <li>Fixed issue 1836050 - "-onlyAnalyze broken"
- <li>Fixed issue 1853011 - "Typo: Field names should start
- with aN lower case letter"
- <li>Fixed issue 1844181 - "JNLP file does not contain all
- necessary JARs"
- <li>Fixed issue 1840245 - "xxxException class does not
- derive from Exception"
- <li>Fixed issue 1840277 - "[M D EC] Typo in bug
- documentation"
- <li>Fixed issue 1782447 - "OutOfMemoryError if i activate
- Findbugs on my project"
- <li>Fixed issue 1830576 - "[regression] keySet/entrySet
- false positive"
- </ul>
- </li>
- <li>Other:
- <ul>
- <li>New bug code: "IO" (for
- IO_APPENDING_TO_OBJECT_OUTPUT_STREAM)</li>
- <li>Added "-onlyMostRecent" option for computeBugHistory
- script/ant task
- <li>More explicit language in
- RV_RETURN_VALUE_IGNORED_BAD_PRACTICE messages
- <li>Modified ResourceValueAnalysis to correctly identify
- null == X or null != X as a null check (for issue 1844671)
- <li>Modified DMI_HARDCODED_ABSOLUTE_FILENAME logic in
- DumbMethodInvocations to ignore files from /etc or /dev and
- increase priority of files from /home
- <li>Better bug details for infinite loop warnings
- <li>Modified unread-fields detector to reduce false
- positives from reflective fields
- <li>build.xml "classes" target now builds all sources in one
- step
- </ul>
- </li>
- </ul>
-
- <p>Changes since version 1.2.1</p>
- <ul>
- <li>New Detectors and Reports
- <ul>
- <li>SynchronizationOnSharedBuiltinConstant
- <ul>
- <li>DL_SYNCHRONIZATION_ON_SHARED_CONSTANT: The code
- synchronizes on a shared primitive constant, such as an
- interned String. Such constants are interned and shared across
- all other classes loaded by the JVM. Thus, this could be
- locking on something that other code might also be locking.
- This could result in very strange and hard to diagnose
- blocking and deadlock behavior. See <a
- href="http://www.javalobby.org/java/forums/t96352.html">http://www.javalobby.org/java/forums/t96352.html</a>
- and <a href="http://jira.codehaus.org/browse/JETTY-352">http://jira.codehaus.org/browse/JETTY-352</a>.
-
- </ul>
- </li>
- <li>OverridingEqualsNotSymmetrical
- <ul>
- <li>EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC: Looks for equals
- methods that override equals methods in a superclass where the
- equivalence relationship might not be symmetrical.
- </ul>
- </li>
- <li>CheckTypeQualifiers
- <ul>
- <li>TQ_ALWAYS_VALUE_USED_WHERE_NEVER_REQUIRED: A value
- specified as carrying a type qualifier annotation is consumed
- in a location or locations requiring that the value not carry
- that annotation. More precisely, a value annotated with a type
- qualifier specifying when=ALWAYS is guaranteed to reach a use
- or uses where the same type qualifier specifies when=NEVER.</li>
- <li>TQ_NEVER_VALUE_USED_WHERE_ALWAYS_REQUIRED: A value
- specified as not carrying a type qualifier annotation is
- guaranteed to be consumed in a location or locations requiring
- that the value does carry that annotation. More precisely, a
- value annotated with a type qualifier specifying when=NEVER is
- guaranteed to reach a use or uses where the same type
- qualifier specifies when=ALWAYS.</li>
- <li>TQ_MAYBE_SOURCE_VALUE_REACHES_ALWAYS_SINK: A value
- that might not carry a type qualifier annotation reaches a use
- which requires that annotation.</li>
- <li>TQ_MAYBE_SOURCE_VALUE_REACHES_NEVER_SINK: A value
- which might carry a type qualifier annotation reaches a use
- which forbids values carrying that annotation.</li>
- </ul>
- </li>
- </ul>
- </li>
- <li>New Reports (existing detectors)
- <ul>
- <li>FindHEmismatch
- <ul>
- <li>EQ_DOESNT_OVERRIDE_EQUALS: This class extends a class
- that defines an equals method and adds fields, but doesn't
- define an equals method itself. Thus, equality on instances of
- this class will ignore the identity of the subclass and the
- added fields. Be sure this is what is intended, and that you
- don't need to override the equals method. Even if you don't
- need to override the equals method, consider overriding it
- anyway to document the fact that the equals method for the
- subclass just return the result of invoking super.equals(o).</li>
- </ul>
- </li>
- <li>Naming
- <ul>
- <li>NM_WRONG_PACKAGE, NM_WRONG_PACKAGE_INTENTIONAL: The
- method in the subclass doesn't override a similar method in a
- superclass because the type of a parameter doesn't exactly
- match the type of the corresponding parameter in the
- superclass.</li>
- <li>NM_SAME_SIMPLE_NAME_AS_SUPERCLASS: This class has a
- simple name that is identical to that of its superclass,
- except that its superclass is in a different package (e.g., <code>alpha.Foo</code>
- extends <code>beta.Foo</code>). This can be exceptionally
- confusing, create lots of situations in which you have to look
- at import statements to resolve references and creates many
- opportunities to accidently define methods that do not
- override methods in their superclasses.
- </li>
- <li>NM_SAME_SIMPLE_NAME_AS_INTERFACE: This class/interface
- has a simple name that is identical to that of an
- implemented/extended interface, except that the interface is
- in a different package (e.g., <code>alpha.Foo</code> extends <code>beta.Foo</code>).
- This can be exceptionally confusing, create lots of situations
- in which you have to look at import statements to resolve
- references and creates many opportunities to accidently define
- methods that do not override methods in their superclasses.
- </li>
- </ul>
- <li>FindRefComparison
- <ul>
- <li>EC_UNRELATED_TYPES_USING_POINTER_EQUALITY: This method
- uses using pointer equality to compare two references that
- seem to be of different types. The result of this comparison
- will always be false at runtime.</li>
- </ul>
- </li>
- <li>IncompatMask
- <ul>
- <li>BIT_SIGNED_CHECK, BIT_SIGNED_CHECK_HIGH_BIT: This
- method compares an expression such as <tt>((event.detail
- & SWT.SELECTED) > 0)</tt>. Using bit arithmetic and then
- comparing with the greater than operator can lead to
- unexpected results (of course depending on the value of
- SWT.SELECTED). If SWT.SELECTED is a negative number, this is a
- candidate for a bug. Even when SWT.SELECTED is not negative,
- it seems good practice to use '!= 0' instead of '> 0'.
- </li>
- </ul>
- </li>
- <li>LazyInit
- <ul>
- <li>LI_LAZY_INIT_UPDATE_STATIC: This method contains an
- unsynchronized lazy initialization of a static field. After
- the field is set, the object stored into that location is
- further accessed. The setting of the field is visible to other
- threads as soon as it is set. If the further accesses in the
- method that set the field serve to initialize the object, then
- you have a <em>very serious</em> multithreading bug, unless
- something else prevents any other thread from accessing the
- stored object until it is fully initialized.
- </li>
- </ul>
- </li>
- <li>FindDeadLocalStores
- <ul>
- <li>DLS_DEAD_STORE_OF_CLASS_LITERAL: This instruction
- assigns a class literal to a variable and then never uses it.
- <a href="//java.sun.com/j2se/1.5.0/compatibility.html#literal">The
- behavior of this differs in Java 1.4 and in Java 5.</a> In Java
- 1.4 and earlier, a reference to <code>Foo.class</code> would
- force the static initializer for <code>Foo</code> to be
- executed, if it has not been executed already. In Java 5 and
- later, it does not. See Sun's <a
- href="//java.sun.com/j2se/1.5.0/compatibility.html#literal">article
- on Java SE compatibility</a> for more details and examples, and
- suggestions on how to force class initialization in Java 5.
- </li>
- </ul>
- </li>
- <li>MethodReturnCheck
- <ul>
- <li>RV_RETURN_VALUE_IGNORED_BAD_PRACTICE: This method
- returns a value that is not checked. The return value should
- be checked since it can indication an unusual or unexpected
- function execution. For example, the <code>File.delete()</code>
- method returns false if the file could not be successfully
- deleted (rather than throwing an Exception). If you don't
- check the result, you won't notice if the method invocation
- signals unexpected behavior by returning an atypical return
- value.
- </li>
- <li>RV_EXCEPTION_NOT_THROWN: This code creates an
- exception (or error) object, but doesn't do anything with it.
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li>Changes to Existing Reports
- <ul>
- <li>NS_NON_SHORT_CIRCUIT: BAD_PRACTICE -> STYLE</li>
- <li>NS_DANGEROUS_NON_SHORT_CIRCUIT: CORRECTNESS -> STYLE</li>
- <li>RC_REF_COMPARISON: CORRECTNESS -> BAD_PRACTICE</li>
- </ul>
- </li>
- <li>GUI Changes
- <ul>
- <li>Added importing and exporting of bug filters</li>
- <li>Better handling of failed analysis runs</li>
- <li>Added "-look" parameter for selecting look-and-feel</li>
- <li>Fixed incorrect package filtering</li>
- <li>Fixed issue where "synchronized" was not
- syntax-highlighted</li>
- </ul>
- </li>
- <li>Ant-task Changes
- <ul>
- <li>Refactored common ant-task code to AbstractFindBugsTask</li>
- <li>Added tasks for computeBugHistory, convertXmlToText,
- filterBugs, mineBugHistory, setBugDatabaseInfo</li>
- </ul>
- </li>
- <li>Manual
- <ul>
- <li>Updates to GUI section, including new screenshots</li>
- <li>Added description of rejarForAnalysis</li>
- <li>Revamp of data-mining section</li>
- </ul>
- </li>
- <li>Other Major
- <ul>
- <li>Internal restructuring for lower memory overhead</li>
- </ul>
- </li>
- <li>Other Minor
- <ul>
- <li>Fixed typo: was STCAL_STATIC_SIMPLE_DATA_FORMAT_INSTANCE
- now STCAL_STATIC_SIMPLE_DATE_FORMAT_INSTANCE</li>
- <li>-outputFile parameter became -output</li>
- <li>More sensitivity and specificity inLazyInit detector</li>
- <li>More sensitivity and specificity in Naming detector</li>
- <li>More sensitivity and specificity in UnreadFields
- detector</li>
- <li>More sensitivity in FindNullDeref detector</li>
- <li>More sensitivity in FindBadCast2 detector</li>
- <li>More specificity in FindReturnRef detector</li>
- <li>Many other tweaks and bug fixes</li>
- </ul>
- </li>
- </ul>
-
- <p>Changes since version 1.2.0</p>
- <ul>
- <li>Bug fixes:
- <ul>
- <li><a
- href="http://fisheye2.cenqua.com/changelog/findbugs/?cs=8219">Fix</a>
- <a
- href="http://sourceforge.net/tracker/index.php?func=detail&aid=1726946&group_id=96405&atid=614693">bug</a>
- with detectors that were requested to be disabled but were
- enabled due to requirements of other detectors.</li>
- <li>Fix bugs in incremental analysis within Eclipse plugin</li>
- <li>Fix some analysis errors</li>
- <li>Fix some threading bugs in GUI2</li>
- <li>Report version as version when it was compiled, not when
- it was run</li>
- <li>Copy analysis time stamp when filtering or transforming
- analysis files.</li>
- </ul>
- <li>Enabled StaticCalendarDetector</li>
- <li>Reworked GUI2 to use standard FindBugs filters
- <ul>
- <li>Allow a suppression filter to be stored in a project and
- persisted to the XML representation of a project.</li>
- </ul>
- </li>
-
- <li>Move away from old GUI2 save format (a directory
- containing an xml file and another file containing serialized
- filters).</li>
- <li>Support/recommend use of two new file extensions/formats:
- <dl>
- <dt>.fba - FindBugs Analysis File</dt>
- <dd>Exactly the same as an existing bug collection file
- stored in XML format, but using a distinct file extension to
- make it easier to figure out which xml files contain FindBugs
- results.</dd>
- <dt>.fbp - FindBugs Project File</dt>
- <dd>Contains just the information needed to run FindBugs and
- display the results (e.g., the files to be analyzed, the
- auxiliary class path and the location of source files)
- </dl>
- </li>
- </ul>
- <p>Changes since version 1.1.3</p>
- <ul>
- <li>Added -xml:withAbridgedMessages option to generate xml
- containing shorter messages. The messages will be shorted by doing
- things like eliding package names, and leaving off the source line
- from the LongMessage. These messages are appropriate if being used
- in a context where the non-message components of the bug
- annotations will be used to provide more information (e.g.,
- clicking on the message for a MethodAnnotation will display the
- source for the method).
- <ul>
- <li>FindBugsDisplayFeatures.setAbridgedMessages(true) can be
- used to generate abridged messages when FindBugs is being
- accessed directly (not via generated XML) from a GUI or IDE.</li>
- </ul>
- <li>In null pointer analysis, try to be better about always
- showing two locations: where it is known null and where it is
- dereferenced.
- <li>Interprocedural analysis of which methods return nonnull
- values
- <li>Use method calls to select order in which classes are
- analyzed, and order in which methods are analyzed, to improve
- interprocedural analysis results.
- <li>Significant improvements in memory footprint, memory
- allocation and CPU utilization (20-30% reduction in all three)
- <li>Added a project name, to provide better descriptions in
- the HTML output.
- <li>Added new bug pattern: Casting to char, or bit masking
- with nonnegative value, and then checking to see if the result is
- negative.
- <li>Stopped reporting transient fields of classes not marked
- as serializable. Transient is used by other persistence
- frameworks.
- <li>Improvements to detector for SQL injection (Thanks to <a
- href="http://www.clock.org/~matt">Matt Hargett</a> for his
- contributions
- <li>Changed open/save options in GUI2 to not distinguish
- between FindBugs projects and saved FindBugs analysis results.
- <li>Improvements to detection of serious non-short-circuit
- evaluation.
- <li>Updated Japanese localization (thanks to Ruimo Uno)
- <li>Eclipse plugin changes:
- <ul>
- <li>Created Bug User Annotations and Bug Tree Views
- <li>Use different icons for different bug priorities
- <li>Provide more information in Bug Details view
- </ul>
- </ul>
-
- <p>Changes since version 1.1.2:</p>
- <ul>
- <li>Fixed broken Ant task
- <li>Added running ant task to smoke test
- <li>Added validating xml and html output to smoke test
- <li>Fixed some (but not all) issues with html output
- validation
- <li>Added check for x.equals(x) and x.compareTo(x)
- <li>Various bug fixes
- </ul>
- <p>Changes since version 1.1.1:</p>
- <ul>
- <li>Added check for infinite iterative loops</li>
- <li>Added check for use of incompatible types in a collection
- (e.g., checking to see if a Set<String> contains a
- StringBuffer).</li>
- <li>Added check for invocations of equals or hashCode on a
- URL, which, <a
- href="http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html">surprising
- many people</a>, requires DNS resolution.
- </li>
- <li>Added check for classes that define compareTo but not
- equals; such classes can exhibit some anomalous behavior (e.g.,
- they are treated differently by PriorityQueues in Java 5 and Java
- 6).</li>
- <li>Added a check for useless self operations (e.g., x < x
- or x ^ x).</li>
- <li>Fixed a data race that could cause the GUI to fail on
- startup</li>
- <li>Partial internationalization of the new GUI</li>
- <li>Fix bug in "Redo analysis" option of new GUI</li>
- <li>Tuning to reduce false positives</li>
- <li>Fixed a bug in null pointer analysis that was generating
- false positive null pointer warnings on exception paths. Fixing
- this bug eliminates about 1/4 of the warnings on null pointer
- exceptions on exception paths.</li>
- <li>Fixed a bug in the processing of phi nodes for fields in
- the null pointer analysis</li>
- <li>Applied contributed patch that provides more quick fixes
- in Eclipse plugin.</li>
- <li>Fixed a number of bugs in the Eclipse auto update sites,
- and in the way date qualifiers were being used in the Eclipse
- plugin. You may need to manually disable your existing version of
- the plugin and download the 1.1.2 from the update site to get the
- automatic update function working correctly. The Eclipse update
- sites are described at <a
- href="http://findbugs.cs.umd.edu/eclipse/">http://findbugs.cs.umd.edu/eclipse/</a>.
-
- </li>
- <li>Fixed progress bar in Eclipse plugin</li>
- <li>A number of other bug fixes.</li>
- </ul>
-
- <p>Changes since version 1.1.0:</p>
- <ul>
- <li>less scanning of classes not on the analysis path (This
- was causing some performance problems.)</li>
- <li>no unread field warnings for fields annotated with
- javax.persistent or javax.ejb3</li>
- <li>Eclipse plugin
- <ul>
- <li>bug annotation info displayed in Bug Details tab</li>
- <li>.fbwarnings data file now stored in .metadata (not in
- the project itself)</li>
- </ul>
- </li>
- <li>new SE_BAD_FIELD_INNER_CLASS pattern</li>
- <li>updates to Japanese translation (ruimo)</li>
- <li>fix some internal slashed/dotted path confusion</li>
- <li>other minor improvements</li>
- </ul>
-
- <p>Changes since version 1.0.0:</p>
-
- <ul>
- <li>Overall, the change from FindBugs 1.0.0 to FindBugs 1.1.0
- has been a big change. We've done a lot of work in a lot of areas,
- and aren't even going to try to enumerate all the changes.</li>
- <li>We spent a lot of time reviewing the results generated by
- FindBugs for open source and commercial code bases, and made a
- number of changes, small and large, to minimize the number of
- false positives. Our primary focus for this was warnings reported
- as high and medium priority correctness warnings. Our internal
- evaluation is that we produce very few high/medium priority
- correctness warnings where the analysis is actually wrong, and
- that more than 75% of the high/medium priority correctness
- warnings correspond to real coding defects that need addressing in
- the source code. The remaining 25% are largely cases such as a
- branch or statement that if taken would lead to an error, but in
- fact is a dead branch or statement that can never be taken. Such
- coding is confusing and hard to maintain, so it should arguably be
- fixed, but it is unlikely to actually result in an error during
- execution. Thus, some might classify those warnings as false
- positives.</li>
- <li>We've substantially improved the analysis for errors that
- could result in null pointer dereferences. Overall, our experience
- has been that these changes have roughly doubled the number of
- null pointer errors we detect, without increasing the number of
- false positives (in fact, our false positive rate has gone down).
- The improvements are due to four factors:
- <ul>
- <li>By default, we now do some interprocedural analysis to
- determine methods that unconditionally dereference their
- parameters.</li>
- <li>FindBugs also comes with a model of which JDK methods
- unconditionally dereference their parameters.</li>
- <li>We do limited tracking of fields, so that we can detect
- null values stored in fields that lead to exceptions.</li>
- <li>We implemented a new analysis technique to find
- guaranteed dereferences. Consider the following example: <pre>public int f(Object x, boolean b) {
+
+ <li>Changes by Andrey Loskutov
+ <ul>
+ <li>fixed job scheduling errors in 3.8/4.2 Eclipse <a
+ href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=393748">bug
+ report</a>
+ <li>more realistic progress bar updates for jobs
+ <li>added nullness annotations for some common Eclipse API
+ methods known to usually return null values
+ <li>Added support for org.eclipse.jdt.annotation.Nullable,
+ NonNull and NonNullByDefault annotations (introduced with
+ Eclipse 3.8/4.2)</li>
+ </ul>
+ <li>Documentation improvements
+ <li><a href="http://code.google.com/p/findbugs/source/list">lots
+ of other small changes</a>
+ </ul>
+ <h1>FindBugs Change Log, Version 2.0.1</h1>
+
+ <ul>
+ <li>New bug patterns; in some cases, bugs previous reported as
+ other bug patterns are reported as instances of these new bug
+ patterns in order to make it easier for developers to understand
+ the bug reports
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#PT_ABSOLUTE_PATH_TRAVERSAL">PT_ABSOLUTE_PATH_TRAVERSAL</a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#PT_RELATIVE_PATH_TRAVERSAL">PT_RELATIVE_PATH_TRAVERSAL</a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR">NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR</a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#MS_SHOULD_BE_REFACTORED_TO_BE_FINAL">MS_SHOULD_BE_REFACTORED_TO_BE_FINAL</a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_UNCONFIRMED_CAST_OF_RETURN_VALUE">BC_UNCONFIRMED_CAST_OF_RETURN_VALUE</a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#PT_ABSOLUTE_PATH_TRAVERSAL">PT_ABSOLUTE_PATH_TRAVERSAL</a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#TQ_COMPARING_VALUES_WITH_INCOMPATIBLE_TYPE_QUALIFIERS">TQ_COMPARING_VALUES_WITH_INCOMPATIBLE_TYPE_QUALIFIERS</a></li>
+ </ul>
+ </li>
+
+ <li>Changes to fix false negatives for the following bug
+ patterns: <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_UNCONFIRMED_CAST">BC_UNCONFIRMED_CAST</a>,
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_BAD_ARRAY_COMPARE">EC_BAD_ARRAY_COMPARE</a>,
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#EQ_UNUSUAL">EQ_UNUSUAL</a>,
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#GC_UNRELATED_TYPES">GC_UNRELATED_TYPES</a>,
+ and <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE">NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE</a>.
+ </li>
+
+ <li>Changes to fix false positions for the following bug
+ patterns: <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DMI_DOH">DMI_DOH</a>,
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_UNRELATED_TYPES">EC_UNRELATED_TYPES</a>,
+ and <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#SE_BAD_FIELD">SE_BAD_FIELD</a>.
+ </li>
+ </ul>
+
+ <h1>FindBugs Change Log, Version 2.0.0</h1>
+
+ <h2>Changes since version 1.3.8</h2>
+ <ul>
+ <li>New bug patterns; in some cases, bugs previous reported as
+ other bug patterns are reported as instances of these new bug
+ patterns in order to make it easier for developers to understand
+ the bug reports
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_IMPOSSIBLE_DOWNCAST ">BC_IMPOSSIBLE_DOWNCAST
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY ">BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_INCOMPATIBLE_ARRAY_COMPARE ">EC_INCOMPATIBLE_ARRAY_COMPARE
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#JLM_JSR166_UTILCONCURRENT_MONITORENTER ">JLM_JSR166_UTILCONCURRENT_MONITORENTER
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE ">LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_CLOSING_NULL ">NP_CLOSING_NULL
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RC_REF_COMPARISON_BAD_PRACTICE ">RC_REF_COMPARISON_BAD_PRACTICE
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN ">RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED ">RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#SIC_THREADLOCAL_DEADLY_EMBRACE ">SIC_THREADLOCAL_DEADLY_EMBRACE
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR ">UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR
+ </a></li>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED ">VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED
+ </a></li>
+ </ul>
+ </li>
+ <li>Providing a bug rank (1-20), and the ability to filter by
+ bug rank. Eventually, it will be possible to specify your own
+ rules for ranking bugs, but the procedure for doing so hasn't been
+ specified yet.</li>
+ <li>Fixed about <a
+ href="https://sourceforge.net/search/index.php?group_id=96405&search_summary=1&search_details=1&type_of_search=artifact&group_artifact_id%5B%5D=614693&open_date_start=2009-03-16&open_date_end=2009-08-20&form_submit=Search">45
+ bugs filed</a> through SourceForge
+ </li>
+ <li>Various reclassifications and priority tweaks</li>
+ <li>Added more bug annotations to a variety of bug reports.
+ This provides more context for understanding bug reports (e.g., if
+ the value in question was is the return value of a method, the
+ method is described as the source of the value in a bug
+ annotation). This also provide more accurate tracking of issues
+ across versions of the code being analyzed, but has the downside
+ that when comparing results from FindBugs 1.3.8 and FindBugs 1.3.9
+ on the same version of code being analyzed, FindBugs may think
+ that mistakenly believe that the issue reported by 1.3.8 was fixed
+ and a new issue was introduced that was reported by FindBugs
+ 1.3.9. While annoying, it would be unusual for more than a dozen
+ issues per million lines of codes to be mistracked.</li>
+ <li>Lots of internal changes moving towards FindBugs 2.0, but
+ these features are undocumented, not yet officially supported, and
+ subject to radical changes before FindBugs 2.0 is released.</li>
+ </ul>
+
+ <p>Changes since version 1.3.8</p>
+ <ul>
+ <li>New bug patterns; in some cases, bugs previous reported as
+ other bug patterns are reported as instances of these new bug
+ patterns in order to make it easier for developers to understand
+ the bug reports
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_IMPOSSIBLE_DOWNCAST ">BC_IMPOSSIBLE_DOWNCAST
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY ">BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#EC_INCOMPATIBLE_ARRAY_COMPARE ">EC_INCOMPATIBLE_ARRAY_COMPARE
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#JLM_JSR166_UTILCONCURRENT_MONITORENTER ">JLM_JSR166_UTILCONCURRENT_MONITORENTER
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE ">LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_CLOSING_NULL ">NP_CLOSING_NULL
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RC_REF_COMPARISON_BAD_PRACTICE ">RC_REF_COMPARISON_BAD_PRACTICE
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN ">RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED ">RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#SIC_THREADLOCAL_DEADLY_EMBRACE ">SIC_THREADLOCAL_DEADLY_EMBRACE
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR ">UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR
+ </a>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED ">VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED
+ </a>
+ </ul>
+ </li>
+ <li>Providing a bug rank (1-20), and the ability to filter by
+ bug rank. Eventually, it will be possible to specify your own
+ rules for ranking bugs, but the procedure for doing so hasn't been
+ specified yet.</li>
+ <li>Fixed about <a
+ href="https://sourceforge.net/search/index.php?group_id=96405&search_summary=1&search_details=1&type_of_search=artifact&group_artifact_id%5B%5D=614693&open_date_start=2009-03-16&open_date_end=2009-08-20&form_submit=Search">45
+ bugs filed</a> through SourceForge
+ </li>
+ <li>Various reclassifications and priority tweaks</li>
+ <li>Added more bug annotations to a variety of bug reports.
+ This provides more context for understanding bug reports (e.g., if
+ the value in question was is the return value of a method, the
+ method is described as the source of the value in a bug
+ annotation). This also provide more accurate tracking of issues
+ across versions of the code being analyzed, but has the downside
+ that when comparing results from FindBugs 1.3.8 and FindBugs 1.3.9
+ on the same version of code being analyzed, FindBugs may think
+ that mistakenly believe that the issue reported by 1.3.8 was fixed
+ and a new issue was introduced that was reported by FindBugs
+ 1.3.9. While annoying, it would be unusual for more than a dozen
+ issues per million lines of codes to be mistracked.</li>
+ <li>Lots of internal changes moving towards FindBugs 2.0, but
+ these features are undocumented, not yet officially supported, and
+ subject to radical changes before FindBugs 2.0 is released.</li>
+ </ul>
+
+ <p>Changes since version 1.3.7</p>
+ <ul>
+ <li>Primarily another small bugfix release.</li>
+ <li>FindBugs base:
+ <ul>
+ <li>New Reports:
+ <ul>
+ <li>SF_SWITCH_NO_DEFAULT: missing default case in switch
+ statement.</li>
+ <li>SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH_TO_THROW:
+ value ignored when switch fallthrough leads to thrown
+ exception.</li>
+ <li>INT_VACUOUS_BIT_OPERATION: bit operations that don't
+ do any meaningful work.</li>
+ <li>FB_UNEXPECTED_WARNING: warning generated that
+ conflicts with @NoWarning FindBugs annotation.</li>
+ <li>FB_MISSING_EXPECTED_WARNING: warning not generated
+ despite presence of @ExpectedWarning FindBugs annotation.</li>
+ <li>NOISE category: intended for use in data mining
+ experiments.
+ <ul>
+ <li>NOISE_NULL_DEREFERENCE: fake null point dereference
+ warning.</li>
+ <li>NOISE_METHOD_CALL: fake method call warning.</li>
+ <li>NOISE_FIELD_REFERENCE: fake field dereference
+ warning.</li>
+ <li>NOISE_OPERATION: fake operation warning.</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>Other:
+ <ul>
+ <li>Garvin Leclaire has created a new Apache Maven
+ repository for FindBugs at <a
+ href="http://code.google.com/p/findbugs/">the Google Code
+ FindBugs SVN repository</a>. (Thanks Garvin!)
+ </li>
+ </ul>
+ </li>
+ <li>Fixes:
+ <ul>
+ <li>[ 2317842 ] Highlighting broken in Windows</li>
+ <li>[ 2515908 ] check for oddness should track sign of
+ argument</li>
+ <li>[ 2487936 ] "L B GC" false pos cast from
+ Map.Entry.getKey() to Map.get()</li>
+ <li>[ 2528264 ] Ant tasks not compatible with Ant 1.7.1</li>
+ <li>[ 2539590 ] SF_SWITCH_FALLTHROUGH wrong message
+ reported</li>
+ <li>[ 2020066 ] Bug history displayed in fancy-hist.xsl is
+ incorrect</li>
+ <li>[ 2545098 ] Invalid character in analysis results file</li>
+ <li>[ 2492673 ] Plugin sites should specify "requires
+ Eclipse 3.3 or newer"</li>
+ <li>[ 2588044 ] a tiny typing error</li>
+ <li>[ 2589048 ] Documentation for convertXmlToText
+ insufficient</li>
+ <li>[ 2638739 ] NullPointerException when building</li>
+ </ul>
+ </li>
+ <li>Patches:
+ <ul>
+ <li>[ 2538184 ] Make BugCollection implement
+ Iterable<BugInstance> (thanks to Tomas Pollak)</li>
+ <li>[ 2249771 ] Add Maven2 Findbugs plugin link to the
+ Links page (thanks to Garvin Leclaire)</li>
+ <li>[ 2609526 ] Japanese manual update (thanks to K.
+ Hashimoto)</li>
+ <li>[ 2119482 ] CheckBcel checks for nonexistent classes
+ (thanks to Jerry James)</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>FindBugs Eclipse plugin:
+ <ul>
+ <li>Major feature enhancements (thanks to Andrey Loskutov).
+ See <a href="http://andrei.gmxhome.de/findbugs/index.html">this
+ overview</a> for more information.
+ </li>
+ <li>Major test improvements (thanks to Tomas Pollak).</li>
+ <li>Fixes:
+ <ul>
+ <li>[ 2532365 ] Compiler warning</li>
+ <li>[ 2522989 ] Fix filter files selection</li>
+ <li>[ 2504068 ] NullPointerException</li>
+ <li>[ 2640849 ] NPE in Eclipse plugin 1.3.7 and Eclipse
+ 3.5 M5</li>
+ </ul>
+ </li>
+ <li>Patches:
+ <ul>
+ <li>[ 2143140 ] Unchecked conversion fixes for Eclipse
+ plugin (thanks to Jerry James)
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+
+ <p>Changes since version 1.3.6</p>
+ <ul>
+ <li>Overall, a small bugfix release.
+ <li>New detection of accidental vacuous/useless calls to
+ EasyMock methods, and of generic signatures that proclaim the use
+ of unhashable classes in ways that require that they be hashed.
+ <li>Eliminate some false positives where we were warning about
+ a useless call (e.g., comparing two incompatible types for
+ equality), but the only thing the code was doing with the result
+ was passing it to assertFalse.
+ <li>Japanese localization and manual by K.Hashimoto. (Thanks!)
+
+ <li>Added -exclude and -outputDir command line options to
+ rejarForAnalysis
+ <li>Extended -adjustPriorities option to FindBugs analysis
+ textui so that you can modify the priorities of individual bug
+ patterns as well as visitors, and also completely suppress
+ individual bug patterns or visitors.
+ <ul>
+ <li>e.g., -adjustPriority
+ MS_SHOULD_BE_FINAL=suppress,MS_PKGPROTECT=suppress,EI_EXPOSE_REP=suppress,EI_EXPOSE_REP2=suppress,PZLA_PREFER_ZERO_LENGTH_ARRAYS=raise
+
+ </ul>
+ </ul>
+
+
+ <p>Changes since version 1.3.5</p>
+ <ul>
+ <li>Added fairly exhaustive static analysis of uses of format
+ strings, checking for missing or extra arguements, invalid format
+ specifiers, or mismatched format specifiers and arguments (e.g,
+ passing a String value for a %d format specifier). The logic for
+ doing so is derived from Sun's java.util.Formatter class, and
+ available separately from FindBugs as part of the <a
+ href="https://jformatstring.dev.java.net/">jFormatString</a>
+ project.
+ <li>More tuning of the unsatisfied obligation detector. Since
+ this detector is still rather noisy and an unfinished research
+ project, I've moved the generated issues to a new category:
+ EXPERIMENTAL.
+ <li>Added check for <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BIT_ADD_OF_SIGNED_BYTE">BIT_ADD_OF_SIGNED_BYTE</a>;
+ similar to <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BIT_IOR_OF_SIGNED_BYTE">BIT_IOR_OF_SIGNED_BYTE</a>,
+ except that addition is being used to combine shifted signed
+ bytes.
+ <li>Changed detection of EI_EXPOSE_REP2, so we only report it
+ if the value stored is guaranteed to be the same value that was
+ passed in as a parameter.
+ <li>Added <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS">EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS</a>,
+ a warning when an equals method checks to see if an operand is an
+ instance of a class not compatible with itself. For example, if
+ the Foo class checks to see if the argument is an instance of
+ String. This is either a questionable design decision or a coding
+ mistake.
+ <li>Added <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DMI_INVOKING_HASHCODE_ON_ARRAY">DMI_INVOKING_HASHCODE_ON_ARRAY</a>,
+ which checks for invoking <code>hashCode()</code> on an array,
+ which returns a hash code that ignores the contents of the array.
+
+ <li>Added checks for using <code>x.removeAll(x)</code> to
+ rather than <code>x.clear()</code> to clear an array.
+ <li>Add checks for calls such as <code>x.contains(x)</code>, <code>x.remove(x)</code>
+ and <code>x.containsAll(x)</code>.
+ <li>Improvements to Eclipse plugin (thanks to Andrey
+ Loskutov):
+ <ul>
+ <li>Report separate markers for each occurrence of an issue
+ that appears multiple times in a method
+ <li>fine tuning for reported markers: add only one marker
+ for fields, add marker on right position
+ <li>link bugs selected in bug explorer view to the opened
+ editor and vice versa
+ <li>select bugs selected in editor ruler in the opened bug
+ explorer view
+ <li>consistent abbreviations used in both bug explorer and
+ bug details view
+ <li>added "Expand All" button to the bug explorer view
+ <li>added "Go Into/Go Up" buttons to the bug explorer view
+ <li>added "Copy to clipboard" menu/functionality to the
+ details view list widget
+ <li>fix for CNF exception if loading the backup solution for
+ broken browser widget
+ </ul>
+ </ul>
+
+
+
+ <p>Changes since version 1.3.4</p>
+ <ul>
+ <li>Analysis about 15% faster
+ <li><a
+ href="http://sourceforge.net/tracker/?atid=614693&group_id=96405&func=browse&status=closed">38
+ bugs closed</a></li>
+ <li>New defect warnings:
+ <ul>
+ <li>calls to methods that always throw
+ UnsupportedOperationException (DMI_UNSUPPORTED_METHOD)
+ <li>repeated conditional tests (e.g., <code>if (x
+ < 0 || x < 0) ...</code>) (RpC_REPEATED_CONDITIONAL_TEST)
+ <li>Complete rewrite of detector for format string problems.
+ More accurate, finds more problems, generates more descriptive
+ reports, several different bug pattern
+ (VA_FORMAT_STRING_EXTRA_ARGUMENTS_PASSED,
+ VA_FORMAT_STRING_ILLEGAL, VA_FORMAT_STRING_MISSING_ARGUMENT,
+ VA_FORMAT_STRING_BAD_ARGUMENT,
+ VA_FORMAT_STRING_NO_PREVIOUS_ARGUMENT)
+ <li>Fairly complete implementation of JSR-305 custom type
+ qualifier analysis (no support for custom validators yet).
+ (TQ_MAYBE_SOURCE_VALUE_REACHES_NEVER_SINK
+ TQ_EXPLICIT_UNKNOWN_SOURCE_VALUE_REACHES_ALWAYS_SINK
+ TQ_EXPLICIT_UNKNOWN_SOURCE_VALUE_REACHES_NEVER_SINK)
+ <li>New detector for unsatisfied obligations such forgetting
+ to close a file (OBL_UNSATISFIED_OBLIGATION).
+ <li>Warning when a parameter is marked as nullable, but is
+ always dereferenced.
+ (NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE)
+ <lI>Separate warning for dereference the result of readLine
+ (NP_DEREFERENCE_OF_READLINE_VALUE)
+ </ul>
+ <li>When XML is generated with messages, the project stats now
+ include <FileStat> elements. For each source file, this
+ gives the path for the file, the total number of warnings for that
+ file, and a bugHash for the file. While the instanceHash for a bug
+ is intended to be version invariant (ignoring line numbers, etc),
+ the bugHash for a file is intended to reflect all the information
+ about the warnings in that file. The intended use case is that if
+ the bugHash for a file is the same in two analysis runs, then <em>nothing</em>
+ has changed about any of the warnings reported for that file
+ between the two analysis runs.
+ <li>More merging of similar issues within a method. For
+ example, if the result of readLine() is dereferences multiple
+ times within a method, it will be reported as a single warning
+ with occurrences at multiple source lines.
+ </ul>
+ <p>Changes since version 1.3.3</p>
+
+ <ul>
+ <li>FindBugs base
+ <ul>
+ <li>New Reports:
+ <ul>
+ <li>EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC: equals method
+ overrides equals in superclass and may not be symmetric</li>
+ <li>EQ_ALWAYS_TRUE: equals method always returns true</li>
+ <li>EQ_ALWAYS_FALSE: equals method always returns false</li>
+ <li>EQ_COMPARING_CLASS_NAMES: equals method compares class
+ names rather than class objects</li>
+ <li>EQ_UNUSUAL: Unusual equals method</li>
+ <li>EQ_GETCLASS_AND_CLASS_CONSTANT: equals method fails
+ for subtypes</li>
+ <li>SE_READ_RESOLVE_IS_STATIC: The readResolve method must
+ not be declared as a static method.</li>
+ <li>SE_PRIVATE_READ_RESOLVE_NOT_INHERITED: private
+ readResolve method not inherited by subclasses</li>
+ <li>MSF_MUTABLE_SERVLET_FIELD: Mutable servlet field</li>
+ <li>XSS_REQUEST_PARAMETER_TO_SEND_ERROR: Servlet reflected
+ cross site scripting vulnerability</li>
+ <li>SKIPPED_CLASS_TOO_BIG: Class too big for analysis</li>
+ </ul>
+ </li>
+ <li>Other:
+ <ul>
+ <li>Value-number analysis now more space-efficient</li>
+ <li>Enhancements to reduce memory overhead when analyzing
+ very large classes</li>
+ <li>Now skips very large classes that would otherwise take
+ too much time and memory to analyze</li>
+ <li>Infrastructure for tracking effectively-constant/
+ effectively-final fields</li>
+ <li>Added more cweids</li>
+ <li>Enhanced taint tracking for taint-based detectors</li>
+ <li>Ignore doomed calls to equals if result is used as an
+ argument to assertFalse</li>
+ <li>EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC handles compareTo</li>
+ <li>Priority tweak for ICAST_INTEGER_MULTIPLY_CAST_TO_LONG
+ (only low priority if multiplying by 1000)</li>
+ <li>Improved tracking of fields across method calls</li>
+ </ul>
+ </li>
+ <li>Fixes:
+ <ul>
+ <li>[ 1941450 ] DLS_DEAD_LOCAL_STORE not reported</li>
+ <li>[ 1953323 ] Omitted break statement in
+ SynchronizeAndNullCheckField</li>
+ <li>[ 1942620 ] Source Directories selection dialog
+ interface confusion (partial)</li>
+ <li>[ 1948275 ] Unhelpful "Load of known null"</li>
+ <li>[ 1933922 ] MWM error in findbugs</li>
+ <li>[ 1934772 ] 1.3.3 appears to rely on JDK 1.6, JNLP
+ still specifies 1.5</li>
+ <li>[ 1933945 ] -loadbugs doesn't work</li>
+ <li>Fixed problems for class names starting with '$'</li>
+ <li>Fixed bugs and incomplete handling of annotations in
+ VersionInsensitiveBugComparator</li>
+ </ul>
+ </li>
+ <li>Patches:
+ <ul>
+ <li>[ 1955106 ] Javadoc fixes</li>
+ <li>[ 1951930 ] Superfluous import statements (thanks to
+ Jerry James)</li>
+ <li>[ 1951907 ] Missing @Deprecated annotations (thanks to
+ Jerry James)</li>
+ <li>[ 1951876 ] Infonode Docking Windows compile fix
+ (thanks to Jerry James)</li>
+ <li>[ 1936055 ] bugfix for findbugs.de.comment not working
+ (thanks to Peter Fokkinga)
+ </ul>
+ </li>
+ </ul>
+ <li>FindBugs BlueJ plugin
+ <ul>
+ <li>Updated to use FindBugs 1.3.4 (first new release since
+ 1.1.3)</li>
+ </ul>
+ </li>
+ </ul>
+
+ <p>Changes since version 1.3.2</p>
+
+ <ul>
+ <li>FindBugs base
+ <ul>
+ <li>New Detectors:
+ <ul>
+ <li>FieldItemSummary: Produces summary information for
+ what is stored into fields</li>
+ <li>SynchronizeOnClassLiteralNotGetClass: Look for code
+ that synchronizes on the results of getClass rather than on
+ class literals</li>
+ <li>SynchronizingOnContentsOfFieldToProtectField: This
+ detector looks for code that seems to be synchronizing on a
+ field in order to guard updates of that field</li>
+ </ul>
+ </li>
+ <li>New BugCode:
+ <ul>
+ <li>HRS: HTTP Response splitting vulnerability</li>
+ <li>WL: Possible locking on wrong object</li>
+ </ul>
+ </li>
+ <li>New Reports:
+ <ul>
+ <li>DMI_CONSTANT_DB_PASSWORD: This code creates a database
+ connect using a hard coded, constant password</li>
+ <li>HRS_REQUEST_PARAMETER_TO_COOKIE: HTTP cookie formed
+ from untrusted input</li>
+ <li>HRS_REQUEST_PARAMETER_TO_HTTP_HEADER: HTTP parameter
+ directly written to HTTP header output</li>
+ <li>CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE: Class defines
+ clone() but doesn't implement Cloneable</li>
+ <li>DL_SYNCHRONIZATION_ON_BOXED_PRIMITIVE: Synchronization
+ on boxed primitive could lead to deadlock</li>
+ <li>DL_SYNCHRONIZATION_ON_BOOLEAN: Synchronization on
+ Boolean could lead to deadlock</li>
+ <li>ML_SYNC_ON_FIELD_TO_GUARD_CHANGING_THAT_FIELD:
+ Synchronization on field in futile attempt to guard that field
+ </li>
+ <li>DLS_DEAD_LOCAL_STORE_IN_RETURN: Useless assignment in
+ return statement</li>
+ <li>WL_USING_GETCLASS_RATHER_THAN_CLASS_LITERAL:
+ Synchronization on getClass rather than class literal</li>
+ </ul>
+ </li>
+ <li>Other:
+ <ul>
+ <li>Many enhancements to cross-site scripting detector and
+ its documentation</li>
+ <li>Enhanced switch fall through handling</li>
+ <li>Enhanced unread field handling (look for IF_ACMPEQ and
+ IF_ACMPNE)</li>
+ <li>Clarified documentation for @Nullable in manual</li>
+ <li>Fewer DeadLocalStore false positives</li>
+ <li>Fewer UnreadField false positives</li>
+ <li>Fewer StaticCalendarDetector false positives</li>
+ <li>Performance fix for slow file system IO e.g. Clearcase
+ repositories (thanks, Andrei!)</li>
+ <li>Other, general performance enhancements (thanks,
+ Andrei!)</li>
+ <li>Enhancements for using FindBugs scripts with MKS on
+ Windows (thanks, Kelly O'Hair!)</li>
+ <li>Noted in the manual that jsr305.jar must be present
+ for annotations to compile</li>
+ <li>Added and fine-tuned default-nullness annotations</li>
+ <li>More CWE IDs added</li>
+ <li>Check and warning for unexpected BCEL version in
+ classpath</li>
+ </ul>
+ </li>
+ <li>Fixes:
+ <ul>
+ <li>Bug fix to handling of local variable tables in BCEL</li>
+ <li>Refined documentation for
+ MTIA_SUSPECT_STRUTS_INSTANCE_FIELD</li>
+ <li>[ 1927295 ] NPE when called on project root</li>
+ <li>[ 1926405 ] Incorrect dead store warning</li>
+ <li>[ 1926409 ] Incorrect redundant nullcheck warning</li>
+ <li>[ 1926389 ] Wrong line number printed/highlighted in
+ bug</li>
+ <li>[ 1927040 ] typo in bug description</li>
+ <li>[ 1926263 ] Minor glitch in HTML output</li>
+ <li>[ 1926240 ] Minor error in standard options in manual</li>
+ <li>[ 1926236 ] Minor bug in installation section of
+ manual</li>
+ <li>[ 1925539 ] ZIP is default file system code base</li>
+ <li>[ 1894701 ] Livelock / memory leak in
+ ObjectTypeFactory (thanks, Andrei!)</li>
+ <li>[ 1867491 ] Doesn't reload annotations after code
+ changes in IDE (thanks, Andrei!)</li>
+ <li>[ 1921399 ] -project option not supported</li>
+ <li>[ 1913834 ] "Dead" store to variable with method call</li>
+ <li>[ 1917352 ] H B se:...field in serializable class</li>
+ <li>[ 1911617 ] CloneIdiom relies on
+ getNameConstantOperand for INSTANCEOF</li>
+ <li>[ 1911620 ] False +: DLS predecrement before return</li>
+ <li>[ 1871376 ] False negative: non-serializable Map field</li>
+ <li>[ 1871051 ] non standard clone() method</li>
+ <li>[ 1908854 ] Error in TestASM</li>
+ <li>[ 1907539 ] 22 minor errors in bug checker
+ documentation</li>
+ <li>[ 1897323 ] EJB implementation class false positives</li>
+ <li>[ 1899648 ] Crash on startup on Vista with Java
+ 1.6.0_04</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>FindBugs Eclipse plugin (change log by Andrey Loskutov)
+ <ul>
+ <li>new feature: export basic FindBugs numbers for projects
+ via File->Export->Java->BugCounts (Andrey Loskutov)</li>
+ <li>new feature: jobs for different projects will be run in
+ parallel per default if running on a multi-core PC
+ ("fb.allowParallelBuild" system property not used anymore)
+ (Andrey Loskutov)</li>
+ <li>fixed performance slowdown in the multi-threaded build,
+ caused by workspace operation locks during assigning marker
+ attributes (Andrey Loskutov)</li>
+ </ul>
+ </li>
+ </ul>
+
+ <p>Changes since version 1.3.1</p>
+
+ <ul>
+ <li>FindBugs base
+ <ul>
+ <li>New Bug Category:
+ <ul>
+ <li>SECURITY (Abbrev: S), A use of untrusted input in a
+ way that could create a remotely exploitable security
+ vulnerability</li>
+ </ul>
+ </li>
+ <li>New Detectors:
+ <ul>
+ <li>CrossSiteScripting: This detector looks for
+ obvious/blatant cases of cross site scripting vulnerabilities</li>
+ </ul>
+ </li>
+ <li>New BugCode:
+ <ul>
+ <li>XSS: Cross site scripting</li>
+ </ul>
+ </li>
+ <li>New Reports:
+ <ul>
+ <li>XSS_REQUEST_PARAMETER_TO_SERVLET_WRITER: HTTP
+ parameter directly written to Servlet output, giving XSS
+ vulnerability</li>
+ <li>XSS_REQUEST_PARAMETER_TO_JSP_WRITER: HTTP parameter
+ directly written to JSP output, giving XSS vulnerability</li>
+ <li>EQ_OTHER_USE_OBJECT: equals() method defined that
+ doesn't override Object.equals(Object)</li>
+ <li>EQ_OTHER_NO_OBJECT: equals() method inherits rather
+ than overrides equals(Object)</li>
+ <li>NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE: Possible
+ null pointer dereference on path that might be infeasible</li>
+ </ul>
+ </li>
+ <li>Other:
+ <ul>
+ <li>Added -noClassOk command-line parameter to
+ command-line and ant interfaces; when -noClassOk is specified
+ and no classfiles are given, FindBugs will print a warning
+ message and output a well- formed file with no warnings</li>
+ <li>Fewer false positives for null pointer bugs</li>
+ <li>Suppress dead-local-store false positives in .jsp code</li>
+ <li>Type fixes in warning messages</li>
+ <li>Better warning message for NP_NULL_ON_SOME_PATH</li>
+ <li>"WMI" bug code description renamed from "Wrong Map
+ Iterator" to "Inefficient Map Iterator"</li>
+ </ul>
+ </li>
+ <li>Fixes:
+ <ul>
+ <li>[ 1893048 ] FindBugs confused by a findbugs.xml file</li>
+ <li>[ 1878528 ] XSL xforms don't support history features</li>
+ <li>[ 1876584 ] two default.xsl flaws</li>
+ <li>[ 1874856 ] Format string bug detector doesn't handle
+ special operators</li>
+ <li>[ 1872645 ] computeBugHistory -
+ java.lang.IllegalArgumentException</li>
+ <li>[ 1872237 ] Ant task fails when no .class files</li>
+ <li>[ 1868670 ] Filters: include AND exclude don't allowed</li>
+ <li>[ 1868666 ] check-for-oddness reported, but array
+ length can never be negative</li>
+ <li>[ 1866108 ] SetBugDatabaseInfoTask strips dir from
+ output filename</li>
+ <li>[ 1866021 ] MineBugHistoryTask strips dir of output
+ filename</li>
+ <li>[ 1865265 ] code doesn't handle
+ StringBuffer.append([CII) right</li>
+ <li>[ 1864793 ] Warning when casting a null reference
+ compared to a String</li>
+ <li>[ 1863376 ] Typo in manual chap 8: Filter Files</li>
+ <li>[ 1862705 ] Transient fields that default to null</li>
+ <li>[ 1842545 ] DLS on catch variable (with priority
+ tweaking)</li>
+ <li>[ 1816258 ] false positive BC_IMPOSSIBLE_CAST</li>
+ <li>[ 1551732 ] Get erroneous DLS with while loop</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>FindBugs Eclipse plugin (change log by Andrey Loskutov)
+ <ul>
+ <li>new feature: added Bug explorer view (replacing Bug tree
+ view), based on Common Navigator framework (Andrey Loskutov)</li>
+ <li>bug 1873860 fixed: empty projects are no longer shown in
+ Bug tree view (Andrey Loskutov)</li>
+ <li>new feature: bug counts decorators for projects, folders
+ and files (has to be activated via Preferences -> general
+ -> appearance -> label decorations)(Andrey Loskutov)</li>
+ <li>patch 1746499: better icons (Alessandro Nistico)</li>
+ <li>patch 1893685: Find bug actions on change sets bug
+ (Alessandro Nistico)</li>
+ <li>fixed bug 1855384: Bug configuration is broken in
+ Eclipse (Andrey Loskutov)</li>
+ <li>refactored FindBugs properties page (Andrey Loskutov)</li>
+ <li>refactored FindBugs worker/builder/run action (Andrey
+ Loskutov)</li>
+ <li>FB detects now only bugs from classes on project's
+ classpath (no double work on duplicated class files) (Andrey
+ Loskutov)</li>
+ <li>fixed bug introduced by the bad patch for 1867951: FB
+ cannot be executed incrementally on a folder of file (Andrey
+ Loskutov)</li>
+ <li>fixed job rule: now jobs for different projects may run
+ in parallel if running on a multi-core PC and
+ "fb.allowParallelBuild" system property is set to true (Andrey
+ Loskutov)</li>
+ <li>fixed FB auto-build not started if .fbprefs or
+ .classpath was changed (Andrey Loskutov)</li>
+ <li>fixed not reporting bugs on secondary types (classes
+ defined in java files with different name) (Andrey Loskutov)</li>
+ </ul>
+ </li>
+ </ul>
+
+ <p>Changes since version 1.3.0</p>
+ <ul>
+ <li>New Reports
+ <ul>
+ <li>VA_FORMAT_STRING_ARG_MISMATCH: A format-string method
+ with a variable number of arguments is called, but the number of
+ arguments passed does not match with the number of %
+ placeholders in the format string. This is probably not what the
+ author intended.
+ <li>IO_APPENDING_TO_OBJECT_OUTPUT_STREAM: This code opens a
+ file in append mode and that wraps the result in an object
+ output stream. This won't allow you to append to an existing
+ object output stream stored in a file. If you want to be able to
+ append to an object output stream, you need to keep the object
+ output stream open. The only situation in which opening a file
+ in append mode and the writing an object output stream could
+ work is if on reading the file you plan to open it in random
+ access mode and seek to the byte offset where the append
+ started.
+ <li>NP_BOOLEAN_RETURN_NULL: A method that returns either
+ Boolean.TRUE, Boolean.FALSE or null is an accident waiting to
+ happen. This method can be invoked as though it returned a value
+ of type boolean, and the compiler will insert automatic unboxing
+ of the Boolean value. If a null value is returned, this will
+ result in a NullPointerException.
+ </ul>
+ </li>
+ <li>Changes to Existing Reports
+ <ul>
+ <li>RV_DONT_JUST_NULL_CHECK_READLINE: CORRECTNESS ->
+ STYLE</li>
+ <li>DMI_INVOKING_TOSTRING_ON_ARRAY: Long description
+ mentions array name whenever possible</li>
+ </ul>
+ </li>
+ <li>Fixes:
+ <ul>
+ <li>Updated manual to mention that Java 1.5 is now a
+ requirement for running FindBugs
+ <li>Applied patch 1840206 fixing issue "Ant task does not
+ work when presetdef is used" - thanks to phejl
+ <li>Applied patch 1778690 fixing issue "Ant task: tolerate
+ but complain about invalid auxClasspath" - thanks to David
+ Schmidt
+ <li>Applied patch 1852125 adding a Chinese-language GUI
+ bundle props file - thanks to fifi
+ <li>Applied patch 1845903 adding ability to load XML results
+ with the Eclipse plugin - thanks to Alex Mont
+ <li>Fixed issue 1844671 - "FP for "reversed" null check in
+ catch for stream close"
+ <li>Fixed issue 1836050 - "-onlyAnalyze broken"
+ <li>Fixed issue 1853011 - "Typo: Field names should start
+ with aN lower case letter"
+ <li>Fixed issue 1844181 - "JNLP file does not contain all
+ necessary JARs"
+ <li>Fixed issue 1840245 - "xxxException class does not
+ derive from Exception"
+ <li>Fixed issue 1840277 - "[M D EC] Typo in bug
+ documentation"
+ <li>Fixed issue 1782447 - "OutOfMemoryError if i activate
+ Findbugs on my project"
+ <li>Fixed issue 1830576 - "[regression] keySet/entrySet
+ false positive"
+ </ul>
+ </li>
+ <li>Other:
+ <ul>
+ <li>New bug code: "IO" (for
+ IO_APPENDING_TO_OBJECT_OUTPUT_STREAM)</li>
+ <li>Added "-onlyMostRecent" option for computeBugHistory
+ script/ant task
+ <li>More explicit language in
+ RV_RETURN_VALUE_IGNORED_BAD_PRACTICE messages
+ <li>Modified ResourceValueAnalysis to correctly identify
+ null == X or null != X as a null check (for issue 1844671)
+ <li>Modified DMI_HARDCODED_ABSOLUTE_FILENAME logic in
+ DumbMethodInvocations to ignore files from /etc or /dev and
+ increase priority of files from /home
+ <li>Better bug details for infinite loop warnings
+ <li>Modified unread-fields detector to reduce false
+ positives from reflective fields
+ <li>build.xml "classes" target now builds all sources in one
+ step
+ </ul>
+ </li>
+ </ul>
+
+ <p>Changes since version 1.2.1</p>
+ <ul>
+ <li>New Detectors and Reports
+ <ul>
+ <li>SynchronizationOnSharedBuiltinConstant
+ <ul>
+ <li>DL_SYNCHRONIZATION_ON_SHARED_CONSTANT: The code
+ synchronizes on a shared primitive constant, such as an
+ interned String. Such constants are interned and shared across
+ all other classes loaded by the JVM. Thus, this could be
+ locking on something that other code might also be locking.
+ This could result in very strange and hard to diagnose
+ blocking and deadlock behavior. See <a
+ href="http://www.javalobby.org/java/forums/t96352.html">http://www.javalobby.org/java/forums/t96352.html</a>
+ and <a href="http://jira.codehaus.org/browse/JETTY-352">http://jira.codehaus.org/browse/JETTY-352</a>.
+
+ </ul>
+ </li>
+ <li>OverridingEqualsNotSymmetrical
+ <ul>
+ <li>EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC: Looks for equals
+ methods that override equals methods in a superclass where the
+ equivalence relationship might not be symmetrical.
+ </ul>
+ </li>
+ <li>CheckTypeQualifiers
+ <ul>
+ <li>TQ_ALWAYS_VALUE_USED_WHERE_NEVER_REQUIRED: A value
+ specified as carrying a type qualifier annotation is consumed
+ in a location or locations requiring that the value not carry
+ that annotation. More precisely, a value annotated with a type
+ qualifier specifying when=ALWAYS is guaranteed to reach a use
+ or uses where the same type qualifier specifies when=NEVER.</li>
+ <li>TQ_NEVER_VALUE_USED_WHERE_ALWAYS_REQUIRED: A value
+ specified as not carrying a type qualifier annotation is
+ guaranteed to be consumed in a location or locations requiring
+ that the value does carry that annotation. More precisely, a
+ value annotated with a type qualifier specifying when=NEVER is
+ guaranteed to reach a use or uses where the same type
+ qualifier specifies when=ALWAYS.</li>
+ <li>TQ_MAYBE_SOURCE_VALUE_REACHES_ALWAYS_SINK: A value
+ that might not carry a type qualifier annotation reaches a use
+ which requires that annotation.</li>
+ <li>TQ_MAYBE_SOURCE_VALUE_REACHES_NEVER_SINK: A value
+ which might carry a type qualifier annotation reaches a use
+ which forbids values carrying that annotation.</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>New Reports (existing detectors)
+ <ul>
+ <li>FindHEmismatch
+ <ul>
+ <li>EQ_DOESNT_OVERRIDE_EQUALS: This class extends a class
+ that defines an equals method and adds fields, but doesn't
+ define an equals method itself. Thus, equality on instances of
+ this class will ignore the identity of the subclass and the
+ added fields. Be sure this is what is intended, and that you
+ don't need to override the equals method. Even if you don't
+ need to override the equals method, consider overriding it
+ anyway to document the fact that the equals method for the
+ subclass just return the result of invoking super.equals(o).</li>
+ </ul>
+ </li>
+ <li>Naming
+ <ul>
+ <li>NM_WRONG_PACKAGE, NM_WRONG_PACKAGE_INTENTIONAL: The
+ method in the subclass doesn't override a similar method in a
+ superclass because the type of a parameter doesn't exactly
+ match the type of the corresponding parameter in the
+ superclass.</li>
+ <li>NM_SAME_SIMPLE_NAME_AS_SUPERCLASS: This class has a
+ simple name that is identical to that of its superclass,
+ except that its superclass is in a different package (e.g., <code>alpha.Foo</code>
+ extends <code>beta.Foo</code>). This can be exceptionally
+ confusing, create lots of situations in which you have to look
+ at import statements to resolve references and creates many
+ opportunities to accidently define methods that do not
+ override methods in their superclasses.
+ </li>
+ <li>NM_SAME_SIMPLE_NAME_AS_INTERFACE: This class/interface
+ has a simple name that is identical to that of an
+ implemented/extended interface, except that the interface is
+ in a different package (e.g., <code>alpha.Foo</code> extends <code>beta.Foo</code>).
+ This can be exceptionally confusing, create lots of situations
+ in which you have to look at import statements to resolve
+ references and creates many opportunities to accidently define
+ methods that do not override methods in their superclasses.
+ </li>
+ </ul>
+ <li>FindRefComparison
+ <ul>
+ <li>EC_UNRELATED_TYPES_USING_POINTER_EQUALITY: This method
+ uses using pointer equality to compare two references that
+ seem to be of different types. The result of this comparison
+ will always be false at runtime.</li>
+ </ul>
+ </li>
+ <li>IncompatMask
+ <ul>
+ <li>BIT_SIGNED_CHECK, BIT_SIGNED_CHECK_HIGH_BIT: This
+ method compares an expression such as <tt>((event.detail
+ & SWT.SELECTED) > 0)</tt>. Using bit arithmetic and then
+ comparing with the greater than operator can lead to
+ unexpected results (of course depending on the value of
+ SWT.SELECTED). If SWT.SELECTED is a negative number, this is a
+ candidate for a bug. Even when SWT.SELECTED is not negative,
+ it seems good practice to use '!= 0' instead of '> 0'.
+ </li>
+ </ul>
+ </li>
+ <li>LazyInit
+ <ul>
+ <li>LI_LAZY_INIT_UPDATE_STATIC: This method contains an
+ unsynchronized lazy initialization of a static field. After
+ the field is set, the object stored into that location is
+ further accessed. The setting of the field is visible to other
+ threads as soon as it is set. If the further accesses in the
+ method that set the field serve to initialize the object, then
+ you have a <em>very serious</em> multithreading bug, unless
+ something else prevents any other thread from accessing the
+ stored object until it is fully initialized.
+ </li>
+ </ul>
+ </li>
+ <li>FindDeadLocalStores
+ <ul>
+ <li>DLS_DEAD_STORE_OF_CLASS_LITERAL: This instruction
+ assigns a class literal to a variable and then never uses it.
+ <a href="//java.sun.com/j2se/1.5.0/compatibility.html#literal">The
+ behavior of this differs in Java 1.4 and in Java 5.</a> In Java
+ 1.4 and earlier, a reference to <code>Foo.class</code> would
+ force the static initializer for <code>Foo</code> to be
+ executed, if it has not been executed already. In Java 5 and
+ later, it does not. See Sun's <a
+ href="//java.sun.com/j2se/1.5.0/compatibility.html#literal">article
+ on Java SE compatibility</a> for more details and examples, and
+ suggestions on how to force class initialization in Java 5.
+ </li>
+ </ul>
+ </li>
+ <li>MethodReturnCheck
+ <ul>
+ <li>RV_RETURN_VALUE_IGNORED_BAD_PRACTICE: This method
+ returns a value that is not checked. The return value should
+ be checked since it can indication an unusual or unexpected
+ function execution. For example, the <code>File.delete()</code>
+ method returns false if the file could not be successfully
+ deleted (rather than throwing an Exception). If you don't
+ check the result, you won't notice if the method invocation
+ signals unexpected behavior by returning an atypical return
+ value.
+ </li>
+ <li>RV_EXCEPTION_NOT_THROWN: This code creates an
+ exception (or error) object, but doesn't do anything with it.
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>Changes to Existing Reports
+ <ul>
+ <li>NS_NON_SHORT_CIRCUIT: BAD_PRACTICE -> STYLE</li>
+ <li>NS_DANGEROUS_NON_SHORT_CIRCUIT: CORRECTNESS -> STYLE</li>
+ <li>RC_REF_COMPARISON: CORRECTNESS -> BAD_PRACTICE</li>
+ </ul>
+ </li>
+ <li>GUI Changes
+ <ul>
+ <li>Added importing and exporting of bug filters</li>
+ <li>Better handling of failed analysis runs</li>
+ <li>Added "-look" parameter for selecting look-and-feel</li>
+ <li>Fixed incorrect package filtering</li>
+ <li>Fixed issue where "synchronized" was not
+ syntax-highlighted</li>
+ </ul>
+ </li>
+ <li>Ant-task Changes
+ <ul>
+ <li>Refactored common ant-task code to AbstractFindBugsTask</li>
+ <li>Added tasks for computeBugHistory, convertXmlToText,
+ filterBugs, mineBugHistory, setBugDatabaseInfo</li>
+ </ul>
+ </li>
+ <li>Manual
+ <ul>
+ <li>Updates to GUI section, including new screenshots</li>
+ <li>Added description of rejarForAnalysis</li>
+ <li>Revamp of data-mining section</li>
+ </ul>
+ </li>
+ <li>Other Major
+ <ul>
+ <li>Internal restructuring for lower memory overhead</li>
+ </ul>
+ </li>
+ <li>Other Minor
+ <ul>
+ <li>Fixed typo: was STCAL_STATIC_SIMPLE_DATA_FORMAT_INSTANCE
+ now STCAL_STATIC_SIMPLE_DATE_FORMAT_INSTANCE</li>
+ <li>-outputFile parameter became -output</li>
+ <li>More sensitivity and specificity inLazyInit detector</li>
+ <li>More sensitivity and specificity in Naming detector</li>
+ <li>More sensitivity and specificity in UnreadFields
+ detector</li>
+ <li>More sensitivity in FindNullDeref detector</li>
+ <li>More sensitivity in FindBadCast2 detector</li>
+ <li>More specificity in FindReturnRef detector</li>
+ <li>Many other tweaks and bug fixes</li>
+ </ul>
+ </li>
+ </ul>
+
+ <p>Changes since version 1.2.0</p>
+ <ul>
+ <li>Bug fixes:
+ <ul>
+ <li><a
+ href="http://fisheye2.cenqua.com/changelog/findbugs/?cs=8219">Fix</a>
+ <a
+ href="http://sourceforge.net/tracker/index.php?func=detail&aid=1726946&group_id=96405&atid=614693">bug</a>
+ with detectors that were requested to be disabled but were
+ enabled due to requirements of other detectors.</li>
+ <li>Fix bugs in incremental analysis within Eclipse plugin</li>
+ <li>Fix some analysis errors</li>
+ <li>Fix some threading bugs in GUI2</li>
+ <li>Report version as version when it was compiled, not when
+ it was run</li>
+ <li>Copy analysis time stamp when filtering or transforming
+ analysis files.</li>
+ </ul>
+ <li>Enabled StaticCalendarDetector</li>
+ <li>Reworked GUI2 to use standard FindBugs filters
+ <ul>
+ <li>Allow a suppression filter to be stored in a project and
+ persisted to the XML representation of a project.</li>
+ </ul>
+ </li>
+
+ <li>Move away from old GUI2 save format (a directory
+ containing an xml file and another file containing serialized
+ filters).</li>
+ <li>Support/recommend use of two new file extensions/formats:
+ <dl>
+ <dt>.fba - FindBugs Analysis File</dt>
+ <dd>Exactly the same as an existing bug collection file
+ stored in XML format, but using a distinct file extension to
+ make it easier to figure out which xml files contain FindBugs
+ results.</dd>
+ <dt>.fbp - FindBugs Project File</dt>
+ <dd>Contains just the information needed to run FindBugs and
+ display the results (e.g., the files to be analyzed, the
+ auxiliary class path and the location of source files)
+ </dl>
+ </li>
+ </ul>
+ <p>Changes since version 1.1.3</p>
+ <ul>
+ <li>Added -xml:withAbridgedMessages option to generate xml
+ containing shorter messages. The messages will be shorted by doing
+ things like eliding package names, and leaving off the source line
+ from the LongMessage. These messages are appropriate if being used
+ in a context where the non-message components of the bug
+ annotations will be used to provide more information (e.g.,
+ clicking on the message for a MethodAnnotation will display the
+ source for the method).
+ <ul>
+ <li>FindBugsDisplayFeatures.setAbridgedMessages(true) can be
+ used to generate abridged messages when FindBugs is being
+ accessed directly (not via generated XML) from a GUI or IDE.</li>
+ </ul>
+ <li>In null pointer analysis, try to be better about always
+ showing two locations: where it is known null and where it is
+ dereferenced.
+ <li>Interprocedural analysis of which methods return nonnull
+ values
+ <li>Use method calls to select order in which classes are
+ analyzed, and order in which methods are analyzed, to improve
+ interprocedural analysis results.
+ <li>Significant improvements in memory footprint, memory
+ allocation and CPU utilization (20-30% reduction in all three)
+ <li>Added a project name, to provide better descriptions in
+ the HTML output.
+ <li>Added new bug pattern: Casting to char, or bit masking
+ with nonnegative value, and then checking to see if the result is
+ negative.
+ <li>Stopped reporting transient fields of classes not marked
+ as serializable. Transient is used by other persistence
+ frameworks.
+ <li>Improvements to detector for SQL injection (Thanks to <a
+ href="http://www.clock.org/~matt">Matt Hargett</a> for his
+ contributions
+ <li>Changed open/save options in GUI2 to not distinguish
+ between FindBugs projects and saved FindBugs analysis results.
+ <li>Improvements to detection of serious non-short-circuit
+ evaluation.
+ <li>Updated Japanese localization (thanks to Ruimo Uno)
+ <li>Eclipse plugin changes:
+ <ul>
+ <li>Created Bug User Annotations and Bug Tree Views
+ <li>Use different icons for different bug priorities
+ <li>Provide more information in Bug Details view
+ </ul>
+ </ul>
+
+ <p>Changes since version 1.1.2:</p>
+ <ul>
+ <li>Fixed broken Ant task
+ <li>Added running ant task to smoke test
+ <li>Added validating xml and html output to smoke test
+ <li>Fixed some (but not all) issues with html output
+ validation
+ <li>Added check for x.equals(x) and x.compareTo(x)
+ <li>Various bug fixes
+ </ul>
+ <p>Changes since version 1.1.1:</p>
+ <ul>
+ <li>Added check for infinite iterative loops</li>
+ <li>Added check for use of incompatible types in a collection
+ (e.g., checking to see if a Set<String> contains a
+ StringBuffer).</li>
+ <li>Added check for invocations of equals or hashCode on a
+ URL, which, <a
+ href="http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html">surprising
+ many people</a>, requires DNS resolution.
+ </li>
+ <li>Added check for classes that define compareTo but not
+ equals; such classes can exhibit some anomalous behavior (e.g.,
+ they are treated differently by PriorityQueues in Java 5 and Java
+ 6).</li>
+ <li>Added a check for useless self operations (e.g., x < x
+ or x ^ x).</li>
+ <li>Fixed a data race that could cause the GUI to fail on
+ startup</li>
+ <li>Partial internationalization of the new GUI</li>
+ <li>Fix bug in "Redo analysis" option of new GUI</li>
+ <li>Tuning to reduce false positives</li>
+ <li>Fixed a bug in null pointer analysis that was generating
+ false positive null pointer warnings on exception paths. Fixing
+ this bug eliminates about 1/4 of the warnings on null pointer
+ exceptions on exception paths.</li>
+ <li>Fixed a bug in the processing of phi nodes for fields in
+ the null pointer analysis</li>
+ <li>Applied contributed patch that provides more quick fixes
+ in Eclipse plugin.</li>
+ <li>Fixed a number of bugs in the Eclipse auto update sites,
+ and in the way date qualifiers were being used in the Eclipse
+ plugin. You may need to manually disable your existing version of
+ the plugin and download the 1.1.2 from the update site to get the
+ automatic update function working correctly. The Eclipse update
+ sites are described at <a
+ href="http://findbugs.cs.umd.edu/eclipse/">http://findbugs.cs.umd.edu/eclipse/</a>.
+
+ </li>
+ <li>Fixed progress bar in Eclipse plugin</li>
+ <li>A number of other bug fixes.</li>
+ </ul>
+
+ <p>Changes since version 1.1.0:</p>
+ <ul>
+ <li>less scanning of classes not on the analysis path (This
+ was causing some performance problems.)</li>
+ <li>no unread field warnings for fields annotated with
+ javax.persistent or javax.ejb3</li>
+ <li>Eclipse plugin
+ <ul>
+ <li>bug annotation info displayed in Bug Details tab</li>
+ <li>.fbwarnings data file now stored in .metadata (not in
+ the project itself)</li>
+ </ul>
+ </li>
+ <li>new SE_BAD_FIELD_INNER_CLASS pattern</li>
+ <li>updates to Japanese translation (ruimo)</li>
+ <li>fix some internal slashed/dotted path confusion</li>
+ <li>other minor improvements</li>
+ </ul>
+
+ <p>Changes since version 1.0.0:</p>
+
+ <ul>
+ <li>Overall, the change from FindBugs 1.0.0 to FindBugs 1.1.0
+ has been a big change. We've done a lot of work in a lot of areas,
+ and aren't even going to try to enumerate all the changes.</li>
+ <li>We spent a lot of time reviewing the results generated by
+ FindBugs for open source and commercial code bases, and made a
+ number of changes, small and large, to minimize the number of
+ false positives. Our primary focus for this was warnings reported
+ as high and medium priority correctness warnings. Our internal
+ evaluation is that we produce very few high/medium priority
+ correctness warnings where the analysis is actually wrong, and
+ that more than 75% of the high/medium priority correctness
+ warnings correspond to real coding defects that need addressing in
+ the source code. The remaining 25% are largely cases such as a
+ branch or statement that if taken would lead to an error, but in
+ fact is a dead branch or statement that can never be taken. Such
+ coding is confusing and hard to maintain, so it should arguably be
+ fixed, but it is unlikely to actually result in an error during
+ execution. Thus, some might classify those warnings as false
+ positives.</li>
+ <li>We've substantially improved the analysis for errors that
+ could result in null pointer dereferences. Overall, our experience
+ has been that these changes have roughly doubled the number of
+ null pointer errors we detect, without increasing the number of
+ false positives (in fact, our false positive rate has gone down).
+ The improvements are due to four factors:
+ <ul>
+ <li>By default, we now do some interprocedural analysis to
+ determine methods that unconditionally dereference their
+ parameters.</li>
+ <li>FindBugs also comes with a model of which JDK methods
+ unconditionally dereference their parameters.</li>
+ <li>We do limited tracking of fields, so that we can detect
+ null values stored in fields that lead to exceptions.</li>
+ <li>We implemented a new analysis technique to find
+ guaranteed dereferences. Consider the following example: <pre>public int f(Object x, boolean b) {
int result = 0;
if (x == null) result++;
else result--;
@@ -1455,1304 +1658,1304 @@
}
</pre>
- <p>
- FindBugs 1.0 used forward dataflow analysis to determine
- whether each value is definitely null, null on a simple path,
- possible null on a complex path, or definitely nonnull. Thus,
- at the statement where
- <code> result </code>
- is decremented, we know that
- <code> x </code>
- is definitely null, and at the point before
- <code> if (b) </code>
- , we know that
- <code> x </code>
- is null on a simple path. If
- <code> x </code>
- were to be dereferenced here, we would generate a warning,
- because if the else branch of the
- <code> if (x == null) </code>
- were ever taken, a null pointer exception would result.
- </p>
-
- <p>
- However, in both the then and else branches of the
- <code> if (b) </code>
- statement,
- <code> x </code>
- is only null on a complex path that may be infeasible. It might
- be that the program logic is such that if
- <code> x </code>
- is null, then
- <code> b </code>
- is never true, so generating a warning about the dereference in
- the then clause might be a false positive. We could try to
- analyze the program to determine whether it is possible for
- <code> x </code>
- to be null and
- <code> b </code>
- to be true, but that can be a hard analysis problem.
- </p>
-
- <p>
- However,
- <code> x </code>
- is dereferenced in both the then <em>and</em> else branches of
- the
- <code> if (b) </code>
- statement. So at the point immediately before
- <code> if (b) </code>
- , we know that
- <code> x </code>
- is null on a simple path <em>and</em> that
- <code> x </code>
- is guaranteed to be dereferenced on all paths from this point
- forward. FindBugs 1.1 performs a backwards data flow analysis
- to determine the values that are guaranteed to be dereferenced,
- and will generate a warning in this case.
- </p>
- </li>
- </ul>
- <p>
- The following screen shot of our new GUI shows an example of this
- analysis, as well as showing off our new GUI and points out a
- limitation of our current plugins for Eclipse and NetBeans. The
- screen shot shows a null pointer bug in HelpDisplay.java. The
- test for
- <code> href!=null </code>
- on line 78 suggests that
- <code> href </code>
- could be null. If it is, then
- <code> href </code>
- will be dereferenced on either line 87 or on line 90, generating
- a NPE. Note that our analysis here also understands that passing
- <code> href </code>
- to
- <code> URLEncoder.encode </code>
- will deference it, and thus treats line 87 as a dereference, even
- though
- <code> href </code>
- is not actually dereferenced at that line. Within our new GUI,
- all of these locations are highlighted and listed in the summary
- panel. In the original GUI (and in HTML output) we list all of
- the locations, but only the primary location is highlighted by
- the original GUI. In the Eclipse and NetBeans plugins, only the
- primary location is displayed; fixing this is on our todo list
- (contributions welcome).
- </p>
- <p>
- <img src="guaranteedDereference.png" alt="">
-
-
- </p>
-
- </li>
- <li>Preliminary support for detectors using the frameworks
- other than BCEL, such as the <a href="http://asm.objectweb.org/">ASM</a>
- bytecode framework. You may experiment with writing ASM-based
- detectors, but beware the API may still change (which could
- possibly also affect BCEL-based detectors). In general, we've
- started trying to move away from a deep dependence on BCEL, but
- that change is only partially complete. Probably best to just
- avoid this until we complete more work on this. This change is
- only visible to FindBugs plugin developers, and shouldn't be
- visible to FindBugs users.
- </li>
- <li>
- <p>Bug categories (CORRECTNESS, MT_CORRECTNESS, etc.) are no
- longer hard-coded, but rather defined in xml files associated
- with plugins, including the core plugin which defines the
- standard categories. Third-party plugins can define their own
- categories.</p>
- </li>
- <li>
- <p>Several bug patterns have been moved from CORRECTNESS and
- STYLE into a new category, BAD_PRACTICE. The English localization
- of STYLE has changed from "Style" to "Dodgy."</p>
- <p>In general, we've worked very hard to limit CORRECTNESS
- bugs to be real programming errors and sins of commission. We
- have reclassified as BAD_PRACTICE a number of bad design
- practices that result in overly fragile code, such as defining an
- equals method that doesn't accept null or defining class with a
- equals method that inherits hashCode from class Object.</p>
- <p>In general, our guidelines for deciding whether a bug
- should be classified as CORRECTNESS, BAD_PRACTICE or STYLE are:</p>
- <dl>
- <dt>CORRECTNESS</dt>
- <dd>A problem that we can recognize with high confidence and
- is an issue that we believe almost all developers would want to
- examine and address. We recommend that software teams review all
- high and medium priority warnings in their entire code base.</dd>
- <dt>BAD_PRACTICE</dt>
- <dd>A problem that we can recognize with high confidence and
- represents a clear violation of recommended and standard coding
- practice. We believe each software team should decide which bad
- practices identified by FindBugs it wants to prohibit in the
- team's coding standard, and take action to remedy violations of
- those coding standards.</dd>
- <dt>STYLE</dt>
- <dd>These are places where something strange or dodgy is
- going on, such as a dead store to a local variable. Typically,
- less than half of these represent actionable programming
- defects. Reviewing these warnings in any code under active
- development is probably a good idea, but reviewing all such
- warnings in your entire code base might be appropriate only in
- some situations. Individual or team programming styles can
- substantially influence the effectiveness of each of these
- warnings (e.g., you might have a coding practice or style in
- your group that confuses one of the detectors into generating a
- lot of STYLE warnings); you will likely want to selectively
- suppress or report the STYLE warnings that are effective for
- your group.</dd>
- </dl>
- </li>
- <li>Released a preliminary version of a new GUI (known
- internally as GUI2 -- not very creative, huh?)</li>
- <li>Provided standard ways to mark user designations of bug
- warnings (e.g., as NOT_A_BUG or SHOULD_FIX). The internal logic
- now records this, it is represented in the XML file, and GUI2
- allows the designations to be applied (along with free-form user
- annotations about each warning). The user designations and
- annotations are not yet supported by the Eclipse plugin, but we
- clearly want to support it in Eclipse shortly.</li>
- <li>Added a check for a bad comparison with a signed byte with
- a value not in the range -128..127. For example: <pre>boolean find200(byte b[]) {
+ <p>
+ FindBugs 1.0 used forward dataflow analysis to determine
+ whether each value is definitely null, null on a simple path,
+ possible null on a complex path, or definitely nonnull. Thus,
+ at the statement where
+ <code> result </code>
+ is decremented, we know that
+ <code> x </code>
+ is definitely null, and at the point before
+ <code> if (b) </code>
+ , we know that
+ <code> x </code>
+ is null on a simple path. If
+ <code> x </code>
+ were to be dereferenced here, we would generate a warning,
+ because if the else branch of the
+ <code> if (x == null) </code>
+ were ever taken, a null pointer exception would result.
+ </p>
+
+ <p>
+ However, in both the then and else branches of the
+ <code> if (b) </code>
+ statement,
+ <code> x </code>
+ is only null on a complex path that may be infeasible. It might
+ be that the program logic is such that if
+ <code> x </code>
+ is null, then
+ <code> b </code>
+ is never true, so generating a warning about the dereference in
+ the then clause might be a false positive. We could try to
+ analyze the program to determine whether it is possible for
+ <code> x </code>
+ to be null and
+ <code> b </code>
+ to be true, but that can be a hard analysis problem.
+ </p>
+
+ <p>
+ However,
+ <code> x </code>
+ is dereferenced in both the then <em>and</em> else branches of
+ the
+ <code> if (b) </code>
+ statement. So at the point immediately before
+ <code> if (b) </code>
+ , we know that
+ <code> x </code>
+ is null on a simple path <em>and</em> that
+ <code> x </code>
+ is guaranteed to be dereferenced on all paths from this point
+ forward. FindBugs 1.1 performs a backwards data flow analysis
+ to determine the values that are guaranteed to be dereferenced,
+ and will generate a warning in this case.
+ </p>
+ </li>
+ </ul>
+ <p>
+ The following screen shot of our new GUI shows an example of this
+ analysis, as well as showing off our new GUI and points out a
+ limitation of our current plugins for Eclipse and NetBeans. The
+ screen shot shows a null pointer bug in HelpDisplay.java. The
+ test for
+ <code> href!=null </code>
+ on line 78 suggests that
+ <code> href </code>
+ could be null. If it is, then
+ <code> href </code>
+ will be dereferenced on either line 87 or on line 90, generating
+ a NPE. Note that our analysis here also understands that passing
+ <code> href </code>
+ to
+ <code> URLEncoder.encode </code>
+ will deference it, and thus treats line 87 as a dereference, even
+ though
+ <code> href </code>
+ is not actually dereferenced at that line. Within our new GUI,
+ all of these locations are highlighted and listed in the summary
+ panel. In the original GUI (and in HTML output) we list all of
+ the locations, but only the primary location is highlighted by
+ the original GUI. In the Eclipse and NetBeans plugins, only the
+ primary location is displayed; fixing this is on our todo list
+ (contributions welcome).
+ </p>
+ <p>
+ <img src="guaranteedDereference.png" alt="">
+
+
+ </p>
+
+ </li>
+ <li>Preliminary support for detectors using the frameworks
+ other than BCEL, such as the <a href="http://asm.objectweb.org/">ASM</a>
+ bytecode framework. You may experiment with writing ASM-based
+ detectors, but beware the API may still change (which could
+ possibly also affect BCEL-based detectors). In general, we've
+ started trying to move away from a deep dependence on BCEL, but
+ that change is only partially complete. Probably best to just
+ avoid this until we complete more work on this. This change is
+ only visible to FindBugs plugin developers, and shouldn't be
+ visible to FindBugs users.
+ </li>
+ <li>
+ <p>Bug categories (CORRECTNESS, MT_CORRECTNESS, etc.) are no
+ longer hard-coded, but rather defined in xml files associated
+ with plugins, including the core plugin which defines the
+ standard categories. Third-party plugins can define their own
+ categories.</p>
+ </li>
+ <li>
+ <p>Several bug patterns have been moved from CORRECTNESS and
+ STYLE into a new category, BAD_PRACTICE. The English localization
+ of STYLE has changed from "Style" to "Dodgy."</p>
+ <p>In general, we've worked very hard to limit CORRECTNESS
+ bugs to be real programming errors and sins of commission. We
+ have reclassified as BAD_PRACTICE a number of bad design
+ practices that result in overly fragile code, such as defining an
+ equals method that doesn't accept null or defining class with a
+ equals method that inherits hashCode from class Object.</p>
+ <p>In general, our guidelines for deciding whether a bug
+ should be classified as CORRECTNESS, BAD_PRACTICE or STYLE are:</p>
+ <dl>
+ <dt>CORRECTNESS</dt>
+ <dd>A problem that we can recognize with high confidence and
+ is an issue that we believe almost all developers would want to
+ examine and address. We recommend that software teams review all
+ high and medium priority warnings in their entire code base.</dd>
+ <dt>BAD_PRACTICE</dt>
+ <dd>A problem that we can recognize with high confidence and
+ represents a clear violation of recommended and standard coding
+ practice. We believe each software team should decide which bad
+ practices identified by FindBugs it wants to prohibit in the
+ team's coding standard, and take action to remedy violations of
+ those coding standards.</dd>
+ <dt>STYLE</dt>
+ <dd>These are places where something strange or dodgy is
+ going on, such as a dead store to a local variable. Typically,
+ less than half of these represent actionable programming
+ defects. Reviewing these warnings in any code under active
+ development is probably a good idea, but reviewing all such
+ warnings in your entire code base might be appropriate only in
+ some situations. Individual or team programming styles can
+ substantially influence the effectiveness of each of these
+ warnings (e.g., you might have a coding practice or style in
+ your group that confuses one of the detectors into generating a
+ lot of STYLE warnings); you will likely want to selectively
+ suppress or report the STYLE warnings that are effective for
+ your group.</dd>
+ </dl>
+ </li>
+ <li>Released a preliminary version of a new GUI (known
+ internally as GUI2 -- not very creative, huh?)</li>
+ <li>Provided standard ways to mark user designations of bug
+ warnings (e.g., as NOT_A_BUG or SHOULD_FIX). The internal logic
+ now records this, it is represented in the XML file, and GUI2
+ allows the designations to be applied (along with free-form user
+ annotations about each warning). The user designations and
+ annotations are not yet supported by the Eclipse plugin, but we
+ clearly want to support it in Eclipse shortly.</li>
+ <li>Added a check for a bad comparison with a signed byte with
+ a value not in the range -128..127. For example: <pre>boolean find200(byte b[]) {
for(int i = 0; i < b.length; i++) if (b[i] == 200) return i;
return -1;
}
</pre>
- </li>
- <li>Added a checking for testing if a value is equal to
- Double.NaN (no value is equal to NaN, not even NaN).</li>
- <li>Added a check for using a class with an equals method but
- no hashCode method in a hashed data structure.</li>
- <li>Added check for uncallable method of an anonymous inner
- class. For example, in the following code, it is impossible to
- invoke the initalValue method (because the name is misspelled and
- as a result is doesn't override a method in ThreadLocal). <pre>private static ThreadLocal serialNum = new ThreadLocal() {
+ </li>
+ <li>Added a checking for testing if a value is equal to
+ Double.NaN (no value is equal to NaN, not even NaN).</li>
+ <li>Added a check for using a class with an equals method but
+ no hashCode method in a hashed data structure.</li>
+ <li>Added check for uncallable method of an anonymous inner
+ class. For example, in the following code, it is impossible to
+ invoke the initalValue method (because the name is misspelled and
+ as a result is doesn't override a method in ThreadLocal). <pre>private static ThreadLocal serialNum = new ThreadLocal() {
protected synchronized Object initalValue() {
return new Integer(nextSerialNum++);
}
};
</pre>
- </li>
- <li>Added check for a dead local store caused by a switch
- statement fall through</li>
- <li>Added check for computing the absolute value of a random
- 32 bit integer or of a hashcode. This is broken because <code>
- Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE </code> , and thus
- result of calling Math.abs, which is expected to be nonnegative,
- will in fact be negative one time out of 2 <sup> 32 </sup> , which
- will invariably be the time your boss is demoing the software to
- your customers.
-
- </li>
- <li>More careful resolution of inherited methods and fields.
- Some of the shortcuts we were taking in FindBugs 1.0.0 were
- leading to inaccurate results, and it was fairly easy to address
- this by making the analysis more accurate.</li>
- <li>Overall, analysis times are about 1.6 times longer in
- FindBugs 1.1.0 than in FindBugs 1.0.0. This is because we have
- enabled substantial additional analysis at the default effort
- level (the actual analysis engine is significantly faster than in
- FindBugs 1.0). On a recent AMD Athlon processor, analyzing
- JDK1.6.0 (about 1 million lines of code) requires about 15 minutes
- of wall clock time.</li>
- <li>Provided class and script (printClass) to print classfile
- in the human readable format produced by BCEL</li>
- <li>Provided -findSource option to setBugDatabaseInfo</li>
- </ul>
-
-
- <p>Changes since version 0.9.7:</p>
-
- <ul>
- <li>fix ObjectTypeFactory bug that was suppressing some bugs</li>
- <li>opcode stack may determine definite zeros on some paths</li>
- <li>opcode stack can track some constant string concatenations
- (dbrosius)</li>
- <li>default effort performs iterative opcode analysis (but min
- effort does not)</li>
- <li>default heap size upped to 384m</li>
- <li>schema for XML output available: bugcollection.xsd</li>
- <li>fixed some internal confusion between dotted and slashed
- class names</li>
- <li>New detectors
- <ul>
- <li>CheckImmutableAnnotation.java: checks JCIP annotations</li>
- </ul>
- </li>
- <li>Updated detectors
- <ul>
- <li>BadRegEx.java: understands Pattern.LITERAL, warns about
- "."</li>
- <li>FindUnreleasedLock.java: fewer false positives</li>
- <li>DumbMethods.java: check for vacuous comparisons to
- MAX_INTEGER or MIN_INTEGER, fix bugs detecting
- DM_NEXTINT_VIA_NEXTDOUBLE</li>
- <li>FindPuzzlers.java: detect <tt>n%2==1</tt>, detect
- toString() on array types
- </li>
- <li>FindInconsistentSync2.java: detects IS_FIELD_NOT_GUARDED
- </li>
- <li>MethodReturnCheck.java: add check for discarded newly
- constructed values, increase priority of some ignored
- constructed exceptions, better handling of bytecode compiled by
- Eclipse</li>
- <li>FindEmptySynchronizedBlock.java: better handling of
- bytecode compiled by Eclipse</li>
- <li>DoInsideDoPrivileged.java: warn if call to setAccessible
- isn't in doPriviledged, don't report private methods</li>
- <li>LoadOfKnownNullValue.java: fix bug that was reporting
- false positives on <code> finally </code> blocks
- </li>
- <li>CheckReturnAnnotationDatabase.java: better checks for
- unstarted threads</li>
- <li>ConfusionBetweenInheritedAndOuterMethod.java: fewer
- false positives, fixed a package-handling bug</li>
- <li>BadResultSetAccess.java: separate bug pattern for
- PreparedStatements, <code> BRZA </code> category folded into <code>
- SQL </code> category
- </li>
- <li>FindDeadLocalStores.java, FindBadCast2.java,
- DumbMethods.java, RuntimeExceptionCapture.java: coalesce similar
- bugs within a method into a single bug instance with multiple
- source lines</li>
- </ul>
- </li>
- <li>Eclipse plugin
- <ul>
- <li>plugin ID changed from <tt>de.tobject.findbugs</tt> to <tt>edu.umd.cs.findbugs.plugin.eclipse</tt>
- </li>
- <li>support for findbugs eclipse auto-update site</li>
- </ul>
- </li>
- <li>Updated test case files
- <ul>
- <li>BadRegEx.java</li>
- <li>JSR166.java</li>
- <li>ConcurrentModificationBug.java</li>
- <li>DeadStore.java</li>
- <li>InstanceOf.java</li>
- <li>LoadKnownNull.java</li>
- <li>NeedsToCheckReturnValue.java</li>
- <li>BadResultSetAccessTest.java</li>
- <li>DeadStore.java</li>
- <li>TestNonNull2.java</li>
- <li>TestImmutable.java</li>
- <li>TestGuardedBy.java</li>
- <li>BadRandomInt.java</li>
- <li>six test cases added to new <code> TigerTraps </code>
- directory
- </li>
- </ul>
- </li>
- <li>fix bug that was generating duplicate uids</li>
- <li>fix bug with <code> -onlyAnalyze some.package.* </code> on
- jdk1.4
- </li>
- <li>fix regression bug in
- DismantleByteCode.getRefConstantOperand()</li>
- <li>fix some minor bugs with the Swing GUI</li>
- <li>reordered some bugInstances so that source line
- annotations come last</li>
- <li>removed references to unused java system properties</li>
- <li>French translation updates (David Cotton)</li>
- <li>Japanese translation updates (Hanai Shisei)</li>
- <li>content cleanup for findbugs.xml and messages.xml</li>
- <li>references to cvs hostname updated to
- findbugs.cvs.sourceforge.net</li>
- <li>documented xdoc output options, new
- mineBugHistory/computeBugHistory options</li>
- </ul>
-
- <p>Changes since version 0.9.6:</p>
-
- <ul>
- <li>performance improvements</li>
- <li>ObjectType instances are cached to reduce memory footprint
- </li>
- <li>for performance and memory reasons stateless detectors are
- no longer cloned, must clear their own state between .class files
- </li>
- <li>fixed bug in bytecode-set lookup for methods (was causing
- bad results for IS2, perhaps others)</li>
- <li>fix some OpcodeStack bugs with integer and long
- operations, perform iterative analysis when effort is <tt>max</tt>
- </li>
- <li>HTML output includes LongMessage text again (regression in
- 0.95 - 0.96)</li>
- <li>New detectors
- <ul>
- <li>CalledMethods.java: builds a list of invoked methods for
- other detectors to consult (non-reporting)</li>
- <li>UncallableMethodOfAnonymousClass.java: detect anonymous
- inner classes that define methods that are probably intended to
- but do not override methods in a superclass.</li>
- </ul>
- </li>
- <li>Updated detectors
- <ul>
- <li>FindFieldSelfAssignment.java: recognize separate fields
- with the same name (one from superclass)</li>
- <li>FindLocalSelfAssignment2.java: handles backward branches
- better (Dave Brosius)</li>
- <li>FindBadCast2.java: BC_NULL_INSTANCEOF changed to
- NP_NULL_INSTANCEOF</li>
- <li>FindPuzzlers.java: eliminate false positive on setDate()
- (Dave Brosius)</li>
- </ul>
- </li>
- <li>Eclipse plugin
- <ul>
- <li>fix serious threading bug</li>
- <li>preferences for Filters and effort (Peter Hendriks)</li>
- <li>French localization (David Cotton)</li>
- <li>fix bug when reporting inner classes (Peter Friese)</li>
- </ul>
- </li>
- <li>Updated test case files
- <ul>
- <li>Mwn.java (Carl Burke/Dave Brosius)</li>
- <li>DumbMethodInvocations.java (Anto paul/Dave Brosius)</li>
- <!--sic-->
- </ul>
- </li>
- <li>XML output includes garbage collection duration</li>
- <li>French messages updated (David Cotton)</li>
- <li>Swing GUI shows file name after Load Bugs command</li>
- <li>Ant task to launch the findbugs frame (Mark McKay)</li>
- <li>miscellaneous code cleanup</li>
- </ul>
-
- <p>Changes since version 0.9.5:</p>
-
- <ul>
- <li>Updated detectors
- <ul>
- <li>FindNullDeref.java: respect NonNull and CheckForNull
- field annotations</li>
- <li>SerializableIdiom.java: detect non-private readObject
- and writeObject methods</li>
- <li>FindRefComparison.java: smarter array comparison
- detection</li>
- <li>IsNullValueAnalysis.java: detect <tt>null
- instanceof</tt>
- </li>
- <li>FindLocalSelfAssignment2.java: suppress some false
- positives (Dave Brosius)</li>
- <li>FindUnreleasedLock.java: don't waste time processing
- classes that don't refer to java.util.concurrent.locks</li>
- <li>MutableStaticFields.java: report the source line (Dave
- Brosius)</li>
- <li>SwitchFallthrough.java: better handling of System.exit()
- (Dave Brosius)</li>
- <li>MultithreadedInstanceAccess.java: better handling of
- Servlet.init() (Dave Brosius)</li>
- <li>ConfusionBetweenInheritedAndOuterMethod.java: now
- enabled</li>
- </ul>
- </li>
- <li>Eclipse plugin
- <ul>
- <li>background processing (Peter Friese)</li>
- <li>internationalization, Japanese localization (Takashi
- Okamoto)</li>
- </ul>
- </li>
- <li>findbugs <tt>-onlyAnalyze</tt> option now works on windows
- platforms
- </li>
- <li>mineBugHistory <tt>-noTabs</tt> option for better
- alignment of output columns
- </li>
- <li>filterBugs <tt>-fixed</tt> option (also: will now
- recognize the most recent version string)
- </li>
- <li>XML output includes running time and memory usage data</li>
- <li>miscellaneous minor corrections to the manual</li>
- <li>better bytecode analysis of the <tt>iinc</tt> instruction
- </li>
- <li>fix bug in null pointer analysis</li>
- <li>improved catch block heuristics</li>
- <li>some type analysis tweaks</li>
- <li>Bug priority changes
- <ul>
- <li>DumbMethodInvocations.java: decrease priority of
- hard-coded <tt>/tmp</tt> filenames
- </li>
- <li>ComparatorIdiom.java: decrease priority of
- non-serializable anonymous comparators</li>
- <li>FindSqlInjection.java: decrease priority of appending a
- constant or a static</li>
- </ul>
- </li>
- <li>Updated bug explanations
- <ul>
- <li>NM_VERY_CONFUSING (Dave Brosius)</li>
- </ul>
- </li>
- <li>Updated test case files
- <ul>
- <li>BadStoreOfNonSerializableObject.java</li>
- <li>BadRandomInt.java</li>
- <li>TestFieldAnnotations.java</li>
- <li>UseInitCause.java</li>
- <li>SqlInjection.java</li>
- <li>ArrayEquality.java</li>
- <li>BadIntegerOperations.java</li>
- <li>Pilhuhn.java</li>
- <li>InstanceOf.java</li>
- <li>SwitchFallthrough.java (Dave Brosius)</li>
- </ul>
- </li>
- <li>fix URL decoding bug when running under Java Web Start
- (Dave Brosius)</li>
- <li>distribution includes <tt>project.xml</tt> file for
- NetBeans
- </li>
- </ul>
-
- <p>Changes since version 0.9.4:</p>
- <ul>
- <li>New detectors
- <ul>
- <li>VarArgsProblems.java</li>
- <li>FindSqlInjection.java: now enabled</li>
- <li>ComparatorIdiom.java: comparators usually implement
- serializable</li>
- <li>Naming.java: detect methods not overridden due to
- eponymously typed args from different packages</li>
- </ul>
- </li>
- <li>Updated detectors
- <ul>
- <li>SwitchFallthrough.java: surpress some false positives</li>
- <li>DuplicateBranches.java: surpress some false positives</li>
- <li>IteratorIdioms.java: surpress some false positives</li>
- <li>FindHEmismatch.java: surpress some false positives</li>
- <li>QuestionableBooleanAssignment.java: finds more cases of
- <tt>if (b=true)</tt> ilk
- </li>
- <li>DumbMethods.java: detect int remainder by 1, delayed gc
- errors</li>
- <li>SerializableIdiom.java: detect store of nonserializable
- object into field of serializable class</li>
- <li>FindNullDeref.java: fix potential exception</li>
- <li>IsNullValue.java: fix potential exception</li>
- <li>MultithreadedInstanceAccess.java: fix potential
- exception</li>
- <li>PreferZeroLengthArrays.java: flag the method, not the
- line</li>
- </ul>
- </li>
- <li>Remove some inadvertent dependencies on JDK 1.5</li>
- <li>Sort order should be more consistent</li>
- <li>XML output changes
- <ul>
- <li>Option to sort XML bug output</li>
- <li>Now contains instance IDs</li>
- <li>uid no longer missing (was causing problems with fancy
- HTML output)</li>
- <li>Typo fixed</li>
- </ul>
- </li>
- <li>Internal changes to track source files, <tt>-sourceInfo</tt>
- option
- </li>
- <li>Bug matching: first try exact bug pattern matching, option
- to compare priorities, option to disable package moves</li>
- <li>Architecture documentation in <tt>design/architecture</tt>
- </li>
- <li>Test cases move into their own CVS project</li>
- <li>Don't report warnings that occur outside the analyzed
- classes</li>
- <li>Fixes to the build.xml files</li>
- <li>Better handling of @CheckReturnValue and @CheckForNull
- annotations (also, some additional methods searched for check
- return value and check for null)</li>
- <li>Fixed some stream-closing bugs (one by <tt>z-fb-user</tt>/Dave
- Brosius)
- </li>
- <li>Bug priority changes
- <ul>
- <li>increase priority of ignoring return value of
- java.sql.Connection methods</li>
- <li>increase priority of comparing classes like Integer
- using <tt>==</tt>
- </li>
- <li>decrease priority of IT_NO_SUCH_ELEMENT if we see any
- call to <tt>next()</tt>
- </li>
- <li>tweak priority of NM_METHOD_CONSTRUCTOR_CONFUSION</li>
- <li>decrease priority of RV_RETURN_VALUE_IGNORED for an
- inherited annotation that doesn't return same type as class</li>
- </ul>
- </li>
- <li>Updated bug explanations
- <ul>
- <li>RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE</li>
- <li>DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED</li>
- <li>IMA_INEFFICIENT_MEMBER_ACCESS (Dave Brosius)</li>
- <li>some Japanese improvements to messages_ja.xml ( <tt>ruimo</tt>)
- </li>
- <li>some German improvements to findbugs_de.properties (Dave
- Brosius, <tt>dvholten</tt>)
- </li>
- </ul>
- </li>
- <li>Updated test case files
- <ul>
- <li>BadIntegerOperations.java</li>
- <li>SecondKaboom.java</li>
- <li>OpenDatabase.java (Dave Brosius)</li>
- <li>FindOpenStream.java (Dave Brosius)</li>
- <li>BadRandomInt.java</li>
- </ul>
- </li>
- <li>Source-lines info maintained for methods (handy for
- abstract and native methods)</li>
- <li>Remove surrounding opcodes from source line annotations</li>
- <li>Better error when can't read file</li>
- <li>Swing GUI: removed console pane from FindBugsFrame, fix
- missing classes bug</li>
- <li>Fixes to OpcodeStack.java</li>
- <li>Detectors may attach a custom value to an OpcodeStack.Item
- (Dave Brosius)</li>
- <li>Filter.java: ability to add text messages to XML output,
- fix bug with <tt>-withMessages</tt>
- </li>
- <li>SourceInfoMap supports ranges of source lines</li>
- <li>Ant task supports the <tt>timestampNow</tt> attribute
- </li>
- </ul>
-
- <p>Changes since version 0.9.3:</p>
- <ul>
- <li>Substantial rework of datamining code</li>
- <li>Removed bogus warnings about await on things other than
- Condition not being in a loop</li>
- <li>Fixed bug in OpcodeStack handling of dup2 of long/double
- values</li>
- <li>Don't report array types as missing classes</li>
- <li>Adjustment of some warnings on ignored return values</li>
- <li>Added thread safety annotations from Java Concurrency in
- Practice (no detectors written for these yet)</li>
- <li>Added annotation for methods that, if overridden, should
- be invoked by overriding methods via a call to super</li>
- <li>Updated -html:fancy.xsl (Etienne Giraudy)</li>
- </ul>
-
- <p>Note: there was no version 0.9.2</p>
-
- <p>Changes since version 0.9.1:</p>
- <ul>
- <!-- New detectors -->
- <li>Embellish USM to find abstract methods that implement an
- interface method (Dave Brosius)</li>
- <li>New detector to find stores of literal booleans inside if
- or while expressions (Dave Brosius)</li>
- <li>New style detector to find final classes that declare
- protected fields (Dave Brosius)</li>
- <li>New detector to find subclass methods that simply forward,
- verbatim, to the super class (Dave Brosius)</li>
- <li>Detector to find instances where code is attempting to
- write an object out via an implementation of DataOutput, but the
- object is not guaranteed to be Serializable (Jon Christiansen,
- Bill Pugh)</li>
-
- <!-- Feature enhancements -->
- <li>Large (35%) analysis speedup (Bill Pugh)</li>
- <li>Add line numbers to Swing GUI code panel (Dave Brosius)</li>
- <li>Added effort options to Swing GUI (Dave Brosius)</li>
- <li>Add ability to specify bugs file to open from command line
- for GUI version, through -loadbugs (Phillip Martin)</li>
- <li>New stylesheet for generating HTML: use option <tt>-html:plain.xsl</tt>
- (Chris Nappin)
- </li>
- <li>New stylesheet for generating HTML: use option <tt>-html:fancy.xsl</tt>
- (Etienne Giraudy)
- </li>
- <li>Updated Japanese bug message translations (Shisei Hanai)</li>
-
- <!-- Bug fixes -->
- <li>XHTML compliance fixes for bug details (Etienne Giraudy)</li>
- <li>Various detector fixes (Shisei Hanai)</li>
- <li>Fixed bugs in the project preferences dialog int the
- Eclipse plugin (Takashi Okamoto, Thomas Einwaller)</li>
- <li>Lowered priority of analysis thread in Swing GUI (David
- Hovemeyer, suggested by Shisei Hanai and Jeffrey W. Badorek)</li>
- <li>Fixed EclipsePlugin to correctly pick up auxclasspath
- entries (Jon Christiansen)</li>
- </ul>
-
- <p>Changes since version 0.9.0:</p>
- <ul>
- <li>Fixed dependence on JRE 1.5: all features should work on
- JRE 1.4 again</li>
- <li>Fixed -effort command line option handling for Swing GUI</li>
- <li>Fixed conserveSpace and workHard attributes int Ant task</li>
- <li>Added support for effort attribute in Ant task</li>
- </ul>
-
- <p>Changes since version 0.8.8:</p>
- <ul>
- <!-- New detectors and bug patterns -->
- <li>XMLFactoryBypass detector to find direct allocation of xml
- class implementations (Dave Brosius)</li>
- <li>InefficientMemberAccess detector to find accesses to
- owning class private members (Dave Brosius)</li>
- <li>DuplicateBranches detector checks switch statements too
- (Dave Brosius)</li>
-
- <!-- Feature enhancements -->
- <li>FindBugs available from findbugs.sourceforge.net as Java
- Web Start application (Dave Brosius)</li>
- <li>Updated Japanese bug message translations (Shisei Hanai)</li>
- <li>Improved bug detail message for covariant equals() (Shisei
- Hanai)</li>
- <li>Modeling of instanceof checks is now enabled by default,
- making the bad cast detector much more useful (Bill Pugh, David
- Hovemeyer)</li>
- <li>Support for detector ordering constraints in plugin
- descriptor (David Hovemeyer)</li>
- <li>Simpler option to control analysis effort: -effort: <i>value</i>,
- where <i>value</i> is one of <code> min </code> , <code>
- default </code> , or <code> max </code> (David Hovemeyer)
- </li>
- <li>Using -effort:max, FindNullDeref checks for null arguments
- passed to methods which dereference them unconditionally (David
- Hovemeyer)</li>
- <li>FindNullDeref checks @Null and @NonNull annotations for
- parameters and return values (David Hovemeyer)</li>
-
- <!-- Bug fixes -->
- </ul>
-
- <p>Changes since version 0.8.7:</p>
-
- <ul>
- <!-- New detectors and bug patterns -->
- <li>New detector to find duplicate code in if/else statements
- (Dave Brosius)</li>
- <li>Look for calls to wait() on Condition objects (David
- Hovemeyer)</li>
- <li>Look for java.util.concurrent.Lock objects not released on
- every path out of method (David Hovemeyer)</li>
- <li>Look for calls to Thread.sleep() with a lock held (David
- Hovemeyer)</li>
- <li>More accurate detection of impossible casts (Bill Pugh,
- David Hovemeyer)</li>
-
- <!-- Feature enhancements -->
- <li>Saved XML now contains project statistics (Jay Dunning)</li>
- <li>Filter files can select by bug pattern type and warning
- priority (David Hovemeyer)</li>
-
- <!-- Bug fixes -->
- <li>Restored some files inadvertently omitted from previous
- release (Rohan Lloyd, David Hovemeyer)</li>
- <li>Make sure detectors requiring JDK 1.5 runtime classes are
- only executed if those classes are available (David Hovemeyer)</li>
- <li>Don't display analysis error dialog unless there is really
- an error (David Hovemeyer)</li>
- <li>Updated and expanded French translations of bug patterns
- and Swing GUI (Olivier Parent)</li>
- <li>Fixed invalid character encoding in German Swing GUI
- translation (Olivier Parent)</li>
- <li>Fix locale used for date format in project stats (K.
- Hashimoto)</li>
- <li>Fixed LongDescription elements in xml:withMessages output
- format (K. Hashimoto)</li>
- </ul>
-
- <p>Changes since version 0.8.6:</p>
-
- <ul>
- <!-- new detectors -->
- <li>Extend Naming detector to look for classes that are named
- XXXException but that are not Exceptions (Dave Brosius)</li>
- <li>New detector to find classes that expose semaphores in the
- public implementation through the 'this' reference. (Dave Brosius)
- </li>
- <li>New Style detector to find Struts Action/Servlet derived
- classes that reference instance member variable not in
- synchronized blocks. (Dave Brosius)</li>
- <li>New Style detector to find classes that declare
- implementation of interfaces that are already implemented by super
- classes (Dave Brosius)</li>
- <li>New Style detector to find circular dependencies between
- classes (Dave Brosius)</li>
- <li>New Style detector to find unnecessary math on constants
- (Dave Brosius)</li>
- <li>New detector to find equality comparisons using floating
- point math (Jay Dunning)</li>
- <li>New faster detector to find local self assignments (Bill
- Pugh)</li>
- <li>New detector to find infinite recursive loops (Bill Pugh)
- </li>
- <li>New detector to find for loops with an incorrect increment
- (Bill Pugh)</li>
- <li>New detector to find suspicious uses of
- BufferedReader.readLine() and String.indexOf() (Bill Pugh)</li>
- <li>New detector to find suspicious integer to double casts
- (David Hovemeyer, Bill Pugh)</li>
- <li>New detector to find invalid regular expression patterns
- (Bill Pugh)</li>
- <li>New detector to find Bloch/Gafter Java puzzlers (Bill
- Pugh)</li>
-
- <!-- feature enhancements -->
- <li>New system property to suppress reporting of DLS based on
- local variable name (Glenn Boysko)</li>
- <li>Enhancements to configuration dialog in Eclipse plugin,
- allow for saving enabled detectors in Eclipse projects (Phil
- Crosby)</li>
- <li>Sortable columns in detector dialog (Dave Brosius)</li>
- <li>New tab in gui for showing bugs grouped by category (Dave
- Brosius)</li>
- <li>Improved German translation of Swing GUI (Thomas Kuehne)</li>
- <li>Improved source file reporting in Emacs output format (Len
- Trigg)</li>
- <li>Improvements to redundant null comparison detector (Bill
- Pugh)</li>
- <li>Localization of run analysis and analysis error dialogs in
- Swing GUI (K. Hashimoto)</li>
-
- <!-- Bug fixes -->
- <li>Don't scan equals methods in FindHEMismatch if code is
- native (Greg Bentz)</li>
- <li>French translation fixes (David Cotton)</li>
- <li>Internationalization report fixes (K. Hashimoto)</li>
- <li>Japanese translations updates (SHISEI Hanai)</li>
- </ul>
-
- <p>Changes since version 0.8.5:</p>
- <ul>
- <!-- new detectors -->
- <li>New detector to find catch blocks that may inadvertently
- catch runtime exceptions (Brian Goetz)</li>
- <li>New detector to find objects that are instantiated based
- on classes that only have static methods and fields, using the
- synthesized constructor (Dave Brosius)</li>
- <li>New detector to find calls to Thread.interrupted() in a
- non static context, and especially with non currentThread()
- threads (Dave Brosius)</li>
- <li>New detector to find calls to equals() methods that use
- Object's version. (Dave Brosius)</li>
- <li>New detector to find Applets that call methods in the
- constructor refering to the AppletStub (Dave Brosius)</li>
- <li>New detector to find some cases of infinite recursion
- (Bill Pugh)</li>
- <li>New detector to find dead stores to local variables (David
- Hovemeyer, Bill Pugh)</li>
- <li>Extend Dumb Method detector for toUpperCase(),
- toLowerCase() without a locale, new Integer(1).toString(), new
- XXX().getClass(), and new Thread() without a run implementation
- (Dave Brosius) <!-- feature enhancements -->
- </li>
- <li>Ant task supports "errorProperty" attribute, which sets an
- Ant property to "true" if an error occurs running FindBugs
- (Michael Tamm)</li>
- <li>Eclipse plugin allows filtering of warnings by bug
- category, priority (David Hovemeyer)</li>
- <li>Swing GUI allows filtering of warnings by bug category
- (David Hovemeyer)</li>
- <li>Ability to annotate methods using Java 1.5 annotations
- that suppress FindBugs warnings (Bill Pugh)</li>
- <li>New -adjustExperimental for lowering priority of
- BugPatterns that are experimental (Dave Brosius)</li>
- <li>Allow for command line options 'files' using the @ symbol
- (David Hovemeyer)</li>
- <li>New -adjustPriority command line option to for adjusting
- bug priorites (David Hovemeyer)</li>
- <li>Added an Edit menu (cut/copy/paste) to Swing GUI (Dave
- Brosius)</li>
- <li>French translation supplied (David Cotton) <!-- Bug fixes -->
- </li>
- </ul>
-
- <p>Changes since version 0.8.4:</p>
- <ul>
- <!-- new detectors -->
- <li>New detector for volatile references to arrays (Bill Pugh)
- </li>
- <li>New detector to find instanceof usage where inheritance
- can be determined statically (Dave Brosius)</li>
- <li>New detector to find ResultSet.getXXX updateXXX calls
- using index 0 (Dave Brosius)</li>
- <li>New detector to find empty zip or jar entries (Bill Pugh)
-
- <!-- feature enhancements -->
- </li>
- <li>HTML output generation using built-in XSLT stylesheet or
- user-defined stylesheet (David Hovemeyer)</li>
- <li>Allow URLs to be specified to analyze zip/jar files, local
- directories, and single classfiles (David Hovemeyer)</li>
- <li>New command line option -onlyAnalyze restricts analysis to
- selected classes and packages without reducing accuracy (David
- Hovemeyer)</li>
- <li>Allow Swing GUI to show source code in jar files on
- Windows systems (Dave Brosius) <!-- Bug fixes -->
- </li>
- <li>Fix the Switch Fall Thru detector (Dave Brosius, David
- Hovemeyer, Bill Pugh)</li>
- <li>MacOS GUI fixes (Rohan Lloyd)</li>
- <li>Fix false positive in BOA in case where method is
- correctly and 'incorrectly' overridden (Dave Brosius)</li>
- <li>Fixed memory blowup when analyzing methods which access a
- large number of fields (David Hovemeyer)</li>
- </ul>
-
- <p>Changes since version 0.8.3:</p>
- <ul>
- <li>Initial and preliminary localization of the Swing
- GUI. Translations by:
- <ul>
- <li>German - Peter D. Stout, Holger Stenzhorn</li>
- <li>Finnish - Juha Knuutila</li>
- <li>Estonian - Tanel Lebedev</li>
- <li>Japanese - Hanai Shisei</li>
- </ul>
- </li>
- <li>Eliminated debug print statements inadvertently left
- enabled</li>
- <li>Reverted some changes in the open stream detector: this
- should fix some false positives that were introduced in the
- previous release</li>
- <li>Fixed a couple missing class reports</li>
- </ul>
-
- <p>Changes since version 0.8.2:</p>
- <ul>
-
- <!-- New detectors -->
- <li>New detector to find improperly overridden GUI Adapter
- classes (Dave Brosius)</li>
- <li>New detector to find improperly setup JUnit TestCases
- (Dave Brosius)</li>
- <li>New detector to find variables that mask class level
- fields (Dave Brosius)</li>
- <li>New detector to find comparisons of values computed with
- bitwise operators that always yield the same result (Tom Truscott)
- </li>
- <li>New detector to find unsafe getClass().getResource() calls
- (Bill Pugh)</li>
- <li>New detector to find GUI changes not in GUI thread but in
- static main (Bill Pugh)</li>
- <li>New detector to find calls to Collection.toArray() with
- zero-length array argument; it is more efficient to pass an array
- the size of the collection, which can be populated and returned as
- the result (Dave Brosius) <!-- Analysis improvements -->
- </li>
- <li>Better suppression of false warnings in various detectors
- (Bill Pugh, David Hovemeyer)</li>
- <li>Enhancement to ReadReturnShouldBeChecked detector for
- skip() (Dave Brosius)</li>
- <li>Enhancement to DumbMethods detector (Dave Brosius)</li>
- <li>Open stream detector does not report wrappers of streams
- passed as method parameters (David Hovemeyer) <!-- Feature enhancements -->
- </li>
- <li>Cancel confirmation dialog in Swing GUI (Pete Angstadt)</li>
- <li>Better relative path saving in Project file (Dave Brosius)
- </li>
- <li>Detector Priority in GUI is now saved in prefs file (Dave
- Brosius)</li>
- <li>Controls in GUI to reorder source and classpath entries,
- and ability to flip between Project details and bugs pages (Dave
- Brosius)</li>
- <li>In Swing GUI, analysis error dialog supports "Select All"
- and "Copy" operations for easy generation of error reports (Dave
- Brosius)</li>
- <li>Complete translation of bug descriptions and messages into
- Japanese (Hanai Shisei) <!-- Bug fixes -->
- </li>
- <li>Fixed bug in DroppedException detector (Dave Brosius) <!-- Development stuff -->
- </li>
- <li>The source distribution defaults to using JDK 1.5 javac to
- compile, but support for compiling with JSR-14 prototype is still
- supported</li>
- </ul>
-
- <p>Changes since version 0.8.1:</p>
- <ul>
- <li>Fixed a critical ClassCastException bug (triggered if the
- -workHard option was used, and an exception type was merged with
- an array type during type inference)</li>
- </ul>
-
- <p>Changes since version 0.8.0:</p>
- <ul>
- <li>Disabled SwitchFallthrough detector to work around
- NullPointerExceptions</li>
- <li>Added some additional false positive suppression
- heuristics</li>
- </ul>
-
- <p>Also, two contributors to the 0.8.0 release were
- inadvertently left out of the credits:</p>
- <ul>
- <li>Pete Angstadt fixed several problems in the Swing GUI</li>
- <li>Francis Lalonde provided a task resource file for the
- FindBugs Ant task</li>
- </ul>
-
- <p>Changes since version 0.7.4:</p>
- <ul>
- <li>New detector to look for uses of "+" operator to
- concatenate String objects in a loop (Dave Brosius)</li>
- <li>Reference comparison detector looks for places where the
- argument passed to the equals(Object) method isn't the same type
- as the receiver object</li>
- <li>Better suppression of false warnings in many detectors</li>
- <li>Many improvements to Eclipse plugin (Andrey Loskutov,
- Peter Friese)</li>
- <li>Fixed problem with building Eclipse plugin on Windows
- (Thomas Klaeger)</li>
- <li>Open stream detector looks for unclosed PreparedStatement
- objects (Thomas Klaeger, Rohan Lloyd)</li>
- <li>Fix for open stream detector: it wasn't detecting close()
- methods called through an invokeinterface instruction (Thomas
- Klaeger)</li>
- <li>Refactoring of visitor classes to enforce use of accessors
- for visited class features (Brian Goetz)</li>
- </ul>
-
- <p>Changes since version 0.7.3:</p>
- <ul>
- <li>Experimental modification of open stream detector to look
- for non-escaping JDBC resources (connections and statements) that
- aren't closed on all paths out of method</li>
- <li>Eclipse plugin fixed so it compiles and runs on Eclipse
- 2.1.x (Peter Friese)</li>
- <li>Option to Swing GUI and command line to generate project
- file using relative paths for archives, source directories, and
- aux classpath entries (Dave Brosius)</li>
- <li>Improvements to findbugs.bat script for launching FindBugs
- on Windows (Dave Brosius)</li>
- <li>Updated Japanese message translations (Hiroshi Okugawa)</li>
- <li>Uncalled private methods are now reported as low priority,
- unless they have the same name as another method in the class
- (which is more likely to indicate an actual bug)</li>
- <li>Added some missing data in the bug messages XML files</li>
- <li>Fixed some problems building from source on Windows
- systems</li>
- <li>Various minor bug fixes</li>
- </ul>
-
- <p>Changes since version 0.7.2:</p>
- <ul>
- <li>Enhanced Eclipse plugin, which displays the detailed bug
- description in a view (Phil Crosby)</li>
- <li>Various tweaks to existing detectors to reduce false
- warnings</li>
- <li>New command line option <code> -workHard </code> enables
- pruning of infeasible or unlikely exception edges, which results
- in better accuracy in the open stream detector, at the expense of
- a 30%-100% slowdown
- </li>
- <li>New website and HTML documentation design</li>
- <li>Documentation includes an HTML document with descriptions
- of all bug patterns reported by FindBugs</li>
- <li>Web page has a link to a <a
- href="http://www.simeji.com/findbugs/doc/manual_ja/index.html">Japanese
- translation</a> of the FindBugs manual, contributed by Hiroshi
- Okugawa
- </li>
- <li>Changed the Inconsistent Synchronization detector so that
- fields synchronized 50% of the time (or more) are reported as
- medium priority bugs (previously they were reported as low)</li>
- <li>New detector to find code that catches
- IllegalMonitorStateException</li>
- <li>New detector to find private methods that are never called
- </li>
- <li>New detector to find suspicious uses of
- non-short-circuiting boolean operators ( <code> & </code> and
- <code> | </code> , rather than <code> && </code> and <code>
- || </code> )
- </li>
- </ul>
-
- <p>Changes since version 0.7.1:</p>
- <ul>
- <li>Incorporated patched version of BCEL, which allows classes
- compiled with JDK 1.5.0 beta to be analyzed</li>
- <li>Fixed some bugs related to lookups of array classes</li>
- <li>Fixed bug that prevented GUI from loading XML result files
- when running under JDK 1.5.0 beta</li>
- <li>Added new experimental bug detector, LazyInit, which looks
- for potentially buggy lazy initializations of static fields</li>
- <li>Because of long filenames, switched to distributing the
- source archive as a zip file rather than a tar file</li>
- <li>The 0.7.1 source tarfile was botched - 0.7.2 has a valid
- source archive</li>
- <li>Fixed some problems in the Ant build script</li>
- <li>Fixed NullPointerException when checking Class-Path
- attribute for Jar files without manifests</li>
- <li>Generate version numbers for the core and UI Eclipse
- plugins using the Version class; all version numbers are now in a
- common location</li>
- </ul>
-
- <p>Changes since version 0.7.0:</p>
- <ul>
- <li>Eclipse plugin (contributed by Peter Friese)</li>
- <li>Source package structure rearranged: all source (other
- than Eclipse plugin UI) is in the edu.umd.cs.findbugs package, or
- a subpackage</li>
- <li>Class-Path attributes of manifests of analyzed jar files
- are used to set the aux classpath automatically (Peter D. Stout)</li>
- <li>GUI starts in directory specified by user.home property
- (Peter D. Stout)</li>
- <li>Added -project option to GUI (Mikko T.)</li>
- <li>Added -look:{plastic,gtk,native} option to GUI, for
- setting look and feel (Mikko T.)</li>
- <li>Fixed DataflowAnalysisException in inconsistent
- synchronization detector</li>
- <li>Ant task supports failOnError parameter (Rohan Lloyd)</li>
- <li>Serializable class warnings are downgraded to low priority
- for GUI classes</li>
- <li>MWN detector will only report calls to wait(), notify(),
- and notifyAll() methods that have the correct signature</li>
- <li>FindBugs works with latest CVS version of BCEL</li>
- <li>Zip and Jar files may be added to the source path</li>
- <li>The GUI will automatically find source files residing in
- analyzed Zip or Jar files</li>
- </ul>
-
- <p>Note that the version number jumped from 0.6.6 to 0.6.9;
- there were no 0.6.7 or 0.6.8 releases.</p>
- <p>Changes since version 0.6.9:</p>
- <ul>
- <li>Added -conserveSpace option to reduce memory use at the
- expense of analysis precision</li>
- <li>Bug fixes in findbugs.bat script: JAVA_HOME handling,
- autodetection of FINDBUGS_HOME, missing output with -textui</li>
- <li>Fixed NullPointerException when a missing class is
- encountered</li>
- </ul>
-
- <p>Changes since version 0.6.6:</p>
- <ul>
- <li>The null pointer dereference detector is more powerful</li>
- <li>Significantly improved heuristics and bug fixes in
- inconsistent synchronization detector</li>
- <li>Improved heuristics in open stream and dropped exception
- detectors; fewer false positives should be reported</li>
- <li>Save HTML summary in XML results files, rather than
- recomputing; this makes loading results in GUI much faster</li>
- <li>Report at most one String comparison using == or != per
- method</li>
- <li>The findbugs.bat script on Windows autodetects
- FINDBUGS_HOME, and doesn't open a DOS window when launching the
- GUI (contributed by TJSB)</li>
- <li>Emacs reporting format (contributed by David Li)</li>
- <li>Various bug fixes</li>
- </ul>
-
- <p>Changes since 0.6.5:</p>
- <ul>
- <li>Rewritten inconsistent synchronization detector; accuracy
- is significantly improved, and bug reports are prioritized</li>
- <li>New detector to find self assignment (x=x) of local
- variables (suggested by Jeff Martin)</li>
- <li>New detector to find calls to wait(), notify(), and
- notifyAll() on an object which is not obviously locked</li>
- <li>Open stream detector now reports Readers and Writers</li>
- <li>Fixed bug in finalizer idioms detector which caused
- spurious warnings about failure to call super.finalize() (reported
- by Jim Menard)</li>
- <li>Fixed bug where output stream was not closed using non-XML
- output (reported by Sigiswald Madou)</li>
- <li>Fixed corrupted HTML bug detail message (reported by
- Trevor Harmon)</li>
- </ul>
-
- <p>Changes since version 0.6.4:</p>
- <ul>
- <li>For redundant comparison of reference values, fixed false
- positives resulting from duplication of code in finally blocks</li>
- <li>Fixed false positives resulting from wrapped byte array
- streams left open</li>
- <li>Fixed bug in Ant task preventing output file from working
- properly if a relative path was used</li>
- </ul>
-
- <p>Changes since version 0.6.3:</p>
- <ul>
- <li>Fixed bug in Ant task where output would be corrupted, and
- added a <code> timeout </code> attribute
- </li>
- <li>Added -outputFile option to text UI, for explicitly
- specifying an output file</li>
- <li>GUI has a summary window, for statistics about overall bug
- densities (contributed by Mike Fagan)</li>
- <li>Find redundant comparisons of reference values</li>
- <li>More accurate detection of Strings compared with == and !=
- operators</li>
- <li>Detection of other reference types which should generally
- not be compared with == and != operators; Boolean, Integer, etc.</li>
- <li>Find non-transient non-serializable instance fields in
- Serializable classes</li>
- <li>Source code may be compiled with latest early access
- generics-enabled javac (version 2.2)</li>
- </ul>
-
- <p>Changes since version 0.6.2:</p>
- <ul>
- <li>GUI supports filtering bugs by priority</li>
- <li>Ant task rewritten; supports all functionality offered by
- Text UI (contributed by Mike Fagan)</li>
- <li>Ant task is fully documented in the manual</li>
- <li>Classes in nested archives are analyzed; this allows full
- support for analyzing .ear and .war files (contributed by Mike
- Fagan)</li>
- <li>DepthFirstSearch changed to use non-recursive
- implementation; this should fix the StackOverflowErrors that
- several users reported</li>
- <li>Various minor bugfixes and improvements</li>
- </ul>
-
- <p>Changes since version 0.6.1:</p>
- <ul>
- <li>New detector to look for useless control flow (suggested
- by Richard P. King and Mike Fagan)</li>
- <li>Look for places where return value of
- java.io.File.createNewFile() is ignored (suggested by Richard P.
- King)</li>
- <li>Fixed bug in resolution of source files (only the first
- source directory was searched)</li>
- <li>Fixed a NullPointerException in the bytecode pattern
- matching code</li>
- <li>Ant task supports project files (contributed by Mike
- Fagan)</li>
- <li>Unix findbugs script honors the <code> JAVA_HOME </code>
- environment variable (contributed by Pedro Morais)
- </li>
- <li>Allow .war and .ear files to be analyzed</li>
- </ul>
-
- <p>Changes since version 0.6.0:</p>
- <ul>
- <li>New bug pattern detector which looks for places where a
- null pointer might be dereferenced</li>
- <li>New bug pattern detector which looks for IO streams that
- are opened, do not escape the method, and are not closed on all
- paths out of the method</li>
- <li>New bug pattern detector to find methods that can return
- null instead of a zero-length array</li>
- <li>New bug pattern detector to find places where the == or !=
- operators are used to compare String objects</li>
- <li>Command line interface can save bugs as XML</li>
- <li>GUI can save bugs to and load bugs from XML</li>
- <li>An "Annotations" window in the GUI allows the user to add
- textual annotations to bug reports; these annotations are
- preserved when bugs are saved as XML</li>
- <li>In this release, the Japanese bug summary translations by
- Germano Leichsenring are really included (they were inadvertently
- omitted in the previous release)</li>
- <li>Completely rewrote the control flow graph builder,
- hopefully for the last time</li>
- <li>Simplified implementation of control flow graphs, which
- should reduce memory use and possibly improve performance</li>
- <li>Improvements to command line interface (list bug
- priorities, filter by priority, specify aux classpath, specify
- project to analyze)</li>
- <li>Various bug fixes and enhancements</li>
- </ul>
-
- <p>Changes since version 0.5.4</p>
- <ul>
- <li>Added an <a href="http://ant.apache.org/">Ant</a> task for
- FindBugs, contributed by Mike Fagan.
- </li>
- <li>Added a GUI dialog which allows individual bug pattern
- detectors to be enabled or disabled. Disabling certain slow
- detectors can greatly speed up analysis of large programs, at the
- expense of reducing the number of potential bugs found.</li>
- <li>Added a new detector for finding improperly ignored return
- values for methods such as <code> String.trim() </code> .
- Suggested by Andreas Mandel.
- </li>
- <li>Japanese translations of the bug summaries, contributed by
- Germano Leichsenring.</li>
- <li>Filtering of results is supported in command line
- interface. See the <a href="manual/index.html">FindBugs manual</a>
- for details.
- </li>
- <li>Added "byte code patterns", a general pattern matching
- infrastructure for bytecode instructions. This feature
- significantly reduces the complexity of implementing new bug
- pattern detectors.</li>
- <li>Enabled a new general dataflow analysis to track values in
- methods.</li>
- <li>Switched to new control-flow graph builder implementation.
- </li>
- </ul>
-
- <p>Changes since version 0.5.3</p>
- <ul>
- <li>Fixed a bug in the script used to launch FindBugs on
- Windows platforms.</li>
- <li>Fixed crashes when analyzing class files without source
- line information.</li>
- <li>All major errors are reported using an error dialog; file
- not found errors are more informative.</li>
- <li>Minor GUI improvements.</li>
- </ul>
-
- <p>Changes since version 0.5.2</p>
- <ul>
- <li>All of the source code and related files are in a single
- directory tree.</li>
- <li>Updated some of the detectors to produce source line
- information.</li>
- <li><a href="http://ant.apache.org/">Ant</a> build script and
- several GUI enhancements and fixes contributed by Mike Fagan.</li>
- <li>Converted to use a <a href="AddingDetectors.txt">plugin
- architecture</a> for loading bug detectors.
- </li>
- <li>Eliminated generics-related compiler warnings.</li>
- <li>More complete documentation has been added.</li>
- </ul>
-
- <p>Changes since version 0.5.1:</p>
- <ul>
- <li>Fixed a large number of bugs in the BCEL Repository and
- FindBugs's use of the Repository. With these changes,
- FindBugs should <em>never</em> crash or otherwise misbehave
- because of Repository lookup failures. Because of these
- changes, you must use a modified version of <code> bcel.jar
- </code> with FindBugs. This jar file is included in the FindBugs
- 0.5.2 binary release. A complete patch containing the <a
- href="http://faculty.ycp.edu/~dhovemey/bcel-30-April-2003.patch">modifications
- against the BCEL CVS main branch as of April 30, 2003</a> is also
- available.
- </li>
- <li>Implemented the "auxiliary classpath entry list".
- Aux classpath entries can be added to a project to provide classes
- that are referenced by the analyzed application, but should not
- themselves be analyzed. Having all referenced classes
- available allows FindBugs to produce more accurate results.</li>
- </ul>
-
- <p>Changes since version 0.5.0:</p>
- <ul>
- <li>Many user interface bugs have been fixed.</li>
- <li>Upgraded to a recent CVS version of BCEL, with some bug
- fixes. This should prevent FindBugs from crashing when there
- is a failure to find a class on the classpath.</li>
- <li>Added support for Plastic look and feel from <a
- href="http://www.jgoodies.com/">jgoodies.com</a>.
- </li>
- <li>Major overhaul of infrastructure for doing dataflow
- analysis.</li>
- </ul> @HTML_FOOTER@
-
- </td>
-
- </tr>
- </table>
+ </li>
+ <li>Added check for a dead local store caused by a switch
+ statement fall through</li>
+ <li>Added check for computing the absolute value of a random
+ 32 bit integer or of a hashcode. This is broken because <code>
+ Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE </code> , and thus
+ result of calling Math.abs, which is expected to be nonnegative,
+ will in fact be negative one time out of 2 <sup> 32 </sup> , which
+ will invariably be the time your boss is demoing the software to
+ your customers.
+
+ </li>
+ <li>More careful resolution of inherited methods and fields.
+ Some of the shortcuts we were taking in FindBugs 1.0.0 were
+ leading to inaccurate results, and it was fairly easy to address
+ this by making the analysis more accurate.</li>
+ <li>Overall, analysis times are about 1.6 times longer in
+ FindBugs 1.1.0 than in FindBugs 1.0.0. This is because we have
+ enabled substantial additional analysis at the default effort
+ level (the actual analysis engine is significantly faster than in
+ FindBugs 1.0). On a recent AMD Athlon processor, analyzing
+ JDK1.6.0 (about 1 million lines of code) requires about 15 minutes
+ of wall clock time.</li>
+ <li>Provided class and script (printClass) to print classfile
+ in the human readable format produced by BCEL</li>
+ <li>Provided -findSource option to setBugDatabaseInfo</li>
+ </ul>
+
+
+ <p>Changes since version 0.9.7:</p>
+
+ <ul>
+ <li>fix ObjectTypeFactory bug that was suppressing some bugs</li>
+ <li>opcode stack may determine definite zeros on some paths</li>
+ <li>opcode stack can track some constant string concatenations
+ (dbrosius)</li>
+ <li>default effort performs iterative opcode analysis (but min
+ effort does not)</li>
+ <li>default heap size upped to 384m</li>
+ <li>schema for XML output available: bugcollection.xsd</li>
+ <li>fixed some internal confusion between dotted and slashed
+ class names</li>
+ <li>New detectors
+ <ul>
+ <li>CheckImmutableAnnotation.java: checks JCIP annotations</li>
+ </ul>
+ </li>
+ <li>Updated detectors
+ <ul>
+ <li>BadRegEx.java: understands Pattern.LITERAL, warns about
+ "."</li>
+ <li>FindUnreleasedLock.java: fewer false positives</li>
+ <li>DumbMethods.java: check for vacuous comparisons to
+ MAX_INTEGER or MIN_INTEGER, fix bugs detecting
+ DM_NEXTINT_VIA_NEXTDOUBLE</li>
+ <li>FindPuzzlers.java: detect <tt>n%2==1</tt>, detect
+ toString() on array types
+ </li>
+ <li>FindInconsistentSync2.java: detects IS_FIELD_NOT_GUARDED
+ </li>
+ <li>MethodReturnCheck.java: add check for discarded newly
+ constructed values, increase priority of some ignored
+ constructed exceptions, better handling of bytecode compiled by
+ Eclipse</li>
+ <li>FindEmptySynchronizedBlock.java: better handling of
+ bytecode compiled by Eclipse</li>
+ <li>DoInsideDoPrivileged.java: warn if call to setAccessible
+ isn't in doPriviledged, don't report private methods</li>
+ <li>LoadOfKnownNullValue.java: fix bug that was reporting
+ false positives on <code> finally </code> blocks
+ </li>
+ <li>CheckReturnAnnotationDatabase.java: better checks for
+ unstarted threads</li>
+ <li>ConfusionBetweenInheritedAndOuterMethod.java: fewer
+ false positives, fixed a package-handling bug</li>
+ <li>BadResultSetAccess.java: separate bug pattern for
+ PreparedStatements, <code> BRZA </code> category folded into <code>
+ SQL </code> category
+ </li>
+ <li>FindDeadLocalStores.java, FindBadCast2.java,
+ DumbMethods.java, RuntimeExceptionCapture.java: coalesce similar
+ bugs within a method into a single bug instance with multiple
+ source lines</li>
+ </ul>
+ </li>
+ <li>Eclipse plugin
+ <ul>
+ <li>plugin ID changed from <tt>de.tobject.findbugs</tt> to <tt>edu.umd.cs.findbugs.plugin.eclipse</tt>
+ </li>
+ <li>support for findbugs eclipse auto-update site</li>
+ </ul>
+ </li>
+ <li>Updated test case files
+ <ul>
+ <li>BadRegEx.java</li>
+ <li>JSR166.java</li>
+ <li>ConcurrentModificationBug.java</li>
+ <li>DeadStore.java</li>
+ <li>InstanceOf.java</li>
+ <li>LoadKnownNull.java</li>
+ <li>NeedsToCheckReturnValue.java</li>
+ <li>BadResultSetAccessTest.java</li>
+ <li>DeadStore.java</li>
+ <li>TestNonNull2.java</li>
+ <li>TestImmutable.java</li>
+ <li>TestGuardedBy.java</li>
+ <li>BadRandomInt.java</li>
+ <li>six test cases added to new <code> TigerTraps </code>
+ directory
+ </li>
+ </ul>
+ </li>
+ <li>fix bug that was generating duplicate uids</li>
+ <li>fix bug with <code> -onlyAnalyze some.package.* </code> on
+ jdk1.4
+ </li>
+ <li>fix regression bug in
+ DismantleByteCode.getRefConstantOperand()</li>
+ <li>fix some minor bugs with the Swing GUI</li>
+ <li>reordered some bugInstances so that source line
+ annotations come last</li>
+ <li>removed references to unused java system properties</li>
+ <li>French translation updates (David Cotton)</li>
+ <li>Japanese translation updates (Hanai Shisei)</li>
+ <li>content cleanup for findbugs.xml and messages.xml</li>
+ <li>references to cvs hostname updated to
+ findbugs.cvs.sourceforge.net</li>
+ <li>documented xdoc output options, new
+ mineBugHistory/computeBugHistory options</li>
+ </ul>
+
+ <p>Changes since version 0.9.6:</p>
+
+ <ul>
+ <li>performance improvements</li>
+ <li>ObjectType instances are cached to reduce memory footprint
+ </li>
+ <li>for performance and memory reasons stateless detectors are
+ no longer cloned, must clear their own state between .class files
+ </li>
+ <li>fixed bug in bytecode-set lookup for methods (was causing
+ bad results for IS2, perhaps others)</li>
+ <li>fix some OpcodeStack bugs with integer and long
+ operations, perform iterative analysis when effort is <tt>max</tt>
+ </li>
+ <li>HTML output includes LongMessage text again (regression in
+ 0.95 - 0.96)</li>
+ <li>New detectors
+ <ul>
+ <li>CalledMethods.java: builds a list of invoked methods for
+ other detectors to consult (non-reporting)</li>
+ <li>UncallableMethodOfAnonymousClass.java: detect anonymous
+ inner classes that define methods that are probably intended to
+ but do not override methods in a superclass.</li>
+ </ul>
+ </li>
+ <li>Updated detectors
+ <ul>
+ <li>FindFieldSelfAssignment.java: recognize separate fields
+ with the same name (one from superclass)</li>
+ <li>FindLocalSelfAssignment2.java: handles backward branches
+ better (Dave Brosius)</li>
+ <li>FindBadCast2.java: BC_NULL_INSTANCEOF changed to
+ NP_NULL_INSTANCEOF</li>
+ <li>FindPuzzlers.java: eliminate false positive on setDate()
+ (Dave Brosius)</li>
+ </ul>
+ </li>
+ <li>Eclipse plugin
+ <ul>
+ <li>fix serious threading bug</li>
+ <li>preferences for Filters and effort (Peter Hendriks)</li>
+ <li>French localization (David Cotton)</li>
+ <li>fix bug when reporting inner classes (Peter Friese)</li>
+ </ul>
+ </li>
+ <li>Updated test case files
+ <ul>
+ <li>Mwn.java (Carl Burke/Dave Brosius)</li>
+ <li>DumbMethodInvocations.java (Anto paul/Dave Brosius)</li>
+ <!--sic-->
+ </ul>
+ </li>
+ <li>XML output includes garbage collection duration</li>
+ <li>French messages updated (David Cotton)</li>
+ <li>Swing GUI shows file name after Load Bugs command</li>
+ <li>Ant task to launch the findbugs frame (Mark McKay)</li>
+ <li>miscellaneous code cleanup</li>
+ </ul>
+
+ <p>Changes since version 0.9.5:</p>
+
+ <ul>
+ <li>Updated detectors
+ <ul>
+ <li>FindNullDeref.java: respect NonNull and CheckForNull
+ field annotations</li>
+ <li>SerializableIdiom.java: detect non-private readObject
+ and writeObject methods</li>
+ <li>FindRefComparison.java: smarter array comparison
+ detection</li>
+ <li>IsNullValueAnalysis.java: detect <tt>null
+ instanceof</tt>
+ </li>
+ <li>FindLocalSelfAssignment2.java: suppress some false
+ positives (Dave Brosius)</li>
+ <li>FindUnreleasedLock.java: don't waste time processing
+ classes that don't refer to java.util.concurrent.locks</li>
+ <li>MutableStaticFields.java: report the source line (Dave
+ Brosius)</li>
+ <li>SwitchFallthrough.java: better handling of System.exit()
+ (Dave Brosius)</li>
+ <li>MultithreadedInstanceAccess.java: better handling of
+ Servlet.init() (Dave Brosius)</li>
+ <li>ConfusionBetweenInheritedAndOuterMethod.java: now
+ enabled</li>
+ </ul>
+ </li>
+ <li>Eclipse plugin
+ <ul>
+ <li>background processing (Peter Friese)</li>
+ <li>internationalization, Japanese localization (Takashi
+ Okamoto)</li>
+ </ul>
+ </li>
+ <li>findbugs <tt>-onlyAnalyze</tt> option now works on windows
+ platforms
+ </li>
+ <li>mineBugHistory <tt>-noTabs</tt> option for better
+ alignment of output columns
+ </li>
+ <li>filterBugs <tt>-fixed</tt> option (also: will now
+ recognize the most recent version string)
+ </li>
+ <li>XML output includes running time and memory usage data</li>
+ <li>miscellaneous minor corrections to the manual</li>
+ <li>better bytecode analysis of the <tt>iinc</tt> instruction
+ </li>
+ <li>fix bug in null pointer analysis</li>
+ <li>improved catch block heuristics</li>
+ <li>some type analysis tweaks</li>
+ <li>Bug priority changes
+ <ul>
+ <li>DumbMethodInvocations.java: decrease priority of
+ hard-coded <tt>/tmp</tt> filenames
+ </li>
+ <li>ComparatorIdiom.java: decrease priority of
+ non-serializable anonymous comparators</li>
+ <li>FindSqlInjection.java: decrease priority of appending a
+ constant or a static</li>
+ </ul>
+ </li>
+ <li>Updated bug explanations
+ <ul>
+ <li>NM_VERY_CONFUSING (Dave Brosius)</li>
+ </ul>
+ </li>
+ <li>Updated test case files
+ <ul>
+ <li>BadStoreOfNonSerializableObject.java</li>
+ <li>BadRandomInt.java</li>
+ <li>TestFieldAnnotations.java</li>
+ <li>UseInitCause.java</li>
+ <li>SqlInjection.java</li>
+ <li>ArrayEquality.java</li>
+ <li>BadIntegerOperations.java</li>
+ <li>Pilhuhn.java</li>
+ <li>InstanceOf.java</li>
+ <li>SwitchFallthrough.java (Dave Brosius)</li>
+ </ul>
+ </li>
+ <li>fix URL decoding bug when running under Java Web Start
+ (Dave Brosius)</li>
+ <li>distribution includes <tt>project.xml</tt> file for
+ NetBeans
+ </li>
+ </ul>
+
+ <p>Changes since version 0.9.4:</p>
+ <ul>
+ <li>New detectors
+ <ul>
+ <li>VarArgsProblems.java</li>
+ <li>FindSqlInjection.java: now enabled</li>
+ <li>ComparatorIdiom.java: comparators usually implement
+ serializable</li>
+ <li>Naming.java: detect methods not overridden due to
+ eponymously typed args from different packages</li>
+ </ul>
+ </li>
+ <li>Updated detectors
+ <ul>
+ <li>SwitchFallthrough.java: surpress some false positives</li>
+ <li>DuplicateBranches.java: surpress some false positives</li>
+ <li>IteratorIdioms.java: surpress some false positives</li>
+ <li>FindHEmismatch.java: surpress some false positives</li>
+ <li>QuestionableBooleanAssignment.java: finds more cases of
+ <tt>if (b=true)</tt> ilk
+ </li>
+ <li>DumbMethods.java: detect int remainder by 1, delayed gc
+ errors</li>
+ <li>SerializableIdiom.java: detect store of nonserializable
+ object into field of serializable class</li>
+ <li>FindNullDeref.java: fix potential exception</li>
+ <li>IsNullValue.java: fix potential exception</li>
+ <li>MultithreadedInstanceAccess.java: fix potential
+ exception</li>
+ <li>PreferZeroLengthArrays.java: flag the method, not the
+ line</li>
+ </ul>
+ </li>
+ <li>Remove some inadvertent dependencies on JDK 1.5</li>
+ <li>Sort order should be more consistent</li>
+ <li>XML output changes
+ <ul>
+ <li>Option to sort XML bug output</li>
+ <li>Now contains instance IDs</li>
+ <li>uid no longer missing (was causing problems with fancy
+ HTML output)</li>
+ <li>Typo fixed</li>
+ </ul>
+ </li>
+ <li>Internal changes to track source files, <tt>-sourceInfo</tt>
+ option
+ </li>
+ <li>Bug matching: first try exact bug pattern matching, option
+ to compare priorities, option to disable package moves</li>
+ <li>Architecture documentation in <tt>design/architecture</tt>
+ </li>
+ <li>Test cases move into their own CVS project</li>
+ <li>Don't report warnings that occur outside the analyzed
+ classes</li>
+ <li>Fixes to the build.xml files</li>
+ <li>Better handling of @CheckReturnValue and @CheckForNull
+ annotations (also, some additional methods searched for check
+ return value and check for null)</li>
+ <li>Fixed some stream-closing bugs (one by <tt>z-fb-user</tt>/Dave
+ Brosius)
+ </li>
+ <li>Bug priority changes
+ <ul>
+ <li>increase priority of ignoring return value of
+ java.sql.Connection methods</li>
+ <li>increase priority of comparing classes like Integer
+ using <tt>==</tt>
+ </li>
+ <li>decrease priority of IT_NO_SUCH_ELEMENT if we see any
+ call to <tt>next()</tt>
+ </li>
+ <li>tweak priority of NM_METHOD_CONSTRUCTOR_CONFUSION</li>
+ <li>decrease priority of RV_RETURN_VALUE_IGNORED for an
+ inherited annotation that doesn't return same type as class</li>
+ </ul>
+ </li>
+ <li>Updated bug explanations
+ <ul>
+ <li>RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE</li>
+ <li>DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED</li>
+ <li>IMA_INEFFICIENT_MEMBER_ACCESS (Dave Brosius)</li>
+ <li>some Japanese improvements to messages_ja.xml ( <tt>ruimo</tt>)
+ </li>
+ <li>some German improvements to findbugs_de.properties (Dave
+ Brosius, <tt>dvholten</tt>)
+ </li>
+ </ul>
+ </li>
+ <li>Updated test case files
+ <ul>
+ <li>BadIntegerOperations.java</li>
+ <li>SecondKaboom.java</li>
+ <li>OpenDatabase.java (Dave Brosius)</li>
+ <li>FindOpenStream.java (Dave Brosius)</li>
+ <li>BadRandomInt.java</li>
+ </ul>
+ </li>
+ <li>Source-lines info maintained for methods (handy for
+ abstract and native methods)</li>
+ <li>Remove surrounding opcodes from source line annotations</li>
+ <li>Better error when can't read file</li>
+ <li>Swing GUI: removed console pane from FindBugsFrame, fix
+ missing classes bug</li>
+ <li>Fixes to OpcodeStack.java</li>
+ <li>Detectors may attach a custom value to an OpcodeStack.Item
+ (Dave Brosius)</li>
+ <li>Filter.java: ability to add text messages to XML output,
+ fix bug with <tt>-withMessages</tt>
+ </li>
+ <li>SourceInfoMap supports ranges of source lines</li>
+ <li>Ant task supports the <tt>timestampNow</tt> attribute
+ </li>
+ </ul>
+
+ <p>Changes since version 0.9.3:</p>
+ <ul>
+ <li>Substantial rework of datamining code</li>
+ <li>Removed bogus warnings about await on things other than
+ Condition not being in a loop</li>
+ <li>Fixed bug in OpcodeStack handling of dup2 of long/double
+ values</li>
+ <li>Don't report array types as missing classes</li>
+ <li>Adjustment of some warnings on ignored return values</li>
+ <li>Added thread safety annotations from Java Concurrency in
+ Practice (no detectors written for these yet)</li>
+ <li>Added annotation for methods that, if overridden, should
+ be invoked by overriding methods via a call to super</li>
+ <li>Updated -html:fancy.xsl (Etienne Giraudy)</li>
+ </ul>
+
+ <p>Note: there was no version 0.9.2</p>
+
+ <p>Changes since version 0.9.1:</p>
+ <ul>
+ <!-- New detectors -->
+ <li>Embellish USM to find abstract methods that implement an
+ interface method (Dave Brosius)</li>
+ <li>New detector to find stores of literal booleans inside if
+ or while expressions (Dave Brosius)</li>
+ <li>New style detector to find final classes that declare
+ protected fields (Dave Brosius)</li>
+ <li>New detector to find subclass methods that simply forward,
+ verbatim, to the super class (Dave Brosius)</li>
+ <li>Detector to find instances where code is attempting to
+ write an object out via an implementation of DataOutput, but the
+ object is not guaranteed to be Serializable (Jon Christiansen,
+ Bill Pugh)</li>
+
+ <!-- Feature enhancements -->
+ <li>Large (35%) analysis speedup (Bill Pugh)</li>
+ <li>Add line numbers to Swing GUI code panel (Dave Brosius)</li>
+ <li>Added effort options to Swing GUI (Dave Brosius)</li>
+ <li>Add ability to specify bugs file to open from command line
+ for GUI version, through -loadbugs (Phillip Martin)</li>
+ <li>New stylesheet for generating HTML: use option <tt>-html:plain.xsl</tt>
+ (Chris Nappin)
+ </li>
+ <li>New stylesheet for generating HTML: use option <tt>-html:fancy.xsl</tt>
+ (Etienne Giraudy)
+ </li>
+ <li>Updated Japanese bug message translations (Shisei Hanai)</li>
+
+ <!-- Bug fixes -->
+ <li>XHTML compliance fixes for bug details (Etienne Giraudy)</li>
+ <li>Various detector fixes (Shisei Hanai)</li>
+ <li>Fixed bugs in the project preferences dialog int the
+ Eclipse plugin (Takashi Okamoto, Thomas Einwaller)</li>
+ <li>Lowered priority of analysis thread in Swing GUI (David
+ Hovemeyer, suggested by Shisei Hanai and Jeffrey W. Badorek)</li>
+ <li>Fixed EclipsePlugin to correctly pick up auxclasspath
+ entries (Jon Christiansen)</li>
+ </ul>
+
+ <p>Changes since version 0.9.0:</p>
+ <ul>
+ <li>Fixed dependence on JRE 1.5: all features should work on
+ JRE 1.4 again</li>
+ <li>Fixed -effort command line option handling for Swing GUI</li>
+ <li>Fixed conserveSpace and workHard attributes int Ant task</li>
+ <li>Added support for effort attribute in Ant task</li>
+ </ul>
+
+ <p>Changes since version 0.8.8:</p>
+ <ul>
+ <!-- New detectors and bug patterns -->
+ <li>XMLFactoryBypass detector to find direct allocation of xml
+ class implementations (Dave Brosius)</li>
+ <li>InefficientMemberAccess detector to find accesses to
+ owning class private members (Dave Brosius)</li>
+ <li>DuplicateBranches detector checks switch statements too
+ (Dave Brosius)</li>
+
+ <!-- Feature enhancements -->
+ <li>FindBugs available from findbugs.sourceforge.net as Java
+ Web Start application (Dave Brosius)</li>
+ <li>Updated Japanese bug message translations (Shisei Hanai)</li>
+ <li>Improved bug detail message for covariant equals() (Shisei
+ Hanai)</li>
+ <li>Modeling of instanceof checks is now enabled by default,
+ making the bad cast detector much more useful (Bill Pugh, David
+ Hovemeyer)</li>
+ <li>Support for detector ordering constraints in plugin
+ descriptor (David Hovemeyer)</li>
+ <li>Simpler option to control analysis effort: -effort: <i>value</i>,
+ where <i>value</i> is one of <code> min </code> , <code>
+ default </code> , or <code> max </code> (David Hovemeyer)
+ </li>
+ <li>Using -effort:max, FindNullDeref checks for null arguments
+ passed to methods which dereference them unconditionally (David
+ Hovemeyer)</li>
+ <li>FindNullDeref checks @Null and @NonNull annotations for
+ parameters and return values (David Hovemeyer)</li>
+
+ <!-- Bug fixes -->
+ </ul>
+
+ <p>Changes since version 0.8.7:</p>
+
+ <ul>
+ <!-- New detectors and bug patterns -->
+ <li>New detector to find duplicate code in if/else statements
+ (Dave Brosius)</li>
+ <li>Look for calls to wait() on Condition objects (David
+ Hovemeyer)</li>
+ <li>Look for java.util.concurrent.Lock objects not released on
+ every path out of method (David Hovemeyer)</li>
+ <li>Look for calls to Thread.sleep() with a lock held (David
+ Hovemeyer)</li>
+ <li>More accurate detection of impossible casts (Bill Pugh,
+ David Hovemeyer)</li>
+
+ <!-- Feature enhancements -->
+ <li>Saved XML now contains project statistics (Jay Dunning)</li>
+ <li>Filter files can select by bug pattern type and warning
+ priority (David Hovemeyer)</li>
+
+ <!-- Bug fixes -->
+ <li>Restored some files inadvertently omitted from previous
+ release (Rohan Lloyd, David Hovemeyer)</li>
+ <li>Make sure detectors requiring JDK 1.5 runtime classes are
+ only executed if those classes are available (David Hovemeyer)</li>
+ <li>Don't display analysis error dialog unless there is really
+ an error (David Hovemeyer)</li>
+ <li>Updated and expanded French translations of bug patterns
+ and Swing GUI (Olivier Parent)</li>
+ <li>Fixed invalid character encoding in German Swing GUI
+ translation (Olivier Parent)</li>
+ <li>Fix locale used for date format in project stats (K.
+ Hashimoto)</li>
+ <li>Fixed LongDescription elements in xml:withMessages output
+ format (K. Hashimoto)</li>
+ </ul>
+
+ <p>Changes since version 0.8.6:</p>
+
+ <ul>
+ <!-- new detectors -->
+ <li>Extend Naming detector to look for classes that are named
+ XXXException but that are not Exceptions (Dave Brosius)</li>
+ <li>New detector to find classes that expose semaphores in the
+ public implementation through the 'this' reference. (Dave Brosius)
+ </li>
+ <li>New Style detector to find Struts Action/Servlet derived
+ classes that reference instance member variable not in
+ synchronized blocks. (Dave Brosius)</li>
+ <li>New Style detector to find classes that declare
+ implementation of interfaces that are already implemented by super
+ classes (Dave Brosius)</li>
+ <li>New Style detector to find circular dependencies between
+ classes (Dave Brosius)</li>
+ <li>New Style detector to find unnecessary math on constants
+ (Dave Brosius)</li>
+ <li>New detector to find equality comparisons using floating
+ point math (Jay Dunning)</li>
+ <li>New faster detector to find local self assignments (Bill
+ Pugh)</li>
+ <li>New detector to find infinite recursive loops (Bill Pugh)
+ </li>
+ <li>New detector to find for loops with an incorrect increment
+ (Bill Pugh)</li>
+ <li>New detector to find suspicious uses of
+ BufferedReader.readLine() and String.indexOf() (Bill Pugh)</li>
+ <li>New detector to find suspicious integer to double casts
+ (David Hovemeyer, Bill Pugh)</li>
+ <li>New detector to find invalid regular expression patterns
+ (Bill Pugh)</li>
+ <li>New detector to find Bloch/Gafter Java puzzlers (Bill
+ Pugh)</li>
+
+ <!-- feature enhancements -->
+ <li>New system property to suppress reporting of DLS based on
+ local variable name (Glenn Boysko)</li>
+ <li>Enhancements to configuration dialog in Eclipse plugin,
+ allow for saving enabled detectors in Eclipse projects (Phil
+ Crosby)</li>
+ <li>Sortable columns in detector dialog (Dave Brosius)</li>
+ <li>New tab in gui for showing bugs grouped by category (Dave
+ Brosius)</li>
+ <li>Improved German translation of Swing GUI (Thomas Kuehne)</li>
+ <li>Improved source file reporting in Emacs output format (Len
+ Trigg)</li>
+ <li>Improvements to redundant null comparison detector (Bill
+ Pugh)</li>
+ <li>Localization of run analysis and analysis error dialogs in
+ Swing GUI (K. Hashimoto)</li>
+
+ <!-- Bug fixes -->
+ <li>Don't scan equals methods in FindHEMismatch if code is
+ native (Greg Bentz)</li>
+ <li>French translation fixes (David Cotton)</li>
+ <li>Internationalization report fixes (K. Hashimoto)</li>
+ <li>Japanese translations updates (SHISEI Hanai)</li>
+ </ul>
+
+ <p>Changes since version 0.8.5:</p>
+ <ul>
+ <!-- new detectors -->
+ <li>New detector to find catch blocks that may inadvertently
+ catch runtime exceptions (Brian Goetz)</li>
+ <li>New detector to find objects that are instantiated based
+ on classes that only have static methods and fields, using the
+ synthesized constructor (Dave Brosius)</li>
+ <li>New detector to find calls to Thread.interrupted() in a
+ non static context, and especially with non currentThread()
+ threads (Dave Brosius)</li>
+ <li>New detector to find calls to equals() methods that use
+ Object's version. (Dave Brosius)</li>
+ <li>New detector to find Applets that call methods in the
+ constructor refering to the AppletStub (Dave Brosius)</li>
+ <li>New detector to find some cases of infinite recursion
+ (Bill Pugh)</li>
+ <li>New detector to find dead stores to local variables (David
+ Hovemeyer, Bill Pugh)</li>
+ <li>Extend Dumb Method detector for toUpperCase(),
+ toLowerCase() without a locale, new Integer(1).toString(), new
+ XXX().getClass(), and new Thread() without a run implementation
+ (Dave Brosius) <!-- feature enhancements -->
+ </li>
+ <li>Ant task supports "errorProperty" attribute, which sets an
+ Ant property to "true" if an error occurs running FindBugs
+ (Michael Tamm)</li>
+ <li>Eclipse plugin allows filtering of warnings by bug
+ category, priority (David Hovemeyer)</li>
+ <li>Swing GUI allows filtering of warnings by bug category
+ (David Hovemeyer)</li>
+ <li>Ability to annotate methods using Java 1.5 annotations
+ that suppress FindBugs warnings (Bill Pugh)</li>
+ <li>New -adjustExperimental for lowering priority of
+ BugPatterns that are experimental (Dave Brosius)</li>
+ <li>Allow for command line options 'files' using the @ symbol
+ (David Hovemeyer)</li>
+ <li>New -adjustPriority command line option to for adjusting
+ bug priorites (David Hovemeyer)</li>
+ <li>Added an Edit menu (cut/copy/paste) to Swing GUI (Dave
+ Brosius)</li>
+ <li>French translation supplied (David Cotton) <!-- Bug fixes -->
+ </li>
+ </ul>
+
+ <p>Changes since version 0.8.4:</p>
+ <ul>
+ <!-- new detectors -->
+ <li>New detector for volatile references to arrays (Bill Pugh)
+ </li>
+ <li>New detector to find instanceof usage where inheritance
+ can be determined statically (Dave Brosius)</li>
+ <li>New detector to find ResultSet.getXXX updateXXX calls
+ using index 0 (Dave Brosius)</li>
+ <li>New detector to find empty zip or jar entries (Bill Pugh)
+
+ <!-- feature enhancements -->
+ </li>
+ <li>HTML output generation using built-in XSLT stylesheet or
+ user-defined stylesheet (David Hovemeyer)</li>
+ <li>Allow URLs to be specified to analyze zip/jar files, local
+ directories, and single classfiles (David Hovemeyer)</li>
+ <li>New command line option -onlyAnalyze restricts analysis to
+ selected classes and packages without reducing accuracy (David
+ Hovemeyer)</li>
+ <li>Allow Swing GUI to show source code in jar files on
+ Windows systems (Dave Brosius) <!-- Bug fixes -->
+ </li>
+ <li>Fix the Switch Fall Thru detector (Dave Brosius, David
+ Hovemeyer, Bill Pugh)</li>
+ <li>MacOS GUI fixes (Rohan Lloyd)</li>
+ <li>Fix false positive in BOA in case where method is
+ correctly and 'incorrectly' overridden (Dave Brosius)</li>
+ <li>Fixed memory blowup when analyzing methods which access a
+ large number of fields (David Hovemeyer)</li>
+ </ul>
+
+ <p>Changes since version 0.8.3:</p>
+ <ul>
+ <li>Initial and preliminary localization of the Swing
+ GUI. Translations by:
+ <ul>
+ <li>German - Peter D. Stout, Holger Stenzhorn</li>
+ <li>Finnish - Juha Knuutila</li>
+ <li>Estonian - Tanel Lebedev</li>
+ <li>Japanese - Hanai Shisei</li>
+ </ul>
+ </li>
+ <li>Eliminated debug print statements inadvertently left
+ enabled</li>
+ <li>Reverted some changes in the open stream detector: this
+ should fix some false positives that were introduced in the
+ previous release</li>
+ <li>Fixed a couple missing class reports</li>
+ </ul>
+
+ <p>Changes since version 0.8.2:</p>
+ <ul>
+
+ <!-- New detectors -->
+ <li>New detector to find improperly overridden GUI Adapter
+ classes (Dave Brosius)</li>
+ <li>New detector to find improperly setup JUnit TestCases
+ (Dave Brosius)</li>
+ <li>New detector to find variables that mask class level
+ fields (Dave Brosius)</li>
+ <li>New detector to find comparisons of values computed with
+ bitwise operators that always yield the same result (Tom Truscott)
+ </li>
+ <li>New detector to find unsafe getClass().getResource() calls
+ (Bill Pugh)</li>
+ <li>New detector to find GUI changes not in GUI thread but in
+ static main (Bill Pugh)</li>
+ <li>New detector to find calls to Collection.toArray() with
+ zero-length array argument; it is more efficient to pass an array
+ the size of the collection, which can be populated and returned as
+ the result (Dave Brosius) <!-- Analysis improvements -->
+ </li>
+ <li>Better suppression of false warnings in various detectors
+ (Bill Pugh, David Hovemeyer)</li>
+ <li>Enhancement to ReadReturnShouldBeChecked detector for
+ skip() (Dave Brosius)</li>
+ <li>Enhancement to DumbMethods detector (Dave Brosius)</li>
+ <li>Open stream detector does not report wrappers of streams
+ passed as method parameters (David Hovemeyer) <!-- Feature enhancements -->
+ </li>
+ <li>Cancel confirmation dialog in Swing GUI (Pete Angstadt)</li>
+ <li>Better relative path saving in Project file (Dave Brosius)
+ </li>
+ <li>Detector Priority in GUI is now saved in prefs file (Dave
+ Brosius)</li>
+ <li>Controls in GUI to reorder source and classpath entries,
+ and ability to flip between Project details and bugs pages (Dave
+ Brosius)</li>
+ <li>In Swing GUI, analysis error dialog supports "Select All"
+ and "Copy" operations for easy generation of error reports (Dave
+ Brosius)</li>
+ <li>Complete translation of bug descriptions and messages into
+ Japanese (Hanai Shisei) <!-- Bug fixes -->
+ </li>
+ <li>Fixed bug in DroppedException detector (Dave Brosius) <!-- Development stuff -->
+ </li>
+ <li>The source distribution defaults to using JDK 1.5 javac to
+ compile, but support for compiling with JSR-14 prototype is still
+ supported</li>
+ </ul>
+
+ <p>Changes since version 0.8.1:</p>
+ <ul>
+ <li>Fixed a critical ClassCastException bug (triggered if the
+ -workHard option was used, and an exception type was merged with
+ an array type during type inference)</li>
+ </ul>
+
+ <p>Changes since version 0.8.0:</p>
+ <ul>
+ <li>Disabled SwitchFallthrough detector to work around
+ NullPointerExceptions</li>
+ <li>Added some additional false positive suppression
+ heuristics</li>
+ </ul>
+
+ <p>Also, two contributors to the 0.8.0 release were
+ inadvertently left out of the credits:</p>
+ <ul>
+ <li>Pete Angstadt fixed several problems in the Swing GUI</li>
+ <li>Francis Lalonde provided a task resource file for the
+ FindBugs Ant task</li>
+ </ul>
+
+ <p>Changes since version 0.7.4:</p>
+ <ul>
+ <li>New detector to look for uses of "+" operator to
+ concatenate String objects in a loop (Dave Brosius)</li>
+ <li>Reference comparison detector looks for places where the
+ argument passed to the equals(Object) method isn't the same type
+ as the receiver object</li>
+ <li>Better suppression of false warnings in many detectors</li>
+ <li>Many improvements to Eclipse plugin (Andrey Loskutov,
+ Peter Friese)</li>
+ <li>Fixed problem with building Eclipse plugin on Windows
+ (Thomas Klaeger)</li>
+ <li>Open stream detector looks for unclosed PreparedStatement
+ objects (Thomas Klaeger, Rohan Lloyd)</li>
+ <li>Fix for open stream detector: it wasn't detecting close()
+ methods called through an invokeinterface instruction (Thomas
+ Klaeger)</li>
+ <li>Refactoring of visitor classes to enforce use of accessors
+ for visited class features (Brian Goetz)</li>
+ </ul>
+
+ <p>Changes since version 0.7.3:</p>
+ <ul>
+ <li>Experimental modification of open stream detector to look
+ for non-escaping JDBC resources (connections and statements) that
+ aren't closed on all paths out of method</li>
+ <li>Eclipse plugin fixed so it compiles and runs on Eclipse
+ 2.1.x (Peter Friese)</li>
+ <li>Option to Swing GUI and command line to generate project
+ file using relative paths for archives, source directories, and
+ aux classpath entries (Dave Brosius)</li>
+ <li>Improvements to findbugs.bat script for launching FindBugs
+ on Windows (Dave Brosius)</li>
+ <li>Updated Japanese message translations (Hiroshi Okugawa)</li>
+ <li>Uncalled private methods are now reported as low priority,
+ unless they have the same name as another method in the class
+ (which is more likely to indicate an actual bug)</li>
+ <li>Added some missing data in the bug messages XML files</li>
+ <li>Fixed some problems building from source on Windows
+ systems</li>
+ <li>Various minor bug fixes</li>
+ </ul>
+
+ <p>Changes since version 0.7.2:</p>
+ <ul>
+ <li>Enhanced Eclipse plugin, which displays the detailed bug
+ description in a view (Phil Crosby)</li>
+ <li>Various tweaks to existing detectors to reduce false
+ warnings</li>
+ <li>New command line option <code> -workHard </code> enables
+ pruning of infeasible or unlikely exception edges, which results
+ in better accuracy in the open stream detector, at the expense of
+ a 30%-100% slowdown
+ </li>
+ <li>New website and HTML documentation design</li>
+ <li>Documentation includes an HTML document with descriptions
+ of all bug patterns reported by FindBugs</li>
+ <li>Web page has a link to a <a
+ href="http://www.simeji.com/findbugs/doc/manual_ja/index.html">Japanese
+ translation</a> of the FindBugs manual, contributed by Hiroshi
+ Okugawa
+ </li>
+ <li>Changed the Inconsistent Synchronization detector so that
+ fields synchronized 50% of the time (or more) are reported as
+ medium priority bugs (previously they were reported as low)</li>
+ <li>New detector to find code that catches
+ IllegalMonitorStateException</li>
+ <li>New detector to find private methods that are never called
+ </li>
+ <li>New detector to find suspicious uses of
+ non-short-circuiting boolean operators ( <code> & </code> and
+ <code> | </code> , rather than <code> && </code> and <code>
+ || </code> )
+ </li>
+ </ul>
+
+ <p>Changes since version 0.7.1:</p>
+ <ul>
+ <li>Incorporated patched version of BCEL, which allows classes
+ compiled with JDK 1.5.0 beta to be analyzed</li>
+ <li>Fixed some bugs related to lookups of array classes</li>
+ <li>Fixed bug that prevented GUI from loading XML result files
+ when running under JDK 1.5.0 beta</li>
+ <li>Added new experimental bug detector, LazyInit, which looks
+ for potentially buggy lazy initializations of static fields</li>
+ <li>Because of long filenames, switched to distributing the
+ source archive as a zip file rather than a tar file</li>
+ <li>The 0.7.1 source tarfile was botched - 0.7.2 has a valid
+ source archive</li>
+ <li>Fixed some problems in the Ant build script</li>
+ <li>Fixed NullPointerException when checking Class-Path
+ attribute for Jar files without manifests</li>
+ <li>Generate version numbers for the core and UI Eclipse
+ plugins using the Version class; all version numbers are now in a
+ common location</li>
+ </ul>
+
+ <p>Changes since version 0.7.0:</p>
+ <ul>
+ <li>Eclipse plugin (contributed by Peter Friese)</li>
+ <li>Source package structure rearranged: all source (other
+ than Eclipse plugin UI) is in the edu.umd.cs.findbugs package, or
+ a subpackage</li>
+ <li>Class-Path attributes of manifests of analyzed jar files
+ are used to set the aux classpath automatically (Peter D. Stout)</li>
+ <li>GUI starts in directory specified by user.home property
+ (Peter D. Stout)</li>
+ <li>Added -project option to GUI (Mikko T.)</li>
+ <li>Added -look:{plastic,gtk,native} option to GUI, for
+ setting look and feel (Mikko T.)</li>
+ <li>Fixed DataflowAnalysisException in inconsistent
+ synchronization detector</li>
+ <li>Ant task supports failOnError parameter (Rohan Lloyd)</li>
+ <li>Serializable class warnings are downgraded to low priority
+ for GUI classes</li>
+ <li>MWN detector will only report calls to wait(), notify(),
+ and notifyAll() methods that have the correct signature</li>
+ <li>FindBugs works with latest CVS version of BCEL</li>
+ <li>Zip and Jar files may be added to the source path</li>
+ <li>The GUI will automatically find source files residing in
+ analyzed Zip or Jar files</li>
+ </ul>
+
+ <p>Note that the version number jumped from 0.6.6 to 0.6.9;
+ there were no 0.6.7 or 0.6.8 releases.</p>
+ <p>Changes since version 0.6.9:</p>
+ <ul>
+ <li>Added -conserveSpace option to reduce memory use at the
+ expense of analysis precision</li>
+ <li>Bug fixes in findbugs.bat script: JAVA_HOME handling,
+ autodetection of FINDBUGS_HOME, missing output with -textui</li>
+ <li>Fixed NullPointerException when a missing class is
+ encountered</li>
+ </ul>
+
+ <p>Changes since version 0.6.6:</p>
+ <ul>
+ <li>The null pointer dereference detector is more powerful</li>
+ <li>Significantly improved heuristics and bug fixes in
+ inconsistent synchronization detector</li>
+ <li>Improved heuristics in open stream and dropped exception
+ detectors; fewer false positives should be reported</li>
+ <li>Save HTML summary in XML results files, rather than
+ recomputing; this makes loading results in GUI much faster</li>
+ <li>Report at most one String comparison using == or != per
+ method</li>
+ <li>The findbugs.bat script on Windows autodetects
+ FINDBUGS_HOME, and doesn't open a DOS window when launching the
+ GUI (contributed by TJSB)</li>
+ <li>Emacs reporting format (contributed by David Li)</li>
+ <li>Various bug fixes</li>
+ </ul>
+
+ <p>Changes since 0.6.5:</p>
+ <ul>
+ <li>Rewritten inconsistent synchronization detector; accuracy
+ is significantly improved, and bug reports are prioritized</li>
+ <li>New detector to find self assignment (x=x) of local
+ variables (suggested by Jeff Martin)</li>
+ <li>New detector to find calls to wait(), notify(), and
+ notifyAll() on an object which is not obviously locked</li>
+ <li>Open stream detector now reports Readers and Writers</li>
+ <li>Fixed bug in finalizer idioms detector which caused
+ spurious warnings about failure to call super.finalize() (reported
+ by Jim Menard)</li>
+ <li>Fixed bug where output stream was not closed using non-XML
+ output (reported by Sigiswald Madou)</li>
+ <li>Fixed corrupted HTML bug detail message (reported by
+ Trevor Harmon)</li>
+ </ul>
+
+ <p>Changes since version 0.6.4:</p>
+ <ul>
+ <li>For redundant comparison of reference values, fixed false
+ positives resulting from duplication of code in finally blocks</li>
+ <li>Fixed false positives resulting from wrapped byte array
+ streams left open</li>
+ <li>Fixed bug in Ant task preventing output file from working
+ properly if a relative path was used</li>
+ </ul>
+
+ <p>Changes since version 0.6.3:</p>
+ <ul>
+ <li>Fixed bug in Ant task where output would be corrupted, and
+ added a <code> timeout </code> attribute
+ </li>
+ <li>Added -outputFile option to text UI, for explicitly
+ specifying an output file</li>
+ <li>GUI has a summary window, for statistics about overall bug
+ densities (contributed by Mike Fagan)</li>
+ <li>Find redundant comparisons of reference values</li>
+ <li>More accurate detection of Strings compared with == and !=
+ operators</li>
+ <li>Detection of other reference types which should generally
+ not be compared with == and != operators; Boolean, Integer, etc.</li>
+ <li>Find non-transient non-serializable instance fields in
+ Serializable classes</li>
+ <li>Source code may be compiled with latest early access
+ generics-enabled javac (version 2.2)</li>
+ </ul>
+
+ <p>Changes since version 0.6.2:</p>
+ <ul>
+ <li>GUI supports filtering bugs by priority</li>
+ <li>Ant task rewritten; supports all functionality offered by
+ Text UI (contributed by Mike Fagan)</li>
+ <li>Ant task is fully documented in the manual</li>
+ <li>Classes in nested archives are analyzed; this allows full
+ support for analyzing .ear and .war files (contributed by Mike
+ Fagan)</li>
+ <li>DepthFirstSearch changed to use non-recursive
+ implementation; this should fix the StackOverflowErrors that
+ several users reported</li>
+ <li>Various minor bugfixes and improvements</li>
+ </ul>
+
+ <p>Changes since version 0.6.1:</p>
+ <ul>
+ <li>New detector to look for useless control flow (suggested
+ by Richard P. King and Mike Fagan)</li>
+ <li>Look for places where return value of
+ java.io.File.createNewFile() is ignored (suggested by Richard P.
+ King)</li>
+ <li>Fixed bug in resolution of source files (only the first
+ source directory was searched)</li>
+ <li>Fixed a NullPointerException in the bytecode pattern
+ matching code</li>
+ <li>Ant task supports project files (contributed by Mike
+ Fagan)</li>
+ <li>Unix findbugs script honors the <code> JAVA_HOME </code>
+ environment variable (contributed by Pedro Morais)
+ </li>
+ <li>Allow .war and .ear files to be analyzed</li>
+ </ul>
+
+ <p>Changes since version 0.6.0:</p>
+ <ul>
+ <li>New bug pattern detector which looks for places where a
+ null pointer might be dereferenced</li>
+ <li>New bug pattern detector which looks for IO streams that
+ are opened, do not escape the method, and are not closed on all
+ paths out of the method</li>
+ <li>New bug pattern detector to find methods that can return
+ null instead of a zero-length array</li>
+ <li>New bug pattern detector to find places where the == or !=
+ operators are used to compare String objects</li>
+ <li>Command line interface can save bugs as XML</li>
+ <li>GUI can save bugs to and load bugs from XML</li>
+ <li>An "Annotations" window in the GUI allows the user to add
+ textual annotations to bug reports; these annotations are
+ preserved when bugs are saved as XML</li>
+ <li>In this release, the Japanese bug summary translations by
+ Germano Leichsenring are really included (they were inadvertently
+ omitted in the previous release)</li>
+ <li>Completely rewrote the control flow graph builder,
+ hopefully for the last time</li>
+ <li>Simplified implementation of control flow graphs, which
+ should reduce memory use and possibly improve performance</li>
+ <li>Improvements to command line interface (list bug
+ priorities, filter by priority, specify aux classpath, specify
+ project to analyze)</li>
+ <li>Various bug fixes and enhancements</li>
+ </ul>
+
+ <p>Changes since version 0.5.4</p>
+ <ul>
+ <li>Added an <a href="http://ant.apache.org/">Ant</a> task for
+ FindBugs, contributed by Mike Fagan.
+ </li>
+ <li>Added a GUI dialog which allows individual bug pattern
+ detectors to be enabled or disabled. Disabling certain slow
+ detectors can greatly speed up analysis of large programs, at the
+ expense of reducing the number of potential bugs found.</li>
+ <li>Added a new detector for finding improperly ignored return
+ values for methods such as <code> String.trim() </code> .
+ Suggested by Andreas Mandel.
+ </li>
+ <li>Japanese translations of the bug summaries, contributed by
+ Germano Leichsenring.</li>
+ <li>Filtering of results is supported in command line
+ interface. See the <a href="manual/index.html">FindBugs manual</a>
+ for details.
+ </li>
+ <li>Added "byte code patterns", a general pattern matching
+ infrastructure for bytecode instructions. This feature
+ significantly reduces the complexity of implementing new bug
+ pattern detectors.</li>
+ <li>Enabled a new general dataflow analysis to track values in
+ methods.</li>
+ <li>Switched to new control-flow graph builder implementation.
+ </li>
+ </ul>
+
+ <p>Changes since version 0.5.3</p>
+ <ul>
+ <li>Fixed a bug in the script used to launch FindBugs on
+ Windows platforms.</li>
+ <li>Fixed crashes when analyzing class files without source
+ line information.</li>
+ <li>All major errors are reported using an error dialog; file
+ not found errors are more informative.</li>
+ <li>Minor GUI improvements.</li>
+ </ul>
+
+ <p>Changes since version 0.5.2</p>
+ <ul>
+ <li>All of the source code and related files are in a single
+ directory tree.</li>
+ <li>Updated some of the detectors to produce source line
+ information.</li>
+ <li><a href="http://ant.apache.org/">Ant</a> build script and
+ several GUI enhancements and fixes contributed by Mike Fagan.</li>
+ <li>Converted to use a <a href="AddingDetectors.txt">plugin
+ architecture</a> for loading bug detectors.
+ </li>
+ <li>Eliminated generics-related compiler warnings.</li>
+ <li>More complete documentation has been added.</li>
+ </ul>
+
+ <p>Changes since version 0.5.1:</p>
+ <ul>
+ <li>Fixed a large number of bugs in the BCEL Repository and
+ FindBugs's use of the Repository. With these changes,
+ FindBugs should <em>never</em> crash or otherwise misbehave
+ because of Repository lookup failures. Because of these
+ changes, you must use a modified version of <code> bcel.jar
+ </code> with FindBugs. This jar file is included in the FindBugs
+ 0.5.2 binary release. A complete patch containing the <a
+ href="http://faculty.ycp.edu/~dhovemey/bcel-30-April-2003.patch">modifications
+ against the BCEL CVS main branch as of April 30, 2003</a> is also
+ available.
+ </li>
+ <li>Implemented the "auxiliary classpath entry list".
+ Aux classpath entries can be added to a project to provide classes
+ that are referenced by the analyzed application, but should not
+ themselves be analyzed. Having all referenced classes
+ available allows FindBugs to produce more accurate results.</li>
+ </ul>
+
+ <p>Changes since version 0.5.0:</p>
+ <ul>
+ <li>Many user interface bugs have been fixed.</li>
+ <li>Upgraded to a recent CVS version of BCEL, with some bug
+ fixes. This should prevent FindBugs from crashing when there
+ is a failure to find a class on the classpath.</li>
+ <li>Added support for Plastic look and feel from <a
+ href="http://www.jgoodies.com/">jgoodies.com</a>.
+ </li>
+ <li>Major overhaul of infrastructure for doing dataflow
+ analysis.</li>
+ </ul> @HTML_FOOTER@
+
+ </td>
+
+ </tr>
+ </table>
</body>
diff --git a/src/doc/FAQ.html b/src/doc/FAQ.html
index 0778a1f..eabcd05 100644
--- a/src/doc/FAQ.html
+++ b/src/doc/FAQ.html
@@ -35,13 +35,13 @@ information about FindBugs, have a look at the
<h2><a name="q1">Q1: I'm getting java.lang.UnsupportedClassVersionError when I try to run FindBugs</a></h2>
-<p> FindBugs requires JRE 1.5.0 or later to run. If you use an earlier version,
+<p> FindBugs requires JRE 1.7.0 or later to run. If you use an earlier version,
you will see an exception error message similar to the following:
<pre>
Exception in thread "main" java.lang.UnsupportedClassVersionError:
-edu/umd/cs/findbugs/gui/FindBugsFrame (Unsupported major.minor version 48.0)
+edu/umd/cs/findbugs/gui/FindBugsFrame (Unsupported major.minor version 51.0)
</pre>
-The solution is to upgrade to JRE 1.5.0 or later.
+The solution is to upgrade to JRE 1.7.0 or later.
<h2><a name="q2">Q2: When I click the "Find Bugs!" button, I get a NoSuchMethodError or VerifyError</a></h2>
@@ -101,8 +101,8 @@ for providing information on this problem.
<h2><a name="q3">Q3: FindBugs is running out of memory, or is taking a long time to finish</a></h2>
<p> In general, FindBugs requires lots of memory and a relatively
-fast CPU. For large applications, 512M or more of heap space may be
-required. By default, FindBugs allocates 256M of heap space.
+fast CPU. For large applications, 1024M or more of heap space may be
+required. By default, FindBugs allocates 768M of heap space.
You can increase this using the <code>-maxHeap <i>n</i></code> option,
where <i>n</i> is the number of megabytes of heap space to allocate.
diff --git a/src/doc/contributing.html b/src/doc/contributing.html
index 7e5cc8d..0531869 100644
--- a/src/doc/contributing.html
+++ b/src/doc/contributing.html
@@ -19,45 +19,47 @@ we would be happy to consider it for inclusion.</p>
<h2>Import FindBugs code as Eclipse projects</h2>
-<p>The preferred way to get the FindBugs source code and create the patch is to use Eclipse + SVN.
+<p>The preferred way to get the FindBugs source code and create the patch is to use Eclipse + Git.
You can easily import FindBugs code into Eclipse by following the steps described
-here: <a href="http://code.google.com/p/findbugs/source/browse/trunk/eclipsePlugin/doc/building_findbugsplugin.txt">Import Eclipse projects</a>
-.
+here: <a href="https://code.google.com/p/findbugs/source/browse/eclipsePlugin/doc/building_findbugsplugin.txt">Import Eclipse projects</a>
+.
</p>
<h2>Preparing a patch</h2>
-<p> The best way to
-send an enhancement is to create a patch against the latest code
-in the FindBugs Subversion repository
-at <a href="http://findbugs.googlecode.com/svn/trunk/">http://findbugs.googlecode.com/svn/trunk/</a>
-(those people who have been given commit priviledges should use
-<a href="https://findbugs.googlecode.com/svn/trunk/">http<b>s</b>://findbugs.googlecode.com/svn/trunk/</a>).
-</p>
-
-<p>To create a patch from Eclipse, please right click the [findbugs] or [findBugsEclipsePlugin] project
-and choose [Team | Create Patch...] context menu.
+<p> The best way to create a patch is to clone FindBugs Git repository here:
+ <a href="http://code.google.com/p/findbugs/source/clones">http://code.google.com/p/findbugs/source/clones</a>,
+ commit changes with descriptive commit messages (small commits are better) and
+ create a new <a href="https://sourceforge.net/p/findbugs/bugs/">bug</a>
+ or <a href="https://sourceforge.net/p/findbugs/feature-requests/">feature request</a>
+ with the "[patch]" prefix in the title and link to your repository in the description.
</p>
<p> Please follow these guidelines when preparing your patch:</p>
<ul>
<li> <b>Use the same indentation style as the source file(s) you
- are modifying</b>. In particular, please use tabs (not spaces)
- to indent your code; one tab per indent level.
+ are modifying</b>. In particular, please use spaces
+ to indent your code; four spaces per indent level.
<li> If at all possible, avoid making whitespace modifications.
-<li> Small patches are appreciated.
+<li> Small patches/changesets are appreciated.
+<li> If you have lot of changes, try to group them by small commits with descriptive messages.
+<li> If you have multiple patches, create <b>branch per patch</b>.
+<li> All new files should contain proper license header (<a href="http://www.gnu.org/licenses/lgpl.html">Lesser GNU Public License</a>).
<li> If you are submitting a new bug detector, please submit a small
standalone source file that contains an instance of the
- kind of bug the detector looks for.
+ kind of bug the detector looks for. The file should be placed at
+ <a href="https://code.google.com/p/findbugs/source/browse/#git%2FfindbugsTestCases%2Fsrc%2Fjava%2FsfBugsNew">findbugsTestCases/src/java/sfBugsNew</a>
+ package and named after the bug or feature you are addressing.
</ul>
<p> Following these guidelines makes it much easier for us
to incorporate new code.
-<h2>How to submit a patch</h2>
+<h2>Where to submit a patch</h2>
<p> Patches may be submitted through the
-<a href="http://sourceforge.net/tracker/?atid=614695&group_id=96405&func=browse">Patches</a> tracker on the
+<a href="https://sourceforge.net/p/findbugs/bugs/">bug</a>
+ or <a href="https://sourceforge.net/p/findbugs/feature-requests/">feature request</a> trackers on the
<a href="http://sourceforge.net/projects/findbugs/">sourceforge project page</a>.
@HTML_FOOTER@
diff --git a/src/doc/downloads.html b/src/doc/downloads.html
index e8e4118..33f3b3c 100644
--- a/src/doc/downloads.html
+++ b/src/doc/downloads.html
@@ -43,9 +43,8 @@ on the sourceforge download page</a>.
</li>
<li>Eclipse plugin for FindBugs version @ECLIPSE_UI_VERSION@ (requires Eclipse 3.6 or later)
<ul>
-<li><a href="http://sourceforge.net/projects/findbugs/files/findbugs%20eclipse%20plugin/@VERSION_BASE@/edu.umd.cs.findbugs.plugin.eclipse_@ECLIPSE_UI_VERSION@-@FINDBUGS_SVN_REVISION@.zip/download">edu.umd.cs.findbugs.plugin.eclipse_ at ECLIPSE_UI_VERSION@- at FINDBUGS_SVN_REVISION@.zip</a>
-<li><a href="http://sourceforge.net/projects/findbugs/files/findbugs%20eclipse%20plugin/@VERSION_BASE@/eclipsePlugin-@ECLIPSE_UI_VERSION@-@FINDBUGS_SVN_REVISION@-source.zip/download">
-eclipsePlugin- at ECLIPSE_UI_VERSION@- at FINDBUGS_SVN_REVISION@-source.zip/download</a>
+<li><a href="http://sourceforge.net/projects/findbugs/files/findbugs%20eclipse%20plugin/@VERSION_BASE@/edu.umd.cs.findbugs.plugin.eclipse_@ECLIPSE_UI_VERSION@-@FINDBUGS_GIT_REVISION@.zip/download">edu.umd.cs.findbugs.plugin.eclipse_ at ECLIPSE_UI_VERSION@- at FINDBUGS_GIT_REVISION@.zip</a>
+<li><a href="http://sourceforge.net/projects/findbugs/files/findbugs%20eclipse%20plugin/@VERSION_BASE@/edu.umd.cs.findbugs.plugin.eclipse_@ECLIPSE_UI_VERSION@-@FINDBUGS_GIT_REVISION@-source.zip/download">edu.umd.cs.findbugs.plugin.eclipse_ at ECLIPSE_UI_VERSION@- at FINDBUGS_GIT_REVISION@-source.zip</a>
</ul>
</li>
</ul>
diff --git a/src/doc/index.html b/src/doc/index.html
index ce866f4..fe6d9d5 100644
--- a/src/doc/index.html
+++ b/src/doc/index.html
@@ -38,32 +38,147 @@
<p>The current version of FindBugs is @VERSION at .</p>
<p>
- FindBugs requires JRE (or JDK) 1.5.0 or later to run. However, it can analyze programs
- compiled for any version of Java, from 1.0 to 1.7. Some classfiles compiled for Java 1.8 give
- FindBugs problems, the next major release of FindBugs will handle Java 1.8 classfiles.
-
+ FindBugs requires JRE (or JDK) 1.7.0 or later to run. However, it can analyze programs
+ compiled for any version of Java, from 1.0 to 1.8.
+
<p> The current version of FindBugs is @VERSION@,
released on @RELEASE_DATE at . <a href="reportingBugs.html">We are very interested in getting
feedback on how to improve FindBugs</a>. File bug reports on <a
- href="http://sourceforge.net/tracker/?func=browse&group_id=96405&atid=614693"> our
+ href="http://sourceforge.net/p/findbugs/_list/tickets?source=navbar"> our
sourceforge bug tracker</a>
</p>
- <p>The current version of FindBugs may encounter errors when analyzing
- Java 1.8 bytecode, due to changes in the classfile format. After FindBugs 2.0.3
- is released, work will start on the next major release of FindBugs, which will
- be able to analyze Java 1.8 (and will require Java 1.7 to compile and run).
-
+
<p>
<a href="#changes">Changes</a> | <a href="#talks">Talks</a> | <a href="#papers">Papers </a> | <a
href="#sponsors">Sponsors</a> | <a href="#support">Support</a>
</p>
+ <h1>FindBugs 3.0.1 Release</h1>
+ <ul>
+ <li>A number of changes described in the <a href="Changes.html">changes document</a>, including new bug patterns:
+<ul>
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#BSHIFT_WRONG_ADD_PRIORITY">BSHIFT_WRONG_ADD_PRIORITY</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#CO_COMPARETO_INCORRECT_FLOATING">CO_COMPARETO_INCORRECT_FLOATING</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DC_PARTIALLY_CONSTRUCTED">DC_PARTIALLY_CONSTRUCTED</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DM_BOXED_PRIMITIVE_FOR_COMPARE">DM_BOXED_PRIMITIVE_FOR_COMPARE</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#DM_INVALID_MIN_MAX">DM_INVALID_MIN_MAX</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#ME_MUTABLE_ENUM_FIELD">ME_MUTABLE_ENUM_FIELD</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#ME_ENUM_FIELD_SETTER">ME_ENUM_FIELD_SETTER</a>,
+<li>
+
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#MS_MUTABLE_COLLECTION">MS_MUTABLE_COLLECTION</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#MS_MUTABLE_COLLECTION_PKGPROTECT">MS_MUTABLE_COLLECTION_PKGPROTECT</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RANGE_ARRAY_INDEX">RANGE_ARRAY_INDEX</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RANGE_ARRAY_OFFSET">RANGE_ARRAY_OFFSET</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RANGE_ARRAY_LENGTH">RANGE_ARRAY_LENGTH</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RANGE_STRING_INDEX">RANGE_STRING_INDEX</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT">RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UC_USELESS_CONDITION">UC_USELESS_CONDITION</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UC_USELESS_CONDITION_TYPE">UC_USELESS_CONDITION_TYPE</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UC_USELESS_OBJECT">UC_USELESS_OBJECT</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UC_USELESS_OBJECT_STACK">UC_USELESS_OBJECT_STACK</a>,
+<li>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#UC_USELESS_VOID_METHOD">UC_USELESS_VOID_METHOD</a>
+</ul>
+ </li>
+ </ul>
+ <h1>FindBugs 3.0.0 Release</h1>
+
+ <ul>
+ <li>FindBugs supports Java 8 now (both as runtime and target platform).
+ <li>FindBugs requires minimum Java 7 as runtime environment!
+ <li>FindBugs uses ASM 5 now which means that some 3rd party detectors based on FindBugs 2.x/ASM 3 has to be upgraded.
+ See details in <a href="http://download.forge.objectweb.org/asm/asm4-guide.pdf#chapter.5">ASM documentation</a>.
+ <li>New Bug patterns:
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#NP_OPTIONAL_RETURN_NULL">NP_OPTIONAL_RETURN_NULL</a>,
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IIO_INEFFICIENT_INDEX_OF">IIO_INEFFICIENT_INDEX_OF</a>,
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#IIO_INEFFICIENT_LAST_INDEX_OF">IIO_INEFFICIENT_LAST_INDEX_OF</a>
+ <a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#CNT_ROUGH_CONSTANT_VALUE">CNT_ROUGH_CONSTANT_VALUE</a>
+ </li>
+ <li>New "Source" filter which can be used to filter out classes generated from other languages:
+ <pre>
+ <?xml version="1.0" encoding="UTF-8"?>
+ <FindBugsFilter>
+ <Match>
+ <Source name="~.*\.groovy" />
+ </Match>
+ </FindBugsFilter>
+ </pre>
+ </li>
+ <li>New "-auxclasspathFromFile" and "-analyzeFromFile" command line options.
+ </li>
+ <li>New "nested" ant task attribute.
+ </li>
+
+
+ <!--
+ <li>Fixed false positives for the following bug patterns (XXX occurrences in findbugsTestCases):
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#XXX">XXX</a>
+ </ul>
+ </li>
+
+ <li>Fixed false negatives for the following bug patterns (XXX occurrences in findbugsTestCases):
+ <ul>
+ <li><a
+ href="http://findbugs.sourceforge.net/bugDescriptions.html#XXX">XXX</a>
+ </ul>
+ </li>
+ -->
+
+ <li>Various bug fixes, also many patches from community. Thanks for your contributions!
+ </li>
+ </ul>
+
+
+
<h1>FindBugs 2.0.3 Release</h1>
<p>FindBugs 2.0.3 is intended to be a minor bug fix release over
FindBugs 2.0.2. Although than some improvements to existing bug detectors
- and analysis engines, and a few new bug patterns, and some
+ and analysis engines, and a few new bug patterns, and some
important bug fixes to the Eclipse plugin, no significant changes
should be observed. Consult the <a href="Changes.html">Change log</a>
for more details.</p>
@@ -117,7 +232,7 @@
</dd>
<dt><a href="https://wiki.jenkins-ci.org/display/JENKINS">Jenkins</a></dt>
<dd> <a href="https://wiki.jenkins-ci.org/display/JENKINS/FindBugs+Plugin">Jenkins FindBugs Plugin</a>
-
+
<dt>
<a href="http://wiki.hudson-ci.org/display/HUDSON/Home">Hudson</a>
</dt>
@@ -134,38 +249,6 @@
</dd>
</dl>
-
- <h1>New</h1>
- <ul>
-
- <li>jFormatString library republished at
- <a href="http://code.google.com/p/j-format-string">http://code.google.com/p/j-format-string</a>.
- This is the library we use for compile time checking of format strings. It is separately published to
-
- <li>We're releasing FindBugs 2.0.3.
-
- Mostly small changes to address false positives, with one important fix to the Eclipse plugin
- to fix a problem that had prevented the plugin from running in some versions of Eclipse.
- Check the <a href="Changes.html">change log</a> for more details.
-
- <li>We've released <a href="findbugs2.html">FindBugs 2.0</a>
- </li>
- <li>FindBugs communal cloud and Java web start links:. We have analyzed several large open
- source projects, and provide Java web start links to allow you to view the results. We'd be
- happy to work with projects to make the results available from a continuous build:
- <p></p>
- <ul>
- <li><a href="http://findbugs.cs.umd.edu/cloud/jdk.jnlp">Sun's JDK 8</a></li>
- <li><a href="http://findbugs.cs.umd.edu/cloud/eclipse.jnlp">Eclipse 3.8</a></li>
- <li><a href="http://findbugs.cs.umd.edu/cloud/tomcat.jnlp">Apache Tomcat 7.0</a></li>
- <li><a href="http://findbugs.cs.umd.edu/cloud/intellij.jnlp">IntelliJ IDEA</a></li>
- <li><a href="http://findbugs.cs.umd.edu/cloud/jboss.jnlp">JBoss</a></li>
- </ul>
- </li>
- </ul>
-
-
-
<h1>Experience with FindBugs</h1>
<ul>
<li><b>Google FindBugs Fixit</b>: Google has a tradition of <a
diff --git a/src/doc/links.html b/src/doc/links.html
index 5d596e7..2ed5357 100644
--- a/src/doc/links.html
+++ b/src/doc/links.html
@@ -22,7 +22,10 @@ including tools that are similar to FindBugs.
<ul>
<li> <a href="http://fb-contrib.sourceforge.net/">fb-contrib</a>: additional bug detectors for use with
FindBugs. The lead FindBugs team does not vouch for the relevance, accuracy or wisdom of the warnings
- generated by any third-party plugin.
+ generated by any third-party plugin.
+<li> <a href="http://h3xstream.github.io/find-sec-bugs/">Find Security Bugs</a>: additional bug detectors for use with
+ FindBugs. The lead FindBugs team does not vouch for the relevance, accuracy or wisdom of the warnings
+ generated by any third-party plugin.
<li> <a href="http://www.tobject.de/development/findbugs.html">FindBugs Eclipse plugin</a>.
This is now included as part of FindBugs.
<!--<li> <a href="http://maven-plugins.sourceforge.net/maven-findbugs-plugin/index.html">Maven FindBugs plugin</a>. -->
diff --git a/src/doc/manual.xml b/src/doc/manual.xml
index 2b2e924..647d85a 100644
--- a/src/doc/manual.xml
+++ b/src/doc/manual.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "file:../etc/docbook/docbookx.dtd" [
+ "../../etc/docbook/docbookx.dtd" [
<!ENTITY FindBugs "<application>FindBugs</application>">
<!ENTITY Ant "<application>Ant</application>">
<!ENTITY Saxon "<application>Saxon</application>">
@@ -939,6 +939,36 @@ These options are only accepted by the Text User Interface.
</varlistentry>
<varlistentry>
+ <term><command>-auxclasspathFromInput</command> </term>
+ <listitem>
+ <para>
+ Read the auxiliary classpath for analysis from standard input, each line adds new
+ entry to the auxiliary classpath for analysis.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>-auxclasspathFromFile</command> <replaceable>filepath</replaceable></term>
+ <listitem>
+ <para>
+ Read the auxiliary classpath for analysis from file, each line adds new
+ entry to the auxiliary classpath for analysis.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>-analyzeFromFile</command> <replaceable>filepath</replaceable></term>
+ <listitem>
+ <para>
+ Read the files to analyze from file, each line adds new
+ entry to the classpath for analysis.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><command>-userPrefs</command> <replaceable>edu.umd.cs.findbugs.core.prefs</replaceable></term>
<listitem>
<para>
@@ -1416,13 +1446,24 @@ using the &FindBugs; task.
<term><literal>omitVisitors</literal></term>
<listitem>
<para>
- Optional attribute. It is like the <literal>visitors</literal> attribute,
+ Optional attribute. It specifies a comma-separated list of bug detectors.
+ It is like the <literal>visitors</literal> attribute,
except it specifies detectors which will <emphasis>not</emphasis> be run.
</para>
</listitem>
</varlistentry>
<varlistentry>
+ <term><literal>chooseVisitors</literal></term>
+ <listitem>
+ <para>
+ Optional attribute. It specifies a comma-separated list of bug detectors
+ prefixed with "+" or "-" to selectively enable/disable them.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>excludeFilter</literal></term>
<listitem>
<para>
@@ -1539,6 +1580,27 @@ using the &FindBugs; task.
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>nested</literal></term>
+ <listitem>
+ <para>
+ Optional attribute which enables or disables scanning of nested jar and zip files found in
+ the list of files and directories to be analyzed.
+ By default, scanning of nested jar/zip files is enabled.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>setExitCode</literal></term>
+ <listitem>
+ <para>
+ Optional boolean attribute. Whether the exit code will be returned to
+ the main ant job. Defaults to "true".
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
@@ -1565,7 +1627,7 @@ using the &FindBugs; task.
The FindBugs Eclipse plugin allows &FindBugs; to be used within
the <ulink url="http://www.eclipse.org/">Eclipse</ulink> IDE.
The FindBugs Eclipse plugin was generously contributed by Peter Friese.
-Phil Crosby and Andrei Loskutov contributed major improvements
+Phil Crosby and Andrey Loskutov contributed major improvements
to the plugin.
</para>
@@ -1694,7 +1756,7 @@ Options you may choose include:
<title>Extending the Eclipse Plugin (since 2.0.0)</title>
<para>
Eclipse plugin supports contribution of custom &FindBugs; detectors (see also
-<ulink url="http://code.google.com/p/findbugs/source/browse/trunk/findbugs/src/doc/AddingDetectors.txt">AddingDetectors.txt</ulink>
+<ulink url="http://code.google.com/p/findbugs/source/browse/findbugs/src/doc/AddingDetectors.txt">AddingDetectors.txt</ulink>
for more information). There are two ways to contribute custom plugins to the Eclipse:
</para>
<itemizedlist>
@@ -1705,7 +1767,7 @@ for more information). There are two ways to contribute custom plugins to the Ec
<guimenu>Window</guimenu>
<guimenuitem>Preferences</guimenuitem>
<guimenuitem>Java</guimenuitem>
- <guimenuitem>&FindBugs;</guimenuitem>
+ <guimenuitem>FindBugs</guimenuitem>
<guimenuitem>Misc. Settings</guimenuitem>
<guimenuitem>Custom Detectors</guimenuitem>
</menuchoice>.
@@ -1727,7 +1789,7 @@ for more information). There are two ways to contribute custom plugins to the Ec
<para>
Please check the documentation of the
- <ulink url="http://code.google.com/p/findbugs/source/browse/trunk/eclipsePlugin/schema/detectorPlugins.exsd">
+ <ulink url="http://code.google.com/p/findbugs/source/browse/eclipsePlugin/schema/detectorPlugins.exsd">
findBugsEclipsePlugin/schema/detectorPlugins.exsd</ulink>
extension point how to update the plugin.xml. Existing &FindBugs; detector plugins can
be easily "extended" to be full featured &FindBugs; AND Eclipse detector plugins.
@@ -1743,7 +1805,7 @@ for more information). There are two ways to contribute custom plugins to the Ec
Eclipse plugin. You can do this even for third-party detector packages.
Another major differentiator is the ability to extend the default FindBugs
classpath at runtime with required third party libraries (see
- <ulink url="http://code.google.com/p/findbugs/source/browse/trunk/findbugs/src/doc/AddingDetectors.txt">AddingDetectors.txt</ulink>
+ <ulink url="http://code.google.com/p/findbugs/source/browse/findbugs/src/doc/AddingDetectors.txt">AddingDetectors.txt</ulink>
for more information).
</para>
</listitem>
@@ -1802,14 +1864,6 @@ This section lists common problems with the plugin and (if known) how to resolve
<para>
Filter files may be used to include or exclude bug reports for particular classes
and methods. This chapter explains how to use filter files.
-
-<note>
-<title>Planned Features</title>
-<para>
- Filters are currently only supported by the Command Line interface.
- Eventually, filter support will be added to the GUI.
-</para>
-</note>
</para>
@@ -1932,7 +1986,7 @@ In other words, each of the children must be true for the predicate to be true.
<para>
This element matches warnings associated with a particular class. The
<literal>name</literal> attribute is used to specify the exact or regex match pattern
- for the class name.
+ for the class name. The <literal>role</literal> attribute is the class role.
</para>
<para>
@@ -1952,13 +2006,25 @@ In other words, each of the children must be true for the predicate to be true.
</varlistentry>
<varlistentry>
+ <term><literal><Source></literal></term>
+ <listitem>
+ <para>
+ This element matches warnings associated with a particular source file. The
+ <literal>name</literal> attribute is used to specify the exact or regex match pattern
+ for the source file name.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal><Method></literal></term>
<listitem><para>This element specifies a method. The <literal>name</literal> is used to specify
the exact or regex match pattern for the method name.
The <literal>params</literal> attribute is a comma-separated list
of the types of the method's parameters. The <literal>returns</literal> attribute is
- the method's return type. In <literal>params</literal> and <literal>returns</literal>, class names
+ the method's return type. The <literal>role</literal> attribute is
+ the method role. In <literal>params</literal> and <literal>returns</literal>, class names
must be fully qualified. (E.g., "java.lang.String" instead of just
"String".) If one of the latter attributes is specified the other is required for creating a method signature.
Note that you can provide either <literal>name</literal> attribute or <literal>params</literal>
@@ -1973,7 +2039,8 @@ In other words, each of the children must be true for the predicate to be true.
<listitem><para>This element specifies a field. The <literal>name</literal> attribute is is used to specify
the exact or regex match pattern for the field name. You can also filter fields according to their signature -
use <literal>type</literal> attribute to specify fully qualified type of the field. You can specify eiter or both
- of these attributes in order to perform name / signature based matches.
+ of these attributes in order to perform name / signature based matches. The <literal>role</literal> attribute is
+ the field role.
</para></listitem>
</varlistentry>
@@ -1996,8 +2063,8 @@ In other words, each of the children must be true for the predicate to be true.
<term><literal><And></literal></term>
<listitem><para>
This element combines <literal>Match</literal> clauses which both must evaluate to true. I.e., you can put
- <literal>Bug</literal> and <literal>Priority</literal> elements in an <literal>And</literal> clause in order
- to match specific bugs with given priority only.
+ <literal>Bug</literal> and <literal>Confidence</literal> elements in an <literal>And</literal> clause in order
+ to match specific bugs with given confidence only.
</para></listitem>
</varlistentry>
<varlistentry>
@@ -2016,8 +2083,9 @@ In other words, each of the children must be true for the predicate to be true.
<title>Java element name matching</title>
<para>
-If the <literal>name</literal> attribute of <literal>Class</literal>, <literal>Method</literal> or
-<literal>Field</literal> starts with the ~ character the rest of attribute content is interpreted as
+If the <literal>name</literal> attribute of <literal>Class</literal>, <literal>Source</literal>,
+<literal>Method</literal> or <literal>Field</literal> starts with the ~ character
+the rest of attribute content is interpreted as
a Java regular expression that is matched against the names of the Java element in question.
</para>
@@ -2259,6 +2327,21 @@ as expected.
</programlisting>
</para>
+<para>
+ 12. Full exclusion filter file to match all classes generated from Groovy source files.
+
+<programlisting>
+<![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<FindBugsFilter>
+<Match>
+ <Source name="~.*\.groovy" />
+</Match>
+</FindBugsFilter>
+]]>
+</programlisting>
+</para>
+
</sect1>
<sect1>
@@ -2461,7 +2544,9 @@ files in the classpath while compiling your program.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.CheckForNull</command></term>
<listitem>
-<command>[Target]</command> Field, Method, Parameter
+ <para>
+ <command>[Target]</command> Field, Method, Parameter
+ </para>
</listitem>
<listitem>
<para>
@@ -2474,7 +2559,9 @@ When this annotation is applied to a method it applies to the method return valu
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.CheckReturnValue</command></term>
<listitem>
+ <para>
<command>[Target]</command> Method, Constructor
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -2503,7 +2590,9 @@ This annotation is used to denote a method whose return value should always be c
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.DefaultAnnotation</command></term>
<listitem>
- <command>[Target]</command> Type, Package
+ <para>
+ <command>[Target]</command> Type, Package
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -2536,7 +2625,9 @@ on those parameters, methods or fields that you want to allow to be null.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields</command></term>
<listitem>
+ <para>
<command>[Target]</command> Type, Package
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -2565,7 +2656,9 @@ This is same as the DefaultAnnotation except it only applys to fields.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.DefaultAnnotationForMethods</command></term>
<listitem>
+ <para>
<command>[Target]</command> Type, Package
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -2594,7 +2687,9 @@ This is same as the DefaultAnnotation except it only applys to methods.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters</command></term>
<listitem>
+ <para>
<command>[Target]</command> Type, Package
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -2623,7 +2718,9 @@ This is same as the DefaultAnnotation except it only applys to method parameters
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.NonNull</command></term>
<listitem>
+ <para>
<command>[Target]</command> Field, Method, Parameter
+ </para>
</listitem>
<listitem>
<para>
@@ -2636,7 +2733,9 @@ Annotated fields must not be null after construction has completed. Annotated me
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.Nullable</command></term>
<listitem>
+ <para>
<command>[Target]</command> Field, Method, Parameter
+ </para>
</listitem>
<listitem>
<para>
@@ -2646,7 +2745,7 @@ acceptable and whether it is neccessary to check for a null value. FindBugs wil
treat the annotated items as though they had no annotation.
</para>
<para>
-In pratice this annotation is useful only for overriding an overarching NonNull
+In practice this annotation is useful only for overriding an overarching NonNull
annotation.
</para>
</listitem>
@@ -2655,7 +2754,9 @@ annotation.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.OverrideMustInvoke</command></term>
<listitem>
+ <para>
<command>[Target]</command> Method
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -2693,7 +2794,9 @@ This annotation is deprecated. Use CheckForNull instead.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.SuppressWarnings</command></term>
<listitem>
+ <para>
<command>[Target]</command> Type, Field, Method, Parameter, Constructor, Package
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -2728,7 +2831,9 @@ are encouraged to cooperate to ensure that the same names work across multiple c
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.UnknownNullness</command></term>
<listitem>
+ <para>
<command>[Target]</command> Field, Method, Parameter
+ </para>
</listitem>
<listitem>
<para>
@@ -2740,7 +2845,9 @@ Used to indicate that the nullness of the target is unknown, or my vary in unkno
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.UnknownNullness</command></term>
<listitem>
+ <para>
<command>[Target]</command> Field, Method, Parameter
+ </para>
</listitem>
<listitem>
<para>
@@ -2753,10 +2860,10 @@ Used to indicate that the nullness of the target is unknown, or my vary in unkno
<para>
&FindBugs; also supports the following annotations:
<itemizedlist>
- <listitem>net.jcip.annotations.GuardedBy</listitem>
- <listitem>net.jcip.annotations.Immutable</listitem>
- <listitem>net.jcip.annotations.NotThreadSafe</listitem>
- <listitem>net.jcip.annotations.ThreadSafe</listitem>
+ <listitem><para>net.jcip.annotations.GuardedBy</para></listitem>
+ <listitem><para>net.jcip.annotations.Immutable</para></listitem>
+ <listitem><para>net.jcip.annotations.NotThreadSafe</para></listitem>
+ <listitem><para>net.jcip.annotations.ThreadSafe</para></listitem>
</itemizedlist>
</para>
<para>
@@ -3766,8 +3873,8 @@ contributed the string concatenation detector.</para>
<para>Thomas Klaeger contributed a number of bug fixes and
bug detector improvements.</para>
-<para>Andrei Loskutov made a number of improvements to the
-Eclipse plugin.</para>
+<para>Andrey Loskutov made a number of bug fixes and
+bug detector improvements. He is maintainer of the Eclipse plugin.</para>
<para>Brian Goetz contributed a major refactoring of the
visitor classes to improve readability and understandability.</para>
@@ -3852,6 +3959,10 @@ and fixed a bug related to renaming the Eclipse plugin ID.</para>
<para>Dieter von Holten (dvholten) contributed
some German improvements to findbugs_de.properties.</para>
+<para>Kevin Lubick contributed fixes and tests for multi-quick-fixes and customizable
+annotation colors for Eclipse plugin.</para>
+
+<para>Tagir Valeev contributed several new bug detectors and improved existing ones.</para>
<para>If you have contributed to &FindBugs;, but aren't mentioned above,
please send email to <email>findbugs at cs.umd.edu</email> (and also accept
diff --git a/src/doc/manual_ja.xml b/src/doc/manual_ja.xml
index 921a112..9c17484 100644
--- a/src/doc/manual_ja.xml
+++ b/src/doc/manual_ja.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://findbugs.googlecode.com/svn/trunk/findbugs/etc/docbook/docbookx.dtd"
-[
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "../../etc/docbook/docbookx.dtd" [
<!ENTITY FindBugs "<application>FindBugs</application>">
<!ENTITY Ant "<application>Ant</application>">
<!ENTITY Saxon "<application>Saxon</application>">
@@ -13,7 +13,7 @@
<bookinfo>
<title>&FindBugs;™ マニュアル</title>
-<authorgroup>
+<authorgroup lang="en">
<author>
<firstname>David</firstname>
<othername>H.</othername>
@@ -26,12 +26,8 @@
</author>
</authorgroup>
-<copyright>
- <year>2003</year>
- <year>2004</year>
- <year>2005</year>
- <year>2006</year>
- <year>2008</year>
+<copyright lang="en">
+ <year>2003 - 2012</year>
<holder>University of Maryland</holder>
</copyright>
@@ -42,7 +38,7 @@
<edition>@VERSION@</edition>
-<pubdate>@RELEASE_DATE@</pubdate>
+<pubdate>@RELEASE_DATE@ (翻訳 2014年7月)</pubdate>
</bookinfo>
@@ -120,7 +116,7 @@
</listitem>
<listitem>
<para>
- <ulink url="http://java.sun.com/j2se/">JDK 1.5.0 ベータ またはそれ以降</ulink>
+ <ulink url="http://java.sun.com/j2se/">JDK 1.5.0 またはそれ以降</ulink>
</para>
</listitem>
<listitem>
@@ -636,6 +632,37 @@ The second invokes the Command Line Interface (Text UI):
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><command>-auxclasspathFromInput</command> </term>
+ <listitem>
+ <para>分析時に使用する補助クラスパスを標準入力から読み込みます。標準入力の各行が分析時に使用する補助クラスパスに追加されます。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>-auxclasspathFromFile</command> <replaceable>ファイルパス</replaceable></term>
+ <listitem>
+ <para>分析時に使用する補助クラスパスをファイルから読み込みます。ファイルの各行が分析時に使用する補助クラスパスに追加されます。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>-analyzeFromFile</command> <replaceable>ファイルパス</replaceable></term>
+ <listitem>
+ <para>分析対象ファイルをファイルから読み込みます。ファイルの各行が分析対象クラスパスに追加されます。</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>-userPrefs</command> <replaceable>edu.umd.cs.findbugs.core.prefs</replaceable></term>
+ <listitem>
+ <para>ユーザー設定ファイルのパスを設定します。ユーザー設定ファイルの内容で、他のオプションの一部を上書きすることができます。
+ <literal>userPrefs</literal> を一番目の引数に指定した場合は、後続のオプションの方がユーザー設定ファイルの内容に優先します。
+ <literal>userPrefs</literal> を最後の引数に指定した場合は、ユーザー設定ファイルの内容の方が前に指定したオプションに優先します。
+ このオプションを設けた背景・理由は、 Eclipse プロジェクトの FindBugs の設定をコマンドライン実行で再利用するためです。</para>
+ </listitem>
+ </varlistentry>
+
<!--
<varlistentry>
<term><command></command> <replaceable></replaceable></term>
@@ -668,7 +695,7 @@ The second invokes the Command Line Interface (Text UI):
</mediaobject>
</para>
-<para>「Class archives and directories to analyze」テキストフィールドの横にある 「Add」ボタンを押すと、バグを分析する java クラスを含んでいる Java アーカイブファイル (zip, jar, ear, or war file) を選択して指定できます。複数の アーカイブ/ディレクトリーを追加することが可能です。</para>
+<para>「Classpath to analyze」の横にある 「Add」ボタンを押すと、バグを分析する java クラスを含んでいる Java アーカイブファイル (zip, jar, ear, or war file) を選択して指定できます。複数の アーカイブ/ディレクトリーを追加することが可能です。</para>
<para>また、分析を行う Java アーカイブのソースコードを含んだソースディレクトリーを指定することもできます。そうすると、バグの可能性があるソースコードの場所が、&FindBugs; 上でハイライトして表示されます。ソースディレクトリーは、Java パッケージ階層のルートディレクトリーを指定する必要があります。例えば、ユーザのアプリケーションが <varname>org.foobar.myapp</varname> パッケージの中にある場合は、 <filename class="directory">org</filename> ディレクトリーの親ディレクトリーをソースディレクトリーリストに指定する必要があります。</para>
@@ -678,7 +705,7 @@ The second invokes the Command Line Interface (Text UI):
<sect1>
<title>分析の実行</title>
-<para>アーカイブ、ディレクトリーおよびソースディレクトリーの指定ができれば、「Finish」ボタンを押して Jar ファイルに含まれるクラスに対する分析を実行します。巨大なプロジェクトを古いコンピュータ上で実行すると、かなりの時間(数十分)がかかることに注意してください。大容量メモリである最近のコンピュータなら、大きなプログラムであっても数分程度で分析できます。</para>
+<para>アーカイブ、ディレクトリーおよびソースディレクトリーの指定ができれば、「Analyze」ボタンを押して Jar ファイルに含まれるクラスに対する分析を実行します。巨大なプロジェクトを古いコンピュータ上で実行すると、かなりの時間(数十分)がかかることに注意してください。大容量メモリである最近のコンピュータなら、大きなプログラムであっても数分程度で分析できます。</para>
</sect1>
<sect1>
@@ -803,9 +830,22 @@ Command Line Interface.
<sect1>
<title>パラメーター</title>
-<para>このセクションでは、 &FindBugs; タスクを使用する際に、指定することができるパラメーターについて説明します。<variablelist> <varlistentry> <term><literal>class</literal></term>
+<para>このセクションでは、 &FindBugs; タスクを使用する際に、指定することができるパラメーターについて説明します。
+
+<variablelist>
+
+ <varlistentry>
+ <term><literal>class</literal></term>
<listitem>
- <para>分析の対象となるクラス群を指定するためのネストされる要素です。<literal>class</literal> 要素には <literal>location</literal> 属性の指定が必須です。分析対象となるアーカイブファイル (jar, zip, 他)、ディレクトリーまたはクラスファイルの名前を記述します。1 つの <literal>findbugs</literal> 要素に対して、複数の <literal>class</literal> 子要素を指定することができます。</para>
+ <para>任意指定のネストされる要素です。分析の対象となるクラス群を指定します。
+ <literal>class</literal> 要素には <literal>location</literal> 属性の指定が必須です。
+ 分析対象となるアーカイブファイル (jar, zip, 他)、ディレクトリーまたはクラスファイルの名前を記述します。
+ 1 つの <literal>findbugs</literal> 要素に対して、複数の <literal>class</literal> 子要素を指定することができます。
+ </para>
+ <para><literal>class</literal> 要素の指定を置き換えるまたは追加する形で、 &FindBugs; タスクに1個以上の <literal>fileset</literal> 要素を記述することで
+ 分析するファイル群を指定することができます。
+ 例えば、 fileset において特定のディレクトリにある全ての jar ファイルを分析対象に指定することができます。
+ </para>
</listitem>
</varlistentry>
@@ -840,7 +880,12 @@ Command Line Interface.
<varlistentry>
<term><literal>reportLevel</literal></term>
<listitem>
- <para>任意指定の属性です。報告されるバグの優先度のしきい値を指定します。「low」に設定すると、すべてのバグが報告されます。「medium」 (デフォルト) に設定すると、優先度 (中)および優先度 (高)のバグが報告されます。「high」に設定すると、優先度 (高) のバグのみが報告されます。</para>
+ <para>
+ 任意指定の属性です。報告される問題の信頼度・優先度のしきい値を指定します。
+ 「low」に設定すると、バグ報告が信頼度により除外されることはありません。
+ 「medium」 (デフォルト) に設定すると、信頼度(低)の問題が除外されます。
+ 「high」に設定すると、信頼度(高) のバグのみが報告されます。
+ </para>
</listitem>
</varlistentry>
@@ -909,7 +954,22 @@ Command Line Interface.
<varlistentry>
<term><literal>omitVisitors</literal></term>
<listitem>
- <para>任意指定の属性です。<literal>visitors</literal> 属性と似ていますが、こちらは <emphasis>実行されない</emphasis> ディテクタを指定します。</para>
+ <para>
+ 任意指定の属性です。
+ バグディテクタをコンマ区切りのリストで指定します。
+ <literal>visitors</literal> 属性と似ていますが、こちらは <emphasis>実行されない</emphasis> ディテクタを指定します。
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>chooseVisitors</literal></term>
+ <listitem>
+ <para>
+ 任意指定の属性です。
+ 頭に「+」または「-」を付け加えたバグディテクタをコンマ区切りのリストで指定します。
+ 「+」を付け加えたバグディテクタは有効に、「-」を付け加えたバグディテクタは無効になります。
+ </para>
</listitem>
</varlistentry>
@@ -976,6 +1036,29 @@ Command Line Interface.
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>userPreferencesFile</literal></term>
+ <listitem>
+ <para>
+ 任意指定の属性です。
+ ユーザー設定ファイルのパスを設定します。ユーザー設定ファイルの内容で、他のオプションの一部を上書きすることができます。
+ <literal>userPreferencesFile</literal> を一番目の引数に指定した場合は、後続のオプションの方がユーザー設定ファイルの内容に優先します。
+ <literal>userPreferencesFile</literal> を最後の引数に指定した場合は、ユーザー設定ファイルの内容の方が前に指定したオプションに優先します。
+ このオプションを設けた背景・理由は、 Eclipse プロジェクトの FindBugs の設定をコマンドライン実行で再利用するためです。
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>nested</literal></term>
+ <listitem>
+ <para>
+ 任意指定の属性です。分析対象のファイル・ディレクトリーリストにあるファイル内にネストされた jar および zip ファイルに対する分析を有効化・無効化します。
+ デフォルトでは、ネストされた jar/zip の分析は有効です。
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
@@ -998,7 +1081,11 @@ Command Line Interface.
<chapter id="eclipse">
<title>&FindBugs;™ Eclipse プラグインの使用方法</title>
-<para>FindBugs Eclipse プラグインを使用することによって、 &FindBugs; を <ulink url="http://www.eclipse.org/">Eclipse</ulink> IDE で使用することができるようになります。このFindBugs Eclipse プラグインは、 Peter Friese 氏の多大な貢献によるものです。Phil Crosby 氏 と Andrei Loskutov 氏は、プラグインの重要な改良に貢献しました。</para>
+<para>
+FindBugs Eclipse プラグインを使用することによって、 &FindBugs; を <ulink url="http://www.eclipse.org/">Eclipse</ulink> IDE で使用することができるようになります。
+このFindBugs Eclipse プラグインは、 Peter Friese 氏の多大な貢献によるものです。
+Phil Crosby 氏 と Andrey Loskutov 氏は、プラグインの重要な改良に貢献しました。
+</para>
<sect1>
<title>必要条件</title>
@@ -1020,7 +1107,7 @@ Command Line Interface.
</listitem>
</varlistentry>
- <varlistentry><term><ulink url="http://findbugs.cs.umd.edu/eclipse-candidate/">http://findbugs.cs.umd.edu/eclips-candidate/</ulink></term>
+ <varlistentry><term><ulink url="http://findbugs.cs.umd.edu/eclipse-candidate/">http://findbugs.cs.umd.edu/eclipse-candidate/</ulink></term>
<listitem>
<para>FindBugsの公式リリース物に加えて、公式リリース候補版を提供します。</para>
@@ -1064,13 +1151,86 @@ Command Line Interface.
</sect1>
<sect1>
+<title>Eclipse プラグインの拡張方法 (2.0.0 以降)</title>
+<para>
+Eclipse プラグインでは、 独自の &FindBugs; ディテクタを追加することができます。
+(詳しく知りたい方は、
+<ulink url="http://code.google.com/p/findbugs/source/browse/findbugs/src/doc/AddingDetectors.txt">AddingDetectors.txt</ulink>
+もご覧ください)。
+独自のプラグインを Eclipse に追加するには以下の2通りの方法があります。
+</para>
+<itemizedlist>
+ <listitem>
+ <para>
+ 既存の標準 &FindBugs; ディテクタパッケージは以下で設定できます。
+ <menuchoice>
+ <guimenu>Window</guimenu>
+ <guimenuitem>Preferences</guimenuitem>
+ <guimenuitem>Java</guimenuitem>
+ <guimenuitem>FindBugs</guimenuitem>
+ <guimenuitem>Misc. Settings</guimenuitem>
+ <guimenuitem>Custom Detectors</guimenuitem>
+ </menuchoice>。
+ ここで追加するプラグインライブラリの場所を指定するだけです。
+ </para>
+
+ <para>
+ この方法の利点は、既存のディテクタパッケージは「そのまま」で、サードパーティーディテクタの品質をすばやく検証できることです。
+ 欠点としては、この設定は Eclipse ワークスペース毎に適用する必要があり、この設定をチームメンバー間で共有することができないことです。
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Eclipse 標準の拡張機構を使って独自のディテクタを追加することができます。
+ </para>
+
+ <para>
+ <ulink url="http://code.google.com/p/findbugs/source/browse/eclipsePlugin/schema/detectorPlugins.exsd">
+ findBugsEclipsePlugin/schema/detectorPlugins.exsd</ulink> の documentation で plugin.xml の更新方法を確認してください。
+ 既存の &FindBugs; ディテクタプラグイン を簡単に「拡張」して強力な &FindBugs; Eclipse ディテクタプラグイン にすることができます。
+ 通常必要なのは、 META-INF/MANIFEST.MF および plugin.xml を jar に追加してかつ、 MANIFEST.MF がビルド時に上書きされないようにビルドスクリプトを更新するだけです。
+ </para>
+
+ <para>
+ この方法の利点は、 Eclipse インストールを共有しさえすれば、チームメンバー同士で正確に同じディテクタ設定を使用できることです。
+ 前提条件は現在使用しているディテクタパッケージを Eclipse プラグインに変換しておくことです。
+ これはサードパーティのディテクタパッケージも同様です。
+ もうひとつの主な差別化要因は、 FindBugs のデフォルト実行時クラスパス に当該サードパーティライブラリーを追加することが必要なことです(くわしくは
+ <ulink url="http://code.google.com/p/findbugs/source/browse/findbugs/src/doc/AddingDetectors.txt">AddingDetectors.txt</ulink>
+ をご覧ください)。
+ </para>
+ </listitem>
+
+</itemizedlist>
+
+</sect1>
+
+<sect1>
<title>トラブルシューティング</title>
-<para>&FindBugs; Eclipse プラグインは、まだ実験段階です。このセクションでは、プラグインに関する一般的な問題と (判明していれば) それらの問題の解決方法を記述します。</para>
+<para>
+このセクションでは、プラグインに関する一般的な問題と (判明していれば) それらの問題の解決方法を記述します。
+</para>
<itemizedlist>
<listitem>
- <para>&FindBugs; 問題マーカーが (ソース画面および問題ビューに) 表示されない場合は、問題ビューのフィルター設定を変更してください。詳細情報は <ulink url="http://findbugs.sourceforge.net/FAQ.html#q7">http://findbugs.sourceforge.net/FAQ.html#q7</ulink> を参照してください。</para>
+ <para>
+ Eclipse において &FindBugs; の分析開始後に OutOfMemory エラーダイアログが 出た場合は、
+ JVM の使用メモリを増やしてください。すなわち、 eclipse.ini の末尾に以下の記述を追加してください。
+ <programlisting>
+ -vmargs
+ -Xmx1000m
+ </programlisting>
+ 重要:「-vmargs」で始まる設定引数は eclipse.ini ファイルの末尾に記述する必要があります。
+ また、各行には引数を一つだけしか書くことができません!
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ &FindBugs; 問題マーカーが (ソース画面および問題ビューに) 表示されない場合は、問題ビューのフィルター設定を変更してください。
+ 詳細情報は <ulink url="http://findbugs.sourceforge.net/FAQ.html#q7">http://findbugs.sourceforge.net/FAQ.html#q7</ulink> を参照してください。
+ </para>
</listitem>
</itemizedlist>
@@ -1124,12 +1284,36 @@ Command Line Interface.
</varlistentry>
<varlistentry>
+ <term><literal><Confidence></literal></term>
+ <listitem>
+ <para>
+ この要素は、特定のバグ信頼度をもつ警告を照合します。
+ <literal>value</literal> 属性には、整数値を指定します。すなわち 1 は信頼度(高) 、また、 2 は信頼度(中) 、 3 は信頼度(低) を示します。
+ <Confidence> は 2.0.0 リリースから <Priority> の後継として取って代わりました。
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal><Priority></literal></term>
<listitem>
- <para>この要素は、特定の優先度をもつ警告を照合します。<literal>value</literal> 属性には、整数値を指定します : 1 は優先度(高)、また、 2 は優先度(中) 、 3 は優先度(低) を示します。</para>
+ <para>
+ <literal><Confidence></literal> と同一です。下位互換性を保つため残されています。
+ </para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal><Rank></literal></term>
+ <listitem>
+ <para>
+ この要素は、特定のバグランクをもつ警告を照合します。
+ <literal>value</literal> 属性には、 1 から 20 の整数値を指定します。
+ 1 から 4 は最も恐ろしいバグ、 5 から 9 は恐ろしいバグ、 10 から 14 は厄介なバグ,
+ そして 15 から 20 は不安なバグを示します。
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><literal><Package></literal></term>
@@ -1150,6 +1334,16 @@ Command Line Interface.
</varlistentry>
<varlistentry>
+ <term><literal><Source></literal></term>
+ <listitem>
+ <para>
+ この要素は、特定のソースファイルに関連した警告を照合します。
+ <literal>name</literal> 属性を使用して、照合するソースファイル名をソースファイル名そのものか、または、正規表現で指定します。
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal><Method></literal></term>
<listitem><para>この要素は、メソッドを指定します。<literal>name</literal> 属性を使用して、照合するメソッド名をメソッド名そのものか、または、正規表現で指定します。<literal>params</literal> 属性には、コンマ区切りでメソッド引数の型のリストを指定します。<literal>returns</literal> 属性にはメソッドの戻り値の型を指定します。<literal>params</literal> および <literal>returns</literal> においては、クラス名は完全修飾名である必要があります。(例えば、単に "String" ではなく "java.lang.String" としてください。) <literal>params</literal> <literal>returns</literal> のどちらか一方を指定した場合は、もう一方の属性の指定も必須です。なぜならば、メソッドシグニチャーを構築のために必要だからです。<literal>nam [...]
@@ -1171,6 +1365,21 @@ Command Line Interface.
<term><literal><Or></literal></term>
<listitem><para>この要素は、論理和として <literal>Match</literal> 条項を結合します。すなわち、2つの <literal>Method</literal> 要素を <literal>Or</literal> 条項に入れることで、どちらか一方のメソッドでマッチさせることができます。</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal><And></literal></term>
+ <listitem><para>
+ この要素は、論理積として <literal>Match</literal> 条項を結合します。
+ すなわち、 <literal>Bug</literal> および <literal>Confidence</literal> 要素を <literal>And</literal> 条項内に指定することで
+ 特定の信頼度の特定のバグのみ照合することができます。
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal><Not></literal></term>
+ <listitem><para>
+ この要素は、内包する子 <literal>Match</literal> を反転します。
+ すなわち、 <literal>Bug</literal> 要素を <literal>Not</literal> 条項内に指定することで指定したバグ以外のすべてのバグと照合します。
+ </para></listitem>
+ </varlistentry>
</variablelist>
</sect1>
@@ -1178,7 +1387,11 @@ Command Line Interface.
<sect1>
<title>Java 要素名マッチング</title>
-<para><literal>Class</literal> 、 <literal>Method</literal> または <literal>Field</literal> の <literal>name</literal> 属性が文字 ~ で始まっている場合は、属性値の残りの部分を Java の正規表現として解釈します。そうして、当該 Java 要素の名前に対しての照合が行われます。</para>
+<para>
+<literal>Class</literal> 、 <literal>Source</literal> 、 <literal>Method</literal> または <literal>Field</literal> の <literal>name</literal> 属性が文字 ~ で始まっている場合は、
+属性値の残りの部分を Java の正規表現として解釈します。
+そうして、当該 Java 要素の名前に対しての照合が行われます。
+</para>
<para>パターンの照合は要素の名前全体に対して行われることに注意してください。そのため、部分一致照合を行いたい場合はパターン文字列の前後に .* を付加して使用する必要があります。</para>
@@ -1337,7 +1550,42 @@ Command Line Interface.
</Match>
]]>
</programlisting>
+</para>
+
+<para>
+ 11. Not フィルター演算子を使用してバグに一致させます。
+<programlisting>
+<![CDATA[
+<!-- テストクラスのバグは無視する。ただし、 JUnit テスト特有のバグは例外とする。 -->
+<!-- i.e. filter bug if ( classIsJUnitTest && ! bugIsRelatedToJUnit ) -->
+<Match>
+ <!-- Match フィルタは論理和と同等 -->
+
+ <Class name="~.*\.*Test" />
+ <!-- テストクラスは末尾に「Test」 -->
+
+ <Not>
+ <Bug code="IJU" /> <!-- 「IJU」は JUnit テストコード関連のバグコード -->
+ </Not>
+</Match>
+]]>
+</programlisting>
+</para>
+
+<para>
+ 12. 完全な除外フィルター。 Groovy ソースファイルから生成された全クラスを除外します。
+
+<programlisting>
+<![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<FindBugsFilter>
+<Match>
+ <Source name="~.*\.groovy" />
+</Match>
+</FindBugsFilter>
+]]>
+</programlisting>
</para>
</sect1>
@@ -1380,6 +1628,15 @@ Command Line Interface.
<Bug pattern="DLS_DEAD_LOCAL_STORE" />
<Priority value="2" />
</Match>
+
+ <!-- テストクラスのバグすべて。 JUnit 特有のバグは除く。 -->
+ <Match>
+ <Class name="~.*\.*Test" />
+ <Not>
+ <Bug code="IJU" />
+ </Not>
+ </Match>
+
</FindBugsFilter>
]]>
</programlisting>
@@ -1489,7 +1746,9 @@ Command Line Interface.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.CheckForNull</command></term>
<listitem>
-<command>[Target]</command> Field, Method, Parameter
+ <para>
+ <command>[Target]</command> Field, Method, Parameter
+ </para>
</listitem>
<listitem>
<para>アノテーションをつけた要素は、 null である可能性があります。したがって、当該要素を使用する際は null チェックをするべきです。このアノテーションをメソッドに適用すると、メソッドの戻り値に適用されます。</para>
@@ -1499,7 +1758,9 @@ Command Line Interface.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.CheckReturnValue</command></term>
<listitem>
+ <para>
<command>[Target]</command> Method, Constructor
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -1524,7 +1785,9 @@ Command Line Interface.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.DefaultAnnotation</command></term>
<listitem>
+ <para>
<command>[Target]</command> Type, Package
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -1543,11 +1806,10 @@ Command Line Interface.
</listitem>
<listitem>
<para>
-Indicates that all members of the class or package should be annotated with the default
-value of the supplied annotation classes. This would be used for behavior annotations
-such as @NonNull, @CheckForNull, or @CheckReturnValue. In particular, you can use
- at DefaultAnnotation(NonNull.class) on a class or package, and then use @Nullable only
-on those parameters, methods or fields that you want to allow to be null.
+クラスまたはパッケージのすべてのメンバーが指定されたアノテーションクラスのデフォルト値でアノテートされることを指定することができます。
+この指定は @NonNull 、 @CheckForNull 、または @CheckReturnValueなどに使用する想定です。
+具体的には、 クラスまたはパッケージに @DefaultAnnotation(NonNull.class) を指定した上で、
+null を許容したいパラメーター、メソッドまたはフィールドにのみ @Nullable を指定するという使用方法があります。
</para>
</listitem>
</varlistentry>
@@ -1555,7 +1817,9 @@ on those parameters, methods or fields that you want to allow to be null.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields</command></term>
<listitem>
+ <para>
<command>[Target]</command> Type, Package
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -1574,7 +1838,7 @@ on those parameters, methods or fields that you want to allow to be null.
</listitem>
<listitem>
<para>
-This is same as the DefaultAnnotation except it only applys to fields.
+フィールドのみに適用されること以外は DefaultAnnotation と同様です。
</para>
</listitem>
</varlistentry>
@@ -1582,7 +1846,9 @@ This is same as the DefaultAnnotation except it only applys to fields.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.DefaultAnnotationForMethods</command></term>
<listitem>
+ <para>
<command>[Target]</command> Type, Package
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -1601,7 +1867,7 @@ This is same as the DefaultAnnotation except it only applys to fields.
</listitem>
<listitem>
<para>
-This is same as the DefaultAnnotation except it only applys to methods.
+メソッドのみに適用されること以外は DefaultAnnotation と同様です。
</para>
</listitem>
</varlistentry>
@@ -1609,7 +1875,9 @@ This is same as the DefaultAnnotation except it only applys to methods.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters</command></term>
<listitem>
+ <para>
<command>[Target]</command> Type, Package
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -1628,7 +1896,7 @@ This is same as the DefaultAnnotation except it only applys to methods.
</listitem>
<listitem>
<para>
-This is same as the DefaultAnnotation except it only applys to method parameters.
+パラメーターのみに適用されること以外は DefaultAnnotation と同様です。
</para>
</listitem>
</varlistentry>
@@ -1636,7 +1904,9 @@ This is same as the DefaultAnnotation except it only applys to method parameters
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.NonNull</command></term>
<listitem>
+ <para>
<command>[Target]</command> Field, Method, Parameter
+ </para>
</listitem>
<listitem>
<para>アノテーションをつけた要素は、 null であってはいけません。アノテーションをつけたフィールドは、構築完了後 null であってはいけません。アノテーションをつけたメソッドは、 null ではない値を戻り値としなければなりません。</para>
@@ -1646,13 +1916,18 @@ This is same as the DefaultAnnotation except it only applys to method parameters
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.Nullable</command></term>
<listitem>
+ <para>
<command>[Target]</command> Field, Method, Parameter
+ </para>
</listitem>
<listitem>
- <para>アノテーションをつけた要素は、 null であってはいけません。In general, this means developers will have to read the documentation to determine when a null value is acceptable and whether it is neccessary to check for a null value. FindBugs will treat the annotated items as though they had no annotation.</para>
<para>
-In pratice this annotation is useful only for overriding an overarching NonNull
-annotation.
+アノテーションをつけた要素は、 条件により null である可能性があります。
+一般に、開発者はドキュメントを読んで null 値を許容するかどうかまたは null 値をチェックするかどうかを決定する必要があります。
+FindBugs はこのアノテーションをつけた要素を、アノテーションがついていないものと同様に扱います。
+ </para>
+ <para>
+実際には、このアノテーションは NonNull をつけた要素をオーバーライドする場合に有用です。
</para>
</listitem>
</varlistentry>
@@ -1660,7 +1935,9 @@ annotation.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.OverrideMustInvoke</command></term>
<listitem>
+ <para>
<command>[Target]</command> Method
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -1668,8 +1945,7 @@ annotation.
<term><command>[Parameter]</command></term>
<listitem>
<para>
- <command>value:</command>Specify when the super invocation should be
- performed (FIRST, ANYTIME, LAST). Default value:ANYTIME.
+ <command>value:</command>super の呼び出し箇所を指定します (FIRST, ANYTIME, LAST)。 デフォルト値 :ANYTIME。
</para>
</listitem>
</varlistentry>
@@ -1677,11 +1953,9 @@ annotation.
</listitem>
<listitem>
<para>
-Used to annotate a method that, if overridden, must (or should) be invoke super
-in the overriding method. Examples of such methods include finalize() and clone().
-The argument to the method indicates when the super invocation should occur:
-at any time, at the beginning of the overriding method, or at the end of the overriding method.
-(This anotation is not implmemented in FindBugs as of September 8, 2006).
+オーバーライドされた場合にオーバーライドメソッド内で super を呼び出すべきメソッドにアノテートします。
+例えば、 finalize() や clone() がそのようなメソッドに該当します。
+引数は、 super の呼び出し箇所を指定します。すなわち、随時、メソッドの最初またはメソッドの最後です。
</para>
</listitem>
</varlistentry>
@@ -1690,7 +1964,7 @@ at any time, at the beginning of the overriding method, or at the end of the ove
<term><command>edu.umd.cs.findbugs.annotations.PossiblyNull</command></term>
<listitem>
<para>
-This annotation is deprecated. Use CheckForNull instead.
+非推奨です。 CheckForNull を使用してください。
</para>
</listitem>
</varlistentry>
@@ -1698,7 +1972,9 @@ This annotation is deprecated. Use CheckForNull instead.
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.SuppressWarnings</command></term>
<listitem>
+ <para>
<command>[Target]</command> Type, Field, Method, Parameter, Constructor, Package
+ </para>
</listitem>
<listitem>
<variablelist>
@@ -1706,12 +1982,12 @@ This annotation is deprecated. Use CheckForNull instead.
<term><command>[Parameter]</command></term>
<listitem>
<para>
- <command>value:</command>The name of the warning. More than one name can be specified.
+ <command>value:</command>警告の名称。複数の名称を指定することができます。
</para>
</listitem>
<listitem>
<para>
- <command>justification:</command>Reason why the warning should be ignored. デフォルト値 :""。</para>
+ <command>justification:</command>警告を無視する理由。 デフォルト値 :""。</para>
</listitem>
</varlistentry>
</variablelist>
@@ -1732,7 +2008,9 @@ are encouraged to cooperate to ensure that the same names work across multiple c
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.UnknownNullness</command></term>
<listitem>
+ <para>
<command>[Target]</command> Field, Method, Parameter
+ </para>
</listitem>
<listitem>
<para>
@@ -1744,7 +2022,9 @@ Used to indicate that the nullness of the target is unknown, or my vary in unkno
<varlistentry>
<term><command>edu.umd.cs.findbugs.annotations.UnknownNullness</command></term>
<listitem>
+ <para>
<command>[Target]</command> Field, Method, Parameter
+ </para>
</listitem>
<listitem>
<para>
@@ -1755,10 +2035,10 @@ Used to indicate that the nullness of the target is unknown, or my vary in unkno
</variablelist>
<para>また、 &FindBugs; 次に示すアノテーションもサポートしています。 :<itemizedlist>
- <listitem>net.jcip.annotations.GuardedBy</listitem>
- <listitem>net.jcip.annotations.Immutable</listitem>
- <listitem>net.jcip.annotations.NotThreadSafe</listitem>
- <listitem>net.jcip.annotations.ThreadSafe</listitem>
+ <listitem><para>net.jcip.annotations.GuardedBy</para></listitem>
+ <listitem><para>net.jcip.annotations.Immutable</para></listitem>
+ <listitem><para>net.jcip.annotations.NotThreadSafe</para></listitem>
+ <listitem><para>net.jcip.annotations.ThreadSafe</para></listitem>
</itemizedlist>
</para>
<para><ulink url="http://jcip.net/">Java Concurrency in Practice</ulink> の <ulink url="http://jcip.net/annotations/doc/index.html"> API ドキュメント</ulink> を参照してください。</para>
@@ -2016,6 +2296,7 @@ Used to indicate that the nullness of the target is unknown, or my vary in unkno
<row><entry>-newCode[:truth]</entry> <entry>newCode="[true|false]"</entry> <entry>新クラスの追加によってもたらされた警告のみ出力されます。</entry></row>
<row><entry>-removedCode[:truth]</entry> <entry>removedCode="[true|false]"</entry> <entry>クラスの削除によって除去された警告のみ出力されます。</entry></row>
<row><entry>-priority <level></entry> <entry>priority="<level>"</entry> <entry>指定した優先度以上の優先度をもつ警告のみ出力されます。</entry></row>
+<row><entry>-maxRank <rank></entry> <entry>rank="[1..20]"</entry> <entry>allow only warnings with this rank or lower</entry></row>
<row><entry>-class <pattern></entry> <entry>class="<class>"</entry> <entry>指定したパターンに一致する主クラスをもつ警告のみ出力されます。</entry></row>
<row><entry>-bugPattern <pattern></entry> <entry>bugPattern="<pattern>"</entry> <entry>指定したパターンに一致するバグ種別をもつ警告のみ出力されます。</entry></row>
<row><entry>-category <category></entry> <entry>category="<category>"</entry> <entry>指定した文字列で始まるカテゴリーの警告のみ出力されます。</entry></row>
@@ -2583,8 +2864,8 @@ contributed the string concatenation detector.</para>
<para>Thomas Klaeger contributed a number of bug fixes and
bug detector improvements.</para>
-<para>Andrei Loskutov made a number of improvements to the
-Eclipse plugin.</para>
+<para>Andrey Loskutov made a number of bug fixes and
+bug detector improvements. He is maintainer of the Eclipse plugin.</para>
<para>Brian Goetz contributed a major refactoring of the
visitor classes to improve readability and understandability.</para>
diff --git a/src/doc/performance.html b/src/doc/performance.html
index 3ddc53c..edbf3b0 100644
--- a/src/doc/performance.html
+++ b/src/doc/performance.html
@@ -26,29 +26,29 @@
<h2>Important Request</h2>
<p> If you are seeing any significant performance regressions in FindBugs 2.0,
I very much need your help. Please either email <a href="mailto:findbugs at cs.umd.edu">findbugs at cs.umd.edu</a>
- or file <a href="http://sourceforge.net/tracker/?atid=614693&group_id=96405&func=browse">a
+ or file <a href="http://sourceforge.net/p/findbugs/_list/tickets?source=navbar">a
bug report</a>. with the following information from the xml file for your project (from both the
1.3.9 and 2.0.0 version if possible). Sending me your code or pointing me to a open source repository
would be great, but I know that isn't feasible for a lot of projects. The information I'm requesting
doesn't include any information about the code being analyzed other than the total size of the code
being analyzed and the total number of issues found at the different confidence levels. The
<FindBugsSummary ... > start tag. For example: <quote> <pre>
- <FindBugsSummary timestamp="Tue, 30 Dec 2008 21:29:52 -0500"
- total_classes="206" referenced_classes="325" total_bugs="72" total_size="7654" num_packages="21"
- vm_version="20.4-b02-402" cpu_seconds="62.52" clock_seconds="22.01"
- peak_mbytes="112.21" alloc_mbytes="1683.38" gc_seconds="1.19"
+ <FindBugsSummary timestamp="Tue, 30 Dec 2008 21:29:52 -0500"
+ total_classes="206" referenced_classes="325" total_bugs="72" total_size="7654" num_packages="21"
+ vm_version="20.4-b02-402" cpu_seconds="62.52" clock_seconds="22.01"
+ peak_mbytes="112.21" alloc_mbytes="1683.38" gc_seconds="1.19"
priority_3="56" priority_2="14" priority_1="2">
</pre> </quote> The <FindBugsProfile>...</FindBugsProfile> element. For example: <quote>
<pre>
<FindBugsProfile>
- <ClassProfile name="edu.umd.cs.findbugs.detect.IncompatMask" totalMilliseconds="11"
- invocations="206" avgMicrosecondsPerInvocation="55" maxMicrosecondsPerInvocation="475"
+ <ClassProfile name="edu.umd.cs.findbugs.detect.IncompatMask" totalMilliseconds="11"
+ invocations="206" avgMicrosecondsPerInvocation="55" maxMicrosecondsPerInvocation="475"
standardDeviationMircosecondsPerInvocation="75"/>
- <ClassProfile name="edu.umd.cs.findbugs.detect.FindFinalizeInvocations" totalMilliseconds="11"
- invocations="206" avgMicrosecondsPerInvocation="55" maxMicrosecondsPerInvocation="402"
+ <ClassProfile name="edu.umd.cs.findbugs.detect.FindFinalizeInvocations" totalMilliseconds="11"
+ invocations="206" avgMicrosecondsPerInvocation="55" maxMicrosecondsPerInvocation="402"
standardDeviationMircosecondsPerInvocation="69"/>
- <ClassProfile name="edu.umd.cs.findbugs.classfile.engine.bcel.LockDataflowFactory" totalMilliseconds="11"
- invocations="23" avgMicrosecondsPerInvocation="515" maxMicrosecondsPerInvocation="2637"
+ <ClassProfile name="edu.umd.cs.findbugs.classfile.engine.bcel.LockDataflowFactory" totalMilliseconds="11"
+ invocations="23" avgMicrosecondsPerInvocation="515" maxMicrosecondsPerInvocation="2637"
standardDeviationMircosecondsPerInvocation="639"/>
...
</FindBugsProfile>
diff --git a/src/doc/reportingBugs.html b/src/doc/reportingBugs.html
index c54b7aa..9975fa4 100644
--- a/src/doc/reportingBugs.html
+++ b/src/doc/reportingBugs.html
@@ -23,13 +23,13 @@ credit you on our website and in the manual.
<p>
Please report bugs using the
-<a href="http://sourceforge.net/tracker/?atid=614693&group_id=96405&func=browse">Sourceforge
+<a href="http://sourceforge.net/p/findbugs/_list/tickets?source=navbar">Sourceforge
bugs tracker</a>. Note that you need to be logged in to sourceforge to
use the bug tracker.
</p>
<p>
-If you cannot use the Sourceforge tracker, you can try sending
+If you cannot use the Sourceforge tracker, you can try sending
email to the <a href="http://www.cs.umd.edu/mailman/listinfo/findbugs-discuss"
>findbugs-discuss mailing list</a>. You must be subscribed
to the list to post a message.
@@ -40,14 +40,14 @@ Finally, as a last resort, you can email <a href="mailto:findbugs at cs.umd.edu">fi
However, such emails are much less likely to be handled in a timely manner than
posts to the tracker or mailing list.
</p>
-
+
<h2>False and Inaccurate Warnings</h2>
-
+
<p>
- Like most bug-detection tools based on static analysis, FindBugs
- issues some warnings that do not correspond to real bugs.
- While in general we would like to make the percentage of such warnings
- small, we can never fully eliminate them.
+ Like most bug-detection tools based on static analysis, FindBugs
+ issues some warnings that do not correspond to real bugs.
+ While in general we would like to make the percentage of such warnings
+ small, we can never fully eliminate them.
</p>
<h2>Information to include</h2>
diff --git a/src/gui/edu/umd/cs/findbugs/gui/AnnotatedString.java b/src/gui/edu/umd/cs/findbugs/gui/AnnotatedString.java
index f8e6c2c..61150c0 100644
--- a/src/gui/edu/umd/cs/findbugs/gui/AnnotatedString.java
+++ b/src/gui/edu/umd/cs/findbugs/gui/AnnotatedString.java
@@ -32,13 +32,14 @@ import java.awt.event.KeyEvent;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
import edu.umd.cs.findbugs.L10N;
import edu.umd.cs.findbugs.SystemProperties;
/**
* Class to handle Strings annotated with embedded mnemonics
- *
+ *
* Note: Since the human interface guidelines for Mac OS X say never to use
* mnemonics, this class behaves as if no mnemonics are set when run on Mac OS
* X.
@@ -80,7 +81,7 @@ public class AnnotatedString {
/**
* Return the appropriate mnemonic character for this string. If no mnemonic
* should be displayed, KeyEvent.VK_UNDEFINED is returned.
- *
+ *
* @return the Mnemonic character, or VK_UNDEFINED if no mnemonic should be
* set
*/
@@ -126,7 +127,7 @@ public class AnnotatedString {
public static void main(String[] args) {
// Some basic tests
- JFrame frame = new JFrame();
+ final JFrame frame = new JFrame();
frame.getContentPane().setLayout(new FlowLayout());
addButton(frame, "&File");
@@ -142,14 +143,20 @@ public class AnnotatedString {
addButton(frame, "Cat & Dog");
addButton(frame, "Cat && Dog");
- frame.pack();
- frame.setVisible(true);
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ frame.pack();
+ frame.setVisible(true);
+ }
+ });
+
}
/**
* Localise the given AbstractButton, setting the text and optionally
* mnemonic Note that AbstractButton includes menus and menu items.
- *
+ *
* @param button
* The button to localise
* @param key
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/AboutDialog.java b/src/gui/edu/umd/cs/findbugs/gui2/AboutDialog.java
index 5e5e475..4ab9351 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/AboutDialog.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/AboutDialog.java
@@ -25,9 +25,7 @@
package edu.umd.cs.findbugs.gui2;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStream;
import java.net.URL;
import java.text.MessageFormat;
import java.util.regex.Pattern;
@@ -36,7 +34,6 @@ import javax.swing.JFrame;
import javax.swing.event.HyperlinkEvent;
import edu.umd.cs.findbugs.Version;
-import edu.umd.cs.findbugs.charsets.UTF8;
import edu.umd.cs.findbugs.log.Logger;
import edu.umd.cs.findbugs.util.LaunchBrowser;
@@ -76,7 +73,7 @@ public class AboutDialog extends javax.swing.JDialog {
/**
* Process an HTML page to replace certain substitution patterns. Right now,
* we just expand @VERSION at .
- */
+ *
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings("OS_OPEN_STREAM")
private void processPage(javax.swing.JEditorPane pane, String fileName) throws IOException {
InputStream in = null;
@@ -114,7 +111,7 @@ public class AboutDialog extends javax.swing.JDialog {
} catch (IOException e) {
}
}
- }
+ }*/
/**
* This method is called from within the constructor to initialize the form.
@@ -145,6 +142,7 @@ public class AboutDialog extends javax.swing.JDialog {
aboutEditorPane.setEditable(false);
aboutEditorPane.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
+ @Override
public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
editorPaneHyperlinkUpdate(evt);
}
@@ -156,6 +154,7 @@ public class AboutDialog extends javax.swing.JDialog {
licenseEditorPane.setEditable(false);
licenseEditorPane.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
+ @Override
public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
editorPaneHyperlinkUpdate(evt);
}
@@ -167,6 +166,7 @@ public class AboutDialog extends javax.swing.JDialog {
acknowldgementsEditorPane.setEditable(false);
acknowldgementsEditorPane.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
+ @Override
public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
editorPaneHyperlinkUpdate(evt);
}
@@ -196,6 +196,7 @@ public class AboutDialog extends javax.swing.JDialog {
okButton.setMnemonic('O');
okButton.setText(edu.umd.cs.findbugs.L10N.getLocalString("dlg.ok_btn", "OK"));
okButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
okButtonActionPerformed(evt);
}
@@ -257,5 +258,3 @@ public class AboutDialog extends javax.swing.JDialog {
// End of variables declaration//GEN-END:variables
}
-
-// vim:ts=4
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/AbstractSwingGuiCallback.java b/src/gui/edu/umd/cs/findbugs/gui2/AbstractSwingGuiCallback.java
index 1e8ced6..6d31d97 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/AbstractSwingGuiCallback.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/AbstractSwingGuiCallback.java
@@ -1,258 +1,284 @@
-package edu.umd.cs.findbugs.gui2;
-
-import java.awt.Component;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JComboBox;
-import javax.swing.JComponent;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JPasswordField;
-import javax.swing.JTextField;
-import javax.swing.MutableComboBoxModel;
-import javax.swing.ProgressMonitor;
-import javax.swing.ProgressMonitorInputStream;
-import javax.swing.SwingUtilities;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import javax.swing.text.JTextComponent;
-
-import edu.umd.cs.findbugs.AWTEventQueueExecutor;
-import edu.umd.cs.findbugs.IGuiCallback;
-import edu.umd.cs.findbugs.util.LaunchBrowser;
-
-public abstract class AbstractSwingGuiCallback implements IGuiCallback {
- private final AWTEventQueueExecutor bugUpdateExecutor = new AWTEventQueueExecutor();
-
- private final Component parent;
-
- public AbstractSwingGuiCallback(Component parent) {
- this.parent = parent;
- }
-
- public ExecutorService getBugUpdateExecutor() {
- return bugUpdateExecutor;
- }
-
- public void showMessageDialogAndWait(final String message) throws InterruptedException {
- if (SwingUtilities.isEventDispatchThread())
- JOptionPane.showMessageDialog(parent, message);
- else
- try {
- SwingUtilities.invokeAndWait(new Runnable() {
- public void run() {
- JOptionPane.showMessageDialog(parent, message);
- }
- });
- } catch (InvocationTargetException e) {
- throw new IllegalStateException(e);
- }
- }
-
- public void showMessageDialog(final String message) {
- if (SwingUtilities.isEventDispatchThread())
- JOptionPane.showMessageDialog(parent, message);
- else
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- JOptionPane.showMessageDialog(parent, message);
- }
- });
- }
-
- public int showConfirmDialog(String message, String title, String ok, String cancel) {
- return JOptionPane.showOptionDialog(parent, message, title, JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,
- null, new Object[] { ok, cancel }, ok);
- }
-
- public InputStream getProgressMonitorInputStream(InputStream in, int length, String msg) {
- ProgressMonitorInputStream pmin = new ProgressMonitorInputStream(parent, msg, in);
- ProgressMonitor pm = pmin.getProgressMonitor();
-
- if (length > 0)
- pm.setMaximum(length);
- return pmin;
- }
-
- public void displayNonmodelMessage(String title, String message) {
- DisplayNonmodelMessage.displayNonmodelMessage(title, message, parent, true);
- }
-
- public String showQuestionDialog(String message, String title, String defaultValue) {
- return (String) JOptionPane.showInputDialog(parent, message, title, JOptionPane.QUESTION_MESSAGE, null, null,
- defaultValue);
- }
-
- public List<String> showForm(String message, String title, List<FormItem> items) {
- int result = showFormDialog(message, title, items);
- if (result != JOptionPane.OK_OPTION)
- return null;
- updateFormItemsFromGui(items);
- List<String> results = new ArrayList<String>();
- for (FormItem item : items) {
- results.add(item.getCurrentValue());
- }
- return results;
- }
-
- public boolean showDocument(URL u) {
- return LaunchBrowser.showDocument(u);
- }
-
- public boolean isHeadless() {
- return false;
- }
-
- public void invokeInGUIThread(Runnable r) {
- SwingUtilities.invokeLater(r);
- }
-
-
- private void updateFormItemsFromGui(List<FormItem> items) {
- for (FormItem item : items) {
- JComponent field = item.getField();
- if (field instanceof JTextComponent) {
- JTextComponent textComponent = (JTextComponent) field;
- item.setCurrentValue(textComponent.getText());
-
- } else if (field instanceof JComboBox) {
- JComboBox box = (JComboBox) field;
- String value = (String) box.getSelectedItem();
- item.setCurrentValue(value);
- }
- item.updated();
- }
- updateComboBoxes(items);
- }
-
- private void updateComboBoxes(List<FormItem> items) {
- for (FormItem item : items) {
- JComponent field = item.getField();
- if (field instanceof JComboBox) {
- JComboBox box = (JComboBox) field;
- List<String> newPossibleValues = item.getPossibleValues();
- if (!boxModelIsSame(box, newPossibleValues)) {
- MutableComboBoxModel mmodel = (MutableComboBoxModel) box.getModel();
- replaceBoxModelValues(mmodel, newPossibleValues);
- mmodel.setSelectedItem(item.getCurrentValue());
- }
- }
- }
- }
-
- private void replaceBoxModelValues(MutableComboBoxModel mmodel, List<String> newPossibleValues) {
- try {
- while (mmodel.getSize() > 0)
- mmodel.removeElementAt(0);
- } catch (Exception e) {
- // ignore weird index out of bounds exceptions
- }
- for (String value : newPossibleValues) {
- mmodel.addElement(value);
- }
- }
-
- private boolean boxModelIsSame(JComboBox box, List<String> newPossibleValues) {
- boolean same = true;
- if (box.getModel().getSize() != newPossibleValues.size())
- same = false;
- else
- for (int i = 0; i < box.getModel().getSize(); i++) {
- if (!box.getModel().getElementAt(i).equals(newPossibleValues.get(i))) {
- same = false;
- break;
- }
- }
- return same;
- }
-
- private int showFormDialog(String message, String title, final List<FormItem> items) {
- JPanel panel = new JPanel();
- panel.setLayout(new GridBagLayout());
- GridBagConstraints gbc = new GridBagConstraints();
- gbc.fill = GridBagConstraints.BOTH;
- gbc.weightx = 1;
- gbc.weighty = 0;
- gbc.gridwidth = 2;
- gbc.gridy = 1;
- gbc.insets = new Insets(5, 5, 5, 5);
- panel.add(new JLabel(message), gbc);
- gbc.gridwidth = 1;
-
- for (FormItem item : items) {
- item.setItems(items);
- gbc.gridy++;
- panel.add(new JLabel(item.getLabel()), gbc);
- String defaultValue = item.getDefaultValue();
- if (item.getPossibleValues() != null) {
- JComboBox box = createComboBox(items, item);
- panel.add(box, gbc);
-
- } else {
- JTextField field = createTextField(items, item);
- panel.add(field, gbc);
- }
- }
-
- return JOptionPane.showConfirmDialog(parent, panel, title, JOptionPane.OK_CANCEL_OPTION);
- }
-
- private JTextField createTextField(final List<FormItem> items, FormItem item) {
- String defaultValue = item.getDefaultValue();
- JTextField field = (item.isPassword() ? new JPasswordField() : new JTextField());
- if (defaultValue != null) {
- field.setText(defaultValue);
- }
- item.setField(field);
- field.getDocument().addDocumentListener(new DocumentListener() {
- public void insertUpdate(DocumentEvent e) {
- changed();
- }
-
- public void removeUpdate(DocumentEvent e) {
- changed();
- }
-
- public void changedUpdate(DocumentEvent e) {
- changed();
- }
-
- private void changed() {
- updateFormItemsFromGui(items);
- }
- });
- return field;
- }
-
- private JComboBox createComboBox(final List<FormItem> items, FormItem item) {
- DefaultComboBoxModel model = new DefaultComboBoxModel();
- JComboBox box = new JComboBox(model);
- item.setField(box);
- for (String possibleValue : item.getPossibleValues()) {
- model.addElement(possibleValue);
- }
- String defaultValue = item.getDefaultValue();
- if (defaultValue == null)
- model.setSelectedItem(model.getElementAt(0));
- else
- model.setSelectedItem(defaultValue);
- box.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- updateFormItemsFromGui(items);
- }
- });
- return box;
- }
-}
+package edu.umd.cs.findbugs.gui2;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.MutableComboBoxModel;
+import javax.swing.ProgressMonitor;
+import javax.swing.ProgressMonitorInputStream;
+import javax.swing.SwingUtilities;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.JTextComponent;
+
+import edu.umd.cs.findbugs.AWTEventQueueExecutor;
+import edu.umd.cs.findbugs.IGuiCallback;
+import edu.umd.cs.findbugs.util.LaunchBrowser;
+
+public abstract class AbstractSwingGuiCallback implements IGuiCallback {
+ private final AWTEventQueueExecutor bugUpdateExecutor = new AWTEventQueueExecutor();
+
+ private final Component parent;
+
+ public AbstractSwingGuiCallback(Component parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public ExecutorService getBugUpdateExecutor() {
+ return bugUpdateExecutor;
+ }
+
+ @Override
+ public void showMessageDialogAndWait(final String message) throws InterruptedException {
+ if (SwingUtilities.isEventDispatchThread()) {
+ JOptionPane.showMessageDialog(parent, message);
+ } else {
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ JOptionPane.showMessageDialog(parent, message);
+ }
+ });
+ } catch (InvocationTargetException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ @Override
+ public void showMessageDialog(final String message) {
+ if (SwingUtilities.isEventDispatchThread()) {
+ JOptionPane.showMessageDialog(parent, message);
+ } else {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ JOptionPane.showMessageDialog(parent, message);
+ }
+ });
+ }
+ }
+
+ @Override
+ public int showConfirmDialog(String message, String title, String ok, String cancel) {
+ return JOptionPane.showOptionDialog(parent, message, title, JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,
+ null, new Object[] { ok, cancel }, ok);
+ }
+
+ @Override
+ public InputStream getProgressMonitorInputStream(InputStream in, int length, String msg) {
+ ProgressMonitorInputStream pmin = new ProgressMonitorInputStream(parent, msg, in);
+ ProgressMonitor pm = pmin.getProgressMonitor();
+
+ if (length > 0) {
+ pm.setMaximum(length);
+ }
+ return pmin;
+ }
+
+ @Override
+ public void displayNonmodelMessage(String title, String message) {
+ DisplayNonmodelMessage.displayNonmodelMessage(title, message, parent, true);
+ }
+
+ @Override
+ public String showQuestionDialog(String message, String title, String defaultValue) {
+ return (String) JOptionPane.showInputDialog(parent, message, title, JOptionPane.QUESTION_MESSAGE, null, null,
+ defaultValue);
+ }
+
+ @Override
+ public List<String> showForm(String message, String title, List<FormItem> items) {
+ int result = showFormDialog(message, title, items);
+ if (result != JOptionPane.OK_OPTION) {
+ return null;
+ }
+ updateFormItemsFromGui(items);
+ List<String> results = new ArrayList<String>();
+ for (FormItem item : items) {
+ results.add(item.getCurrentValue());
+ }
+ return results;
+ }
+
+ @Override
+ public boolean showDocument(URL u) {
+ return LaunchBrowser.showDocument(u);
+ }
+
+ @Override
+ public boolean isHeadless() {
+ return false;
+ }
+
+ @Override
+ public void invokeInGUIThread(Runnable r) {
+ SwingUtilities.invokeLater(r);
+ }
+
+
+ private void updateFormItemsFromGui(List<FormItem> items) {
+ for (FormItem item : items) {
+ JComponent field = item.getField();
+ if (field instanceof JTextComponent) {
+ JTextComponent textComponent = (JTextComponent) field;
+ item.setCurrentValue(textComponent.getText());
+
+ } else if (field instanceof JComboBox) {
+ @SuppressWarnings("unchecked")
+ JComboBox<String> box = (JComboBox<String>) field;
+ String value = (String) box.getSelectedItem();
+ item.setCurrentValue(value);
+ }
+ item.updated();
+ }
+ updateComboBoxes(items);
+ }
+
+ private void updateComboBoxes(List<FormItem> items) {
+ for (FormItem item : items) {
+ JComponent field = item.getField();
+ if (field instanceof JComboBox) {
+ @SuppressWarnings("unchecked")
+ JComboBox<String> box = (JComboBox<String>) field;
+ List<String> newPossibleValues = item.getPossibleValues();
+ if (!boxModelIsSame(box, newPossibleValues)) {
+ MutableComboBoxModel<String> mmodel = (MutableComboBoxModel<String>) box.getModel();
+ replaceBoxModelValues(mmodel, newPossibleValues);
+ mmodel.setSelectedItem(item.getCurrentValue());
+ }
+ }
+ }
+ }
+
+ private void replaceBoxModelValues(MutableComboBoxModel<String> mmodel, List<String> newPossibleValues) {
+ try {
+ while (mmodel.getSize() > 0) {
+ mmodel.removeElementAt(0);
+ }
+ } catch (Exception e) {
+ // ignore weird index out of bounds exceptions
+ }
+ for (String value : newPossibleValues) {
+ mmodel.addElement(value);
+ }
+ }
+
+ private boolean boxModelIsSame(JComboBox<String> box, List<String> newPossibleValues) {
+ boolean same = true;
+ if (box.getModel().getSize() != newPossibleValues.size()) {
+ same = false;
+ } else {
+ for (int i = 0; i < box.getModel().getSize(); i++) {
+ if (!box.getModel().getElementAt(i).equals(newPossibleValues.get(i))) {
+ same = false;
+ break;
+ }
+ }
+ }
+ return same;
+ }
+
+ private int showFormDialog(String message, String title, final List<FormItem> items) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new GridBagLayout());
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.weightx = 1;
+ gbc.weighty = 0;
+ gbc.gridwidth = 2;
+ gbc.gridy = 1;
+ gbc.insets = new Insets(5, 5, 5, 5);
+ panel.add(new JLabel(message), gbc);
+ gbc.gridwidth = 1;
+
+ for (FormItem item : items) {
+ item.setItems(items);
+ gbc.gridy++;
+ panel.add(new JLabel(item.getLabel()), gbc);
+ String defaultValue = item.getDefaultValue();
+ if (item.getPossibleValues() != null) {
+ JComboBox<?> box = createComboBox(items, item);
+ panel.add(box, gbc);
+
+ } else {
+ JTextField field = createTextField(items, item);
+ panel.add(field, gbc);
+ }
+ }
+
+ return JOptionPane.showConfirmDialog(parent, panel, title, JOptionPane.OK_CANCEL_OPTION);
+ }
+
+ private JTextField createTextField(final List<FormItem> items, FormItem item) {
+ String defaultValue = item.getDefaultValue();
+ JTextField field = (item.isPassword() ? new JPasswordField() : new JTextField());
+ if (defaultValue != null) {
+ field.setText(defaultValue);
+ }
+ item.setField(field);
+ field.getDocument().addDocumentListener(new DocumentListener() {
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ changed();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ changed();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ changed();
+ }
+
+ private void changed() {
+ updateFormItemsFromGui(items);
+ }
+ });
+ return field;
+ }
+
+ private JComboBox<String> createComboBox(final List<FormItem> items, FormItem item) {
+ DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
+ JComboBox<String> box = new JComboBox<>(model);
+ item.setField(box);
+ for (String possibleValue : item.getPossibleValues()) {
+ model.addElement(possibleValue);
+ }
+ String defaultValue = item.getDefaultValue();
+ if (defaultValue == null) {
+ model.setSelectedItem(model.getElementAt(0));
+ } else {
+ model.setSelectedItem(defaultValue);
+ }
+ box.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ updateFormItemsFromGui(items);
+ }
+ });
+ return box;
+ }
+}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/AnalyzingDialog.java b/src/gui/edu/umd/cs/findbugs/gui2/AnalyzingDialog.java
index dbb8fa2..c4d0bfc 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/AnalyzingDialog.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/AnalyzingDialog.java
@@ -50,24 +50,25 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
private volatile boolean analysisFinished = false;
@Nonnull
- private Project project;
+ private final Project project;
- private AnalysisCallback callback;
+ private final AnalysisCallback callback;
- private AnalysisThread analysisThread = new AnalysisThread();
+ private final AnalysisThread analysisThread = new AnalysisThread();
private int count;
private int goal;
- private JLabel statusLabel;
+ private final JLabel statusLabel;
- private JProgressBar progressBar;
+ private final JProgressBar progressBar;
- private JButton cancelButton;
+ private final JButton cancelButton;
public static void show(@Nonnull final Project project) {
AnalysisCallback callback = new AnalysisCallback() {
+ @Override
public void analysisFinished(BugCollection results) {
MainFrame instance = MainFrame.getInstance();
assert results.getProject() == project;
@@ -80,6 +81,7 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
results.reinitializeCloud();
}
+ @Override
public void analysisInterrupted() {
MainFrame instance = MainFrame.getInstance();
instance.updateProjectAndBugCollection(null);
@@ -87,11 +89,11 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
}
};
show(project, callback, false);
-
+
}
-
+
/**
- *
+ *
* @param project
* The Project to analyze
* @param callback
@@ -102,28 +104,30 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
* analysis is complete. If true, the constructor does not return
* until the analysis is either finished or interrupted.
*/
-
+
public static void show(@Nonnull
- Project project, AnalysisCallback callback, boolean joinThread) {
+ Project project, AnalysisCallback callback, boolean joinThread) {
AnalyzingDialog dialog = new AnalyzingDialog(project, callback, joinThread);
MainFrame.getInstance().acquireDisplayWait();
try {
dialog.analysisThread.start();
- if (joinThread)
+ if (joinThread) {
try {
dialog.analysisThread.join();
} catch (InterruptedException e) {
}
+ }
} finally {
- if (joinThread)
+ if (joinThread) {
MainFrame.getInstance().releaseDisplayWait();
+ }
}
}
-
-
+
+
/**
- *
+ *
* @param project
* The Project to analyze
* @param callback
@@ -135,8 +139,9 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
* until the analysis is either finished or interrupted.
*/
private AnalyzingDialog(@Nonnull Project project, AnalysisCallback callback, boolean joinThread) {
- if (project == null)
+ if (project == null) {
throw new NullPointerException("null project");
+ }
this.project = project;
this.callback = callback;
statusLabel = new JLabel(" ");
@@ -144,6 +149,7 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
progressBar.setStringPainted(true);
cancelButton = new JButton(edu.umd.cs.findbugs.L10N.getLocalString("dlg.cancel_btn", "Cancel"));
cancelButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
cancel();
}
@@ -155,8 +161,9 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
cancel();
}
});
-
+
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
add(statusLabel);
@@ -178,7 +185,7 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
}
}
});
-
+
}
private void cancel() {
@@ -197,6 +204,7 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
private void incrementCount() {
count++;
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
progressBar.setString(count + "/" + goal);
progressBar.setValue(count);
@@ -208,6 +216,7 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
this.count = count;
this.goal = goal;
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
progressBar.setString(count + "/" + goal);
progressBar.setValue(count);
@@ -216,18 +225,22 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
});
}
+ @Override
public void finishArchive() {
incrementCount();
}
+ @Override
public void finishClass() {
incrementCount();
}
+ @Override
public void finishPerClassAnalysis() {
updateStage(edu.umd.cs.findbugs.L10N.getLocalString("progress.finishing_analysis", "Finishing analysis..."));
}
+ @Override
public void reportNumberOfArchives(int numArchives) {
updateStage(edu.umd.cs.findbugs.L10N.getLocalString("progress.scanning_archives", "Scanning archives..."));
updateCount(0, numArchives);
@@ -235,6 +248,7 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
int pass = 0;
+ @Override
public void startAnalysis(int numClasses) {
pass++;
String localString = edu.umd.cs.findbugs.L10N.getLocalString("progress.analyzing_classes", "Analyzing classes...");
@@ -252,8 +266,9 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
@Override
public void run() {
- if (project == null)
+ if (project == null) {
throw new NullPointerException("null project");
+ }
BugCollection data;
try {
@@ -287,9 +302,10 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
SwingUtilities.invokeLater(new Runnable() {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Runnable#run()
*/
+ @Override
public void run() {
AnalyzingDialog.this.setVisible(false);
}
@@ -300,9 +316,10 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
SwingUtilities.invokeLater(new Runnable() {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Runnable#run()
*/
+ @Override
public void run() {
JOptionPane.showMessageDialog(MainFrame.getInstance(), message, title, JOptionPane.ERROR_MESSAGE);
}
@@ -314,14 +331,16 @@ public final class AnalyzingDialog extends FBDialog implements FindBugsProgress
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.FindBugsProgress#predictPassCount(int[])
*/
+ @Override
public void predictPassCount(int[] classesPerPass) {
this.classesPerPass = classesPerPass;
}
+ @Override
public void startArchive(String name) {
// noop
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/ApplyNewFilter.java b/src/gui/edu/umd/cs/findbugs/gui2/ApplyNewFilter.java
index fbfd4b6..bd5f023 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/ApplyNewFilter.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/ApplyNewFilter.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.gui2.FilterActivity.FilterActivityNotifier;
/**
* Updates filters in the current running FindBugs.
- *
+ *
* @author Graham Allan
*/
public class ApplyNewFilter {
@@ -39,14 +39,14 @@ public class ApplyNewFilter {
this.preferencesFrame = preferencesFrame;
this.filterActivityNotifier = filterActivityNotifier;
}
-
+
public void fromMatcher(Matcher matcher) {
if (matcher != null) {
suppressionFilter.addChild(matcher);
-
+
preferencesFrame.updateFilterPanel();
filterActivityNotifier.notifyListeners(FilterListener.Action.FILTERING, null);
}
}
-
+
}
\ No newline at end of file
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/BugAspects.java b/src/gui/edu/umd/cs/findbugs/gui2/BugAspects.java
index 0284c2a..e27a8ca 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/BugAspects.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/BugAspects.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.filter.Matcher;
* could be sent to the main bugset to return all the bugs it contains For
* example, a single bugAspects could be <priority,high> or it could be
* <priority,high>, <designation,must fix>,<class,fishpond>,<package,default>
- *
+ *
* In this implementation, <priority,high>,<designation,unclassified> is
* different from <designation,unclassified>,<priority,high>. (I'm not talking
* about the fact we use the .equals from ArrayList, I'm talking about what a
@@ -40,8 +40,8 @@ import edu.umd.cs.findbugs.filter.Matcher;
* more like Swing's validate, only clearing data if the data is wrong. This
* would save time after changing certain aspects of the tree. Just an idea, I
* wouldn't suggest it unless its absolutely necessary. -Dan
- *
- *
+ *
+ *
* @author All of us
*/
public class BugAspects implements Iterable<BugAspects.SortableValue> {
@@ -65,20 +65,21 @@ public class BugAspects implements Iterable<BugAspects.SortableValue> {
@Override
public String toString() {
- if (lst.isEmpty())
+ if (lst.isEmpty()) {
return edu.umd.cs.findbugs.L10N.getLocalString("tree.bugs", "Bugs") + " (" + count + ")";
- else {
- if (count == -1)
+ } else {
+ if (count == -1) {
return last().value;
- else
+ } else {
return last().key.formatValue(last().value) + " (" + count + ")";
+ }
}
}
/**
* This is how the numbers after the branches contain the number of bugs in
* them, even if they aren't the final branch
- *
+ *
* @param count
*/
public void setCount(int count) {
@@ -114,8 +115,9 @@ public class BugAspects implements Iterable<BugAspects.SortableValue> {
public StackedFilterMatcher getStackedFilterMatcher() {
FilterMatcher[] filters = new FilterMatcher[lst.size()];
- for (int i = 0; i < filters.length; i++)
+ for (int i = 0; i < filters.length; i++) {
filters[i] = new FilterMatcher(lst.get(i));
+ }
StackedFilterMatcher sfm = new StackedFilterMatcher(filters);
return sfm;
}
@@ -141,8 +143,9 @@ public class BugAspects implements Iterable<BugAspects.SortableValue> {
@Override
public boolean equals(Object that) {
- if (!(that instanceof SortableValue))
+ if (!(that instanceof SortableValue)) {
return false;
+ }
SortableValue thatStringPair = ((SortableValue) that);
return this.key.equals(thatStringPair.key) && this.value.equals(thatStringPair.value);
}
@@ -153,6 +156,7 @@ public class BugAspects implements Iterable<BugAspects.SortableValue> {
}
}
+ @Override
public Iterator<SortableValue> iterator() {
return lst.iterator();
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/BugLeafNode.java b/src/gui/edu/umd/cs/findbugs/gui2/BugLeafNode.java
index d94c389..9a83e60 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/BugLeafNode.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/BugLeafNode.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.gui2.BugAspects.SortableValue;
public class BugLeafNode {
- private BugInstance bug;
+ private final BugInstance bug;
BugLeafNode(BugInstance b) {
bug = b;
@@ -44,8 +44,9 @@ public class BugLeafNode {
@Override
public String toString() {
- if (bug.isDead())
+ if (bug.isDead()) {
return "\u2620 " + bug.getMessageWithoutPrefix();
+ }
return bug.getMessageWithoutPrefix();
}
@@ -70,10 +71,11 @@ public class BugLeafNode {
@Override
public boolean equals(Object o) {
- if (!(o instanceof BugLeafNode))
+ if (!(o instanceof BugLeafNode)) {
return false;
- else
+ } else {
return bug == (((BugLeafNode) o).getBug());
+ }
}
@Override
@@ -82,11 +84,13 @@ public class BugLeafNode {
}
public boolean matches(BugAspects aspects) {
- if (aspects.size() == 0)
+ if (aspects.size() == 0) {
return true;
+ }
for (BugAspects.SortableValue strPair : aspects) {
- if (!matches(strPair))
+ if (!matches(strPair)) {
return false;
+ }
}
return true;
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/BugLoader.java b/src/gui/edu/umd/cs/findbugs/gui2/BugLoader.java
index 921e1af..1a78b5c 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/BugLoader.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/BugLoader.java
@@ -19,6 +19,8 @@
package edu.umd.cs.findbugs.gui2;
+import static java.util.Objects.requireNonNull;
+
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
@@ -87,10 +89,10 @@ public class BugLoader {
* @throws IOException
*/
public static BugCollection doAnalysis(@Nonnull Project p, FindBugsProgress progressCallback) throws IOException,
- InterruptedException {
+ InterruptedException {
StringWriter stringWriter = new StringWriter();
BugCollectionBugReporter pcb = new BugCollectionBugReporter(p, new PrintWriter(stringWriter, true));
- pcb.setPriorityThreshold(Priorities.NORMAL_PRIORITY);
+ pcb.setPriorityThreshold(Priorities.LOW_PRIORITY);
IFindBugsEngine fb = createEngine(p, pcb);
fb.setUserPreferences(getUserPreferences());
fb.setProgressCallback(progressCallback);
@@ -156,13 +158,9 @@ public class BugLoader {
return col;
}
- /**
- * @param col
- */
private static void initiateCommunication(SortedBugCollection col) {
Cloud cloud = col.getCloud();
- if (cloud != null)
- cloud.initiateCommunication();
+ cloud.initiateCommunication();
}
public static @CheckForNull
@@ -183,18 +181,21 @@ public class BugLoader {
initiateCommunication(col);
addDeadBugMatcher(col);
- } catch (Exception e) {
+ } catch (Throwable e) {
String msg = SystemProperties.getOSDependentProperty("findbugs.unableToLoadViaURL");
- if (msg == null)
- msg = e.getMessage();
- else try {
- msg = String.format(msg, url);
- } catch (Exception e2) {
+ if (msg == null) {
msg = e.getMessage();
+ } else {
+ try {
+ msg = String.format(msg, url);
+ } catch (Exception e2) {
+ msg = e.getMessage();
+ }
}
JOptionPane.showMessageDialog(mainFrame, "Could not read " + url + "\n" + msg);
- if (SystemProperties.getBoolean("findbugs.failIfUnableToLoadViaURL"))
+ if (SystemProperties.getBoolean("findbugs.failIfUnableToLoadViaURL")) {
System.exit(1);
+ }
}
MainFrame.getInstance().setProjectAndBugCollectionInSwingThread(project, col);
return col;
@@ -204,11 +205,9 @@ public class BugLoader {
if (bugCollection == null || !bugCollection.hasDeadBugs()) {
return;
}
-
+
Filter suppressionMatcher = bugCollection.getProject().getSuppressionFilter();
- if (suppressionMatcher != null) {
- suppressionMatcher.softAdd(LastVersionMatcher.DEAD_BUG_MATCHER);
- }
+ suppressionMatcher.softAdd(LastVersionMatcher.DEAD_BUG_MATCHER);
}
public static @CheckForNull
@@ -249,8 +248,9 @@ public class BugLoader {
// This is done by FBFileChooser.
chooser.setMultiSelectionEnabled(true);
chooser.setDialogTitle(edu.umd.cs.findbugs.L10N.getLocalString("dlg.choose_xmls_ttl", "Choose All XML's To Combine"));
- if (chooser.showOpenDialog(MainFrame.getInstance()) == JFileChooser.CANCEL_OPTION)
+ if (chooser.showOpenDialog(MainFrame.getInstance()) == JFileChooser.CANCEL_OPTION) {
return null;
+ }
SortedBugCollection conglomeration = new SortedBugCollection();
conglomeration.readXML(chooser.getSelectedFiles()[0]);
@@ -260,11 +260,11 @@ public class BugLoader {
SortedBugCollection col = new SortedBugCollection();
col.readXML(f);
conglomeration = (SortedBugCollection) update.mergeCollections(conglomeration, col, false, false);// False
- // means
- // dont
- // show
- // dead
- // bugs
+ // means
+ // dont
+ // show
+ // dead
+ // bugs
}
return conglomeration;
@@ -287,17 +287,17 @@ public class BugLoader {
*/
public static @CheckForNull
BugCollection doAnalysis(@Nonnull Project p) {
- if (p == null)
- throw new NullPointerException("null project");
+ requireNonNull(p, "null project");
RedoAnalysisCallback ac = new RedoAnalysisCallback();
AnalyzingDialog.show(p, ac, true);
- if (ac.finished)
+ if (ac.finished) {
return ac.getBugCollection();
- else
+ } else {
return null;
+ }
}
@@ -310,29 +310,29 @@ public class BugLoader {
*/
public static @CheckForNull
BugCollection redoAnalysisKeepComments(@Nonnull Project p) {
- if (p == null)
- throw new NullPointerException("null project");
-
+ requireNonNull(p, "null project");
+
BugCollection current = MainFrame.getInstance().getBugCollection();
-
+
Update update = new Update();
RedoAnalysisCallback ac = new RedoAnalysisCallback();
AnalyzingDialog.show(p, ac, true);
- if (!ac.finished)
+ if (!ac.finished) {
return null;
- if (current == null)
+ }
+ if (current == null) {
current = ac.getBugCollection();
- else {
+ } else {
current = update.mergeCollections(current, ac.getBugCollection(), true, false);
if (current.hasDeadBugs()) {
addDeadBugMatcher(current);
}
}
- return current;
-
+ return current;
+
}
@@ -347,11 +347,13 @@ public class BugLoader {
volatile boolean finished;
+ @Override
public void analysisFinished(BugCollection b) {
justAnalyzed = b;
finished = true;
}
+ @Override
public void analysisInterrupted() {
finished = false;
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/BugRenderer.java b/src/gui/edu/umd/cs/findbugs/gui2/BugRenderer.java
index 044c969..4f4ce29 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/BugRenderer.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/BugRenderer.java
@@ -43,9 +43,9 @@ public class BugRenderer extends DefaultTreeCellRenderer {
int row, boolean hasFocus) {
Component toReturn = super.getTreeCellRendererComponent(tree, node, selected, expanded, leaf, row, hasFocus);
- if (!(node instanceof BugLeafNode))
+ if (!(node instanceof BugLeafNode)) {
return toReturn;
- else {
+ } else {
BugInstance bug = ((BugLeafNode) node).getBug();
final Color c;
switch (bug.getPriority()) {
@@ -53,16 +53,18 @@ public class BugRenderer extends DefaultTreeCellRenderer {
c = new Color(0.4f, 0.4f, 0.6f);
break;
case Priorities.NORMAL_PRIORITY:
- if (bug.isDead())
+ if (bug.isDead()) {
c = new Color(0.2f, 0.2f, 0.2f);
- else
+ } else {
c = new Color(255, 204, 0);
+ }
break;
case Priorities.HIGH_PRIORITY:
- if (bug.isDead())
+ if (bug.isDead()) {
c = new Color(.65f, 0.2f, 0.2f);
- else
+ } else {
c = new Color(.85f, 0, 0);
+ }
break;
case Priorities.EXP_PRIORITY:
case Priorities.IGNORE_PRIORITY:
@@ -72,6 +74,7 @@ public class BugRenderer extends DefaultTreeCellRenderer {
}
if (leaf) {
Icon icon = new Icon() {
+ @Override
public void paintIcon(Component comp, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
@@ -81,15 +84,17 @@ public class BugRenderer extends DefaultTreeCellRenderer {
g2.drawOval(2, 2, 12, 12);
}
+ @Override
public int getIconWidth() {
return 16;
}
+ @Override
public int getIconHeight() {
return 16;
}
};
- ((BugRenderer) toReturn).setLeafIcon(icon);
+ ((BugRenderer) toReturn).setIcon(icon);
}
return toReturn;
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/BugSet.java b/src/gui/edu/umd/cs/findbugs/gui2/BugSet.java
index 66dbf2f..0d5a36d 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/BugSet.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/BugSet.java
@@ -60,9 +60,9 @@ public class BugSet implements Iterable<BugLeafNode> {
private ArrayList<BugLeafNode> mainList;
- private HashMap<SortableValue, BugSet> doneMap;
+ private final HashMap<SortableValue, BugSet> doneMap;
- private HashMap<SortableValue, Boolean> doneContainsMap;
+ private final HashMap<SortableValue, Boolean> doneContainsMap;
private HashMap<Sortables, String[]> sortablesToStrings;
@@ -108,8 +108,9 @@ public class BugSet implements Iterable<BugLeafNode> {
BugSet(BugCollection bugCollection) {
this(Collections.<BugLeafNode> emptyList());
- for (Iterator<BugInstance> i = bugCollection.iterator(); i.hasNext();)
+ for (Iterator<BugInstance> i = bugCollection.iterator(); i.hasNext();) {
mainList.add(new BugLeafNode(i.next()));
+ }
}
@@ -152,14 +153,16 @@ public class BugSet implements Iterable<BugLeafNode> {
String[] computeDistinctValues(Sortables key) {
- if (key == Sortables.DIVIDER)
+ if (key == Sortables.DIVIDER) {
return EMPTY_STRING_ARRAY;
+ }
Collection<String> list = new HashSet<String>();
for (BugLeafNode p : mainList) {
- if (suppress(p))
+ if (suppress(p)) {
continue;
+ }
BugInstance bug = p.getBug();
String value = key.getFrom(bug);
@@ -178,9 +181,11 @@ public class BugSet implements Iterable<BugLeafNode> {
*/
static int countFilteredBugs() {
int result = 0;
- for (BugLeafNode bug : getMainBugSet().mainList)
- if (suppress(bug))
+ for (BugLeafNode bug : getMainBugSet().mainList) {
+ if (suppress(bug)) {
result++;
+ }
+ }
return result;
}
@@ -209,18 +214,17 @@ public class BugSet implements Iterable<BugLeafNode> {
* with all the Mutable Static bugs in the current set Note also: This query
* will only be performed once, and then stored and reused if the same query
* is used again.
- *
- * @param keyValuePair
- * @return
*/
BugSet query(SortableValue keyValuePair) {
- if (doneMap.containsKey(keyValuePair))
+ if (doneMap.containsKey(keyValuePair)) {
return doneMap.get(keyValuePair);
+ }
ArrayList<BugLeafNode> bugs = new ArrayList<BugLeafNode>();
for (BugLeafNode b : mainList) {
- if (b.matches(keyValuePair))
+ if (b.matches(keyValuePair)) {
bugs.add(b);
+ }
}
BugSet temp = new BugSet(bugs);
@@ -238,59 +242,72 @@ public class BugSet implements Iterable<BugLeafNode> {
Comparator<BugLeafNode> comparator = new Comparator<BugLeafNode>() {
int compare(int one, int two) {
- if (one > two)
+ if (one > two) {
return 1;
- else if (one < two)
+ } else if (one < two) {
return -1;
+ }
return 0;
}
+ @Override
public int compare(BugLeafNode one, BugLeafNode two) {
- if (one == two)
+ if (one == two) {
return 0;
+ }
int result;
for (Sortables i : order) {
result = i.getBugLeafNodeComparator().compare(one, two);
- if (result != 0)
+ if (result != 0) {
return result;
+ }
}
BugInstance bugOne = one.getBug();
BugInstance bugTwo = two.getBug();
result = bugOne.getPrimaryClass().getClassName().compareTo(bugTwo.getPrimaryClass().getClassName());
- if (result != 0)
+ if (result != 0) {
return result;
+ }
SourceLineAnnotation oneSource = bugOne.getPrimarySourceLineAnnotation();
SourceLineAnnotation twoSource = bugTwo.getPrimarySourceLineAnnotation();
result = oneSource.getClassName().compareTo(twoSource.getClassName());
- if (result != 0)
+ if (result != 0) {
return result;
+ }
result = compare(oneSource.getStartLine(), twoSource.getStartLine());
- if (result != 0)
+ if (result != 0) {
return result;
+ }
result = compare(oneSource.getEndLine(), twoSource.getEndLine());
- if (result != 0)
+ if (result != 0) {
return result;
+ }
result = compare(oneSource.getStartBytecode(), twoSource.getStartBytecode());
- if (result != 0)
+ if (result != 0) {
return result;
+ }
result = compare(oneSource.getEndBytecode(), twoSource.getEndBytecode());
return result;
}
};
- Collections.sort(mainList, comparator);
-
- if (SystemProperties.ASSERTIONS_ENABLED)
- for(int i = 0; i < mainList.size(); i++) {
- BugLeafNode nodeI = mainList.get(i);
-
- for(int j = i+1; j < mainList.size(); j++) {
- BugLeafNode nodeJ = mainList.get(j);
- if (comparator.compare(nodeI, nodeJ) > 0)
- throw new AssertionError(
- String.format("bug list isn't consistently sorted (%d:%s) vs. (%d:%s)",
- i, nodeI.getBug().getInstanceHash(), j, nodeJ.getBug().getInstanceHash()));
- }}
+ ArrayList<BugLeafNode> copy = new ArrayList<BugLeafNode>(mainList);
+ Collections.sort(copy, comparator);
+ mainList = copy;
+
+ if (SystemProperties.ASSERTIONS_ENABLED) {
+ for(int i = 0; i < mainList.size(); i++) {
+ BugLeafNode nodeI = mainList.get(i);
+
+ for(int j = i+1; j < mainList.size(); j++) {
+ BugLeafNode nodeJ = mainList.get(j);
+ if (comparator.compare(nodeI, nodeJ) > 0) {
+ throw new AssertionError(
+ String.format("bug list isn't consistently sorted (%d:%s) vs. (%d:%s)",
+ i, nodeI.getBug().getInstanceHash(), j, nodeJ.getBug().getInstanceHash()));
+ }
+ }}
+ }
@@ -304,8 +321,9 @@ public class BugSet implements Iterable<BugLeafNode> {
* @return true if a bug leaf from filterNoCache() matches the pair
*/
public boolean contains(SortableValue keyValuePair) {
- if (doneContainsMap.containsKey(keyValuePair))
+ if (doneContainsMap.containsKey(keyValuePair)) {
return doneContainsMap.get(keyValuePair);
+ }
for (BugLeafNode p : filteredBugsCached().mainList) {
if (p.matches(keyValuePair)) {
@@ -341,6 +359,7 @@ public class BugSet implements Iterable<BugLeafNode> {
return mainList.get(index);
}
+ @Override
public Iterator<BugLeafNode> iterator() {
return mainList.iterator();
}
@@ -351,16 +370,18 @@ public class BugSet implements Iterable<BugLeafNode> {
this.mainList = new ArrayList<BugLeafNode>(filteredSet);
doneMap = new HashMap<SortableValue, BugSet>();
doneContainsMap = new HashMap<SortableValue, Boolean>();
- if (cacheSortables)
+ if (cacheSortables) {
cacheSortables();
+ }
}
private BugSet filteredBugsNoCache() {
ArrayList<BugLeafNode> people = new ArrayList<BugLeafNode>();
for (BugLeafNode p : mainList) {
- if (!suppress(p))
+ if (!suppress(p)) {
people.add(p);
+ }
}
return new BugSet(people, false);
}
@@ -372,16 +393,18 @@ public class BugSet implements Iterable<BugLeafNode> {
}
private BugSet filteredBugsCached() {
- if (cache == null)
+ if (cache == null) {
cache = filteredBugsNoCache();
+ }
return cache;
}
public BugSet getBugsMatchingFilter(Matcher m) {
ArrayList<BugLeafNode> people = new ArrayList<BugLeafNode>();
for (BugLeafNode p : mainList) {
- if (!(m.match(p.getBug())))
+ if (!(m.match(p.getBug()))) {
people.add(p);
+ }
}
return new BugSet(people, false);
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/BugTreeModel.java b/src/gui/edu/umd/cs/findbugs/gui2/BugTreeModel.java
index b0d5e5a..cbe5b6c 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/BugTreeModel.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/BugTreeModel.java
@@ -86,7 +86,7 @@ import edu.umd.cs.findbugs.gui2.BugAspects.SortableValue;
public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeExpansionListener {
private BugAspects root = new BugAspects();
- private SorterTableColumnModel st;
+ private final SorterTableColumnModel st;
private BugSet bugSet;
@@ -115,29 +115,34 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
BugSet.setAsRootAndCache(this.bugSet);
root.setCount(data.size());
FilterActivity.addFilterListener(bugTreeFilterListener);
- if (DEBUG)
+ if (DEBUG) {
this.addTreeModelListener(new TreeModelListener() {
+ @Override
public void treeNodesChanged(TreeModelEvent arg0) {
System.out.println("Tree nodes changed");
System.out.println(" " + arg0.getTreePath());
}
+ @Override
public void treeNodesInserted(TreeModelEvent arg0) {
System.out.println("Tree nodes inserted");
System.out.println(" " + arg0.getTreePath());
}
+ @Override
public void treeNodesRemoved(TreeModelEvent arg0) {
System.out.println("Tree nodes removed");
System.out.println(" " + arg0.getTreePath());
}
+ @Override
public void treeStructureChanged(TreeModelEvent arg0) {
System.out.println("Tree structure changed");
System.out.println(" " + arg0.getTreePath());
}
});
+ }
}
public BugTreeModel(BugTreeModel other) {
@@ -159,10 +164,12 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
bugSet.clearCache();
}
+ @Override
public Object getRoot() {
return root;
}
+ @Override
public Object getChild(Object o, int index) {
int childCount = getChildCount(o);
if (index < 0 || index >= childCount) {
@@ -206,26 +213,30 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
}
}
+ @Override
public int getChildCount(Object o) {
- if (!(o instanceof BugAspects))
+ if (!(o instanceof BugAspects)) {
return 0;
+ }
BugAspects a = (BugAspects) o;
- if (st.getOrderBeforeDivider().size() == 0 && a.size() == 0)// If its
- // the root
- // and we
- // aren't
- // sorting
- // by
- // anything
+ if (st.getOrderBeforeDivider().size() == 0 && a.size() == 0) {
+ // the root
+ // and we
+ // aren't
+ // sorting
+ // by
+ // anything
return bugSet.size();
+ }
- if ((a.size() == 0) || (a.last().key != st.getOrderBeforeDivider().get(st.getOrderBeforeDivider().size() - 1)))
+ if ((a.size() == 0) || (a.last().key != st.getOrderBeforeDivider().get(st.getOrderBeforeDivider().size() - 1))) {
return enumsThatExist(a).size();
- else
+ } else {
return bugSet.query(a).size();
+ }
}
/*
@@ -243,35 +254,41 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
}
Sortables key;
- if (a.size() == 0)
+ if (a.size() == 0) {
key = orderBeforeDivider.get(0);
- else {
+ } else {
Sortables lastKey = a.last().key;
int index = orderBeforeDivider.indexOf(lastKey);
- if (index + 1 < orderBeforeDivider.size())
+ if (index + 1 < orderBeforeDivider.size()) {
key = orderBeforeDivider.get(index + 1);
- else
+ } else {
key = lastKey;
+ }
}
String[] all = key.getAll(bugSet.query(a));
ArrayList<SortableValue> result = new ArrayList<SortableValue>(all.length);
- for (String i : all)
+ for (String i : all) {
result.add(new SortableValue(key, i));
+ }
return result;
}
+ @Override
public boolean isLeaf(Object o) {
return (o instanceof BugLeafNode);
}
+ @Override
public void valueForPathChanged(TreePath arg0, Object arg1) {
}
+ @Override
public int getIndexOfChild(Object parent, Object child) {
- if (parent == null || child == null || isLeaf(parent))
+ if (parent == null || child == null || isLeaf(parent)) {
return -1;
+ }
if (isLeaf(child)) {
return bugSet.query((BugAspects) parent).indexOf((BugLeafNode) child);
@@ -282,27 +299,33 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
}
}
+ @Override
public void addTreeModelListener(TreeModelListener listener) {
listeners.add(listener);
}
+ @Override
public void removeTreeModelListener(TreeModelListener listener) {
listeners.remove(listener);
}
+ @Override
public void columnAdded(TableColumnModelEvent e) {
sortsAddedOrRemoved = true;
// rebuild();
}
+ @Override
public void columnRemoved(TableColumnModelEvent e) {
sortsAddedOrRemoved = true;
// rebuild();
}
+ @Override
public void columnMoved(final TableColumnModelEvent evt) {
- if (evt.getFromIndex() == evt.getToIndex())
+ if (evt.getFromIndex() == evt.getToIndex()) {
return;
+ }
sortOrderChanged = true;
// rebuild();
}
@@ -323,8 +346,9 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
*
*/
public void rebuild() {
- if (TRACE)
+ if (TRACE) {
System.out.println("rebuilding bug tree model");
+ }
NewFilterFromBug.closeAll();
@@ -336,14 +360,16 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
// As of now, it should be impossible to interrupt a rebuilding thread,
// in another version this may change, so this if statement check is
// left in, even though it should always be true.
- if (rebuildingThread == null)
+ if (rebuildingThread == null) {
setOldSelectedBugs();
+ }
Debug.println("Please Wait called right before starting rebuild thread");
mainFrame.acquireDisplayWait();
rebuildingThread = edu.umd.cs.findbugs.util.Util.runInDameonThread(new Runnable() {
BugTreeModel newModel;
+ @Override
public void run() {
try {
newModel = new BugTreeModel(BugTreeModel.this);
@@ -353,6 +379,7 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
} finally {
rebuildingThread = null;
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
if (newModel != null) {
JTree newTree = new JTree(newModel);
@@ -370,15 +397,17 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
}
public void crawl(final ArrayList<BugAspects> path, final int depth) {
- for (int i = 0; i < getChildCount(path.get(path.size() - 1)); i++)
+ for (int i = 0; i < getChildCount(path.get(path.size() - 1)); i++) {
if (depth > 0) {
ArrayList<BugAspects> newPath = new ArrayList<BugAspects>(path);
newPath.add((BugAspects) getChild(path.get(path.size() - 1), i));
crawl(newPath, depth - 1);
} else {
- for (TreeModelListener l : listeners)
+ for (TreeModelListener l : listeners) {
l.treeStructureChanged(new TreeModelEvent(this, path.toArray()));
+ }
}
+ }
}
void openPreviouslySelected(List<BugLeafNode> selected) {
@@ -388,8 +417,9 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
try {
BugInstance bug = b.getBug();
TreePath path = getPathToBug(bug);
- if (path == null)
+ if (path == null) {
continue;
+ }
Debug.printf("Opening %s\n", path);
mainFrame.getTree().expandPath(path.getParentPath());
mainFrame.getTree().addSelectionPath(path);
@@ -409,7 +439,7 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
public void crawlToOpen(TreePath path, ArrayList<BugLeafNode> bugLeafNodes, ArrayList<TreePath> treePaths) {
for (int i = 0; i < getChildCount(path.getLastPathComponent()); i++) {
- if (!isLeaf(getChild(path.getLastPathComponent(), i)))
+ if (!isLeaf(getChild(path.getLastPathComponent(), i))) {
for (BugLeafNode p : bugLeafNodes) {
if (p.matches((BugAspects) getChild(path.getLastPathComponent(), i))) {
tree.expandPath(path);
@@ -417,7 +447,7 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
break;
}
}
- else {
+ } else {
for (BugLeafNode b : bugLeafNodes) {
if (getChild(path.getLastPathComponent(), i).equals(b)) {
tree.expandPath(path);
@@ -431,30 +461,33 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
public static boolean TRACE = false;
public void resetData()// FIXME: Does this need a setAsRootAndCache() on the
- // new BugSet?
+ // new BugSet?
{
- if (TRACE)
+ if (TRACE) {
System.out.println("Reseting data in bug tree model");
+ }
bugSet = new BugSet(bugSet);
}
FilterListener bugTreeFilterListener = new MyFilterListener();
class MyFilterListener implements FilterListener {
+ @Override
public void clearCache() {
- if (TRACE)
+ if (TRACE) {
System.out.println("clearing cache in bug tree model");
+ }
resetData();
BugSet.setAsRootAndCache(bugSet);// FIXME: Should this be in
- // resetData? Does this allow our
- // main list to not be the same as
- // the data in our tree?
+ // resetData? Does this allow our
+ // main list to not be the same as
+ // the data in our tree?
root.setCount(bugSet.size());
rebuild();
}
- }
+ }
void treeNodeChanged(TreePath path) {
Debug.println("Tree Node Changed: " + path);
@@ -480,8 +513,9 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
// Create an array of BugAspects of lengths from one to the full
// BugAspect list of the bugInstance
BugAspects[] toBug = new BugAspects[order.size()];
- for (int i = 0; i < order.size(); i++)
+ for (int i = 0; i < order.size(); i++) {
toBug[i] = new BugAspects();
+ }
for (int x = 0; x < order.size(); x++) {
for (int y = 0; y <= x; y++) {
@@ -496,26 +530,28 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
if (index == -1) {
if (MainFrame.GUI2_DEBUG)
+ {
System.err.println("Node does not exist in the tree");// For
- // example,
- // not
- // a
- // bug
- // bugs
- // are
- // filtered,
- // they
- // set
- // a
- // bug
- // to
- // be
- // not
- // a
- // bug
- // it
- // filters
- // out
+ }
+ // example,
+ // not
+ // a
+ // bug
+ // bugs
+ // are
+ // filtered,
+ // they
+ // set
+ // a
+ // bug
+ // to
+ // be
+ // not
+ // a
+ // bug
+ // it
+ // filters
+ // out
return null;
}
@@ -524,8 +560,9 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
// Using a hashlist to store bugs in BugSet will make getIndexOfChild
// Waaaaaay faster, thus making this O(1) (avg case)
int index = getIndexOfChild(pathToBug.getLastPathComponent(), new BugLeafNode(b));
- if (index == -1)
+ if (index == -1) {
return null;
+ }
pathToBug = pathToBug.pathByAddingChild(getChild(pathToBug.getLastPathComponent(), index));
return pathToBug;
@@ -546,25 +583,32 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
Debug.println("The BugTreeModel has been DELETED! This means there are no more references to it, and its finally off all of the stupid listener lists");
}
+ @Override
public void columnMarginChanged(ChangeEvent arg0) {
}
+ @Override
public void columnSelectionChanged(ListSelectionEvent arg0) {
}
+ @Override
public void treeExpanded(TreeExpansionEvent event) {
}
+ @Override
public void treeCollapsed(TreeExpansionEvent event) {
}
private void setOldSelectedBugs() {
selectedBugLeafNodes.clear();
- if (tree.getSelectionPaths() != null) // Who the cussword wrote this API
- // anyway?
- for (TreePath path : tree.getSelectionPaths())
- if (isLeaf(path.getLastPathComponent()))
+ if (tree.getSelectionPaths() != null) {
+ // anyway?
+ for (TreePath path : tree.getSelectionPaths()) {
+ if (isLeaf(path.getLastPathComponent())) {
selectedBugLeafNodes.add((BugLeafNode) path.getLastPathComponent());
+ }
+ }
+ }
}
ArrayList<BugLeafNode> getOldSelectedBugs() {
@@ -580,10 +624,11 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
}
public TreeModelEvent restructureBranch(ArrayList<String> stringsToBranch, boolean removing) throws BranchOperationException {
- if (removing)
+ if (removing) {
return branchOperations(stringsToBranch, TreeModification.REMOVERESTRUCTURE);
- else
+ } else {
return branchOperations(stringsToBranch, TreeModification.INSERTRESTRUCTURE);
+ }
}
public TreeModelEvent insertBranch(ArrayList<String> stringsToBranch) throws BranchOperationException {
@@ -630,14 +675,15 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
throws BranchOperationException {
TreeModelEvent event = null;
- if (whatToDo == TreeModification.REMOVE)
+ if (whatToDo == TreeModification.REMOVE) {
Debug.println("Removing a branch......");
- else if (whatToDo == TreeModification.INSERT)
+ } else if (whatToDo == TreeModification.INSERT) {
Debug.println("Inserting a branch......");
- else if (whatToDo == TreeModification.REMOVERESTRUCTURE)
+ } else if (whatToDo == TreeModification.REMOVERESTRUCTURE) {
Debug.println("Restructuring from branch to remove......");
- else if (whatToDo == TreeModification.INSERTRESTRUCTURE)
+ } else if (whatToDo == TreeModification.INSERTRESTRUCTURE) {
Debug.println("Restructuring from branch to insert......");
+ }
Debug.println(stringsToBranch);
if (whatToDo == TreeModification.INSERT || whatToDo == TreeModification.INSERTRESTRUCTURE) {
@@ -671,12 +717,14 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
// break;
}
}
- if (pathToBranch.getParentPath() != null)
+ if (pathToBranch.getParentPath() != null) {
while (getChildCount(pathToBranch.getParentPath().getLastPathComponent()) == 1) {
- if (pathToBranch.getParentPath().getLastPathComponent().equals(root))
+ if (pathToBranch.getParentPath().getLastPathComponent().equals(root)) {
break;
+ }
pathToBranch = pathToBranch.getParentPath();
}
+ }
Debug.println(pathToBranch);
if (whatToDo == TreeModification.INSERT) {
@@ -696,8 +744,9 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
event = new TreeModelEvent(this, pathToBranch);
}
- if (whatToDo == TreeModification.REMOVE || whatToDo == TreeModification.REMOVERESTRUCTURE)
+ if (whatToDo == TreeModification.REMOVE || whatToDo == TreeModification.REMOVERESTRUCTURE) {
resetData();
+ }
return event;
}
@@ -709,9 +758,9 @@ public class BugTreeModel implements TreeModel, TableColumnModelListener, TreeEx
}
resetData();
for (TreeModelListener l : listeners) {
- if (whatToDo == TreeModification.REMOVE)
+ if (whatToDo == TreeModification.REMOVE) {
l.treeNodesRemoved(event);
- else if (whatToDo == TreeModification.INSERT) {
+ } else if (whatToDo == TreeModification.INSERT) {
l.treeNodesInserted(event);
l.treeStructureChanged(new TreeModelEvent(this, new TreePath(event.getPath()).pathByAddingChild(event
.getChildren()[0])));
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/CheckBoxList.java b/src/gui/edu/umd/cs/findbugs/gui2/CheckBoxList.java
index ed175a7..9749587 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/CheckBoxList.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/CheckBoxList.java
@@ -33,13 +33,13 @@ import javax.swing.border.EmptyBorder;
/**
* A list of JCheckBoxes! How convenient!
- *
+ *
* Adapted from: http://www.devx.com/tips/Tip/5342
- *
+ *
* @author Trevor Harmon
*/
@SuppressWarnings("serial")
-public class CheckBoxList extends JList {
+public class CheckBoxList<E> extends JList<E> {
private static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public CheckBoxList() {
@@ -61,7 +61,7 @@ public class CheckBoxList extends JList {
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
- public CheckBoxList(Object[] list) {
+ public CheckBoxList(E[] list) {
this();
setListData(list);
}
@@ -70,12 +70,14 @@ public class CheckBoxList extends JList {
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
- for (int i = 0; i < getModel().getSize(); i++)
+ for (int i = 0; i < getModel().getSize(); i++) {
((JCheckBox) getModel().getElementAt(i)).setEnabled(enabled);
+ }
}
- protected class CellRenderer implements ListCellRenderer {
- public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+ protected class CellRenderer implements ListCellRenderer<E> {
+ @Override
+ public Component getListCellRendererComponent(JList<? extends E> list, E value, int index, boolean isSelected,
boolean cellHasFocus) {
JCheckBox checkbox = (JCheckBox) value;
checkbox.setBackground(isSelected ? getSelectionBackground() : getBackground());
@@ -87,5 +89,8 @@ public class CheckBoxList extends JList {
checkbox.setBorder(isSelected ? UIManager.getBorder("List.focusCellHighlightBorder") : noFocusBorder);
return checkbox;
}
+
+
+
}
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/CloudCommentsPane.java b/src/gui/edu/umd/cs/findbugs/gui2/CloudCommentsPane.java
index d57f5a5..9e52b2f 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/CloudCommentsPane.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/CloudCommentsPane.java
@@ -1,1050 +1,1101 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2010-2013 University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.gui2;
-
-import static edu.umd.cs.findbugs.util.Util.nullSafeEquals;
-
-import java.awt.BorderLayout;
-import java.awt.CardLayout;
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.Font;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.awt.Toolkit;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.text.DateFormat;
-import java.text.MessageFormat;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.swing.BorderFactory;
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.JButton;
-import javax.swing.JComponent;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
-import javax.swing.border.EmptyBorder;
-import javax.swing.border.EtchedBorder;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-
-import edu.umd.cs.findbugs.BugCollection;
-import edu.umd.cs.findbugs.BugInstance;
-import edu.umd.cs.findbugs.DetectorFactoryCollection;
-import edu.umd.cs.findbugs.I18N;
-import edu.umd.cs.findbugs.L10N;
-import edu.umd.cs.findbugs.cloud.Cloud;
-import edu.umd.cs.findbugs.cloud.Cloud.SigninState;
-import edu.umd.cs.findbugs.cloud.Cloud.UserDesignation;
-import edu.umd.cs.findbugs.cloud.CloudPlugin;
-import edu.umd.cs.findbugs.util.Util;
-
- at edu.umd.cs.findbugs.annotations.SuppressFBWarnings({"SE_TRANSIENT_FIELD_NOT_RESTORED", "SE_BAD_FIELD", "SE_BAD_FIELD_STORE"})
-public abstract class CloudCommentsPane extends JPanel {
-
- private static final String MSG_REVIEW = L10N.getLocalString("dlg.cloud.add_review", "Click to add review...");
- private static final String MSG_REVIEW_MULTI = L10N.getLocalString("dlg.cloud.add_review_multi",
- "Click to add review to {0} bugs...");
- private static final String MSG_OVERWRITE_REVIEW = L10N.getLocalString("dlg.cloud.ovwrt_review_multi",
- "Click to overwrite {0} reviews...");
-
- private JTextArea cloudReportPane;
- protected JComponent cancelLink;
- protected JComponent signInOutLink;
- private JTextArea commentBox;
- private JButton submitCommentButton;
- private WideComboBox designationCombo;
- private JPanel mainPanel;
- private JScrollPane _cloudReportScrollPane;
- protected JLabel titleLabel;
- protected JTextArea cloudDetailsLabel;
- private JPanel dumbPanelSignInOutLink;
- private JLabel lastSavedLabel;
- private JPanel cards;
- private JButton bulkReviewButton;
- private JLabel warningLabel;
-
- protected BugCollection _bugCollection;
- protected BugInstance _bugInstance;
- private BugAspects _bugAspects;
-
- private final Executor backgroundExecutor = Executors.newCachedThreadPool();
-
- private final Cloud.CloudStatusListener _cloudStatusListener = new MyCloudStatusListener();
- private Cloud lastCloud = null;
- private Font plainCommentFont;
- private String lastCommentText = null;
- private Set<BugInstance> lastBugsEdited = Collections.emptySet();
- private boolean clickedBulkReview = false;
-
-
- private void addNotInCloudCard() {
- final JPanel panel5 = new JPanel();
- cards.add(panel5, "NOT_IN_CLOUD");
- }
-
- public CloudCommentsPane() {
- $$$setupUI$$$();
- addNotInCloudCard();
- cloudReportPane.setBackground(this.getBackground());
- cloudReportPane.setBorder(new EmptyBorder(0, 0, 0, 0));
- _cloudReportScrollPane.setBorder(new EmptyBorder(0, 0, 0, 0));
-
-// designationCombo.setPreferredSize(new Dimension(300, 20));
- commentBox.addMouseListener(new MouseAdapter() {
- @Override
- public void mousePressed(MouseEvent e) {
- commentBoxClicked();
- }
- });
- commentBox.getDocument().addDocumentListener(new DocumentListener() {
- public void insertUpdate(DocumentEvent e) {
- changed();
- }
-
- public void removeUpdate(DocumentEvent e) {
- changed();
- }
-
- public void changedUpdate(DocumentEvent e) {
- changed();
- }
-
- private void changed() {
- updateSaveButton();
- }
- });
- commentBox.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
-
- dumbPanelSignInOutLink.setPreferredSize(null);
-
- setLayout(new BorderLayout());
- add(mainPanel, BorderLayout.CENTER);
-
- designationCombo.removeAllItems();
- final List<String> userDesignationKeys = I18N.instance().getUserDesignationKeys(true);
- for (final String designation : userDesignationKeys) {
- designationCombo.addItem(I18N.instance().getUserDesignation(designation));
- }
- designationCombo.addItem(null);
- designationCombo.setRenderer(new DefaultListCellRenderer() {
- @Override
- public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
- boolean cellHasFocus) {
- Component real = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
- if (value == null)
- return real;
- if (index == -1)
- return real;
- JPanel panel = new JPanel(new GridBagLayout());
- panel.setBorder(new EmptyBorder(3, 3, 3, 3));
- int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- GridBagConstraints gbc = new GridBagConstraints();
- gbc.fill = GridBagConstraints.BOTH;
- gbc.weightx = 1;
- gbc.anchor = GridBagConstraints.WEST;
- panel.add(real, gbc);
-
- gbc.weightx = 0;
- gbc.anchor = GridBagConstraints.EAST;
- gbc.insets = new Insets(0, 10, 0, 0);
- JLabel label = new JLabel(KeyEvent.getKeyModifiersText(mask) + "-" + (index + 1));
- label.setForeground(Color.GRAY);
-// Font font = label.getFont();
-// label.setFont(font.deriveFont(font.getSize() - 2f));
- panel.add(label, gbc);
- panel.setBackground(real.getBackground());
- return panel;
- }
- });
- designationCombo.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (!updatingHeader) {
- int selectedIndex = designationCombo.getSelectedIndex();
- if (selectedIndex >= 0)
- setDesignation(userDesignationKeys.get(selectedIndex));
- }
- }
- });
-
-// commentEntryPanel.setVisible(false);
- submitCommentButton.addActionListener(new ActionListener() {
- public void actionPerformed(final ActionEvent e) {
- submitComment(CloudCommentsPane.this.getSelectedBugs());
- }
- });
- cloudDetailsLabel.setBackground(null);
- cloudDetailsLabel.setBorder(null);
- plainCommentFont = commentBox.getFont().deriveFont(Font.PLAIN);
- cloudReportPane.setFont(plainCommentFont);
-// cloudReportPane.setEditorKit(new HTMLEditorKit());
-// ((HTMLEditorKit) cloudReportPane.getDocument()).getStyleSheet().addRule("body { font-");
-
- setDefaultComment(MSG_REVIEW);
- commentBox.addFocusListener(new FocusListener() {
- public void focusGained(FocusEvent e) {
- commentBox.setForeground(null);
- commentBox.setFont(plainCommentFont);
- if (isDefaultComment(commentBox.getText())) {
- resetCommentBoxFont();
- setCommentText("");
- }
- }
-
- public void focusLost(FocusEvent e) {
- String text = commentBox.getText();
- if (isDefaultComment(text)) {
- refresh();
- } else if (text.equals(lastCommentText)) {
- if (text.trim().length() == 0)
- refresh();
- } else {
- submitComment(CloudCommentsPane.this.getSelectedBugs());
- resetCommentBoxFont();
- }
- }
- });
- commentBox.addKeyListener(new KeyAdapter() {
- @Override
- public void keyPressed(KeyEvent e) {
- if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
- cancelClicked();
- } else if (e.getKeyCode() == KeyEvent.VK_ENTER && (e.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) != 0) {
- submitComment(CloudCommentsPane.this.getSelectedBugs());
- }
- }
- });
- submitCommentButton.setToolTipText("Submit review [Enter]");
- cancelLink.setToolTipText("Cancel [Esc]");
-
- bulkReviewButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- clickedBulkReview = true;
- refresh();
- }
- });
-
- setCanAddComments(false, false);
- setLastSaved(0);
-
- updateBugCommentsView();
- }
-
- private boolean isDefaultComment(String text) {
- if (text.equals(MSG_REVIEW)) return true;
- try {
- new MessageFormat(MSG_REVIEW_MULTI).parse(text);
- return true; // didn't throw an exception
- } catch (ParseException e) {
- }
- try {
- new MessageFormat(MSG_OVERWRITE_REVIEW).parse(text);
- return true; // didn't throw an exception
- } catch (ParseException e) {
- }
- return false;
- }
-
- private void updateSaveButton() {
- boolean changed = commentWasChanged();
- submitCommentButton.setEnabled(changed);
- submitCommentButton.setText(changed
- ? L10N.getLocalString("dlg.save_btn", "Save")
- : L10N.getLocalString("dlg.saved_btn", "Saved"));
- cancelLink.setEnabled(false/*changed*/);
- }
-
- private void setCommentText(String t) {
- lastCommentText = t;
- if (!commentBox.getText().equals(t))
- commentBox.setText(t);
- }
-
- private void resetCommentBoxFont() {
- commentBox.setFont(plainCommentFont);
- commentBox.setForeground(null);
- }
-
- private void setDefaultComment(String defaultComment) {
- setCommentText(defaultComment);
- commentBox.setForeground(Color.DARK_GRAY);
- commentBox.setFont(plainCommentFont.deriveFont(Font.ITALIC));
- }
-
- private void createUIComponents() {
- setupLinksOrButtons();
- }
-
- protected abstract void setupLinksOrButtons();
-
-
- private void applyToBugs(final BugAction bugAction) {
- Executor executor = backgroundExecutor;
-
- final AtomicInteger shownErrorMessages = new AtomicInteger(0);
- for (final BugInstance bug : getSelectedBugs())
- executor.execute(new Runnable() {
- public void run() {
- if (shownErrorMessages.get() > 5) {
- // 5 errors? let's just stop trying.
- return;
- }
- try {
- bugAction.execute(bug);
- } catch (Throwable e) {
- if (shownErrorMessages.addAndGet(1) > 5) {
- return;
- }
- JOptionPane.showMessageDialog(CloudCommentsPane.this,
- "Error while submitting cloud reviews:\n"
- + e.getClass().getSimpleName() + ": " + e.getMessage(),
- "Review Submission Error", JOptionPane.ERROR_MESSAGE);
- }
- }
- });
- }
-
- protected void signInOrOutClicked() {
- if (_bugCollection != null) {
- final Cloud cloud = _bugCollection.getCloud();
- if (cloud.getPlugin().getId().equals("edu.umd.cs.findbugs.cloud.doNothingCloud")) {
- changeClicked();
- }
- SigninState state = cloud.getSigninState();
- if (state == SigninState.SIGNED_IN) {
- backgroundExecutor.execute(new Runnable() {
- public void run() {
- cloud.signOut();
- refresh();
- }
- });
- refresh();
- } else if (state.couldSignIn()) {
- backgroundExecutor.execute(new Runnable() {
- public void run() {
- try {
- cloud.signIn();
- } catch (Exception e) {
- _bugCollection
- .getProject()
- .getGuiCallback()
- .showMessageDialog(
- "The FindBugs Cloud could not be contacted at this time.\n\n"
- + Util.getNetworkErrorMessage(e));
- }
- refresh();
- }
- });
- refresh();
-
- }
- }
- }
-
- protected void commentBoxClicked() {
- if (commentWasChanged())
- return;
- setCanAddComments(false, true);
- CommentInfo commentInfo = new CommentInfo().invoke();
- boolean sameText = commentInfo.isSameText();
- String txt = commentInfo.getTxt();
- if (!sameText)
- txt = "";
- if (txt == null || txt.trim().length() == 0)
- txt = "";
- resetCommentBoxFont();
- boolean sameTextInBox = commentBox.getText().equals(txt);
- setCommentText(txt);
- int start = commentBox.getSelectionStart();
- int end = commentBox.getSelectionEnd();
- if (!commentBox.hasFocus() && (!sameTextInBox || start != 0 || end != txt.length())) {
- commentBox.setSelectionStart(0);
- commentBox.setSelectionEnd(txt.length());
- }
- updateSaveButton();
- }
-
- private boolean commentWasChanged() {
- String text = commentBox.getText();
- boolean b = !isDefaultComment(text);
-// boolean b1 = text.trim().equals("");
- boolean b3 = text.equals(lastCommentText);
- return b && !b3;
- }
-
- public boolean canSetDesignations() {
- List<BugInstance> bugs = getSelectedBugs();
- if (bugs.isEmpty())
- return true;
- Cloud plugin = _bugCollection != null ? _bugCollection.getCloud() : null;
- if (plugin == null)
- return false;
- for(BugInstance b : bugs)
- if (plugin.canStoreUserAnnotation(b))
- return true;
- return false;
- }
-
- public void setDesignation(final String designationKey) {
-
-// List<BugInstance> selectedBugs = getSelectedBugs();
-// if (selectedBugs.size() > 1)
-// if (!confirmAnnotation(selectedBugs))
-// return;
- final AtomicBoolean stop = new AtomicBoolean(false);
- applyToBugs(new BugAction() {
- public void execute(BugInstance bug) {
- if (stop.get())
- return;
- String oldValue = bug.getUserDesignationKey();
- String key = designationKey;
- if (key.equals(oldValue))
- return;
- Cloud plugin = _bugCollection != null ? _bugCollection.getCloud() : null;
- if (plugin != null && key.equals("I_WILL_FIX") && plugin.supportsClaims()) {
- String claimedBy = plugin.claimedBy(bug);
- if (claimedBy != null && !plugin.getUser().equals(claimedBy)) {
- int result = JOptionPane.showConfirmDialog(null,
- bug.getMessage() + "\n"
- + claimedBy + " has already said they will fix this issue\n"
- + "Do you want to also be listed as fixing this issue?\n"
- + "If so, please coordinate with " + claimedBy,
- "Issue already claimed", JOptionPane.YES_NO_CANCEL_OPTION);
- if (result == JOptionPane.CANCEL_OPTION) {
- stop.set(true);
- return;
- }
- if (result != JOptionPane.YES_OPTION)
- key = "MUST_FIX";
- }
- }
- changeDesignationOfBugRightNow(bug, key);
- refresh();
- }
- });
- }
-
- @SuppressWarnings({"UnusedDeclaration"})
- private void submitComment(List<BugInstance> selectedBugs) {
- String comment = commentBox.getText();
- if (isDefaultComment(comment))
- comment = "";
- // if (selectedBugs.size() > 1)
- // if (!confirmAnnotation(selectedBugs))
- // return;
- if (designationCombo.getSelectedItem() != null) {
- final int index = designationCombo.getSelectedIndex();
- final String choice;
- if (index == -1) {
- choice = UserDesignation.UNCLASSIFIED.name();
- } else {
- choice = I18N.instance().getUserDesignationKeys(true).get(index);
- }
- setDesignation(choice);
- }
- final String finalComment = comment;
- applyToBugs(new BugAction() {
- public void execute(BugInstance bug) {
- bug.setAnnotationText(finalComment, _bugCollection);
- refresh();
- setLastSaved(System.currentTimeMillis());
- }
- });
-
- refresh();
-
- setCanAddComments(true, false);
- commentBox.requestFocus();
- }
-
- private void setLastSaved(long date) {
- if (date > 0)
- lastSavedLabel.setText("saved " + DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT)
- .format(new Date(date)));
- else
- lastSavedLabel.setText("");
- }
-
- protected void cancelClicked() {
- setDefaultComment(lastCommentText);
-// commentEntryPanel.setVisible(false);
- setCanAddComments(true, false);
- }
-
- private List<BugInstance> getSelectedBugs() {
- if (_bugInstance != null)
- return Collections.singletonList(_bugInstance);
- if (_bugAspects != null) {
- List<BugInstance> set = new ArrayList<BugInstance>();
- for (BugLeafNode node : _bugAspects.getMatchingBugs(BugSet.getMainBugSet())) {
- if (!BugSet.suppress(node))
- set.add(node.getBug());
- }
- return set;
- }
- return Collections.emptyList();
- }
-
- private boolean hasSelectedBugs() {
- return _bugInstance != null || _bugAspects != null;
- }
-
- protected void changeClicked() {
- final List<CloudPlugin> plugins = new ArrayList<CloudPlugin>();
- final List<String> descriptions = new ArrayList<String>();
- List<CloudPlugin> clouds = new ArrayList<CloudPlugin>(DetectorFactoryCollection.instance().getRegisteredClouds().values());
- Collections.sort(clouds, new Comparator<CloudPlugin>() {
- public int compare(CloudPlugin o1, CloudPlugin o2) {
- return o1.getDescription().compareToIgnoreCase(o2.getDescription());
- }
- });
- for (final CloudPlugin plugin : clouds) {
- final boolean disabled = isDisabled(plugin);
- if (!disabled && !plugin.isHidden()) {
- descriptions.add(plugin.getDescription());
- plugins.add(plugin);
- }
- }
- showCloudChooser(plugins, descriptions);
- }
-
- protected abstract boolean isDisabled(CloudPlugin plugin);
-
- protected abstract void showCloudChooser(List<CloudPlugin> plugins, List<String> descriptions);
-
- protected void changeCloud(String newCloudId) {
- final String oldCloudId = _bugCollection.getCloud().getPlugin().getId();
- if (!oldCloudId.equals(newCloudId)) {
- _bugCollection.getProject().setCloudId(newCloudId);
- MainFrame.getInstance().setProjectChanged(true);
- backgroundExecutor.execute(new Runnable() {
- public void run() {
- _bugCollection.reinitializeCloud();
- Cloud cloud = _bugCollection.getCloud();
- if (cloud != null)
- cloud.waitUntilIssueDataDownloaded();
- updateCloudListeners(_bugCollection);
- refresh();
- }
- });
- refresh();
- }
- }
-
- public void setBugCollection(BugCollection bugCollection) {
- updateCloudListeners(bugCollection);
- _bugCollection = bugCollection;
- _bugInstance = null;
- _bugAspects = null;
- refresh();
- }
-
- public void setBugInstance(final BugInstance bugInstance) {
- setBugs(bugInstance, null);
- }
-
- public void setBugAspects(BugAspects aspects) {
- setBugs(null, aspects);
- }
-
- private void setBugs(BugInstance bugInstance, BugAspects bugAspects) {
- if (_bugInstance == bugInstance && _bugAspects == bugAspects)
- return;
- if (!canNavigateAway())
- return;
-
- _bugInstance = bugInstance;
- _bugAspects = bugAspects;
- refresh();
- }
-
- public boolean canNavigateAway() {
- if (commentWasChanged()) {
- submitComment(getSelectedBugs());
- return true;
- } else {
- return true;
- }
- }
-
- protected void changeDesignationOfBugRightNow(final BugInstance bug, final String designationKey) {
- String oldValue = bug.getUserDesignationKey();
- if (designationKey.equals(oldValue))
- return;
- bug.setUserDesignationKey(designationKey, _bugCollection);
- }
-
- public void refresh() {
- updateBugCommentsView();
- }
-
- public void updateCloud() {
- updateCloudListeners(_bugCollection);
- refresh();
- }
-
- private void updateCloudListeners(BugCollection newBugCollection) {
- final Cloud newCloud = newBugCollection == null ? null : newBugCollection.getCloud();
- if (_bugCollection != null) {
- //noinspection ObjectEquality
- if (lastCloud != newCloud) {
- if (lastCloud != null) {
- lastCloud.removeStatusListener(_cloudStatusListener);
- }
- }
- }
- if (lastCloud != newCloud && newCloud != null) {
- lastCloud = newCloud;
- newCloud.addStatusListener(_cloudStatusListener);
- }
- }
-
-
- private boolean inCloud(Collection<BugInstance> bugs) {
- final Cloud cloud = _bugCollection.getCloud();
-
- for (BugInstance b : bugs)
- if (cloud.isInCloud(b))
- return true;
- return false;
-
- }
-
- private void updateBugCommentsView() {
-
- //TODO: fix cancel button
- List<BugInstance> bugs = getSelectedBugs();
- if (_bugCollection == null) {
- signInOutLink.setVisible(false);
- cloudDetailsLabel.setText("");
- cloudReportPane.setText("");
- titleLabel.setText("<html>Reviews");
- return;
- }
- updateHeader();
- final Cloud cloud = _bugCollection.getCloud();
- final CloudPlugin plugin = cloud.getPlugin();
- String details = plugin.getDetails();
- cloudDetailsLabel.setText(details);
-
- if (bugs.isEmpty()) {
- setCanAddComments(false, false);
- return;
- }
-
- String report;
- long lastSaved = -1;
- if (bugs.size() > 1) {
- int totalReviews = 0;
- int bugsWithReviews = 0;
- for (BugInstance bug : bugs) {
- long newTs = cloud.getUserTimestamp(bug);
- if (bug.hasSomeUserAnnotation() && newTs > 0 && (lastSaved == -1 || lastSaved < newTs)) {
- lastSaved = newTs;
- }
- int reviewers = cloud.getNumberReviewers(bug);
- if (reviewers > 0)
- bugsWithReviews++;
- totalReviews += reviewers;
- }
- report = bugs.size() + " bug" + (bugs.size() == 1 ? "" : "s") + " selected\n";
- report += bugsWithReviews + " reviewed bug" + (bugsWithReviews == 1 ? "" : "s")
- + " / " + totalReviews + " total review" + (totalReviews == 1 ? "" : "s");
- } else {
- BugInstance bug = bugs.get(0);
- if (bug.hasSomeUserAnnotation()) {
- lastSaved = bug.getUserTimestamp();
- }
- report = cloud.getCloudReportWithoutMe(bug);
- }
- setLastSaved(lastSaved);
- cloudReportPane.setText(report);
- CommentInfo commentInfo = new CommentInfo().invoke();
- boolean sameText = commentInfo.isSameText();
- String txt = commentInfo.getTxt();
- CardLayout cl = (CardLayout) (cards.getLayout());
- HashSet<BugInstance> newBugSet = new HashSet<BugInstance>(bugs);
- boolean sameBugs = newBugSet.equals(lastBugsEdited);
- if (!sameBugs) {
- lastBugsEdited = newBugSet;
- clickedBulkReview = false;
- }
- if (!inCloud(bugs)) {
- cl.show(cards, "NOT_IN_CLOUD");
- } else if (bugs.size() > 1 && !clickedBulkReview) {
- warningLabel.setText("<HTML>" + bugs.size() + " bugs are selected.<BR>Click to review them all at once.");
- cl.show(cards, "WARNING");
- } else {
- cl.show(cards, "COMMENTS");
- }
- if (!sameText) {
- txt = MessageFormat.format(MSG_OVERWRITE_REVIEW, bugs.size());
- setDefaultComment(txt);
- } else {
- if (txt == null || txt.trim().length() == 0) {
- txt = bugs.size() > 1 ? MessageFormat.format(MSG_REVIEW_MULTI, bugs.size()) : MSG_REVIEW;
- setDefaultComment(txt);
- } else {
- resetCommentBoxFont();
- setCommentText(txt);
- }
- }
-
- setCanAddComments(cloud.canStoreUserAnnotation(bugs.get(0)), false);
- updateSaveButton();
- }
-
- private boolean updatingHeader = false;
-
- private void updateHeader() {
- final Cloud cloud = _bugCollection.getCloud();
- CloudPlugin plugin = cloud.getPlugin();
- if (hasSelectedBugs()) {
- CommentInfo commentInfo = new CommentInfo().invoke();
- boolean sameDesignation = commentInfo.isSameDesignation();
- String designation = commentInfo.getDesignation();
- if (!sameDesignation)
- designation = null;
- updatingHeader = true;
- designationCombo.setSelectedIndex(I18N.instance().getUserDesignationKeys(true).indexOf(designation));
- updatingHeader = false;
- setCanAddComments(true, true);
- } else {
- setCanAddComments(false, false);
- }
-
- final Cloud.SigninState state = cloud.getSigninState();
- final String stateStr = state == Cloud.SigninState.NO_SIGNIN_REQUIRED ? "" : "" + state;
- final String userStr = cloud.getUser() == null ? "" : cloud.getUser();
- if (plugin.getId().equals("edu.umd.cs.findbugs.cloud.doNothingCloud"))
- titleLabel.setText("<html><b>No cloud selected");
- else
- titleLabel.setText("<html><b>Reviews - " + cloud.getCloudName() + "</b>"
- + "<br><font style='font-size: x-small;color:darkgray'>" + stateStr
- + (userStr.length() > 0 ? " - " + userStr : ""));
- switch (state) {
- case NO_SIGNIN_REQUIRED:
- case SIGNING_IN:
- signInOutLink.setVisible(false);
- break;
- case SIGNED_IN:
- setSignInOutText("sign out");
- signInOutLink.setVisible(true);
- break;
- default:
- if (state.couldSignIn()) {
- setSignInOutText("sign in");
- signInOutLink.setVisible(true);
- }
- break;
- }
- if (cloud.getPlugin().getId().equals("edu.umd.cs.findbugs.cloud.doNothingCloud")) {
- setSignInOutText("enable cloud plugin...");
- signInOutLink.setVisible(true);
- }
- }
-
- private void setCanAddComments(boolean canClick, boolean canEnter) {
- submitCommentButton.setEnabled(canClick || canEnter);
- designationCombo.setEnabled(canClick || canEnter);
- commentBox.setEnabled(canClick || canEnter);
- }
-
- protected abstract void setSignInOutText(String buttonText);
-
- /**
- * Method generated by IntelliJ IDEA GUI Designer
- * >>> IMPORTANT!! <<<
- * DO NOT edit this method OR call it in your code!
- *
- * @noinspection ALL
- */
- private void $$$setupUI$$$() {
- createUIComponents();
- mainPanel = new JPanel();
- mainPanel.setLayout(new GridBagLayout());
- mainPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3), null));
- _cloudReportScrollPane = new JScrollPane();
- GridBagConstraints gbc;
- gbc = new GridBagConstraints();
- gbc.gridx = 0;
- gbc.gridy = 2;
- gbc.gridwidth = 6;
- gbc.weightx = 1.0;
- gbc.weighty = 1.0;
- gbc.fill = GridBagConstraints.BOTH;
- gbc.insets = new Insets(5, 5, 5, 5);
- mainPanel.add(_cloudReportScrollPane, gbc);
- cloudReportPane = new JTextArea();
- cloudReportPane.setEditable(false);
- cloudReportPane.setLineWrap(true);
- cloudReportPane.setText("<html>\r\n <head>\r\n \r\n </head>\r\n <body>\r\n </body>\r\n</html>\r\n");
- cloudReportPane.setWrapStyleWord(true);
- _cloudReportScrollPane.setViewportView(cloudReportPane);
- final JPanel panel1 = new JPanel();
- panel1.setLayout(new GridBagLayout());
- panel1.setBackground(new Color(-3355444));
- gbc = new GridBagConstraints();
- gbc.gridx = 0;
- gbc.gridy = 0;
- gbc.gridwidth = 6;
- gbc.weightx = 1.0;
- gbc.fill = GridBagConstraints.BOTH;
- mainPanel.add(panel1, gbc);
- panel1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(new Color(-16751002)), null));
- titleLabel = new JLabel();
- titleLabel.setFont(new Font(titleLabel.getFont().getName(), Font.BOLD, 14));
- titleLabel.setForeground(new Color(-16777216));
- titleLabel.setText("FindBugs Cloud - signed in");
- gbc = new GridBagConstraints();
- gbc.gridx = 0;
- gbc.gridy = 0;
- gbc.gridheight = 2;
- gbc.weightx = 1.0;
- gbc.anchor = GridBagConstraints.NORTHWEST;
- panel1.add(titleLabel, gbc);
- dumbPanelSignInOutLink = new JPanel();
- dumbPanelSignInOutLink.setLayout(new GridBagLayout());
- dumbPanelSignInOutLink.setOpaque(false);
- dumbPanelSignInOutLink.setPreferredSize(new Dimension(50, 10));
- gbc = new GridBagConstraints();
- gbc.gridx = 1;
- gbc.gridy = 0;
- gbc.gridheight = 2;
- gbc.fill = GridBagConstraints.BOTH;
- panel1.add(dumbPanelSignInOutLink, gbc);
- gbc = new GridBagConstraints();
- gbc.gridx = 0;
- gbc.gridy = 0;
- gbc.anchor = GridBagConstraints.NORTHWEST;
- dumbPanelSignInOutLink.add(signInOutLink, gbc);
- final JPanel panel2 = new JPanel();
- panel2.setLayout(new GridBagLayout());
- panel2.setVisible(false);
- gbc = new GridBagConstraints();
- gbc.gridx = 0;
- gbc.gridy = 1;
- gbc.weightx = 1.0;
- gbc.fill = GridBagConstraints.BOTH;
- gbc.insets = new Insets(5, 5, 5, 5);
- mainPanel.add(panel2, gbc);
- cloudDetailsLabel = new JTextArea();
- cloudDetailsLabel.setEditable(false);
- cloudDetailsLabel.setFont(new Font(cloudDetailsLabel.getFont().getName(), Font.ITALIC, 10));
- cloudDetailsLabel.setForeground(new Color(-10066330));
- cloudDetailsLabel.setLineWrap(true);
- cloudDetailsLabel.setMaximumSize(new Dimension(100, 50));
- cloudDetailsLabel.setMinimumSize(new Dimension(50, 16));
- cloudDetailsLabel.setOpaque(false);
- cloudDetailsLabel.setPreferredSize(new Dimension(100, 31));
- cloudDetailsLabel.setText("Comments are stored on the FindBugs Cloud at http://findbugs-cloud.appspot.com");
- cloudDetailsLabel.setWrapStyleWord(true);
- gbc = new GridBagConstraints();
- gbc.gridx = 0;
- gbc.gridy = 0;
- gbc.weightx = 1.0;
- gbc.weighty = 1.0;
- gbc.fill = GridBagConstraints.BOTH;
- panel2.add(cloudDetailsLabel, gbc);
- final JPanel panel3 = new JPanel();
- panel3.setLayout(new GridBagLayout());
- gbc = new GridBagConstraints();
- gbc.gridx = 1;
- gbc.gridy = 3;
- gbc.gridwidth = 5;
- gbc.weightx = 1.0;
- gbc.weighty = 1.0;
- gbc.fill = GridBagConstraints.BOTH;
- mainPanel.add(panel3, gbc);
- cards = new JPanel();
- cards.setLayout(new CardLayout(0, 0));
- gbc = new GridBagConstraints();
- gbc.gridx = 5;
- gbc.gridy = 4;
- gbc.weightx = 1.0;
- gbc.weighty = 1.0;
- gbc.fill = GridBagConstraints.BOTH;
- mainPanel.add(cards, gbc);
- final JPanel panel4 = new JPanel();
- panel4.setLayout(new GridBagLayout());
- cards.add(panel4, "COMMENTS");
- designationCombo = new WideComboBox();
- gbc = new GridBagConstraints();
- gbc.gridx = 4;
- gbc.gridy = 0;
- gbc.gridwidth = 2;
- gbc.anchor = GridBagConstraints.NORTHWEST;
- gbc.insets = new Insets(5, 0, 0, 0);
- panel4.add(designationCombo, gbc);
- final JScrollPane scrollPane1 = new JScrollPane();
- gbc = new GridBagConstraints();
- gbc.gridx = 0;
- gbc.gridy = 0;
- gbc.gridwidth = 4;
- gbc.gridheight = 4;
- gbc.weightx = 1.0;
- gbc.fill = GridBagConstraints.BOTH;
- panel4.add(scrollPane1, gbc);
- scrollPane1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null));
- commentBox = new JTextArea();
- commentBox.setLineWrap(true);
- commentBox.setRows(5);
- commentBox.setText(" ");
- commentBox.setWrapStyleWord(true);
- scrollPane1.setViewportView(commentBox);
- submitCommentButton = new JButton();
- submitCommentButton.setText("Save");
- gbc = new GridBagConstraints();
- gbc.gridx = 4;
- gbc.gridy = 1;
- gbc.insets = new Insets(5, 5, 5, 5);
- panel4.add(submitCommentButton, gbc);
- lastSavedLabel = new JLabel();
- lastSavedLabel.setFont(new Font(lastSavedLabel.getFont().getName(), Font.ITALIC, 9));
- lastSavedLabel.setText("saved at");
- gbc = new GridBagConstraints();
- gbc.gridx = 4;
- gbc.gridy = 3;
- gbc.gridwidth = 2;
- panel4.add(lastSavedLabel, gbc);
- gbc = new GridBagConstraints();
- gbc.gridx = 5;
- gbc.gridy = 1;
- panel4.add(cancelLink, gbc);
- final JPanel panel5 = new JPanel();
- panel5.setLayout(new GridBagLayout());
- cards.add(panel5, "WARNING");
- warningLabel = new JLabel();
- warningLabel.setHorizontalAlignment(0);
- warningLabel.setHorizontalTextPosition(0);
- warningLabel.setText("<HTML>Multiple bugs are selected.<BR>Click to review them all at once.");
- gbc = new GridBagConstraints();
- gbc.gridx = 0;
- gbc.gridy = 0;
- gbc.insets = new Insets(10, 10, 10, 10);
- panel5.add(warningLabel, gbc);
- bulkReviewButton = new JButton();
- bulkReviewButton.setText("Bulk Review");
- gbc = new GridBagConstraints();
- gbc.gridx = 1;
- gbc.gridy = 0;
- gbc.fill = GridBagConstraints.HORIZONTAL;
- gbc.insets = new Insets(10, 10, 10, 10);
- panel5.add(bulkReviewButton, gbc);
- }
-
- /**
- * @noinspection ALL
- */
- public JComponent $$$getRootComponent$$$() {
- return mainPanel;
- }
-
- private class MyCloudStatusListener implements Cloud.CloudStatusListener {
- public void handleIssueDataDownloadedEvent() {
- refresh();
- }
-
-
- public void handleStateChange(final Cloud.SigninState oldState, final Cloud.SigninState state) {
- updateHeader();
- refresh();
- }
-
-
- }
-
- private interface BugAction {
- void execute(BugInstance bug);
- }
-
- private class CommentInfo {
- private String txt;
- private boolean sameText;
- private String designation;
- private boolean sameDesignation;
-
- public String getTxt() {
- return txt;
- }
-
- public boolean isSameText() {
- return sameText;
- }
-
- public String getDesignation() {
- return designation;
- }
-
- public boolean isSameDesignation() {
- return sameDesignation;
- }
-
- public CommentInfo invoke() {
- txt = null;
- sameText = true;
- designation = null;
- sameDesignation = true;
- for (BugInstance bug : getSelectedBugs()) {
- String newText = bug.getAnnotationText();
- if (txt == null)
- txt = newText;
- else {
- if (!nullSafeEquals(txt, newText))
- sameText = false;
- }
-
- String newDesignation = bug.getUserDesignationKey();
- if (designation == null)
- designation = newDesignation;
- else {
- if (!nullSafeEquals(designation, newDesignation))
- sameDesignation = false;
- }
- }
- return this;
- }
- }
-}
+/*
+ * FindBugs - Find bugs in Java programs
+ * Copyright (C) 2010-2013 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.gui2;
+
+import static edu.umd.cs.findbugs.util.Util.nullSafeEquals;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.text.DateFormat;
+import java.text.MessageFormat;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.swing.BorderFactory;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+
+import edu.umd.cs.findbugs.BugCollection;
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.DetectorFactoryCollection;
+import edu.umd.cs.findbugs.I18N;
+import edu.umd.cs.findbugs.L10N;
+import edu.umd.cs.findbugs.cloud.Cloud;
+import edu.umd.cs.findbugs.cloud.Cloud.SigninState;
+import edu.umd.cs.findbugs.cloud.Cloud.UserDesignation;
+import edu.umd.cs.findbugs.cloud.CloudPlugin;
+import edu.umd.cs.findbugs.util.Util;
+
+ at edu.umd.cs.findbugs.annotations.SuppressFBWarnings({"SE_TRANSIENT_FIELD_NOT_RESTORED", "SE_BAD_FIELD", "SE_BAD_FIELD_STORE"})
+public abstract class CloudCommentsPane extends JPanel {
+
+ private static final String MSG_REVIEW = L10N.getLocalString("dlg.cloud.add_review", "Click to add review...");
+ private static final String MSG_REVIEW_MULTI = L10N.getLocalString("dlg.cloud.add_review_multi",
+ "Click to add review to {0} bugs...");
+ private static final String MSG_OVERWRITE_REVIEW = L10N.getLocalString("dlg.cloud.ovwrt_review_multi",
+ "Click to overwrite {0} reviews...");
+
+ private JTextArea cloudReportPane;
+ protected JComponent cancelLink;
+ protected JComponent signInOutLink;
+ private JTextArea commentBox;
+ private JButton submitCommentButton;
+ private WideComboBox<String> designationCombo;
+ private JPanel mainPanel;
+ private JScrollPane _cloudReportScrollPane;
+ protected JLabel titleLabel;
+ protected JTextArea cloudDetailsLabel;
+ private JPanel dumbPanelSignInOutLink;
+ private JLabel lastSavedLabel;
+ private JPanel cards;
+ private JButton bulkReviewButton;
+ private JLabel warningLabel;
+
+ protected BugCollection _bugCollection;
+ protected BugInstance _bugInstance;
+ private BugAspects _bugAspects;
+
+ private final Executor backgroundExecutor = Executors.newCachedThreadPool();
+
+ private final Cloud.CloudStatusListener _cloudStatusListener = new MyCloudStatusListener();
+ private Cloud lastCloud = null;
+ private Font plainCommentFont;
+ private String lastCommentText = null;
+ private Set<BugInstance> lastBugsEdited = Collections.emptySet();
+ private boolean clickedBulkReview = false;
+
+
+ private void addNotInCloudCard() {
+ final JPanel panel5 = new JPanel();
+ cards.add(panel5, "NOT_IN_CLOUD");
+ }
+
+ public CloudCommentsPane() {
+ $$$setupUI$$$();
+ addNotInCloudCard();
+ cloudReportPane.setBackground(this.getBackground());
+ cloudReportPane.setBorder(new EmptyBorder(0, 0, 0, 0));
+ _cloudReportScrollPane.setBorder(new EmptyBorder(0, 0, 0, 0));
+
+ // designationCombo.setPreferredSize(new Dimension(300, 20));
+ commentBox.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ commentBoxClicked();
+ }
+ });
+ commentBox.getDocument().addDocumentListener(new DocumentListener() {
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ changed();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ changed();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ changed();
+ }
+
+ private void changed() {
+ updateSaveButton();
+ }
+ });
+ commentBox.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
+
+ dumbPanelSignInOutLink.setPreferredSize(null);
+
+ setLayout(new BorderLayout());
+ add(mainPanel, BorderLayout.CENTER);
+
+ designationCombo.removeAllItems();
+ final List<String> userDesignationKeys = I18N.instance().getUserDesignationKeys(true);
+ for (final String designation : userDesignationKeys) {
+ designationCombo.addItem(I18N.instance().getUserDesignation(designation));
+ }
+ designationCombo.addItem(null);
+ designationCombo.setRenderer(new DefaultListCellRenderer() {
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+ boolean cellHasFocus) {
+ Component real = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+ if (value == null) {
+ return real;
+ }
+ if (index == -1) {
+ return real;
+ }
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.setBorder(new EmptyBorder(3, 3, 3, 3));
+ int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.weightx = 1;
+ gbc.anchor = GridBagConstraints.WEST;
+ panel.add(real, gbc);
+
+ gbc.weightx = 0;
+ gbc.anchor = GridBagConstraints.EAST;
+ gbc.insets = new Insets(0, 10, 0, 0);
+ JLabel label = new JLabel(KeyEvent.getKeyModifiersText(mask) + "-" + (index + 1));
+ label.setForeground(Color.GRAY);
+ // Font font = label.getFont();
+ // label.setFont(font.deriveFont(font.getSize() - 2f));
+ panel.add(label, gbc);
+ panel.setBackground(real.getBackground());
+ return panel;
+ }
+ });
+ designationCombo.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (!updatingHeader) {
+ int selectedIndex = designationCombo.getSelectedIndex();
+ if (selectedIndex >= 0) {
+ setDesignation(userDesignationKeys.get(selectedIndex));
+ }
+ }
+ }
+ });
+
+ // commentEntryPanel.setVisible(false);
+ submitCommentButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ submitComment(CloudCommentsPane.this.getSelectedBugs());
+ }
+ });
+ cloudDetailsLabel.setBackground(null);
+ cloudDetailsLabel.setBorder(null);
+ plainCommentFont = commentBox.getFont().deriveFont(Font.PLAIN);
+ cloudReportPane.setFont(plainCommentFont);
+ // cloudReportPane.setEditorKit(new HTMLEditorKit());
+ // ((HTMLEditorKit) cloudReportPane.getDocument()).getStyleSheet().addRule("body { font-");
+
+ setDefaultComment(MSG_REVIEW);
+ commentBox.addFocusListener(new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ commentBox.setForeground(null);
+ commentBox.setFont(plainCommentFont);
+ if (isDefaultComment(commentBox.getText())) {
+ resetCommentBoxFont();
+ setCommentText("");
+ }
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ String text = commentBox.getText();
+ if (isDefaultComment(text)) {
+ refresh();
+ } else if (text.equals(lastCommentText)) {
+ if (text.trim().length() == 0) {
+ refresh();
+ }
+ } else {
+ submitComment(CloudCommentsPane.this.getSelectedBugs());
+ resetCommentBoxFont();
+ }
+ }
+ });
+ commentBox.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ cancelClicked();
+ } else if (e.getKeyCode() == KeyEvent.VK_ENTER && (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) {
+ submitComment(CloudCommentsPane.this.getSelectedBugs());
+ }
+ }
+ });
+ submitCommentButton.setToolTipText("Submit review [Enter]");
+ cancelLink.setToolTipText("Cancel [Esc]");
+
+ bulkReviewButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ clickedBulkReview = true;
+ refresh();
+ }
+ });
+
+ setCanAddComments(false, false);
+ setLastSaved(0);
+
+ updateBugCommentsView();
+ }
+
+ private boolean isDefaultComment(String text) {
+ if (text.equals(MSG_REVIEW)) {
+ return true;
+ }
+ try {
+ new MessageFormat(MSG_REVIEW_MULTI).parse(text);
+ return true; // didn't throw an exception
+ } catch (ParseException e) {
+ }
+ try {
+ new MessageFormat(MSG_OVERWRITE_REVIEW).parse(text);
+ return true; // didn't throw an exception
+ } catch (ParseException e) {
+ }
+ return false;
+ }
+
+ private void updateSaveButton() {
+ boolean changed = commentWasChanged();
+ submitCommentButton.setEnabled(changed);
+ submitCommentButton.setText(changed
+ ? L10N.getLocalString("dlg.save_btn", "Save")
+ : L10N.getLocalString("dlg.saved_btn", "Saved"));
+ cancelLink.setEnabled(false/*changed*/);
+ }
+
+ private void setCommentText(String t) {
+ lastCommentText = t;
+ if (!commentBox.getText().equals(t)) {
+ commentBox.setText(t);
+ }
+ }
+
+ private void resetCommentBoxFont() {
+ commentBox.setFont(plainCommentFont);
+ commentBox.setForeground(null);
+ }
+
+ private void setDefaultComment(String defaultComment) {
+ setCommentText(defaultComment);
+ commentBox.setForeground(Color.DARK_GRAY);
+ commentBox.setFont(plainCommentFont.deriveFont(Font.ITALIC));
+ }
+
+ private void createUIComponents() {
+ setupLinksOrButtons();
+ }
+
+ protected abstract void setupLinksOrButtons();
+
+
+ private void applyToBugs(final BugAction bugAction) {
+ Executor executor = backgroundExecutor;
+
+ final AtomicInteger shownErrorMessages = new AtomicInteger(0);
+ for (final BugInstance bug : getSelectedBugs()) {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ if (shownErrorMessages.get() > 5) {
+ // 5 errors? let's just stop trying.
+ return;
+ }
+ try {
+ bugAction.execute(bug);
+ } catch (Throwable e) {
+ if (shownErrorMessages.addAndGet(1) > 5) {
+ return;
+ }
+ JOptionPane.showMessageDialog(CloudCommentsPane.this,
+ "Error while submitting cloud reviews:\n"
+ + e.getClass().getSimpleName() + ": " + e.getMessage(),
+ "Review Submission Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ });
+ }
+ }
+
+ protected void signInOrOutClicked() {
+ if (_bugCollection != null) {
+ final Cloud cloud = _bugCollection.getCloud();
+ if ("edu.umd.cs.findbugs.cloud.doNothingCloud".equals(cloud.getPlugin().getId())) {
+ changeClicked();
+ }
+ SigninState state = cloud.getSigninState();
+ if (state == SigninState.SIGNED_IN) {
+ backgroundExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ cloud.signOut();
+ refresh();
+ }
+ });
+ refresh();
+ } else if (state.couldSignIn()) {
+ backgroundExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ cloud.signIn();
+ } catch (Exception e) {
+ _bugCollection
+ .getProject()
+ .getGuiCallback()
+ .showMessageDialog(
+ "The FindBugs Cloud could not be contacted at this time.\n\n"
+ + Util.getNetworkErrorMessage(e));
+ }
+ refresh();
+ }
+ });
+ refresh();
+
+ }
+ }
+ }
+
+ protected void commentBoxClicked() {
+ if (commentWasChanged()) {
+ return;
+ }
+ setCanAddComments(false, true);
+ CommentInfo commentInfo = new CommentInfo().invoke();
+ boolean sameText = commentInfo.isSameText();
+ String txt = commentInfo.getTxt();
+ if (!sameText) {
+ txt = "";
+ }
+ if (txt == null || txt.trim().length() == 0) {
+ txt = "";
+ }
+ resetCommentBoxFont();
+ boolean sameTextInBox = commentBox.getText().equals(txt);
+ setCommentText(txt);
+ int start = commentBox.getSelectionStart();
+ int end = commentBox.getSelectionEnd();
+ if (!commentBox.hasFocus() && (!sameTextInBox || start != 0 || end != txt.length())) {
+ commentBox.setSelectionStart(0);
+ commentBox.setSelectionEnd(txt.length());
+ }
+ updateSaveButton();
+ }
+
+ private boolean commentWasChanged() {
+ String text = commentBox.getText();
+ boolean b = !isDefaultComment(text);
+ // boolean b1 = text.trim().equals("");
+ boolean b3 = text.equals(lastCommentText);
+ return b && !b3;
+ }
+
+ public boolean canSetDesignations() {
+ List<BugInstance> bugs = getSelectedBugs();
+ if (bugs.isEmpty()) {
+ return true;
+ }
+ Cloud plugin = _bugCollection != null ? _bugCollection.getCloud() : null;
+ if (plugin == null) {
+ return false;
+ }
+ for(BugInstance b : bugs) {
+ if (plugin.canStoreUserAnnotation(b)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setDesignation(final String designationKey) {
+
+ // List<BugInstance> selectedBugs = getSelectedBugs();
+ // if (selectedBugs.size() > 1)
+ // if (!confirmAnnotation(selectedBugs))
+ // return;
+ final AtomicBoolean stop = new AtomicBoolean(false);
+ applyToBugs(new BugAction() {
+ @Override
+ public void execute(BugInstance bug) {
+ if (stop.get()) {
+ return;
+ }
+ String oldValue = bug.getUserDesignationKey();
+ String key = designationKey;
+ if (key.equals(oldValue)) {
+ return;
+ }
+ Cloud plugin = _bugCollection != null ? _bugCollection.getCloud() : null;
+ if (plugin != null && "I_WILL_FIX".equals(key) && plugin.supportsClaims()) {
+ String claimedBy = plugin.claimedBy(bug);
+ if (claimedBy != null && !plugin.getUser().equals(claimedBy)) {
+ int result = JOptionPane.showConfirmDialog(null,
+ bug.getMessage() + "\n"
+ + claimedBy + " has already said they will fix this issue\n"
+ + "Do you want to also be listed as fixing this issue?\n"
+ + "If so, please coordinate with " + claimedBy,
+ "Issue already claimed", JOptionPane.YES_NO_CANCEL_OPTION);
+ if (result == JOptionPane.CANCEL_OPTION) {
+ stop.set(true);
+ return;
+ }
+ if (result != JOptionPane.YES_OPTION) {
+ key = "MUST_FIX";
+ }
+ }
+ }
+ changeDesignationOfBugRightNow(bug, key);
+ refresh();
+ }
+ });
+ }
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ private void submitComment(List<BugInstance> selectedBugs) {
+ String comment = commentBox.getText();
+ if (isDefaultComment(comment)) {
+ comment = "";
+ }
+ // if (selectedBugs.size() > 1)
+ // if (!confirmAnnotation(selectedBugs))
+ // return;
+ if (designationCombo.getSelectedItem() != null) {
+ final int index = designationCombo.getSelectedIndex();
+ final String choice;
+ if (index == -1) {
+ choice = UserDesignation.UNCLASSIFIED.name();
+ } else {
+ choice = I18N.instance().getUserDesignationKeys(true).get(index);
+ }
+ setDesignation(choice);
+ }
+ final String finalComment = comment;
+ applyToBugs(new BugAction() {
+ @Override
+ public void execute(BugInstance bug) {
+ bug.setAnnotationText(finalComment, _bugCollection);
+ refresh();
+ setLastSaved(System.currentTimeMillis());
+ }
+ });
+
+ refresh();
+
+ setCanAddComments(true, false);
+ commentBox.requestFocus();
+ }
+
+ private void setLastSaved(long date) {
+ if (date > 0) {
+ lastSavedLabel.setText("saved " + DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT)
+ .format(new Date(date)));
+ } else {
+ lastSavedLabel.setText("");
+ }
+ }
+
+ protected void cancelClicked() {
+ setDefaultComment(lastCommentText);
+ // commentEntryPanel.setVisible(false);
+ setCanAddComments(true, false);
+ }
+
+ private List<BugInstance> getSelectedBugs() {
+ if (_bugInstance != null) {
+ return Collections.singletonList(_bugInstance);
+ }
+ if (_bugAspects != null) {
+ List<BugInstance> set = new ArrayList<BugInstance>();
+ for (BugLeafNode node : _bugAspects.getMatchingBugs(BugSet.getMainBugSet())) {
+ if (!BugSet.suppress(node)) {
+ set.add(node.getBug());
+ }
+ }
+ return set;
+ }
+ return Collections.emptyList();
+ }
+
+ private boolean hasSelectedBugs() {
+ return _bugInstance != null || _bugAspects != null;
+ }
+
+ protected void changeClicked() {
+ final List<CloudPlugin> plugins = new ArrayList<CloudPlugin>();
+ final List<String> descriptions = new ArrayList<String>();
+ List<CloudPlugin> clouds = new ArrayList<CloudPlugin>(DetectorFactoryCollection.instance().getRegisteredClouds().values());
+ Collections.sort(clouds, new Comparator<CloudPlugin>() {
+ @Override
+ public int compare(CloudPlugin o1, CloudPlugin o2) {
+ return o1.getDescription().compareToIgnoreCase(o2.getDescription());
+ }
+ });
+ for (final CloudPlugin plugin : clouds) {
+ final boolean disabled = isDisabled(plugin);
+ if (!disabled && !plugin.isHidden()) {
+ descriptions.add(plugin.getDescription());
+ plugins.add(plugin);
+ }
+ }
+ showCloudChooser(plugins, descriptions);
+ }
+
+ protected abstract boolean isDisabled(CloudPlugin plugin);
+
+ protected abstract void showCloudChooser(List<CloudPlugin> plugins, List<String> descriptions);
+
+ protected void changeCloud(String newCloudId) {
+ final String oldCloudId = _bugCollection.getCloud().getPlugin().getId();
+ if (!oldCloudId.equals(newCloudId)) {
+ _bugCollection.getProject().setCloudId(newCloudId);
+ MainFrame.getInstance().setProjectChanged(true);
+ backgroundExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ _bugCollection.reinitializeCloud();
+ Cloud cloud = _bugCollection.getCloud();
+ if (cloud != null) {
+ cloud.waitUntilIssueDataDownloaded();
+ }
+ updateCloudListeners(_bugCollection);
+ refresh();
+ }
+ });
+ refresh();
+ }
+ }
+
+ public void setBugCollection(BugCollection bugCollection) {
+ updateCloudListeners(bugCollection);
+ _bugCollection = bugCollection;
+ _bugInstance = null;
+ _bugAspects = null;
+ refresh();
+ }
+
+ public void setBugInstance(final BugInstance bugInstance) {
+ setBugs(bugInstance, null);
+ }
+
+ public void setBugAspects(BugAspects aspects) {
+ setBugs(null, aspects);
+ }
+
+ private void setBugs(BugInstance bugInstance, BugAspects bugAspects) {
+ if (_bugInstance == bugInstance && _bugAspects == bugAspects) {
+ return;
+ }
+ if (!canNavigateAway()) {
+ return;
+ }
+
+ _bugInstance = bugInstance;
+ _bugAspects = bugAspects;
+ refresh();
+ }
+
+ public boolean canNavigateAway() {
+ if (commentWasChanged()) {
+ submitComment(getSelectedBugs());
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+ protected void changeDesignationOfBugRightNow(final BugInstance bug, final String designationKey) {
+ String oldValue = bug.getUserDesignationKey();
+ if (designationKey.equals(oldValue)) {
+ return;
+ }
+ bug.setUserDesignationKey(designationKey, _bugCollection);
+ }
+
+ public void refresh() {
+ updateBugCommentsView();
+ }
+
+ public void updateCloud() {
+ updateCloudListeners(_bugCollection);
+ refresh();
+ }
+
+ private void updateCloudListeners(BugCollection newBugCollection) {
+ final Cloud newCloud = newBugCollection == null ? null : newBugCollection.getCloud();
+ if (_bugCollection != null) {
+ //noinspection ObjectEquality
+ if (lastCloud != newCloud) {
+ if (lastCloud != null) {
+ lastCloud.removeStatusListener(_cloudStatusListener);
+ }
+ }
+ }
+ if (lastCloud != newCloud && newCloud != null) {
+ lastCloud = newCloud;
+ newCloud.addStatusListener(_cloudStatusListener);
+ }
+ }
+
+
+ private boolean inCloud(Collection<BugInstance> bugs) {
+ final Cloud cloud = _bugCollection.getCloud();
+
+ for (BugInstance b : bugs) {
+ if (cloud.isInCloud(b)) {
+ return true;
+ }
+ }
+ return false;
+
+ }
+
+ private void updateBugCommentsView() {
+
+ //TODO: fix cancel button
+ List<BugInstance> bugs = getSelectedBugs();
+ if (_bugCollection == null) {
+ signInOutLink.setVisible(false);
+ cloudDetailsLabel.setText("");
+ cloudReportPane.setText("");
+ titleLabel.setText("<html>Reviews");
+ return;
+ }
+ updateHeader();
+ final Cloud cloud = _bugCollection.getCloud();
+ final CloudPlugin plugin = cloud.getPlugin();
+ String details = plugin.getDetails();
+ cloudDetailsLabel.setText(details);
+
+ if (bugs.isEmpty()) {
+ setCanAddComments(false, false);
+ return;
+ }
+
+ String report;
+ long lastSaved = -1;
+ if (bugs.size() > 1) {
+ int totalReviews = 0;
+ int bugsWithReviews = 0;
+ for (BugInstance bug : bugs) {
+ long newTs = cloud.getUserTimestamp(bug);
+ if (bug.hasSomeUserAnnotation() && newTs > 0 && (lastSaved == -1 || lastSaved < newTs)) {
+ lastSaved = newTs;
+ }
+ int reviewers = cloud.getNumberReviewers(bug);
+ if (reviewers > 0) {
+ bugsWithReviews++;
+ }
+ totalReviews += reviewers;
+ }
+ report = bugs.size() + " bug" + (bugs.size() == 1 ? "" : "s") + " selected\n";
+ report += bugsWithReviews + " reviewed bug" + (bugsWithReviews == 1 ? "" : "s")
+ + " / " + totalReviews + " total review" + (totalReviews == 1 ? "" : "s");
+ } else {
+ BugInstance bug = bugs.get(0);
+ if (bug.hasSomeUserAnnotation()) {
+ lastSaved = bug.getUserTimestamp();
+ }
+ report = cloud.getCloudReportWithoutMe(bug);
+ }
+ setLastSaved(lastSaved);
+ cloudReportPane.setText(report);
+ CommentInfo commentInfo = new CommentInfo().invoke();
+ boolean sameText = commentInfo.isSameText();
+ String txt = commentInfo.getTxt();
+ CardLayout cl = (CardLayout) (cards.getLayout());
+ HashSet<BugInstance> newBugSet = new HashSet<BugInstance>(bugs);
+ boolean sameBugs = newBugSet.equals(lastBugsEdited);
+ if (!sameBugs) {
+ lastBugsEdited = newBugSet;
+ clickedBulkReview = false;
+ }
+ if (!inCloud(bugs)) {
+ cl.show(cards, "NOT_IN_CLOUD");
+ } else if (bugs.size() > 1 && !clickedBulkReview) {
+ warningLabel.setText("<HTML>" + bugs.size() + " bugs are selected.<BR>Click to review them all at once.");
+ cl.show(cards, "WARNING");
+ } else {
+ cl.show(cards, "COMMENTS");
+ }
+ if (!sameText) {
+ txt = MessageFormat.format(MSG_OVERWRITE_REVIEW, bugs.size());
+ setDefaultComment(txt);
+ } else {
+ if (txt == null || txt.trim().length() == 0) {
+ txt = bugs.size() > 1 ? MessageFormat.format(MSG_REVIEW_MULTI, bugs.size()) : MSG_REVIEW;
+ setDefaultComment(txt);
+ } else {
+ resetCommentBoxFont();
+ setCommentText(txt);
+ }
+ }
+
+ setCanAddComments(cloud.canStoreUserAnnotation(bugs.get(0)), false);
+ updateSaveButton();
+ }
+
+ private boolean updatingHeader = false;
+
+ private void updateHeader() {
+ final Cloud cloud = _bugCollection.getCloud();
+ CloudPlugin plugin = cloud.getPlugin();
+ if (hasSelectedBugs()) {
+ CommentInfo commentInfo = new CommentInfo().invoke();
+ boolean sameDesignation = commentInfo.isSameDesignation();
+ String designation = commentInfo.getDesignation();
+ if (!sameDesignation) {
+ designation = null;
+ }
+ updatingHeader = true;
+ designationCombo.setSelectedIndex(I18N.instance().getUserDesignationKeys(true).indexOf(designation));
+ updatingHeader = false;
+ setCanAddComments(true, true);
+ } else {
+ setCanAddComments(false, false);
+ }
+
+ final Cloud.SigninState state = cloud.getSigninState();
+ final String stateStr = state == Cloud.SigninState.NO_SIGNIN_REQUIRED ? "" : "" + state;
+ final String userStr = cloud.getUser() == null ? "" : cloud.getUser();
+ if ("edu.umd.cs.findbugs.cloud.doNothingCloud".equals(plugin.getId())) {
+ titleLabel.setText("<html><b>No cloud selected");
+ } else {
+ titleLabel.setText("<html><b>Reviews - " + cloud.getCloudName() + "</b>"
+ + "<br><font style='font-size: x-small;color:darkgray'>" + stateStr
+ + (userStr.length() > 0 ? " - " + userStr : ""));
+ }
+ switch (state) {
+ case NO_SIGNIN_REQUIRED:
+ case SIGNING_IN:
+ signInOutLink.setVisible(false);
+ break;
+ case SIGNED_IN:
+ setSignInOutText("sign out");
+ signInOutLink.setVisible(true);
+ break;
+ default:
+ if (state.couldSignIn()) {
+ setSignInOutText("sign in");
+ signInOutLink.setVisible(true);
+ }
+ break;
+ }
+ if ("edu.umd.cs.findbugs.cloud.doNothingCloud".equals(cloud.getPlugin().getId())) {
+ setSignInOutText("enable cloud plugin...");
+ signInOutLink.setVisible(true);
+ }
+ }
+
+ private void setCanAddComments(boolean canClick, boolean canEnter) {
+ submitCommentButton.setEnabled(canClick || canEnter);
+ designationCombo.setEnabled(canClick || canEnter);
+ commentBox.setEnabled(canClick || canEnter);
+ }
+
+ protected abstract void setSignInOutText(String buttonText);
+
+ /**
+ * Method generated by IntelliJ IDEA GUI Designer
+ * >>> IMPORTANT!! <<<
+ * DO NOT edit this method OR call it in your code!
+ *
+ * @noinspection ALL
+ */
+ private void $$$setupUI$$$() {
+ createUIComponents();
+ mainPanel = new JPanel();
+ mainPanel.setLayout(new GridBagLayout());
+ mainPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3), null));
+ _cloudReportScrollPane = new JScrollPane();
+ GridBagConstraints gbc;
+ gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 2;
+ gbc.gridwidth = 6;
+ gbc.weightx = 1.0;
+ gbc.weighty = 1.0;
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.insets = new Insets(5, 5, 5, 5);
+ mainPanel.add(_cloudReportScrollPane, gbc);
+ cloudReportPane = new JTextArea();
+ cloudReportPane.setEditable(false);
+ cloudReportPane.setLineWrap(true);
+ cloudReportPane.setText("<html>\r\n <head>\r\n \r\n </head>\r\n <body>\r\n </body>\r\n</html>\r\n");
+ cloudReportPane.setWrapStyleWord(true);
+ _cloudReportScrollPane.setViewportView(cloudReportPane);
+ final JPanel panel1 = new JPanel();
+ panel1.setLayout(new GridBagLayout());
+ panel1.setBackground(new Color(-3355444));
+ gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.gridwidth = 6;
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.BOTH;
+ mainPanel.add(panel1, gbc);
+ panel1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(new Color(-16751002)), null));
+ titleLabel = new JLabel();
+ titleLabel.setFont(new Font(titleLabel.getFont().getName(), Font.BOLD, 14));
+ titleLabel.setForeground(new Color(-16777216));
+ titleLabel.setText("FindBugs Cloud - signed in");
+ gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.gridheight = 2;
+ gbc.weightx = 1.0;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ panel1.add(titleLabel, gbc);
+ dumbPanelSignInOutLink = new JPanel();
+ dumbPanelSignInOutLink.setLayout(new GridBagLayout());
+ dumbPanelSignInOutLink.setOpaque(false);
+ dumbPanelSignInOutLink.setPreferredSize(new Dimension(50, 10));
+ gbc = new GridBagConstraints();
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ gbc.gridheight = 2;
+ gbc.fill = GridBagConstraints.BOTH;
+ panel1.add(dumbPanelSignInOutLink, gbc);
+ gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ dumbPanelSignInOutLink.add(signInOutLink, gbc);
+ final JPanel panel2 = new JPanel();
+ panel2.setLayout(new GridBagLayout());
+ panel2.setVisible(false);
+ gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.insets = new Insets(5, 5, 5, 5);
+ mainPanel.add(panel2, gbc);
+ cloudDetailsLabel = new JTextArea();
+ cloudDetailsLabel.setEditable(false);
+ cloudDetailsLabel.setFont(new Font(cloudDetailsLabel.getFont().getName(), Font.ITALIC, 10));
+ cloudDetailsLabel.setForeground(new Color(-10066330));
+ cloudDetailsLabel.setLineWrap(true);
+ cloudDetailsLabel.setMaximumSize(new Dimension(100, 50));
+ cloudDetailsLabel.setMinimumSize(new Dimension(50, 16));
+ cloudDetailsLabel.setOpaque(false);
+ cloudDetailsLabel.setPreferredSize(new Dimension(100, 31));
+ cloudDetailsLabel.setText("Comments are stored on the FindBugs Cloud at http://findbugs-cloud.appspot.com");
+ cloudDetailsLabel.setWrapStyleWord(true);
+ gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.weightx = 1.0;
+ gbc.weighty = 1.0;
+ gbc.fill = GridBagConstraints.BOTH;
+ panel2.add(cloudDetailsLabel, gbc);
+ final JPanel panel3 = new JPanel();
+ panel3.setLayout(new GridBagLayout());
+ gbc = new GridBagConstraints();
+ gbc.gridx = 1;
+ gbc.gridy = 3;
+ gbc.gridwidth = 5;
+ gbc.weightx = 1.0;
+ gbc.weighty = 1.0;
+ gbc.fill = GridBagConstraints.BOTH;
+ mainPanel.add(panel3, gbc);
+ cards = new JPanel();
+ cards.setLayout(new CardLayout(0, 0));
+ gbc = new GridBagConstraints();
+ gbc.gridx = 5;
+ gbc.gridy = 4;
+ gbc.weightx = 1.0;
+ gbc.weighty = 1.0;
+ gbc.fill = GridBagConstraints.BOTH;
+ mainPanel.add(cards, gbc);
+ final JPanel panel4 = new JPanel();
+ panel4.setLayout(new GridBagLayout());
+ cards.add(panel4, "COMMENTS");
+ designationCombo = new WideComboBox<>();
+ gbc = new GridBagConstraints();
+ gbc.gridx = 4;
+ gbc.gridy = 0;
+ gbc.gridwidth = 2;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.insets = new Insets(5, 0, 0, 0);
+ panel4.add(designationCombo, gbc);
+ final JScrollPane scrollPane1 = new JScrollPane();
+ gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.gridwidth = 4;
+ gbc.gridheight = 4;
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.BOTH;
+ panel4.add(scrollPane1, gbc);
+ scrollPane1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null));
+ commentBox = new JTextArea();
+ commentBox.setLineWrap(true);
+ commentBox.setRows(5);
+ commentBox.setText(" ");
+ commentBox.setWrapStyleWord(true);
+ scrollPane1.setViewportView(commentBox);
+ submitCommentButton = new JButton();
+ submitCommentButton.setText("Save");
+ gbc = new GridBagConstraints();
+ gbc.gridx = 4;
+ gbc.gridy = 1;
+ gbc.insets = new Insets(5, 5, 5, 5);
+ panel4.add(submitCommentButton, gbc);
+ lastSavedLabel = new JLabel();
+ lastSavedLabel.setFont(new Font(lastSavedLabel.getFont().getName(), Font.ITALIC, 9));
+ lastSavedLabel.setText("saved at");
+ gbc = new GridBagConstraints();
+ gbc.gridx = 4;
+ gbc.gridy = 3;
+ gbc.gridwidth = 2;
+ panel4.add(lastSavedLabel, gbc);
+ gbc = new GridBagConstraints();
+ gbc.gridx = 5;
+ gbc.gridy = 1;
+ panel4.add(cancelLink, gbc);
+ final JPanel panel5 = new JPanel();
+ panel5.setLayout(new GridBagLayout());
+ cards.add(panel5, "WARNING");
+ warningLabel = new JLabel();
+ warningLabel.setHorizontalAlignment(0);
+ warningLabel.setHorizontalTextPosition(0);
+ warningLabel.setText("<HTML>Multiple bugs are selected.<BR>Click to review them all at once.");
+ gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.insets = new Insets(10, 10, 10, 10);
+ panel5.add(warningLabel, gbc);
+ bulkReviewButton = new JButton();
+ bulkReviewButton.setText("Bulk Review");
+ gbc = new GridBagConstraints();
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.insets = new Insets(10, 10, 10, 10);
+ panel5.add(bulkReviewButton, gbc);
+ }
+
+ /**
+ * @noinspection ALL
+ */
+ public JComponent $$$getRootComponent$$$() {
+ return mainPanel;
+ }
+
+ private class MyCloudStatusListener implements Cloud.CloudStatusListener {
+ @Override
+ public void handleIssueDataDownloadedEvent() {
+ refresh();
+ }
+
+
+ @Override
+ public void handleStateChange(final Cloud.SigninState oldState, final Cloud.SigninState state) {
+ updateHeader();
+ refresh();
+ }
+
+
+ }
+
+ private interface BugAction {
+ void execute(BugInstance bug);
+ }
+
+ private class CommentInfo {
+ private String txt;
+ private boolean sameText;
+ private String designation;
+ private boolean sameDesignation;
+
+ public String getTxt() {
+ return txt;
+ }
+
+ public boolean isSameText() {
+ return sameText;
+ }
+
+ public String getDesignation() {
+ return designation;
+ }
+
+ public boolean isSameDesignation() {
+ return sameDesignation;
+ }
+
+ public CommentInfo invoke() {
+ txt = null;
+ sameText = true;
+ designation = null;
+ sameDesignation = true;
+ for (BugInstance bug : getSelectedBugs()) {
+ String newText = bug.getAnnotationText();
+ if (txt == null) {
+ txt = newText;
+ } else {
+ if (!nullSafeEquals(txt, newText)) {
+ sameText = false;
+ }
+ }
+
+ String newDesignation = bug.getUserDesignationKey();
+ if (designation == null) {
+ designation = newDesignation;
+ } else {
+ if (!nullSafeEquals(designation, newDesignation)) {
+ sameDesignation = false;
+ }
+ }
+ }
+ return this;
+ }
+ }
+}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/CommentsArea.java b/src/gui/edu/umd/cs/findbugs/gui2/CommentsArea.java
index 390e84a..2ce6392 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/CommentsArea.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/CommentsArea.java
@@ -70,16 +70,19 @@ public class CommentsArea {
fileBug.setToolTipText("Click to file bug for this issue");
fileBug.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
if (frame.getCurrentSelectedBugLeaf() == null) {
return;
}
- if (!canNavigateAway())
+ if (!canNavigateAway()) {
return;
+ }
BugInstance bug = frame.getCurrentSelectedBugLeaf().getBug();
Cloud cloud1 = MainFrame.getInstance().getBugCollection().getCloud();
- if (!cloud1.supportsBugLinks())
+ if (!cloud1.supportsBugLinks()) {
return;
+ }
try {
URL u = cloud1.getBugLink(bug);
if (u != null) {
@@ -118,9 +121,11 @@ public class CommentsArea {
}
void updateCommentsFromLeafInformation(final BugLeafNode node) {
- if (node == null)
+ if (node == null) {
return;
+ }
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
BugInstance bug = node.getBug();
Cloud plugin = getCloud();
@@ -145,6 +150,7 @@ public class CommentsArea {
void updateCommentsFromNonLeafInformation(final BugAspects theAspects) {
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
updateCommentsFromNonLeafInformationFromSwingThread(theAspects);
}
@@ -168,8 +174,9 @@ public class CommentsArea {
private @CheckForNull Cloud getCloud() {
MainFrame instance = MainFrame.getInstance();
BugCollection bugCollection = instance.getBugCollection();
- if (bugCollection == null)
+ if (bugCollection == null) {
return null;
+ }
return bugCollection.getCloud();
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/CompoundMatcher.java b/src/gui/edu/umd/cs/findbugs/gui2/CompoundMatcher.java
index 1e0cb4e..2de7491 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/CompoundMatcher.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/CompoundMatcher.java
@@ -34,13 +34,17 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
public class CompoundMatcher extends HashSet<Matcher> implements Matcher {
private static final long serialVersionUID = -6167545252176658833L;
+ @Override
public boolean match(BugInstance bugInstance) {
- for (Matcher i : this)
- if (!i.match(bugInstance))
+ for (Matcher i : this) {
+ if (!i.match(bugInstance)) {
return false;
+ }
+ }
return true;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
throw new UnsupportedOperationException();
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/DeadBugFilter.java b/src/gui/edu/umd/cs/findbugs/gui2/DeadBugFilter.java
index ac16699..4343815 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/DeadBugFilter.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/DeadBugFilter.java
@@ -19,18 +19,11 @@
package edu.umd.cs.findbugs.gui2;
-import edu.umd.cs.findbugs.BugInstance;
-
/**
* @author Dan
*/
public class DeadBugFilter extends FilterMatcher {
- /**
- * @param filterBy
- * @param value
- * @param mode
- */
public DeadBugFilter(Sortables filterBy, String value, FilterWhere mode) {
super(filterBy, value, mode);
}
@@ -40,8 +33,4 @@ public class DeadBugFilter extends FilterMatcher {
return edu.umd.cs.findbugs.L10N.getLocalString("pref.dead_bugs", "Dead Bugs");
}
- @Override
- public boolean match(BugInstance bugInstance) {
- return super.match(bugInstance);
- }
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/Debug.java b/src/gui/edu/umd/cs/findbugs/gui2/Debug.java
index 99c565d..7c5eff2 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/Debug.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/Debug.java
@@ -22,24 +22,27 @@ package edu.umd.cs.findbugs.gui2;
/**
* For debugging purposes only... Make sure DEBUG is set to false before you
* release a new version.
- *
+ *
* @author Dan
- *
+ *
*/
public class Debug {
public static void println(Object s) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.out.println(s);
+ }
}
public static void printf(String format, Object... args) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.out.printf(format, args);
+ }
}
public static void println(Exception e) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
e.printStackTrace();
+ }
}
public static void main(String[] args) {
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/DisplayNonmodelMessage.java b/src/gui/edu/umd/cs/findbugs/gui2/DisplayNonmodelMessage.java
index f19c905..9906891 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/DisplayNonmodelMessage.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/DisplayNonmodelMessage.java
@@ -50,11 +50,15 @@ public class DisplayNonmodelMessage {
static Font sourceFont = new Font("Monospaced", Font.PLAIN, (int) Driver.getFontSize());
+ static void setMessageFrame(JFrame messageFrame) {
+ DisplayNonmodelMessage.messageFrame = messageFrame;
+ }
+
public static void displayNonmodelMessage(String title, String message, @CheckForNull Component centerOver, boolean onTop) {
boolean positionWindow = false;
if (messageFrame == null) {
positionWindow = true;
- messageFrame = new JFrame(title);
+ setMessageFrame(new JFrame(title));
messageTextArea = new JTextArea(40, 80);
messageTextArea.setEditable(false);
@@ -75,7 +79,7 @@ public class DisplayNonmodelMessage {
@Override
public void windowClosed(WindowEvent e) {
JFrame tmp = messageFrame;
- messageFrame = null;
+ setMessageFrame(null);
tmp.setVisible(false);
tmp.dispose();
}
@@ -84,8 +88,9 @@ public class DisplayNonmodelMessage {
messageTextArea.setText(message);
messageFrame.setTitle(title);
messageFrame.pack();
- if (positionWindow)
+ if (positionWindow) {
messageFrame.setLocationRelativeTo(centerOver);
+ }
messageFrame.setVisible(true);
messageFrame.toFront();
@@ -103,33 +108,43 @@ public class DisplayNonmodelMessage {
}
}
+ /*
static Runnable moveToFrontLater = new Runnable() {
+ @Override
public void run() {
sleep(5);
SwingUtilities.invokeLater(moveToFront);
}
};
+ */
static Runnable clearAlwaysOnTopLater = new Runnable() {
+ @Override
public void run() {
sleep(5);
SwingUtilities.invokeLater(clearAlwaysOnTop);
}
};
+ /*
static Runnable moveToFront = new Runnable() {
+ @Override
public void run() {
JFrame frame = messageFrame;
- if (frame != null)
+ if (frame != null) {
frame.toFront();
+ }
}
};
+ */
static Runnable clearAlwaysOnTop = new Runnable() {
+ @Override
public void run() {
JFrame frame = messageFrame;
- if (frame != null)
+ if (frame != null) {
frame.setAlwaysOnTop(false);
+ }
}
};
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/Driver.java b/src/gui/edu/umd/cs/findbugs/gui2/Driver.java
index 54ca6e9..5e885e5 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/Driver.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/Driver.java
@@ -51,85 +51,88 @@ public class Driver {
public static void main(String[] args) throws Exception {
try {
- String name = "FindBugs GUI";
- if (JavaWebStart.isRunningViaJavaWebstart())
- name = "FindBugs webstart GUI";
- Version.registerApplication(name, Version.RELEASE);
-
- if (SystemProperties.getProperty("os.name").startsWith("Mac")) {
- System.setProperty("apple.laf.useScreenMenuBar", "true");
- System.setProperty("com.apple.mrj.application.apple.menu.about.name", "FindBugs");
- Debug.println("Mac OS detected");
- }
- splash = new SplashFrame();
- splash.setVisible(true);
-
- int numParsed = commandLine.parse(args, 0, 1, USAGE);
-
- //
- // See if an argument filename was specified after the parsed
- // options/switches.
- //
- if (numParsed < args.length) {
- String arg = args[numParsed];
- String argLowerCase = arg.toLowerCase(Locale.ENGLISH);
- if (argLowerCase.endsWith(".fbp") || argLowerCase.endsWith(".fb")) {
- // Project file specified
- commandLine.loadProject(arg);
- } else if (argLowerCase.endsWith(".xml") || argLowerCase.endsWith(".xml.gz") || argLowerCase.endsWith(".fba")) {
- // Saved analysis results specified
- commandLine.setSaveFile(new File(arg));
- } else {
- System.out.println("Unknown argument: " + arg);
- commandLine.printUsage(System.out);
- System.exit(1);
+ String name = "FindBugs GUI";
+ if (JavaWebStart.isRunningViaJavaWebstart()) {
+ name = "FindBugs webstart GUI";
}
- }
+ Version.registerApplication(name, Version.RELEASE);
- if (commandLine.getDocking()) {
- // make sure docking runtime support is available
- try {
- Class.forName("net.infonode.docking.DockingWindow");
- Class.forName("edu.umd.cs.findbugs.gui2.DockLayout");
- } catch (Exception e) {
- commandLine.setDocking(false);
+ if (SystemProperties.getProperty("os.name").startsWith("Mac")) {
+ System.setProperty("apple.laf.useScreenMenuBar", "true");
+ System.setProperty("com.apple.mrj.application.apple.menu.about.name", "FindBugs");
+ Debug.println("Mac OS detected");
+ }
+ splash = new SplashFrame();
+ splash.setVisible(true);
+
+ int numParsed = commandLine.parse(args, 0, 1, USAGE);
+
+ //
+ // See if an argument filename was specified after the parsed
+ // options/switches.
+ //
+ if (numParsed < args.length) {
+ String arg = args[numParsed];
+ String argLowerCase = arg.toLowerCase(Locale.ENGLISH);
+ if (argLowerCase.endsWith(".fbp") || argLowerCase.endsWith(".fb")) {
+ // Project file specified
+ commandLine.loadProject(arg);
+ } else if (argLowerCase.endsWith(".xml") || argLowerCase.endsWith(".xml.gz") || argLowerCase.endsWith(".fba")) {
+ // Saved analysis results specified
+ commandLine.setSaveFile(new File(arg));
+ } else {
+ System.out.println("Unknown argument: " + arg);
+ commandLine.printUsage(System.out);
+ System.exit(1);
+ }
}
- }
- try {
- GUISaveState.loadInstance();
- } catch (RuntimeException e) {
- GUISaveState.clear();
- e.printStackTrace();
- }
+ if (commandLine.getDocking()) {
+ // make sure docking runtime support is available
+ try {
+ Class.forName("net.infonode.docking.DockingWindow");
+ Class.forName("edu.umd.cs.findbugs.gui2.DockLayout");
+ } catch (Exception e) {
+ commandLine.setDocking(false);
+ }
+ }
- GUISaveState guiSavedPreferences = GUISaveState.getInstance();
- if (commandLine.isFontSizeSpecified())
- guiSavedPreferences.setFontSize(commandLine.getFontSize());
+ try {
+ GUISaveState.loadInstance();
+ } catch (RuntimeException e) {
+ GUISaveState.clear();
+ e.printStackTrace();
+ }
- // System.setProperty("findbugs.home",".."+File.separator+"findbugs");
+ GUISaveState guiSavedPreferences = GUISaveState.getInstance();
+ if (commandLine.isFontSizeSpecified()) {
+ guiSavedPreferences.setFontSize(commandLine.getFontSize());
+ }
- enablePlugins(guiSavedPreferences.getEnabledPlugins(), true);
- enablePlugins(guiSavedPreferences.getDisabledPlugins(), false);
+ // System.setProperty("findbugs.home",".."+File.separator+"findbugs");
- // The bug with serializable idiom detection has been fixed on the
- // findbugs end.
- // DetectorFactory
- // serializableIdiomDetector=DetectorFactoryCollection.instance().getFactory("SerializableIdiom");
- // System.out.println(serializableIdiomDetector.getFullName());
- // UserPreferences.getUserPreferences().enableDetector(serializableIdiomDetector,false);
+ enablePlugins(guiSavedPreferences.getEnabledPlugins(), true);
+ enablePlugins(guiSavedPreferences.getDisabledPlugins(), false);
- FindBugsLayoutManagerFactory factory;
+ // The bug with serializable idiom detection has been fixed on the
+ // findbugs end.
+ // DetectorFactory
+ // serializableIdiomDetector=DetectorFactoryCollection.instance().getFactory("SerializableIdiom");
+ // System.out.println(serializableIdiomDetector.getFullName());
+ // UserPreferences.getUserPreferences().enableDetector(serializableIdiomDetector,false);
- if (isDocking())
- factory = new FindBugsLayoutManagerFactory("edu.umd.cs.findbugs.gui2.DockLayout");
- else
- factory = new FindBugsLayoutManagerFactory(SplitLayout.class.getName());
- MainFrame.makeInstance(factory);
+ FindBugsLayoutManagerFactory factory;
+ if (isDocking()) {
+ factory = new FindBugsLayoutManagerFactory("edu.umd.cs.findbugs.gui2.DockLayout");
+ } else {
+ factory = new FindBugsLayoutManagerFactory(SplitLayout.class.getName());
+ }
+ MainFrame.makeInstance(factory);
- splash.setVisible(false);
- splash.dispose();
+
+ splash.setVisible(false);
+ splash.dispose();
} catch (Throwable t) {
JOptionPane.showMessageDialog(null, t.toString(), "Fatal Error during FindBugs startup", JOptionPane.ERROR_MESSAGE);
t.printStackTrace(System.err);
@@ -141,19 +144,21 @@ public class Driver {
for (String pid : plugins) {
Plugin plugin = Plugin.getByPluginId(pid);
if (plugin != null) {
- if (!enabled && plugin.cannotDisable())
+ if (!enabled && plugin.cannotDisable()) {
JOptionPane.showMessageDialog(null,
"Cannot disable plugin: " + plugin.getPluginId() + "\n" + plugin.getShortDescription(),
"Cannot disable plugin", JOptionPane.ERROR_MESSAGE);
- else
+ } else {
plugin.setGloballyEnabled(enabled);
+ }
}
}
}
public static void removeSplashScreen() {
- if (splash == null)
+ if (splash == null) {
return;
+ }
splash.setVisible(false);
splash.dispose();
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/FBDialog.java b/src/gui/edu/umd/cs/findbugs/gui2/FBDialog.java
index 8e4025d..15acda7 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/FBDialog.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/FBDialog.java
@@ -28,9 +28,9 @@ import javax.swing.JDialog;
/**
* All Dialogs are FBDialogs so font size will work.
- *
+ *
* @author Kristin
- *
+ *
*/
@SuppressWarnings("serial")
public class FBDialog extends JDialog {
@@ -49,7 +49,7 @@ public class FBDialog extends JDialog {
/**
* Sets size of font
- *
+ *
* @param size
*/
protected void setFontSize(float size) {
@@ -62,13 +62,15 @@ public class FBDialog extends JDialog {
* Helps above method, runs through all components recursively.
*/
protected void setFontSizeHelper(Component[] comps, float size) {
- if (comps.length <= 0)
+ if (comps.length <= 0) {
return;
+ }
for (Component comp : comps) {
comp.setFont(comp.getFont().deriveFont(size));
- if (comp instanceof Container)
+ if (comp instanceof Container) {
setFontSizeHelper(((Container) comp).getComponents(), size);
+ }
}
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/FBFileChooser.java b/src/gui/edu/umd/cs/findbugs/gui2/FBFileChooser.java
index 32c623e..4abd7f2 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/FBFileChooser.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/FBFileChooser.java
@@ -35,9 +35,9 @@ import edu.umd.cs.findbugs.SystemProperties;
/**
* All FileChoosers are FBFileChoosers so font size will work
- *
+ *
* @author Kristin
- *
+ *
*/
public class FBFileChooser extends JFileChooser {
@@ -49,7 +49,7 @@ public class FBFileChooser extends JFileChooser {
/**
* Sets size of font
- *
+ *
* @param size
*/
protected void setFontSize(float size) {
@@ -62,13 +62,15 @@ public class FBFileChooser extends JFileChooser {
* Helps above method, runs through all components recursively.
*/
protected void setFontSizeHelper(Component[] comps, float size) {
- if (comps.length <= 0)
+ if (comps.length <= 0) {
return;
+ }
for (Component comp : comps) {
comp.setFont(comp.getFont().deriveFont(size));
- if (comp instanceof Container)
+ if (comp instanceof Container) {
setFontSizeHelper(((Container) comp).getComponents(), size);
+ }
}
}
@@ -99,8 +101,9 @@ public class FBFileChooser extends JFileChooser {
public int showOpenDialog(Component parent) {
assert java.awt.EventQueue.isDispatchThread();
int x = super.showOpenDialog(parent);
- if (SystemProperties.getProperty("os.name").startsWith("Mac"))
+ if (SystemProperties.getProperty("os.name").startsWith("Mac")) {
workAroundJFileChooserBug();
+ }
GUISaveState.getInstance().setStarterDirectoryForLoadBugs(getCurrentDirectory());
@@ -111,8 +114,9 @@ public class FBFileChooser extends JFileChooser {
public int showSaveDialog(Component parent) {
assert java.awt.EventQueue.isDispatchThread();
int x = super.showSaveDialog(parent);
- if (SystemProperties.getProperty("os.name").startsWith("Mac"))
+ if (SystemProperties.getProperty("os.name").startsWith("Mac")) {
workAroundJFileChooserBug();
+ }
GUISaveState.getInstance().setStarterDirectoryForLoadBugs(getCurrentDirectory());
@@ -123,14 +127,15 @@ public class FBFileChooser extends JFileChooser {
public int showDialog(Component parent, String approveButtonText) {
assert java.awt.EventQueue.isDispatchThread();
int x = super.showDialog(parent, approveButtonText);
- if (SystemProperties.getProperty("os.name").startsWith("Mac"))
+ if (SystemProperties.getProperty("os.name").startsWith("Mac")) {
workAroundJFileChooserBug();
+ }
GUISaveState.getInstance().setStarterDirectoryForLoadBugs(getCurrentDirectory());
return x;
}
-
+
private void addHiddenFileCheckBox() {
final JCheckBox showHiddenFileCheckBox = new JCheckBox("Show Hidden");
JPanel accessory = new JPanel();
@@ -140,6 +145,7 @@ public class FBFileChooser extends JFileChooser {
setAccessory(accessory);
showHiddenFileCheckBox.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent ae) {
setFileHidingEnabled(!showHiddenFileCheckBox.isSelected());
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/FBFrame.java b/src/gui/edu/umd/cs/findbugs/gui2/FBFrame.java
index ce56fe9..fd2c4cf 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/FBFrame.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/FBFrame.java
@@ -31,7 +31,7 @@ public class FBFrame extends JFrame {
/**
* Sets size of font
- *
+ *
* @param size
*/
protected void setFontSize(float size) {
@@ -57,8 +57,9 @@ public class FBFrame extends JFrame {
protected void setFontSizeHelper(float size, Component... comps) {
for (Component comp : comps) {
comp.setFont(comp.getFont().deriveFont(size));
- if (comp instanceof Container)
+ if (comp instanceof Container) {
setFontSizeHelper(size, ((Container) comp).getComponents());
+ }
}
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/FilterActivity.java b/src/gui/edu/umd/cs/findbugs/gui2/FilterActivity.java
index 6ad5f9c..07e7629 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/FilterActivity.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/FilterActivity.java
@@ -47,14 +47,15 @@ public class FilterActivity {
switch (whatsGoingOnCode) {
case FILTERING:
case UNFILTERING:
- for (FilterListener i : currentListeners)
+ for (FilterListener i : currentListeners) {
i.clearCache();
+ }
break;
-
+
}
MainFrame.getInstance().updateStatusBar();
}
-
+
public static class FilterActivityNotifier {
public void notifyListeners(FilterListener.Action whatsGoingOnCode, TreePath optionalPath) {
FilterActivity.notifyListeners(whatsGoingOnCode, optionalPath);
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/FilterFactory.java b/src/gui/edu/umd/cs/findbugs/gui2/FilterFactory.java
index 09c7659..b096172 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/FilterFactory.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/FilterFactory.java
@@ -41,7 +41,7 @@ import edu.umd.cs.findbugs.util.NotImplementedYetException;
* @author pugh
*/
public class FilterFactory {
-
+
public static Matcher makeOrMatcher(Collection<SortableValue> sortables) {
return makeMatcher(sortables, false);
}
@@ -54,39 +54,44 @@ public class FilterFactory {
if (originalMatcher instanceof NotMatcher) {
return ((NotMatcher) originalMatcher).originalMatcher();
}
-
+
NotMatcher notMatcher = new NotMatcher();
notMatcher.addChild(originalMatcher);
return notMatcher;
}
-
+
private static Matcher makeMatcher(Collection<SortableValue> sortables, boolean andOr) {
if (sortables.size() == 1) {
- for (SortableValue s : sortables)
+ for (SortableValue s : sortables) {
return makeMatcher(s);
+ }
}
edu.umd.cs.findbugs.filter.CompoundMatcher matcher;
- if (andOr == true)
+ if (andOr == true) {
matcher = new AndMatcher();
- else
+ } else {
matcher = new OrMatcher();
- for (SortableValue s : sortables)
+ }
+ for (SortableValue s : sortables) {
matcher.addChild(makeMatcher(s));
+ }
return matcher;
}
public static Matcher makeMatcher(Collection<Sortables> sortables, BugInstance bug) {
if (sortables.size() == 1) {
- for (Sortables s : sortables)
+ for (Sortables s : sortables) {
return makeMatcher(s, bug);
+ }
}
AndMatcher matcher = new AndMatcher();
- for (Sortables s : sortables)
+ for (Sortables s : sortables) {
matcher.addChild(makeMatcher(s, bug));
+ }
return matcher;
}
-
+
public static boolean canFilter(Sortables s) {
switch (s) {
case BUGCODE:
@@ -104,7 +109,7 @@ public class FilterFactory {
return false;
}
}
-
+
private static Matcher makeMatcher(Sortables s, BugInstance bug) {
switch (s) {
@@ -124,18 +129,19 @@ public class FilterFactory {
case PACKAGE:
String p = Sortables.CLASS.getFrom(bug);
int lastDot = p.lastIndexOf('.');
- if (lastDot > 0)
+ if (lastDot > 0) {
p = p.substring(0, lastDot);
+ }
return new ClassMatcher("~" + p + "\\.[^.]+");
case PRIORITY:
return new PriorityMatcher(Integer.toString(bug.getPriority()));
-
+
case TYPE:
return new BugMatcher(null, s.getFrom(bug), null);
case BUG_RANK:
return new RankMatcher(s.getFrom(bug));
-
+
case DIVIDER:
default:
throw new IllegalArgumentException("Don't know how to make maker for " + s);
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/FilterFromBugPicker.java b/src/gui/edu/umd/cs/findbugs/gui2/FilterFromBugPicker.java
index bc0db3e..384f784 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/FilterFromBugPicker.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/FilterFromBugPicker.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -38,19 +38,19 @@ import edu.umd.cs.findbugs.filter.NotMatcher;
/**
* Creates a list of options on for filtering bugs based on the current bug selected.
- *
+ *
* Gives the option to invert the created filter by wrapping it in a {@link NotMatcher}.
- *
+ *
* @author Graham Allan (grundlefleck at gmail.com)
*/
final class FilterFromBugPicker {
-
+
private final HashMap<JCheckBox, Sortables> map = new HashMap<JCheckBox, Sortables>();
private final BugInstance bug;
private final List<Sortables> availableSortables;
private final JPanel pickerPanel;
private final JCheckBox notFilterCheck = new JCheckBox("Invert (i.e. filter bugs which do not match selected criteria).");
-
+
public FilterFromBugPicker(BugInstance bug, List<Sortables> availableSortables) {
this.bug = bug;
this.availableSortables = availableSortables;
@@ -61,19 +61,19 @@ final class FilterFromBugPicker {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(new EmptyBorder(new Insets(6, 6, 6, 6)));
-
+
addFilterLikeCheckboxes(panel);
addNotFilterOption(panel);
-
+
return panel;
}
-
+
private void addFilterLikeCheckboxes(JPanel center) {
for (Sortables sortable : availableSortables) {
if (!FilterFactory.canFilter(sortable)) { continue; }
-
+
JCheckBox checkBox = new JCheckBox(sortable.toString() + " is " + sortable.formatValue(sortable.getFrom(bug)));
-
+
map.put(checkBox, sortable);
center.add(checkBox);
}
@@ -98,13 +98,13 @@ final class FilterFromBugPicker {
Matcher matcher = null;
if (!set.isEmpty()) {
matcher = FilterFactory.makeMatcher(set, bug);
-
+
if(notFilterCheck.isSelected()) {
matcher = FilterFactory.invertMatcher(matcher);
}
}
-
+
return matcher;
}
-
+
}
\ No newline at end of file
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/FilterMatcher.java b/src/gui/edu/umd/cs/findbugs/gui2/FilterMatcher.java
index c683ea8..0fef6b6 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/FilterMatcher.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/FilterMatcher.java
@@ -61,22 +61,22 @@ public class FilterMatcher implements Matcher, Serializable, Comparable<FilterMa
}
public FilterMatcher(Sortables filterBy, String value, FilterWhere mode) // 0
- // =
- // exactly;
- // 1
- // =
- // at
- // or
- // after;
- // 2
- // =
- // at
- // or
- // before;
- // 3
- // =
- // not
- // at
+ // =
+ // exactly;
+ // 1
+ // =
+ // at
+ // or
+ // after;
+ // 2
+ // =
+ // at
+ // or
+ // before;
+ // 3
+ // =
+ // not
+ // at
{
this.filterBy = filterBy;
this.value = value;
@@ -94,10 +94,11 @@ public class FilterMatcher implements Matcher, Serializable, Comparable<FilterMa
public void setActive(boolean active) {
if (active != this.active) {
this.active = active;
- if (active == true)
+ if (active == true) {
FilterActivity.notifyListeners(FilterListener.Action.FILTERING, null);
- else
+ } else {
FilterActivity.notifyListeners(FilterListener.Action.UNFILTERING, null);
+ }
}
}
@@ -105,9 +106,11 @@ public class FilterMatcher implements Matcher, Serializable, Comparable<FilterMa
return active;
}
+ @Override
public boolean match(BugInstance bugInstance) {
- if (!active)
+ if (!active) {
return true;
+ }
SortableStringComparator ssc = filterBy.getComparator();
int compare = ssc.compare(filterBy.getFrom(bugInstance), value);
@@ -130,19 +133,19 @@ public class FilterMatcher implements Matcher, Serializable, Comparable<FilterMa
switch (mode) {
case FILTER_EXACTLY:
return filterBy.toString() + " " + edu.umd.cs.findbugs.L10N.getLocalString("dlg.is", "is") + " "
- + edu.umd.cs.findbugs.L10N.getLocalString("mode.equal_to", "equal to") + " " + filterBy.formatValue(value);
+ + edu.umd.cs.findbugs.L10N.getLocalString("mode.equal_to", "equal to") + " " + filterBy.formatValue(value);
case FILTER_AT_OR_AFTER:
return filterBy.toString() + " " + edu.umd.cs.findbugs.L10N.getLocalString("dlg.is", "is") + " "
- + edu.umd.cs.findbugs.L10N.getLocalString("mode.at_or_after", "at or after") + " "
- + filterBy.formatValue(value);
+ + edu.umd.cs.findbugs.L10N.getLocalString("mode.at_or_after", "at or after") + " "
+ + filterBy.formatValue(value);
case FILTER_AT_OR_BEFORE:
return filterBy.toString() + " " + edu.umd.cs.findbugs.L10N.getLocalString("dlg.is", "is") + " "
- + edu.umd.cs.findbugs.L10N.getLocalString("mode.at_or_before", "at or before") + " "
- + filterBy.formatValue(value);
+ + edu.umd.cs.findbugs.L10N.getLocalString("mode.at_or_before", "at or before") + " "
+ + filterBy.formatValue(value);
case FILTER_ALL_BUT:
return filterBy.toString() + " " + edu.umd.cs.findbugs.L10N.getLocalString("dlg.is", "is") + " "
- + edu.umd.cs.findbugs.L10N.getLocalString("mode.not_equal_to", "not equal to") + " "
- + filterBy.formatValue(value);
+ + edu.umd.cs.findbugs.L10N.getLocalString("mode.not_equal_to", "not equal to") + " "
+ + filterBy.formatValue(value);
default:
throw new RuntimeException();
}
@@ -150,13 +153,16 @@ public class FilterMatcher implements Matcher, Serializable, Comparable<FilterMa
@Override
public boolean equals(Object o) {
- if (o == null)
+ if (o == null) {
return false;
- if (getClass() != o.getClass())
+ }
+ if (getClass() != o.getClass()) {
return false;
+ }
- if (filterBy.equals(((FilterMatcher) o).filterBy) && value.equals(((FilterMatcher) o).value))
+ if (filterBy.equals(((FilterMatcher) o).filterBy) && value.equals(((FilterMatcher) o).value)) {
return true;
+ }
return false;
}
@@ -165,13 +171,16 @@ public class FilterMatcher implements Matcher, Serializable, Comparable<FilterMa
return value.hashCode() + filterBy.hashCode();
}
+ @Override
public int compareTo(FilterMatcher that) {
- if (this.filterBy != that.filterBy)
+ if (this.filterBy != that.filterBy) {
return (this.filterBy.ordinal() < that.filterBy.ordinal() ? -1 : 1);
+ }
return this.value.compareTo(that.value);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
throw new UnsupportedOperationException();
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/GUI2CommandLine.java b/src/gui/edu/umd/cs/findbugs/gui2/GUI2CommandLine.java
index cacaacd..03cfd01 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/GUI2CommandLine.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/GUI2CommandLine.java
@@ -28,7 +28,7 @@ import edu.umd.cs.findbugs.FindBugsCommandLine;
/**
* Command line switches/options for GUI2.
- *
+ *
* @author David Hovemeyer
*/
public class GUI2CommandLine extends FindBugsCommandLine {
@@ -51,24 +51,24 @@ public class GUI2CommandLine extends FindBugsCommandLine {
@Override
protected void handleOption(String option, String optionExtraPart) {
- if (option.equals("-clear")) {
+ if ("-clear".equals(option)) {
GUISaveState.clear();
System.exit(0);
- } else if (option.equals("-d") || option.equals("--nodock")) {
+ } else if ("-d".equals(option) || "--nodock".equals(option)) {
docking = false;
- } else if (option.equals("-look")) {
+ } else if ("-look".equals(option)) {
String arg = optionExtraPart;
String theme = null;
- if (arg.equals("plastic")) {
+ if ("plastic".equals(arg)) {
// You can get the Plastic look and feel from jgoodies.com:
// http://www.jgoodies.com/downloads/libraries.html
// Just put "plastic.jar" in the lib directory, right next
// to the other jar files.
theme = "com.jgoodies.plaf.plastic.PlasticXPLookAndFeel";
- } else if (arg.equals("gtk")) {
+ } else if ("gtk".equals(arg)) {
theme = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
- } else if (arg.equals("native")) {
+ } else if ("native".equals(arg)) {
theme = UIManager.getSystemLookAndFeelClassName();
} else {
System.err.println("Style '" + arg + "' not supported");
@@ -88,20 +88,20 @@ public class GUI2CommandLine extends FindBugsCommandLine {
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-f")) {
+ if ("-f".equals(option)) {
try {
fontSize = Float.parseFloat(argument);
fontSizeSpecified = true;
} catch (NumberFormatException e) {
// ignore
}
- } else if (option.equals("-priority")) {
+ } else if ("-priority".equals(option)) {
try {
priority = Integer.parseInt(argument);
} catch (NumberFormatException e) {
// ignore
}
- } else if (option.equals("-loadBugs") || option.equals("-loadbugs")) {
+ } else if ("-loadBugs".equals(option) || "-loadbugs".equals(option)) {
saveFile = new File(argument);
if (!saveFile.exists()) {
System.err.println("Bugs file \"" + argument + "\" could not be found");
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/GUISaveState.java b/src/gui/edu/umd/cs/findbugs/gui2/GUISaveState.java
index 70efd81..90d5662 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/GUISaveState.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/GUISaveState.java
@@ -70,7 +70,7 @@ public class GUISaveState {
private static final int MAXNUMRECENTPROJECTS = 5;
private static final Sortables[] DEFAULT_COLUMN_HEADERS = new Sortables[] { Sortables.CATEGORY, Sortables.BUGCODE,
- Sortables.TYPE, Sortables.DIVIDER, Sortables.BUG_RANK, Sortables.FIRST_SEEN, Sortables.DESIGNATION };
+ Sortables.TYPE, Sortables.DIVIDER, Sortables.BUG_RANK, Sortables.FIRST_SEEN, Sortables.DESIGNATION };
private static final String[] RECENTPROJECTKEYS = new String[MAXNUMRECENTPROJECTS];
@@ -93,10 +93,12 @@ public class GUISaveState {
static {
- for (int x = 0; x < RECENTPROJECTKEYS.length; x++)
+ for (int x = 0; x < RECENTPROJECTKEYS.length; x++) {
RECENTPROJECTKEYS[x] = "Project" + x;
- for (int x = 0; x < COMMENTKEYS.length; x++)
+ }
+ for (int x = 0; x < COMMENTKEYS.length; x++) {
COMMENTKEYS[x] = "Comment" + x;
+ }
}
private int splitMain;
@@ -135,7 +137,7 @@ public class GUISaveState {
private List<String> enabledPlugins = new ArrayList<String>();
private List<String> disabledPlugins = new ArrayList<String>();
- private LinkedHashSet<URI> customPlugins = new LinkedHashSet<URI>();
+ private final LinkedHashSet<URI> customPlugins = new LinkedHashSet<URI>();
private static String[] generateSorterKeys(int numSorters) {
String[] result = new String[numSorters];
@@ -146,8 +148,9 @@ public class GUISaveState {
}
public static synchronized GUISaveState getInstance() {
- if (instance == null)
+ if (instance == null) {
instance = new GUISaveState();
+ }
return instance;
}
@@ -183,8 +186,9 @@ public class GUISaveState {
Sortables s = Sortables.getSortableByPrettyName(p.get(sortKeys[x], "*none*"));
if (s == null) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.err.println("Sort order was corrupted, using default sort order");
+ }
newInstance.useDefault = true;
break;
}
@@ -197,8 +201,9 @@ public class GUISaveState {
sortColumns.addAll(missingSortColumns);
newInstance.sortColumns = sortColumns.toArray(new Sortables[sortColumns.size()]);
}
- } else
+ } else {
newInstance.useDefault = true;
+ }
newInstance.dockingLayout = p.getByteArray(DOCKINGLAYOUT, new byte[0]);
@@ -206,30 +211,34 @@ public class GUISaveState {
Rectangle r = new Rectangle(0, 0, 800, 650);
if (boundsString != null) {
String[] a = boundsString.split(",", 4);
- if (a.length > 0)
+ if (a.length > 0) {
try {
r.x = Math.max(0, Integer.parseInt(a[0]));
} catch (NumberFormatException nfe) {
assert true;
}
- if (a.length > 1)
+ }
+ if (a.length > 1) {
try {
r.y = Math.max(0, Integer.parseInt(a[1]));
} catch (NumberFormatException nfe) {
assert true;
}
- if (a.length > 2)
+ }
+ if (a.length > 2) {
try {
r.width = Math.max(40, Integer.parseInt(a[2]));
} catch (NumberFormatException nfe) {
assert true;
}
- if (a.length > 3)
+ }
+ if (a.length > 3) {
try {
r.height = Math.max(40, Integer.parseInt(a[3]));
} catch (NumberFormatException nfe) {
assert true;
}
+ }
}
newInstance.frameBounds = r;
newInstance.extendedWindowState = p.getInt(EXTENDED_WINDOW_STATE, Frame.NORMAL);
@@ -241,16 +250,17 @@ public class GUISaveState {
newInstance.packagePrefixSegments = p.getInt(PACKAGE_PREFIX_SEGEMENTS, 3);
String plugins = p.get(CUSTOM_PLUGINS, "");
- if (plugins.length() > 0)
+ if (plugins.length() > 0) {
for (String s : plugins.split(" ")) {
- try {
- URI u = new URI(s);
- Plugin.addCustomPlugin(u);
- newInstance.customPlugins.add(u);
- } catch (PluginException e) {
- assert true;
- } catch (URISyntaxException e) {
- assert true;
+ try {
+ URI u = new URI(s);
+ Plugin.addCustomPlugin(u);
+ newInstance.customPlugins.add(u);
+ } catch (PluginException e) {
+ assert true;
+ } catch (URISyntaxException e) {
+ assert true;
+ }
}
}
@@ -320,8 +330,9 @@ public class GUISaveState {
* @param f
*/
public void addRecentFile(File f) {
- if (null != f)
+ if (null != f) {
recentFiles.add(f);
+ }
}
/**
@@ -341,8 +352,9 @@ public class GUISaveState {
public void fileNotFound(File f) {
if (!recentFiles.contains(f)) {
throw new IllegalStateException("Well no wonder it wasn't found, its not in the list.");
- } else
+ } else {
recentFiles.remove(f);
+ }
}
@@ -550,7 +562,7 @@ public class GUISaveState {
try {
return customPlugins.add(u.toURI());
} catch (URISyntaxException e) {
- throw new IllegalArgumentException("Error converting to uri: " + u, e);
+ throw new IllegalArgumentException("Error converting to uri: " + u, e);
}
}
public List<String> getDisabledPlugins() {
@@ -566,13 +578,15 @@ public class GUISaveState {
}
SorterTableColumnModel getStarterTable() {
- if (starterTable != null)
+ if (starterTable != null) {
return starterTable;
+ }
- if (useDefault || sortColumns == null)
+ if (useDefault || sortColumns == null) {
starterTable = new SorterTableColumnModel(GUISaveState.DEFAULT_COLUMN_HEADERS);
- else
+ } else {
starterTable = new SorterTableColumnModel(sortColumns);
+ }
return starterTable;
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/MainFrame.java b/src/gui/edu/umd/cs/findbugs/gui2/MainFrame.java
index 1e8fb3e..da3d3f6 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/MainFrame.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/MainFrame.java
@@ -177,15 +177,17 @@ public class MainFrame extends FBFrame implements LogSync {
private final PluginUpdateDialog pluginUpdateDialog = new PluginUpdateDialog();
public static void makeInstance(FindBugsLayoutManagerFactory factory) {
- if (instance != null)
+ if (instance != null) {
throw new IllegalStateException();
+ }
instance = new MainFrame(factory);
instance.initializeGUI();
}
public static MainFrame getInstance() {
- if (instance == null)
+ if (instance == null) {
throw new IllegalStateException();
+ }
return instance;
}
@@ -215,8 +217,9 @@ public class MainFrame extends FBFrame implements LogSync {
System.err.println("acquiring display wait, count " + waitCount);
Thread.dumpStack();
}
- if (waitCount == 1)
+ if (waitCount == 1) {
mainFrameTree.showCard(BugCard.WAITCARD, new Cursor(Cursor.WAIT_CURSOR), this);
+ }
}
}
@@ -225,10 +228,11 @@ public class MainFrame extends FBFrame implements LogSync {
public void releaseDisplayWait() {
synchronized (waitLock) {
if (waitCount <= 0) {
- if (previousDecrementToZero != null)
+ if (previousDecrementToZero != null) {
throw new IllegalStateException("Can't decrease wait count; already zero", previousDecrementToZero);
- else
+ } else {
throw new IllegalStateException("Can't decrease wait count; never incremented");
+ }
}
waitCount--;
if (GUI2_DEBUG) {
@@ -271,11 +275,13 @@ public class MainFrame extends FBFrame implements LogSync {
* b.
*/
public void setProjectChanged(boolean b) {
- if (curProject == null)
+ if (curProject == null) {
return;
+ }
- if (projectChanged == b)
+ if (projectChanged == b) {
return;
+ }
projectChanged = b;
mainFrameMenu.setSaveMenu(this);
@@ -287,6 +293,7 @@ public class MainFrame extends FBFrame implements LogSync {
/**
* Show an error dialog.
*/
+ @Override
public void error(String message) {
JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE);
}
@@ -294,9 +301,11 @@ public class MainFrame extends FBFrame implements LogSync {
/**
* Write a message to stdout.
*/
+ @Override
public void writeToLog(String message) {
- if (GUI2_DEBUG)
+ if (GUI2_DEBUG) {
System.out.println(message);
+ }
}
public int showConfirmDialog(String message, String title, int optionType) {
@@ -342,22 +351,23 @@ public class MainFrame extends FBFrame implements LogSync {
+ edu.umd.cs.findbugs.L10N.getLocalString("statusbar.bugs_hidden", "bugs hidden (see view menu)");
}
msg = updateCloudSigninStatus(msg);
- if (errorMsg != null && errorMsg.length() > 0)
+ if (errorMsg != null && errorMsg.length() > 0) {
msg = join(msg, errorMsg);
+ }
mainFrameTree.setWaitStatusLabelText(msg); // should not be the URL
- if (msg.length() == 0)
+ if (msg.length() == 0) {
msg = "http://findbugs.sourceforge.net";
+ }
statusBarLabel.setText(msg);
}
private String updateCloudSigninStatus(String msg) {
if (getBugCollection() != null) {
Cloud cloud = getBugCollection().getCloud();
- if (cloud != null) {
- String pluginMsg = cloud.getStatusMsg();
- if (pluginMsg != null && pluginMsg.length() > 1)
- msg = join(msg, pluginMsg);
+ String pluginMsg = cloud.getStatusMsg();
+ if (pluginMsg != null && pluginMsg.length() > 1) {
+ msg = join(msg, pluginMsg);
}
}
return msg;
@@ -368,8 +378,9 @@ public class MainFrame extends FBFrame implements LogSync {
* the exit menuItem or by clicking on the window's system menu.
*/
void callOnClose() {
- if (!canNavigateAway())
+ if (!canNavigateAway()) {
return;
+ }
if (projectChanged && !SystemProperties.getBoolean("findbugs.skipSaveChangesWarning")) {
Object[] options = {
@@ -381,15 +392,17 @@ public class MainFrame extends FBFrame implements LogSync {
edu.umd.cs.findbugs.L10N.getLocalString("msg.confirm_save_txt", "Do you want to save?"),
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
- if (value == 2 || value == JOptionPane.CLOSED_OPTION)
+ if (value == 2 || value == JOptionPane.CLOSED_OPTION) {
return;
- else if (value == 0) {
+ } else if (value == 0) {
if (saveFile == null) {
- if (!mainFrameLoadSaveHelper.saveAs())
+ if (!mainFrameLoadSaveHelper.saveAs()) {
return;
- } else
+ }
+ } else {
mainFrameLoadSaveHelper.save();
+ }
}
}
@@ -400,8 +413,7 @@ public class MainFrame extends FBFrame implements LogSync {
guiSaveState.save();
if (this.bugCollection != null) {
Cloud cloud = this.bugCollection.getCloud();
- if (cloud != null)
- cloud.shutdown();
+ cloud.shutdown();
}
System.exit(0);
}
@@ -463,10 +475,11 @@ public class MainFrame extends FBFrame implements LogSync {
@SwingThread
private void setProjectAndBugCollection(@CheckForNull Project project, @CheckForNull BugCollection bugCollection) {
if (GUI2_DEBUG) {
- if (bugCollection == null)
+ if (bugCollection == null) {
System.out.println("Setting bug collection to null");
- else
+ } else {
System.out.println("Setting bug collection; contains " + bugCollection.getCollection().size() + " bugs");
+ }
}
if (bugCollection != null && bugCollection.getProject() != project) {
@@ -479,11 +492,9 @@ public class MainFrame extends FBFrame implements LogSync {
if (this.bugCollection != bugCollection && this.bugCollection != null) {
Cloud plugin = this.bugCollection.getCloud();
- if (plugin != null) {
- plugin.removeListener(userAnnotationListener);
- plugin.removeStatusListener(cloudStatusListener);
- plugin.shutdown();
- }
+ plugin.removeListener(userAnnotationListener);
+ plugin.removeStatusListener(cloudStatusListener);
+ plugin.shutdown();
}
// setRebuilding(false);
setProject(project);
@@ -494,14 +505,13 @@ public class MainFrame extends FBFrame implements LogSync {
displayer.clearCache();
if (bugCollection != null) {
Cloud plugin = bugCollection.getCloud();
- if (plugin != null) {
- plugin.addListener(userAnnotationListener);
- plugin.addStatusListener(cloudStatusListener);
- }
+ plugin.addListener(userAnnotationListener);
+ plugin.addStatusListener(cloudStatusListener);
}
mainFrameTree.updateBugTree();
setProjectChanged(false);
Runnable runnable = new Runnable() {
+ @Override
public void run() {
PreferencesFrame.getInstance().updateFilterPanel();
mainFrameMenu.getReconfigMenuItem().setEnabled(true);
@@ -519,10 +529,11 @@ public class MainFrame extends FBFrame implements LogSync {
updateTitle();
}
};
- if (SwingUtilities.isEventDispatchThread())
+ if (SwingUtilities.isEventDispatchThread()) {
runnable.run();
- else
+ } else {
SwingUtilities.invokeLater(runnable);
+ }
} finally {
releaseDisplayWait();
}
@@ -545,21 +556,24 @@ public class MainFrame extends FBFrame implements LogSync {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
- @SuppressWarnings({ "SimplifiableIfStatement" })
+ // @SuppressWarnings({ "SimplifiableIfStatement" })
boolean shouldDisplayIssue(BugInstance b) {
Project project = getProject();
Filter suppressionFilter = project.getSuppressionFilter();
- if (null == getBugCollection() || suppressionFilter.match(b))
+ if (null == getBugCollection() || suppressionFilter.match(b)) {
return false;
+ }
return viewFilter.show(b);
}
// ============================= menu actions
// ===============================
+ @SuppressWarnings("unused")
public void createNewProjectFromMenuItem() {
- if (!canNavigateAway())
+ if (!canNavigateAway()) {
return;
+ }
new NewProjectWizard();
newProject = true;
@@ -589,8 +603,9 @@ public class MainFrame extends FBFrame implements LogSync {
}
void preferences() {
- if (!canNavigateAway())
+ if (!canNavigateAway()) {
return;
+ }
PreferencesFrame.getInstance().setLocationRelativeTo(this);
PreferencesFrame.getInstance().setVisible(true);
}
@@ -608,25 +623,27 @@ public class MainFrame extends FBFrame implements LogSync {
}
void redoAnalysis() {
- if (!canNavigateAway())
+ if (!canNavigateAway()) {
return;
+ }
/// QQQ-TODO: new RuntimeException("Redo analysis called").printStackTrace();
acquireDisplayWait();
edu.umd.cs.findbugs.util.Util.runInDameonThread(
- new Runnable() {
- public void run() {
- try {
- updateDesignationDisplay();
- Project project = getProject();
- BugCollection bc = BugLoader.redoAnalysisKeepComments(project);
- updateProjectAndBugCollection(bc);
- setProjectAndBugCollectionInSwingThread(project, bc);
- } finally {
- releaseDisplayWait();
- }
- }
- });
+ new Runnable() {
+ @Override
+ public void run() {
+ try {
+ updateDesignationDisplay();
+ Project project = getProject();
+ BugCollection bc = BugLoader.redoAnalysisKeepComments(project);
+ updateProjectAndBugCollection(bc);
+ setProjectAndBugCollectionInSwingThread(project, bc);
+ } finally {
+ releaseDisplayWait();
+ }
+ }
+ });
}
// ================================== misc junk 2
@@ -654,6 +671,7 @@ public class MainFrame extends FBFrame implements LogSync {
void clearSourcePane() {
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
mainFrameComponentFactory.setSourceTab("", null);
sourceCodeTextPane.setDocument(SourceCodeDisplay.SOURCE_NOT_RELEVANT);
@@ -706,10 +724,11 @@ public class MainFrame extends FBFrame implements LogSync {
private String getActionWithoutSavingMsg(String action) {
String msg = edu.umd.cs.findbugs.L10N.getLocalString("msg.you_are_" + action + "_without_saving_txt", null);
- if (msg != null)
+ if (msg != null) {
return msg;
+ }
return edu.umd.cs.findbugs.L10N.getLocalString("msg.you_are_" + action + "_txt", "You are " + action) + " "
- + edu.umd.cs.findbugs.L10N.getLocalString("msg.without_saving_txt", "without saving. Do you want to save?");
+ + edu.umd.cs.findbugs.L10N.getLocalString("msg.without_saving_txt", "without saving. Do you want to save?");
}
public void updateBugTree() {
@@ -727,23 +746,27 @@ public class MainFrame extends FBFrame implements LogSync {
public void updateTitle() {
Project project = getProject();
String name = project.getProjectName();
- if ((name == null || name.trim().equals("")) && saveFile != null)
+ if ((name == null || "".equals(name.trim())) && saveFile != null) {
name = saveFile.getAbsolutePath();
- if (name == null)
+ }
+ if (name == null) {
name = "";//Project.UNNAMED_PROJECT;
+ }
String oldTitle = this.getTitle();
- String newTitle = TITLE_START_TXT + (name.trim().equals("") ? "" : " - " + name);
- if (oldTitle.equals(newTitle))
+ String newTitle = TITLE_START_TXT + ("".equals(name.trim()) ? "" : " - " + name);
+ if (oldTitle.equals(newTitle)) {
return;
+ }
this.setTitle(newTitle);
}
- @SuppressWarnings({ "SimplifiableIfStatement" })
+ // @SuppressWarnings({ "SimplifiableIfStatement" })
private boolean shouldDisplayIssueIgnoringPackagePrefixes(BugInstance b) {
Project project = getProject();
Filter suppressionFilter = project.getSuppressionFilter();
- if (null == getBugCollection() || suppressionFilter.match(b))
+ if (null == getBugCollection() || suppressionFilter.match(b)) {
return false;
+ }
return viewFilter.showIgnoringPackagePrefixes(b);
}
@@ -751,13 +774,14 @@ public class MainFrame extends FBFrame implements LogSync {
TreeSet<String> projects = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
Multiset<String> count = new Multiset<String>();
int total = 0;
- for (BugInstance b : getBugCollection().getCollection())
+ for (BugInstance b : getBugCollection().getCollection()) {
if (shouldDisplayIssueIgnoringPackagePrefixes(b)) {
TreeSet<String> projectsForThisBug = projectPackagePrefixes.getProjects(b.getPrimaryClass().getClassName());
projects.addAll(projectsForThisBug);
count.addAll(projectsForThisBug);
total++;
}
+ }
if (projects.size() == 0) {
JOptionPane.showMessageDialog(this, "No issues in current view");
return;
@@ -772,8 +796,9 @@ public class MainFrame extends FBFrame implements LogSync {
ProjectSelector choice = (ProjectSelector) JOptionPane.showInputDialog(null,
"Choose a project to set appropriate package prefix(es)", "Select package prefixes by package",
JOptionPane.QUESTION_MESSAGE, null, selectors.toArray(), everything);
- if (choice == null)
+ if (choice == null) {
return;
+ }
mainFrameTree.setFieldForPackagesToDisplayText(choice.filter);
viewFilter.setPackagesToDisplay(choice.filter);
@@ -782,10 +807,12 @@ public class MainFrame extends FBFrame implements LogSync {
}
private static String join(String s1, String s2) {
- if (s1 == null || s1.length() == 0)
+ if (s1 == null || s1.length() == 0) {
return s2;
- if (s2 == null || s2.length() == 0)
+ }
+ if (s2 == null || s2.length() == 0) {
return s1;
+ }
return s1 + "; " + s2;
}
@@ -793,20 +820,22 @@ public class MainFrame extends FBFrame implements LogSync {
final BugInstance bug = node.getBug();
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
summaryTopPanel.removeAll();
summaryTopPanel.add(mainFrameComponentFactory.bugSummaryComponent(bug.getAbridgedMessage(), bug));
- for (BugAnnotation b : bug.getAnnotationsForMessage(true))
+ for (BugAnnotation b : bug.getAnnotationsForMessage(true)) {
summaryTopPanel.add(mainFrameComponentFactory.bugSummaryComponent(b, bug));
+ }
BugPattern bugPattern = bug.getBugPattern();
String detailText =
bugPattern.getDetailText()
+"<br><p> <b>Bug kind and pattern: " +
- bugPattern.getAbbrev() + " - " + bugPattern.getType();
+ bugPattern.getAbbrev() + " - " + bugPattern.getType();
String txt = bugPattern.getDetailHTML(detailText);
summaryHtmlArea.setText(txt);
@@ -814,6 +843,7 @@ public class MainFrame extends FBFrame implements LogSync {
summaryTopPanel.revalidate();
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
summaryHtmlScrollPane.getVerticalScrollBar().setValue(
summaryHtmlScrollPane.getVerticalScrollBar().getMinimum());
@@ -842,9 +872,12 @@ public class MainFrame extends FBFrame implements LogSync {
case 2:
targetLineNum = displayer.findPrevious(targetString);
break;
+ default:
+ break;
}
- if (targetLineNum != -1)
+ if (targetLineNum != -1) {
displayer.foundItem(targetLineNum);
+ }
}
public boolean canNavigateAway() {
@@ -867,8 +900,9 @@ public class MainFrame extends FBFrame implements LogSync {
}
public void setSaveType(SaveType saveType) {
- if (GUI2_DEBUG && this.saveType != saveType)
+ if (GUI2_DEBUG && this.saveType != saveType) {
System.out.println("Changing save type from " + this.saveType + " to " + saveType);
+ }
this.saveType = saveType;
}
@@ -878,6 +912,7 @@ public class MainFrame extends FBFrame implements LogSync {
private Iterable<BugInstance> getDisplayedBugs() {
return new Iterable<BugInstance>() {
+ @Override
public Iterator<BugInstance> iterator() {
return new ShownBugsIterator();
}
@@ -1023,13 +1058,14 @@ public class MainFrame extends FBFrame implements LogSync {
JMenuItem toggleItem = new JMenuItem(text);
toggleItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent arg0) {
Cloud cloud = getBugCollection().getCloud();
if (cloud instanceof DoNothingCloud) {
JOptionPane.showMessageDialog(MainFrame.this, "No cloud selected; enable and select optional Bug Collection XML Pseudo-Cloud plugin to store designations in XML");
- } else if (comments.canSetDesignations())
+ } else if (comments.canSetDesignations()) {
comments.setDesignation(key);
- else {
+ } else {
JOptionPane.showMessageDialog(MainFrame.this, "The currently selected cloud cannot store these designations");
}
}
@@ -1068,13 +1104,15 @@ public class MainFrame extends FBFrame implements LogSync {
BugInstance next;
+ @Override
public boolean hasNext() {
if (!nextKnown) {
nextKnown = true;
while (base.hasNext()) {
next = base.next();
- if (shouldDisplayIssue(next))
+ if (shouldDisplayIssue(next)) {
return true;
+ }
}
next = null;
return false;
@@ -1082,15 +1120,18 @@ public class MainFrame extends FBFrame implements LogSync {
return next != null;
}
+ @Override
public BugInstance next() {
- if (!hasNext())
+ if (!hasNext()) {
throw new NoSuchElementException();
+ }
BugInstance result = next;
next = null;
nextKnown = false;
return result;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -1101,15 +1142,17 @@ public class MainFrame extends FBFrame implements LogSync {
super(MainFrame.this);
}
+ @Override
public void registerCloud(Project project, BugCollection collection, Cloud plugin) {
-// assert collection.getCloud() == plugin
-// : collection.getCloud().getCloudName() + " vs " + plugin.getCloudName();
+ // assert collection.getCloud() == plugin
+ // : collection.getCloud().getCloudName() + " vs " + plugin.getCloudName();
if (MainFrame.this.bugCollection == collection) {
plugin.addListener(userAnnotationListener);
plugin.addStatusListener(cloudStatusListener);
}
}
+ @Override
public void unregisterCloud(Project project, BugCollection collection, Cloud plugin) {
assert collection.getCloud() == plugin;
if (MainFrame.this.bugCollection == collection) {
@@ -1118,9 +1161,11 @@ public class MainFrame extends FBFrame implements LogSync {
}
}
+ @Override
public void setErrorMessage(String errorMsg) {
MainFrame.this.errorMsg = errorMsg;
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
updateStatusBar();
}
@@ -1129,32 +1174,40 @@ public class MainFrame extends FBFrame implements LogSync {
}
private class MyCloudListener implements CloudListener {
+ @Override
public void issueUpdated(BugInstance bug) {
- if (mainFrameTree.getCurrentSelectedBugLeaf() != null && mainFrameTree.getCurrentSelectedBugLeaf().getBug() == bug)
+ if (mainFrameTree.getCurrentSelectedBugLeaf() != null && mainFrameTree.getCurrentSelectedBugLeaf().getBug() == bug) {
comments.updateCommentsFromLeafInformation(mainFrameTree.getCurrentSelectedBugLeaf());
+ }
}
+ @Override
public void statusUpdated() {
SwingUtilities.invokeLater(updateStatusBarRunner);
}
+ @Override
public void taskStarted(Cloud.CloudTask task) {
}
}
private class MyCloudStatusListener implements Cloud.CloudStatusListener {
+ @Override
public void handleIssueDataDownloadedEvent() {
mainFrameTree.rebuildBugTreeIfSortablesDependOnCloud();
}
+ @Override
public void handleStateChange(SigninState oldState, SigninState state) {
Cloud cloud = MainFrame.this.bugCollection.getCloudLazily();
- if (cloud != null && cloud.isInitialized())
- mainFrameTree.rebuildBugTreeIfSortablesDependOnCloud();
+ if (cloud != null && cloud.isInitialized()) {
+ mainFrameTree.rebuildBugTreeIfSortablesDependOnCloud();
+ }
}
}
private class StatusBarUpdater implements Runnable {
+ @Override
public void run() {
updateStatusBar();
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/MainFrameComponentFactory.java b/src/gui/edu/umd/cs/findbugs/gui2/MainFrameComponentFactory.java
index cc96725..fe3f404 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/MainFrameComponentFactory.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/MainFrameComponentFactory.java
@@ -108,7 +108,7 @@ public class MainFrameComponentFactory implements Serializable {
mainFrame.setSummaryTopPanel(new JPanel());
mainFrame.getSummaryTopPanel().setLayout(new GridLayout(0, 1));
mainFrame.getSummaryTopPanel().setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4));
-// mainFrame.getSummaryTopPanel().setMinimumSize(new Dimension(fontSize * 50, fontSize * 5));
+ // mainFrame.getSummaryTopPanel().setMinimumSize(new Dimension(fontSize * 50, fontSize * 5));
JPanel summaryTopOuter = new JPanel(new BorderLayout());
summaryTopOuter.add(mainFrame.getSummaryTopPanel(), BorderLayout.NORTH);
@@ -116,6 +116,7 @@ public class MainFrameComponentFactory implements Serializable {
mainFrame.getSummaryHtmlArea().setContentType("text/html");
mainFrame.getSummaryHtmlArea().setEditable(false);
mainFrame.getSummaryHtmlArea().addHyperlinkListener(new HyperlinkListener() {
+ @Override
public void hyperlinkUpdate(HyperlinkEvent evt) {
AboutDialog.editorPaneHyperlinkUpdate(evt);
}
@@ -179,8 +180,9 @@ public class MainFrameComponentFactory implements Serializable {
panel.add(sourceCodeScrollPane, BorderLayout.CENTER);
panel.revalidate();
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.out.println("Created source code panel");
+ }
return panel;
}
@@ -201,6 +203,7 @@ public class MainFrameComponentFactory implements Serializable {
thePanel.add(mainFrame.getSourceSearchTextField());
// add the buttons
mainFrame.getFindButton().addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.searchSource(0);
}
@@ -211,6 +214,7 @@ public class MainFrameComponentFactory implements Serializable {
gridbag.setConstraints(mainFrame.getFindButton(), c);
thePanel.add(mainFrame.getFindButton());
mainFrame.getFindNextButton().addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.searchSource(1);
}
@@ -221,6 +225,7 @@ public class MainFrameComponentFactory implements Serializable {
gridbag.setConstraints(mainFrame.getFindNextButton(), c);
thePanel.add(mainFrame.getFindNextButton());
mainFrame.getFindPreviousButton().addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.searchSource(2);
}
@@ -243,13 +248,15 @@ public class MainFrameComponentFactory implements Serializable {
URL u = null;
if (bug != null) {
Cloud plugin = mainFrame.getBugCollection().getCloud();
- if (plugin.supportsSourceLinks())
+ if (plugin.supportsSourceLinks()) {
u = plugin.getSourceLink(bug);
+ }
}
- if (u != null)
+ if (u != null) {
addLink(label, u);
- else
+ } else {
removeLink(label);
+ }
}
mainFrame.getGuiLayout().setSourceTitle(title);
@@ -264,16 +271,18 @@ public class MainFrameComponentFactory implements Serializable {
@Override
public void mouseClicked(MouseEvent e) {
URL u = sourceLink;
- if (u != null)
+ if (u != null) {
LaunchBrowser.showDocument(u);
+ }
}
});
}
component.setCursor(new Cursor(Cursor.HAND_CURSOR));
Cloud plugin = mainFrame.getBugCollection().getCloud();
- if (plugin != null)
+ if (plugin != null) {
component.setToolTipText(plugin.getSourceLinkToolTip(null));
+ }
}
@@ -305,12 +314,13 @@ public class MainFrameComponentFactory implements Serializable {
String srcStr = "";
int start = link.getStartLine();
int end = link.getEndLine();
- if (start < 0 && end < 0)
+ if (start < 0 && end < 0) {
srcStr = sourceCodeLabel;
- else if (start == end)
+ } else if (start == end) {
srcStr = " [" + summaryLine + " " + start + "]";
- else if (start < end)
+ } else if (start < end) {
srcStr = " [" + summaryLines + " " + start + " - " + end + "]";
+ }
label.setToolTipText(clickToGoToText + " " + srcStr);
@@ -325,27 +335,30 @@ public class MainFrameComponentFactory implements Serializable {
if (link != null && sourceCodeExists(link)) {
int start = link.getStartLine();
int end = link.getEndLine();
- if (start < 0 && end < 0)
+ if (start < 0 && end < 0) {
srcStr = sourceCodeLabel;
- else if (start == end)
+ } else if (start == end) {
srcStr = " [" + summaryLine + " " + start + "]";
- else if (start < end)
+ } else if (start < end) {
srcStr = " [" + summaryLines + " " + start + " - " + end + "]";
+ }
- if (!srcStr.equals("")) {
+ if (!"".equals(srcStr)) {
label.setToolTipText(clickToGoToText + " " + srcStr);
label.addMouseListener(new BugSummaryMouseListener(bug, label, link));
}
}
String noteText;
- if (note == bug.getPrimaryMethod() || note == bug.getPrimaryField())
+ if (note == bug.getPrimaryMethod() || note == bug.getPrimaryField()) {
noteText = note.toString();
- else
+ } else {
noteText = note.toString(primaryClass);
- if (!srcStr.equals(sourceCodeLabel))
+ }
+ if (!srcStr.equals(sourceCodeLabel)) {
label.setText(noteText + srcStr);
- else
+ } else {
label.setText(noteText);
+ }
} else {
label.setText(value.toString(primaryClass));
}
@@ -359,8 +372,6 @@ public class MainFrameComponentFactory implements Serializable {
* return a JLabel with the annotation's toString(). If that annotation is a
* SourceLineAnnotation or has a SourceLineAnnotation connected to it and
* the source file is available will attach a listener to the label.
- *
- * @return
*/
public Component bugSummaryComponent(String str, BugInstance bug) {
JLabel label = new JLabel();
@@ -371,8 +382,9 @@ public class MainFrameComponentFactory implements Serializable {
label.setText(str);
SourceLineAnnotation link = bug.getPrimarySourceLineAnnotation();
- if (link != null)
+ if (link != null) {
label.addMouseListener(new BugSummaryMouseListener(bug, label, link));
+ }
return label;
}
@@ -389,12 +401,13 @@ public class MainFrameComponentFactory implements Serializable {
}
private static class InitializeGUI implements Runnable {
- private MainFrame mainFrame;
+ private final MainFrame mainFrame;
public InitializeGUI(final MainFrame mainFrame) {
this.mainFrame = mainFrame;
}
+ @Override
public void run() {
mainFrame.setTitle("FindBugs");
// noinspection ConstantConditions
@@ -414,7 +427,7 @@ public class MainFrameComponentFactory implements Serializable {
// (as in sourceforge bug 1899648). In an attempt to recover
// gracefully, this code reverts to the cross-platform look-
// and-feel and attempts again to initialize the layout.
- if (!UIManager.getLookAndFeel().getName().equals("Metal")) {
+ if (!"Metal".equals(UIManager.getLookAndFeel().getName())) {
System.err.println("Exception caught initializing GUI; reverting to CrossPlatformLookAndFeel");
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
@@ -431,8 +444,9 @@ public class MainFrameComponentFactory implements Serializable {
mainFrame.mainFrameTree.setBranchPopupMenu(mainFrame.mainFrameTree.createBranchPopUpMenu());
mainFrame.updateStatusBar();
Rectangle bounds = GUISaveState.getInstance().getFrameBounds();
- if (bounds != null)
+ if (bounds != null) {
mainFrame.setBounds(bounds);
+ }
mainFrame.setExtendedState(GUISaveState.getInstance().getExtendedWindowState());
Toolkit.getDefaultToolkit().setDynamicLayout(true);
@@ -482,15 +496,15 @@ public class MainFrameComponentFactory implements Serializable {
// a system without the EAWT
// because OSXAdapter extends ApplicationAdapter in its def
System.err
- .println("This version of Mac OS X does not support the Apple EAWT. Application Menu handling has been disabled ("
- + e + ")");
+ .println("This version of Mac OS X does not support the Apple EAWT. Application Menu handling has been disabled ("
+ + e + ")");
} catch (ClassNotFoundException e) {
// This shouldn't be reached; if there's a problem with the
// OSXAdapter we should get the
// above NoClassDefFoundError first.
System.err
- .println("This version of Mac OS X does not support the Apple EAWT. Application Menu handling has been disabled ("
- + e + ")");
+ .println("This version of Mac OS X does not support the Apple EAWT. Application Menu handling has been disabled ("
+ + e + ")");
} catch (Exception e) {
System.err.println("Exception while loading the OSXAdapter: " + e);
e.printStackTrace();
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/MainFrameLoadSaveHelper.java b/src/gui/edu/umd/cs/findbugs/gui2/MainFrameLoadSaveHelper.java
index 834245d..863a103 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/MainFrameLoadSaveHelper.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/MainFrameLoadSaveHelper.java
@@ -62,8 +62,9 @@ public class MainFrameLoadSaveHelper implements Serializable {
int value = filterOpenFileChooser.showOpenDialog(mainFrame);
- if (value != JFileChooser.APPROVE_OPTION)
+ if (value != JFileChooser.APPROVE_OPTION) {
return;
+ }
f = filterOpenFileChooser.getSelectedFile();
@@ -82,11 +83,11 @@ public class MainFrameLoadSaveHelper implements Serializable {
}
mainFrame.setProjectChanged(true);
Filter suppressionFilter = mainFrame.getProject().getSuppressionFilter();
-
+
for (Matcher m : filter.getChildren()) {
suppressionFilter.addChild(m);
}
-
+
PreferencesFrame.getInstance().updateFilterPanel();
}
@@ -96,17 +97,21 @@ public class MainFrameLoadSaveHelper implements Serializable {
* This method is for when the user wants to open a file.
*/
void open() {
- if (!mainFrame.canNavigateAway())
+ if (!mainFrame.canNavigateAway()) {
return;
+ }
- if (askToSave()) return;
+ if (askToSave()) {
+ return;
+ }
boolean loading = true;
SaveType fileType;
tryAgain: while (loading) {
int value = saveOpenFileChooser.showOpenDialog(mainFrame);
- if (value != JFileChooser.APPROVE_OPTION)
+ if (value != JFileChooser.APPROVE_OPTION) {
return;
+ }
loading = false;
fileType = convertFilterToType(saveOpenFileChooser.getFileFilter());
@@ -162,16 +167,19 @@ public class MainFrameLoadSaveHelper implements Serializable {
if (mainFrame.isProjectChanged()) {
int response = JOptionPane.showConfirmDialog(mainFrame, L10N.getLocalString("dlg.save_current_changes",
"The current project has been changed, Save current changes?"), L10N.getLocalString("dlg.save_changes",
- "Save Changes?"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
+ "Save Changes?"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
if (response == JOptionPane.YES_OPTION) {
- if (mainFrame.getSaveFile() != null)
+ if (mainFrame.getSaveFile() != null) {
save();
- else
+ } else {
saveAs();
+ }
} else if (response == JOptionPane.CANCEL_OPTION)
+ {
return true;
- // IF no, do nothing.
+ // IF no, do nothing.
+ }
}
return false;
}
@@ -203,8 +211,9 @@ public class MainFrameLoadSaveHelper implements Serializable {
int value = filterOpenFileChooser.showSaveDialog(mainFrame);
- if (value != JFileChooser.APPROVE_OPTION)
+ if (value != JFileChooser.APPROVE_OPTION) {
return false;
+ }
f = filterOpenFileChooser.getSelectedFile();
@@ -215,8 +224,9 @@ public class MainFrameLoadSaveHelper implements Serializable {
L10N.getLocalString("dlg.warning_ttl", "Warning!"), JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
- if (response == JOptionPane.OK_OPTION)
+ if (response == JOptionPane.OK_OPTION) {
retry = false;
+ }
if (response == JOptionPane.CANCEL_OPTION) {
retry = true;
continue;
@@ -238,8 +248,9 @@ public class MainFrameLoadSaveHelper implements Serializable {
}
boolean saveAs() {
- if (!mainFrame.canNavigateAway())
+ if (!mainFrame.canNavigateAway()) {
return false;
+ }
saveOpenFileChooser.setDialogTitle(L10N.getLocalString("dlg.saveas_ttl", "Save as..."));
@@ -257,8 +268,9 @@ public class MainFrameLoadSaveHelper implements Serializable {
int value = saveOpenFileChooser.showSaveDialog(mainFrame);
- if (value != JFileChooser.APPROVE_OPTION)
+ if (value != JFileChooser.APPROVE_OPTION) {
return false;
+ }
fileType = convertFilterToType(saveOpenFileChooser.getFileFilter());
if (fileType == SaveType.NOT_KNOWN) {
@@ -292,29 +304,30 @@ public class MainFrameLoadSaveHelper implements Serializable {
L10N.getLocalString("dlg.warning_ttl", "Warning!"), JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
break;case XML_ANALYSIS:
- response = JOptionPane.showConfirmDialog(saveOpenFileChooser,
- L10N.getLocalString("dlg.analysis_exists_lbl", "This analysis already exists.\nReplace it?"),
- L10N.getLocalString("dlg.warning_ttl", "Warning!"), JOptionPane.OK_CANCEL_OPTION,
- JOptionPane.WARNING_MESSAGE);
- break;
- case FBP_FILE:
- response = JOptionPane.showConfirmDialog(saveOpenFileChooser,
- L10N.getLocalString("FB Project File already exists",
- "This FB project file already exists.\nDo you want to replace it?"), L10N.getLocalString(
- "dlg.warning_ttl", "Warning!"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
- break;
- case FBA_FILE:
- response = JOptionPane.showConfirmDialog(saveOpenFileChooser, L10N.getLocalString(
- "FB Analysis File already exists",
- "This FB analysis file already exists.\nDo you want to replace it?"), L10N.getLocalString(
- "dlg.warning_ttl", "Warning!"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
- break;
- default:
- assert false;
+ response = JOptionPane.showConfirmDialog(saveOpenFileChooser,
+ L10N.getLocalString("dlg.analysis_exists_lbl", "This analysis already exists.\nReplace it?"),
+ L10N.getLocalString("dlg.warning_ttl", "Warning!"), JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.WARNING_MESSAGE);
+ break;
+ case FBP_FILE:
+ response = JOptionPane.showConfirmDialog(saveOpenFileChooser,
+ L10N.getLocalString("FB Project File already exists",
+ "This FB project file already exists.\nDo you want to replace it?"), L10N.getLocalString(
+ "dlg.warning_ttl", "Warning!"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
+ break;
+ case FBA_FILE:
+ response = JOptionPane.showConfirmDialog(saveOpenFileChooser, L10N.getLocalString(
+ "FB Analysis File already exists",
+ "This FB analysis file already exists.\nDo you want to replace it?"), L10N.getLocalString(
+ "dlg.warning_ttl", "Warning!"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
+ break;
+ default:
+ assert false;
}
- if (response == JOptionPane.OK_OPTION)
+ if (response == JOptionPane.OK_OPTION) {
retry = false;
+ }
if (response == JOptionPane.CANCEL_OPTION) {
retry = true;
continue;
@@ -363,8 +376,9 @@ public class MainFrameLoadSaveHelper implements Serializable {
}
SaveType convertFilterToType(FileFilter f) {
- if (f instanceof FindBugsFileFilter)
+ if (f instanceof FindBugsFileFilter) {
return ((FindBugsFileFilter) f).getSaveType();
+ }
return SaveType.NOT_KNOWN;
}
@@ -377,15 +391,17 @@ public class MainFrameLoadSaveHelper implements Serializable {
File convertFile(File f, SaveType fileType) {
// Checks that it has the correct file extension, makes a new file if it
// doesn't.
- if (!f.getName().endsWith(fileType.getFileExtension()))
+ if (!f.getName().endsWith(fileType.getFileExtension())) {
f = new File(f.getAbsolutePath() + fileType.getFileExtension());
+ }
return f;
}
void save() {
- if (!mainFrame.canNavigateAway())
+ if (!mainFrame.canNavigateAway()) {
return;
+ }
File sFile = mainFrame.getSaveFile();
assert sFile != null;
@@ -418,8 +434,9 @@ public class MainFrameLoadSaveHelper implements Serializable {
}
SaveReturn saveFBPFile(File saveFile2) {
- if (!mainFrame.canNavigateAway())
+ if (!mainFrame.canNavigateAway()) {
return SaveReturn.SAVE_ERROR;
+ }
try {
mainFrame.getProject().writeXML(saveFile2, mainFrame.getBugCollection());
} catch (IOException e) {
@@ -435,15 +452,16 @@ public class MainFrameLoadSaveHelper implements Serializable {
SaveReturn printHtml(final File f) {
Future<Object> waiter = mainFrame.getBackgroundExecutor().submit(new Callable<Object>() {
+ @Override
public Object call() throws Exception {
HTMLBugReporter reporter = new HTMLBugReporter( mainFrame.getProject(), "default.xsl");
reporter.setIsRelaxed(true);
reporter.setOutputStream(UTF8.printStream(new FileOutputStream(f)));
for(BugInstance bug : mainFrame.getBugCollection().getCollection()) {
try {
- if (mainFrame.getViewFilter().show(bug)) {
- reporter.reportBug(bug);
- }
+ if (mainFrame.getViewFilter().show(bug)) {
+ reporter.reportBug(bug);
+ }
} catch (Exception e) {
e.printStackTrace();
}
@@ -462,7 +480,7 @@ public class MainFrameLoadSaveHelper implements Serializable {
return SaveReturn.SAVE_SUCCESSFUL;
}
-
+
/**
* Save current analysis as file passed in. Return SAVE_SUCCESSFUL if save
* successful. Method doesn't do much. This method is more if need to do
@@ -472,6 +490,7 @@ public class MainFrameLoadSaveHelper implements Serializable {
SaveReturn saveAnalysis(final File f) {
Future<Object> waiter = mainFrame.getBackgroundExecutor().submit(new Callable<Object>() {
+ @Override
public Object call() throws Exception {
BugSaver.saveBugs(f, mainFrame.getBugCollection(), mainFrame.getProject());
return null;
@@ -501,12 +520,13 @@ public class MainFrameLoadSaveHelper implements Serializable {
}
void closeProject() {
- if (askToSave())
+ if (askToSave()) {
return;
+ }
closeProjectInternal();
}
-
+
private void closeProjectInternal() {
// This creates a new filters and suppressions so don't use the
// previoues one.
@@ -521,6 +541,7 @@ public class MainFrameLoadSaveHelper implements Serializable {
void loadAnalysis(final File file) {
Runnable runnable = new Runnable() {
+ @Override
public void run() {
mainFrame.acquireDisplayWait();
try {
@@ -529,22 +550,24 @@ public class MainFrameLoadSaveHelper implements Serializable {
project.setCurrentWorkingDirectory(file.getParentFile());
BugLoader.loadBugs(mainFrame, project, file);
project.getSourceFinder(); // force source finder to be
- // initialized
+ // initialized
mainFrame.updateBugTree();
} finally {
mainFrame.releaseDisplayWait();
}
}
};
- if (EventQueue.isDispatchThread())
+ if (EventQueue.isDispatchThread()) {
new Thread(runnable, "Analysis loading thread").start();
- else
+ } else {
runnable.run();
+ }
}
void loadAnalysis(final URL url) {
Runnable runnable = new Runnable() {
+ @Override
public void run() {
mainFrame.acquireDisplayWait();
try {
@@ -559,15 +582,17 @@ public class MainFrameLoadSaveHelper implements Serializable {
}
}
};
- if (EventQueue.isDispatchThread())
+ if (EventQueue.isDispatchThread()) {
new Thread(runnable, "Analysis loading thread").start();
- else
+ } else {
runnable.run();
+ }
}
void loadProjectFromFile(final File f) {
Runnable runnable = new Runnable() {
+ @Override
public void run() {
final Project project = BugLoader.loadProject(mainFrame, f);
final BugCollection bc = project == null ? null : BugLoader.doAnalysis(project);
@@ -575,15 +600,17 @@ public class MainFrameLoadSaveHelper implements Serializable {
mainFrame.setProjectAndBugCollectionInSwingThread(project, bc);
}
};
- if (EventQueue.isDispatchThread())
+ if (EventQueue.isDispatchThread()) {
new Thread(runnable).start();
- else
+ } else {
runnable.run();
+ }
}
void mergeAnalysis() {
- if (!mainFrame.canNavigateAway())
+ if (!mainFrame.canNavigateAway()) {
return;
+ }
mainFrame.acquireDisplayWait();
try {
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/MainFrameMenu.java b/src/gui/edu/umd/cs/findbugs/gui2/MainFrameMenu.java
index a5606f2..ba83864 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/MainFrameMenu.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/MainFrameMenu.java
@@ -1,8 +1,6 @@
package edu.umd.cs.findbugs.gui2;
-import static edu.umd.cs.findbugs.gui2.MainFrameHelper.attachAcceleratorKey;
-import static edu.umd.cs.findbugs.gui2.MainFrameHelper.newJMenu;
-import static edu.umd.cs.findbugs.gui2.MainFrameHelper.newJMenuItem;
+import static edu.umd.cs.findbugs.gui2.MainFrameHelper.*;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
@@ -16,6 +14,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Locale;
import javax.swing.ActionMap;
import javax.swing.ButtonGroup;
@@ -37,6 +36,7 @@ import edu.umd.cs.findbugs.Project;
import edu.umd.cs.findbugs.cloud.Cloud;
import edu.umd.cs.findbugs.filter.Filter;
import edu.umd.cs.findbugs.filter.Matcher;
+import edu.umd.cs.findbugs.gui.AnnotatedString;
import edu.umd.cs.findbugs.gui2.FilterListener.Action;
import edu.umd.cs.findbugs.updates.UpdateChecker;
@@ -69,12 +69,14 @@ public class MainFrameMenu implements Serializable {
}
JMenuItem createRecentItem(final File f, final SaveType localSaveType) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.out.println("createRecentItem(" + f + ", " + localSaveType + ")");
+ }
String name = f.getName();
final JMenuItem item = new JMenuItem(name);
item.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
try {
mainFrame.setCursor(new Cursor(Cursor.WAIT_CURSOR));
@@ -86,16 +88,17 @@ public class MainFrameMenu implements Serializable {
return;
}
GUISaveState.getInstance().fileReused(f);// Move to front in
- // GUISaveState, so
- // it will be last
- // thing to be
- // removed from the
- // list
+ // GUISaveState, so
+ // it will be last
+ // thing to be
+ // removed from the
+ // list
recentMenuCache.addRecentFile(f);
- if (!f.exists())
+ if (!f.exists()) {
throw new IllegalStateException("User used a recent projects menu item that didn't exist.");
+ }
// Moved this outside of the thread, and above the line
// saveFile=f.getParentFile()
@@ -105,17 +108,20 @@ public class MainFrameMenu implements Serializable {
if (mainFrame.getCurProject() != null && mainFrame.isProjectChanged()) {
int response = JOptionPane.showConfirmDialog(mainFrame, L10N.getLocalString("dlg.save_current_changes",
"The current project has been changed, Save current changes?"), L10N.getLocalString(
- "dlg.save_changes", "Save Changes?"), JOptionPane.YES_NO_CANCEL_OPTION,
- JOptionPane.WARNING_MESSAGE);
+ "dlg.save_changes", "Save Changes?"), JOptionPane.YES_NO_CANCEL_OPTION,
+ JOptionPane.WARNING_MESSAGE);
if (response == JOptionPane.YES_OPTION) {
- if (mainFrame.getSaveFile() != null)
+ if (mainFrame.getSaveFile() != null) {
mainFrame.getMainFrameLoadSaveHelper().save();
- else
+ } else {
mainFrame.getMainFrameLoadSaveHelper().saveAs();
+ }
} else if (response == JOptionPane.CANCEL_OPTION)
+ {
return;
- // IF no, do nothing.
+ // IF no, do nothing.
+ }
}
SaveType st = SaveType.forFile(f);
@@ -150,7 +156,7 @@ public class MainFrameMenu implements Serializable {
/**
* Creates the MainFrame's menu bar.
- *
+ *
* @return the menu bar for the MainFrame
*/
JMenuBar createMainMenuBar() {
@@ -174,6 +180,7 @@ public class MainFrameMenu implements Serializable {
if (!MainFrame.MAC_OS_X) {
exitMenuItem = newJMenuItem("menu.exit", "Exit", KeyEvent.VK_X);
exitMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.callOnClose();
}
@@ -188,6 +195,7 @@ public class MainFrameMenu implements Serializable {
attachAcceleratorKey(newProjectMenuItem, KeyEvent.VK_N);
newProjectMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.createNewProjectFromMenuItem();
}
@@ -197,9 +205,11 @@ public class MainFrameMenu implements Serializable {
reconfigMenuItem.setEnabled(false);
attachAcceleratorKey(reconfigMenuItem, KeyEvent.VK_F);
reconfigMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
- if (!mainFrame.canNavigateAway())
+ if (!mainFrame.canNavigateAway()) {
return;
+ }
new NewProjectWizard(mainFrame.getCurProject());
}
});
@@ -208,6 +218,7 @@ public class MainFrameMenu implements Serializable {
mergeMenuItem.setEnabled(true);
mergeMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.getMainFrameLoadSaveHelper().mergeAnalysis();
}
@@ -219,6 +230,7 @@ public class MainFrameMenu implements Serializable {
redoAnalysis.setEnabled(false);
attachAcceleratorKey(redoAnalysis, KeyEvent.VK_R);
redoAnalysis.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.redoAnalysis();
}
@@ -226,6 +238,7 @@ public class MainFrameMenu implements Serializable {
}
closeProjectItem = newJMenuItem("menu.closeProject", "Close Project");
closeProjectItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
mainFrame.getMainFrameLoadSaveHelper().closeProject();
mainFrame.clearBugCollection();
@@ -237,22 +250,26 @@ public class MainFrameMenu implements Serializable {
openMenuItem.setEnabled(true);
attachAcceleratorKey(openMenuItem, KeyEvent.VK_O);
openMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.getMainFrameLoadSaveHelper().open();
}
});
saveAsMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.getMainFrameLoadSaveHelper().saveAs();
}
});
exportFilter.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.getMainFrameLoadSaveHelper().exportFilter();
}
});
importFilter.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.getMainFrameLoadSaveHelper().importFilter();
}
@@ -260,13 +277,15 @@ public class MainFrameMenu implements Serializable {
saveMenuItem.setEnabled(false);
attachAcceleratorKey(saveMenuItem, KeyEvent.VK_S);
saveMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.getMainFrameLoadSaveHelper().save();
}
});
- if (!FindBugs.isNoAnalysis())
+ if (!FindBugs.isNoAnalysis()) {
fileMenu.add(newProjectMenuItem);
+ }
fileMenu.add(openMenuItem);
fileMenu.add(recentMenu);
@@ -306,15 +325,18 @@ public class MainFrameMenu implements Serializable {
attachAcceleratorKey(pasteMenuItem, KeyEvent.VK_V);
preferencesMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.preferences();
}
});
groupByMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
- if (!mainFrame.canNavigateAway())
+ if (!mainFrame.canNavigateAway()) {
return;
+ }
SorterDialog.getInstance().setLocationRelativeTo(mainFrame);
SorterDialog.getInstance().setVisible(true);
}
@@ -322,6 +344,7 @@ public class MainFrameMenu implements Serializable {
attachAcceleratorKey(goToLineMenuItem, KeyEvent.VK_L);
goToLineMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.getGuiLayout().makeSourceVisible();
try {
@@ -348,8 +371,9 @@ public class MainFrameMenu implements Serializable {
menuBar.add(editMenu);
- if (windowMenu != null)
+ if (windowMenu != null) {
menuBar.add(windowMenu);
+ }
viewMenu = newJMenu("menu.view_menu", "View");
setViewMenu();
@@ -384,6 +408,7 @@ public class MainFrameMenu implements Serializable {
helpMenu.add(aboutItem);
aboutItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
mainFrame.about();
}
@@ -393,12 +418,14 @@ public class MainFrameMenu implements Serializable {
UpdateChecker checker = DetectorFactoryCollection.instance().getUpdateChecker();
boolean disabled = checker.updateChecksGloballyDisabled();
updateItem.setEnabled(!disabled);
- if (disabled)
+ if (disabled) {
updateItem.setToolTipText("Update checks disabled by plugin: "
+ checker.getPluginThatDisabledUpdateChecks());
+ }
helpMenu.add(updateItem);
updateItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
DetectorFactoryCollection.instance().checkForUpdates(true);
}
@@ -417,6 +444,7 @@ public class MainFrameMenu implements Serializable {
if (cloud != null && cloud.supportsCloudSummaries()) {
JMenuItem cloudReport = new JMenuItem("Cloud summary");
cloudReport.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
mainFrame.displayCloudReport();
@@ -427,6 +455,7 @@ public class MainFrameMenu implements Serializable {
if (mainFrame.getProjectPackagePrefixes().size() > 0 && mainFrame.getBugCollection() != null) {
JMenuItem selectPackagePrefixMenu = new JMenuItem("Select class search strings by project...");
selectPackagePrefixMenu.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
mainFrame.selectPackagePrefixByProject();
@@ -435,17 +464,21 @@ public class MainFrameMenu implements Serializable {
viewMenu.add(selectPackagePrefixMenu);
}
- if (viewMenu.getItemCount() > 0)
+ if (viewMenu.getItemCount() > 0) {
viewMenu.addSeparator();
+ }
ButtonGroup rankButtonGroup = new ButtonGroup();
for (final ViewFilter.RankFilter r : ViewFilter.RankFilter.values()) {
JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem(r.toString());
+ AnnotatedString.localiseButton(rbMenuItem, "menu.rankFilter_"+r.name().toLowerCase(Locale.ENGLISH), r.toString(), true);
rankButtonGroup.add(rbMenuItem);
- if (r == ViewFilter.RankFilter.ALL)
+ if (r == ViewFilter.RankFilter.ALL) {
rbMenuItem.setSelected(true);
+ }
rbMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
mainFrame.getViewFilter().setRank(r);
mainFrame.resetViewCache();
@@ -456,17 +489,42 @@ public class MainFrameMenu implements Serializable {
viewMenu.addSeparator();
+ ButtonGroup priorityButtonGroup = new ButtonGroup();
+ for (final ViewFilter.PriorityFilter r : ViewFilter.PriorityFilter.values()) {
+ JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem(r.toString());
+ AnnotatedString.localiseButton(rbMenuItem, "menu.priorityFilter_"+r.name().toLowerCase(Locale.ENGLISH), r.toString(), true);
+ priorityButtonGroup.add(rbMenuItem);
+ if (r == ViewFilter.PriorityFilter.ALL_BUGS) {
+ rbMenuItem.setSelected(true);
+ }
+ rbMenuItem.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ mainFrame.getViewFilter().setPriority(r);
+ mainFrame.resetViewCache();
+ }
+ });
+ viewMenu.add(rbMenuItem);
+ }
+
+ viewMenu.addSeparator();
+
if (cloud != null && cloud.getMode() == Cloud.Mode.COMMUNAL) {
ButtonGroup overallClassificationButtonGroup = new ButtonGroup();
for (final ViewFilter.OverallClassificationFilter r : ViewFilter.OverallClassificationFilter.values()) {
- if (!r.supported(cloud))
+ if (!r.supported(cloud)) {
continue;
+ }
JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem(r.toString());
+ AnnotatedString.localiseButton(rbMenuItem, "menu.classificatonFilter_"+r.name().toLowerCase(Locale.ENGLISH), r.toString(), true);
overallClassificationButtonGroup.add(rbMenuItem);
- if (r == ViewFilter.OverallClassificationFilter.ALL)
+ if (r == ViewFilter.OverallClassificationFilter.ALL) {
rbMenuItem.setSelected(true);
+ }
rbMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
mainFrame.getViewFilter().setClassification(r);
mainFrame.resetViewCache();
@@ -479,14 +537,18 @@ public class MainFrameMenu implements Serializable {
ButtonGroup evalButtonGroup = new ButtonGroup();
for (final ViewFilter.CloudFilter r : ViewFilter.CloudFilter.values()) {
- if (cloud != null && !r.supported(cloud))
+ if (cloud != null && !r.supported(cloud)) {
continue;
+ }
JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem(r.toString());
+ AnnotatedString.localiseButton(rbMenuItem, "menu.cloudFilter_"+r.name().toLowerCase(Locale.ENGLISH), r.toString(), true);
evalButtonGroup.add(rbMenuItem);
- if (r == ViewFilter.CloudFilter.ALL)
+ if (r == ViewFilter.CloudFilter.ALL) {
rbMenuItem.setSelected(true);
+ }
rbMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
mainFrame.getViewFilter().setEvaluation(r);
mainFrame.resetViewCache();
@@ -498,11 +560,14 @@ public class MainFrameMenu implements Serializable {
ButtonGroup ageButtonGroup = new ButtonGroup();
for (final ViewFilter.FirstSeenFilter r : ViewFilter.FirstSeenFilter.values()) {
JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem(r.toString());
+ AnnotatedString.localiseButton(rbMenuItem, "menu.firstSeenFilter_"+r.name().toLowerCase(Locale.ENGLISH), r.toString(), true);
ageButtonGroup.add(rbMenuItem);
- if (r == ViewFilter.FirstSeenFilter.ALL)
+ if (r == ViewFilter.FirstSeenFilter.ALL) {
rbMenuItem.setSelected(true);
+ }
rbMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
mainFrame.getViewFilter().setFirstSeen(r);
mainFrame.resetViewCache();
@@ -514,33 +579,35 @@ public class MainFrameMenu implements Serializable {
final Filter suppressionFilter = MainFrame.getInstance().getProject().getSuppressionFilter();
Collection<Matcher> filters = suppressionFilter.getChildren();
JMenuItem filterMenu = new JMenuItem(filters.isEmpty() ? "Add Filters..." : "Filters...");
-
+
filterMenu.addActionListener(new ActionListener() {
-
+
+ @Override
public void actionPerformed(ActionEvent e) {
PreferencesFrame preferenceFrame = PreferencesFrame.getInstance();
preferenceFrame.showFilterPane();
preferenceFrame.setLocationRelativeTo(mainFrame);
preferenceFrame.setVisible(true);
-
-
+
+
}
});
viewMenu.add(filterMenu);
- for(final Matcher m : filters) {
+ for(final Matcher m : filters) {
JCheckBoxMenuItem f = new JCheckBoxMenuItem(m.toString(), suppressionFilter.isEnabled(m));
viewMenu.add(f);
f.addItemListener(new ItemListener() {
-
+
+ @Override
public void itemStateChanged(ItemEvent e) {
boolean enabled = e.getStateChange() == ItemEvent.SELECTED;
suppressionFilter.setEnabled(m, enabled);
FilterActivity.notifyListeners(enabled ? Action.FILTERING : Action.UNFILTERING, null);
-
+
}
});
-
+
}
@@ -549,7 +616,7 @@ public class MainFrameMenu implements Serializable {
/**
* This checks if the xmlFile is in the GUISaveState. If not adds it. Then
* adds the file to the recentMenuCache.
- *
+ *
* @param xmlFile
*/
/*
@@ -635,11 +702,13 @@ public class MainFrameMenu implements Serializable {
super(L10N.getLocalString("txt.cut", "Cut"));
}
+ @Override
public void actionPerformed(ActionEvent evt) {
JTextComponent text = getTextComponent(evt);
- if (text == null)
+ if (text == null) {
return;
+ }
text.cut();
}
@@ -663,11 +732,13 @@ public class MainFrameMenu implements Serializable {
super(L10N.getLocalString("txt.copy", "Copy"));
}
+ @Override
public void actionPerformed(ActionEvent evt) {
JTextComponent text = getTextComponent(evt);
- if (text == null)
+ if (text == null) {
return;
+ }
text.copy();
}
@@ -679,11 +750,13 @@ public class MainFrameMenu implements Serializable {
super(L10N.getLocalString("txt.paste", "Paste"));
}
+ @Override
public void actionPerformed(ActionEvent evt) {
JTextComponent text = getTextComponent(evt);
- if (text == null)
+ if (text == null) {
return;
+ }
text.paste();
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/MainFrameTree.java b/src/gui/edu/umd/cs/findbugs/gui2/MainFrameTree.java
index 5e4b327..d4d6902 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/MainFrameTree.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/MainFrameTree.java
@@ -85,6 +85,7 @@ public class MainFrameTree implements Serializable {
public void newTree(final JTree newTree, final BugTreeModel newModel) {
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
tree = newTree;
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
@@ -121,9 +122,11 @@ public class MainFrameTree implements Serializable {
public Sortables[] getAvailableSortables() {
Sortables[] sortables;
ArrayList<Sortables> a = new ArrayList<Sortables>(Sortables.values().length);
- for (Sortables s : Sortables.values())
- if (s.isAvailable(mainFrame))
+ for (Sortables s : Sortables.values()) {
+ if (s.isAvailable(mainFrame)) {
a.add(s);
+ }
+ }
sortables = new Sortables[a.size()];
a.toArray(sortables);
return sortables;
@@ -131,8 +134,6 @@ public class MainFrameTree implements Serializable {
/**
* Returns the SorterTableColumnModel of the MainFrame.
- *
- * @return
*/
SorterTableColumnModel getSorter() {
return sorter;
@@ -173,18 +174,16 @@ public class MainFrameTree implements Serializable {
private void warnUserOfFilters() {
JOptionPane
- .showMessageDialog(
- mainFrame,
- edu.umd.cs.findbugs.L10N
- .getLocalString("dlg.everything_is_filtered",
- "All bugs in this project appear to be filtered out. \nYou may wish to check your filter settings in the preferences menu."),
+ .showMessageDialog(
+ mainFrame,
+ edu.umd.cs.findbugs.L10N
+ .getLocalString("dlg.everything_is_filtered",
+ "All bugs in this project appear to be filtered out. \nYou may wish to check your filter settings in the preferences menu."),
"Warning", JOptionPane.WARNING_MESSAGE);
}
/**
* Creates popup menu for bugs on tree.
- *
- * @return
*/
JPopupMenu createBugPopupMenu() {
JPopupMenu popupMenu = new JPopupMenu();
@@ -192,14 +191,15 @@ public class MainFrameTree implements Serializable {
JMenuItem filterMenuItem = MainFrameHelper.newJMenuItem("menu.filterBugsLikeThis", "Filter bugs like this");
filterMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
if (!mainFrame.canNavigateAway()) { return; }
-
- new NewFilterFromBug(new FilterFromBugPicker(currentSelectedBugLeaf.getBug(),
- Arrays.asList(mainFrame.getAvailableSortables())),
- new ApplyNewFilter(mainFrame.getProject().getSuppressionFilter(),
- PreferencesFrame.getInstance(),
- new FilterActivityNotifier()));
+
+ new NewFilterFromBug(new FilterFromBugPicker(currentSelectedBugLeaf.getBug(),
+ Arrays.asList(mainFrame.getAvailableSortables())),
+ new ApplyNewFilter(mainFrame.getProject().getSuppressionFilter(),
+ PreferencesFrame.getInstance(),
+ new FilterActivityNotifier()));
mainFrame.setProjectChanged(true);
mainFrame.getTree().setSelectionRow(0); // Selects the top of the Jtree so the CommentsArea syncs up.
@@ -226,8 +226,6 @@ public class MainFrameTree implements Serializable {
/**
* Creates the branch pop up menu that ask if the user wants to hide all the
* bugs in that branch.
- *
- * @return
*/
JPopupMenu createBranchPopUpMenu() {
JPopupMenu popupMenu = new JPopupMenu();
@@ -235,6 +233,7 @@ public class MainFrameTree implements Serializable {
JMenuItem filterMenuItem = MainFrameHelper.newJMenuItem("menu.filterTheseBugs", "Filter these bugs");
filterMenuItem.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
// TODO This code does a smarter version of filtering that is
// only possible for branches, and does so correctly
@@ -245,8 +244,9 @@ public class MainFrameTree implements Serializable {
// benefit of using the smarter deletion method.
try {
- if (!mainFrame.canNavigateAway())
+ if (!mainFrame.canNavigateAway()) {
return;
+ }
int startCount;
TreePath path = MainFrame.getInstance().getTree().getSelectionPath();
TreePath deletePath = path;
@@ -255,12 +255,12 @@ public class MainFrameTree implements Serializable {
while (count == startCount) {
deletePath = deletePath.getParentPath();
if (deletePath.getParentPath() == null)// We are at the
- // top of the
- // tree, don't
- // let this be
- // removed,
- // rebuild tree
- // from root.
+ // top of the
+ // tree, don't
+ // let this be
+ // removed,
+ // rebuild tree
+ // from root.
{
Matcher m = mainFrame.getCurrentSelectedBugAspects().getMatcher();
Filter suppressionFilter = MainFrame.getInstance().getProject().getSuppressionFilter();
@@ -293,16 +293,16 @@ public class MainFrameTree implements Serializable {
mainFrame.setProjectChanged(true);
MainFrame.getInstance().getTree().setSelectionRow(0);// Selects
- // the
- // top
- // of
- // the
- // Jtree
- // so
- // the
- // CommentsArea
- // syncs
- // up.
+ // the
+ // top
+ // of
+ // the
+ // Jtree
+ // so
+ // the
+ // CommentsArea
+ // syncs
+ // up.
} catch (RuntimeException e) {
MainFrame.getInstance().showMessageDialog("Unable to create filter: " + e.getMessage());
}
@@ -329,6 +329,7 @@ public class MainFrameTree implements Serializable {
ActionListener treeActionAdapter(ActionMap map, String actionName) {
final Action selectPrevious = map.get(actionName);
return new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
e.setSource(tree);
selectPrevious.actionPerformed(e);
@@ -343,8 +344,9 @@ public class MainFrameTree implements Serializable {
int i = 0;
while (true) {
int rows = jTree.getRowCount();
- if (i >= rows || rows >= max)
+ if (i >= rows || rows >= max) {
break;
+ }
jTree.expandRow(i++);
}
}
@@ -357,8 +359,9 @@ public class MainFrameTree implements Serializable {
for (int i = 0; i < rows; i++) {
TreePath treePath = jTree.getPathForRow(i);
Object lastPathComponent = treePath.getLastPathComponent();
- if (lastPathComponent instanceof BugLeafNode)
+ if (lastPathComponent instanceof BugLeafNode) {
return true;
+ }
}
return false;
}
@@ -366,26 +369,30 @@ public class MainFrameTree implements Serializable {
@SwingThread
void expandToFirstLeaf(int max) {
Debug.println("expand to first leaf");
- if (leavesShown())
+ if (leavesShown()) {
return;
+ }
JTree jTree = getTree();
int i = 0;
while (true) {
int rows = jTree.getRowCount();
- if (i >= rows || rows >= max)
+ if (i >= rows || rows >= max) {
break;
+ }
TreePath treePath = jTree.getPathForRow(i);
Object lastPathComponent = treePath.getLastPathComponent();
- if (lastPathComponent instanceof BugLeafNode)
+ if (lastPathComponent instanceof BugLeafNode) {
return;
+ }
jTree.expandRow(i++);
}
}
void setupTreeListeners() {
// noinspection ConstantIfStatement
- if (false)
+ if (false) {
tree.addTreeExpansionListener(new MyTreeExpansionListener());
+ }
tree.addTreeSelectionListener(new MyTreeSelectionListener());
tree.addMouseListener(new TreeMouseListener());
@@ -413,16 +420,19 @@ public class MainFrameTree implements Serializable {
@Override
public void mouseClicked(MouseEvent e) {
Debug.println("tableheader.getReorderingAllowed() = " + getTableheader().getReorderingAllowed());
- if (!getTableheader().getReorderingAllowed())
+ if (!getTableheader().getReorderingAllowed()) {
return;
- if (e.getClickCount() == 2)
+ }
+ if (e.getClickCount() == 2) {
SorterDialog.getInstance().setVisible(true);
+ }
}
@Override
public void mouseReleased(MouseEvent arg0) {
- if (!getTableheader().getReorderingAllowed())
+ if (!getTableheader().getReorderingAllowed()) {
return;
+ }
BugTreeModel bt = (BugTreeModel) (getTree().getModel());
bt.checkSorter();
}
@@ -451,6 +461,7 @@ public class MainFrameTree implements Serializable {
textFieldForPackagesToDisplay = new JTextField();
ActionListener filterAction = new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
try {
String text = textFieldForPackagesToDisplay.getText();
@@ -532,6 +543,7 @@ public class MainFrameTree implements Serializable {
void showCard(final MainFrame.BugCard card, final Cursor cursor, final Window window) {
Runnable doRun = new Runnable() {
+ @Override
public void run() {
mainFrame.enableRecentMenu(card == MainFrame.BugCard.TREECARD);
getTableheader().setReorderingAllowed(card == MainFrame.BugCard.TREECARD);
@@ -539,16 +551,18 @@ public class MainFrameTree implements Serializable {
window.setCursor(cursor);
CardLayout layout = (CardLayout) cardPanel.getLayout();
layout.show(cardPanel, card.name());
- if (card == MainFrame.BugCard.TREECARD)
+ if (card == MainFrame.BugCard.TREECARD) {
SorterDialog.getInstance().thaw();
- else
+ } else {
SorterDialog.getInstance().freeze();
+ }
}
};
- if (SwingUtilities.isEventDispatchThread())
+ if (SwingUtilities.isEventDispatchThread()) {
doRun.run();
- else
+ } else {
SwingUtilities.invokeLater(doRun);
+ }
}
private JPanel makeNavigationPanel(String packageSelectorLabel, JComponent packageSelector, JComponent treeHeader,
@@ -596,11 +610,18 @@ public class MainFrameTree implements Serializable {
}
private class TreeMouseListener implements MouseListener {
+ @Override
public void mouseClicked(MouseEvent e) {
TreePath path = tree.getPathForLocation(e.getX(), e.getY());
- if (path == null)
+ if (path == null) {
return;
+ }
+
+ if(currentSelectedBugLeaf == path.getLastPathComponent()) {
+ // sync mainFrame if user just clicks on the same bug
+ mainFrame.syncBugInformation();
+ }
if ((e.getButton() == MouseEvent.BUTTON3) || (e.getButton() == MouseEvent.BUTTON1 && e.isControlDown())) {
@@ -609,34 +630,41 @@ public class MainFrameTree implements Serializable {
bugPopupMenu.show(tree, e.getX(), e.getY());
} else {
tree.setSelectionPath(path);
- if (!(path.getParentPath() == null))// If the path's parent
- // path is null, the
- // root was selected,
- // dont allow them to
- // filter out the root.
+ if (!(path.getParentPath() == null)) {
+ // path is null, the
+ // root was selected,
+ // dont allow them to
+ // filter out the root.
branchPopupMenu.show(tree, e.getX(), e.getY());
+ }
}
}
}
+ @Override
public void mousePressed(MouseEvent arg0) {
}
+ @Override
public void mouseReleased(MouseEvent arg0) {
}
+ @Override
public void mouseEntered(MouseEvent arg0) {
}
+ @Override
public void mouseExited(MouseEvent arg0) {
}
}
private class MyTreeSelectionListener implements TreeSelectionListener {
private volatile boolean ignoreSelection = false;
+ @Override
public void valueChanged(TreeSelectionEvent selectionEvent) {
- if (ignoreSelection)
+ if (ignoreSelection) {
return;
+ }
TreePath path = selectionEvent.getNewLeadSelectionPath();
if (path != null) {
@@ -672,6 +700,7 @@ public class MainFrameTree implements Serializable {
private class MyTreeExpansionListener implements TreeExpansionListener {
+ @Override
public void treeExpanded(TreeExpansionEvent event) {
System.out.println("Tree expanded");
TreePath path = event.getPath();
@@ -683,6 +712,7 @@ public class MainFrameTree implements Serializable {
final TreePath p = path.pathByAddingChild(o);
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
try {
System.out.println("auto expanding " + p);
@@ -698,6 +728,7 @@ public class MainFrameTree implements Serializable {
}
}
+ @Override
public void treeCollapsed(TreeExpansionEvent event) {
// do nothing
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/NewFilterFrame.java b/src/gui/edu/umd/cs/findbugs/gui2/NewFilterFrame.java
index be8a19c..1646d0d 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/NewFilterFrame.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/NewFilterFrame.java
@@ -44,15 +44,15 @@ import javax.swing.ListCellRenderer;
import edu.umd.cs.findbugs.gui2.BugAspects.SortableValue;
/**
- *
+ *
* Lets you choose your new filter, shouldn't let you choose filters that
* wouldn't filter anything out including filters that you already have
- *
+ *
*/
@SuppressWarnings("serial")
public class NewFilterFrame extends FBDialog {
- private JList list = new JList();
+ private final JList<String> list = new JList<>();
private static NewFilterFrame instance = null;
@@ -98,27 +98,32 @@ public class NewFilterFrame extends FBDialog {
}
}
- final JComboBox comboBox = new JComboBox(valuesWithoutDivider);
- comboBox.setRenderer(new ListCellRenderer() {
+ final JComboBox<Sortables> comboBox = new JComboBox<>(valuesWithoutDivider);
+ comboBox.setRenderer(new ListCellRenderer<Sortables>() {
final Color SELECTED_BACKGROUND = new Color(183, 184, 204);
- public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+ @Override
+ public Component getListCellRendererComponent(JList<? extends Sortables> list, Sortables value, int index, boolean isSelected,
boolean cellHasFocus) {
JLabel result = new JLabel();
result.setFont(result.getFont().deriveFont(Driver.getFontSize()));
result.setOpaque(true);
result.setText(value.toString().toLowerCase());
- if (isSelected)
+ if (isSelected) {
result.setBackground(SELECTED_BACKGROUND);
+ }
return result;
}
});
comboBox.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
Sortables filterBy = (Sortables) comboBox.getSelectedItem();
- String[] listData = filterBy.getAllSorted();
- for (int i = 0; i < listData.length; i++)
- listData[i] = filterBy.formatValue(listData[i]);
+ String[] rawValues = filterBy.getAllSorted();
+ String[] listData = new String[rawValues.length];
+ for (int i = 0; i < listData.length; i++) {
+ listData[i] = filterBy.formatValue(rawValues[i]);
+ }
list.setListData(listData);
}
});
@@ -128,13 +133,14 @@ public class NewFilterFrame extends FBDialog {
String[] filterModes = { edu.umd.cs.findbugs.L10N.getLocalString("mode.equal_to", "equal to"),
edu.umd.cs.findbugs.L10N.getLocalString("mode.at_or_after", "at or after"),
edu.umd.cs.findbugs.L10N.getLocalString("mode.at_or_before", "at or before") };
- final JComboBox filterModeComboBox = new JComboBox(filterModes);
+ final JComboBox<String> filterModeComboBox = new JComboBox<>(filterModes);
north.add(filterModeComboBox);
north.add(new JLabel(":"));
north.add(Box.createHorizontalGlue());
JPanel south = new JPanel();
JButton okButton = new JButton(edu.umd.cs.findbugs.L10N.getLocalString("dlg.ok_btn", "OK"));
okButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
Sortables key = (Sortables) comboBox.getSelectedItem();
String[] values = key.getAllSorted();
@@ -158,6 +164,7 @@ public class NewFilterFrame extends FBDialog {
});
JButton cancelButton = new JButton(edu.umd.cs.findbugs.L10N.getLocalString("dlg.cancel_btn", "Cancel"));
cancelButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
close();
}
@@ -179,8 +186,9 @@ public class NewFilterFrame extends FBDialog {
// ProjectSettings.getInstance().addFilter(fm);
// }
FilterMatcher[] newFilters = new FilterMatcher[list.getSelectedIndices().length];
- for (int i = 0; i < newFilters.length; i++)
+ for (int i = 0; i < newFilters.length; i++) {
newFilters[i] = new FilterMatcher(key, values[list.getSelectedIndices()[i]]);
+ }
ProjectSettings.getInstance().addFilters(newFilters);
PreferencesFrame.getInstance().updateFilterPanel();
close();
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/NewFilterFromBug.java b/src/gui/edu/umd/cs/findbugs/gui2/NewFilterFromBug.java
index 72a1f40..493cc4a 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/NewFilterFromBug.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/NewFilterFromBug.java
@@ -40,7 +40,7 @@ import edu.umd.cs.findbugs.filter.Matcher;
public class NewFilterFromBug extends FBDialog {
private static final List<NewFilterFromBug> listOfAllFrames = new ArrayList<NewFilterFromBug>();
-
+
public NewFilterFromBug(final FilterFromBugPicker filterFromBugPicker, final ApplyNewFilter applyNewFilter) {
this.setModal(true);
listOfAllFrames.add(this);
@@ -53,8 +53,9 @@ public class NewFilterFromBug extends FBDialog {
JPanel south = new JPanel();
JButton okButton = new JButton(edu.umd.cs.findbugs.L10N.getLocalString("dlg.ok_btn", "OK"));
-
+
okButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
Matcher matcherFromSelection = filterFromBugPicker.makeMatcherFromSelection();
applyNewFilter.fromMatcher(matcherFromSelection);
@@ -63,6 +64,7 @@ public class NewFilterFromBug extends FBDialog {
});
JButton cancelButton = new JButton(edu.umd.cs.findbugs.L10N.getLocalString("dlg.cancel_btn", "Cancel"));
cancelButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
closeDialog();
}
@@ -73,7 +75,7 @@ public class NewFilterFromBug extends FBDialog {
pack();
setVisible(true);
}
-
+
private final void closeDialog() {
NewFilterFromBug.this.dispose();
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/NewProjectWizard.java b/src/gui/edu/umd/cs/findbugs/gui2/NewProjectWizard.java
index b692957..c6d06cb 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/NewProjectWizard.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/NewProjectWizard.java
@@ -50,6 +50,7 @@ import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextField;
+import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileFilter;
@@ -97,25 +98,25 @@ public class NewProjectWizard extends FBDialog {
}
};
- private final JList analyzeList = new JList();
+ private final JList<String> analyzeList = new JList<String>();
- private final DefaultListModel analyzeModel = new DefaultListModel();
+ private final DefaultListModel<String> analyzeModel = new DefaultListModel<String>();
private final JTextField projectName = new JTextField();
- private final JList auxList = new JList();
+ private final JList<String> auxList = new JList<String>();
- private final DefaultListModel auxModel = new DefaultListModel();
+ private final DefaultListModel<String> auxModel = new DefaultListModel<String>();
- private final JList sourceList = new JList();
+ private final JList<String> sourceList = new JList<String>();
- private final DefaultListModel sourceModel = new DefaultListModel();
+ private final DefaultListModel<String> sourceModel = new DefaultListModel<String>();
private final JButton finishButton = new JButton();
private final JButton cancelButton = new JButton(edu.umd.cs.findbugs.L10N.getLocalString("dlg.cancel_btn", "Cancel"));
- private final JComboBox cloudSelector = new JComboBox();
+ private final JComboBox<CloudPlugin> cloudSelector = new JComboBox<CloudPlugin>();
private final JComponent[] wizardComponents = new JComponent[4];
@@ -131,10 +132,11 @@ public class NewProjectWizard extends FBDialog {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
if (-1 < index) {
- if (plugin == null)
+ if (plugin == null) {
list.setToolTipText("No cloud plugin specified by project");
- else
+ } else {
list.setToolTipText(plugin.getDetails());
+ }
}
} else {
setBackground(list.getBackground());
@@ -164,9 +166,9 @@ public class NewProjectWizard extends FBDialog {
}
boolean temp = false;
- if (curProject == null)
+ if (curProject == null) {
setTitle(edu.umd.cs.findbugs.L10N.getLocalString("dlg.new_item", "New Project"));
- else {
+ } else {
setTitle(edu.umd.cs.findbugs.L10N.getLocalString("dlg.reconfig", "Reconfigure"));
temp = true;
}
@@ -198,18 +200,22 @@ public class NewProjectWizard extends FBDialog {
cloudPanel.add(cloudSelector, BorderLayout.CENTER);
wizardComponents[3] = cloudPanel;
- cloudSelector.setRenderer(new CloudComboBoxRenderer());
+ @SuppressWarnings("unchecked")
+ ListCellRenderer<CloudPlugin> aRenderer = new CloudComboBoxRenderer();
+ cloudSelector.setRenderer(aRenderer);
cloudSelector.addItem(null);
String cloudId = project.getCloudId();
for (CloudPlugin c : DetectorFactoryCollection.instance().getRegisteredClouds().values()) {
String fbid = c.getFindbugsPluginId();
Plugin plugin = Plugin.getByPluginId(fbid);
- if (plugin == null)
+ if (plugin == null) {
continue;
+ }
Boolean fbPluginStatus = project.getPluginStatus(plugin);
- if ((!c.isHidden() || c.getId().equals(cloudId)) && !Boolean.FALSE.equals(fbPluginStatus))
+ if ((!c.isHidden() || c.getId().equals(cloudId)) && !Boolean.FALSE.equals(fbPluginStatus)) {
cloudSelector.addItem(c);
+ }
}
if (cloudId != null) {
@@ -233,20 +239,24 @@ public class NewProjectWizard extends FBDialog {
boolean keepGoing = false;
private boolean displayWarningAndAskIfWeShouldContinue(String msg, String title) {
- if (keepGoing)
+ if (keepGoing) {
return true;
+ }
boolean result = JOptionPane.showConfirmDialog(NewProjectWizard.this, msg, title, JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION;
- if (result)
+ if (result) {
keepGoing = true;
+ }
return result;
}
+ @Override
public void actionPerformed(ActionEvent evt) {
- if (displayWarnings())
+ if (displayWarnings()) {
return;
+ }
Project p;
String oldCloudId = null;
p = project;
@@ -256,12 +266,15 @@ public class NewProjectWizard extends FBDialog {
// Now that p is cleared, we can add in all the correct files.
- for (int i = 0; i < analyzeModel.getSize(); i++)
- p.addFile((String) analyzeModel.get(i));
- for (int i = 0; i < auxModel.getSize(); i++)
- p.addAuxClasspathEntry((String) auxModel.get(i));
- for (int i = 0; i < sourceModel.getSize(); i++)
- p.addSourceDir((String) sourceModel.get(i));
+ for (int i = 0; i < analyzeModel.getSize(); i++) {
+ p.addFile(analyzeModel.get(i));
+ }
+ for (int i = 0; i < auxModel.getSize(); i++) {
+ p.addAuxClasspathEntry(auxModel.get(i));
+ }
+ for (int i = 0; i < sourceModel.getSize(); i++) {
+ p.addSourceDir(sourceModel.get(i));
+ }
p.setProjectName(projectName.getText());
CloudPlugin cloudPlugin = (CloudPlugin) cloudSelector.getSelectedItem();
String newCloudId;
@@ -280,8 +293,8 @@ public class NewProjectWizard extends FBDialog {
|| JOptionPane.showConfirmDialog(NewProjectWizard.this, edu.umd.cs.findbugs.L10N
.getLocalString("dlg.project_settings_changed_lbl",
"Project settings have been changed. Perform a new analysis with the changed files?"),
- edu.umd.cs.findbugs.L10N.getLocalString("dlg.redo_analysis_question_lbl", "Redo analysis?"),
- JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)) {
+ edu.umd.cs.findbugs.L10N.getLocalString("dlg.redo_analysis_question_lbl", "Redo analysis?"),
+ JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)) {
AnalyzingDialog.show(p);
} else if (!Util.nullSafeEquals(newCloudId, oldCloudId)) {
BugCollection bugs = mainFrame.getBugCollection();
@@ -297,8 +310,9 @@ public class NewProjectWizard extends FBDialog {
mainFrame.getComments().updateCommentsFromLeafInformation(mainFrame.getCurrentSelectedBugLeaf());
}
- if (reconfig)
+ if (reconfig) {
mainFrame.setProjectChanged(true);
+ }
String name = p.getProjectName();
if (name == null) {
@@ -314,42 +328,47 @@ public class NewProjectWizard extends FBDialog {
private boolean displayWarnings() {
for (int i = 0; i < analyzeModel.getSize(); i++) {
- File temp = new File((String) analyzeModel.get(i));
+ File temp = new File(analyzeModel.get(i));
if (!temp.exists() && directoryOrArchive.accept(temp)) {
if (!displayWarningAndAskIfWeShouldContinue(
temp.getName() + " " + edu.umd.cs.findbugs.L10N.getLocalString("dlg.invalid_txt", " is invalid."),
- edu.umd.cs.findbugs.L10N.getLocalString("dlg.error_ttl", "Can't locate file")))
+ edu.umd.cs.findbugs.L10N.getLocalString("dlg.error_ttl", "Can't locate file"))) {
return true;
+ }
}
}
for (int i = 0; i < sourceModel.getSize(); i++) {
- File temp = new File((String) sourceModel.get(i));
+ File temp = new File(sourceModel.get(i));
if (!temp.exists() && directoryOrArchive.accept(temp)) {
if (!displayWarningAndAskIfWeShouldContinue(
temp.getName() + " " + edu.umd.cs.findbugs.L10N.getLocalString("dlg.invalid_txt", " is invalid."),
- edu.umd.cs.findbugs.L10N.getLocalString("dlg.error_ttl", "Can't locate file")))
+ edu.umd.cs.findbugs.L10N.getLocalString("dlg.error_ttl", "Can't locate file"))) {
return true;
+ }
}
}
for (int i = 0; i < auxModel.getSize(); i++) {
- File temp = new File((String) auxModel.get(i));
+ File temp = new File(auxModel.get(i));
if (!temp.exists() && directoryOrArchive.accept(temp)) {
if (!displayWarningAndAskIfWeShouldContinue(
temp.getName() + " " + edu.umd.cs.findbugs.L10N.getLocalString("dlg.invalid_txt", " is invalid."),
- edu.umd.cs.findbugs.L10N.getLocalString("dlg.error_ttl", "Can't locate file")))
+ edu.umd.cs.findbugs.L10N.getLocalString("dlg.error_ttl", "Can't locate file"))) {
return true;
+ }
}
}
return false;
}
});
- if (curProject == null)
+ if (curProject == null) {
finishButton.setText(edu.umd.cs.findbugs.L10N.getLocalString("dlg.analyze_btn", "Analyze"));
- else
+ } else {
finishButton.setText(edu.umd.cs.findbugs.L10N.getLocalString("dlg.ok_btn", "OK"));
+ }
cancelButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
dispose();
}
@@ -361,16 +380,19 @@ public class NewProjectWizard extends FBDialog {
south.add(buttons, BorderLayout.EAST);
if (curProject != null) {
- for (String i : curProject.getFileList())
+ for (String i : curProject.getFileList()) {
analyzeModel.addElement(i);
+ }
// If the project had no classes in it, disable the finish button
// until classes are added.
// if (curProject.getFileList().size()==0)
// this.finishButton.setEnabled(false);
- for (String i : curProject.getAuxClasspathEntryList())
+ for (String i : curProject.getAuxClasspathEntryList()) {
auxModel.addElement(i);
- for (String i : curProject.getSourceDirList())
+ }
+ for (String i : curProject.getSourceDirList()) {
sourceModel.addElement(i);
+ }
projectName.setText(curProject.getProjectName());
projectName.addKeyListener(new KeyAdapter() {
@Override
@@ -400,16 +422,19 @@ public class NewProjectWizard extends FBDialog {
// First clear p's old files, otherwise we can't remove a file
// once an analysis has been performed on it
int numOldFiles = p.getFileCount();
- for (int x = 0; x < numOldFiles; x++)
+ for (int x = 0; x < numOldFiles; x++) {
p.removeFile(0);
+ }
int numOldAuxFiles = p.getNumAuxClasspathEntries();
- for (int x = 0; x < numOldAuxFiles; x++)
+ for (int x = 0; x < numOldAuxFiles; x++) {
p.removeAuxClasspathEntry(0);
+ }
int numOldSrc = p.getNumSourceDirs();
- for (int x = 0; x < numOldSrc; x++)
+ for (int x = 0; x < numOldSrc; x++) {
p.removeSourceDir(0);
+ }
}
private JComponent createTextFieldPanel(String label, JTextField textField) {
@@ -422,9 +447,9 @@ public class NewProjectWizard extends FBDialog {
return myPanel;
}
- private JPanel createFilePanel(final String label, final JList list, final DefaultListModel listModel,
- final int fileSelectionMode, final FileFilter filter, final String dialogTitle,
- boolean wizard, final String helpUrl) {
+ private JPanel createFilePanel(final String label, final JList<String> list, final DefaultListModel<String> listModel,
+ final int fileSelectionMode, final FileFilter filter, final String dialogTitle,
+ boolean wizard, final String helpUrl) {
JPanel myPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
@@ -450,6 +475,7 @@ public class NewProjectWizard extends FBDialog {
button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
button.setContentAreaFilled(false);
button.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
try {
LaunchBrowser.showDocument(new URL(helpUrl));
@@ -491,22 +517,27 @@ public class NewProjectWizard extends FBDialog {
final NewProjectWizard thisGUI = this;
myPanel.add(wizardButton, gbc);
wizardButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
final Project tempProject = new Project();
- for (int i = 0; i < analyzeModel.getSize(); i++)
- tempProject.addFile((String) analyzeModel.get(i));
- for (int i = 0; i < auxModel.getSize(); i++)
- tempProject.addAuxClasspathEntry((String) auxModel.get(i));
+ for (int i = 0; i < analyzeModel.getSize(); i++) {
+ tempProject.addFile(analyzeModel.get(i));
+ }
+ for (int i = 0; i < auxModel.getSize(); i++) {
+ tempProject.addAuxClasspathEntry(auxModel.get(i));
+ }
java.awt.EventQueue.invokeLater(new Runnable() {
+ @Override
public void run() {
final SourceDirectoryWizard dialog = new SourceDirectoryWizard(new javax.swing.JFrame(), true,
tempProject, thisGUI);
dialog.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
- if (dialog.discover != null && dialog.discover.isAlive())
+ if (dialog.discover != null && dialog.discover.isAlive()) {
dialog.discover.interrupt();
+ }
}
});
dialog.setVisible(true);
@@ -519,6 +550,7 @@ public class NewProjectWizard extends FBDialog {
myPanel.add(Box.createGlue(), gbc);
myPanel.setBorder(border);
addButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
chooser.setFileSelectionMode(fileSelectionMode);
chooser.setMultiSelectionEnabled(true);
@@ -541,24 +573,29 @@ public class NewProjectWizard extends FBDialog {
// If this is the primary class directories add button, set
// it to enable the finish button of the main dialog
if (label.equals(edu.umd.cs.findbugs.L10N.getLocalString("dlg.class_jars_dirs_lbl",
- "Class archives and directories to analyze:")))
+ "Class archives and directories to analyze:"))) {
finishButton.setEnabled(true);
+ }
}
}
});
removeButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
- if (list.getSelectedValues().length > 0)
+ if (list.getSelectedValues().length > 0) {
projectChanged = true;
+ }
for (Object i : list.getSelectedValues())
+ {
listModel.removeElement(i);
- // If this is the primary class directories remove button, set
- // it to disable finish when there are no class files being
- // analyzed
- // if (listModel.size()==0 &&
- // label.equals(edu.umd.cs.findbugs.L10N.getLocalString("dlg.class_jars_dirs_lbl",
- // "Class archives and directories to analyze:")))
- // finishButton.setEnabled(false);
+ // If this is the primary class directories remove button, set
+ // it to disable finish when there are no class files being
+ // analyzed
+ // if (listModel.size()==0 &&
+ // label.equals(edu.umd.cs.findbugs.L10N.getLocalString("dlg.class_jars_dirs_lbl",
+ // "Class archives and directories to analyze:")))
+ // finishButton.setEnabled(false);
+ }
}
});
return myPanel;
@@ -573,12 +610,15 @@ public class NewProjectWizard extends FBDialog {
*/
private void loadAllPanels(final JPanel mainPanel) {
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
int numPanels = wizardComponents.length;
- for (int i = 0; i < numPanels; i++)
+ for (int i = 0; i < numPanels; i++) {
mainPanel.remove(wizardComponents[i]);
- for (int i = 0; i < numPanels; i++)
+ }
+ for (int i = 0; i < numPanels; i++) {
mainPanel.add(wizardComponents[i]);
+ }
validate();
repaint();
}
@@ -597,8 +637,9 @@ public class NewProjectWizard extends FBDialog {
int width = super.getWidth();
- if (width < 600)
+ if (width < 600) {
width = 600;
+ }
setSize(new Dimension(width, 500));
setLocationRelativeTo(MainFrame.getInstance());
}
@@ -606,7 +647,7 @@ public class NewProjectWizard extends FBDialog {
/**
* @param foundModel
*/
- public void setSourceDirecs(DefaultListModel foundModel) {
+ public void setSourceDirecs(DefaultListModel<String> foundModel) {
for (int i = 0; i < foundModel.size(); i++) {
this.sourceModel.addElement(foundModel.getElementAt(i));
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/OSXAdapter.java b/src/gui/edu/umd/cs/findbugs/gui2/OSXAdapter.java
index 39f2018..e40aa08 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/OSXAdapter.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/OSXAdapter.java
@@ -57,6 +57,7 @@ public class OSXAdapter extends ApplicationAdapter {
// selected, and we get a ReOpenApplication event when user
// switches back to Findbugs.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
mainApp.about();
}
@@ -100,8 +101,9 @@ public class OSXAdapter extends ApplicationAdapter {
// that needs to be called at runtime, and it can easily be done using
// reflection (see MyApp.java)
public static void registerMacOSXApplication(MainFrame inApp) {
- if (mainApp != null)
+ if (mainApp != null) {
throw new IllegalStateException("application already set");
+ }
mainApp = inApp;
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/PluginUpdateDialog.java b/src/gui/edu/umd/cs/findbugs/gui2/PluginUpdateDialog.java
index 0988f85..764f632 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/PluginUpdateDialog.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/PluginUpdateDialog.java
@@ -1,201 +1,214 @@
-package edu.umd.cs.findbugs.gui2;
-
-import java.awt.Cursor;
-import java.awt.Font;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.Serializable;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.swing.JButton;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JTextPane;
-import javax.swing.SwingUtilities;
-
-import edu.umd.cs.findbugs.DetectorFactoryCollection;
-import edu.umd.cs.findbugs.updates.PluginUpdateListener;
-import edu.umd.cs.findbugs.updates.UpdateChecker;
-import edu.umd.cs.findbugs.util.LaunchBrowser;
-
-public class PluginUpdateDialog implements Serializable {
- private static final Logger LOGGER = Logger.getLogger(PluginUpdateDialog.class.getName());
-
- private static final int SOFTWARE_UPDATE_DIALOG_DELAY_MS = 5000;
-
- public void showUpdateDialog(Collection<UpdateChecker.PluginUpdate> updates, boolean force) {
- List<UpdateChecker.PluginUpdate> sortedUpdates = new ArrayList<UpdateChecker.PluginUpdate>();
- UpdateChecker.PluginUpdate core = sortUpdates(updates, sortedUpdates);
-
- if (DetectorFactoryCollection.instance().getUpdateChecker()
- .updatesHaveBeenSeenBefore(sortedUpdates) && !force)
- return;
-
- String headline;
- if (core != null && updates.size() >= 2)
- headline = "FindBugs and some plugins have updates";
- else if (updates.isEmpty())
- headline = "FindBugs and all plugins are up to date!";
- else if (core == null)
- headline = "Some FindBugs plugins have updates";
- else
- headline = null;
-
- final JPanel comp = new JPanel(new GridBagLayout());
- GridBagConstraints gbc = new GridBagConstraints();
- gbc.insets = new Insets(5, 5, 5, 5);
- gbc.gridwidth = 3;
- gbc.fill = GridBagConstraints.BOTH;
- if (headline != null) {
- JLabel headlineLabel = new JLabel(headline);
- headlineLabel.setFont(headlineLabel.getFont().deriveFont(Font.BOLD, 24));
- comp.add(headlineLabel, gbc);
- }
- if (!updates.isEmpty()) {
- int i = 1;
- for (final UpdateChecker.PluginUpdate update : sortedUpdates) {
- gbc.gridy = ++i;
- gbc.gridx = 1;
- gbc.fill = GridBagConstraints.BOTH;
- gbc.gridwidth = 1;
- gbc.weightx = 1;
- JLabel label = createPluginLabel(update);
- comp.add(label, gbc);
- gbc.weightx = 0;
- gbc.gridx = 2;
- String url = update.getUrl();
- if (url != null && url.length() > 0) {
- JButton button = createPluginUpdateButton(comp, update);
- comp.add(button, gbc);
- }
- String msg = update.getMessage();
- if (msg != null && msg.length() > 0) {
- gbc.gridx = 1;
- gbc.gridwidth = 3;
- gbc.weightx = 1;
- gbc.fill = GridBagConstraints.BOTH;
- gbc.gridy = ++i;
- JTextPane msgpane = createMessagePane(msg);
- comp.add(msgpane, gbc);
- }
- }
- }
- JOptionPane.showMessageDialog(null, comp, "Software Updates", JOptionPane.INFORMATION_MESSAGE);
- }
-
- private JTextPane createMessagePane(String msg) {
- JTextPane msgpane = new JTextPane();
- msgpane.setEditable(false);
- msgpane.setFocusable(false);
- msgpane.setText(msg);
- return msgpane;
- }
-
- private JLabel createPluginLabel(UpdateChecker.PluginUpdate update) {
- String name;
- if (update.getPlugin().isCorePlugin())
- name = "FindBugs";
- else
- name = update.getPlugin().getShortDescription();
- JLabel label = new JLabel(MessageFormat.format(
- "<html><b>{0} {2}</b> is available<br><i><small>(currently installed: {1})",
- name, update.getPlugin().getVersion(), update.getVersion()));
- label.setFont(label.getFont().deriveFont(Font.PLAIN, label.getFont().getSize() + 4));
- return label;
- }
-
-
- public PluginUpdateListener createListener() {
- return new MyPluginUpdateListener();
- }
-
-
-
- private JButton createPluginUpdateButton(final JPanel comp, final UpdateChecker.PluginUpdate update) {
- JButton button = new JButton("<html><u><font color=#0000ff>More info...");
- button.setBorderPainted(false);
- button.setOpaque(false);
- button.setContentAreaFilled(false);
- button.setBackground(comp.getBackground());
- button.setToolTipText(update.getUrl());
- button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
- button.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- boolean failed;
- String url = update.getUrl();
- try {
- failed = url == null || !LaunchBrowser.showDocument(new URL(url));
- } catch (MalformedURLException e1) {
- failed = true;
- }
- if (failed)
- JOptionPane.showMessageDialog(comp, "Could not open URL " + url);
- }
- });
- return button;
- }
-
- private UpdateChecker.PluginUpdate sortUpdates(Collection<UpdateChecker.PluginUpdate> updates,
- List<UpdateChecker.PluginUpdate> sorted) {
- UpdateChecker.PluginUpdate core = null;
- for (UpdateChecker.PluginUpdate update : updates) {
- if (update.getPlugin().isCorePlugin())
- core = update;
- else
- sorted.add(update);
- }
- // sort by name
- Collections.sort(sorted, new Comparator<UpdateChecker.PluginUpdate>() {
- public int compare(UpdateChecker.PluginUpdate o1, UpdateChecker.PluginUpdate o2) {
- return o1.getPlugin().getShortDescription().compareTo(o2.getPlugin().getShortDescription());
- }
- });
- // place core plugin first, if present
- if (core != null)
- sorted.add(0, core);
- return core;
- }
-
- private class MyPluginUpdateListener implements PluginUpdateListener {
- public void pluginUpdateCheckComplete(final Collection<UpdateChecker.PluginUpdate> updates, final boolean force) {
- if (updates.isEmpty() && !force)
- return;
-
- if (force)
- showUpdateDialogInSwingThread(updates, force);
- else
- // wait 5 seconds before showing dialog
- edu.umd.cs.findbugs.util.Util.runInDameonThread(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SOFTWARE_UPDATE_DIALOG_DELAY_MS);
- showUpdateDialogInSwingThread(updates, force);
- } catch (InterruptedException e) {
- LOGGER.log(Level.FINE, "Software update dialog thread interrupted", e);
- }
- }
- }, "Software Update Dialog");
- }
-
- private void showUpdateDialogInSwingThread(final Collection<UpdateChecker.PluginUpdate> updates, final boolean force) {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- showUpdateDialog(updates, force);
- }
- });
- }
- }
+package edu.umd.cs.findbugs.gui2;
+
+import java.awt.Cursor;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextPane;
+import javax.swing.SwingUtilities;
+
+import edu.umd.cs.findbugs.DetectorFactoryCollection;
+import edu.umd.cs.findbugs.updates.PluginUpdateListener;
+import edu.umd.cs.findbugs.updates.UpdateChecker;
+import edu.umd.cs.findbugs.util.LaunchBrowser;
+
+public class PluginUpdateDialog implements Serializable {
+ private static final Logger LOGGER = Logger.getLogger(PluginUpdateDialog.class.getName());
+
+ private static final int SOFTWARE_UPDATE_DIALOG_DELAY_MS = 5000;
+
+ public void showUpdateDialog(Collection<UpdateChecker.PluginUpdate> updates, boolean force) {
+ List<UpdateChecker.PluginUpdate> sortedUpdates = new ArrayList<UpdateChecker.PluginUpdate>();
+ UpdateChecker.PluginUpdate core = sortUpdates(updates, sortedUpdates);
+
+ if (DetectorFactoryCollection.instance().getUpdateChecker()
+ .updatesHaveBeenSeenBefore(sortedUpdates) && !force) {
+ return;
+ }
+
+ String headline;
+ if (core != null && updates.size() >= 2) {
+ headline = "FindBugs and some plugins have updates";
+ } else if (updates.isEmpty()) {
+ headline = "FindBugs and all plugins are up to date!";
+ } else if (core == null) {
+ headline = "Some FindBugs plugins have updates";
+ } else {
+ headline = null;
+ }
+
+ final JPanel comp = new JPanel(new GridBagLayout());
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.insets = new Insets(5, 5, 5, 5);
+ gbc.gridwidth = 3;
+ gbc.fill = GridBagConstraints.BOTH;
+ if (headline != null) {
+ JLabel headlineLabel = new JLabel(headline);
+ headlineLabel.setFont(headlineLabel.getFont().deriveFont(Font.BOLD, 24));
+ comp.add(headlineLabel, gbc);
+ }
+ if (!updates.isEmpty()) {
+ int i = 1;
+ for (final UpdateChecker.PluginUpdate update : sortedUpdates) {
+ gbc.gridy = ++i;
+ gbc.gridx = 1;
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.gridwidth = 1;
+ gbc.weightx = 1;
+ JLabel label = createPluginLabel(update);
+ comp.add(label, gbc);
+ gbc.weightx = 0;
+ gbc.gridx = 2;
+ String url = update.getUrl();
+ if (url != null && url.length() > 0) {
+ JButton button = createPluginUpdateButton(comp, update);
+ comp.add(button, gbc);
+ }
+ String msg = update.getMessage();
+ if (msg != null && msg.length() > 0) {
+ gbc.gridx = 1;
+ gbc.gridwidth = 3;
+ gbc.weightx = 1;
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.gridy = ++i;
+ JTextPane msgpane = createMessagePane(msg);
+ comp.add(msgpane, gbc);
+ }
+ }
+ }
+ JOptionPane.showMessageDialog(null, comp, "Software Updates", JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ private JTextPane createMessagePane(String msg) {
+ JTextPane msgpane = new JTextPane();
+ msgpane.setEditable(false);
+ msgpane.setFocusable(false);
+ msgpane.setText(msg);
+ return msgpane;
+ }
+
+ private JLabel createPluginLabel(UpdateChecker.PluginUpdate update) {
+ String name;
+ if (update.getPlugin().isCorePlugin()) {
+ name = "FindBugs";
+ } else {
+ name = update.getPlugin().getShortDescription();
+ }
+ JLabel label = new JLabel(MessageFormat.format(
+ "<html><b>{0} {2}</b> is available<br><i><small>(currently installed: {1})",
+ name, update.getPlugin().getVersion(), update.getVersion()));
+ label.setFont(label.getFont().deriveFont(Font.PLAIN, label.getFont().getSize() + 4));
+ return label;
+ }
+
+
+ public PluginUpdateListener createListener() {
+ return new MyPluginUpdateListener();
+ }
+
+
+
+ private JButton createPluginUpdateButton(final JPanel comp, final UpdateChecker.PluginUpdate update) {
+ JButton button = new JButton("<html><u><font color=#0000ff>More info...");
+ button.setBorderPainted(false);
+ button.setOpaque(false);
+ button.setContentAreaFilled(false);
+ button.setBackground(comp.getBackground());
+ button.setToolTipText(update.getUrl());
+ button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ boolean failed;
+ String url = update.getUrl();
+ try {
+ failed = url == null || !LaunchBrowser.showDocument(new URL(url));
+ } catch (MalformedURLException e1) {
+ failed = true;
+ }
+ if (failed) {
+ JOptionPane.showMessageDialog(comp, "Could not open URL " + url);
+ }
+ }
+ });
+ return button;
+ }
+
+ private UpdateChecker.PluginUpdate sortUpdates(Collection<UpdateChecker.PluginUpdate> updates,
+ List<UpdateChecker.PluginUpdate> sorted) {
+ UpdateChecker.PluginUpdate core = null;
+ for (UpdateChecker.PluginUpdate update : updates) {
+ if (update.getPlugin().isCorePlugin()) {
+ core = update;
+ } else {
+ sorted.add(update);
+ }
+ }
+ // sort by name
+ Collections.sort(sorted, new Comparator<UpdateChecker.PluginUpdate>() {
+ @Override
+ public int compare(UpdateChecker.PluginUpdate o1, UpdateChecker.PluginUpdate o2) {
+ return o1.getPlugin().getShortDescription().compareTo(o2.getPlugin().getShortDescription());
+ }
+ });
+ // place core plugin first, if present
+ if (core != null) {
+ sorted.add(0, core);
+ }
+ return core;
+ }
+
+ private class MyPluginUpdateListener implements PluginUpdateListener {
+ @Override
+ public void pluginUpdateCheckComplete(final Collection<UpdateChecker.PluginUpdate> updates, final boolean force) {
+ if (updates.isEmpty() && !force) {
+ return;
+ }
+
+ if (force) {
+ showUpdateDialogInSwingThread(updates, force);
+ } else {
+ // wait 5 seconds before showing dialog
+ edu.umd.cs.findbugs.util.Util.runInDameonThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(SOFTWARE_UPDATE_DIALOG_DELAY_MS);
+ showUpdateDialogInSwingThread(updates, force);
+ } catch (InterruptedException e) {
+ LOGGER.log(Level.FINE, "Software update dialog thread interrupted", e);
+ }
+ }
+ }, "Software Update Dialog");
+ }
+ }
+
+ private void showUpdateDialogInSwingThread(final Collection<UpdateChecker.PluginUpdate> updates, final boolean force) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ showUpdateDialog(updates, force);
+ }
+ });
+ }
+ }
}
\ No newline at end of file
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/PreferencesFrame.java b/src/gui/edu/umd/cs/findbugs/gui2/PreferencesFrame.java
index a439e55..3f9ded4 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/PreferencesFrame.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/PreferencesFrame.java
@@ -48,6 +48,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -78,6 +79,7 @@ import javax.swing.tree.TreeModel;
import edu.umd.cs.findbugs.BugCollection;
import edu.umd.cs.findbugs.Plugin;
+import edu.umd.cs.findbugs.PluginException;
import edu.umd.cs.findbugs.Project;
import edu.umd.cs.findbugs.cloud.CloudPlugin;
import edu.umd.cs.findbugs.filter.Filter;
@@ -96,7 +98,7 @@ public class PreferencesFrame extends FBDialog {
private static PreferencesFrame instance;
- private final CheckBoxList filterCheckBoxList = new CheckBoxList();
+ private final CheckBoxList<MatchBox> filterCheckBoxList = new CheckBoxList<>();
// Variables for Properties tab.
private JTextField tabTextField;
@@ -118,8 +120,9 @@ public class PreferencesFrame extends FBDialog {
}
public static PreferencesFrame getInstance() {
- if (instance == null)
+ if (instance == null) {
instance = new PreferencesFrame();
+ }
return instance;
}
@@ -127,10 +130,10 @@ public class PreferencesFrame extends FBDialog {
private boolean pluginsAdded = false;
private final JPanel filterPane;
private final JTabbedPane mainTabPane;
-
+
public void showFilterPane() {
mainTabPane.setSelectedComponent(filterPane);
-
+
}
private PreferencesFrame() {
setTitle(edu.umd.cs.findbugs.L10N.getLocalString("dlg.fil_sup_ttl", "Preferences"));
@@ -157,6 +160,7 @@ public class PreferencesFrame extends FBDialog {
bottom.setLayout(new BoxLayout(bottom, BoxLayout.X_AXIS));
bottom.add(Box.createHorizontalGlue());
bottom.add(new JButton(new AbstractAction(edu.umd.cs.findbugs.L10N.getLocalString("pref.close", "Close")) {
+ @Override
public void actionPerformed(ActionEvent evt) {
handleWindowClose();
PreferencesFrame.this.setVisible(false);
@@ -189,8 +193,9 @@ public class PreferencesFrame extends FBDialog {
private void handleWindowClose() {
TreeModel bt = (MainFrame.getInstance().getTree().getModel());
- if (bt instanceof BugTreeModel)
+ if (bt instanceof BugTreeModel) {
((BugTreeModel) bt).checkSorter();
+ }
Project project = getCurrentProject();
boolean changed = pluginsAdded;
@@ -203,15 +208,17 @@ public class PreferencesFrame extends FBDialog {
if (project != null) {
Boolean newSetting = enabled.project;
Boolean existingSetting = project.getPluginStatus(plugin);
- if (existingSetting != newSetting && (newSetting == null || !newSetting.equals(existingSetting))) {
+ boolean sameSettings = Objects.equals(existingSetting, newSetting);
+ if (!sameSettings) {
project.setPluginStatusTrinary(plugin.getPluginId(), newSetting);
changed = true;
}
}
- if (enabled.global)
+ if (enabled.global) {
enabledPlugins.add(plugin.getPluginId());
- else
+ } else {
disabledPlugins.add(plugin.getPluginId());
+ }
if (plugin.isGloballyEnabled() != enabled.global) {
plugin.setGloballyEnabled(enabled.global);
changed = true;
@@ -248,6 +255,7 @@ public class PreferencesFrame extends FBDialog {
south.add(addButton);
addButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
chooser.addChoosableFileFilter(new FileFilter() {
@@ -257,15 +265,17 @@ public class PreferencesFrame extends FBDialog {
return "FindBugs Plugin (*.jar)";
}
- @SuppressWarnings({"RedundantIfStatement"})
@Override
public boolean accept(File f) {
- if (f.isDirectory())
+ if (f.isDirectory()) {
return true;
- if (!f.canRead())
+ }
+ if (!f.canRead()) {
return false;
- if (f.getName().endsWith(".jar"))
+ }
+ if (f.getName().endsWith(".jar")) {
return true;
+ }
return false;
}
});
@@ -289,7 +299,7 @@ public class PreferencesFrame extends FBDialog {
pluginsAdded = true;
rebuildPluginCheckboxes();
- } catch (Exception e1) {
+ } catch (PluginException | MalformedURLException e1) {
LOGGER.log(Level.WARNING, "Could not load " + f.getPath(), e1);
JOptionPane.showMessageDialog(PreferencesFrame.this, "Could not load " + f.getPath()
+ "\n\n"
@@ -308,7 +318,7 @@ public class PreferencesFrame extends FBDialog {
EnabledSettings isEnabled(@CheckForNull Project project, Plugin plugin) {
return new EnabledSettings(plugin.isGloballyEnabled(), project == null ? null : project.getPluginStatus(plugin));
}
-
+
private void rebuildPluginCheckboxes() {
Project currentProject = getCurrentProject();
pluginPanelCenter.removeAll();
@@ -317,9 +327,9 @@ public class PreferencesFrame extends FBDialog {
g.fill = GridBagConstraints.NONE;
g.insets = new Insets(5,5,5,5);
g.gridy = 0;
- // g.anchor = GridBagConstraints.WEST;
- // g.gridx = 1;
- // pluginPanelCenter.add(new JLabel("Global Setting"), g);
+ // g.anchor = GridBagConstraints.WEST;
+ // g.gridx = 1;
+ // pluginPanelCenter.add(new JLabel("Global Setting"), g);
g.anchor = GridBagConstraints.CENTER;
g.gridx = 2;
pluginPanelCenter.add(new JLabel("Project Setting"), g);
@@ -327,12 +337,14 @@ public class PreferencesFrame extends FBDialog {
Collection<Plugin> plugins = Plugin.getAllPlugins();
int added = 0;
for (final Plugin plugin : plugins) {
- if (plugin.isCorePlugin())
+ if (plugin.isCorePlugin()) {
continue;
+ }
String text = plugin.getShortDescription();
String id = plugin.getPluginId();
- if (text == null)
+ if (text == null) {
text = id;
+ }
final URL url = plugin.getPluginLoader().getURL();
String pluginUrlStr = url.toExternalForm();
if ("file".equals(url.getProtocol())) {
@@ -349,25 +361,27 @@ public class PreferencesFrame extends FBDialog {
final JCheckBox checkGlobal = new JCheckBox(text, enabled.global);
final boolean cannotDisable = plugin.isEnabledByDefault() && plugin.cannotDisable();
if (cannotDisable) {
- if (!enabled.global)
+ if (!enabled.global) {
throw new IllegalStateException(
plugin.getPluginId() + " is enabled by default and cannot be disabled, but is disabled");
+ }
checkGlobal.setEnabled(false);
} else {
checkGlobal.addMouseListener(new MouseAdapter() {
-
- @Override
- public void mousePressed(MouseEvent e) {
- if (SwingUtilities.isRightMouseButton(e)) {
- JPopupMenu menu = new JPopupMenu();
- JMenuItem item = new JMenuItem("Uninstall " + plugin.getShortDescription() + "...");
- item.addActionListener(new UninstallClickListener(plugin, url));
- menu.add(item);
- menu.show(checkGlobal, e.getX(), e.getY());
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ if (SwingUtilities.isRightMouseButton(e)) {
+ JPopupMenu menu = new JPopupMenu();
+ JMenuItem item = new JMenuItem("Uninstall " + plugin.getShortDescription() + "...");
+ item.addActionListener(new UninstallClickListener(plugin, url));
+ menu.add(item);
+ menu.show(checkGlobal, e.getX(), e.getY());
+ }
}
- }
- });
+ });
checkGlobal.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
pluginEnabledStatus.get(plugin).global = checkGlobal.isSelected();
}
@@ -375,10 +389,11 @@ public class PreferencesFrame extends FBDialog {
}
checkGlobal.setVerticalTextPosition(SwingConstants.TOP);
String longText = plugin.getDetailedDescription();
- if (longText != null)
+ if (longText != null) {
checkGlobal.setToolTipText("<html>" + longText + "</html>");
+ }
pluginEnabledStatus.put(plugin, enabled);
-
+
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
@@ -389,30 +404,48 @@ public class PreferencesFrame extends FBDialog {
pluginPanelCenter.add(checkGlobal, gbc);
if (currentProject != null && !cannotDisable) {
- final JComboBox combo = new WideComboBox(new Object[]{"DEFAULT", "DISABLED", "ENABLED"});
- if (enabled.project == null) combo.setSelectedIndex(0);
- else combo.setSelectedIndex(enabled.project ? 2 : 1);
+ final JComboBox<String> combo = new WideComboBox<>(new String[]{"DEFAULT", "DISABLED", "ENABLED"});
+ if (enabled.project == null) {
+ combo.setSelectedIndex(0);
+ } else {
+ combo.setSelectedIndex(enabled.project ? 2 : 1);
+ }
combo.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (index == -1) {
- if (value.equals("DEFAULT")) value = "Default";
- if (value.equals("DISABLED")) value = "Disabled";
- if (value.equals("ENABLED")) value = "Enabled";
+ if (value.equals("DEFAULT")) {
+ value = "Default";
+ }
+ if (value.equals("DISABLED")) {
+ value = "Disabled";
+ }
+ if (value.equals("ENABLED")) {
+ value = "Enabled";
+ }
} else {
- if (value.equals("DEFAULT")) value = "Default (use global setting)";
- if (value.equals("DISABLED")) value = "Disabled for this project";
- if (value.equals("ENABLED")) value = "Enabled for this project";
+ if (value.equals("DEFAULT")) {
+ value = "Default (use global setting)";
+ }
+ if (value.equals("DISABLED")) {
+ value = "Disabled for this project";
+ }
+ if (value.equals("ENABLED")) {
+ value = "Enabled for this project";
+ }
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
combo.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
Boolean[] array = { null, false, true };
int i = combo.getSelectedIndex();
if (i < 0 || i > 2)
+ {
return; // ??
+ }
pluginEnabledStatus.get(plugin).project = array[i];
}
});
@@ -446,7 +479,7 @@ public class PreferencesFrame extends FBDialog {
private void addField(JPanel p, GridBagConstraints c, int y, String lbl, JComponent field) {
c.gridy = y;
- JLabel l = new JLabel(lbl, JLabel.TRAILING);
+ JLabel l = new JLabel(lbl, SwingConstants.TRAILING);
l.setLabelFor(field);
c.anchor = GridBagConstraints.LINE_END;
c.gridx = 0;
@@ -460,14 +493,14 @@ public class PreferencesFrame extends FBDialog {
JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.ipadx = c.ipady = 5;
-
+
float currFS = Driver.getFontSize();
tabTextField = new JTextField(Integer.toString(GUISaveState.getInstance().getTabSize()));
tabTextField.setPreferredSize(new Dimension((int) (currFS * 4), (int) (currFS * 2)));
addField(mainPanel, c, 0, "Tab size", tabTextField);
-
+
fontTextField = new JTextField(Float.toString(GUISaveState.getInstance().getFontSize()));
fontTextField.setPreferredSize(new Dimension((int) (currFS * 6), (int) (currFS * 2)));
addField(mainPanel, c, 1, "Font size", fontTextField);
@@ -480,6 +513,7 @@ public class PreferencesFrame extends FBDialog {
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new AbstractAction("Apply") {
+ @Override
public void actionPerformed(ActionEvent evt) {
changeTabSize();
changeFontSize();
@@ -488,6 +522,7 @@ public class PreferencesFrame extends FBDialog {
}));
bottomPanel.add(new JButton(new AbstractAction("Reset") {
+ @Override
public void actionPerformed(ActionEvent evt) {
resetPropertiesPane();
}
@@ -502,15 +537,16 @@ public class PreferencesFrame extends FBDialog {
public PluginWithDescription(String description, CloudPlugin plugin) {
this.description = description;
- this.plugin = plugin;
+ // this.plugin = plugin;
}
final String description;
- final CloudPlugin plugin;
+ // final CloudPlugin plugin;
+
@Override
public String toString() {
return description;
}
-
+
}
private void changeTabSize() {
int tabSize;
@@ -519,7 +555,7 @@ public class PreferencesFrame extends FBDialog {
tabSize = Integer.decode(tabTextField.getText());
} catch (NumberFormatException exc) {
JOptionPane.showMessageDialog(instance, "Error in tab size field.", "Tab Size Error",
- JOptionPane.INFORMATION_MESSAGE);
+ JOptionPane.INFORMATION_MESSAGE);
return;
}
@@ -632,6 +668,7 @@ public class PreferencesFrame extends FBDialog {
gbc.weighty = 0;
filterPanel.add(addButton, gbc);
addButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
NewFilterFrame.open();
}
@@ -641,10 +678,12 @@ public class PreferencesFrame extends FBDialog {
gbc.insets = new Insets(5, 0, 0, 0);
filterPanel.add(removeButton, gbc);
removeButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
Object[] selected = filterCheckBoxList.getSelectedValues();
- if (selected.length == 0)
+ if (selected.length == 0) {
return;
+ }
for (Object o : selected) {
MatchBox box = (MatchBox) o;
MainFrame.getInstance().getProject().getSuppressionFilter().removeChild(box.getMatcher());
@@ -659,16 +698,19 @@ public class PreferencesFrame extends FBDialog {
gbc.insets = new Insets(5, 0, 0, 0);
filterPanel.add(removeAllButton, gbc);
removeAllButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
boolean needsRebuild = false;
Filter suppressionFilter = MainFrame.getInstance().getProject().getSuppressionFilter();
- if (!suppressionFilter.isEmpty())
+ if (!suppressionFilter.isEmpty()) {
needsRebuild = true;
+ }
suppressionFilter.clear();
- if (needsRebuild)// TODO This will rebuild even if all the
- // filters being cleared were disabled
+ if (needsRebuild) {
+ // filters being cleared were disabled
FilterActivity.notifyListeners(FilterListener.Action.UNFILTERING, null);
+ }
MainFrame.getInstance().setProjectChanged(true);
updateFilterPanel();
}
@@ -701,11 +743,13 @@ public class PreferencesFrame extends FBDialog {
for (final Matcher m : f.getChildren()) {
MatchBox box = new MatchBox(m.toString(), m);
box.addItemListener(new ItemListener() {
+ @Override
public void itemStateChanged(ItemEvent evt) {
boolean isSelected = ((JCheckBox) evt.getSource()).isSelected();
boolean wasSelected = f.isEnabled(m);
- if (isSelected == wasSelected)
+ if (isSelected == wasSelected) {
return;
+ }
f.setEnabled(m, isSelected);
updateFilters(isSelected);
@@ -734,12 +778,13 @@ public class PreferencesFrame extends FBDialog {
this.url = url;
}
+ @Override
public void actionPerformed(ActionEvent e) {
int result = JOptionPane.showOptionDialog(PreferencesFrame.this,
"Are you sure you want to uninstall " + plugin.getShortDescription() + "?" +
"\n\nNo files will be deleted from your computer.", "",
- JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null,
- new Object[]{"Uninstall", "Cancel"}, "Cancel");
+ JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null,
+ new Object[]{"Uninstall", "Cancel"}, "Cancel");
if (result == 0) {
if (!GUISaveState.getInstance().removeCustomPlugin(url)) {
if ("file".equals(url.getProtocol())) {
@@ -757,7 +802,7 @@ public class PreferencesFrame extends FBDialog {
"The plugin could not be uninstalled automatically.\n\n" +
"You can try to delete this plugin manually: \n"
+ path + "\n\n(This path has been copied to your clipboard)",
- "Error", JOptionPane.ERROR_MESSAGE);
+ "Error", JOptionPane.ERROR_MESSAGE);
} else {
JOptionPane.showMessageDialog(PreferencesFrame.this,
"This plugin is not actually in the list of plugins...\n" +
@@ -765,7 +810,7 @@ public class PreferencesFrame extends FBDialog {
+ url.toExternalForm()
+ "\n\nPlugin URL's:\n" +
GUISaveState.getInstance().getCustomPlugins(),
- "Error", JOptionPane.ERROR_MESSAGE);
+ "Error", JOptionPane.ERROR_MESSAGE);
}
} else {
JOptionPane.showMessageDialog(PreferencesFrame.this,
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/ProjectSettings.java b/src/gui/edu/umd/cs/findbugs/gui2/ProjectSettings.java
index 5afde56..c7b6d26 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/ProjectSettings.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/ProjectSettings.java
@@ -55,20 +55,21 @@ public class ProjectSettings implements Serializable {
}
public static synchronized ProjectSettings getInstance() {
- if (instance == null)
+ if (instance == null) {
instance = new ProjectSettings();
+ }
return instance;
}
/**
* The list of all defined filters
*/
- private ArrayList<FilterMatcher> filters;
+ private final ArrayList<FilterMatcher> filters;
/**
* The CompoundMatcher enveloping all enabled matchers.
*/
- private CompoundMatcher allMatchers;
+ private final CompoundMatcher allMatchers;
/**
* Max number of previous comments stored.
@@ -81,12 +82,14 @@ public class ProjectSettings implements Serializable {
PreferencesFrame.getInstance().updateFilterPanel();
} catch (ClassNotFoundException e) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.err.println("Error in deserializing Settings:");
+ }
Debug.println(e);
} catch (IOException e) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.err.println("IO error in deserializing Settings:");
+ }
Debug.println(e);
instance = newInstance();
} finally {
@@ -102,8 +105,9 @@ public class ProjectSettings implements Serializable {
try {
new ObjectOutputStream(out).writeObject(this);
} catch (IOException e) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.err.println("Error serializing Settings:");
+ }
Debug.println(e);
} finally {
try {
@@ -118,9 +122,9 @@ public class ProjectSettings implements Serializable {
public void addFilter(FilterMatcher filter) {
filters.add(filter);
allMatchers.add(filter);
- if (!(filter instanceof StackedFilterMatcher))
+ if (!(filter instanceof StackedFilterMatcher)) {
FilterActivity.notifyListeners(FilterListener.Action.FILTERING, null);
- else {
+ } else {
StackedFilterMatcher theSame = (StackedFilterMatcher) filter;
FilterMatcher[] filtersInStack = theSame.getFilters();
ArrayList<Sortables> order = MainFrame.getInstance().getSorter().getOrder();
@@ -143,8 +147,9 @@ public class ProjectSettings implements Serializable {
ArrayList<String> finalPath = new ArrayList<String>();
for (int x = 0; x < almostPath.size(); x++) {
Sortables s = almostPathSortables.get(x);
- if (MainFrame.getInstance().getSorter().getOrderBeforeDivider().contains(s))
+ if (MainFrame.getInstance().getSorter().getOrderBeforeDivider().contains(s)) {
finalPath.add(almostPath.get(x));
+ }
}
BugTreeModel model = (MainFrame.getInstance().getBugTreeModel());
try {
@@ -163,7 +168,7 @@ public class ProjectSettings implements Serializable {
}
public void addFilters(FilterMatcher[] newFilters) {
- for (FilterMatcher i : newFilters)
+ for (FilterMatcher i : newFilters) {
if (!filters.contains(i)) {
filters.add(i);
allMatchers.add(i);
@@ -173,6 +178,7 @@ public class ProjectSettings implements Serializable {
// FIXME Do I need to do this for allMatchers too? Or are the
// filters all the same, with both just holding references?
}
+ }
FilterActivity.notifyListeners(FilterListener.Action.FILTERING, null);
PreferencesFrame.getInstance().updateFilterPanel();
MainFrame.getInstance().updateStatusBar();
@@ -199,7 +205,7 @@ public class ProjectSettings implements Serializable {
/**
* Sets the maximum number of previous comments stored.
- *
+ *
* @param num
*/
public void setMaxSizeOfPreviousComments(int num) {
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/PropertiesDialog.java b/src/gui/edu/umd/cs/findbugs/gui2/PropertiesDialog.java
index 1e40cfe..6dde5f7 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/PropertiesDialog.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/PropertiesDialog.java
@@ -37,19 +37,20 @@ import javax.swing.WindowConstants;
* This is the properties dialog of the GUI. It allows the user to set the size
* of the tabs and font size. If the user changes the font size they will be
* told to restart the computer before the new size takes affect.
- *
+ *
* @author Kristin Stephens
*/
public class PropertiesDialog extends FBDialog {
private static PropertiesDialog instance;
- private JTextField tabTextField;
+ private final JTextField tabTextField;
- private JTextField fontTextField;
+ private final JTextField fontTextField;
public static PropertiesDialog getInstance() {
- if (instance == null)
+ if (instance == null) {
instance = new PropertiesDialog();
+ }
return instance;
}
@@ -69,15 +70,16 @@ public class PropertiesDialog extends FBDialog {
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new AbstractAction("Apply") {
+ @Override
public void actionPerformed(ActionEvent evt) {
if (Integer.decode(tabTextField.getText()).intValue() != GUISaveState.getInstance().getTabSize()) {
GUISaveState.getInstance().setTabSize(Integer.decode(tabTextField.getText()).intValue());
MainFrame.getInstance().getSourceCodeDisplayer().clearCache();
MainFrame.getInstance().syncBugInformation(); // This causes
- // the GUI to
- // redisplay
- // the current
- // code
+ // the GUI to
+ // redisplay
+ // the current
+ // code
}
if (Float.parseFloat(fontTextField.getText()) != GUISaveState.getInstance().getFontSize()) {
@@ -90,6 +92,7 @@ public class PropertiesDialog extends FBDialog {
}));
bottomPanel.add(new JButton(new AbstractAction("Reset") {
+ @Override
public void actionPerformed(ActionEvent evt) {
tabTextField.setText(Integer.toString(GUISaveState.getInstance().getTabSize()));
fontTextField.setText(Float.toString(GUISaveState.getInstance().getFontSize()));
@@ -105,8 +108,9 @@ public class PropertiesDialog extends FBDialog {
addWindowListener(new WindowAdapter() {
@Override
public void windowDeactivated(WindowEvent e) {
- if (Integer.decode(tabTextField.getText()).intValue() != GUISaveState.getInstance().getTabSize())
+ if (Integer.decode(tabTextField.getText()).intValue() != GUISaveState.getInstance().getTabSize()) {
tabTextField.setText(Integer.toString(GUISaveState.getInstance().getTabSize()));
+ }
if (Float.parseFloat(fontTextField.getText()) != GUISaveState.getInstance().getFontSize()) {
fontTextField.setText(Float.toString(GUISaveState.getInstance().getFontSize()));
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/RecentMenu.java b/src/gui/edu/umd/cs/findbugs/gui2/RecentMenu.java
index af8b718..d6be279 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/RecentMenu.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/RecentMenu.java
@@ -52,7 +52,7 @@ public class RecentMenu {
}
LimitedArrayList<File> recentFiles;// Originally called recentProjects
- // before merge two lists into one.
+ // before merge two lists into one.
JMenu recentMenu;
@@ -72,8 +72,9 @@ public class RecentMenu {
for (File f : recentFiles) {
Debug.println(f);
if (!f.exists()) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.err.println("a recent project was not found, removing it from menu");
+ }
continue;
}
@@ -84,12 +85,13 @@ public class RecentMenu {
/**
* Adds a file to the list of recent files used.
- *
+ *
* @param f
*/
public void addRecentFile(final File f) {
- if (f != null)
+ if (f != null) {
recentFiles.add(f);
+ }
makeRecentMenu();
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/SaveType.java b/src/gui/edu/umd/cs/findbugs/gui2/SaveType.java
index 1c4c5de..2af446a 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/SaveType.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/SaveType.java
@@ -31,7 +31,7 @@ enum SaveType {
return FindBugsAnalysisFileFilter.INSTANCE;
case HTML_OUTPUT:
return FindBugsHtmlFileFilter.INSTANCE;
- case FBP_FILE:
+ case FBP_FILE:
return FindBugsFBPFileFilter.INSTANCE;
case FBA_FILE:
return FindBugsFBAFileFilter.INSTANCE;
@@ -42,8 +42,9 @@ enum SaveType {
public boolean isValid(File f) {
- if (f.isDirectory())
+ if (f.isDirectory()) {
return false;
+ }
FindBugsFileFilter filter = getFilter();
return filter.accept(f);
}
@@ -67,18 +68,24 @@ enum SaveType {
public static SaveType forFile(File f) {
String extension = Util.getFileExtension(f);
- if (extension.equals("html") || extension.equals("htm"))
+ if ("html".equals(extension) || "htm".equals(extension)) {
return HTML_OUTPUT;
- if (extension.equals("fba"))
+ }
+ if ("fba".equals(extension)) {
return FBA_FILE;
- if (extension.equals("fbp"))
+ }
+ if ("fbp".equals(extension)) {
return FBP_FILE;
- if (extension.equals("xml"))
+ }
+ if ("xml".equals(extension)) {
return XML_ANALYSIS;
- if (extension.equals("html"))
+ }
+ if ("html".equals(extension)) {
return XML_ANALYSIS;
- if (f.getName().toLowerCase().endsWith("xml.gz"))
+ }
+ if (f.getName().toLowerCase().endsWith("xml.gz")) {
return XML_ANALYSIS;
+ }
return NOT_KNOWN;
}
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/SortableStringComparator.java b/src/gui/edu/umd/cs/findbugs/gui2/SortableStringComparator.java
index 5268447..874c108 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/SortableStringComparator.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/SortableStringComparator.java
@@ -32,6 +32,7 @@ public class SortableStringComparator implements Comparator<String> {
mySortable = theSortable;
}
+ @Override
public int compare(String one, String two) {
return mySortable.compare(one, two);
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/Sortables.java b/src/gui/edu/umd/cs/findbugs/gui2/Sortables.java
index 782011d..0e2f8d6 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/Sortables.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/Sortables.java
@@ -44,7 +44,7 @@ import edu.umd.cs.findbugs.util.ClassName;
* in BugInstances This is the preferred way for getting the information out of
* a BugInstance and formatting it for display It also has the comparators for
* the different types of data
- *
+ *
* @author Reuven
*/
@@ -96,14 +96,16 @@ public enum Sortables implements Comparator<String> {
public String formatValue(String value) {
int seqNum = Integer.parseInt(value);
BugCollection bugCollection = MainFrame.getInstance().getBugCollection();
- if (bugCollection == null)
+ if (bugCollection == null) {
return "--";
+ }
AppVersion appVersion = bugCollection.getAppVersionFromSequenceNumber(seqNum);
if (appVersion != null) {
String timestamp = new Timestamp(appVersion.getTimestamp()).toString();
return appVersion.getReleaseName() + " (" + timestamp.substring(0, timestamp.indexOf(' ')) + ")";
- } else
+ } else {
return "#" + seqNum;
+ }
}
@Override
@@ -133,44 +135,53 @@ public enum Sortables implements Comparator<String> {
@Override
public String formatValue(String value) {
// System.out.println("Formatting last version value");
- if (value.equals("-1"))
+ if ("-1".equals(value)) {
return "";
+ }
int seqNum = Integer.parseInt(value);
BugCollection bugCollection = MainFrame.getInstance().getBugCollection();
- if (bugCollection == null)
+ if (bugCollection == null) {
return "--";
+ }
AppVersion appVersion = bugCollection.getAppVersionFromSequenceNumber(seqNum);
if (appVersion != null) {
String timestamp = new Timestamp(appVersion.getTimestamp()).toString();
return appVersion.getReleaseName() + " (" + timestamp.substring(0, timestamp.indexOf(' ')) + ")";
+ } else {
+ return "#" + seqNum;
}
- else return "#" + seqNum;
}
@Override
public int compare(String one, String two) {
- if (one.equals(two))
+ if (one.equals(two)) {
return 0;
+ }
// Numerical (except that -1 is last)
int first = Integer.parseInt(one);
int second = Integer.parseInt(two);
- if (first == second)
+ if (first == second) {
return 0;
- if (first < 0)
+ }
+ if (first < 0) {
return 1;
- if (second < 0)
+ }
+ if (second < 0) {
return -1;
- if (first < second)
+ }
+ if (first < second) {
return -1;
+ }
return 1;
}
@Override
public boolean isAvailable(MainFrame mainframe) {
BugCollection bugCollection = mainframe.getBugCollection();
- if (bugCollection == null)
+ if (bugCollection == null) {
return true;
+ }
return bugCollection.getCurrentAppVersion().getSequenceNumber() > 0;
}
@@ -185,26 +196,30 @@ public enum Sortables implements Comparator<String> {
@Override
public String formatValue(String value) {
- if (value.equals(String.valueOf(Priorities.HIGH_PRIORITY)))
+ if (value.equals(String.valueOf(Priorities.HIGH_PRIORITY))) {
return edu.umd.cs.findbugs.L10N.getLocalString("sort.priority_high", "High");
- if (value.equals(String.valueOf(Priorities.NORMAL_PRIORITY)))
+ }
+ if (value.equals(String.valueOf(Priorities.NORMAL_PRIORITY))) {
return edu.umd.cs.findbugs.L10N.getLocalString("sort.priority_normal", "Normal");
- if (value.equals(String.valueOf(Priorities.LOW_PRIORITY)))
+ }
+ if (value.equals(String.valueOf(Priorities.LOW_PRIORITY))) {
return edu.umd.cs.findbugs.L10N.getLocalString("sort.priority_low", "Low");
- if (value.equals(String.valueOf(Priorities.EXP_PRIORITY)))
+ }
+ if (value.equals(String.valueOf(Priorities.EXP_PRIORITY))) {
return edu.umd.cs.findbugs.L10N.getLocalString("sort.priority_experimental", "Experimental");
+ }
return edu.umd.cs.findbugs.L10N.getLocalString("sort.priority_ignore", "Ignore"); // This
- // probably
- // shouldn't
- // ever
- // happen,
- // but
- // what
- // the
- // hell,
- // let's
- // be
- // complete
+ // probably
+ // shouldn't
+ // ever
+ // happen,
+ // but
+ // what
+ // the
+ // hell,
+ // let's
+ // be
+ // complete
}
@@ -226,12 +241,13 @@ public enum Sortables implements Comparator<String> {
// compare the numbers after the dollar signs.
try {
if (one.contains("$") && two.contains("$")
- && one.substring(0, one.lastIndexOf("$")).equals(two.substring(0, two.lastIndexOf("$"))))
- return Integer.valueOf(one.substring(one.lastIndexOf("$"))).compareTo(
- Integer.valueOf(two.substring(two.lastIndexOf("$"))));
+ && one.substring(0, one.lastIndexOf('$')).equals(two.substring(0, two.lastIndexOf('$')))) {
+ return Integer.valueOf(one.substring(one.lastIndexOf('$'))).compareTo(
+ Integer.valueOf(two.substring(two.lastIndexOf('$'))));
+ }
} catch (NumberFormatException e) {
} // Somebody's playing silly buggers with dollar signs, just do it
- // lexicographically
+ // lexicographically
// Otherwise, lexicographicalify it
return one.compareTo(two);
@@ -245,8 +261,9 @@ public enum Sortables implements Comparator<String> {
@Override
public String formatValue(String value) {
- if (value.equals(""))
+ if ("".equals(value)) {
return "(Default)";
+ }
return value;
}
},
@@ -255,8 +272,9 @@ public enum Sortables implements Comparator<String> {
public String getFrom(BugInstance bug) {
int count = GUISaveState.getInstance().getPackagePrefixSegments();
- if (count < 1)
+ if (count < 1) {
count = 1;
+ }
String packageName = bug.getPrimarySourceLineAnnotation().getPackageName();
return ClassName.extractPackagePrefix(packageName, count);
}
@@ -284,12 +302,15 @@ public enum Sortables implements Comparator<String> {
String catOne = one;
String catTwo = two;
int compare = catOne.compareTo(catTwo);
- if (compare == 0)
+ if (compare == 0) {
return 0;
- if (catOne.equals("CORRECTNESS"))
+ }
+ if ("CORRECTNESS".equals(catOne)) {
return -1;
- if (catTwo.equals("CORRECTNESS"))
+ }
+ if ("CORRECTNESS".equals(catTwo)) {
return 1;
+ }
return compare;
}
@@ -303,7 +324,7 @@ public enum Sortables implements Comparator<String> {
/**
* value is the key of the designations.
- *
+ *
* @param value
* @return
*/
@@ -314,9 +335,9 @@ public enum Sortables implements Comparator<String> {
@Override
public String[] getAllSorted() {// FIXME I think we always want user to
- // see all possible designations, not
- // just the ones he has set in his
- // project, Agreement? -Dan
+ // see all possible designations, not
+ // just the ones he has set in his
+ // project, Agreement? -Dan
List<String> sortedDesignations = I18N.instance().getUserDesignationKeys(true);
return sortedDesignations.toArray(new String[sortedDesignations.size()]);
}
@@ -365,8 +386,9 @@ public enum Sortables implements Comparator<String> {
@Override
public boolean isAvailable(MainFrame mf) {
BugCollection bugCollection = mf.getBugCollection();
- if (bugCollection == null || bugCollection.getCloud() == null)
+ if (bugCollection == null) {
return false;
+ }
return bugCollection.getCloud().getMode() == Mode.COMMUNAL;
}
@@ -376,8 +398,9 @@ public enum Sortables implements Comparator<String> {
String[] values;
{
values = new String[40];
- for (int i = 0; i < values.length; i++)
+ for (int i = 0; i < values.length; i++) {
values[i] = String.format("%2d", i);
+ }
}
@Override
@@ -403,8 +426,9 @@ public enum Sortables implements Comparator<String> {
BugFilingStatus status = cloud.getBugLinkStatus(bug);
if (status == BugFilingStatus.VIEW_BUG) {
String bugStatus = cloud.getBugStatus(bug);
- if (bugStatus != null)
+ if (bugStatus != null) {
return bugStatus;
+ }
}
return CONSENSUS.getFrom(bug);
@@ -418,8 +442,9 @@ public enum Sortables implements Comparator<String> {
@Override
public boolean isAvailable(MainFrame mf) {
BugCollection bugCollection = mf.getBugCollection();
- if (bugCollection == null || bugCollection.getCloud() == null)
+ if (bugCollection == null) {
return false;
+ }
boolean a = bugCollection.getCloud().supportsBugLinks() && bugCollection.getCloud().getMode() == Mode.COMMUNAL;
return a;
@@ -432,8 +457,9 @@ public enum Sortables implements Comparator<String> {
public String getFrom(BugInstance bug) {
ProjectPackagePrefixes p = MainFrame.getInstance().getProjectPackagePrefixes();
Collection<String> projects = p.getProjects(bug.getPrimaryClass().getClassName());
- if (projects.size() == 0)
+ if (projects.size() == 0) {
return "unclassified";
+ }
String result = projects.toString();
return result.substring(1, result.length() - 1);
@@ -473,6 +499,7 @@ public enum Sortables implements Comparator<String> {
Sortables(String prettyName) {
this.prettyName = prettyName;
this.bugLeafNodeComparator = new Comparator<BugLeafNode>() {
+ @Override
public int compare(BugLeafNode one, BugLeafNode two) {
return Sortables.this.compare(Sortables.this.getFrom(one.getBug()), Sortables.this.getFrom(two.getBug()));
}
@@ -498,6 +525,7 @@ public enum Sortables implements Comparator<String> {
return value;
}
+ @Override
public int compare(String one, String two) {
// Lexicographical by default
return one.compareTo(two);
@@ -513,7 +541,7 @@ public enum Sortables implements Comparator<String> {
return values;
}
- private SortableStringComparator comparator = new SortableStringComparator(this);
+ private final SortableStringComparator comparator = new SortableStringComparator(this);
public SortableStringComparator getComparator() {
return comparator;
@@ -531,8 +559,9 @@ public enum Sortables implements Comparator<String> {
public static Sortables getSortableByPrettyName(String name) {
for (Sortables s : values()) {
- if (s.prettyName.equals(name))
+ if (s.prettyName.equals(name)) {
return s;
+ }
}
return null;
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/SorterDialog.java b/src/gui/edu/umd/cs/findbugs/gui2/SorterDialog.java
index 84c5dff..c0c9e07 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/SorterDialog.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/SorterDialog.java
@@ -43,19 +43,19 @@ import javax.swing.table.JTableHeader;
/**
* This is the window that pops up when the user double clicks on the sorting
* table Its also available from the menu if they remove all Sortables.
- *
+ *
* The user can choose what Sortables he wants to sort by, sort them into the
* order he wants to see and then click apply to move his choices onto the
* sorting table
- *
+ *
* @author Dan
- *
+ *
*/
public class SorterDialog extends FBDialog {
private JTableHeader preview;
- private ArrayList<SortableCheckBox> checkBoxSortList = new ArrayList<SortableCheckBox>();
+ private final ArrayList<SortableCheckBox> checkBoxSortList = new ArrayList<SortableCheckBox>();
JButton sortApply;
@@ -89,6 +89,7 @@ public class SorterDialog extends FBDialog {
super(s == Sortables.DIVIDER ? edu.umd.cs.findbugs.L10N.getLocalString("sort.divider", "[divider]") : s.toString());
this.sortable = s;
addChangeListener(new ChangeListener() {
+ @Override
public void stateChanged(ChangeEvent e) {
((SorterTableColumnModel) preview.getColumnModel()).setVisible(sortable, isSelected());
}
@@ -100,8 +101,6 @@ public class SorterDialog extends FBDialog {
/**
* Creates JPanel with checkboxes of different things to sort by. List is:
* priority, class, package, category, bugcode, status, and type.
- *
- * @return
*/
private JPanel createSorterPane() {
JPanel insidePanel = new JPanel();
@@ -110,10 +109,11 @@ public class SorterDialog extends FBDialog {
Sortables[] sortables = MainFrame.getInstance().getAvailableSortables();
preview.setColumnModel(new SorterTableColumnModel(sortables));
- for (Sortables s : sortables)
+ for (Sortables s : sortables) {
if (s != Sortables.DIVIDER) {
checkBoxSortList.add(new SortableCheckBox(s));
}
+ }
setSorterCheckBoxes();
@@ -122,7 +122,7 @@ public class SorterDialog extends FBDialog {
gbc.gridx = 1;
gbc.insets = new Insets(2,5,2,5);
insidePanel.add(new JLabel("<html><h2>1. Choose bug properties"), gbc);
- insidePanel.add(new CheckBoxList(checkBoxSortList.toArray(new JCheckBox[checkBoxSortList.size()])), gbc);
+ insidePanel.add(new CheckBoxList<>(checkBoxSortList.toArray(new JCheckBox[checkBoxSortList.size()])), gbc);
JTable t = new JTable(new DefaultTableModel(0, sortables.length));
t.setTableHeader(preview);
@@ -132,6 +132,7 @@ public class SorterDialog extends FBDialog {
sortApply = new JButton(edu.umd.cs.findbugs.L10N.getLocalString("dlg.apply_btn", "Apply"));
sortApply.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
MainFrame.getInstance().getSorter().createFrom((SorterTableColumnModel) preview.getColumnModel());
((BugTreeModel) MainFrame.getInstance().getTree().getModel()).checkSorter();
@@ -167,8 +168,9 @@ public class SorterDialog extends FBDialog {
SorterTableColumnModel sorter = MainFrame.getInstance().getSorter();
- for (SortableCheckBox c : checkBoxSortList)
+ for (SortableCheckBox c : checkBoxSortList) {
c.setSelected(sorter.isShown(c.sortable));
+ }
}
void freeze() {
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/SorterTableColumnModel.java b/src/gui/edu/umd/cs/findbugs/gui2/SorterTableColumnModel.java
index 736e94b..be023cf 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/SorterTableColumnModel.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/SorterTableColumnModel.java
@@ -46,43 +46,48 @@ import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.tree.TreeModel;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
/**
* Handles the sorting order and informs the treeModel when changes are
* necessary
- *
+ *
* @author Dan
- *
+ *
*/
public class SorterTableColumnModel implements TableColumnModel {
private ArrayList<Sortables> order = new ArrayList<Sortables>();
- private Set<Sortables> shown = new HashSet<Sortables>();
+ private final Set<Sortables> shown = new HashSet<Sortables>();
- private ArrayList<TableColumn> columnList = new ArrayList<TableColumn>();
+ private final ArrayList<TableColumn> columnList = new ArrayList<TableColumn>();
private DefaultListSelectionModel dlsm;
- private ArrayList<TableColumnModelListener> watchers = new ArrayList<TableColumnModelListener>();
+ private final ArrayList<TableColumnModelListener> watchers = new ArrayList<TableColumnModelListener>();
private boolean frozen = false;
public boolean isShown(Sortables s) {
return shown.contains(s);
}
-
+
@Override
public String toString() {
return order.toString();
}
- static boolean shownError = false;
+ static boolean shownError;
+ @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
public void check() {
- if (order.size() == shown.size() && order.containsAll(shown))
+ if (order.size() == shown.size() && order.containsAll(shown)) {
return;
- if (shownError)
+ }
+ if (shownError) {
return;
+ }
shownError = true;
MainFrame.getInstance().error("Incompatible order and shown for SorterTable: " + order + " vs. " + shown);
shown.clear();
@@ -93,8 +98,9 @@ public class SorterTableColumnModel implements TableColumnModel {
MainFrame mainFrame = MainFrame.getInstance();
int x = 0;
for (Sortables c : columnHeaders) {
- if (!c.isAvailable(mainFrame))
+ if (!c.isAvailable(mainFrame)) {
continue;
+ }
shown.add(c);
TableColumn tc = makeTableColumn(x, c);
@@ -107,11 +113,6 @@ public class SorterTableColumnModel implements TableColumnModel {
check();
}
- /**
- * @param x
- * @param c
- * @return
- */
private TableColumn makeTableColumn(int x, Sortables c) {
TableColumn tc = new TableColumn(x);
FBTableCellRenderer temp = new FBTableCellRenderer();
@@ -124,12 +125,14 @@ public class SorterTableColumnModel implements TableColumnModel {
}
public void createFrom(SorterTableColumnModel other) {
- if (this.getOrder().equals(other.getOrder()))
+ if (this.getOrder().equals(other.getOrder())) {
return;
+ }
columnList.clear();
for (int x = 0; x < order.size(); x++) {
- for (TableColumnModelListener l : watchers)
+ for (TableColumnModelListener l : watchers) {
l.columnRemoved(new TableColumnModelEvent(this, x, x));
+ }
}
// First, empty showOrder
@@ -137,14 +140,16 @@ public class SorterTableColumnModel implements TableColumnModel {
MainFrame mainFrame = MainFrame.getInstance();
int x = 0;
for (Sortables c : other.order) {
- if (!c.isAvailable(mainFrame))
+ if (!c.isAvailable(mainFrame)) {
continue;
+ }
shown.add(c);
TableColumn tc = makeTableColumn(x, c);
columnList.add(tc);
- for (TableColumnModelListener l : watchers)
+ for (TableColumnModelListener l : watchers) {
l.columnAdded(new TableColumnModelEvent(this, x, x));
+ }
x++;
}
dlsm = new DefaultListSelectionModel();
@@ -160,8 +165,9 @@ public class SorterTableColumnModel implements TableColumnModel {
static class FBTableCellRenderer implements TableCellRenderer {
- private TableCellRenderer defaultRenderer = new JTableHeader().getDefaultRenderer();
+ private final TableCellRenderer defaultRenderer = new JTableHeader().getDefaultRenderer();
+ @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
@@ -188,10 +194,12 @@ public class SorterTableColumnModel implements TableColumnModel {
}
}
+ @Override
public void addColumn(TableColumn arg0) {
throw new UnsupportedOperationException("Can't change sorter table columns using addColumn");
}
+ @Override
public void removeColumn(TableColumn arg0) {
throw new UnsupportedOperationException("Can't change sorter table columns using removeColumn");
}
@@ -213,7 +221,7 @@ public class SorterTableColumnModel implements TableColumnModel {
for (TableColumnModelListener l : watchers) {
l.columnAdded(new TableColumnModelEvent(this, columnList.size() - 1, columnList.size() - 1));
}
- } else if (!on) {
+ } else {
shown.remove(s);
for (int x = 0; x < columnList.size(); x++) {
columnList.get(x).setModelIndex(x);
@@ -228,19 +236,21 @@ public class SorterTableColumnModel implements TableColumnModel {
}
orderUpdate();
- for (TableColumnModelListener l : watchers)
+ for (TableColumnModelListener l : watchers) {
l.columnRemoved(new TableColumnModelEvent(this, counter, counter));
-
+ }
}
}
}
}
+ @Override
public void moveColumn(int fromIndex, int toIndex) {
- if (!MainFrame.getInstance().canNavigateAway())
+ if (!MainFrame.getInstance().canNavigateAway()) {
return;
+ }
MainFrame.getInstance().updateDesignationDisplay();
TableColumn from = columnList.get(fromIndex);
TableColumn to = columnList.get(toIndex);
@@ -258,49 +268,60 @@ public class SorterTableColumnModel implements TableColumnModel {
}
}
+ @Override
public void setColumnMargin(int arg0) {
throw new UnsupportedOperationException("NoBah");
}
+ @Override
public int getColumnCount() {
return columnList.size();
}
+ @Override
public Enumeration<TableColumn> getColumns() {
return Collections.<TableColumn> enumeration(columnList);
}
+ @Override
public int getColumnIndex(Object columnIdentifier) {
- if (columnIdentifier == null)
+ if (columnIdentifier == null) {
throw new IllegalArgumentException("Dont send null to getColumnIndex, null shouldn't be in the sorting table.");
+ }
for (int x = 0; x < columnList.size(); x++) {
- if (columnList.get(x).getIdentifier().equals(columnIdentifier))
+ if (columnList.get(x).getIdentifier().equals(columnIdentifier)) {
return x;
+ }
}
throw new IllegalArgumentException();
}
+ @Override
public TableColumn getColumn(int x) {
return columnList.get(x);
}
+ @Override
public int getColumnMargin() {
return 0;
}
+ @Override
public int getColumnIndexAtX(int XPosition) {
for (TableColumn tc : columnList) {
XPosition -= tc.getWidth();
- if (XPosition < 0)
+ if (XPosition < 0) {
return tc.getModelIndex();
+ }
}
return -1;
}
+ @Override
public int getTotalColumnWidth() {
int total = 0;
for (TableColumn tc : columnList) {
@@ -309,40 +330,50 @@ public class SorterTableColumnModel implements TableColumnModel {
return total;
}
+ @Override
public void setColumnSelectionAllowed(boolean arg0) {
throw new UnsupportedOperationException("BAH");// BAH
}
+ @Override
public boolean getColumnSelectionAllowed() {
return true;
}
+ @Override
public int[] getSelectedColumns() {
int index = dlsm.getMinSelectionIndex();
- if (index == -1)
+ if (index == -1) {
return new int[] {};
+ }
return new int[] { index };
}
+ @Override
public int getSelectedColumnCount() {
- if (dlsm.getMinSelectionIndex() == -1)
+ if (dlsm.getMinSelectionIndex() == -1) {
return 0;
+ }
return 1;
}
+ @Override
public void setSelectionModel(ListSelectionModel arg0) {
throw new UnsupportedOperationException("No... NO NO NO NO");
}
+ @Override
public ListSelectionModel getSelectionModel() {
return dlsm;
}
+ @Override
public void addColumnModelListener(TableColumnModelListener listener) {
watchers.add(listener);
}
+ @Override
public void removeColumnModelListener(TableColumnModelListener listener) {
watchers.remove(listener);
}
@@ -356,15 +387,17 @@ public class SorterTableColumnModel implements TableColumnModel {
}
List<Sortables> getOrderBeforeDivider() {
- if (!order.contains(Sortables.DIVIDER))
+ if (!order.contains(Sortables.DIVIDER)) {
return order;
+ }
return order.subList(0, order.indexOf(Sortables.DIVIDER));
}
List<Sortables> getOrderAfterDivider() {
- if (!order.contains(Sortables.DIVIDER) || order.indexOf(Sortables.DIVIDER) == order.size() - 1)
+ if (!order.contains(Sortables.DIVIDER) || order.indexOf(Sortables.DIVIDER) == order.size() - 1) {
return new ArrayList<Sortables>();
+ }
return order.subList(order.indexOf(Sortables.DIVIDER) + 1, order.size());
}
@@ -373,8 +406,9 @@ public class SorterTableColumnModel implements TableColumnModel {
// order.clear();
if (!frozen) {
order = new ArrayList<Sortables>();
- for (TableColumn c : columnList)
+ for (TableColumn c : columnList) {
order.add((Sortables) c.getIdentifier());
+ }
}
check();
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/SourceCodeDisplay.java b/src/gui/edu/umd/cs/findbugs/gui2/SourceCodeDisplay.java
index 218eb8f..cda5e36 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/SourceCodeDisplay.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/SourceCodeDisplay.java
@@ -79,7 +79,7 @@ public final class SourceCodeDisplay implements Runnable {
}
final BlockingQueue<DisplayMe> queue = new LinkedBlockingQueue<DisplayMe>();
-
+
public void displaySource(BugInstance bug, SourceLineAnnotation source) {
queue.add(new DisplayMe(bug, source));
}
@@ -95,10 +95,12 @@ public final class SourceCodeDisplay implements Runnable {
String fullFileName = sourceFile.getFullFileName();
SoftReference<JavaSourceDocument> resultReference = map.get(fullFileName);
JavaSourceDocument result = null;
- if (resultReference != null)
+ if (resultReference != null) {
result = resultReference.get();
- if (result != null)
+ }
+ if (result != null) {
return result;
+ }
try {
InputStream in = sourceFile.getInputStream();
result = new JavaSourceDocument(source.getClassName(), SourceCharset.bufferedReader(in), sourceFile);
@@ -115,6 +117,7 @@ public final class SourceCodeDisplay implements Runnable {
}
}
+ @Override
public void run() {
while (true) {
DisplayMe display;
@@ -127,7 +130,7 @@ public final class SourceCodeDisplay implements Runnable {
}
BugInstance myBug = display.bug;
SourceLineAnnotation mySourceLine = display.source;
-
+
if (myBug == null || mySourceLine == null) {
frame.clearSourcePane();
continue;
@@ -143,12 +146,14 @@ public final class SourceCodeDisplay implements Runnable {
BugAnnotation annotation = i.next();
if (annotation instanceof SourceLineAnnotation) {
SourceLineAnnotation sourceAnnotation = (SourceLineAnnotation) annotation;
- if (sourceAnnotation == mySourceLine)
+ if (sourceAnnotation == mySourceLine) {
continue;
- if (sourceAnnotation.getDescription().equals(primaryKind))
+ }
+ if (sourceAnnotation.getDescription().equals(primaryKind)) {
highlight(src, sourceAnnotation, MAIN_HIGHLIGHT_MORE);
- else
+ } else {
highlight(src, sourceAnnotation, ALTERNATIVE_HIGHLIGHT);
+ }
}
}
highlight(src, mySourceLine, MAIN_HIGHLIGHT);
@@ -173,12 +178,13 @@ public final class SourceCodeDisplay implements Runnable {
this.myBug = myBug;
}
+ @Override
public void run() {
frame.getSourceCodeTextPane().setEditorKit(src.getEditorKit());
StyledDocument document = src.getDocument();
frame.getSourceCodeTextPane().setDocument(document);
String sourceFile = mySourceLine.getSourceFile();
- if (sourceFile == null || sourceFile.equals("<Unknown>")) {
+ if (sourceFile == null || "<Unknown>".equals(sourceFile)) {
sourceFile = mySourceLine.getSimpleClassName();
}
int startLine = mySourceLine.getStartLine();
@@ -197,15 +203,17 @@ public final class SourceCodeDisplay implements Runnable {
// show(frame.getSourceCodeTextPane(),
// document, sourceAnnotation);
int otherLine = sourceAnnotation.getStartLine();
- if (otherLine > originLine)
+ if (otherLine > originLine) {
otherLine = sourceAnnotation.getEndLine();
+ }
otherLines.add(otherLine);
}
}
}
-
- if (startLine >= 0 && endLine >= 0)
+
+ if (startLine >= 0 && endLine >= 0) {
frame.getSourceCodeTextPane().scrollLinesToVisible(startLine, endLine, otherLines);
+ }
}
}
@@ -216,15 +224,17 @@ public final class SourceCodeDisplay implements Runnable {
private void highlight(JavaSourceDocument src, SourceLineAnnotation sourceAnnotation, Color color) {
int startLine = sourceAnnotation.getStartLine();
- if (startLine == -1)
+ if (startLine == -1) {
return;
+ }
String sourceFile = sourceAnnotation.getSourcePath();
String sourceFile2 = src.getSourceFile().getFullFileName();
if (!java.io.File.separator.equals(String.valueOf(SourceLineAnnotation.CANONICAL_PACKAGE_SEPARATOR))) {
sourceFile2 = sourceFile2.replace(java.io.File.separatorChar, SourceLineAnnotation.CANONICAL_PACKAGE_SEPARATOR);
}
- if (!sourceFile2.endsWith(sourceFile))
+ if (!sourceFile2.endsWith(sourceFile)) {
return;
+ }
src.getHighlightInformation().setHighlight(startLine, sourceAnnotation.getEndLine(), color);
}
@@ -236,54 +246,67 @@ public final class SourceCodeDisplay implements Runnable {
}
private int search(JavaSourceDocument document, String target, int start, Boolean backwards) {
- if (document == null)
+ if (document == null) {
return -1;
+ }
String docContent = null;
try {
StyledDocument document2 = document.getDocument();
- if (document2 == null)
+ if (document2 == null) {
return -1;
+ }
docContent = document2.getText(0, document2.getLength());
} catch (BadLocationException ble) {
System.out.println("Bad location exception");
} catch (NullPointerException npe) {
return -1;
}
- if (docContent == null)
+ if (docContent == null) {
return -1;
+ }
int targetLen = target.length();
int sourceLen = docContent.length();
- if (targetLen > sourceLen)
+ if (targetLen > sourceLen) {
return -1;
- else if (backwards) {
- for (int i = start; i >= 0; i--)
- if (docContent.substring(i, i + targetLen).equals(target))
+ } else if (backwards) {
+ for (int i = start; i >= 0; i--) {
+ if (docContent.substring(i, i + targetLen).equals(target)) {
return i;
- for (int i = (sourceLen - targetLen); i > start; i--)
- if (docContent.substring(i, i + targetLen).equals(target))
+ }
+ }
+ for (int i = (sourceLen - targetLen); i > start; i--) {
+ if (docContent.substring(i, i + targetLen).equals(target)) {
return i;
+ }
+ }
return -1;
} else {
- for (int i = start; i <= (sourceLen - targetLen); i++)
- if (docContent.substring(i, i + targetLen).equals(target))
+ for (int i = start; i <= (sourceLen - targetLen); i++) {
+ if (docContent.substring(i, i + targetLen).equals(target)) {
return i;
- for (int i = 0; i < start; i++)
- if (docContent.substring(i, i + targetLen).equals(target))
+ }
+ }
+ for (int i = 0; i < start; i++) {
+ if (docContent.substring(i, i + targetLen).equals(target)) {
return i;
+ }
+ }
return -1;
}
}
private int charToLineNum(int charNum) {
- if (charNum == -1)
+ if (charNum == -1) {
return -1;
+ }
try {
for (int i = 1; true; i++) {
- if (frame.getSourceCodeTextPane().getLineOffset(i) > charNum)
+ if (frame.getSourceCodeTextPane().getLineOffset(i) > charNum) {
return i - 1;
- else if (frame.getSourceCodeTextPane().getLineOffset(i) == -1)
+ } else if (frame.getSourceCodeTextPane().getLineOffset(i) == -1) {
return -1;
+ }
}
} catch (BadLocationException ble) {
return -1;
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/SourceDirectoryWizard.java b/src/gui/edu/umd/cs/findbugs/gui2/SourceDirectoryWizard.java
index 1d6f460..00e925c 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/SourceDirectoryWizard.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/SourceDirectoryWizard.java
@@ -41,7 +41,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Wizard dialog to automatically find and configure source directories for a
* project.
- *
+ *
* @author David Hovemeyer
*/
public class SourceDirectoryWizard extends javax.swing.JDialog {
@@ -52,7 +52,7 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
/**
* Creates new form SourceDirectoryWizard
- *
+ *
* @param parentGUI
*/
public SourceDirectoryWizard(java.awt.Frame parent, boolean modal, Project project, NewProjectWizard parentGUI) {
@@ -73,14 +73,14 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
// desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
- foundModel = new DefaultListModel();
- progressModel = new DefaultListModel();
+ foundModel = new DefaultListModel<String>();
+ progressModel = new DefaultListModel<String>();
contentPanel = new javax.swing.JPanel();
secondPanel = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
jScrollPane2 = new javax.swing.JScrollPane();
- jList1 = new javax.swing.JList();
- jList2 = new javax.swing.JList();
+ jList1 = new javax.swing.JList<>();
+ jList2 = new javax.swing.JList<>();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
@@ -159,6 +159,7 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
firstPanel.add(browseButton);
browseButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent evt) {
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setMultiSelectionEnabled(true);
@@ -170,7 +171,7 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
for (File selectedFile : selectedFiles) {
sourceRootBox.setText(selectedFile.getAbsolutePath());
}
- nextButton.setEnabled(!sourceRootBox.getText().equals(""));
+ nextButton.setEnabled(!"".equals(sourceRootBox.getText()));
}
}
});
@@ -199,6 +200,7 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
previousButton.setText("<< Previous");
previousButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
previousButtonActionPerformed(evt);
}
@@ -208,9 +210,10 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
nextButton.setText("Next >>");
nextButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
nextButtonActionPerformed(evt);
-
+
}
});
getContentPane().add(nextButton);
@@ -218,6 +221,7 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
finshButton.setText("Finish");
finshButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
finshButtonActionPerformed(evt);
}
@@ -247,6 +251,7 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
@Override
public void run() {
IErrorLogger errorLogger = new IErrorLogger() {
+ @Override
public void reportMissingClass(ClassNotFoundException ex) {
String className = ClassNotFoundExceptionParser.getMissingClassName(ex);
if (className != null) {
@@ -256,18 +261,22 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
}
}
+ @Override
public void reportMissingClass(ClassDescriptor classDescriptor) {
logError("Missing class: " + classDescriptor.toDottedClassName());
}
+ @Override
public void logError(String message) {
System.err.println("Error: " + message);
}
+ @Override
public void logError(String message, Throwable e) {
logError(message + ": " + e.getMessage());
}
+ @Override
public void reportSkippedAnalysis(MethodDescriptor method) {
logError("Skipped analysis of method " + method.toString());
}
@@ -275,33 +284,42 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
DiscoverSourceDirectories.Progress progress = new DiscoverSourceDirectories.Progress() {
+ @Override
public void startRecursiveDirectorySearch() {
progressModel.addElement("Scanning directories...");
}
+ @Override
public void doneRecursiveDirectorySearch() {
}
+ @Override
public void startScanningArchives(int numArchivesToScan) {
progressModel.addElement("Scanning " + numArchivesToScan + " archives..");
}
+ @Override
public void doneScanningArchives() {
}
+ @Override
public void startScanningClasses(int numClassesToScan) {
progressModel.addElement("Scanning " + numClassesToScan + " classes...");
}
+ @Override
public void finishClass() {
}
+ @Override
public void doneScanningClasses() {
}
+ @Override
public void finishArchive() {
}
+ @Override
public void startArchive(String name) {
}
};
@@ -342,8 +360,9 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
if (parentGUI != null) {
parentGUI.setSourceDirecs(foundModel);
}
- if (discover != null && discover.isAlive())
+ if (discover != null && discover.isAlive()) {
discover.stop();
+ }
dispose();
}// GEN-LAST:event_finshButtonActionPerformed
@@ -353,6 +372,7 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
+ @Override
public void run() {
final SourceDirectoryWizard dialog = new SourceDirectoryWizard(new javax.swing.JFrame(), true, new Project(),
null);
@@ -363,15 +383,15 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
private JFileChooser chooser;
- private Project project;
+ private final Project project;
- private NewProjectWizard parentGUI;
+ private final NewProjectWizard parentGUI;
- private DefaultListModel foundModel;
+ private DefaultListModel<String> foundModel;
- private DefaultListModel progressModel;
+ private DefaultListModel<String> progressModel;
- private JList jList2;
+ private JList<String> jList2;
public Thread discover;
@@ -400,7 +420,7 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
private javax.swing.JLabel jLabel3;
- private javax.swing.JList jList1;
+ private javax.swing.JList<String> jList1;
private javax.swing.JScrollPane jScrollPane1;
@@ -428,7 +448,7 @@ public class SourceDirectoryWizard extends javax.swing.JDialog {
}
this.step = step;
previousButton.setEnabled(step != MIN_STEP);
- nextButton.setEnabled(step != MAX_STEP && !sourceRootBox.getText().equals(""));
+ nextButton.setEnabled(step != MAX_STEP && !"".equals(sourceRootBox.getText()));
CardLayout cards = (CardLayout) contentPanel.getLayout();
cards.show(contentPanel, "card" + step);
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/SplashFrame.java b/src/gui/edu/umd/cs/findbugs/gui2/SplashFrame.java
index bab7114..412fad7 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/SplashFrame.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/SplashFrame.java
@@ -87,8 +87,9 @@ public class SplashFrame extends JWindow {
@Override
public void setVisible(boolean b) {
super.setVisible(b);
- if (!b)
+ if (!b) {
animator.interrupt();
+ }
}
private static class Viewer extends JPanel {
@@ -110,7 +111,7 @@ public class SplashFrame extends JWindow {
int ypos = 0;
- int farRight;
+ // int farRight;
public Viewer(Image i1, Image i2, Image i1r, Image i2r) {
image = i1;
@@ -132,12 +133,14 @@ public class SplashFrame extends JWindow {
System.exit(1);
}
animator = new Thread(new Runnable() {
+ @Override
public void run() {
int deltaX = 1;
while (true) {
- if (Thread.currentThread().isInterrupted())
+ if (Thread.currentThread().isInterrupted()) {
return;
+ }
callCount++;
if (callCount == 10) {
@@ -173,19 +176,16 @@ public class SplashFrame extends JWindow {
animator.start();
}
- @Override
- public void setPreferredSize(Dimension d) {
- super.setPreferredSize(d);
- }
-
private Image imageToDraw() {
if (swap) {
- if (!reverse)
+ if (!reverse) {
return image;
+ }
return imageR;
} else {
- if (!reverse)
+ if (!reverse) {
return image2;
+ }
return image2R;
}
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/SplitLayout.java b/src/gui/edu/umd/cs/findbugs/gui2/SplitLayout.java
index 9a1a52e..827cc20 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/SplitLayout.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/SplitLayout.java
@@ -66,13 +66,15 @@ public class SplitLayout implements FindBugsLayoutManager {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.gui2.FindBugsLayoutManager#createWindowMenu()
*/
+ @Override
public JMenu createWindowMenu() {
return null;
}
+ @Override
public void resetCommentsInputPane() {
if (topLeftSPane != null) {
int position = topLeftSPane.getDividerLocation();
@@ -83,9 +85,10 @@ public class SplitLayout implements FindBugsLayoutManager {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.gui2.FindBugsLayoutManager#initialize()
*/
+ @Override
public void initialize() {
Font buttonFont = viewSource.getFont();
@@ -154,27 +157,30 @@ public class SplitLayout implements FindBugsLayoutManager {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.gui2.FindBugsLayoutManager#makeCommentsVisible()
*/
+ @Override
public void makeCommentsVisible() {
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.gui2.FindBugsLayoutManager#makeSourceVisible()
*/
+ @Override
public void makeSourceVisible() {
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.gui2.FindBugsLayoutManager#saveState()
*/
+ @Override
public void saveState() {
GUISaveState.getInstance().setSplitTreeComments(topLeftSPane.getDividerLocation());
GUISaveState.getInstance().setSplitTop(topSPane.getDividerLocation());
@@ -184,11 +190,12 @@ public class SplitLayout implements FindBugsLayoutManager {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.gui2.FindBugsLayoutManager#setSourceTitle(java.lang
* .String)
*/
+ @Override
public void setSourceTitle(String title) {
sourceTitle.setText(title);
@@ -196,10 +203,11 @@ public class SplitLayout implements FindBugsLayoutManager {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.gui2.FindBugsLayoutManager#getSourceTitleComponent()
*/
+ @Override
public JComponent getSourceViewComponent() {
return viewSource;
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/SpringUtilities.java b/src/gui/edu/umd/cs/findbugs/gui2/SpringUtilities.java
index 64e882a..bc1b687 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/SpringUtilities.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/SpringUtilities.java
@@ -10,9 +10,9 @@ import javax.swing.SpringLayout;
* A 1.4 file that provides utility methods for creating form- or grid-style
* layouts with SpringLayout. These utilities are used by several programs, such
* as SpringBox and SpringCompactGrid.
- *
+ *
* From the Swing tutorial.
- *
+ *
*/
public class SpringUtilities {
/**
@@ -32,7 +32,7 @@ public class SpringUtilities {
* <code>parent</code> in a grid. Each component is as big as the maximum
* preferred width and height of the components. The parent is made just big
* enough to fit them all.
- *
+ *
* @param rows
* number of rows
* @param cols
@@ -51,8 +51,9 @@ public class SpringUtilities {
try {
layout = (SpringLayout) parent.getLayout();
} catch (ClassCastException exc) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.err.println("The first argument to makeGrid must use SpringLayout.");
+ }
return;
}
@@ -125,7 +126,7 @@ public class SpringUtilities {
* the maximum preferred width of the components in that column; height is
* similarly determined for each row. The parent is made just big enough to
* fit them all.
- *
+ *
* @param rows
* number of rows
* @param cols
@@ -144,8 +145,9 @@ public class SpringUtilities {
try {
layout = (SpringLayout) parent.getLayout();
} catch (ClassCastException exc) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
System.err.println("The first argument to makeCompactGrid must use SpringLayout.");
+ }
return;
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/StackedFilterMatcher.java b/src/gui/edu/umd/cs/findbugs/gui2/StackedFilterMatcher.java
index ceafd58..c7dbe78 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/StackedFilterMatcher.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/StackedFilterMatcher.java
@@ -36,7 +36,7 @@ import edu.umd.cs.findbugs.gui2.BugTreeModel.BranchOperationException;
public class StackedFilterMatcher extends FilterMatcher {
private static final long serialVersionUID = 3958267780332359162L;
- private FilterMatcher[] filters;
+ private final FilterMatcher[] filters;
@Override
Sortables getFilterBy() {
@@ -65,17 +65,19 @@ public class StackedFilterMatcher extends FilterMatcher {
BugTreeModel.TreeModification whatToDo;
if (active != this.active) {
- if (active == false)
+ if (active == false) {
this.active = active;
+ }
StackedFilterMatcher theSame = this;
FilterMatcher[] filtersInStack = theSame.getFilters();
ArrayList<Sortables> order = MainFrame.getInstance().getSorter().getOrder();
int sizeToCheck = filtersInStack.length;
- if (order.contains(Sortables.DIVIDER))
+ if (order.contains(Sortables.DIVIDER)) {
if (order.indexOf(Sortables.DIVIDER) < filtersInStack.length) {
sizeToCheck++;
}
+ }
List<Sortables> sortablesToCheck = order.subList(0, Math.min(sizeToCheck, order.size()));
Debug.println("Size to check" + sizeToCheck + " checking list" + sortablesToCheck);
Debug.println("checking filters");
@@ -93,8 +95,9 @@ public class StackedFilterMatcher extends FilterMatcher {
ArrayList<String> finalPath = new ArrayList<String>();
for (int x = 0; x < almostPath.size(); x++) {
Sortables s = almostPathSortables.get(x);
- if (MainFrame.getInstance().getSorter().getOrderBeforeDivider().contains(s))
+ if (MainFrame.getInstance().getSorter().getOrderBeforeDivider().contains(s)) {
finalPath.add(almostPath.get(x));
+ }
}
try {
if (finalPath.size() == filtersInStack.length) {
@@ -107,25 +110,27 @@ public class StackedFilterMatcher extends FilterMatcher {
}
} else {
event = (MainFrame.getInstance().getBugTreeModel()).restructureBranch(finalPath, active);// if
- // active
- // is
- // true,
- // this
- // removes,
- // if
- // active
- // if
- // false,
- // it
- // inserts
- if (active)
+ // active
+ // is
+ // true,
+ // this
+ // removes,
+ // if
+ // active
+ // if
+ // false,
+ // it
+ // inserts
+ if (active) {
whatToDo = BugTreeModel.TreeModification.REMOVERESTRUCTURE;
- else
+ } else {
whatToDo = BugTreeModel.TreeModification.INSERTRESTRUCTURE;
+ }
}
- if (active == true)
+ if (active == true) {
this.active = active;
+ }
(MainFrame.getInstance().getBugTreeModel()).sendEvent(event, whatToDo);
} catch (BranchOperationException e) {
// Another filter already filters out the branch this filter
@@ -143,12 +148,15 @@ public class StackedFilterMatcher extends FilterMatcher {
@Override
public boolean match(BugInstance bugInstance) {
- if (!isActive())
+ if (!isActive()) {
return true;
+ }
- for (FilterMatcher i : filters)
- if (i.match(bugInstance))
+ for (FilterMatcher i : filters) {
+ if (i.match(bugInstance)) {
return true;
+ }
+ }
return false;
}
@@ -157,19 +165,23 @@ public class StackedFilterMatcher extends FilterMatcher {
public String toString() {
// return "StackedFilterMatcher: " + Arrays.toString(filters);
StringBuilder result = new StringBuilder();
- for (int i = 0; i < filters.length - 1; i++)
+ for (int i = 0; i < filters.length - 1; i++) {
result.append(filters[i].toString() + (i == filters.length - 2 ? " " : ", "));
- if (filters.length > 1)
+ }
+ if (filters.length > 1) {
result.append("and ");
- if (filters.length > 0)
+ }
+ if (filters.length > 0) {
result.append(filters[filters.length - 1]);
+ }
return result.toString();
}
@Override
public boolean equals(Object o) {
- if (o == null || !(o instanceof StackedFilterMatcher))
+ if (o == null || !(o instanceof StackedFilterMatcher)) {
return false;
+ }
FilterMatcher[] mine = new FilterMatcher[filters.length];
System.arraycopy(this.filters, 0, mine, 0, mine.length);
@@ -185,8 +197,9 @@ public class StackedFilterMatcher extends FilterMatcher {
@Override
public int hashCode() {
int hash = 0;
- for (FilterMatcher f : filters)
+ for (FilterMatcher f : filters) {
hash += f.hashCode();
+ }
return hash;
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/SuppressionMatcher.java b/src/gui/edu/umd/cs/findbugs/gui2/SuppressionMatcher.java
index 3ab8767..4db7737 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/SuppressionMatcher.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/SuppressionMatcher.java
@@ -33,17 +33,20 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
public class SuppressionMatcher extends ArrayList<BugInstance> implements Matcher {
private static final long serialVersionUID = -689204051024507484L;
+ @Override
public boolean match(BugInstance bugInstance) {
return (!contains(bugInstance));
}
@Override
public boolean add(BugInstance bugInstance) {
- if (contains(bugInstance))
+ if (contains(bugInstance)) {
return false;
+ }
return super.add(bugInstance);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
throw new UnsupportedOperationException();
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/ViewFilter.java b/src/gui/edu/umd/cs/findbugs/gui2/ViewFilter.java
index c7c60d4..9a7b84e 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/ViewFilter.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/ViewFilter.java
@@ -42,6 +42,28 @@ public class ViewFilter {
boolean show(MainFrame mf, BugInstance b);
}
+ enum PriorityFilter implements ViewFilterEnum {
+ HIGH_PRIORITY(1, "High priority only"), NORMAL_PRIORITY(2, "High and normal priority"), ALL_BUGS(10, "All bug priorities");
+
+ final int maxPriority;
+ final String displayName;
+
+ private PriorityFilter(int maxPriority, String displayName) {
+ this.maxPriority = maxPriority;
+ this.displayName = displayName;
+ }
+
+ @Override
+ public boolean show(MainFrame mf, BugInstance b) {
+ return b.getPriority() <= maxPriority;
+ }
+
+ @Override
+ public String toString() {
+ return displayName;
+ }
+ }
+
enum RankFilter implements ViewFilterEnum {
SCARIEST(4, "Scariest"), SCARY(9, "Scary"), TROUBLING(14, "Troubling"), ALL(Integer.MAX_VALUE, "All bug ranks");
final int maxRank;
@@ -53,6 +75,7 @@ public class ViewFilter {
this.displayName = displayName;
}
+ @Override
public boolean show(MainFrame mf, BugInstance b) {
int rank = BugRanker.findRank(b);
return rank <= maxRank;
@@ -60,8 +83,9 @@ public class ViewFilter {
@Override
public String toString() {
- if (maxRank < Integer.MAX_VALUE)
+ if (maxRank < Integer.MAX_VALUE) {
return displayName + " (Ranks 1 - " + maxRank + ")";
+ }
return displayName;
}
@@ -72,14 +96,16 @@ public class ViewFilter {
@Override
boolean show(Cloud cloud, BugInstance b) {
double score = cloud.getClassificationScore(b);
- if (score <= UserDesignation.MOSTLY_HARMLESS.score())
+ if (score <= UserDesignation.MOSTLY_HARMLESS.score()) {
return false;
+ }
score = cloud.getPortionObsoleteClassifications(b);
- if (score >= 0.5)
+ if (score >= 0.5) {
return false;
+ }
- return true;
+ return true;
}
},
SHOULD_FIX("Overall classification is should fix") {
@@ -106,14 +132,16 @@ public class ViewFilter {
UNCERTAIN("Overall classification is uncertain") {
@Override
boolean show(Cloud cloud, BugInstance b) {
- if (SHOULD_FIX.show(cloud, b) || DONT_FIX.show(cloud, b) || OBSOLETE.show(cloud, b))
+ if (SHOULD_FIX.show(cloud, b) || DONT_FIX.show(cloud, b) || OBSOLETE.show(cloud, b)) {
return false;
- if (cloud.getNumberReviewers(b) >= 2)
+ }
+ if (cloud.getNumberReviewers(b) >= 2) {
return true;
+ }
return false;
}
},
- HIGH_VARIANCE("Controversial") {
+ HIGH_VARIANCE("Controversial") {
@Override
boolean show(Cloud cloud, BugInstance b) {
double variance = cloud.getClassificationDisagreement(b);
@@ -122,10 +150,10 @@ public class ViewFilter {
},
ALL("All issues") {
-
+
@Override
public boolean show(MainFrame mf, BugInstance b) {
- return true;
+ return true;
}
@Override
@@ -146,6 +174,7 @@ public class ViewFilter {
return true;
}
+ @Override
public boolean show(MainFrame mf, BugInstance b) {
Cloud c = mf.getBugCollection().getCloud();
return c.isInCloud(b) && show(c, b);
@@ -267,7 +296,7 @@ public class ViewFilter {
@Override
public boolean show(MainFrame mf, BugInstance b) {
- return true;
+ return true;
}
};
@@ -283,6 +312,7 @@ public class ViewFilter {
return true;
}
+ @Override
public boolean show(MainFrame mf, BugInstance b) {
Cloud c = mf.getBugCollection().getCloud();
return c.isInCloud(b) && show(c, b);
@@ -316,10 +346,12 @@ public class ViewFilter {
this.displayName = displayName;
}
+ @Override
public boolean show(MainFrame mf, BugInstance b) {
Cloud cloud = mf.getBugCollection().getCloud();
- if (!cloud.isInCloud(b))
+ if (!cloud.isInCloud(b)) {
return false;
+ }
long firstSeen = cloud.getFirstSeen(b);
long time = System.currentTimeMillis() - firstSeen;
long days = TimeUnit.SECONDS.convert(time, TimeUnit.MILLISECONDS) / 3600 / 24;
@@ -336,6 +368,8 @@ public class ViewFilter {
RankFilter rank = RankFilter.ALL;
+ PriorityFilter priority = PriorityFilter.ALL_BUGS;
+
CloudFilter eval = CloudFilter.ALL;
OverallClassificationFilter classificationFilter = OverallClassificationFilter.ALL;
@@ -344,17 +378,20 @@ public class ViewFilter {
String[] classSearchStrings;
+
static final Pattern legalClassSearchString = Pattern.compile("[\\p{javaLowerCase}\\p{javaUpperCase}0-9.$/_]*");
void setPackagesToDisplay(String value) {
value = value.replace('/', '.').trim();
- if (value.length() == 0)
+ if (value.length() == 0) {
classSearchStrings = new String[0];
- else {
+ } else {
String[] parts = value.split("[ ,:]+");
- for (String p : parts)
- if (!legalClassSearchString.matcher(p).matches())
+ for (String p : parts) {
+ if (!legalClassSearchString.matcher(p).matches()) {
throw new IllegalArgumentException("Classname filter must be legal Java identifier: " + p);
+ }
+ }
classSearchStrings = parts;
}
@@ -371,21 +408,33 @@ public class ViewFilter {
}
+ public PriorityFilter getPriority() {
+ return priority;
+ }
+
+ public void setPriority(PriorityFilter priority) {
+ this.priority = priority;
+ FilterActivity.notifyListeners(FilterListener.Action.FILTERING, null);
+
+ }
+
public CloudFilter getEvaluation() {
return eval;
}
public void setEvaluation(CloudFilter eval) {
- if (this.eval == eval)
+ if (this.eval == eval) {
return;
+ }
this.eval = eval;
FilterActivity.notifyListeners(FilterListener.Action.FILTERING, null);
}
public void setClassification(OverallClassificationFilter classificationFilter) {
- if (this.classificationFilter == classificationFilter)
+ if (this.classificationFilter == classificationFilter) {
return;
+ }
this.classificationFilter = classificationFilter;
FilterActivity.notifyListeners(FilterListener.Action.FILTERING, null);
@@ -412,6 +461,9 @@ public class ViewFilter {
if (!rank.show(mf, b)) {
return false;
}
+ if (!priority.show(mf, b)) {
+ return false;
+ }
if (!eval.show(mf, b)) {
return false;
}
diff --git a/src/gui/edu/umd/cs/findbugs/gui2/WideComboBox.java b/src/gui/edu/umd/cs/findbugs/gui2/WideComboBox.java
index cfb14fc..e8b0b00 100644
--- a/src/gui/edu/umd/cs/findbugs/gui2/WideComboBox.java
+++ b/src/gui/edu/umd/cs/findbugs/gui2/WideComboBox.java
@@ -1,45 +1,47 @@
-package edu.umd.cs.findbugs.gui2;
-
-import java.awt.Dimension;
-import java.util.Vector;
-
-import javax.swing.ComboBoxModel;
-import javax.swing.JComboBox;
-
-public class WideComboBox extends JComboBox {
-
- public WideComboBox() {
- }
-
- public WideComboBox(final Object items[]) {
- super(items);
- }
-
- public WideComboBox(Vector items) {
- super(items);
- }
-
- public WideComboBox(ComboBoxModel aModel) {
- super(aModel);
- }
-
- private boolean layingOut = false;
-
- public void doLayout() {
- try {
- layingOut = true;
- super.doLayout();
- } finally {
- layingOut = false;
- }
- }
-
- public Dimension getSize() {
- Dimension dim = super.getSize();
- if (!layingOut) {
- dim.width = Math.max(dim.width, 300);
- dim.height = Math.max(dim.height, 500);
- }
- return dim;
- }
-}
+package edu.umd.cs.findbugs.gui2;
+
+import java.awt.Dimension;
+import java.util.Vector;
+
+import javax.swing.ComboBoxModel;
+import javax.swing.JComboBox;
+
+public class WideComboBox<E> extends JComboBox<E> {
+
+ public WideComboBox() {
+ }
+
+ public WideComboBox(final E items[]) {
+ super(items);
+ }
+
+ public WideComboBox(Vector<E> items) {
+ super(items);
+ }
+
+ public WideComboBox(ComboBoxModel<E> aModel) {
+ super(aModel);
+ }
+
+ private boolean layingOut = false;
+
+ @Override
+ public void doLayout() {
+ try {
+ layingOut = true;
+ super.doLayout();
+ } finally {
+ layingOut = false;
+ }
+ }
+
+ @Override
+ public Dimension getSize() {
+ Dimension dim = super.getSize();
+ if (!layingOut) {
+ dim.width = Math.max(dim.width, 300);
+ dim.height = Math.max(dim.height, 500);
+ }
+ return dim;
+ }
+}
diff --git a/src/gui/edu/umd/cs/findbugs/sourceViewer/DocumentCharacterIterator.java b/src/gui/edu/umd/cs/findbugs/sourceViewer/DocumentCharacterIterator.java
index 85cce83..0d18c6d 100644
--- a/src/gui/edu/umd/cs/findbugs/sourceViewer/DocumentCharacterIterator.java
+++ b/src/gui/edu/umd/cs/findbugs/sourceViewer/DocumentCharacterIterator.java
@@ -58,26 +58,32 @@ public class DocumentCharacterIterator implements CharacterIterator {
throw new UnsupportedOperationException();
}
+ @Override
public char current() {
return text.current();
}
+ @Override
public char first() {
throw new UnsupportedOperationException();
}
+ @Override
public int getBeginIndex() {
throw new UnsupportedOperationException();
}
+ @Override
public int getEndIndex() {
throw new UnsupportedOperationException();
}
+ @Override
public int getIndex() {
return docPos;
}
+ @Override
public char last() {
throw new UnsupportedOperationException();
}
@@ -85,10 +91,11 @@ public class DocumentCharacterIterator implements CharacterIterator {
/**
* Increments the iterator's index by one and returns the character at the
* new index.
- *
+ *
* @return the character at the new position, or DONE if the new position is
* off the end
*/
+ @Override
public char next() {
++docPos;
if (docPos < segmentEnd || segmentEnd >= doc.getLength()) {
@@ -103,10 +110,12 @@ public class DocumentCharacterIterator implements CharacterIterator {
return text.current();
}
+ @Override
public char previous() {
throw new UnsupportedOperationException();
}
+ @Override
public char setIndex(int position) {
throw new UnsupportedOperationException();
}
diff --git a/src/gui/edu/umd/cs/findbugs/sourceViewer/HighlightInformation.java b/src/gui/edu/umd/cs/findbugs/sourceViewer/HighlightInformation.java
index b69e294..9a0250c 100644
--- a/src/gui/edu/umd/cs/findbugs/sourceViewer/HighlightInformation.java
+++ b/src/gui/edu/umd/cs/findbugs/sourceViewer/HighlightInformation.java
@@ -38,8 +38,9 @@ public class HighlightInformation {
}
public void setHighlight(int start, int end, Color color) {
- for (int i = start; i <= end; i++)
+ for (int i = start; i <= end; i++) {
map.put(i, color);
+ }
}
public void setHighlight(Integer line, Color color) {
@@ -51,8 +52,9 @@ public class HighlightInformation {
}
public void updateFoundLineNum(Integer line) {
- if (foundLineNum != -1)
+ if (foundLineNum != -1) {
unsetHighlight(foundLineNum);
+ }
foundLineNum = line;
}
diff --git a/src/gui/edu/umd/cs/findbugs/sourceViewer/JavaScanner.java b/src/gui/edu/umd/cs/findbugs/sourceViewer/JavaScanner.java
index 82f756e..09df7ea 100644
--- a/src/gui/edu/umd/cs/findbugs/sourceViewer/JavaScanner.java
+++ b/src/gui/edu/umd/cs/findbugs/sourceViewer/JavaScanner.java
@@ -50,8 +50,9 @@ public class JavaScanner {
"synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while" };
int max = 0;
for (String s : keywordList) {
- if (max < s.length())
+ if (max < s.length()) {
max = s.length();
+ }
KEYWORDS.add(s);
}
MAX_KEYWORD_LENGTH = max;
@@ -96,19 +97,22 @@ public class JavaScanner {
boolean couldBeKeyword = Character.isLowerCase(c);
while (true) {
c = iterator.current();
- if (!Character.isJavaIdentifierPart(c))
+ if (!Character.isJavaIdentifierPart(c)) {
break;
+ }
buf.append(c);
if (couldBeKeyword) {
- if (!Character.isLowerCase(c) || buf.length() > MAX_KEYWORD_LENGTH)
+ if (!Character.isLowerCase(c) || buf.length() > MAX_KEYWORD_LENGTH) {
couldBeKeyword = false;
+ }
}
c = iterator.next();
}
kind = NORMAL_TEXT;
if (couldBeKeyword) {
- if (KEYWORDS.contains(buf.toString()))
+ if (KEYWORDS.contains(buf.toString())) {
kind = KEYWORD;
+ }
}
buf.setLength(0);
} else if (c == '/') {
@@ -116,8 +120,9 @@ public class JavaScanner {
if (c2 == '/') {
while (true) {
c2 = iterator.next();
- if (c2 == '\n' || c2 == '\r' || c2 == CharacterIterator.DONE)
+ if (c2 == '\n' || c2 == '\r' || c2 == CharacterIterator.DONE) {
break;
+ }
}
kind = COMMENT;
return kind;
@@ -127,13 +132,14 @@ public class JavaScanner {
if (c2 == '*') {
do {
c2 = iterator.next();
- if (c2 == '/')
+ if (c2 == '/') {
break scanComment;
+ }
} while (c2 == '*');
}
}
- kind = JAVADOC;
- return kind;
+ kind = JAVADOC;
+ return kind;
}
} else if (c == '"') {
kind = QUOTE;
@@ -141,8 +147,9 @@ public class JavaScanner {
while (c2 != '"' && c2 != '\n' && c2 != '\r' && c2 != CharacterIterator.DONE) {
if (c2 == '\\') {
c2 = iterator.next();
- if (c2 == '\n' || c2 == '\r')
+ if (c2 == '\n' || c2 == '\r') {
break;
+ }
}
c2 = iterator.next();
}
@@ -152,14 +159,21 @@ public class JavaScanner {
kind = QUOTE; // or NORMAL_TEXT ?
char c2 = iterator.current();
if (c2 == '\\')
+ {
c2 = iterator.next(); // advance past the escape char
+ }
if (c2 != '\n' && c2 != '\r' && c2 != CharacterIterator.DONE)
+ {
c2 = iterator.next(); // advance past the content char
+ }
if (c2 != '\n' && c2 != '\r' && c2 != CharacterIterator.DONE)
+ {
iterator.next(); // advance past closing char
+ }
- } else
+ } else {
kind = NORMAL_TEXT;
+ }
// System.out.println(kind + " " + startPosition + "-" +
// iterator.getIndex());
return kind;
diff --git a/src/gui/edu/umd/cs/findbugs/sourceViewer/JavaSourceDocument.java b/src/gui/edu/umd/cs/findbugs/sourceViewer/JavaSourceDocument.java
index 2e14a4b..cf2b39d 100644
--- a/src/gui/edu/umd/cs/findbugs/sourceViewer/JavaSourceDocument.java
+++ b/src/gui/edu/umd/cs/findbugs/sourceViewer/JavaSourceDocument.java
@@ -30,10 +30,8 @@ import java.io.StringReader;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Document;
-import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
-import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;
@@ -73,9 +71,9 @@ public class JavaSourceDocument {
final NumberedEditorKit dek = new NumberedEditorKit(highlights);
- final StyleContext styleContext = new StyleContext();
+ // final StyleContext styleContext = new StyleContext();
- final Element root;
+ // final Element root;
final DefaultStyledDocument doc;
@@ -115,15 +113,16 @@ public class JavaSourceDocument {
}
in.close();
doc.putProperty(Document.TitleProperty, title);
- root = doc.getDefaultRootElement();
+ // root = doc.getDefaultRootElement();
Toolkit toolkit = Toolkit.getDefaultToolkit();
FontMetrics fontMetrics = toolkit.getFontMetrics(sourceFont);
TabStop[] tabs = new TabStop[50];
float width = fontMetrics.stringWidth(" ");
int tabSize = GUISaveState.getInstance().getTabSize();
- for (int i = 0; i < tabs.length; i++)
+ for (int i = 0; i < tabs.length; i++) {
tabs[i] = new TabStop(width * (tabSize + tabSize * i));
+ }
TAB_SET = new TabSet(tabs);
StyleConstants.setTabSet(commentAttributes, TAB_SET);
StyleConstants.setTabSet(javadocAttributes, TAB_SET);
@@ -146,19 +145,21 @@ public class JavaSourceDocument {
switch (kind) {
case JavaScanner.COMMENT:
doc.setCharacterAttributes(parser.getStartPosition(), parser.getLength(), commentAttributes, true);
-
break;
+
case JavaScanner.KEYWORD:
doc.setCharacterAttributes(parser.getStartPosition(), parser.getLength(), keywordsAttributes, true);
-
break;
+
case JavaScanner.JAVADOC:
doc.setCharacterAttributes(parser.getStartPosition(), parser.getLength(), javadocAttributes, true);
-
break;
+
case JavaScanner.QUOTE:
doc.setCharacterAttributes(parser.getStartPosition(), parser.getLength(), quotesAttributes, true);
+ break;
+ default:
break;
}
@@ -166,7 +167,7 @@ public class JavaSourceDocument {
}
- private static final long serialVersionUID = 0L;
+ // private static final long serialVersionUID = 0L;
public static final JavaSourceDocument UNKNOWNSOURCE;
static {
diff --git a/src/gui/edu/umd/cs/findbugs/sourceViewer/NavigableTextPane.java b/src/gui/edu/umd/cs/findbugs/sourceViewer/NavigableTextPane.java
index 995d8a4..070ac11 100644
--- a/src/gui/edu/umd/cs/findbugs/sourceViewer/NavigableTextPane.java
+++ b/src/gui/edu/umd/cs/findbugs/sourceViewer/NavigableTextPane.java
@@ -53,8 +53,9 @@ public class NavigableTextPane extends JTextPane {
*/
private int parentHeight() {
Container parent = getParent();
- if (parent != null)
+ if (parent != null) {
return parent.getHeight();
+ }
return getHeight(); // entire pane height, may be huge
}
@@ -66,8 +67,9 @@ public class NavigableTextPane extends JTextPane {
Document d = getDocument();
try {
Element element = d.getDefaultRootElement().getElement(line - 1);
- if (element == null)
+ if (element == null) {
throw new BadLocationException("line " + line + " does not exist", -line);
+ }
return element.getStartOffset();
} catch (ArrayIndexOutOfBoundsException aioobe) {
BadLocationException ble = new BadLocationException("line " + line + " does not exist", -line);
@@ -89,6 +91,7 @@ public class NavigableTextPane extends JTextPane {
final Rectangle r = new Rectangle(0, y - margin, 4, 2 * margin);
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
scrollRectToVisible(r);
}
@@ -100,8 +103,9 @@ public class NavigableTextPane extends JTextPane {
int y = lineToY(line);
scrollYToVisibleImpl(y, margin);
} catch (BadLocationException ble) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
ble.printStackTrace();
+ }
}
}
@@ -111,8 +115,9 @@ public class NavigableTextPane extends JTextPane {
*/
public void scrollLineToVisible(int line, int margin) {
int maxMargin = (parentHeight() - 20) / 2;
- if (margin > maxMargin)
+ if (margin > maxMargin) {
margin = Math.max(0, maxMargin);
+ }
scrollLineToVisibleImpl(line, margin);
}
@@ -131,8 +136,9 @@ public class NavigableTextPane extends JTextPane {
try {
startY = lineToY(startLine);
} catch (BadLocationException ble) {
- if (MainFrame.GUI2_DEBUG)
+ if (MainFrame.GUI2_DEBUG) {
ble.printStackTrace();
+ }
return; // give up
}
try {
@@ -161,15 +167,15 @@ public class NavigableTextPane extends JTextPane {
int y = pq.remove();
int lo = Math.min(startY, y);
int hi = Math.max(endY, y);
- if (hi - lo > max)
+ if (hi - lo > max) {
break;
- else {
+ } else {
startY = lo;
endY = hi;
}
}
}
-
+
if (endY - startY > max) {
endY = startY + max;
}
@@ -189,6 +195,7 @@ public class NavigableTextPane extends JTextPane {
* the origin. This sounds backwards, but this way closer values get a
* higher priority in the priority queue.
*/
+ @Override
public int compare(Integer a, Integer b) {
return Math.abs(b - origin) - Math.abs(a - origin);
}
diff --git a/src/gui/edu/umd/cs/findbugs/sourceViewer/NumberedParagraphView.java b/src/gui/edu/umd/cs/findbugs/sourceViewer/NumberedParagraphView.java
index f81e29f..77c4031 100644
--- a/src/gui/edu/umd/cs/findbugs/sourceViewer/NumberedParagraphView.java
+++ b/src/gui/edu/umd/cs/findbugs/sourceViewer/NumberedParagraphView.java
@@ -101,16 +101,18 @@ class NumberedParagraphView extends ParagraphView {
Element element = this.getElement();
Integer result = elementLineNumberCache.get(element);
- if (result != null)
+ if (result != null) {
return result;
+ }
Element parent = element.getParentElement();
int count = parent.getElementCount();
for (int i = 0; i < count; i++) {
elementLineNumberCache.put(parent.getElement(i), i + 1);
}
result = elementLineNumberCache.get(element);
- if (result != null)
+ if (result != null) {
return result;
+ }
return -1;
}
diff --git a/src/gui/edu/umd/cs/findbugs/sourceViewer/NumberedViewFactory.java b/src/gui/edu/umd/cs/findbugs/sourceViewer/NumberedViewFactory.java
index d5bb95a..0dfb0de 100644
--- a/src/gui/edu/umd/cs/findbugs/sourceViewer/NumberedViewFactory.java
+++ b/src/gui/edu/umd/cs/findbugs/sourceViewer/NumberedViewFactory.java
@@ -35,21 +35,23 @@ class NumberedViewFactory implements ViewFactory {
this.highlight = highlight;
}
+ @Override
public View create(Element elem) {
String kind = elem.getName();
// System.out.println("Kind: " + kind);
- if (kind != null)
- if (kind.equals(AbstractDocument.ContentElementName)) {
+ if (kind != null) {
+ if (AbstractDocument.ContentElementName.equals(kind)) {
return new LabelView(elem);
- } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
+ } else if (AbstractDocument.ParagraphElementName.equals(kind)) {
return new NumberedParagraphView(elem, highlight);
- } else if (kind.equals(AbstractDocument.SectionElementName)) {
+ } else if (AbstractDocument.SectionElementName.equals(kind)) {
return new NoWrapBoxView(elem, View.Y_AXIS);
- } else if (kind.equals(StyleConstants.ComponentElementName)) {
+ } else if (StyleConstants.ComponentElementName.equals(kind)) {
return new ComponentView(elem);
- } else if (kind.equals(StyleConstants.IconElementName)) {
+ } else if (StyleConstants.IconElementName.equals(kind)) {
return new IconView(elem);
}
+ }
// default to text display
return new LabelView(elem);
}
diff --git a/src/java/edu/umd/cs/findbugs/AWTEventQueueExecutor.java b/src/java/edu/umd/cs/findbugs/AWTEventQueueExecutor.java
index 3af9466..30b607b 100644
--- a/src/java/edu/umd/cs/findbugs/AWTEventQueueExecutor.java
+++ b/src/java/edu/umd/cs/findbugs/AWTEventQueueExecutor.java
@@ -1,44 +1,50 @@
-package edu.umd.cs.findbugs;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.AbstractExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.swing.SwingUtilities;
-
-public class AWTEventQueueExecutor extends AbstractExecutorService {
- public void shutdown() {
- }
-
- public List<Runnable> shutdownNow() {
- return Collections.emptyList();
- }
-
- public boolean isShutdown() {
- return true;
- }
-
- public boolean isTerminated() {
- return true;
- }
-
- public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
- return true;
- }
-
- public void execute(Runnable command) {
- if (SwingUtilities.isEventDispatchThread()) {
- command.run();
- return;
- }
- try {
- SwingUtilities.invokeAndWait(command);
- } catch (InterruptedException e) {
- throw new IllegalStateException(e);
- } catch (InvocationTargetException e) {
- throw new IllegalStateException(e);
- }
- }
-}
+package edu.umd.cs.findbugs;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.swing.SwingUtilities;
+
+public class AWTEventQueueExecutor extends AbstractExecutorService {
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return true;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return true;
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ return true;
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ if (SwingUtilities.isEventDispatchThread()) {
+ command.run();
+ return;
+ }
+ try {
+ SwingUtilities.invokeAndWait(command);
+ } catch (InterruptedException e) {
+ throw new IllegalStateException(e);
+ } catch (InvocationTargetException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/AbstractBugReporter.java b/src/java/edu/umd/cs/findbugs/AbstractBugReporter.java
index b6f4917..1fe00cd 100644
--- a/src/java/edu/umd/cs/findbugs/AbstractBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/AbstractBugReporter.java
@@ -139,10 +139,12 @@ public abstract class AbstractBugReporter implements BugReporter {
rankThreshold = BugRanker.VISIBLE_RANK_MAX;
}
+ @Override
public void setErrorVerbosity(int level) {
this.verbosityLevel = level;
}
+ @Override
public void setPriorityThreshold(int threshold) {
this.priorityThreshold = threshold;
}
@@ -150,7 +152,7 @@ public abstract class AbstractBugReporter implements BugReporter {
public void setRankThreshold(int threshold) {
this.rankThreshold = threshold;
}
-
+
public void setIsRelaxed(boolean relaxed) {
this.relaxed = relaxed;
this.relaxedSet = true;
@@ -167,6 +169,7 @@ public abstract class AbstractBugReporter implements BugReporter {
return relaxed;
}
// Subclasses must override doReportBug(), not this method.
+ @Override
public final void reportBug(@Nonnull BugInstance bugInstance) {
if (isRelaxed()) {
doReportBug(bugInstance);
@@ -189,11 +192,12 @@ public abstract class AbstractBugReporter implements BugReporter {
doReportBug(bugInstance);
} else {
if (DEBUG) {
- if (priority <= priorityThreshold)
+ if (priority <= priorityThreshold) {
System.out.println("AbstractBugReporter: Filtering due to priorityThreshold " + priority + " > "
+ priorityThreshold);
- else
+ } else {
System.out.println("AbstractBugReporter: Filtering due to rankThreshold " + bugRank + " > " + rankThreshold);
+ }
}
}
}
@@ -219,6 +223,7 @@ public abstract class AbstractBugReporter implements BugReporter {
return null;
}
+ @Override
public void reportMissingClass(ClassNotFoundException ex) {
if (DEBUG_MISSING_CLASSES) {
System.out.println("Missing class: " + ex.toString());
@@ -249,7 +254,7 @@ public abstract class AbstractBugReporter implements BugReporter {
return false;
}
- if (message.equals("")) {
+ if ("".equals(message)) {
// Subtypes2 throws ClassNotFoundExceptions with no message in
// some cases. Ignore them (the missing classes will already
// have been reported).
@@ -260,8 +265,9 @@ public abstract class AbstractBugReporter implements BugReporter {
// we ignore all "package-info" issues
return false;
}
- if (message.equals("java.lang.Synthetic"))
+ if ("java.lang.Synthetic".equals(message)) {
return false;
+ }
return true;
}
@@ -272,6 +278,7 @@ public abstract class AbstractBugReporter implements BugReporter {
* edu.umd.cs.findbugs.classfile.IErrorLogger#reportMissingClass(edu.umd
* .cs.findbugs.classfile.ClassDescriptor)
*/
+ @Override
public void reportMissingClass(ClassDescriptor classDescriptor) {
if (DEBUG_MISSING_CLASSES) {
System.out.println("Missing class: " + classDescriptor);
@@ -300,10 +307,12 @@ public abstract class AbstractBugReporter implements BugReporter {
*
* @param method
*/
+ @Override
public void reportSkippedAnalysis(MethodDescriptor method) {
// TODO: log this
}
+ @Override
public void logError(String message) {
if (verbosityLevel == SILENT) {
return;
@@ -329,6 +338,7 @@ public abstract class AbstractBugReporter implements BugReporter {
return missingClassMessageList;
}
+ @Override
public void logError(String message, Throwable e) {
if (e instanceof MethodUnprofitableException) {
@@ -361,10 +371,12 @@ public abstract class AbstractBugReporter implements BugReporter {
}
}
+ @Override
public void reportQueuedErrors() {
// Report unique errors in order of their sequence
Error[] errorList = errorSet.toArray(new Error[errorSet.size()]);
Arrays.sort(errorList, new Comparator<Error>() {
+ @Override
public int compare(Error o1, Error o2) {
return o1.getSequence() - o2.getSequence();
}
@@ -378,10 +390,12 @@ public abstract class AbstractBugReporter implements BugReporter {
}
}
+ @Override
public void addObserver(BugReporterObserver observer) {
observerList.add(observer);
}
+ @Override
public ProjectStats getProjectStats() {
return projectStats;
}
@@ -424,4 +438,3 @@ public abstract class AbstractBugReporter implements BugReporter {
public abstract void reportMissingClass(String string);
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/AddAnnotation.java b/src/java/edu/umd/cs/findbugs/AddAnnotation.java
index 99f9537..e826f42 100644
--- a/src/java/edu/umd/cs/findbugs/AddAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/AddAnnotation.java
@@ -32,9 +32,9 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
public class AddAnnotation {
private static final Logger LOGGER = Logger.getLogger(AddAnnotation.class.getName());
- private BugCollection bugCollection;
+ private final BugCollection bugCollection;
- private String annotation;
+ private final String annotation;
public AddAnnotation(BugCollection bugCollection, String annotation) {
this.bugCollection = bugCollection;
@@ -57,12 +57,13 @@ public class AddAnnotation {
public void execute() {
for (BugInstance bugInstance : bugCollection) {
// Don't add the annotation if it is already present
- if (bugInstance.annotationTextContainsWord(this.annotation))
+ if (bugInstance.annotationTextContainsWord(this.annotation)) {
continue;
+ }
String annotation = bugInstance.getAnnotationText();
StringBuilder buf = new StringBuilder();
- if (!annotation.equals("")) {
+ if (!"".equals(annotation)) {
buf.append(annotation);
buf.append('\n');
}
@@ -88,4 +89,3 @@ public class AddAnnotation {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/AddMessages.java b/src/java/edu/umd/cs/findbugs/AddMessages.java
index eeb50a4..1787cf1 100644
--- a/src/java/edu/umd/cs/findbugs/AddMessages.java
+++ b/src/java/edu/umd/cs/findbugs/AddMessages.java
@@ -155,11 +155,12 @@ public class AddMessages {
Element root = document.getRootElement();
for (String bugType : bugTypeSet) {
BugPattern bugPattern = DetectorFactoryCollection.instance().lookupBugPattern(bugType);
- if (bugPattern == null)
+ if (bugPattern == null) {
continue;
+ }
Element details = root.addElement("BugPattern");
details.addAttribute("type", bugType).addAttribute("abbrev", bugPattern.getAbbrev())
- .addAttribute("category", bugPattern.getCategory());
+ .addAttribute("category", bugPattern.getCategory());
details.addElement("ShortDescription").addText(bugPattern.getShortDescription());
details.addElement("Details").addCDATA(bugPattern.getDetailText());
}
@@ -194,4 +195,3 @@ public class AddMessages {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/AnalysisCacheToRepositoryAdapter.java b/src/java/edu/umd/cs/findbugs/AnalysisCacheToRepositoryAdapter.java
index 382a7e1..df523de 100644
--- a/src/java/edu/umd/cs/findbugs/AnalysisCacheToRepositoryAdapter.java
+++ b/src/java/edu/umd/cs/findbugs/AnalysisCacheToRepositoryAdapter.java
@@ -33,7 +33,7 @@ import edu.umd.cs.findbugs.util.ClassName;
/**
* An implementation of org.apache.bcel.util.Repository that uses the
* AnalysisCache as its backing store.
- *
+ *
* @author David Hovemeyer
*/
public class AnalysisCacheToRepositoryAdapter implements Repository {
@@ -45,18 +45,20 @@ public class AnalysisCacheToRepositoryAdapter implements Repository {
/*
* (non-Javadoc)
- *
+ *
* @see org.apache.bcel.util.Repository#clear()
*/
+ @Override
public void clear() {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
- *
+ *
* @see org.apache.bcel.util.Repository#findClass(java.lang.String)
*/
+ @Override
public JavaClass findClass(String className) {
@SlashedClassName
String slashedClassName = ClassName.toSlashedClassName(className);
@@ -66,21 +68,24 @@ public class AnalysisCacheToRepositoryAdapter implements Repository {
/*
* (non-Javadoc)
- *
+ *
* @see org.apache.bcel.util.Repository#getClassPath()
*/
+ @Override
public ClassPath getClassPath() {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
- *
+ *
* @see org.apache.bcel.util.Repository#loadClass(java.lang.String)
*/
+ @Override
public JavaClass loadClass(String className) throws ClassNotFoundException {
- if (className.length() == 0)
+ if (className.length() == 0) {
throw new IllegalArgumentException("Request to load empty class");
+ }
className = ClassName.toSlashedClassName(className);
ClassDescriptor classDescriptor = DescriptorFactory.instance().getClassDescriptor(className);
try {
@@ -92,31 +97,34 @@ public class AnalysisCacheToRepositoryAdapter implements Repository {
/*
* (non-Javadoc)
- *
+ *
* @see org.apache.bcel.util.Repository#loadClass(java.lang.Class)
*/
- public JavaClass loadClass(Class cls) throws ClassNotFoundException {
+ @Override
+ public JavaClass loadClass(Class<?> cls) throws ClassNotFoundException {
return loadClass(cls.getName());
}
/*
* (non-Javadoc)
- *
+ *
* @see
* org.apache.bcel.util.Repository#removeClass(org.apache.bcel.classfile
* .JavaClass)
*/
+ @Override
public void removeClass(JavaClass arg0) {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
- *
+ *
* @see
* org.apache.bcel.util.Repository#storeClass(org.apache.bcel.classfile.
* JavaClass)
*/
+ @Override
public void storeClass(JavaClass cls) {
throw new UnsupportedOperationException();
}
diff --git a/src/java/edu/umd/cs/findbugs/AnalysisError.java b/src/java/edu/umd/cs/findbugs/AnalysisError.java
index 585492a..2de1886 100644
--- a/src/java/edu/umd/cs/findbugs/AnalysisError.java
+++ b/src/java/edu/umd/cs/findbugs/AnalysisError.java
@@ -5,7 +5,7 @@ import java.util.Arrays;
/**
* Object recording a recoverable error that occurred during analysis.
- *
+ *
* @author David Hovemeyer
*/
public class AnalysisError {
@@ -21,7 +21,7 @@ public class AnalysisError {
private final Throwable exception;
-
+
@Override
public int hashCode() {
final int prime = 31;
@@ -36,38 +36,49 @@ public class AnalysisError {
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (!(obj instanceof AnalysisError))
+ }
+ if (!(obj instanceof AnalysisError)) {
return false;
+ }
AnalysisError other = (AnalysisError) obj;
if (exceptionMessage == null) {
- if (other.exceptionMessage != null)
+ if (other.exceptionMessage != null) {
return false;
- } else if (!exceptionMessage.equals(other.exceptionMessage))
+ }
+ } else if (!exceptionMessage.equals(other.exceptionMessage)) {
return false;
+ }
if (message == null) {
- if (other.message != null)
+ if (other.message != null) {
return false;
- } else if (!message.equals(other.message))
+ }
+ } else if (!message.equals(other.message)) {
return false;
+ }
if (nestedExceptionMessage == null) {
- if (other.nestedExceptionMessage != null)
+ if (other.nestedExceptionMessage != null) {
return false;
- } else if (!nestedExceptionMessage.equals(other.nestedExceptionMessage))
+ }
+ } else if (!nestedExceptionMessage.equals(other.nestedExceptionMessage)) {
return false;
- if (!Arrays.equals(nestedStackTrace, other.nestedStackTrace))
+ }
+ if (!Arrays.equals(nestedStackTrace, other.nestedStackTrace)) {
return false;
- if (!Arrays.equals(stackTrace, other.stackTrace))
+ }
+ if (!Arrays.equals(stackTrace, other.stackTrace)) {
return false;
+ }
return true;
}
/**
* Constructor.
- *
+ *
* @param message
* message describing the error
*/
@@ -77,7 +88,7 @@ public class AnalysisError {
/**
* Constructor.
- *
+ *
* @param message
* message describing the error
* @param exception
@@ -98,10 +109,6 @@ public class AnalysisError {
}
}
- /**
- * @param exception
- * @return
- */
private String[] getStackTraceAsStringArray(Throwable exception) {
StackTraceElement[] exceptionStackTrace = exception.getStackTrace();
ArrayList<String> arr = new ArrayList<String>();
@@ -114,7 +121,7 @@ public class AnalysisError {
/**
* Set the message describing the error.
- *
+ *
* @param message
* message describing the error
*/
@@ -132,7 +139,7 @@ public class AnalysisError {
/**
* Set the exception message. This is the value returned by calling
* toString() on the original exception object.
- *
+ *
* @param exceptionMessage
* the exception message
*/
@@ -159,7 +166,7 @@ public class AnalysisError {
/**
* Set the stack trace elements. These are the strings returned by calling
* toString() on each StackTraceElement in the original exception.
- *
+ *
* @param stackTraceList
* the stack trace elements
*/
diff --git a/src/java/edu/umd/cs/findbugs/Analyze.java b/src/java/edu/umd/cs/findbugs/Analyze.java
index e2621f2..4fd53b6 100644
--- a/src/java/edu/umd/cs/findbugs/Analyze.java
+++ b/src/java/edu/umd/cs/findbugs/Analyze.java
@@ -41,40 +41,48 @@ public class Analyze {
try {
remote = AnalysisContext.lookupSystemClass("java.rmi.Remote");
} catch (ClassNotFoundException e) {
- if (storedException == null)
+ if (storedException == null) {
storedException = e;
+ }
}
}
+ /*
private static boolean containsConcreteClasses(Set<JavaClass> s) {
for (JavaClass c : s)
if (!c.isInterface() && !c.isAbstract())
return true;
return false;
}
+ */
public static double isDeepSerializable(String refSig) throws ClassNotFoundException {
- if (storedException != null)
+ if (storedException != null) {
throw storedException;
+ }
- if (isPrimitiveComponentClass(refSig))
+ if (isPrimitiveComponentClass(refSig)) {
return 1.0;
+ }
String refName = getComponentClass(refSig);
- if (refName.equals("java.lang.Object"))
+ if ("java.lang.Object".equals(refName)) {
return 0.99;
+ }
JavaClass refJavaClass = Repository.lookupClass(refName);
return isDeepSerializable(refJavaClass);
}
public static double isDeepRemote(String refSig) {
- if (remote == null)
+ if (remote == null) {
return 0.1;
+ }
String refName = getComponentClass(refSig);
- if (refName.equals("java.lang.Object"))
+ if ("java.lang.Object".equals(refName)) {
return 0.99;
+ }
JavaClass refJavaClass;
try {
@@ -101,31 +109,38 @@ public class Analyze {
}
public static String getComponentClass(String refSig) {
- while (refSig.charAt(0) == '[')
+ while (refSig.charAt(0) == '[') {
refSig = refSig.substring(1);
+ }
// TODO: This method now returns primitive type signatures, is this ok?
- if (refSig.charAt(0) == 'L')
+ if (refSig.charAt(0) == 'L') {
return refSig.substring(1, refSig.length() - 1).replace('/', '.');
+ }
return refSig;
}
public static double isDeepSerializable(JavaClass x) throws ClassNotFoundException {
- if (storedException != null)
+ if (storedException != null) {
throw storedException;
+ }
double result = deepInstanceOf(x, serializable);
- if (result >= 0.9)
+ if (result >= 0.9) {
return result;
+ }
result = Math.max(result, deepInstanceOf(x, collection));
- if (result >= 0.9)
+ if (result >= 0.9) {
return result;
+ }
result = Math.max(result, deepInstanceOf(x, map));
- if (result >= 0.9)
+ if (result >= 0.9) {
return result;
+ }
result = Math.max(result, 0.5 * deepInstanceOf(x, comparator));
- if (result >= 0.9)
+ if (result >= 0.9) {
return result;
+ }
return result;
}
@@ -133,7 +148,7 @@ public class Analyze {
* Given two JavaClasses, try to estimate the probability that an reference
* of type x is also an instance of type y. Will return 0 only if it is
* impossible and 1 only if it is guaranteed.
- *
+ *
* @param x
* Known type of object
* @param y
@@ -150,7 +165,7 @@ public class Analyze {
* Given two JavaClasses, try to estimate the probability that an reference
* of type x is also an instance of type y. Will return 0 only if it is
* impossible and 1 only if it is guaranteed.
- *
+ *
* @param x
* Known type of object
* @param y
@@ -159,23 +174,28 @@ public class Analyze {
*/
public static double deepInstanceOf(JavaClass x, JavaClass y) throws ClassNotFoundException {
- if (x.equals(y))
+ if (x.equals(y)) {
return 1.0;
- if (y.getClassName().equals("java.lang.Object"))
+ }
+ if ("java.lang.Object".equals(y.getClassName())) {
return 1.0;
+ }
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
ClassDescriptor xDesc = DescriptorFactory.createClassDescriptor(x);
ClassDescriptor yDesc = DescriptorFactory.createClassDescriptor(y);
boolean xIsSubtypeOfY = Repository.instanceOf(x, y);
- if (xIsSubtypeOfY)
+ if (xIsSubtypeOfY) {
return 1.0;
+ }
boolean yIsSubtypeOfX = Repository.instanceOf(y, x);
if (!yIsSubtypeOfX) {
- if (x.isFinal() || y.isFinal())
+ if (x.isFinal() || y.isFinal()) {
return 0.0;
- if (!x.isInterface() && !y.isInterface())
+ }
+ if (!x.isInterface() && !y.isInterface()) {
return 0.0;
+ }
}
Set<ClassDescriptor> transitiveCommonSubtypes = subtypes2.getTransitiveCommonSubtypes(xDesc, yDesc);
@@ -189,8 +209,9 @@ public class Analyze {
continue;
}
if (!cx.isAbstract() && !cx.isInterface()) {
- if (x.isAbstract() || x.isInterface())
+ if (x.isAbstract() || x.isInterface()) {
return 0.2;
+ }
return 0.1;
}
}
@@ -201,15 +222,16 @@ public class Analyze {
Set<ClassDescriptor> xButNotY = new HashSet<ClassDescriptor>(subtypes2.getSubtypes(xDesc));
xButNotY.removeAll(transitiveCommonSubtypes);
for (ClassDescriptor c : xButNotY) {
-
+
try {
XClass cx = Global.getAnalysisCache().getClassAnalysis(XClass.class, c);
- if (!cx.isAbstract() && !cx.isInterface())
+ if (!cx.isAbstract() && !cx.isInterface()) {
return 0.7;
+ }
} catch (CheckedAnalysisException e) {
continue;
}
-
+
}
return 0.99;
}
diff --git a/src/java/edu/umd/cs/findbugs/AppVersion.java b/src/java/edu/umd/cs/findbugs/AppVersion.java
index 6e87416..16b50ea 100644
--- a/src/java/edu/umd/cs/findbugs/AppVersion.java
+++ b/src/java/edu/umd/cs/findbugs/AppVersion.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.xml.XMLWriteable;
* application. Timestamp is when FindBugs was run (according to
* System.currentTimeMillis()), and the release name is available if the user
* provided it.
- *
+ *
* @author David Hovemeyer
*/
public class AppVersion implements XMLWriteable, Cloneable {
@@ -41,7 +41,7 @@ public class AppVersion implements XMLWriteable, Cloneable {
*/
public static final String ELEMENT_NAME = "AppVersion";
- private long sequence;
+ private final long sequence;
private long timestamp;
@@ -71,7 +71,7 @@ public class AppVersion implements XMLWriteable, Cloneable {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#clone()
*/
@@ -95,8 +95,9 @@ public class AppVersion implements XMLWriteable, Cloneable {
* @return Returns the timestamp.
*/
public long getTimestamp() {
- if (timestamp <= 0)
+ if (timestamp <= 0) {
return System.currentTimeMillis();
+ }
return timestamp;
}
@@ -127,23 +128,24 @@ public class AppVersion implements XMLWriteable, Cloneable {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.xml.XMLWriteable#writeXML(edu.umd.cs.findbugs.xml
* .XMLOutput)
*/
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
xmlOutput.openCloseTag(
ELEMENT_NAME,
new XMLAttributeList().addAttribute("sequence", String.valueOf(sequence))
- .addAttribute("timestamp", String.valueOf(timestamp)).addAttribute("release", releaseName)
- .addAttribute("codeSize", String.valueOf(codeSize))
- .addAttribute("numClasses", String.valueOf(numClasses)));
+ .addAttribute("timestamp", String.valueOf(timestamp)).addAttribute("release", releaseName)
+ .addAttribute("codeSize", String.valueOf(codeSize))
+ .addAttribute("numClasses", String.valueOf(numClasses)));
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
diff --git a/src/java/edu/umd/cs/findbugs/BugAccumulator.java b/src/java/edu/umd/cs/findbugs/BugAccumulator.java
index cc41bf9..a046322 100644
--- a/src/java/edu/umd/cs/findbugs/BugAccumulator.java
+++ b/src/java/edu/umd/cs/findbugs/BugAccumulator.java
@@ -53,7 +53,9 @@ public class BugAccumulator {
private BugInstance lastBug;
private SourceLineAnnotation lastSourceLine;
+
static class Data {
+
public Data(int priority, SourceLineAnnotation primarySource) {
this.priority = priority;
this.primarySource = primarySource;
@@ -86,7 +88,6 @@ public class BugAccumulator {
public void forgetLastBug() {
Data d = map.get(lastBug);
if (d != null) {
-
d.allSource.remove(lastSourceLine);
if (d.allSource.isEmpty()) {
map.remove(lastBug);
@@ -96,6 +97,7 @@ public class BugAccumulator {
lastBug = null;
lastSourceLine = null;
}
+
/**
* Accumulate a warning at given source location.
*
@@ -105,13 +107,15 @@ public class BugAccumulator {
* the source location
*/
public void accumulateBug(BugInstance bug, SourceLineAnnotation sourceLine) {
- if (sourceLine == null)
+ if (sourceLine == null) {
throw new NullPointerException("Missing source line");
+ }
int priority = bug.getPriority();
- if (!performAccumulation)
+ if (!performAccumulation) {
bug.addSourceLine(sourceLine);
- else
+ } else {
bug.setPriority(Priorities.NORMAL_PRIORITY);
+ }
lastBug = bug;
lastSourceLine = sourceLine;
@@ -120,20 +124,26 @@ public class BugAccumulator {
String hash = bug.getInstanceHash();
BugInstance conflictingBug = hashes.get(hash);
if (conflictingBug != null) {
- if (conflictingBug.getPriority() <= priority)
+ if (conflictingBug.getPriority() <= priority) {
return;
+ }
map.remove(conflictingBug);
}
d = new Data(priority, sourceLine);
map.put(bug, d);
hashes.put(hash, bug);
} else if (d.priority > priority) {
- if (d.priority >= Priorities.LOW_PRIORITY)
+ if (d.priority >= Priorities.LOW_PRIORITY) {
+ reportBug(bug, d);
d.allSource.clear();
+ }
d.priority = priority;
d.primarySource = sourceLine;
- } else if (priority >= Priorities.LOW_PRIORITY && priority > d.priority)
+ } else if (priority >= Priorities.LOW_PRIORITY && priority > d.priority) {
+ bug.setPriority(priority);
+ reporter.reportBug(bug);
return;
+ }
d.allSource.add(sourceLine);
}
@@ -168,20 +178,26 @@ public class BugAccumulator {
for (Map.Entry<BugInstance, Data> e : map.entrySet()) {
BugInstance bug = e.getKey();
Data d = e.getValue();
- bug.setPriority(d.priority);
- bug.addSourceLine(d.primarySource);
- HashSet<Integer> lines = new HashSet<Integer>();
- lines.add(d.primarySource.getStartLine());
- d.allSource.remove(d.primarySource);
- for (SourceLineAnnotation source : d.allSource) if (lines.add(source.getStartLine())) {
+ reportBug(bug, d);
+ }
+ clearBugs();
+ }
+
+ public void reportBug(BugInstance bug, Data d) {
+ bug.setPriority(d.priority);
+ bug.addSourceLine(d.primarySource);
+ HashSet<Integer> lines = new HashSet<Integer>();
+ lines.add(d.primarySource.getStartLine());
+ d.allSource.remove(d.primarySource);
+ for (SourceLineAnnotation source : d.allSource) {
+ if (lines.add(source.getStartLine())) {
bug.addSourceLine(source);
bug.describe(SourceLineAnnotation.ROLE_ANOTHER_INSTANCE);
- } else if (false && SystemProperties.ASSERTIONS_ENABLED) {
+ } /* else if (false && SystemProperties.ASSERTIONS_ENABLED) {
AnalysisContext.logError("Skipping duplicated source warning for " + bug.getInstanceHash() + " " + bug.getMessage());
- }
- reporter.reportBug(bug);
+ }*/
}
- clearBugs();
+ reporter.reportBug(bug);
}
/**
diff --git a/src/java/edu/umd/cs/findbugs/BugAnnotation.java b/src/java/edu/umd/cs/findbugs/BugAnnotation.java
index f15bf35..dc3515f 100644
--- a/src/java/edu/umd/cs/findbugs/BugAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/BugAnnotation.java
@@ -23,7 +23,7 @@ import java.io.Serializable;
/**
* An object providing context information about a particular BugInstance.
- *
+ *
* @author David Hovemeyer
* @see BugInstance
*/
@@ -37,7 +37,7 @@ public interface BugAnnotation extends Comparable<BugAnnotation>, XMLWriteableWi
/**
* Accept a BugAnnotationVisitor.
- *
+ *
* @param visitor
* the visitor to accept
*/
@@ -47,7 +47,7 @@ public interface BugAnnotation extends Comparable<BugAnnotation>, XMLWriteableWi
* Format the annotation as a String. The given key specifies additional
* information about how the annotation should be formatted. If the key is
* empty, then the "default" format will be used.
- *
+ *
* @param key
* how the annotation should be formatted
* @param primaryClass
@@ -71,7 +71,7 @@ public interface BugAnnotation extends Comparable<BugAnnotation>, XMLWriteableWi
/**
* Is this annotation used to compute instance hashes or match bug instances
* across versions
- *
+ *
* @return true if significant
*/
public boolean isSignificant();
@@ -79,4 +79,3 @@ public interface BugAnnotation extends Comparable<BugAnnotation>, XMLWriteableWi
public String toString(ClassAnnotation primaryClass);
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/BugAnnotationUtil.java b/src/java/edu/umd/cs/findbugs/BugAnnotationUtil.java
index 648954f..8beec7e 100644
--- a/src/java/edu/umd/cs/findbugs/BugAnnotationUtil.java
+++ b/src/java/edu/umd/cs/findbugs/BugAnnotationUtil.java
@@ -25,13 +25,13 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* Utility methods for BugAnnotation classes.
- *
+ *
* @author David Hovemeyer
*/
public abstract class BugAnnotationUtil {
/**
* Write a BugAnnotation as XML.
- *
+ *
* @param xmlOutput
* the XMLOutput
* @param elementName
@@ -48,13 +48,15 @@ public abstract class BugAnnotationUtil {
XMLAttributeList attributeList, boolean addMessages) throws IOException {
SourceLineAnnotation src = null;
- if (annotation instanceof BugAnnotationWithSourceLines)
+ if (annotation instanceof BugAnnotationWithSourceLines) {
src = ((BugAnnotationWithSourceLines) annotation).getSourceLines();
+ }
if (addMessages || src != null) {
xmlOutput.openTag(elementName, attributeList);
- if (src != null)
+ if (src != null) {
src.writeXML(xmlOutput, addMessages, false);
+ }
if (addMessages) {
xmlOutput.openTag(BugAnnotation.MESSAGE_TAG);
xmlOutput.writeText(annotation.toString());
diff --git a/src/java/edu/umd/cs/findbugs/BugAnnotationVisitor.java b/src/java/edu/umd/cs/findbugs/BugAnnotationVisitor.java
index 18e050c..3e290cc 100644
--- a/src/java/edu/umd/cs/findbugs/BugAnnotationVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/BugAnnotationVisitor.java
@@ -37,4 +37,3 @@ public interface BugAnnotationVisitor {
public void visitSourceLineAnnotation(SourceLineAnnotation sourceLineAnnotation);
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/BugAnnotationWithSourceLines.java b/src/java/edu/umd/cs/findbugs/BugAnnotationWithSourceLines.java
index c106a36..3cfaebf 100644
--- a/src/java/edu/umd/cs/findbugs/BugAnnotationWithSourceLines.java
+++ b/src/java/edu/umd/cs/findbugs/BugAnnotationWithSourceLines.java
@@ -63,7 +63,7 @@ public abstract class BugAnnotationWithSourceLines implements BugAnnotation {
/**
* Get the SourceLineAnnotation describing the source lines where the method
* is defined.
- *
+ *
* @return the SourceLineAnnotation, or null if there is no source
* information for this package element
*/
@@ -71,6 +71,7 @@ public abstract class BugAnnotationWithSourceLines implements BugAnnotation {
return sourceLines;
}
+ @Override
public String toString(ClassAnnotation primaryClass) {
return toString();
}
diff --git a/src/java/edu/umd/cs/findbugs/BugCategory.java b/src/java/edu/umd/cs/findbugs/BugCategory.java
index 6f7b0ea..2217803 100644
--- a/src/java/edu/umd/cs/findbugs/BugCategory.java
+++ b/src/java/edu/umd/cs/findbugs/BugCategory.java
@@ -31,12 +31,12 @@ public class BugCategory implements Comparable<BugCategory> {
private String abbrev;
private String detailText;
-
+
private boolean hidden;
/**
* Constructor.
- *
+ *
* @param category
* the category
* @param shortDescription
@@ -56,7 +56,7 @@ public class BugCategory implements Comparable<BugCategory> {
/**
* Constructor.
- *
+ *
* @param category
* the category
* @param shortDescription
@@ -68,11 +68,9 @@ public class BugCategory implements Comparable<BugCategory> {
/**
* Constructor.
- *
+ *
* @param category
* the category
- * @param shortDescription
- * short (a word or three) description of the bug species
*/
public BugCategory(String category) {
this(category, null, null, null);
@@ -114,7 +112,7 @@ public class BugCategory implements Comparable<BugCategory> {
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
-
+
/**
* Set the abbreviation (typically a single capital letter)
*/
@@ -130,6 +128,7 @@ public class BugCategory implements Comparable<BugCategory> {
this.detailText = detailText;
}
+ @Override
public int compareTo(BugCategory other) {
return category.compareTo(other.category);
}
@@ -141,8 +140,9 @@ public class BugCategory implements Comparable<BugCategory> {
@Override
public boolean equals(Object o) {
- if (!(o instanceof BugCategory))
+ if (!(o instanceof BugCategory)) {
return false;
+ }
BugCategory other = (BugCategory) o;
return category.equals(other.category);
}
diff --git a/src/java/edu/umd/cs/findbugs/BugCode.java b/src/java/edu/umd/cs/findbugs/BugCode.java
index 97aadbf..3e5fdf0 100644
--- a/src/java/edu/umd/cs/findbugs/BugCode.java
+++ b/src/java/edu/umd/cs/findbugs/BugCode.java
@@ -23,7 +23,7 @@ package edu.umd.cs.findbugs;
* A BugCode is an abbreviation that is shared among some number of BugPatterns.
* For example, the code "HE" is shared by all of the BugPatterns that represent
* hashcode/equals violations.
- *
+ *
* @author David Hovemeyer
* @see BugPattern
*/
@@ -36,7 +36,7 @@ public class BugCode implements Comparable<BugCode> {
/**
* Constructor.
- *
+ *
* @param abbrev
* the abbreviation for the bug code
* @param description
@@ -84,6 +84,7 @@ public class BugCode implements Comparable<BugCode> {
return cweid;
}
+ @Override
public int compareTo(BugCode o) {
return abbrev.compareTo(o.abbrev);
}
diff --git a/src/java/edu/umd/cs/findbugs/BugCollection.java b/src/java/edu/umd/cs/findbugs/BugCollection.java
index 202e7e1..889959c 100644
--- a/src/java/edu/umd/cs/findbugs/BugCollection.java
+++ b/src/java/edu/umd/cs/findbugs/BugCollection.java
@@ -48,21 +48,21 @@ public interface BugCollection extends Iterable<BugInstance> {
static final String ERRORS_ELEMENT_NAME = "Errors";
static final String ANALYSIS_ERROR_ELEMENT_NAME = "AnalysisError"; // 0.8.6
- // and
- // earlier
+ // and
+ // earlier
static final String ERROR_ELEMENT_NAME = "Error"; // 0.8.7 and later
static final String ERROR_MESSAGE_ELEMENT_NAME = "ErrorMessage"; // 0.8.7
- // and
- // later
+ // and
+ // later
static final String ERROR_EXCEPTION_ELEMENT_NAME = "Exception"; // 0.8.7 and
- // later
+ // later
static final String ERROR_STACK_TRACE_ELEMENT_NAME = "StackTrace"; // 0.8.7
- // and
- // later
+ // and
+ // later
static final String MISSING_CLASS_ELEMENT_NAME = "MissingClass";
@@ -71,7 +71,7 @@ public interface BugCollection extends Iterable<BugInstance> {
static final String APP_CLASS_ELEMENT_NAME = "AppClass";
static final String CLASS_HASHES_ELEMENT_NAME = "ClassHashes"; // 0.9.2 and
- // later
+ // later
static final String HISTORY_ELEMENT_NAME = "History"; // 0.9.2 and later
@@ -330,6 +330,7 @@ public interface BugCollection extends Iterable<BugInstance> {
/**
* Return an Iterator over all the BugInstance objects in the BugCollection.
*/
+ @Override
public Iterator<BugInstance> iterator();
/**
diff --git a/src/java/edu/umd/cs/findbugs/BugCollectionBugReporter.java b/src/java/edu/umd/cs/findbugs/BugCollectionBugReporter.java
index db5833c..641cd59 100644
--- a/src/java/edu/umd/cs/findbugs/BugCollectionBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/BugCollectionBugReporter.java
@@ -50,11 +50,13 @@ public class BugCollectionBugReporter extends TextUIBugReporter implements Debug
return project;
}
+ @Override
public @Nonnull
BugCollection getBugCollection() {
return bugCollection;
}
+ @Override
public void observeClass(ClassDescriptor classDescriptor) {
}
@@ -91,10 +93,12 @@ public class BugCollectionBugReporter extends TextUIBugReporter implements Debug
@Override
public void doReportBug(BugInstance bugInstance) {
- if (VERIFY_INTEGRITY)
+ if (VERIFY_INTEGRITY) {
checkBugInstance(bugInstance);
- if (bugCollection.add(bugInstance))
+ }
+ if (bugCollection.add(bugInstance)) {
notifyObservers(bugInstance);
+ }
}
/*
@@ -112,10 +116,12 @@ public class BugCollectionBugReporter extends TextUIBugReporter implements Debug
*
* @see edu.umd.cs.findbugs.BugReporter#finish()
*/
+ @Override
public void finish() {
- bugCollection.bugsPopulated();
- if (writer != null)
+ bugCollection.bugsPopulated();
+ if (writer != null) {
writer.flush();
+ }
}
/**
@@ -138,4 +144,3 @@ public class BugCollectionBugReporter extends TextUIBugReporter implements Debug
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/BugDesignation.java b/src/java/edu/umd/cs/findbugs/BugDesignation.java
index 5915e25..281078a 100644
--- a/src/java/edu/umd/cs/findbugs/BugDesignation.java
+++ b/src/java/edu/umd/cs/findbugs/BugDesignation.java
@@ -52,10 +52,12 @@ public class BugDesignation implements XMLWriteable, Serializable, Comparable<Bu
@Override
public String toString() {
String result = designation;
- if (user != null)
+ if (user != null) {
result += " by " + user;
- if (annotationText != null && annotationText.length() > 0)
+ }
+ if (annotationText != null && annotationText.length() > 0) {
result += " : " + annotationText;
+ }
return result;
}
@@ -69,16 +71,17 @@ public class BugDesignation implements XMLWriteable, Serializable, Comparable<Bu
setDirty(false);
}
public void setDirty(boolean dirty) {
- if (this.dirty == dirty)
+ if (this.dirty == dirty) {
return;
+ }
this.dirty = dirty;
-// if (dirty) {
-// System.out.println("Setting dirty bit");
-// new RuntimeException("Setting dirty bit").printStackTrace(System.out);
-// } else {
-// System.out.println("Clearing dirty bit");
-// new RuntimeException("Clearing dirty bit").printStackTrace(System.out);
-// }
+ // if (dirty) {
+ // System.out.println("Setting dirty bit");
+ // new RuntimeException("Setting dirty bit").printStackTrace(System.out);
+ // } else {
+ // System.out.println("Clearing dirty bit");
+ // new RuntimeException("Clearing dirty bit").printStackTrace(System.out);
+ // }
}
private @javax.annotation.CheckForNull
@@ -144,8 +147,9 @@ public class BugDesignation implements XMLWriteable, Serializable, Comparable<Bu
assert false;
designationKey = null;
}
- if (designation.equals(designationKey))
+ if (designation.equals(designationKey)) {
return;
+ }
setDirty(true);
timestamp = System.currentTimeMillis();
designation = (designationKey != null ? designationKey : UNCLASSIFIED);
@@ -167,8 +171,9 @@ public class BugDesignation implements XMLWriteable, Serializable, Comparable<Bu
public void setTimestamp(long ts) {
if (timestamp != ts) {
timestamp = ts;
- if (false && !hasAnnotationText() && !hasDesignationKey())
+ if (false && !hasAnnotationText() && !hasDesignationKey()) {
new RuntimeException("Setting timestamp on bug designation without annotation or designation").printStackTrace(System.out);
+ }
setDirty(true);
}
}
@@ -184,30 +189,37 @@ public class BugDesignation implements XMLWriteable, Serializable, Comparable<Bu
@Nonnull
public String getNonnullAnnotationText() {
- if (annotationText == null)
+ if (annotationText == null) {
return "";
+ }
return annotationText;
}
public void setAnnotationText(String s) {
- if (s.equals(annotationText))
+ if (s.equals(annotationText)) {
return;
+ }
setDirty(true);
annotationText = s;
timestamp = System.currentTimeMillis();
}
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
XMLAttributeList attributeList = new XMLAttributeList();
// all three of these xml attributes are optional
- if (hasDesignationKey())
+ if (hasDesignationKey()) {
attributeList.addAttribute("designation", designation);
- if (user != null && !"".equals(user))
+ }
+ if (user != null && !"".equals(user)) {
attributeList.addAttribute("user", user);
- if (dirty)
+ }
+ if (dirty) {
attributeList.addAttribute("needsSync", "true");
- if (timestamp > 0)
+ }
+ if (timestamp > 0) {
attributeList.addAttribute("timestamp", String.valueOf(timestamp));
+ }
if ((annotationText != null && !"".equals(annotationText))) {
xmlOutput.openTag("UserAnnotation", attributeList);
@@ -223,8 +235,9 @@ public class BugDesignation implements XMLWriteable, Serializable, Comparable<Bu
* other
*/
public void merge(@CheckForNull BugDesignation other) {
- if (other == null)
+ if (other == null) {
return;
+ }
boolean changed = false;
if ((annotationText == null || annotationText.length() == 0) && other.annotationText != null
&& other.annotationText.length() > 0) {
@@ -238,7 +251,9 @@ public class BugDesignation implements XMLWriteable, Serializable, Comparable<Bu
changed = true;
}
if (!changed)
+ {
return; // if no changes don't even try to copy user or timestamp
+ }
if ((user == null || user.length() == 0) && other.user != null && other.user.length() > 0) {
user = other.user;
@@ -251,38 +266,47 @@ public class BugDesignation implements XMLWriteable, Serializable, Comparable<Bu
@Override
public int hashCode() {
int hash = (int) this.timestamp;
- if (user != null)
+ if (user != null) {
hash += user.hashCode();
+ }
hash += designation.hashCode();
- if (annotationText != null)
+ if (annotationText != null) {
hash += annotationText.hashCode();
+ }
return hash;
}
@Override
public boolean equals(Object o) {
- if (!(o instanceof BugDesignation))
+ if (!(o instanceof BugDesignation)) {
return false;
+ }
return this.compareTo((BugDesignation) o) == 0;
}
+ @Override
public int compareTo(BugDesignation o) {
- if (this == o)
+ if (this == o) {
return 0;
+ }
int result = Util.compare(o.timestamp, this.timestamp);
- if (result != 0)
+ if (result != 0) {
return result;
+ }
result = Util.nullSafeCompareTo(this.user, o.user);
- if (result != 0)
+ if (result != 0) {
return result;
+ }
result = this.designation.compareTo(o.designation);
- if (result != 0)
+ if (result != 0) {
return result;
+ }
result = Util.nullSafeCompareTo(this.annotationText, o.annotationText);
- if (result != 0)
+ if (result != 0) {
return result;
+ }
return 0;
diff --git a/src/java/edu/umd/cs/findbugs/BugInstance.java b/src/java/edu/umd/cs/findbugs/BugInstance.java
index da6c9ac..d32ae07 100644
--- a/src/java/edu/umd/cs/findbugs/BugInstance.java
+++ b/src/java/edu/umd/cs/findbugs/BugInstance.java
@@ -19,6 +19,8 @@
package edu.umd.cs.findbugs;
+import static java.util.Objects.requireNonNull;
+
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
@@ -28,6 +30,7 @@ import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.IdentityHashMap;
@@ -113,6 +116,7 @@ import edu.umd.cs.findbugs.xml.XMLWriteable;
* @see BugAnnotation
*/
public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Serializable, Cloneable {
+
private static final long serialVersionUID = 1L;
private final String type;
@@ -139,16 +143,16 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@CheckForNull
private DetectorFactory detectorFactory;
- private final AtomicReference<XmlProps> xmlProps = new AtomicReference<XmlProps>();
+ private final AtomicReference<XmlProps> xmlProps;
/*
* The following fields are used for tracking Bug instances across multiple
* versions of software. They are meaningless in a BugCollection for just
* one version of software.
*/
- private long firstVersion = 0;
+ private long firstVersion;
- private long lastVersion = -1;
+ private long lastVersion;
private boolean introducedByChangeOfExistingClass;
@@ -160,22 +164,16 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
*/
private static final int INVALID_HASH_CODE = 0;
+ private static final String ELEMENT_NAME = "BugInstance";
+
/**
* This value is used to indicate whether BugInstances should be
* reprioritized very low, when the BugPattern is marked as experimental
*/
- private static boolean adjustExperimental = false;
+ private static boolean adjustExperimental;
private static Set<String> missingBugTypes = Collections.synchronizedSet(new HashSet<String>());
- public static DateFormat firstSeenXMLFormat() {
- return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.ENGLISH);
- }
-
- private boolean isFakeBugType(String type) {
- return "MISSING".equals(type) || "FOUND".equals(type);
- }
-
public static class NoSuchBugPattern extends IllegalArgumentException {
public final String type;
public NoSuchBugPattern(String type) {
@@ -183,6 +181,7 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
this.type = type;
}
}
+
/**
* Constructor.
*
@@ -194,6 +193,8 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public BugInstance(String type, int priority) {
this.type = type.intern();
this.priority = priority;
+ lastVersion = -1;
+ xmlProps = new AtomicReference<XmlProps>();
annotationList = new ArrayList<BugAnnotation>(4);
cachedHashCode = INVALID_HASH_CODE;
@@ -203,13 +204,25 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
String msg = "Can't find definition of bug type " + type;
AnalysisContext.logError(msg, new NoSuchBugPattern(type));
}
- } else
+ } else {
this.priority += p.getPriorityAdjustment();
- if (adjustExperimental && isExperimental())
+ }
+ if (adjustExperimental && isExperimental()) {
this.priority = Priorities.EXP_PRIORITY;
+ }
boundPriority();
}
+ public static DateFormat firstSeenXMLFormat() {
+ return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.ENGLISH);
+ }
+
+ /*
+ private boolean isFakeBugType(String type) {
+ return "MISSING".equals(type) || "FOUND".equals(type);
+ }
+ */
+
private void boundPriority() {
priority = boundedPriority(priority);
}
@@ -217,7 +230,6 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@Override
public Object clone() {
BugInstance dup;
-
try {
dup = (BugInstance) super.clone();
@@ -267,10 +279,10 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
this.priority += factory.getPriorityAdjustment();
boundPriority();
BugPattern bugPattern = getBugPattern();
- if (SystemProperties.ASSERTIONS_ENABLED && !bugPattern.getCategory().equals("EXPERIMENTAL")
+ if (SystemProperties.ASSERTIONS_ENABLED && !"EXPERIMENTAL".equals(bugPattern.getCategory())
&& !factory.getReportedBugPatterns().contains(bugPattern)) {
AnalysisContext.logError(factory.getShortName() + " doesn't note that it reports "
- + bugPattern + " in category " + bugPattern.getCategory());
+ + bugPattern + " in category " + bugPattern.getCategory());
}
}
}
@@ -317,15 +329,16 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
/**
* Get the BugPattern.
*/
- public @Nonnull
- BugPattern getBugPattern() {
+ public @Nonnull BugPattern getBugPattern() {
BugPattern result = DetectorFactoryCollection.instance().lookupBugPattern(getType());
- if (result != null)
+ if (result != null) {
return result;
+ }
AnalysisContext.logError("Unable to find description of bug pattern " + getType());
result = DetectorFactoryCollection.instance().lookupBugPattern("UNKNOWN");
- if (result != null)
+ if (result != null) {
return result;
+ }
return BugPattern.REALLY_UNKNOWN;
}
@@ -373,27 +386,19 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
// first, get the priority
int value = this.getPriority();
String priorityString;
- if (value == Priorities.HIGH_PRIORITY)
+ if (value == Priorities.HIGH_PRIORITY) {
priorityString = edu.umd.cs.findbugs.L10N.getLocalString("sort.priority_high", "High");
- else if (value == Priorities.NORMAL_PRIORITY)
+ } else if (value == Priorities.NORMAL_PRIORITY) {
priorityString = edu.umd.cs.findbugs.L10N.getLocalString("sort.priority_normal", "Medium");
- else if (value == Priorities.LOW_PRIORITY)
+ } else if (value == Priorities.LOW_PRIORITY) {
priorityString = edu.umd.cs.findbugs.L10N.getLocalString("sort.priority_low", "Low");
- else if (value == Priorities.EXP_PRIORITY)
+ } else if (value == Priorities.EXP_PRIORITY) {
priorityString = edu.umd.cs.findbugs.L10N.getLocalString("sort.priority_experimental", "Experimental");
- else
+ }
+ else {
priorityString = edu.umd.cs.findbugs.L10N.getLocalString("sort.priority_ignore", "Ignore"); // This
- // probably
- // shouldn't
- // ever
- // happen,
- // but
- // what
- // the
- // hell,
- // let's
- // be
- // complete
+ }
+ // probably shouldn't ever happen, but what the hell, let's be complete
return priorityString;
}
@@ -441,8 +446,17 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
}
/**
+ * Get the primary type annotation, which indicates where the bug occurs.
+ */
+ @CheckForNull
+ public TypeAnnotation getPrimaryType() {
+ return findPrimaryAnnotationOfType(TypeAnnotation.class);
+ }
+
+ /**
* Get the primary method annotation, which indicates where the bug occurs.
*/
+ @CheckForNull
public MethodAnnotation getPrimaryMethod() {
return findPrimaryAnnotationOfType(MethodAnnotation.class);
}
@@ -450,6 +464,7 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
/**
* Get the primary method annotation, which indicates where the bug occurs.
*/
+ @CheckForNull
public FieldAnnotation getPrimaryField() {
return findPrimaryAnnotationOfType(FieldAnnotation.class);
}
@@ -457,11 +472,13 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@Nonnull
public BugInstance lowerPriorityIfDeprecated() {
MethodAnnotation m = getPrimaryMethod();
- if (m != null && XFactory.createXMethod(m).isDeprecated())
+ if (m != null && XFactory.createXMethod(m).isDeprecated()) {
lowerPriority();
+ }
FieldAnnotation f = getPrimaryField();
- if (f != null && XFactory.createXField(f).isDeprecated())
+ if (f != null && XFactory.createXField(f).isDeprecated()) {
lowerPriority();
+ }
return this;
}
@@ -474,24 +491,28 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
* @return the first matching BugAnnotation of the given type, or null if
* there is no such BugAnnotation
*/
+ @CheckForNull
private <T extends BugAnnotation> T findPrimaryAnnotationOfType(Class<T> cls) {
T firstMatch = null;
for (Iterator<BugAnnotation> i = annotationIterator(); i.hasNext();) {
BugAnnotation annotation = i.next();
if (cls.isAssignableFrom(annotation.getClass())) {
- if (annotation.getDescription().endsWith("DEFAULT"))
+ if (annotation.getDescription().endsWith("DEFAULT")) {
return cls.cast(annotation);
- else if (firstMatch == null)
+ } else if (firstMatch == null) {
firstMatch = cls.cast(annotation);
+ }
}
}
return firstMatch;
}
public LocalVariableAnnotation getPrimaryLocalVariableAnnotation() {
- for (BugAnnotation annotation : annotationList)
- if (annotation instanceof LocalVariableAnnotation)
+ for (BugAnnotation annotation : annotationList) {
+ if (annotation instanceof LocalVariableAnnotation) {
return (LocalVariableAnnotation) annotation;
+ }
+ }
return null;
}
@@ -501,35 +522,54 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
*
* @return the source line annotation
*/
+ @Nonnull
public SourceLineAnnotation getPrimarySourceLineAnnotation() {
// Highest priority: return the first top level source line annotation
for (BugAnnotation annotation : annotationList) {
if (annotation instanceof SourceLineAnnotation
- && annotation.getDescription().equals(SourceLineAnnotation.DEFAULT_ROLE)
- && !((SourceLineAnnotation) annotation).isUnknown())
-
+ && SourceLineAnnotation.DEFAULT_ROLE.equals(annotation.getDescription())
+ && !((SourceLineAnnotation) annotation).isUnknown()) {
return (SourceLineAnnotation) annotation;
+ }
}
for (BugAnnotation annotation : annotationList) {
- if (annotation instanceof SourceLineAnnotation && !((SourceLineAnnotation) annotation).isUnknown())
-
+ if (annotation instanceof SourceLineAnnotation && !((SourceLineAnnotation) annotation).isUnknown()) {
return (SourceLineAnnotation) annotation;
+ }
}
// Next: Try primary method, primary field, primary class
SourceLineAnnotation srcLine;
- if ((srcLine = inspectPackageMemberSourceLines(getPrimaryMethod())) != null)
+ if ((srcLine = inspectPackageMemberSourceLines(getPrimaryMethod())) != null) {
return srcLine;
- if ((srcLine = inspectPackageMemberSourceLines(getPrimaryField())) != null)
+ }
+ if ((srcLine = inspectPackageMemberSourceLines(getPrimaryField())) != null) {
return srcLine;
- if ((srcLine = inspectPackageMemberSourceLines(getPrimaryClass())) != null)
+ }
+ if ((srcLine = inspectPackageMemberSourceLines(getPrimaryClass())) != null) {
return srcLine;
+ }
// Last resort: throw exception
throw new IllegalStateException("BugInstance for " + getType()
+ " must contain at least one class, method, or field annotation");
}
+ public Collection<? extends SourceLineAnnotation> getAnotherInstanceSourceLineAnnotations() {
+ // Highest priority: return the first top level source line annotation
+ Collection<SourceLineAnnotation> result = new ArrayList<SourceLineAnnotation>();
+ for (BugAnnotation annotation : annotationList) {
+ if (annotation instanceof SourceLineAnnotation
+ && SourceLineAnnotation.ROLE_ANOTHER_INSTANCE.equals(annotation.getDescription())
+ && !((SourceLineAnnotation) annotation).isUnknown()) {
+ result.add((SourceLineAnnotation) annotation);
+ }
+ }
+
+ return result;
+ }
+
+
public String getInstanceKey() {
String newValue = getInstanceKeyNew();
return newValue;
@@ -537,12 +577,13 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
private String getInstanceKeyNew() {
StringBuilder buf = new StringBuilder(type);
- for (BugAnnotation annotation : annotationList)
+ for (BugAnnotation annotation : annotationList) {
if (annotation.isSignificant() || annotation instanceof IntAnnotation
|| annotation instanceof LocalVariableAnnotation) {
buf.append(":");
buf.append(annotation.format("hash", null));
}
+ }
return buf.toString();
}
@@ -576,16 +617,14 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
/** Get the first bug annotation with the specified class and role; return null if no
* such annotation exists;
- * @param role
- * @return
*/
public @CheckForNull <A extends BugAnnotation> A getAnnotationWithRole(Class<A> c, String role) {
for(BugAnnotation a : annotationList) {
- if (c.isInstance(a) && Util.nullSafeEquals(role, a.getDescription()))
+ if (c.isInstance(a) && Util.nullSafeEquals(role, a.getDescription())) {
return c.cast(a);
+ }
}
return null;
-
}
/**
@@ -624,10 +663,12 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@Deprecated
@Nullable
public BugDesignation getUserDesignation() {
- if (userDesignation == null)
+ if (userDesignation == null) {
return null;
- if (!userDesignation.hasAnnotationText() && !userDesignation.hasDesignationKey())
+ }
+ if (!userDesignation.hasAnnotationText() && !userDesignation.hasDesignationKey()) {
return null;
+ }
return userDesignation;
}
@@ -641,8 +682,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@Deprecated
@Nonnull
public BugDesignation getNonnullUserDesignation() {
- if (userDesignation == null)
+ if (userDesignation == null) {
userDesignation = new BugDesignation();
+ }
return userDesignation;
}
@@ -660,21 +702,23 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
*/
@Nonnull
public String getUserDesignationKey() {
- if (userDesignation == null)
+ if (userDesignation == null) {
return BugDesignation.UNCLASSIFIED;
+ }
return userDesignation.getDesignationKey();
}
- public @CheckForNull
- String getUserName() {
- if (userDesignation == null)
+ public @CheckForNull String getUserName() {
+ if (userDesignation == null) {
return null;
+ }
return userDesignation.getUser();
}
public long getUserTimestamp() {
- if (userDesignation == null)
+ if (userDesignation == null) {
return Long.MAX_VALUE;
+ }
return userDesignation.getTimestamp();
}
@@ -682,30 +726,21 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
return I18N.instance().getUserDesignationKeys(true).indexOf(getUserDesignationKey());
}
- /**
- * @param key
- * @param bugCollection
- * TODO
- */
public void setUserDesignationKey(String key, @CheckForNull BugCollection bugCollection) {
BugDesignation userDesignation = key.length() > 0 ? getNonnullUserDesignation() : getUserDesignation();
- if (userDesignation == null)
+ if (userDesignation == null) {
return;
- if (userDesignation.getDesignationKey().equals(key))
+ }
+ if (userDesignation.getDesignationKey().equals(key)) {
return;
+ }
userDesignation.setDesignationKey(key);
Cloud plugin = bugCollection != null ? bugCollection.getCloud() : null;
- if (plugin != null)
+ if (plugin != null) {
plugin.storeUserAnnotation(this);
+ }
}
- /**
- * s
- *
- * @param index
- * @param bugCollection
- * TODO
- */
public void setUserDesignationKeyIndex(int index, @CheckForNull BugCollection bugCollection) {
setUserDesignationKey(I18N.instance().getUserDesignationKey(index), bugCollection);
}
@@ -715,20 +750,21 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
*
* @param annotationText
* the user annotation text
- * @param bugCollection
- * TODO
*/
public void setAnnotationText(String annotationText, @CheckForNull BugCollection bugCollection) {
BugDesignation u = annotationText.length() > 0 ? getNonnullUserDesignation() : getUserDesignation();
- if (u == null)
+ if (u == null) {
return;
+ }
String existingText = u.getNonnullAnnotationText();
- if (existingText.equals(annotationText))
+ if (existingText.equals(annotationText)) {
return;
+ }
u.setAnnotationText(annotationText);
Cloud plugin = bugCollection != null ? bugCollection.getCloud() : null;
- if (plugin != null)
+ if (plugin != null) {
plugin.storeUserAnnotation(this);
+ }
}
/**
@@ -739,11 +775,13 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@Nonnull
public String getAnnotationText() {
BugDesignation userDesignation = this.userDesignation;
- if (userDesignation == null)
+ if (userDesignation == null) {
return "";
+ }
String s = userDesignation.getAnnotationText();
- if (s == null)
+ if (s == null) {
return "";
+ }
return s;
}
@@ -759,17 +797,20 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public void setUserAnnotationDirty(boolean dirty) {
BugDesignation userDesignation = getUserDesignation();
- if (userDesignation == null)
+ if (userDesignation == null) {
return;
+ }
userDesignation.setDirty(dirty);
}
public boolean isUserAnnotationDirty() {
BugDesignation userDesignation = getUserDesignation();
- if (userDesignation == null)
+ if (userDesignation == null) {
return false;
+ }
return userDesignation.isDirty();
}
+
/**
* Determine whether or not the annotation text contains the given word.
*
@@ -801,17 +842,19 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public XmlProps getXmlProps() {
XmlProps props = xmlProps.get();
- if (props != null)
+ if (props != null) {
return props;
+ }
props = new XmlProps();
- while (xmlProps.get() == null)
+ while (xmlProps.get() == null) {
xmlProps.compareAndSet(null, props);
+ }
return xmlProps.get();
}
public boolean hasSomeUserAnnotation() {
- return !getAnnotationText().equals("")
+ return !"".equals(getAnnotationText())
|| !getUserDesignationKey().equals(BugDesignation.UNCLASSIFIED);
}
@@ -826,38 +869,28 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
private boolean removed;
- /*
- * (non-Javadoc)
- *
- * @see java.util.Iterator#hasNext()
- */
+ @Override
public boolean hasNext() {
return findNext() != null;
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.Iterator#next()
- */
+ @Override
public BugProperty next() {
BugProperty next = findNext();
- if (next == null)
+ if (next == null) {
throw new NoSuchElementException();
+ }
prev = cur;
cur = next;
removed = false;
return cur;
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.Iterator#remove()
- */
+ @Override
public void remove() {
- if (cur == null || removed)
+ if (cur == null || removed) {
throw new IllegalStateException();
+ }
if (prev == null) {
propertyListHead = cur.getNext();
} else {
@@ -872,7 +905,6 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
private BugProperty findNext() {
return cur == null ? propertyListHead : cur.getNext();
}
-
}
/**
@@ -946,8 +978,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
BugProperty prop = propertyListHead;
while (prop != null) {
- if (prop.getName().equals(name))
+ if (prop.getName().equals(name)) {
break;
+ }
prop = prop.getNext();
}
@@ -967,8 +1000,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
BugProperty prop = propertyListHead;
while (prop != null) {
- if (prop.getName().equals(name))
+ if (prop.getName().equals(name)) {
break;
+ }
prev = prop;
prop = prop.getNext();
}
@@ -1053,18 +1087,21 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
addClass(visitor);
XMethod m = visitor.getXMethod();
addMethod(visitor);
- if (m.isSynthetic())
+ if (m.isSynthetic()) {
foundInSyntheticMethod();
+ }
return this;
}
public void foundInSyntheticMethod() {
- if (annotationList.size() != 2)
+ if (annotationList.size() != 2) {
return;
+ }
priority+=2;
setProperty("FOUND_IN_SYNTHETIC_METHOD", "true");
- if (SystemProperties.ASSERTIONS_ENABLED && AnalysisContext.analyzingApplicationClass() && priority <= 3)
+ if (SystemProperties.ASSERTIONS_ENABLED && AnalysisContext.analyzingApplicationClass() && priority <= 3) {
AnalysisContext.logError("Adding error " + getBugPattern().getType() + " to synthetic method " + getPrimaryMethod());
+ }
}
/**
@@ -1094,8 +1131,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public BugInstance addClassAndMethod(MethodGen methodGen, String sourceFile) {
addClass(methodGen.getClassName());
addMethod(methodGen, sourceFile);
- if (BCELUtil.isSynthetic(methodGen))
+ if (BCELUtil.isSynthetic(methodGen)) {
foundInSyntheticMethod();
+ }
return this;
}
@@ -1112,9 +1150,10 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public BugInstance addClassAndMethod(JavaClass javaClass, Method method) {
addClass(javaClass.getClassName());
addMethod(javaClass, method);
-
- if (BCELUtil.isSynthetic(method))
+
+ if (BCELUtil.isSynthetic(method)) {
foundInSyntheticMethod();
+ }
return this;
}
@@ -1284,18 +1323,17 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
Set<XMethod> targets = Hierarchy2.resolveVirtualMethodCallTargets(expectedClass, "equals", "(Ljava/lang/Object;)Z",
false, false);
addEqualsMethodUsed(targets);
-
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
-
return this;
}
@Nonnull
public BugInstance addEqualsMethodUsed(@CheckForNull Collection<XMethod> equalsMethods) {
- if (equalsMethods == null)
+ if (equalsMethods == null) {
return this;
+ }
if (equalsMethods.size() < 5) {
for (XMethod m : equalsMethods) {
addMethod(m).describe(MethodAnnotation.METHOD_EQUALS_USED);
@@ -1303,7 +1341,6 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
} else {
addMethod(equalsMethods.iterator().next()).describe(MethodAnnotation.METHOD_EQUALS_USED);
}
-
return this;
}
@@ -1405,8 +1442,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
*/
@Nonnull
public BugInstance addOptionalField(@CheckForNull XField xfield) {
- if (xfield == null)
+ if (xfield == null) {
return this;
+ }
return addField(xfield.getClassName(), xfield.getName(), xfield.getSignature(), xfield.isStatic());
}
@@ -1484,8 +1522,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public BugInstance addOptionalLocalVariable(DismantleBytecode dbc, OpcodeStack.Item item) {
int register = item.getRegisterNumber();
- if (register >= 0)
+ if (register >= 0) {
this.add(LocalVariableAnnotation.getLocalVariableAnnotation(dbc.getMethod(), register, dbc.getPC() - 1, dbc.getPC()));
+ }
return this;
}
@@ -1626,6 +1665,7 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public BugInstance addCalledMethod(XMethod m) {
return addMethod(m).describe(MethodAnnotation.METHOD_CALLED);
}
+
/**
* Add a method annotation.
*
@@ -1697,8 +1737,8 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
/**
* Add a MethodAnnotation from an MethodDescriptor.
*
- * @param xmethod
- * the XMethod
+ * @param method
+ * the method
* @return this object
*/
@Nonnull
@@ -1706,6 +1746,7 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
addMethod(MethodAnnotation.fromMethodDescriptor(method));
return this;
}
+
/**
* Add a method annotation. If this is the first method annotation added, it
* becomes the primary method annotation.
@@ -1739,7 +1780,7 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
return this;
}
- /*
+ /**
* Add an annotation about a parameter
*
* @param index parameter index, starting from 0
@@ -1813,8 +1854,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public BugInstance addSourceLine(BytecodeScanningDetector visitor, int pc) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(visitor.getClassContext(),
visitor, pc);
- if (sourceLineAnnotation != null)
+ if (sourceLineAnnotation != null) {
add(sourceLineAnnotation);
+ }
return this;
}
@@ -1835,8 +1877,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@Nonnull
public BugInstance addSourceLine(ClassContext classContext, PreorderVisitor visitor, int pc) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, visitor, pc);
- if (sourceLineAnnotation != null)
+ if (sourceLineAnnotation != null) {
add(sourceLineAnnotation);
+ }
return this;
}
@@ -1860,8 +1903,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@Nonnull InstructionHandle handle) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
sourceFile, handle);
- if (sourceLineAnnotation != null)
+ if (sourceLineAnnotation != null) {
add(sourceLineAnnotation);
+ }
return this;
}
@@ -1891,8 +1935,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
}
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstructionRange(classContext, methodGen,
sourceFile, start, end);
- if (sourceLineAnnotation != null)
+ if (sourceLineAnnotation != null) {
add(sourceLineAnnotation);
+ }
return this;
}
@@ -1949,8 +1994,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public BugInstance addSourceLine(ClassContext classContext, Method method, InstructionHandle handle) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, method,
handle.getPosition());
- if (sourceLineAnnotation != null)
+ if (sourceLineAnnotation != null) {
add(sourceLineAnnotation);
+ }
return this;
}
@@ -1972,8 +2018,8 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public BugInstance addSourceLineRange(BytecodeScanningDetector visitor, int startPC, int endPC) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstructionRange(visitor.getClassContext(),
visitor, startPC, endPC);
- if (sourceLineAnnotation != null)
- add(sourceLineAnnotation);
+ requireNonNull(sourceLineAnnotation);
+ add(sourceLineAnnotation);
return this;
}
@@ -1997,8 +2043,8 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public BugInstance addSourceLineRange(ClassContext classContext, PreorderVisitor visitor, int startPC, int endPC) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstructionRange(classContext, visitor,
startPC, endPC);
- if (sourceLineAnnotation != null)
- add(sourceLineAnnotation);
+ requireNonNull(sourceLineAnnotation);
+ add(sourceLineAnnotation);
return this;
}
@@ -2015,8 +2061,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@Nonnull
public BugInstance addSourceLine(BytecodeScanningDetector visitor) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(visitor);
- if (sourceLineAnnotation != null)
+ if (sourceLineAnnotation != null) {
add(sourceLineAnnotation);
+ }
return this;
}
@@ -2033,8 +2080,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@Nonnull
public BugInstance addUnknownSourceLine(String className, String sourceFile) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.createUnknown(className, sourceFile);
- if (sourceLineAnnotation != null)
+ if (sourceLineAnnotation != null) {
add(sourceLineAnnotation);
+ }
return this;
}
@@ -2144,6 +2192,7 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
* ----------------------------------------------------------------------
*/
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, null, false);
}
@@ -2152,8 +2201,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
BugPattern pattern = getBugPattern();
int cweid = pattern.getCWEid();
- if (cweid != 0)
+ if (cweid != 0) {
return cweid;
+ }
BugCode bugCode = pattern.getBugCode();
return bugCode.getCWEid();
}
@@ -2161,6 +2211,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
XMLAttributeList attributeList = new XMLAttributeList().addAttribute("type", type).addAttribute("priority",
String.valueOf(priority));
+ // Always add the rank attribute.
+ attributeList.addAttribute("rank", Integer.toString(getBugRank()));
+
BugPattern pattern = getBugPattern();
// The bug abbreviation and pattern category are
@@ -2177,24 +2230,26 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
attributeList.addAttribute("instanceHash", getInstanceHash());
attributeList.addAttribute("instanceOccurrenceNum", Integer.toString(getInstanceOccurrenceNum()));
attributeList.addAttribute("instanceOccurrenceMax", Integer.toString(getInstanceOccurrenceMax()));
- attributeList.addAttribute("rank", Integer.toString(getBugRank()));
-
+
int cweid = getCWEid();
- if (cweid != 0)
+ if (cweid != 0) {
attributeList.addAttribute("cweid", Integer.toString(cweid));
-
-
+ }
} else if (oldInstanceHash != null && !isInstanceHashConsistent()) {
attributeList.addAttribute("oldInstanceHash", oldInstanceHash);
}
- if (firstVersion > 0)
+ if (firstVersion > 0) {
attributeList.addAttribute("first", Long.toString(firstVersion));
- if (lastVersion >= 0)
+ }
+ if (lastVersion >= 0) {
attributeList.addAttribute("last", Long.toString(lastVersion));
- if (introducedByChangeOfExistingClass)
+ }
+ if (introducedByChangeOfExistingClass) {
attributeList.addAttribute("introducedByChange", "true");
- if (removedByChangeOfPersistingClass)
+ }
+ if (removedByChangeOfPersistingClass) {
attributeList.addAttribute("removedByChange", "true");
+ }
if (bugCollection != null) {
Cloud cloud = bugCollection.getCloudLazily();
@@ -2209,39 +2264,46 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
if (reviews > 0) {
attributeList.addAttribute("reviews", Integer.toString(reviews));
- if (consensus != UserDesignation.UNCLASSIFIED)
+ if (consensus != UserDesignation.UNCLASSIFIED) {
attributeList.addAttribute("consensus", consensus.toString());
+ }
}
if (addMessages) {
int ageInDays = ageInDays(bugCollection, firstSeen);
attributeList.addAttribute("ageInDays", Integer.toString(ageInDays));
if (reviews > 0 && consensus != UserDesignation.UNCLASSIFIED) {
- if (consensus.score() < 0)
+ if (consensus.score() < 0) {
attributeList.addAttribute("notAProblem", "true");
- if (consensus.score() > 0)
+ }
+ if (consensus.score() > 0) {
attributeList.addAttribute("shouldFix", "true");
+ }
}
}
} else if (hasXmlProps()) {
XmlProps props = getXmlProps();
- if (props.firstSeen != null)
+ if (props.firstSeen != null) {
attributeList.addOptionalAttribute("firstSeen", firstSeenXMLFormat().format(props.firstSeen));
+ }
if (props.reviewCount > 0) {
- if (props.consensus != null)
+ if (props.consensus != null) {
attributeList.addOptionalAttribute("consensus", props.consensus);
+ }
attributeList.addAttribute("reviews", Integer.toString(props.reviewCount));
}
- if (!props.isInCloud())
+ if (!props.isInCloud()) {
attributeList.addAttribute("isInCloud", "false");
+ }
if (addMessages) {
UserDesignation consesus = UserDesignation.valueOf(props.consensus);
- if (consesus.shouldFix())
+ if (consesus.shouldFix()) {
attributeList.addAttribute("shouldFix", "true");
- else if (consesus.notAProblem())
+ } else if (consesus.notAProblem()) {
attributeList.addAttribute("notAProblem", "true");
+ }
if (props.firstSeen != null) {
int ageInDays = ageInDays(bugCollection, props.firstSeen.getTime());
@@ -2266,10 +2328,11 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
xmlOutput.closeTag("ShortMessage");
xmlOutput.openTag("LongMessage");
- if (FindBugsDisplayFeatures.isAbridgedMessages())
+ if (FindBugsDisplayFeatures.isAbridgedMessages()) {
xmlOutput.writeText(this.getAbridgedMessage());
- else
+ } else {
xmlOutput.writeText(this.getMessageWithoutPrefix());
+ }
xmlOutput.closeTag("LongMessage");
}
@@ -2287,44 +2350,45 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
boolean foundSourceAnnotation = false;
for (BugAnnotation annotation : annotationList) {
- if (annotation instanceof SourceLineAnnotation)
+ if (annotation instanceof SourceLineAnnotation) {
foundSourceAnnotation = true;
+ }
annotation.writeXML(xmlOutput, addMessages, primaryAnnotations.containsKey(annotation));
}
if (!foundSourceAnnotation && addMessages) {
SourceLineAnnotation synth = getPrimarySourceLineAnnotation();
- if (synth != null) {
- synth.setSynthetic(true);
- synth.writeXML(xmlOutput, addMessages, false);
- }
+ synth.setSynthetic(true);
+ synth.writeXML(xmlOutput, addMessages, false);
}
if (propertyListHead != null) {
- BugProperty prop = propertyListHead;
- while (prop != null) {
+ List<BugProperty> props = new ArrayList<>();
+ for(BugProperty prop = propertyListHead; prop != null; prop = prop.getNext()) {
+ props.add(prop);
+ }
+ Collections.sort(props, new Comparator<BugProperty>() {
+ @Override
+ public int compare(BugProperty o1, BugProperty o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ });
+ for(BugProperty prop : props) {
prop.writeXML(xmlOutput);
- prop = prop.getNext();
}
}
xmlOutput.closeTag(ELEMENT_NAME);
}
- /**
- * @param bugCollection
- * @param firstSeen
- * @return
- */
private int ageInDays(BugCollection bugCollection, long firstSeen) {
long age = bugCollection.getAnalysisTimestamp() - firstSeen;
- if (age < 0)
+ if (age < 0) {
age = 0;
+ }
int ageInDays = (int) (age / 1000 / 3600 / 24);
return ageInDays;
}
- private static final String ELEMENT_NAME = "BugInstance";
-
/*
* ----------------------------------------------------------------------
* Implementation
@@ -2332,20 +2396,21 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
*/
public BugInstance addOptionalAnnotation(@CheckForNull BugAnnotation annotation) {
- if (annotation == null)
+ if (annotation == null) {
return this;
+ }
return add(annotation);
}
public BugInstance addOptionalAnnotation(@CheckForNull BugAnnotation annotation, String role) {
- if (annotation == null)
+ if (annotation == null) {
return this;
+ }
return add(annotation).describe(role);
}
public BugInstance add(@Nonnull BugAnnotation annotation) {
- if (annotation == null)
- throw new IllegalArgumentException("Missing BugAnnotation!");
+ requireNonNull(annotation, "Missing BugAnnotation!");
// Add to list
annotationList.add(annotation);
@@ -2391,20 +2456,25 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
BugAnnotation a0 = getSomeSource(classContext, method, location, stack, depth);
return a0;
} catch (UnreachableCodeException e) {
- if (SystemProperties.ASSERTIONS_ENABLED)
+ if (SystemProperties.ASSERTIONS_ENABLED) {
AnalysisContext.logError(e.getMessage(), e);
+ }
return null;
}
}
public static @CheckForNull
BugAnnotation getSomeSource(ClassContext classContext, Method method, Location location, OpcodeStack stack, int stackPos) {
+ if (stack.isTop()) {
+ return null;
+ }
int pc = location.getHandle().getPosition();
try {
BugAnnotation result = ValueNumberSourceInfo.getFromValueNumber(classContext, method, location, stackPos);
- if (result != null)
+ if (result != null) {
return result;
+ }
} catch (DataflowAnalysisException e) {
AnalysisContext.logError("Couldn't find value source", e);
} catch (CFGBuilderException e) {
@@ -2418,19 +2488,21 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public static @javax.annotation.CheckForNull
BugAnnotation getValueSource(OpcodeStack.Item item, Method method, int pc) {
LocalVariableAnnotation lv = LocalVariableAnnotation.getLocalVariableAnnotation(method, item, pc);
- if (lv != null && lv.isNamed())
+ if (lv != null && lv.isNamed()) {
return lv;
+ }
BugAnnotation a = getFieldOrMethodValueSource(item);
- if (a != null)
+ if (a != null) {
return a;
+ }
Object c = item.getConstant();
if (c instanceof String) {
a = new StringAnnotation((String) c);
a.setDescription(StringAnnotation.STRING_CONSTANT_ROLE);
return a;
}
- if (c instanceof Integer) {
+ if (c instanceof Integer && !item.isArray()) {
a = new IntAnnotation((Integer) c);
a.setDescription(IntAnnotation.INT_VALUE);
return a;
@@ -2440,8 +2512,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
}
public BugInstance addValueSource(@CheckForNull OpcodeStack.Item item, DismantleBytecode dbc) {
- if (item != null)
+ if (item != null) {
addValueSource(item, dbc.getMethod(), dbc.getPC());
+ }
return this;
}
@@ -2450,9 +2523,6 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
return this;
}
- /**
- * @param item
- */
public BugInstance addFieldOrMethodValueSource(OpcodeStack.Item item) {
addOptionalAnnotation(getFieldOrMethodValueSource(item));
return this;
@@ -2460,35 +2530,42 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public BugInstance addOptionalUniqueAnnotations(BugAnnotation... annotations) {
HashSet<BugAnnotation> added = new HashSet<BugAnnotation>();
- for (BugAnnotation a : annotations)
- if (a != null && added.add(a))
+ for (BugAnnotation a : annotations) {
+ if (a != null && added.add(a)) {
add(a);
+ }
+ }
return this;
}
-
+
public boolean tryAddingOptionalUniqueAnnotations(BugAnnotation... annotations) {
HashSet<BugAnnotation> added = new HashSet<BugAnnotation>();
- for (BugAnnotation a : annotations)
- if (a != null && added.add(a))
+ for (BugAnnotation a : annotations) {
+ if (a != null && added.add(a)) {
add(a);
+ }
+ }
return !added.isEmpty();
}
-
public BugInstance addOptionalUniqueAnnotationsWithFallback(BugAnnotation fallback, BugAnnotation... annotations) {
HashSet<BugAnnotation> added = new HashSet<BugAnnotation>();
- for (BugAnnotation a : annotations)
- if (a != null && added.add(a))
+ for (BugAnnotation a : annotations) {
+ if (a != null && added.add(a)) {
add(a);
- if (added.isEmpty())
+ }
+ }
+ if (added.isEmpty()) {
add(fallback);
+ }
return this;
}
public static @CheckForNull
BugAnnotation getFieldOrMethodValueSource(@CheckForNull OpcodeStack.Item item) {
- if (item == null)
+ if (item == null) {
return null;
+ }
XField xField = item.getXField();
if (xField != null) {
FieldAnnotation a = FieldAnnotation.fromXField(xField);
@@ -2525,10 +2602,12 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
if (cachedHashCode == INVALID_HASH_CODE) {
int hashcode = type.hashCode() + priority;
Iterator<BugAnnotation> i = annotationIterator();
- while (i.hasNext())
+ while (i.hasNext()) {
hashcode += i.next().hashCode();
- if (hashcode == INVALID_HASH_CODE)
+ }
+ if (hashcode == INVALID_HASH_CODE) {
hashcode = INVALID_HASH_CODE + 1;
+ }
cachedHashCode = hashcode;
}
@@ -2537,34 +2616,42 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
@Override
public boolean equals(Object o) {
- if (this == o)
+ if (this == o) {
return true;
- if (!(o instanceof BugInstance))
+ }
+ if (!(o instanceof BugInstance)) {
return false;
+ }
BugInstance other = (BugInstance) o;
- if (!type.equals(other.type) || priority != other.priority)
+ if (!type.equals(other.type) || priority != other.priority) {
return false;
- if (annotationList.size() != other.annotationList.size())
+ }
+ if (annotationList.size() != other.annotationList.size()) {
return false;
+ }
int numAnnotations = annotationList.size();
for (int i = 0; i < numAnnotations; ++i) {
BugAnnotation lhs = annotationList.get(i);
BugAnnotation rhs = other.annotationList.get(i);
- if (!lhs.equals(rhs))
+ if (!lhs.equals(rhs)) {
return false;
+ }
}
return true;
}
+ @Override
public int compareTo(BugInstance other) {
int cmp;
cmp = type.compareTo(other.type);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
cmp = priority - other.priority;
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
// Compare BugAnnotations lexicographically
int pfxLen = Math.min(annotationList.size(), other.annotationList.size());
@@ -2572,8 +2659,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
BugAnnotation lhs = annotationList.get(i);
BugAnnotation rhs = other.annotationList.get(i);
cmp = lhs.compareTo(rhs);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
}
// All elements in prefix were the same,
@@ -2581,15 +2669,11 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
return annotationList.size() - other.annotationList.size();
}
- /**
- * @param firstVersion
- * The firstVersion to set.
- */
public void setFirstVersion(long firstVersion) {
- if (lastVersion >= 0 && firstVersion > lastVersion)
+ if (lastVersion >= 0 && firstVersion > lastVersion) {
throw new IllegalArgumentException(firstVersion + ".." + lastVersion);
+ }
this.firstVersion = firstVersion;
-
}
public void clearHistory() {
@@ -2599,9 +2683,6 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
setRemovedByChangeOfPersistingClass(false);
}
- /**
- * @return Returns the firstVersion.
- */
public long getFirstVersion() {
return firstVersion;
}
@@ -2620,13 +2701,10 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
this.introducedByChangeOfExistingClass = from.introducedByChangeOfExistingClass;
}
- /**
- * @param lastVersion
- * The lastVersion to set.
- */
public void setLastVersion(long lastVersion) {
- if (lastVersion >= 0 && firstVersion > lastVersion)
+ if (lastVersion >= 0 && firstVersion > lastVersion) {
throw new IllegalArgumentException(firstVersion + ".." + lastVersion);
+ }
this.lastVersion = lastVersion;
}
@@ -2634,9 +2712,7 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
public void setLive() {
this.lastVersion = -1;
}
- /**
- * @return Returns the lastVersion.
- */
+
public long getLastVersion() {
return lastVersion;
}
@@ -2645,60 +2721,35 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
return lastVersion != -1;
}
- /**
- * @param introducedByChangeOfExistingClass
- * The introducedByChangeOfExistingClass to set.
- */
public void setIntroducedByChangeOfExistingClass(boolean introducedByChangeOfExistingClass) {
this.introducedByChangeOfExistingClass = introducedByChangeOfExistingClass;
}
- /**
- * @return Returns the introducedByChangeOfExistingClass.
- */
public boolean isIntroducedByChangeOfExistingClass() {
return introducedByChangeOfExistingClass;
}
- /**
- * @param removedByChangeOfPersistingClass
- * The removedByChangeOfPersistingClass to set.
- */
public void setRemovedByChangeOfPersistingClass(boolean removedByChangeOfPersistingClass) {
this.removedByChangeOfPersistingClass = removedByChangeOfPersistingClass;
}
- /**
- * @return Returns the removedByChangeOfPersistingClass.
- */
public boolean isRemovedByChangeOfPersistingClass() {
return removedByChangeOfPersistingClass;
}
- /**
- * @param instanceHash
- * The instanceHash to set.
- */
public void setInstanceHash(String instanceHash) {
this.instanceHash = instanceHash;
}
- /**
- * @param oldInstanceHash
- * The oldInstanceHash to set.
- */
public void setOldInstanceHash(String oldInstanceHash) {
this.oldInstanceHash = oldInstanceHash;
}
- /**
- * @return Returns the instanceHash.
- */
-
public String getInstanceHash() {
String hash = instanceHash;
- if (hash != null)
+ if (hash != null) {
return hash;
+ }
MessageDigest digest = Util.getMD5Digest();
String key = getInstanceKey();
@@ -2717,32 +2768,18 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
return oldInstanceHash == null || getInstanceHash().equals(oldInstanceHash);
}
- /**
- * @param instanceOccurrenceNum
- * The instanceOccurrenceNum to set.
- */
public void setInstanceOccurrenceNum(int instanceOccurrenceNum) {
this.instanceOccurrenceNum = instanceOccurrenceNum;
}
- /**
- * @return Returns the instanceOccurrenceNum.
- */
public int getInstanceOccurrenceNum() {
return instanceOccurrenceNum;
}
- /**
- * @param instanceOccurrenceMax
- * The instanceOccurrenceMax to set.
- */
public void setInstanceOccurrenceMax(int instanceOccurrenceMax) {
this.instanceOccurrenceMax = instanceOccurrenceMax;
}
- /**
- * @return Returns the instanceOccurrenceMax.
- */
public int getInstanceOccurrenceMax() {
return instanceOccurrenceMax;
}
@@ -2753,8 +2790,9 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
}
private void optionalAdd(Collection<BugAnnotation> c, BugAnnotation a) {
- if (a != null)
+ if (a != null) {
c.add(a);
+ }
}
public List<BugAnnotation> getAnnotationsForMessage(boolean showContext) {
@@ -2773,33 +2811,39 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
optionalAdd(primaryAnnotations, primeField);
optionalAdd(primaryAnnotations, primeClass);
- if (primarySourceLineAnnotation != null
- && (showContext || !primarySourceLineAnnotation.getDescription().equals(SourceLineAnnotation.DEFAULT_ROLE)))
+ if ((showContext || !SourceLineAnnotation.DEFAULT_ROLE.equals(primarySourceLineAnnotation.getDescription()))) {
result.add(primarySourceLineAnnotation);
+ }
- if (primeMethod != null && (showContext || !primeMethod.getDescription().equals(MethodAnnotation.DEFAULT_ROLE)))
+ if (primeMethod != null && (showContext || !MethodAnnotation.DEFAULT_ROLE.equals(primeMethod.getDescription()))) {
result.add(primeMethod);
+ }
optionalAdd(result, primeField);
String fieldClass = "";
String methodClass = "";
- if (primeField != null)
+ if (primeField != null) {
fieldClass = primeField.getClassName();
- if (primeMethod != null)
+ }
+ if (primeMethod != null) {
methodClass = primeMethod.getClassName();
+ }
if (showContext && (primaryAnnotations.size() < 2)
|| (!(primeClass.getClassName().equals(fieldClass) || primeClass.getClassName().equals(methodClass)))) {
optionalAdd(result, primeClass);
}
for (BugAnnotation b : getAnnotations()) {
- if (primaryAnnotations.contains(b))
+ if (primaryAnnotations.contains(b)) {
continue;
- if (b instanceof LocalVariableAnnotation && !((LocalVariableAnnotation) b).isNamed())
+ }
+ if (b instanceof LocalVariableAnnotation && !((LocalVariableAnnotation) b).isNamed()) {
continue;
- if (b instanceof SourceLineAnnotation && ((SourceLineAnnotation) b).isUnknown())
+ }
+ if (b instanceof SourceLineAnnotation && ((SourceLineAnnotation) b).isUnknown()) {
continue;
+ }
result.add(b);
}
return result;
@@ -2853,5 +2897,3 @@ public class BugInstance implements Comparable<BugInstance>, XMLWriteable, Seria
}
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/BugPattern.java b/src/java/edu/umd/cs/findbugs/BugPattern.java
index 70b0788..69074a5 100644
--- a/src/java/edu/umd/cs/findbugs/BugPattern.java
+++ b/src/java/edu/umd/cs/findbugs/BugPattern.java
@@ -47,6 +47,8 @@ public class BugPattern implements Comparable<BugPattern> {
final private String detailText;
+ final private String url;
+
final int cweid;
int priorityAdjustment;
@@ -71,33 +73,11 @@ public class BugPattern implements Comparable<BugPattern> {
* by {@link FindBugsMessageFormat} to format BugAnnotations
* @param detailText
* HTML text containing a full description of the bug species
+ * @param bugsUrl
+ * URL of web-page containing bug descriptions or null if there's no such page.
*/
public BugPattern(String type, String abbrev, String category, boolean experimental, String shortDescription,
- String longDescription, String detailText) {
- this(type, abbrev, category, experimental, shortDescription, longDescription, detailText, 0);
- }
-
- /**
- * Constructor.
- *
- * @param type
- * the type (species) of BugInstance
- * @param abbrev
- * the abbreviation or "bug code"; see {@link BugCode}
- * @param category
- * the category
- * @param experimental
- * true if the bug pattern is experimental
- * @param shortDescription
- * short one-line description of the bug species
- * @param longDescription
- * longer one-line description; may contain placeholders for use
- * by {@link FindBugsMessageFormat} to format BugAnnotations
- * @param detailText
- * HTML text containing a full description of the bug species
- */
- public BugPattern(String type, String abbrev, String category, boolean experimental, String shortDescription,
- String longDescription, String detailText, int cweid) {
+ String longDescription, String detailText, String bugsUrl, int cweid) {
this.type = type;
this.abbrev = abbrev.intern();
@@ -107,6 +87,7 @@ public class BugPattern implements Comparable<BugPattern> {
this.longDescription = longDescription;
this.detailText = detailText;
this.cweid = cweid;
+ this.url = bugsUrl;
}
static final BugPattern REALLY_UNKNOWN = new BugPattern("REALLY_UNKNOWN", "TEST", "CORRECTNESS", false,
@@ -114,7 +95,7 @@ public class BugPattern implements Comparable<BugPattern> {
"<p>A warning was recorded, but findbugs can't find the description of this bug pattern "
+ "and so can't describe it. This should occur only in cases of a bug in FindBugs or its configuration, "
+ "or perhaps if an analysis was generated using a plugin, but that plugin is not currently loaded. "
- + "</p>");
+ + "</p>", null, 0);
/**
* Get the BugPattern
@@ -135,7 +116,7 @@ public class BugPattern implements Comparable<BugPattern> {
*/
public @Nonnull BugCode getBugCode() {
return DetectorFactoryCollection.instance().getBugCode(abbrev);
-
+
}
/**
* Get the BugCategory
@@ -155,10 +136,12 @@ public class BugPattern implements Comparable<BugPattern> {
public String getCategoryAbbrev() {
String categoryAbbrev = null;
BugCategory bcat = DetectorFactoryCollection.instance().getBugCategory(getCategory());
- if (bcat != null)
+ if (bcat != null) {
categoryAbbrev = bcat.getAbbrev();
- if (categoryAbbrev == null)
+ }
+ if (categoryAbbrev == null) {
categoryAbbrev = TextUIBugReporter.OTHER_CATEGORY_ABBREV;
+ }
return categoryAbbrev;
}
@@ -208,35 +191,30 @@ public class BugPattern implements Comparable<BugPattern> {
public String getDetailHTML() {
return getDetailHTML(getDetailText());
}
-
+
public String getDetailHTML(String detailText) {
- StringBuilder buf = new StringBuilder();
- buf.append("<!DOCTYPE HTML\">\n");
- buf.append("<HTML><HEAD><TITLE>");
- buf.append(getShortDescription());
- buf.append("</TITLE></HEAD><BODY><H1>");
- buf.append(wrapInDescriptionLink(getShortDescription()));
- buf.append("</H1>\n");
- buf.append(detailText);
- buf.append("</BODY></HTML>\n");
- return buf.toString();
+ StringBuilder buf = new StringBuilder();
+ buf.append("<!DOCTYPE HTML\">\n");
+ buf.append("<HTML><HEAD><TITLE>");
+ buf.append(getShortDescription());
+ buf.append("</TITLE></HEAD><BODY><H1>");
+ buf.append(wrapInDescriptionLink(getShortDescription()));
+ buf.append("</H1>\n");
+ buf.append(detailText);
+ buf.append("</BODY></HTML>\n");
+ return buf.toString();
}
-
public String wrapInDescriptionLink(String text) {
- if (isExperimental())
- return
- "<a href=\"http://findbugs.sourceforge.net/allBugDescriptions.html#"
- + type +"\">"
- + text + "</a>";
- return
- "<a href=\"http://findbugs.sourceforge.net/bugDescriptions.html#"
- + type +"\">"
- + text + "</a>";
-
+ if(url == null) {
+ return text;
+ }
+ return "<a href=\"" + url + "#" + type + "\">" + text + "</a>";
}
+
+ @Override
public int compareTo(BugPattern other) {
return type.compareTo(other.type);
}
@@ -248,8 +226,9 @@ public class BugPattern implements Comparable<BugPattern> {
@Override
public boolean equals(Object o) {
- if (!(o instanceof BugPattern))
+ if (!(o instanceof BugPattern)) {
return false;
+ }
BugPattern other = (BugPattern) o;
return type.equals(other.type);
}
diff --git a/src/java/edu/umd/cs/findbugs/BugProperty.java b/src/java/edu/umd/cs/findbugs/BugProperty.java
index 94d83dc..36cf49a 100644
--- a/src/java/edu/umd/cs/findbugs/BugProperty.java
+++ b/src/java/edu/umd/cs/findbugs/BugProperty.java
@@ -30,7 +30,7 @@ import edu.umd.cs.findbugs.xml.XMLWriteable;
* Name/value metadata pair that may be attached to a BugInstance. These are
* different from BugAnnotations because they are not meant to be shown directly
* to the user.
- *
+ *
* @author David Hovemeyer
*/
public class BugProperty implements XMLWriteable, Serializable, Cloneable {
@@ -50,7 +50,7 @@ public class BugProperty implements XMLWriteable, Serializable, Cloneable {
public static final String SEVERITY = "severity";
// Fields
- private String name;
+ private final String name;
private String value;
@@ -58,7 +58,7 @@ public class BugProperty implements XMLWriteable, Serializable, Cloneable {
/**
* Constructor.
- *
+ *
* @param name
* name of property
* @param value
@@ -80,7 +80,7 @@ public class BugProperty implements XMLWriteable, Serializable, Cloneable {
/**
* Get name of property.
- *
+ *
* @return name of property
*/
public String getName() {
@@ -89,7 +89,7 @@ public class BugProperty implements XMLWriteable, Serializable, Cloneable {
/**
* Get value of property.
- *
+ *
* @return value of property
*/
public String getValue() {
@@ -98,7 +98,7 @@ public class BugProperty implements XMLWriteable, Serializable, Cloneable {
/**
* Get value of property as boolean.
- *
+ *
* @return value of property as a boolean
*/
public boolean getValueAsBoolean() {
@@ -107,7 +107,7 @@ public class BugProperty implements XMLWriteable, Serializable, Cloneable {
/**
* Get value of property as an integer.
- *
+ *
* @return value of property as integer
* @throws NumberFormatException
* if the value cannot be parsed as an integer
@@ -118,7 +118,7 @@ public class BugProperty implements XMLWriteable, Serializable, Cloneable {
/**
* Set value of property.
- *
+ *
* @param value
*/
public void setValue(String value) {
@@ -127,7 +127,7 @@ public class BugProperty implements XMLWriteable, Serializable, Cloneable {
/**
* Set next property in list.
- *
+ *
* @param next
* next property in list
*/
@@ -137,7 +137,7 @@ public class BugProperty implements XMLWriteable, Serializable, Cloneable {
/**
* Get next property in list.
- *
+ *
* @return next property in list
*/
BugProperty getNext() {
@@ -146,11 +146,12 @@ public class BugProperty implements XMLWriteable, Serializable, Cloneable {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.xml.XMLWriteable#writeXML(edu.umd.cs.findbugs.xml
* .XMLOutput)
*/
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
xmlOutput.openCloseTag("Property",
new XMLAttributeList().addAttribute("name", getName()).addAttribute("value", getValue()));
diff --git a/src/java/edu/umd/cs/findbugs/BugRanker.java b/src/java/edu/umd/cs/findbugs/BugRanker.java
index 03da20b..c319871 100644
--- a/src/java/edu/umd/cs/findbugs/BugRanker.java
+++ b/src/java/edu/umd/cs/findbugs/BugRanker.java
@@ -99,8 +99,9 @@ public class BugRanker {
int get(String key) {
Integer v = adjustment.get(key);
- if (v == null)
+ if (v == null) {
return 0;
+ }
return v;
}
@@ -111,13 +112,15 @@ public class BugRanker {
void storeAdjustment(String key, String value) {
for (String k : key.split(",")) {
char firstChar = value.charAt(0);
- if (firstChar == '+')
+ if (firstChar == '+') {
value = value.substring(1);
+ }
int v = Integer.parseInt(value);
adjustment.put(k, v);
- if (firstChar == '+' || firstChar == '-')
+ if (firstChar == '+' || firstChar == '-') {
isRelative.add(k);
+ }
}
@@ -138,25 +141,34 @@ public class BugRanker {
try {
while (true) {
String s = in.readLine();
- if (s == null)
+ if (s == null) {
break;
+ }
s = s.trim();
- if (s.length() == 0)
+ if (s.length() == 0) {
continue;
+ }
String parts[] = s.split(" ");
+ if (parts.length != 3) {
+ AnalysisContext.logError("Can't parse bug rank line: '" + s + "'. "
+ + "Valid line must contain 3 parts separated by spaces.");
+ continue;
+ }
String rank = parts[0];
String kind = parts[1];
String what = parts[2];
- if (kind.equals("BugPattern"))
+ if ("BugPattern".equals(kind)) {
bugPatterns.storeAdjustment(what, rank);
- else if (kind.equals("BugKind"))
+ } else if ("BugKind".equals(kind)) {
bugKinds.storeAdjustment(what, rank);
- else if (kind.equals("Category"))
+ } else if ("Category".equals(kind)) {
bugCategories.storeAdjustment(what, rank);
- else
- AnalysisContext.logError("Can't parse bug rank " + s);
+ } else {
+ AnalysisContext.logError("Can't parse rank kind from line: '" + s + "'. "
+ + "Valid kind must be either 'BugPattern', 'BugKind' or 'Category'.");
+ }
}
} finally {
Util.closeSilently(in);
@@ -191,34 +203,41 @@ public class BugRanker {
private static int adjustRank(int patternRank, int priority) {
int priorityAdjustment = priorityAdjustment(priority);
- if (patternRank > VISIBLE_RANK_MAX)
+ if (patternRank > VISIBLE_RANK_MAX) {
return patternRank + priorityAdjustment;
+ }
return Math.max(VISIBLE_RANK_MIN, Math.min(patternRank + priorityAdjustment, VISIBLE_RANK_MAX));
}
private static int rankBugPattern(BugPattern bugPattern, BugRanker... rankers) {
String type = bugPattern.getType();
int rank = 0;
- for (BugRanker b : rankers)
+ for (BugRanker b : rankers) {
if (b != null) {
rank += b.bugPatterns.get(type);
- if (!b.bugPatterns.isRelative(type))
+ if (!b.bugPatterns.isRelative(type)) {
return rank;
+ }
}
+ }
String kind = bugPattern.getAbbrev();
- for (BugRanker b : rankers)
+ for (BugRanker b : rankers) {
if (b != null) {
rank += b.bugKinds.get(kind);
- if (!b.bugKinds.isRelative(kind))
+ if (!b.bugKinds.isRelative(kind)) {
return rank;
+ }
}
+ }
String category = bugPattern.getCategory();
- for (BugRanker b : rankers)
+ for (BugRanker b : rankers) {
if (b != null) {
rank += b.bugCategories.get(category);
- if (!b.bugCategories.isRelative(category))
+ if (!b.bugCategories.isRelative(category)) {
return rank;
+ }
}
+ }
return rank;
}
@@ -252,26 +271,29 @@ public class BugRanker {
public static int findRank(BugPattern pattern, @CheckForNull DetectorFactory detectorFactory) {
boolean haveCache = Global.getAnalysisCache() != null;
if (haveCache) {
- Integer cachedResult = rankForBugPattern.get().get(pattern);
- if (cachedResult != null)
- return cachedResult;
+ Integer cachedResult = rankForBugPattern.get().get(pattern);
+ if (cachedResult != null) {
+ return cachedResult;
+ }
}
int rank;
- if (detectorFactory == null)
+ if (detectorFactory == null) {
rank = findRankUnknownPlugin(pattern);
- else {
+ } else {
Plugin plugin = detectorFactory.getPlugin();
- BugRanker pluginRanker = plugin.getBugRanker();
+ BugRanker pluginRanker = plugin.getBugRanker();
BugRanker coreRanker = getCoreRanker();
- if (pluginRanker == coreRanker)
+ if (pluginRanker == coreRanker) {
rank = rankBugPattern(pattern, coreRanker);
- else
+ } else {
rank = rankBugPattern(pattern, pluginRanker, coreRanker);
+ }
}
- if (haveCache)
+ if (haveCache) {
rankForBugPattern.get().put(pattern, rank);
+ }
return rank;
}
@@ -279,8 +301,9 @@ public class BugRanker {
List<BugRanker> rankers = new ArrayList<BugRanker>();
pluginLoop: for (Plugin plugin : Plugin.getAllPlugins()) {
- if (plugin.isCorePlugin())
+ if (plugin.isCorePlugin()) {
continue;
+ }
if (false) {
rankers.add(plugin.getBugRanker());
continue pluginLoop;
@@ -288,26 +311,29 @@ public class BugRanker {
for (DetectorFactory df : plugin.getDetectorFactories()) {
if (df.getReportedBugPatterns().contains(pattern)) {
- if (PLUGIN_DEBUG)
+ if (PLUGIN_DEBUG) {
System.out.println("Bug rank match " + plugin + " " + df + " for " + pattern);
+ }
rankers.add(plugin.getBugRanker());
continue pluginLoop;
}
}
- if (PLUGIN_DEBUG)
+ if (PLUGIN_DEBUG) {
System.out.println("plugin " + plugin + " doesn't match " + pattern);
+ }
}
rankers.add(getCoreRanker());
- return rankBugPattern(pattern, rankers.toArray(new BugRanker[] {}));
+ return rankBugPattern(pattern, rankers.toArray(new BugRanker[rankers.size()]));
}
public static void trimToMaxRank(BugCollection origCollection, int maxRank) {
for (Iterator<BugInstance> i = origCollection.getCollection().iterator(); i.hasNext();) {
BugInstance b = i.next();
- if (BugRanker.findRank(b) > maxRank)
+ if (BugRanker.findRank(b) > maxRank) {
i.remove();
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/BugReporter.java b/src/java/edu/umd/cs/findbugs/BugReporter.java
index 521b079..e6e5f32 100644
--- a/src/java/edu/umd/cs/findbugs/BugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/BugReporter.java
@@ -30,7 +30,7 @@ import edu.umd.cs.findbugs.classfile.IClassObserver;
* the information reported by the analysis, which includes bug reports, and
* also auxiliary information such as analysis errors, missing classes, and
* class to source file mapping.
- *
+ *
* @author David Hovemeyer
*/
public interface BugReporter extends RepositoryLookupFailureCallback, IClassObserver {
@@ -47,7 +47,7 @@ public interface BugReporter extends RepositoryLookupFailureCallback, IClassObse
/**
* Set the error-reporting verbosity level.
- *
+ *
* @param level
* the verbosity level
*/
@@ -55,7 +55,7 @@ public interface BugReporter extends RepositoryLookupFailureCallback, IClassObse
/**
* Set the priority threshold.
- *
+ *
* @param threshold
* bug instances must be at least as important as this priority
* to be reported
@@ -65,7 +65,7 @@ public interface BugReporter extends RepositoryLookupFailureCallback, IClassObse
/**
* Report a bug. The implementation may report the bug immediately, or queue
* it for later.
- *
+ *
* @param bugInstance
* object describing the bug instance
*/
@@ -84,7 +84,7 @@ public interface BugReporter extends RepositoryLookupFailureCallback, IClassObse
/**
* Add an observer.
- *
+ *
* @param observer
* the observer
*/
@@ -98,11 +98,8 @@ public interface BugReporter extends RepositoryLookupFailureCallback, IClassObse
/**
* Get the bug collection (if any) associated with this bug reporter
- *
- * @return
*/
public @CheckForNull
BugCollection getBugCollection();
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/BugReporterObserver.java b/src/java/edu/umd/cs/findbugs/BugReporterObserver.java
index 4d940c0..5d354be 100644
--- a/src/java/edu/umd/cs/findbugs/BugReporterObserver.java
+++ b/src/java/edu/umd/cs/findbugs/BugReporterObserver.java
@@ -24,18 +24,17 @@ package edu.umd.cs.findbugs;
* observer, it is possible to determine which bugs a BugReporter is actually
* reporting, because due to filtering, priorities, etc., not all bugs sent to a
* BugReporter will actually be processed.
- *
+ *
* @author David Hovemeyer
* @see BugReporter
*/
public interface BugReporterObserver {
/**
* Called when a BugReporter reports a bug.
- *
+ *
* @param bugInstance
* the BugInstance
*/
public void reportBug(BugInstance bugInstance);
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ByteCodePatternDetector.java b/src/java/edu/umd/cs/findbugs/ByteCodePatternDetector.java
index 587a1ab..7d195d3 100644
--- a/src/java/edu/umd/cs/findbugs/ByteCodePatternDetector.java
+++ b/src/java/edu/umd/cs/findbugs/ByteCodePatternDetector.java
@@ -37,7 +37,7 @@ import edu.umd.cs.findbugs.ba.bcp.PatternMatcher;
* A base class for bug detectors that are based on a ByteCodePattern.
* ByteCodePatterns provide an easy way to detect patterns of bytecode
* instructions, taking into account control flow and uses of fields and values.
- *
+ *
* @see ByteCodePattern
*/
public abstract class ByteCodePatternDetector implements Detector {
@@ -47,6 +47,7 @@ public abstract class ByteCodePatternDetector implements Detector {
protected abstract BugReporter getBugReporter();
+ @Override
public void visitClassContext(ClassContext classContext) {
try {
ByteCodePattern pattern = getPattern();
@@ -54,11 +55,13 @@ public abstract class ByteCodePatternDetector implements Detector {
Method[] methodList = jclass.getMethods();
for (Method method : methodList) {
- if (method.isAbstract() || method.isNative())
+ if (method.isAbstract() || method.isNative()) {
continue;
+ }
- if (METHOD != null && !method.getName().equals(METHOD))
+ if (METHOD != null && !method.getName().equals(METHOD)) {
continue;
+ }
if (DEBUG) {
System.out.print("=====================================================================\n" + "Method "
@@ -66,12 +69,14 @@ public abstract class ByteCodePatternDetector implements Detector {
+ "=====================================================================\n");
}
- if (!prescreen(method, classContext))
+ if (!prescreen(method, classContext)) {
continue;
+ }
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
continue;
+ }
PatternMatcher matcher = new PatternMatcher(pattern, classContext, method);
matcher.execute();
@@ -108,6 +113,7 @@ public abstract class ByteCodePatternDetector implements Detector {
return className;
}
+ @Override
public void report() {
}
@@ -130,7 +136,7 @@ public abstract class ByteCodePatternDetector implements Detector {
* As a datapoint, prescreening speeds up the BCPDoubleCheck detector <b>by
* a factor of 5</b> with no loss of generality and only a dozen or so extra
* lines of code.
- *
+ *
* @param method
* the method
* @param classContext
@@ -142,7 +148,7 @@ public abstract class ByteCodePatternDetector implements Detector {
/**
* Called to report an instance of the ByteCodePattern.
- *
+ *
* @param classContext
* the ClassContext for the analyzed class
* @param method
@@ -155,4 +161,3 @@ public abstract class ByteCodePatternDetector implements Detector {
throws CFGBuilderException, DataflowAnalysisException;
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/BytecodeScanningDetector.java b/src/java/edu/umd/cs/findbugs/BytecodeScanningDetector.java
index 570f384..5868875 100644
--- a/src/java/edu/umd/cs/findbugs/BytecodeScanningDetector.java
+++ b/src/java/edu/umd/cs/findbugs/BytecodeScanningDetector.java
@@ -26,12 +26,13 @@ import edu.umd.cs.findbugs.visitclass.DismantleBytecode;
/**
* Base class for Detectors which want to extend DismantleBytecode.
- *
+ *
* @see DismantleBytecode
*/
public class BytecodeScanningDetector extends DismantleBytecode implements Detector {
private ClassContext classContext;
+ @Override
public void visitClassContext(ClassContext classContext) {
this.classContext = classContext;
classContext.getJavaClass().accept(this);
@@ -39,7 +40,7 @@ public class BytecodeScanningDetector extends DismantleBytecode implements Detec
/**
* Get the ClassContext of the class currently being visited.
- *
+ *
* @return the current ClassContext
*/
public ClassContext getClassContext() {
@@ -48,7 +49,7 @@ public class BytecodeScanningDetector extends DismantleBytecode implements Detec
/**
* Check see if the Code for this method should be visited.
- *
+ *
* @param obj
* Code attribute
* @return true if the Code should be visited
@@ -57,8 +58,8 @@ public class BytecodeScanningDetector extends DismantleBytecode implements Detec
return true;
}
+ @Override
public void report() {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/CallGraph.java b/src/java/edu/umd/cs/findbugs/CallGraph.java
index 434844e..f31d45c 100644
--- a/src/java/edu/umd/cs/findbugs/CallGraph.java
+++ b/src/java/edu/umd/cs/findbugs/CallGraph.java
@@ -26,7 +26,7 @@ import org.apache.bcel.classfile.Method;
import edu.umd.cs.findbugs.graph.AbstractGraph;
public class CallGraph extends AbstractGraph<CallGraphEdge, CallGraphNode> {
- private IdentityHashMap<Method, CallGraphNode> methodToNodeMap;
+ private final IdentityHashMap<Method, CallGraphNode> methodToNodeMap;
public CallGraph() {
this.methodToNodeMap = new IdentityHashMap<Method, CallGraphNode>();
@@ -56,4 +56,3 @@ public class CallGraph extends AbstractGraph<CallGraphEdge, CallGraphNode> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/CallGraphEdge.java b/src/java/edu/umd/cs/findbugs/CallGraphEdge.java
index f884cf2..11bb5cb 100644
--- a/src/java/edu/umd/cs/findbugs/CallGraphEdge.java
+++ b/src/java/edu/umd/cs/findbugs/CallGraphEdge.java
@@ -47,4 +47,3 @@ public class CallGraphEdge extends AbstractEdge<CallGraphEdge, CallGraphNode> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/CallGraphNode.java b/src/java/edu/umd/cs/findbugs/CallGraphNode.java
index 3e57e44..a16e974 100644
--- a/src/java/edu/umd/cs/findbugs/CallGraphNode.java
+++ b/src/java/edu/umd/cs/findbugs/CallGraphNode.java
@@ -35,4 +35,3 @@ public class CallGraphNode extends AbstractVertex<CallGraphEdge, CallGraphNode>
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/CallSite.java b/src/java/edu/umd/cs/findbugs/CallSite.java
index ac49bd0..351f446 100644
--- a/src/java/edu/umd/cs/findbugs/CallSite.java
+++ b/src/java/edu/umd/cs/findbugs/CallSite.java
@@ -35,7 +35,7 @@ public class CallSite {
/**
* Constructor.
- *
+ *
* @param method
* the method containing the call site
* @param basicBlock
@@ -84,11 +84,11 @@ public class CallSite {
@Override
public boolean equals(Object o) {
- if (!(o instanceof CallSite))
+ if (!(o instanceof CallSite)) {
return false;
+ }
CallSite other = (CallSite) o;
return method == other.method && getBasicBlock() == other.getBasicBlock() && getHandle() == other.getHandle();
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/CategoryFilteringBugReporter.java b/src/java/edu/umd/cs/findbugs/CategoryFilteringBugReporter.java
index 3e231d3..2829ccf 100644
--- a/src/java/edu/umd/cs/findbugs/CategoryFilteringBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/CategoryFilteringBugReporter.java
@@ -29,7 +29,7 @@ import javax.annotation.Nonnull;
public class CategoryFilteringBugReporter extends DelegatingBugReporter {
private static final boolean DEBUG = SystemProperties.getBoolean("cfbreporter.debug");
- private Set<String> categorySet;
+ private final Set<String> categorySet;
public CategoryFilteringBugReporter(BugReporter realBugReporter, Set<String> categorySet) {
super(realBugReporter);
@@ -43,8 +43,9 @@ public class CategoryFilteringBugReporter extends DelegatingBugReporter {
if (categorySet.contains(category)) {
getDelegate().reportBug(bugInstance);
} else {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("CategoryFilteringBugReporter: filtered due to category " + category);
+ }
}
}
}
diff --git a/src/java/edu/umd/cs/findbugs/CheckBcel.java b/src/java/edu/umd/cs/findbugs/CheckBcel.java
index dd9efd7..5b60878 100644
--- a/src/java/edu/umd/cs/findbugs/CheckBcel.java
+++ b/src/java/edu/umd/cs/findbugs/CheckBcel.java
@@ -25,11 +25,11 @@ import java.lang.reflect.Modifier;
* Check that the BCEL classes present seem to be the right ones. Specifically,
* we check whether the ones extended in FindBugs code are non-final. The
* following BCEL classes are extended in FindBugs code:
- *
+ *
* org.apache.bcel.generic.ObjectType; org.apache.bcel.generic.Type;
* org.apache.bcel.Constants; org.apache.bcel.classfile.EmptyVisitor
* org.apache.bcel.Repository;
- *
+ *
* @author langmead
*/
@@ -62,7 +62,7 @@ public class CheckBcel {
/**
* Check whether given Class is declared final
- *
+ *
* @param c
* the class to check
* @return true iff Class is declared final
@@ -73,7 +73,7 @@ public class CheckBcel {
/**
* Output an appropriate error when a BCEL class looks wrong.
- *
+ *
* @param cname
* name of the BCEL class
*/
@@ -89,7 +89,7 @@ public class CheckBcel {
* Check that the BCEL classes present seem to be the right ones.
* Specifically, we check whether the ones extended in FindBugs code are
* non-final.
- *
+ *
* @return true iff all checks passed
*/
public static boolean check() {
diff --git a/src/java/edu/umd/cs/findbugs/ClassAnnotation.java b/src/java/edu/umd/cs/findbugs/ClassAnnotation.java
index d3f0288..a0af44c 100644
--- a/src/java/edu/umd/cs/findbugs/ClassAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/ClassAnnotation.java
@@ -86,22 +86,24 @@ public class ClassAnnotation extends PackageMemberAnnotation {
return new ClassAnnotation(classDescriptor.toDottedClassName());
}
+ @Override
public void accept(BugAnnotationVisitor visitor) {
visitor.visitClassAnnotation(this);
}
@Override
protected String formatPackageMember(String key, ClassAnnotation primaryClass) {
- if (key.equals("") || key.equals("hash"))
+ if ("".equals(key) || "hash".equals(key)) {
return className;
- else if (key.equals("givenClass"))
+ } else if ("givenClass".equals(key)) {
return shorten(primaryClass.getPackageName(), className);
- else if (key.equals("excludingPackage"))
+ } else if ("excludingPackage".equals(key)) {
return shorten(getPackageName(), className);
- else if (key.equals("simpleClass") || key.equals("simpleName"))
+ } else if ("simpleClass".equals(key) || "simpleName".equals(key)) {
return ClassName.extractSimpleName(className);
- else
+ } else {
throw new IllegalArgumentException("unknown key " + key);
+ }
}
@Override
@@ -111,8 +113,9 @@ public class ClassAnnotation extends PackageMemberAnnotation {
@Override
public boolean equals(Object o) {
- if (!(o instanceof ClassAnnotation))
+ if (!(o instanceof ClassAnnotation)) {
return false;
+ }
ClassAnnotation other = (ClassAnnotation) o;
return className.equals(other.className);
}
@@ -123,17 +126,20 @@ public class ClassAnnotation extends PackageMemberAnnotation {
public ClassAnnotation getTopLevelClass() {
int firstDollar = className.indexOf('$');
- if (firstDollar <= 0)
+ if (firstDollar <= 0) {
return this;
+ }
return new ClassAnnotation(className.substring(0, firstDollar));
}
+ @Override
public int compareTo(BugAnnotation o) {
- if (!(o instanceof ClassAnnotation)) // BugAnnotations must be
- // Comparable with any type of
- // BugAnnotation
+ if (!(o instanceof ClassAnnotation)) {
+ // Comparable with any type of
+ // BugAnnotation
return this.getClass().getName().compareTo(o.getClass().getName());
+ }
ClassAnnotation other = (ClassAnnotation) o;
return className.compareTo(other.className);
}
@@ -145,8 +151,9 @@ public class ClassAnnotation extends PackageMemberAnnotation {
*/
@Override
public SourceLineAnnotation getSourceLines() {
- if (sourceLines == null)
+ if (sourceLines == null) {
this.sourceLines = getSourceLinesForClass(className, sourceFileName);
+ }
return sourceLines;
}
@@ -156,15 +163,17 @@ public class ClassAnnotation extends PackageMemberAnnotation {
AnalysisContext currentAnalysisContext = AnalysisContext.currentAnalysisContext();
- if (currentAnalysisContext == null)
+ if (currentAnalysisContext == null) {
return new SourceLineAnnotation(className, sourceFileName, -1, -1, -1, -1);
+ }
SourceInfoMap.SourceLineRange classLine = currentAnalysisContext.getSourceInfoMap().getClassLine(className);
- if (classLine == null)
+ if (classLine == null) {
return SourceLineAnnotation.getSourceAnnotationForClass(className, sourceFileName);
- else
+ } else {
return new SourceLineAnnotation(className, sourceFileName, classLine.getStart(), classLine.getEnd(), -1, -1);
+ }
}
/*
@@ -175,18 +184,22 @@ public class ClassAnnotation extends PackageMemberAnnotation {
private static final String ELEMENT_NAME = "Class";
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, false, false);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean addMessages, boolean isPrimary) throws IOException {
XMLAttributeList attributeList = new XMLAttributeList().addAttribute("classname", getClassName());
- if (isPrimary)
+ if (isPrimary) {
attributeList.addAttribute("primary", "true");
+ }
String role = getDescription();
- if (!role.equals(DEFAULT_ROLE))
+ if (!DEFAULT_ROLE.equals(role)) {
attributeList.addAttribute("role", role);
+ }
xmlOutput.openTag(ELEMENT_NAME, attributeList);
getSourceLines().writeXML(xmlOutput, addMessages, false);
@@ -200,4 +213,3 @@ public class ClassAnnotation extends PackageMemberAnnotation {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ClassScreener.java b/src/java/edu/umd/cs/findbugs/ClassScreener.java
index 5814a54..89a16d6 100644
--- a/src/java/edu/umd/cs/findbugs/ClassScreener.java
+++ b/src/java/edu/umd/cs/findbugs/ClassScreener.java
@@ -26,14 +26,14 @@ import java.util.regex.Pattern;
/**
* Class to pre-screen class files, so that only a subset are analyzed. This
* supports the -onlyAnalyze command line option.
- *
+ *
* Modified February 2006 in four ways: a) don't break windows platform by
* hard-coding '/' as the directory separator b) store list of Matchers, not
* Patterns, so we don't keep instantiating Matchers c) fix suffix bug, so
* FooBar and Foo$Bar no longer match Bar d) addAllowedPackage() can now handle
* unicode chars in filenames, though we still may not be handling every case
* mentioned in section 7.2.1 of the JLS
- *
+ *
* @see FindBugs
* @author David Hovemeyer
*/
@@ -46,11 +46,11 @@ public class ClassScreener implements IClassScreener {
* general enough
*/
private static final String SEP = "[/\\\\]"; // could include ':' for
- // classic macOS
+ // classic macOS
private static final String START = "(?:^|" + SEP + ")"; // (?:) is a
- // non-capturing
- // group
+ // non-capturing
+ // group
/**
* regular expression fragment to match a char of a class or package name.
@@ -58,7 +58,7 @@ public class ClassScreener implements IClassScreener {
*/
private static final String JAVA_IDENTIFIER_PART = "[^./\\\\]";
- private LinkedList<Matcher> patternList;
+ private final LinkedList<Matcher> patternList;
/**
* Constructor. By default, the ClassScreener will match <em>all</em> class
@@ -73,7 +73,7 @@ public class ClassScreener implements IClassScreener {
/**
* replace the dots in a fully-qualified class/package name to a regular
* expression fragment that will match file names.
- *
+ *
* @param dotsName
* such as "java.io" or "java.io.File"
* @return regex fragment such as "java[/\\\\]io" (single backslash escaped
@@ -96,21 +96,22 @@ public class ClassScreener implements IClassScreener {
/**
* Add the name of a class to be matched by the screener.
- *
+ *
* @param className
* name of a class to be matched
*/
public void addAllowedClass(String className) {
String classRegex = START + dotsToRegex(className) + ".class$";
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Class regex: " + classRegex);
+ }
patternList.add(Pattern.compile(classRegex).matcher(""));
}
/**
* Add the name of a package to be matched by the screener. All class files
* that appear to be in the package should be matched.
- *
+ *
* @param packageName
* name of the package to be matched
*/
@@ -120,8 +121,9 @@ public class ClassScreener implements IClassScreener {
}
String packageRegex = START + dotsToRegex(packageName) + SEP + JAVA_IDENTIFIER_PART + "+.class$";
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Package regex: " + packageRegex);
+ }
patternList.add(Pattern.compile(packageRegex).matcher(""));
}
@@ -129,7 +131,7 @@ public class ClassScreener implements IClassScreener {
* Add the name of a prefix to be matched by the screener. All class files
* that appear to be in the package specified by the prefix, or a more
* deeply nested package, should be matched.
- *
+ *
* @param prefix
* name of the prefix to be matched
*/
@@ -137,52 +139,60 @@ public class ClassScreener implements IClassScreener {
if (prefix.endsWith(".")) {
prefix = prefix.substring(0, prefix.length() - 1);
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Allowed prefix: " + prefix);
+ }
String packageRegex = START + dotsToRegex(prefix) + SEP;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Prefix regex: " + packageRegex);
+ }
patternList.add(Pattern.compile(packageRegex).matcher(""));
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.IClassScreener#matches(java.lang.String)
*/
+ @Override
public boolean matches(String fileName) {
// Special case: if no classes or packages have been defined,
// then the screener matches all class files.
- if (patternList.isEmpty())
+ if (patternList.isEmpty()) {
return true;
+ }
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Matching: " + fileName);
+ }
// Scan through list of regexes
for (Matcher matcher : patternList) {
- if (DEBUG)
+ if (DEBUG) {
System.out.print("\tTrying [" + matcher.pattern());
+ }
matcher.reset(fileName);
if (matcher.find()) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("]: yes!");
+ }
return true;
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("]: no");
+ }
}
return false;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.IClassScreener#vacuous()
*/
+ @Override
public boolean vacuous() {
return patternList.isEmpty();
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ClassWarningSuppressor.java b/src/java/edu/umd/cs/findbugs/ClassWarningSuppressor.java
index 4655c5c..f88d5cd 100644
--- a/src/java/edu/umd/cs/findbugs/ClassWarningSuppressor.java
+++ b/src/java/edu/umd/cs/findbugs/ClassWarningSuppressor.java
@@ -7,8 +7,9 @@ public class ClassWarningSuppressor extends WarningSuppressor {
public ClassWarningSuppressor(String bugPattern, ClassAnnotation clazz) {
super(bugPattern);
this.clazz = clazz;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Suppressing " + bugPattern + " in " + clazz);
+ }
}
public ClassAnnotation getClassAnnotation() {
@@ -18,12 +19,14 @@ public class ClassWarningSuppressor extends WarningSuppressor {
@Override
public boolean match(BugInstance bugInstance) {
- if (!super.match(bugInstance))
+ if (!super.match(bugInstance)) {
return false;
+ }
ClassAnnotation primaryClassAnnotation = bugInstance.getPrimaryClass();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Compare " + primaryClassAnnotation + " with " + clazz);
+ }
return clazz.contains(primaryClassAnnotation);
diff --git a/src/java/edu/umd/cs/findbugs/CommandLineUiCallback.java b/src/java/edu/umd/cs/findbugs/CommandLineUiCallback.java
index 394f010..80d7c00 100644
--- a/src/java/edu/umd/cs/findbugs/CommandLineUiCallback.java
+++ b/src/java/edu/umd/cs/findbugs/CommandLineUiCallback.java
@@ -45,14 +45,17 @@ public class CommandLineUiCallback implements IGuiCallback {
}
BufferedReader br = UserTextFile.bufferedReader(System.in);
+ @Override
public void showMessageDialogAndWait(String message) throws InterruptedException {
System.out.println(message);
}
+ @Override
public void showMessageDialog(String message) {
System.out.println(message);
}
+ @Override
public int showConfirmDialog(String message, String title, String ok, String cancel) {
String confirmStr = "Yes (Y) or No (N)?";
@@ -95,14 +98,17 @@ public class CommandLineUiCallback implements IGuiCallback {
}
}
+ @Override
public InputStream getProgressMonitorInputStream(InputStream in, int length, String msg) {
return in;
}
+ @Override
public void setErrorMessage(String errorMsg) {
System.err.println(errorMsg);
}
+ @Override
public void displayNonmodelMessage(String title, String message) {
System.out.println(String.format("Message: %s%n%s", title, message));
}
@@ -114,10 +120,12 @@ public class CommandLineUiCallback implements IGuiCallback {
* edu.umd.cs.findbugs.IGuiCallback#showQuestionDialog(java.lang.String,
* java.lang.String, java.lang.String)
*/
+ @Override
public String showQuestionDialog(String message, String title, String defaultValue) {
throw new UnsupportedOperationException();
}
+ @Override
public List<String> showForm(String message, String title, List<FormItem> labels) {
throw new UnsupportedOperationException();
}
@@ -127,37 +135,46 @@ public class CommandLineUiCallback implements IGuiCallback {
*
* @see edu.umd.cs.findbugs.IGuiCallback#showDocument(java.net.URL)
*/
+ @Override
public boolean showDocument(URL u) {
return false;
}
+ @Override
public void registerCloud(Project project, BugCollection collection, Cloud cloud) {
}
+ @Override
public ExecutorService getBugUpdateExecutor() {
return bugUpdateExecutor;
}
private static class CurrentThreadExecutorService extends AbstractExecutorService {
+ @Override
public void shutdown() {
}
+ @Override
public List<Runnable> shutdownNow() {
return null;
}
+ @Override
public boolean isShutdown() {
return false;
}
+ @Override
public boolean isTerminated() {
return false;
}
+ @Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return false;
}
+ @Override
public void execute(Runnable command) {
command.run();
}
@@ -168,6 +185,7 @@ public class CommandLineUiCallback implements IGuiCallback {
*
* @see edu.umd.cs.findbugs.IGuiCallback#isHeadless()
*/
+ @Override
public boolean isHeadless() {
return true;
}
@@ -180,6 +198,7 @@ public class CommandLineUiCallback implements IGuiCallback {
* Project, edu.umd.cs.findbugs.BugCollection,
* edu.umd.cs.findbugs.cloud.Cloud)
*/
+ @Override
public void unregisterCloud(Project project, BugCollection collection, Cloud cloud) {
}
@@ -190,6 +209,7 @@ public class CommandLineUiCallback implements IGuiCallback {
* @see
* edu.umd.cs.findbugs.IGuiCallback#invokeInGUIThread(java.lang.Runnable)
*/
+ @Override
public void invokeInGUIThread(Runnable r) {
throw new UnsupportedOperationException();
diff --git a/src/java/edu/umd/cs/findbugs/ComponentPlugin.java b/src/java/edu/umd/cs/findbugs/ComponentPlugin.java
index 2538a31..d287ae0 100644
--- a/src/java/edu/umd/cs/findbugs/ComponentPlugin.java
+++ b/src/java/edu/umd/cs/findbugs/ComponentPlugin.java
@@ -93,8 +93,9 @@ public class ComponentPlugin<T> {
public Class<? extends T> getComponentClass() {
if (!isAvailable()) {
- if (FindBugs.isNoAnalysis())
+ if (FindBugs.isNoAnalysis()) {
throw new IllegalStateException("No analysis set; no component class loaded for " + getPlugin());
+ }
throw new IllegalStateException("No component class for " + getPlugin());
}
return componentClass;
diff --git a/src/java/edu/umd/cs/findbugs/DeepSubtypeAnalysis.java b/src/java/edu/umd/cs/findbugs/DeepSubtypeAnalysis.java
index 2ad2694..ce38879 100644
--- a/src/java/edu/umd/cs/findbugs/DeepSubtypeAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/DeepSubtypeAnalysis.java
@@ -44,8 +44,9 @@ public class DeepSubtypeAnalysis {
try {
remote = AnalysisContext.lookupSystemClass("java.rmi.Remote");
} catch (ClassNotFoundException e) {
- if (storedException == null)
+ if (storedException == null) {
storedException = e;
+ }
}
}
@@ -53,33 +54,38 @@ public class DeepSubtypeAnalysis {
if (type instanceof ArrayType) {
ArrayType a = (ArrayType) type;
Type t = a.getBasicType();
- if (t instanceof ReferenceType)
+ if (t instanceof ReferenceType) {
type = (ReferenceType) t;
- else
+ } else {
return 1.0;
+ }
}
double result = isDeepSerializable(type.getSignature());
if (type instanceof GenericObjectType && Subtypes2.isContainer(type)) {
GenericObjectType gt = (GenericObjectType) type;
List<? extends ReferenceType> parameters = gt.getParameters();
- if (parameters != null) for(ReferenceType t : parameters) {
- double r = isDeepSerializable(t);
- if (result > r)
- result = r;
+ if (parameters != null) {
+ for(ReferenceType t : parameters) {
+ double r = isDeepSerializable(t);
+ if (result > r) {
+ result = r;
+ }
+ }
}
}
-
+
return result;
}
- public static ReferenceType getLeastSerializableTypeComponent(ReferenceType type)
+ public static ReferenceType getLeastSerializableTypeComponent(ReferenceType type)
throws ClassNotFoundException {
if (type instanceof ArrayType) {
ArrayType a = (ArrayType) type;
Type t = a.getBasicType();
- if (t instanceof ReferenceType)
+ if (t instanceof ReferenceType) {
type = (ReferenceType) t;
- else
+ } else {
return type;
+ }
}
ReferenceType result = type;
@@ -87,21 +93,24 @@ public class DeepSubtypeAnalysis {
if (type instanceof GenericObjectType && Subtypes2.isContainer(type)) {
GenericObjectType gt = (GenericObjectType) type;
List<? extends ReferenceType> parameters = gt.getParameters();
- if (parameters != null) for(ReferenceType t : parameters) {
- double r = isDeepSerializable(t);
- if (value > r) {
- value = r;
- result = getLeastSerializableTypeComponent(t);
+ if (parameters != null) {
+ for(ReferenceType t : parameters) {
+ double r = isDeepSerializable(t);
+ if (value > r) {
+ value = r;
+ result = getLeastSerializableTypeComponent(t);
+ }
}
}
}
-
+
return result;
}
public static double isDeepSerializable(@DottedClassName String refSig) throws ClassNotFoundException {
- if (storedException != null)
+ if (storedException != null) {
throw storedException;
+ }
if (isPrimitiveComponentClass(refSig)) {
if (DEBUG) {
@@ -111,8 +120,9 @@ public class DeepSubtypeAnalysis {
}
String refName = getComponentClass(refSig);
- if (refName.equals("java.lang.Object"))
+ if ("java.lang.Object".equals(refName)) {
return 0.99;
+ }
JavaClass refJavaClass = Repository.lookupClass(refName);
return isDeepSerializable(refJavaClass);
@@ -123,12 +133,14 @@ public class DeepSubtypeAnalysis {
}
public static double isDeepRemote(String refSig) {
- if (remote == null)
+ if (remote == null) {
return 0.1;
+ }
String refName = getComponentClass(refSig);
- if (refName.equals("java.lang.Object"))
+ if ("java.lang.Object".equals(refName)) {
return 0.99;
+ }
JavaClass refJavaClass;
try {
@@ -159,21 +171,25 @@ public class DeepSubtypeAnalysis {
}
public static String getComponentClass(String refSig) {
- while (refSig.charAt(0) == '[')
+ while (refSig.charAt(0) == '[') {
refSig = refSig.substring(1);
+ }
// TODO: This method now returns primitive type signatures, is this ok?
- if (refSig.charAt(0) == 'L')
+ if (refSig.charAt(0) == 'L') {
return refSig.substring(1, refSig.length() - 1).replace('/', '.');
+ }
return refSig;
}
public static double isDeepSerializable(JavaClass x) throws ClassNotFoundException {
- if (storedException != null)
+ if (storedException != null) {
throw storedException;
+ }
- if (x.getClassName().equals("java.lang.Object"))
+ if ("java.lang.Object".equals(x.getClassName())) {
return 0.4;
+ }
if (DEBUG) {
System.out.println("checking " + x.getClassName());
@@ -187,8 +203,9 @@ public class DeepSubtypeAnalysis {
return result;
}
- if (x.isFinal())
+ if (x.isFinal()) {
return result;
+ }
double collectionResult = Analyze.deepInstanceOf(x, collection);
double mapResult = Analyze.deepInstanceOf(x, map);
@@ -211,8 +228,9 @@ public class DeepSubtypeAnalysis {
if (x.isAbstract() || x.isInterface()) {
confidence = 0.8;
result = Math.max(result, 0.4);
- } else if (directSubtypes.isEmpty())
+ } else if (directSubtypes.isEmpty()) {
confidence = 0.2;
+ }
double confidence2 = (1 + confidence) / 2;
result = Math.max(result, confidence2 * collectionResult);
@@ -250,7 +268,7 @@ public class DeepSubtypeAnalysis {
}
- if (DEBUG) {
+ if (DEBUG) {
System.out.println("No high results; max: " + result);
}
return result;
diff --git a/src/java/edu/umd/cs/findbugs/DelegatingBugReporter.java b/src/java/edu/umd/cs/findbugs/DelegatingBugReporter.java
index 1ed182e..88b79c3 100644
--- a/src/java/edu/umd/cs/findbugs/DelegatingBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/DelegatingBugReporter.java
@@ -33,7 +33,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
* @author David Hovemeyer
*/
public class DelegatingBugReporter implements BugReporter {
- private BugReporter delegate;
+ private final BugReporter delegate;
/**
* Constructor.
@@ -49,53 +49,66 @@ public class DelegatingBugReporter implements BugReporter {
return this.delegate;
}
+ @Override
public void setErrorVerbosity(int level) {
delegate.setErrorVerbosity(level);
}
+ @Override
public void setPriorityThreshold(int threshold) {
delegate.setPriorityThreshold(threshold);
}
+ @Override
public void observeClass(ClassDescriptor classDescriptor) {
delegate.observeClass(classDescriptor);
}
+ @Override
public void reportBug(@Nonnull BugInstance bugInstance) {
delegate.reportBug(bugInstance);
}
+ @Override
public void logError(String message) {
delegate.logError(message);
}
+ @Override
public void reportMissingClass(ClassNotFoundException ex) {
delegate.reportMissingClass(ex);
}
+ @Override
public void reportMissingClass(ClassDescriptor classDescriptor) {
delegate.reportMissingClass(classDescriptor);
}
+ @Override
public void finish() {
delegate.finish();
}
+ @Override
public void reportQueuedErrors() {
delegate.reportQueuedErrors();
}
+ @Override
public void addObserver(BugReporterObserver observer) {
delegate.addObserver(observer);
}
+ @Override
public ProjectStats getProjectStats() {
return delegate.getProjectStats();
}
+ @Override
public void logError(String message, Throwable e) {
- if (e instanceof MethodUnprofitableException)
+ if (e instanceof MethodUnprofitableException) {
return;
+ }
delegate.logError(message, e);
}
@@ -104,14 +117,15 @@ public class DelegatingBugReporter implements BugReporter {
*
* @param method
*/
+ @Override
public void reportSkippedAnalysis(MethodDescriptor method) {
delegate.reportSkippedAnalysis(method);
}
+ @Override
public @CheckForNull
BugCollection getBugCollection() {
return delegate.getBugCollection();
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/Detector.java b/src/java/edu/umd/cs/findbugs/Detector.java
index 1d3df4f..8543ce5 100644
--- a/src/java/edu/umd/cs/findbugs/Detector.java
+++ b/src/java/edu/umd/cs/findbugs/Detector.java
@@ -29,7 +29,7 @@ public interface Detector extends Priorities {
/**
* Visit the ClassContext for a class which should be analyzed for instances
* of bug patterns.
- *
+ *
* @param classContext
* the ClassContext
*/
@@ -43,4 +43,3 @@ public interface Detector extends Priorities {
public void report();
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/Detector2.java b/src/java/edu/umd/cs/findbugs/Detector2.java
index 33dd18c..adb10b4 100644
--- a/src/java/edu/umd/cs/findbugs/Detector2.java
+++ b/src/java/edu/umd/cs/findbugs/Detector2.java
@@ -24,14 +24,14 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
/**
* Detector interface for new bytecode-framework-neutral architecture.
- *
+ *
* @author David Hovemeyer
*/
public interface Detector2 extends Priorities {
/**
* Visit a class.
- *
+ *
* @param classDescriptor
* descriptor naming the class to visit
* @throws CheckedAnalysisException
@@ -46,7 +46,7 @@ public interface Detector2 extends Priorities {
/**
* Get the name of the detector class.
- *
+ *
* @return the name of the detector class.
*/
public String getDetectorClassName();
diff --git a/src/java/edu/umd/cs/findbugs/DetectorFactory.java b/src/java/edu/umd/cs/findbugs/DetectorFactory.java
index 4d34dc1..5065f0e 100644
--- a/src/java/edu/umd/cs/findbugs/DetectorFactory.java
+++ b/src/java/edu/umd/cs/findbugs/DetectorFactory.java
@@ -57,13 +57,14 @@ public class DetectorFactory {
ReflectionDetectorCreator(Class<?> detectorClass) {
this.detectorClass = detectorClass;
- if (SUPPORT_OLD_DETECTOR_INTERFACE)
+ if (SUPPORT_OLD_DETECTOR_INTERFACE) {
try {
setAnalysisContext = detectorClass.getDeclaredMethod("setAnalysisContext",
new Class[] { AnalysisContext.class });
} catch (NoSuchMethodException e) {
// Ignore
}
+ }
}
@Override
@@ -95,8 +96,9 @@ public class DetectorFactory {
}
if (Detector.class.isAssignableFrom(detectorClass)) {
- if (NonReportingDetector.class.isAssignableFrom(detectorClass))
+ if (NonReportingDetector.class.isAssignableFrom(detectorClass)) {
return new NonReportingDetectorToDetector2Adapter(createDetector(bugReporter));
+ }
return new DetectorToDetector2Adapter(createDetector(bugReporter));
}
@@ -214,8 +216,9 @@ public class DetectorFactory {
* interface
*/
public boolean isDetectorClassSubtypeOf(Class<?> otherClass) {
- if (FindBugs.isNoAnalysis())
+ if (FindBugs.isNoAnalysis()) {
throw new IllegalStateException("No analysis specified");
+ }
return otherClass.isAssignableFrom(detectorCreator.getDetectorClass());
}
@@ -229,7 +232,7 @@ public class DetectorFactory {
return !isDetectorClassSubtypeOf(TrainingDetector.class) && !isDetectorClassSubtypeOf(FirstPassDetector.class);
}
-
+
/**
* Check to see if we are running on a recent-enough JRE for this detector
* to be enabled.
@@ -238,8 +241,9 @@ public class DetectorFactory {
* false if it is too old
*/
public boolean isEnabledForCurrentJRE() {
- if (requireJRE.equals(""))
+ if ("".equals(requireJRE)) {
return true;
+ }
try {
JavaVersion requiredVersion = new JavaVersion(requireJRE);
JavaVersion runtimeVersion = JavaVersion.getRuntimeVersion();
@@ -309,8 +313,9 @@ public class DetectorFactory {
* @return the priority adjustment
*/
public int getPriorityAdjustment() {
- if (enabledButNonReporting)
+ if (enabledButNonReporting) {
return 100;
+ }
return priorityAdjustment;
}
@@ -339,8 +344,9 @@ public class DetectorFactory {
while (tok.hasMoreTokens()) {
String type = tok.nextToken();
BugPattern bugPattern = DetectorFactoryCollection.instance().lookupBugPattern(type);
- if (bugPattern != null)
+ if (bugPattern != null) {
result.add(bugPattern);
+ }
}
return result;
}
@@ -370,8 +376,9 @@ public class DetectorFactory {
*/
@Deprecated
public Detector create(BugReporter bugReporter) {
- if (FindBugs.isNoAnalysis())
+ if (FindBugs.isNoAnalysis()) {
throw new IllegalStateException("No analysis specified");
+ }
return detectorCreator.createDetector(bugReporter);
}
@@ -383,8 +390,9 @@ public class DetectorFactory {
* @return the Detector2
*/
public Detector2 createDetector2(BugReporter bugReporter) {
- if (FindBugs.isNoAnalysis())
+ if (FindBugs.isNoAnalysis()) {
throw new IllegalStateException("No analysis specified");
+ }
return detectorCreator.createDetector2(bugReporter);
}
@@ -394,8 +402,9 @@ public class DetectorFactory {
*/
public String getShortName() {
int endOfPkg = className.lastIndexOf('.');
- if (endOfPkg >= 0)
+ if (endOfPkg >= 0) {
return className.substring(endOfPkg + 1);
+ }
return className;
}
diff --git a/src/java/edu/umd/cs/findbugs/DetectorFactoryChooser.java b/src/java/edu/umd/cs/findbugs/DetectorFactoryChooser.java
index e44ae4a..793c5bb 100644
--- a/src/java/edu/umd/cs/findbugs/DetectorFactoryChooser.java
+++ b/src/java/edu/umd/cs/findbugs/DetectorFactoryChooser.java
@@ -21,13 +21,13 @@ package edu.umd.cs.findbugs;
/**
* Predicate for choosing DetectorFactory objects.
- *
+ *
* @author David Hovemeyer
*/
public interface DetectorFactoryChooser {
/**
* Return whether or not given DetectorFactory should be chosen.
- *
+ *
* @param factory
* the DetectorFactory
* @return true if the DetectorFactory should be chosen, false if not
@@ -37,7 +37,7 @@ public interface DetectorFactoryChooser {
/**
* Enable the factory due to ordering constraints with other enabled
* detectors
- *
+ *
* @param factory
*/
public void enable(DetectorFactory factory);
diff --git a/src/java/edu/umd/cs/findbugs/DetectorFactoryCollection.java b/src/java/edu/umd/cs/findbugs/DetectorFactoryCollection.java
index 0479603..8cf7bf7 100644
--- a/src/java/edu/umd/cs/findbugs/DetectorFactoryCollection.java
+++ b/src/java/edu/umd/cs/findbugs/DetectorFactoryCollection.java
@@ -61,7 +61,7 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
private static final Logger LOGGER = Logger.getLogger(DetectorFactoryCollection.class.getName());
private static final boolean DEBUG_JAWS = SystemProperties.getBoolean("findbugs.jaws.debug");
-// private static final boolean DEBUG = Boolean.getBoolean("dfc.debug");
+ // private static final boolean DEBUG = Boolean.getBoolean("dfc.debug");
private static DetectorFactoryCollection theInstance;
private static final Object lock = new Object();
@@ -78,7 +78,7 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
private final UpdateChecker updateChecker;
private final CopyOnWriteArrayList<PluginUpdateListener> pluginUpdateListeners
- = new CopyOnWriteArrayList<PluginUpdateListener>();
+ = new CopyOnWriteArrayList<PluginUpdateListener>();
private volatile List<UpdateChecker.PluginUpdate> updates;
private boolean updatesForced;
private final Collection<Plugin> pluginsToUpdate;
@@ -166,35 +166,37 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
}
}
- private void setGlobalOptions() {
- globalOptions.clear();
- globalOptionsSetter.clear();
-
- for(Plugin p : plugins()) {
- if (p.isGloballyEnabled()) {
- for(Map.Entry<String, String> e : p.getMyGlobalOptions().entrySet()) {
- String key = e.getKey();
- String value = e.getValue();
- String oldValue = globalOptions.get(key);
-
- if (oldValue != null) {
- if (oldValue.equals(value)) {
- continue;
- }
- Plugin oldP = globalOptionsSetter.get(key);
- throw new RuntimeException(
- "Incompatible global options for " + key + "; conflict between " + oldP.getPluginId() + " and " + p.getPluginId());
- }
- globalOptions.put(key, value);
- globalOptionsSetter.put(key, p);
- }
- }
- }
- }
+ private void setGlobalOptions() {
+ globalOptions.clear();
+ globalOptionsSetter.clear();
+
+ for(Plugin p : plugins()) {
+ if (p.isGloballyEnabled()) {
+ for(Map.Entry<String, String> e : p.getMyGlobalOptions().entrySet()) {
+ String key = e.getKey();
+ String value = e.getValue();
+ String oldValue = globalOptions.get(key);
+
+ if (oldValue != null) {
+ if (oldValue.equals(value)) {
+ continue;
+ }
+ Plugin oldP = globalOptionsSetter.get(key);
+ throw new RuntimeException(
+ "Incompatible global options for " + key + "; conflict between " + oldP.getPluginId() + " and " + p.getPluginId());
+ }
+ globalOptions.put(key, value);
+ globalOptionsSetter.put(key, p);
+ }
+ }
+ }
+ }
+ @Override
public @CheckForNull String getGlobalOption(String key) {
return globalOptions.get(key);
}
+ @Override
public @CheckForNull Plugin getGlobalOptionSetter(String key) {
return globalOptionsSetter.get(key);
}
@@ -216,8 +218,9 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
@Nonnull
public Plugin getCorePlugin() {
- if (corePlugin == null)
+ if (corePlugin == null) {
throw new IllegalStateException("No core plugin");
+ }
return corePlugin;
}
@@ -249,6 +252,33 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
return factoryList;
}
+ public boolean isDisabledByDefault(String bugPatternOrCode) {
+ @CheckForNull BugPattern pattern = lookupBugPattern(bugPatternOrCode);
+ if (pattern != null) {
+ for(DetectorFactory fac : factoryList) {
+ if (fac.isDefaultEnabled() && fac.getReportedBugPatterns().contains(pattern)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ @CheckForNull BugCode code = lookupBugCode(bugPatternOrCode);
+ if (code != null) {
+ for(DetectorFactory fac : factoryList) {
+ if (fac.isDefaultEnabled()) {
+ for(BugPattern p : fac.getReportedBugPatterns()) {
+ if (p.getBugCode().equals(code)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Look up a DetectorFactory by its short name.
*
@@ -277,8 +307,9 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
* Register a DetectorFactory.
*/
void registerDetector(DetectorFactory factory) {
- if (FindBugs.DEBUG)
+ if (FindBugs.DEBUG) {
System.out.println("Registering detector: " + factory.getFullName());
+ }
String detectorName = factory.getShortName();
if(!factoryList.contains(factory)) {
factoryList.add(factory);
@@ -291,8 +322,9 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
}
void unRegisterDetector(DetectorFactory factory) {
- if (FindBugs.DEBUG)
+ if (FindBugs.DEBUG) {
System.out.println("Unregistering detector: " + factory.getFullName());
+ }
String detectorName = factory.getShortName();
factoryList.remove(factory);
factoriesByName.remove(detectorName);
@@ -315,7 +347,7 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
if (findbugsJarCodeBase != null) {
File findbugsJar = new File(findbugsJarCodeBase);
File libDir = findbugsJar.getParentFile();
- if (libDir.getName().equals("lib")) {
+ if ("lib".equals(libDir.getName())) {
String fbHome = libDir.getParent();
FindBugs.setHome(fbHome);
return fbHome;
@@ -324,7 +356,7 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
}
String classFilePath = FindBugs.class.getName().replaceAll("\\.", "/") + ".class";
URL resource = FindBugs.class.getClassLoader().getResource(classFilePath);
- if (resource != null && resource.getProtocol().equals("file")) {
+ if (resource != null && "file".equals(resource.getProtocol())) {
try {
String classfile = URLDecoder.decode(resource.getPath(), Charset.defaultCharset().name());
Matcher m = Pattern.compile("(.*)/.*?/edu/umd.*").matcher(classfile);
@@ -367,10 +399,11 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
}
public static void jawsDebugMessage(String message) {
- if (DEBUG_JAWS)
+ if (DEBUG_JAWS) {
JOptionPane.showMessageDialog(null, message);
- else if (FindBugs.DEBUG)
+ } else if (FindBugs.DEBUG) {
System.err.println(message);
+ }
}
void loadPlugin(Plugin plugin) {
@@ -427,6 +460,7 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
}
}
+ @Override
@SuppressWarnings({"ConstantConditions"})
public void pluginUpdateCheckComplete(List<UpdateChecker.PluginUpdate> newUpdates, boolean force) {
this.updates = newUpdates;
@@ -452,6 +486,7 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
public FutureValue<Collection<UpdateChecker.PluginUpdate>> getUpdates() {
final FutureValue<Collection<UpdateChecker.PluginUpdate>> results = new FutureValue<Collection<UpdateChecker.PluginUpdate>>();
addPluginUpdateListener(new PluginUpdateListener() {
+ @Override
public void pluginUpdateCheckComplete(Collection<UpdateChecker.PluginUpdate> u, boolean force) {
results.set(u);
}
@@ -459,7 +494,7 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
return results;
}
-
+
public Map<String, CloudPlugin> getRegisteredClouds() {
return Collections.unmodifiableMap(registeredClouds);
}
@@ -484,8 +519,9 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
*/
public boolean registerBugCategory(BugCategory bc) {
String category = bc.getCategory();
- if (categoryDescriptionMap.get(category) != null)
+ if (categoryDescriptionMap.get(category) != null) {
return false;
+ }
categoryDescriptionMap.put(category, bc);
return true;
}
@@ -521,7 +557,7 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
* Get an Iterator over all registered bug patterns.
*/
public Collection<BugPattern> getBugPatterns() {
- return bugPatternMap.values();
+ return bugPatternMap.values();
}
/**
@@ -532,6 +568,9 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
* @return the BugPattern, or null if it can't be found
*/
public @CheckForNull BugPattern lookupBugPattern(String bugType) {
+ if (bugType == null) {
+ return null;
+ }
return bugPatternMap.get(bugType);
}
@@ -558,8 +597,9 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
*/
public @Nonnull BugCode getBugCode(String shortBugType) {
BugCode bugCode = lookupBugCode(shortBugType);
- if (bugCode == null)
+ if (bugCode == null) {
throw new IllegalArgumentException("Error: missing bug code for key" + shortBugType);
+ }
return bugCode;
}
@@ -593,11 +633,13 @@ public class DetectorFactoryCollection implements UpdateCheckCallback {
*/
public Collection<String> getBugCategories() {
ArrayList<String> result = new ArrayList<String>(categoryDescriptionMap.size());
- for(BugCategory c : categoryDescriptionMap.values())
- if (!c.isHidden())
+ for(BugCategory c : categoryDescriptionMap.values()) {
+ if (!c.isHidden()) {
result.add(c.getCategory());
+ }
+ }
return result;
- }
+ }
public Collection<BugCategory> getBugCategoryObjects() {
return categoryDescriptionMap.values(); // backed by the Map
diff --git a/src/java/edu/umd/cs/findbugs/DetectorToDetector2Adapter.java b/src/java/edu/umd/cs/findbugs/DetectorToDetector2Adapter.java
index abeb016..2fb8972 100644
--- a/src/java/edu/umd/cs/findbugs/DetectorToDetector2Adapter.java
+++ b/src/java/edu/umd/cs/findbugs/DetectorToDetector2Adapter.java
@@ -29,15 +29,15 @@ import edu.umd.cs.findbugs.log.Profiler;
/**
* An adapter allowing classes implementing the Detector interface to support
* the new Detector2 interface.
- *
+ *
* @author David Hovemeyer
*/
public class DetectorToDetector2Adapter implements Detector2 {
- private Detector detector;
+ private final Detector detector;
/**
* Constructor.
- *
+ *
* @param detector
* the Detector we want to adapt
*/
@@ -47,20 +47,22 @@ public class DetectorToDetector2Adapter implements Detector2 {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector2#finishPass()
*/
+ @Override
public void finishPass() {
detector.report();
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.Detector2#visitClass(edu.umd.cs.findbugs.classfile
* .ClassDescriptor)
*/
+ @Override
public void visitClass(ClassDescriptor classDescriptor) throws CheckedAnalysisException {
// Just get the ClassContext from the analysis cache
@@ -79,9 +81,10 @@ public class DetectorToDetector2Adapter implements Detector2 {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector2#getDetectorClassName()
*/
+ @Override
public String getDetectorClassName() {
return detector.getClass().getName();
}
diff --git a/src/java/edu/umd/cs/findbugs/DiscoverSourceDirectories.java b/src/java/edu/umd/cs/findbugs/DiscoverSourceDirectories.java
index 9cd268e..cbcca0b 100644
--- a/src/java/edu/umd/cs/findbugs/DiscoverSourceDirectories.java
+++ b/src/java/edu/umd/cs/findbugs/DiscoverSourceDirectories.java
@@ -78,47 +78,61 @@ public class DiscoverSourceDirectories {
private static class NoOpErrorLogger implements IErrorLogger {
+ @Override
public void reportMissingClass(ClassNotFoundException ex) {
}
+ @Override
public void reportMissingClass(ClassDescriptor classDescriptor) {
}
+ @Override
public void logError(String message) {
}
+ @Override
public void logError(String message, Throwable e) {
}
+ @Override
public void reportSkippedAnalysis(MethodDescriptor method) {
}
}
private static class NoOpProgress implements Progress {
+ @Override
public void startScanningArchives(int numArchivesToScan) {
}
+ @Override
public void doneScanningArchives() {
}
+ @Override
public void startScanningClasses(int numClassesToScan) {
}
+ @Override
public void finishClass() {
}
+ @Override
public void doneScanningClasses() {
}
+ @Override
public void finishArchive() {
}
+ @Override
public void startRecursiveDirectorySearch() {
}
+ @Override
public void doneRecursiveDirectorySearch() {
}
+ @Override
public void startArchive(String name) {
}
@@ -225,6 +239,7 @@ public class DiscoverSourceDirectories {
// Find all directories underneath the root source directory
progress.startRecursiveDirectorySearch();
RecursiveFileSearch rfs = new RecursiveFileSearch(rootSourceDirectory, new FileFilter() {
+ @Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
@@ -259,7 +274,7 @@ public class DiscoverSourceDirectories {
}
private IClassPath buildClassPath(IClassPathBuilder builder, IClassFactory factory) throws InterruptedException, IOException,
- CheckedAnalysisException {
+ CheckedAnalysisException {
progress.startScanningArchives(project.getFileCount());
@@ -281,7 +296,7 @@ public class DiscoverSourceDirectories {
}
private String findFullyQualifiedSourceFileName(IClassPath classPath, ClassDescriptor classDesc) throws IOException,
- CheckedAnalysisException {
+ CheckedAnalysisException {
try {
// Open and parse the class file to attempt
// to discover the source file name.
@@ -299,7 +314,7 @@ public class DiscoverSourceDirectories {
String packageName = classDesc.getPackageName();
String sourceFile = classInfo.getSource();
- if (!packageName.equals("")) {
+ if (!"".equals(packageName)) {
packageName = packageName.replace('.', '/');
packageName += "/";
}
@@ -387,6 +402,7 @@ public class DiscoverSourceDirectories {
IErrorLogger errorLogger = new IErrorLogger() {
+ @Override
public void reportMissingClass(ClassNotFoundException ex) {
String className = ClassNotFoundExceptionParser.getMissingClassName(ex);
if (className != null) {
@@ -396,18 +412,22 @@ public class DiscoverSourceDirectories {
}
}
+ @Override
public void reportMissingClass(ClassDescriptor classDescriptor) {
logError("Missing class: " + classDescriptor.toDottedClassName());
}
+ @Override
public void logError(String message) {
System.err.println("Error: " + message);
}
+ @Override
public void logError(String message, Throwable e) {
logError(message + ": " + e.getMessage());
}
+ @Override
public void reportSkippedAnalysis(MethodDescriptor method) {
logError("Skipped analysis of method " + method.toString());
}
@@ -416,43 +436,52 @@ public class DiscoverSourceDirectories {
DiscoverSourceDirectories.Progress progress = new DiscoverSourceDirectories.Progress() {
+ @Override
public void startRecursiveDirectorySearch() {
System.out.print("Scanning directories...");
System.out.flush();
}
+ @Override
public void doneRecursiveDirectorySearch() {
System.out.println("done");
}
+ @Override
public void startScanningArchives(int numArchivesToScan) {
System.out.print("Scanning " + numArchivesToScan + " archives..");
System.out.flush();
}
+ @Override
public void doneScanningArchives() {
System.out.println("done");
}
+ @Override
public void startScanningClasses(int numClassesToScan) {
System.out.print("Scanning " + numClassesToScan + " classes...");
System.out.flush();
}
+ @Override
public void finishClass() {
System.out.print(".");
System.out.flush();
}
+ @Override
public void doneScanningClasses() {
System.out.println("done");
}
+ @Override
public void finishArchive() {
System.out.print(".");
System.out.flush();
}
+ @Override
public void startArchive(String name) {
// noop
}
diff --git a/src/java/edu/umd/cs/findbugs/EmacsBugReporter.java b/src/java/edu/umd/cs/findbugs/EmacsBugReporter.java
index 1bb0296..8404f23 100644
--- a/src/java/edu/umd/cs/findbugs/EmacsBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/EmacsBugReporter.java
@@ -39,10 +39,11 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
*/
public class EmacsBugReporter extends TextUIBugReporter {
- private HashSet<BugInstance> seenAlready = new HashSet<BugInstance>();
+ private final HashSet<BugInstance> seenAlready = new HashSet<BugInstance>();
- private HashMap<String, String> sourceFileNameCache = new HashMap<String, String>();
+ private final HashMap<String, String> sourceFileNameCache = new HashMap<String, String>();
+ @Override
public void observeClass(ClassDescriptor classDescriptor) {
try {
JavaClass javaClass = AnalysisContext.currentAnalysisContext().lookupClass(classDescriptor.toDottedClassName());
@@ -79,10 +80,11 @@ public class EmacsBugReporter extends TextUIBugReporter {
try {
fullPath = sourceFinder.findSourceFile(pkgName, line.getSourceFile()).getFullFileName();
} catch (IOException e) {
- if (pkgName.equals(""))
+ if ("".equals(pkgName)) {
fullPath = line.getSourceFile();
- else
+ } else {
fullPath = pkgName.replace('.', '/') + "/" + line.getSourceFile();
+ }
}
outputStream.print(fullPath + ":" + lineStart + ":" + lineEnd + " " + bugInstance.getMessage());
@@ -114,10 +116,12 @@ public class EmacsBugReporter extends TextUIBugReporter {
}
}
+ @Override
public void finish() {
outputStream.close();
}
+ @Override
public @CheckForNull
BugCollection getBugCollection() {
return null;
diff --git a/src/java/edu/umd/cs/findbugs/ErrorCountingBugReporter.java b/src/java/edu/umd/cs/findbugs/ErrorCountingBugReporter.java
index e7e3e44..55eb20c 100644
--- a/src/java/edu/umd/cs/findbugs/ErrorCountingBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/ErrorCountingBugReporter.java
@@ -28,18 +28,19 @@ import java.util.Set;
public class ErrorCountingBugReporter extends DelegatingBugReporter {
private int bugCount;
- private HashSet<String> errors = new HashSet<String>();
+ private final HashSet<String> errors = new HashSet<String>();
- private Set<String> missingClassSet = new HashSet<String>();
+ private final Set<String> missingClassSet = new HashSet<String>();
public ErrorCountingBugReporter(BugReporter realBugReporter) {
super(realBugReporter);
this.bugCount = 0;
-
+
// Add an observer to record when bugs make it through
// all priority and filter criteria, so our bug count is
// accurate.
realBugReporter.addObserver(new BugReporterObserver() {
+ @Override
public void reportBug(BugInstance bugInstance) {
++bugCount;
}
@@ -60,14 +61,15 @@ public class ErrorCountingBugReporter extends DelegatingBugReporter {
@Override
public void logError(String message) {
- if (errors.add(message))
- super.logError(message);
+ if (errors.add(message)) {
+ super.logError(message);
+ }
}
@Override
public void reportMissingClass(ClassNotFoundException ex) {
String missing = AbstractBugReporter.getMissingClassName(ex);
- if (missing == null || missing.startsWith("[") || missing.equals("java.lang.Synthetic")) {
+ if (missing == null || missing.startsWith("[") || "java.lang.Synthetic".equals(missing)) {
return;
}
if (missingClassSet.add(missing)) {
diff --git a/src/java/edu/umd/cs/findbugs/ExcludingHashesBugReporter.java b/src/java/edu/umd/cs/findbugs/ExcludingHashesBugReporter.java
index 8c02556..4074376 100644
--- a/src/java/edu/umd/cs/findbugs/ExcludingHashesBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/ExcludingHashesBugReporter.java
@@ -50,19 +50,21 @@ public class ExcludingHashesBugReporter extends DelegatingBugReporter {
* @throws DocumentException
*/
public static void addToExcludedInstanceHashes(Set<String> instanceHashesToExclude, String baseline) throws IOException,
- DocumentException {
+ DocumentException {
Project project = new Project();
BugCollection origCollection;
origCollection = new SortedBugCollection(project);
origCollection.readXML(baseline);
- for (BugInstance b : origCollection.getCollection())
+ for (BugInstance b : origCollection.getCollection()) {
instanceHashesToExclude.add(b.getInstanceHash());
+ }
}
@Override
public void reportBug(@Nonnull BugInstance bugInstance) {
String instanceHash = bugInstance.getInstanceHash();
- if (!excludedHashes.contains(instanceHash))
+ if (!excludedHashes.contains(instanceHash)) {
getDelegate().reportBug(bugInstance);
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ExitCodes.java b/src/java/edu/umd/cs/findbugs/ExitCodes.java
index a951115..c7d06b7 100644
--- a/src/java/edu/umd/cs/findbugs/ExitCodes.java
+++ b/src/java/edu/umd/cs/findbugs/ExitCodes.java
@@ -41,4 +41,3 @@ public interface ExitCodes {
public static final int BUGS_FOUND_FLAG = 1;
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/FatalException.java b/src/java/edu/umd/cs/findbugs/FatalException.java
index e326a85..bd4a178 100644
--- a/src/java/edu/umd/cs/findbugs/FatalException.java
+++ b/src/java/edu/umd/cs/findbugs/FatalException.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs;
/**
* A fatal exception which should completely halt the FindBugs analysis. Use
* sparingly.
- *
+ *
* @author David Hovemeyer
*/
public class FatalException extends RuntimeException {
@@ -29,7 +29,7 @@ public class FatalException extends RuntimeException {
/**
* Constructor.
- *
+ *
* @param msg
* message describing the exception
*/
@@ -39,7 +39,7 @@ public class FatalException extends RuntimeException {
/**
* Constructor.
- *
+ *
* @param msg
* message describing the exception
* @param cause
diff --git a/src/java/edu/umd/cs/findbugs/FieldAnnotation.java b/src/java/edu/umd/cs/findbugs/FieldAnnotation.java
index 1962f3d..f78e000 100644
--- a/src/java/edu/umd/cs/findbugs/FieldAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/FieldAnnotation.java
@@ -47,7 +47,7 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* A BugAnnotation specifying a particular field in particular class.
- *
+ *
* @author David Hovemeyer
* @see BugAnnotation
*/
@@ -68,17 +68,17 @@ public class FieldAnnotation extends PackageMemberAnnotation {
public static final String ARGUMENT_ROLE = "FIELD_ARGUMENT";
- private String fieldName;
+ private final String fieldName;
- private String fieldSig;
+ private final String fieldSig;
private String fieldSourceSig;
- private boolean isStatic;
+ private final boolean isStatic;
/**
* Constructor.
- *
+ *
* @param className
* the name of the class containing the field
* @param fieldName
@@ -88,9 +88,9 @@ public class FieldAnnotation extends PackageMemberAnnotation {
*/
public FieldAnnotation(@DottedClassName String className, String fieldName, String fieldSig, boolean isStatic) {
super(className, DEFAULT_ROLE);
- if (fieldSig.indexOf(".") >= 0) {
+ if (fieldSig.indexOf('.') >= 0) {
assert false : "signatures should not be dotted: " + fieldSig;
- fieldSig = fieldSig.replace('.', '/');
+ fieldSig = fieldSig.replace('.', '/');
}
this.fieldName = fieldName;
this.fieldSig = fieldSig;
@@ -105,7 +105,7 @@ public class FieldAnnotation extends PackageMemberAnnotation {
/**
* Constructor.
- *
+ *
* @param className
* the name of the class containing the field
* @param fieldName
@@ -122,7 +122,7 @@ public class FieldAnnotation extends PackageMemberAnnotation {
/**
* Factory method. Class name, field name, and field signatures are taken
* from the given visitor, which is visiting the field.
- *
+ *
* @param visitor
* the visitor which is visiting the field
* @return the FieldAnnotation object
@@ -136,7 +136,7 @@ public class FieldAnnotation extends PackageMemberAnnotation {
* Factory method. Class name, field name, and field signatures are taken
* from the given visitor, which is visiting a reference to the field (i.e.,
* a getfield or getstatic instruction).
- *
+ *
* @param visitor
* the visitor which is visiting the field reference
* @return the FieldAnnotation object
@@ -149,7 +149,7 @@ public class FieldAnnotation extends PackageMemberAnnotation {
/**
* Factory method. Construct from class name and BCEL Field object.
- *
+ *
* @param className
* the name of the class which defines the field
* @param field
@@ -162,7 +162,7 @@ public class FieldAnnotation extends PackageMemberAnnotation {
/**
* Factory method. Construct from class name and BCEL Field object.
- *
+ *
* @param jClass
* the class which defines the field
* @param field
@@ -175,7 +175,7 @@ public class FieldAnnotation extends PackageMemberAnnotation {
/**
* Factory method. Construct from a FieldDescriptor.
- *
+ *
* @param fieldDescriptor
* the FieldDescriptor
* @return the FieldAnnotation
@@ -190,13 +190,13 @@ public class FieldAnnotation extends PackageMemberAnnotation {
fieldDescriptor.getSourceSignature(), fieldDescriptor.isStatic());
}
-
+
public XField toXField() {
return XFactory.createXField(className, fieldName, fieldSig, isStatic);
}
-
+
public FieldDescriptor toFieldDescriptor() {
- return DescriptorFactory.instance().getFieldDescriptor(this);
+ return DescriptorFactory.instance().getFieldDescriptor(this);
}
/**
* Get the field name.
@@ -221,7 +221,7 @@ public class FieldAnnotation extends PackageMemberAnnotation {
/**
* Is the given instruction a read of a field?
- *
+ *
* @param ins
* the Instruction to check
* @param cpg
@@ -233,13 +233,14 @@ public class FieldAnnotation extends PackageMemberAnnotation {
FieldInstruction fins = (FieldInstruction) ins;
String className = fins.getClassName(cpg);
return new FieldAnnotation(className, fins.getName(cpg), fins.getSignature(cpg), fins instanceof GETSTATIC);
- } else
+ } else {
return null;
+ }
}
/**
* Is the instruction a write of a field?
- *
+ *
* @param ins
* the Instruction to check
* @param cpg
@@ -251,55 +252,59 @@ public class FieldAnnotation extends PackageMemberAnnotation {
FieldInstruction fins = (FieldInstruction) ins;
String className = fins.getClassName(cpg);
return new FieldAnnotation(className, fins.getName(cpg), fins.getSignature(cpg), fins instanceof PUTSTATIC);
- } else
+ } else {
return null;
+ }
}
+ @Override
public void accept(BugAnnotationVisitor visitor) {
visitor.visitFieldAnnotation(this);
}
@Override
protected String formatPackageMember(String key, ClassAnnotation primaryClass) {
- if (key.equals("") || key.equals("hash"))
+ if ("".equals(key) || "hash".equals(key)) {
return className + "." + fieldName;
- else if (key.equals("givenClass")) {
+ } else if ("givenClass".equals(key)) {
String primaryClassName = primaryClass.getClassName();
- if (className.equals(primaryClassName))
+ if (className.equals(primaryClassName)) {
return getNameInClass(primaryClass);
- else
+ } else {
return shorten(primaryClass.getPackageName(), className) + "." + fieldName;
- } else if (key.equals("name"))
+ }
+ } else if ("name".equals(key)) {
return fieldName;
- else if (key.equals("fullField")) {
+ } else if ("fullField".equals(key)) {
SignatureConverter converter = new SignatureConverter(fieldSig);
StringBuilder result = new StringBuilder();
- if (isStatic)
+ if (isStatic) {
result.append("static ");
+ }
result.append(converter.parseNext());
result.append(' ');
result.append(className);
result.append('.');
result.append(fieldName);
return result.toString();
- } else
+ } else {
throw new IllegalArgumentException("unknown key " + key);
+ }
}
- /**
- * @param primaryClass
- * @return
- */
private String getNameInClass(ClassAnnotation primaryClass) {
- if (primaryClass == null)
+ if (primaryClass == null) {
return className + "." + fieldName;
+ }
String givenPackageName = primaryClass.getPackageName();
String thisPackageName = this.getPackageName();
- if (thisPackageName.equals(givenPackageName))
- if (thisPackageName.length() == 0)
+ if (thisPackageName.equals(givenPackageName)) {
+ if (thisPackageName.length() == 0) {
return fieldName;
- else
+ } else {
return className.substring(thisPackageName.length() + 1) + "." + fieldName;
+ }
+ }
return className + "." + fieldName;
}
@@ -310,49 +315,50 @@ public class FieldAnnotation extends PackageMemberAnnotation {
@Override
public boolean equals(Object o) {
- if (!(o instanceof FieldAnnotation))
+ if (!(o instanceof FieldAnnotation)) {
return false;
+ }
FieldAnnotation other = (FieldAnnotation) o;
return className.equals(other.className) && fieldName.equals(other.fieldName) && fieldSig.equals(other.fieldSig)
&& isStatic == other.isStatic;
}
+ @Override
public int compareTo(BugAnnotation o) {
- if (!(o instanceof FieldAnnotation)) // BugAnnotations must be
- // Comparable with any type of
- // BugAnnotation
+ if (!(o instanceof FieldAnnotation)) {
+ // Comparable with any type of
+ // BugAnnotation
return this.getClass().getName().compareTo(o.getClass().getName());
+ }
FieldAnnotation other = (FieldAnnotation) o;
int cmp;
cmp = className.compareTo(other.className);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
cmp = fieldName.compareTo(other.fieldName);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return fieldSig.compareTo(other.fieldSig);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.PackageMemberAnnotation#getSourceLines()
- */
@Override
public SourceLineAnnotation getSourceLines() {
if (sourceLines == null) {
// Create source line annotation for field on demand
AnalysisContext currentAnalysisContext = AnalysisContext.currentAnalysisContext();
- if (currentAnalysisContext == null)
+ if (currentAnalysisContext == null) {
sourceLines = new SourceLineAnnotation(className, sourceFileName, -1, -1, -1, -1);
- else {
+ } else {
SourceInfoMap.SourceLineRange fieldLine = currentAnalysisContext.getSourceInfoMap().getFieldLine(className,
fieldName);
- if (fieldLine == null)
+ if (fieldLine == null) {
sourceLines = new SourceLineAnnotation(className, sourceFileName, -1, -1, -1, -1);
- else
+ } else {
sourceLines = new SourceLineAnnotation(className, sourceFileName, fieldLine.getStart(), fieldLine.getEnd(),
-1, -1);
+ }
}
}
return sourceLines;
@@ -366,22 +372,27 @@ public class FieldAnnotation extends PackageMemberAnnotation {
private static final String ELEMENT_NAME = "Field";
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, false, false);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean addMessages, boolean isPrimary) throws IOException {
XMLAttributeList attributeList = new XMLAttributeList().addAttribute("classname", getClassName())
.addAttribute("name", getFieldName()).addAttribute("signature", getFieldSignature());
- if (fieldSourceSig != null)
+ if (fieldSourceSig != null) {
attributeList.addAttribute("sourceSignature", fieldSourceSig);
+ }
attributeList.addAttribute("isStatic", String.valueOf(isStatic()));
- if (isPrimary)
+ if (isPrimary) {
attributeList.addAttribute("primary", "true");
+ }
String role = getDescription();
- if (!role.equals(DEFAULT_ROLE))
+ if (!DEFAULT_ROLE.equals(role)) {
attributeList.addAttribute("role", role);
+ }
xmlOutput.openTag(ELEMENT_NAME, attributeList);
getSourceLines().writeXML(xmlOutput, addMessages, false);
@@ -393,5 +404,3 @@ public class FieldAnnotation extends PackageMemberAnnotation {
xmlOutput.closeTag(ELEMENT_NAME);
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/FieldWarningSuppressor.java b/src/java/edu/umd/cs/findbugs/FieldWarningSuppressor.java
index 3cb46ab..3742561 100644
--- a/src/java/edu/umd/cs/findbugs/FieldWarningSuppressor.java
+++ b/src/java/edu/umd/cs/findbugs/FieldWarningSuppressor.java
@@ -9,7 +9,7 @@ public class FieldWarningSuppressor extends ClassWarningSuppressor {
this.field = field;
}
-
+
@Override
public String toString() {
return String.format("Supress %s in %s.%s", bugPattern, clazz, field);
@@ -17,14 +17,17 @@ public class FieldWarningSuppressor extends ClassWarningSuppressor {
@Override
public boolean match(BugInstance bugInstance) {
- if (!super.match(bugInstance))
+ if (!super.match(bugInstance)) {
return false;
+ }
FieldAnnotation bugField = bugInstance.getPrimaryField();
- if (bugField == null || !field.equals(bugField))
+ if (bugField == null || !field.equals(bugField)) {
return false;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("Suppressing " + bugInstance);
+ }
return true;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/FilterBugReporter.java b/src/java/edu/umd/cs/findbugs/FilterBugReporter.java
index 49d6ad2..4ea396f 100644
--- a/src/java/edu/umd/cs/findbugs/FilterBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/FilterBugReporter.java
@@ -26,9 +26,9 @@ import edu.umd.cs.findbugs.filter.Matcher;
public class FilterBugReporter extends DelegatingBugReporter {
private static final boolean DEBUG = SystemProperties.getBoolean("filter.debug");
- private Matcher filter;
+ private final Matcher filter;
- private boolean include;
+ private final boolean include;
public FilterBugReporter(BugReporter realBugReporter, Matcher filter, boolean include) {
super(realBugReporter);
@@ -38,14 +38,16 @@ public class FilterBugReporter extends DelegatingBugReporter {
@Override
public void reportBug(@Nonnull BugInstance bugInstance) {
- if (DEBUG)
+ if (DEBUG) {
System.out.print("Match ==> ");
+ }
boolean match = filter.match(bugInstance);
- if (DEBUG)
+ if (DEBUG) {
System.out.println(match ? "YES" : "NO");
- if (include == match)
+ }
+ if (include == match) {
getDelegate().reportBug(bugInstance);
+ }
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/FindBugs.java b/src/java/edu/umd/cs/findbugs/FindBugs.java
index 293a580..97d9cd7 100644
--- a/src/java/edu/umd/cs/findbugs/FindBugs.java
+++ b/src/java/edu/umd/cs/findbugs/FindBugs.java
@@ -58,76 +58,76 @@ public abstract class FindBugs {
* Analysis settings for -effort:min.
*/
public static final AnalysisFeatureSetting[] MIN_EFFORT = new AnalysisFeatureSetting[] {
- new AnalysisFeatureSetting(AnalysisFeatures.CONSERVE_SPACE, true),
- new AnalysisFeatureSetting(AnalysisFeatures.ACCURATE_EXCEPTIONS, false),
- new AnalysisFeatureSetting(AnalysisFeatures.MERGE_SIMILAR_WARNINGS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.MODEL_INSTANCEOF, false),
- new AnalysisFeatureSetting(AnalysisFeatures.SKIP_HUGE_METHODS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.TRACK_GUARANTEED_VALUE_DEREFS_IN_NULL_POINTER_ANALYSIS, false),
- new AnalysisFeatureSetting(AnalysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_ANALYSIS, false),
- new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS, false),
- new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES, false), };
+ new AnalysisFeatureSetting(AnalysisFeatures.CONSERVE_SPACE, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.ACCURATE_EXCEPTIONS, false),
+ new AnalysisFeatureSetting(AnalysisFeatures.MERGE_SIMILAR_WARNINGS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.MODEL_INSTANCEOF, false),
+ new AnalysisFeatureSetting(AnalysisFeatures.SKIP_HUGE_METHODS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.TRACK_GUARANTEED_VALUE_DEREFS_IN_NULL_POINTER_ANALYSIS, false),
+ new AnalysisFeatureSetting(AnalysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_ANALYSIS, false),
+ new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS, false),
+ new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES, false), };
/**
* Analysis settings for -effort:less.
*/
public static final AnalysisFeatureSetting[] LESS_EFFORT = new AnalysisFeatureSetting[] {
- new AnalysisFeatureSetting(AnalysisFeatures.CONSERVE_SPACE, false),
- new AnalysisFeatureSetting(AnalysisFeatures.ACCURATE_EXCEPTIONS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.MERGE_SIMILAR_WARNINGS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.MODEL_INSTANCEOF, true),
- new AnalysisFeatureSetting(AnalysisFeatures.SKIP_HUGE_METHODS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.TRACK_GUARANTEED_VALUE_DEREFS_IN_NULL_POINTER_ANALYSIS, false),
- new AnalysisFeatureSetting(AnalysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_ANALYSIS, false),
- new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS, false),
- new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES, false), };
+ new AnalysisFeatureSetting(AnalysisFeatures.CONSERVE_SPACE, false),
+ new AnalysisFeatureSetting(AnalysisFeatures.ACCURATE_EXCEPTIONS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.MERGE_SIMILAR_WARNINGS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.MODEL_INSTANCEOF, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.SKIP_HUGE_METHODS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.TRACK_GUARANTEED_VALUE_DEREFS_IN_NULL_POINTER_ANALYSIS, false),
+ new AnalysisFeatureSetting(AnalysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_ANALYSIS, false),
+ new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS, false),
+ new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES, false), };
/**
* Analysis settings for -effort:default.
*/
public static final AnalysisFeatureSetting[] DEFAULT_EFFORT = new AnalysisFeatureSetting[] {
- new AnalysisFeatureSetting(AnalysisFeatures.CONSERVE_SPACE, false),
- new AnalysisFeatureSetting(AnalysisFeatures.ACCURATE_EXCEPTIONS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.MERGE_SIMILAR_WARNINGS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.MODEL_INSTANCEOF, true),
- new AnalysisFeatureSetting(AnalysisFeatures.SKIP_HUGE_METHODS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.TRACK_GUARANTEED_VALUE_DEREFS_IN_NULL_POINTER_ANALYSIS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_ANALYSIS, true),
- new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS, true),
- new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES, false), };
+ new AnalysisFeatureSetting(AnalysisFeatures.CONSERVE_SPACE, false),
+ new AnalysisFeatureSetting(AnalysisFeatures.ACCURATE_EXCEPTIONS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.MERGE_SIMILAR_WARNINGS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.MODEL_INSTANCEOF, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.SKIP_HUGE_METHODS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.TRACK_GUARANTEED_VALUE_DEREFS_IN_NULL_POINTER_ANALYSIS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_ANALYSIS, true),
+ new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS, true),
+ new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES, false), };
/**
* Analysis settings for -effort:more.
*/
public static final AnalysisFeatureSetting[] MORE_EFFORT = new AnalysisFeatureSetting[] {
- new AnalysisFeatureSetting(AnalysisFeatures.CONSERVE_SPACE, false),
- new AnalysisFeatureSetting(AnalysisFeatures.ACCURATE_EXCEPTIONS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.MERGE_SIMILAR_WARNINGS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.MODEL_INSTANCEOF, true),
- new AnalysisFeatureSetting(AnalysisFeatures.SKIP_HUGE_METHODS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.TRACK_GUARANTEED_VALUE_DEREFS_IN_NULL_POINTER_ANALYSIS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_ANALYSIS, true),
- new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS, true),
- new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES, false), };
+ new AnalysisFeatureSetting(AnalysisFeatures.CONSERVE_SPACE, false),
+ new AnalysisFeatureSetting(AnalysisFeatures.ACCURATE_EXCEPTIONS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.MERGE_SIMILAR_WARNINGS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.MODEL_INSTANCEOF, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.SKIP_HUGE_METHODS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.TRACK_GUARANTEED_VALUE_DEREFS_IN_NULL_POINTER_ANALYSIS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_ANALYSIS, true),
+ new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS, true),
+ new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES, false), };
/**
* Analysis settings for -effort:max.
*/
public static final AnalysisFeatureSetting[] MAX_EFFORT = new AnalysisFeatureSetting[] {
- new AnalysisFeatureSetting(AnalysisFeatures.CONSERVE_SPACE, false),
- new AnalysisFeatureSetting(AnalysisFeatures.ACCURATE_EXCEPTIONS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.MERGE_SIMILAR_WARNINGS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.MODEL_INSTANCEOF, true),
- new AnalysisFeatureSetting(AnalysisFeatures.SKIP_HUGE_METHODS, false),
- new AnalysisFeatureSetting(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.TRACK_GUARANTEED_VALUE_DEREFS_IN_NULL_POINTER_ANALYSIS, true),
- new AnalysisFeatureSetting(AnalysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_ANALYSIS, true),
- new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS, true),
- new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES, true), };
+ new AnalysisFeatureSetting(AnalysisFeatures.CONSERVE_SPACE, false),
+ new AnalysisFeatureSetting(AnalysisFeatures.ACCURATE_EXCEPTIONS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.MERGE_SIMILAR_WARNINGS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.MODEL_INSTANCEOF, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.SKIP_HUGE_METHODS, false),
+ new AnalysisFeatureSetting(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.TRACK_GUARANTEED_VALUE_DEREFS_IN_NULL_POINTER_ANALYSIS, true),
+ new AnalysisFeatureSetting(AnalysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_ANALYSIS, true),
+ new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS, true),
+ new AnalysisFeatureSetting(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES, true), };
/**
* Debug tracing.
@@ -214,8 +214,9 @@ public abstract class FindBugs {
if (findBugs.emitTrainingOutput()) {
String trainingOutputDir = findBugs.getTrainingOutputDir();
- if (!new File(trainingOutputDir).isDirectory())
+ if (!new File(trainingOutputDir).isDirectory()) {
throw new IOException("Training output directory " + trainingOutputDir + " does not exist");
+ }
AnalysisContext.currentAnalysisContext().setDatabaseOutputDir(trainingOutputDir);
// XXX: hack
System.setProperty("findbugs.checkreturn.savetraining", new File(trainingOutputDir, "checkReturn.db").getPath());
@@ -223,8 +224,9 @@ public abstract class FindBugs {
if (findBugs.useTrainingInput()) {
String trainingInputDir = findBugs.getTrainingInputDir();
- if (!new File(trainingInputDir).isDirectory())
+ if (!new File(trainingInputDir).isDirectory()) {
throw new IOException("Training input directory " + trainingInputDir + " does not exist");
+ }
AnalysisContext.currentAnalysisContext().setDatabaseInputDir(trainingInputDir);
AnalysisContext.currentAnalysisContext().loadInterproceduralDatabases();
// XXX: hack
@@ -247,17 +249,20 @@ public abstract class FindBugs {
*/
public static boolean isDetectorEnabled(IFindBugsEngine findBugs, DetectorFactory factory, int rankThreshold) {
- if (!findBugs.getUserPreferences().isDetectorEnabled(factory))
+ if (!findBugs.getUserPreferences().isDetectorEnabled(factory)) {
return false;
+ }
- if (!factory.isEnabledForCurrentJRE())
+ if (!factory.isEnabledForCurrentJRE()) {
return false;
+ }
// Slow first pass detectors are usually disabled, but may be explicitly
// enabled
if (!AnalysisContext.currentAnalysisContext().getBoolProperty(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS)
- && factory.isDetectorClassSubtypeOf(InterproceduralFirstPassDetector.class))
+ && factory.isDetectorClassSubtypeOf(InterproceduralFirstPassDetector.class)) {
return false;
+ }
int maxRank = Integer.MAX_VALUE;
Set<BugPattern> reportedBugPatterns = factory.getReportedBugPatterns();
@@ -265,8 +270,9 @@ public abstract class FindBugs {
if (!isNonReportingDetector && !reportedBugPatterns.isEmpty()) {
for (BugPattern b : reportedBugPatterns) {
int rank = BugRanker.findRank(b, factory);
- if (maxRank > rank)
+ if (maxRank > rank) {
maxRank = rank;
+ }
}
if (maxRank > rankThreshold) {
if (false) {
@@ -284,8 +290,9 @@ public abstract class FindBugs {
return isTrainingDetector || isNonReportingDetector;
}
- if (isTrainingDetector)
+ if (isTrainingDetector) {
return false;
+ }
return true;
}
@@ -346,8 +353,9 @@ public abstract class FindBugs {
}
Project project = commandLine.getProject();
- for (int i = argCount; i < argv.length; ++i)
+ for (int i = argCount; i < argv.length; ++i) {
project.addFile(argv[i]);
+ }
commandLine.handleXArgs();
commandLine.configureEngine(findBugs);
@@ -385,11 +393,12 @@ public abstract class FindBugs {
public static void runMain(IFindBugsEngine findBugs, TextUICommandLine commandLine) throws IOException {
boolean verbose = !commandLine.quiet() || commandLine.setExitCode();
- FutureValue<Collection<UpdateChecker.PluginUpdate>>
+ FutureValue<Collection<UpdateChecker.PluginUpdate>>
updateHolder = null;
- if (verbose)
+ if (verbose) {
updateHolder = DetectorFactoryCollection.instance().getUpdates();
- try {
+ }
+ try {
findBugs.execute();
} catch (InterruptedException e) {
assert false; // should not occur
@@ -408,22 +417,26 @@ public abstract class FindBugs {
int errorCount = findBugs.getErrorCount();
if (verbose) {
- if (bugCount > 0)
+ if (bugCount > 0) {
System.err.println("Warnings generated: " + bugCount);
- if (missingClassCount > 0)
+ }
+ if (missingClassCount > 0) {
System.err.println("Missing classes: " + missingClassCount);
- if (errorCount > 0)
+ }
+ if (errorCount > 0) {
System.err.println("Analysis errors: " + errorCount);
- if (updateHolder.isDone()) {
- try {
- Collection<PluginUpdate> updates = updateHolder.get();
- if (!DetectorFactoryCollection.instance().getUpdateChecker().updatesHaveBeenSeenBefore(updates))
- for(UpdateChecker.PluginUpdate u : updates) {
- System.err.println(u);
- }
- } catch (InterruptedException e) {
- assert true;
}
+ if (updateHolder.isDone()) {
+ try {
+ Collection<PluginUpdate> updates = updateHolder.get();
+ if (!DetectorFactoryCollection.instance().getUpdateChecker().updatesHaveBeenSeenBefore(updates)) {
+ for(UpdateChecker.PluginUpdate u : updates) {
+ System.err.println(u);
+ }
+ }
+ } catch (InterruptedException e) {
+ assert true;
+ }
}
}
@@ -482,7 +495,7 @@ public abstract class FindBugs {
*/
public static void showSynopsis() {
System.out
- .println("Usage: findbugs [general options] -textui [command line options...] [jar/zip/class files, directories...]");
+ .println("Usage: findbugs [general options] -textui [command line options...] [jar/zip/class files, directories...]");
}
/**
@@ -516,7 +529,7 @@ public abstract class FindBugs {
* @throws org.dom4j.DocumentException
*/
public static BugReporter configureBaselineFilter(BugReporter bugReporter, String baselineFileName) throws IOException,
- DocumentException {
+ DocumentException {
return new ExcludingHashesBugReporter(bugReporter, baselineFileName);
}
@@ -554,13 +567,8 @@ public abstract class FindBugs {
/** Date of release of Java 1.0 */
public final static long MINIMUM_TIMESTAMP = new GregorianCalendar(1996, 0, 23).getTime().getTime();
- /**
- * @param timestamp
- * @return
- */
public static boolean validTimestamp(long timestamp) {
return timestamp > MINIMUM_TIMESTAMP;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/FindBugs2.java b/src/java/edu/umd/cs/findbugs/FindBugs2.java
index f9cf848..4f662bb 100644
--- a/src/java/edu/umd/cs/findbugs/FindBugs2.java
+++ b/src/java/edu/umd/cs/findbugs/FindBugs2.java
@@ -46,7 +46,6 @@ import edu.umd.cs.findbugs.ba.ObjectTypeFactory;
import edu.umd.cs.findbugs.ba.SourceInfoMap;
import edu.umd.cs.findbugs.ba.XClass;
import edu.umd.cs.findbugs.ba.XFactory;
-import edu.umd.cs.findbugs.ba.XField;
import edu.umd.cs.findbugs.ba.jsr305.TypeQualifierAnnotation;
import edu.umd.cs.findbugs.ba.jsr305.TypeQualifierApplications;
import edu.umd.cs.findbugs.ba.jsr305.TypeQualifierValue;
@@ -139,15 +138,12 @@ public class FindBugs2 implements IFindBugsEngine {
// By default, do not exclude any classes via the class screener
this.classScreener = new IClassScreener() {
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IClassScreener#matches(java.lang.String)
- */
+ @Override
public boolean matches(String fileName) {
return true;
}
+ @Override
public boolean vacuous() {
return true;
}
@@ -159,8 +155,9 @@ public class FindBugs2 implements IFindBugsEngine {
hostApp = "FindBugs TextUI";
hostAppVersion = System.getProperty(PROP_FINDBUGS_HOST_APP_VERSION);
}
- if (hostAppVersion == null)
+ if (hostAppVersion == null) {
hostAppVersion = "";
+ }
Version.registerApplication(hostApp, hostAppVersion);
// By default, we do not want to scan nested archives
@@ -177,6 +174,7 @@ public class FindBugs2 implements IFindBugsEngine {
* @param detectorFactoryCollection
* The detectorFactoryCollection to set.
*/
+ @Override
public void setDetectorFactoryCollection(DetectorFactoryCollection detectorFactoryCollection) {
this.detectorFactoryCollection = detectorFactoryCollection;
}
@@ -189,118 +187,121 @@ public class FindBugs2 implements IFindBugsEngine {
* @throws IOException
* @throws InterruptedException
*/
+ @Override
public void execute() throws IOException, InterruptedException {
- if (FindBugs.isNoAnalysis())
+ if (FindBugs.isNoAnalysis()) {
throw new UnsupportedOperationException("This FindBugs invocation was started without analysis capabilities");
+ }
Profiler profiler = bugReporter.getProjectStats().getProfiler();
try {
- try {
- // Get the class factory for creating classpath/codebase/etc.
- classFactory = ClassFactory.instance();
+ try {
+ // Get the class factory for creating classpath/codebase/etc.
+ classFactory = ClassFactory.instance();
- // The class path object
- createClassPath();
+ // The class path object
+ createClassPath();
- progress.reportNumberOfArchives(project.getFileCount() + project.getNumAuxClasspathEntries());
- profiler.start(this.getClass());
+ progress.reportNumberOfArchives(project.getFileCount() + project.getNumAuxClasspathEntries());
+ profiler.start(this.getClass());
- // The analysis cache object
- createAnalysisCache();
+ // The analysis cache object
+ createAnalysisCache();
- // Create BCEL compatibility layer
- createAnalysisContext(project, appClassList, analysisOptions.sourceInfoFileName);
+ // Create BCEL compatibility layer
+ createAnalysisContext(project, appClassList, analysisOptions.sourceInfoFileName);
- // Discover all codebases in classpath and
- // enumerate all classes (application and non-application)
- buildClassPath();
+ // Discover all codebases in classpath and
+ // enumerate all classes (application and non-application)
+ buildClassPath();
- // Build set of classes referenced by application classes
- buildReferencedClassSet();
+ // Build set of classes referenced by application classes
+ buildReferencedClassSet();
- // Create BCEL compatibility layer
- setAppClassList(appClassList);
+ // Create BCEL compatibility layer
+ setAppClassList(appClassList);
- // Configure the BugCollection (if we are generating one)
- FindBugs.configureBugCollection(this);
+ // Configure the BugCollection (if we are generating one)
+ FindBugs.configureBugCollection(this);
- // Enable/disabled relaxed reporting mode
- FindBugsAnalysisFeatures.setRelaxedMode(analysisOptions.relaxedReportingMode);
- FindBugsDisplayFeatures.setAbridgedMessages(analysisOptions.abridgedMessages);
+ // Enable/disabled relaxed reporting mode
+ FindBugsAnalysisFeatures.setRelaxedMode(analysisOptions.relaxedReportingMode);
+ FindBugsDisplayFeatures.setAbridgedMessages(analysisOptions.abridgedMessages);
- // Configure training databases
- FindBugs.configureTrainingDatabases(this);
+ // Configure training databases
+ FindBugs.configureTrainingDatabases(this);
- // Configure analysis features
- configureAnalysisFeatures();
+ // Configure analysis features
+ configureAnalysisFeatures();
- // Create the execution plan (which passes/detectors to execute)
- createExecutionPlan();
+ // Create the execution plan (which passes/detectors to execute)
+ createExecutionPlan();
- for (Plugin p : detectorFactoryCollection.plugins()) {
- for (ComponentPlugin<BugReporterDecorator> brp
- : p.getComponentPlugins(BugReporterDecorator.class)) {
- if (brp.isEnabledByDefault() && !brp.isNamed(explicitlyDisabledBugReporterDecorators)
- || brp.isNamed(explicitlyEnabledBugReporterDecorators))
- bugReporter = BugReporterDecorator.construct(brp, bugReporter);
- }
- }
- if (!classScreener.vacuous()) {
- bugReporter = new DelegatingBugReporter(bugReporter) {
-
- @Override
- public void reportBug(@Nonnull BugInstance bugInstance) {
- String className = bugInstance.getPrimaryClass().getClassName();
- String resourceName = className.replace('.', '/') + ".class";
- if (classScreener.matches(resourceName)) {
- this.getDelegate().reportBug(bugInstance);
+ for (Plugin p : detectorFactoryCollection.plugins()) {
+ for (ComponentPlugin<BugReporterDecorator> brp
+ : p.getComponentPlugins(BugReporterDecorator.class)) {
+ if (brp.isEnabledByDefault() && !brp.isNamed(explicitlyDisabledBugReporterDecorators)
+ || brp.isNamed(explicitlyEnabledBugReporterDecorators)) {
+ bugReporter = BugReporterDecorator.construct(brp, bugReporter);
}
}
- };
- }
+ }
+ if (!classScreener.vacuous()) {
+ bugReporter = new DelegatingBugReporter(bugReporter) {
+
+ @Override
+ public void reportBug(@Nonnull BugInstance bugInstance) {
+ String className = bugInstance.getPrimaryClass().getClassName();
+ String resourceName = className.replace('.', '/') + ".class";
+ if (classScreener.matches(resourceName)) {
+ this.getDelegate().reportBug(bugInstance);
+ }
+ }
+ };
+ }
- if (executionPlan.isActive(NoteSuppressedWarnings.class)) {
- SuppressionMatcher m = AnalysisContext.currentAnalysisContext().getSuppressionMatcher();
- bugReporter = new FilterBugReporter(bugReporter, m, false);
- }
+ if (executionPlan.isActive(NoteSuppressedWarnings.class)) {
+ SuppressionMatcher m = AnalysisContext.currentAnalysisContext().getSuppressionMatcher();
+ bugReporter = new FilterBugReporter(bugReporter, m, false);
+ }
- if (appClassList.size() == 0) {
- Map<String, ICodeBaseEntry> codebase = classPath.getApplicationCodebaseEntries();
- if (analysisOptions.noClassOk) {
- System.err.println("No classfiles specified; output will have no warnings");
- } else if (codebase.isEmpty()) {
- throw new IOException("No files to analyze could be opened");
- } else {
- throw new NoClassesFoundToAnalyzeException(classPath);
+ if (appClassList.size() == 0) {
+ Map<String, ICodeBaseEntry> codebase = classPath.getApplicationCodebaseEntries();
+ if (analysisOptions.noClassOk) {
+ System.err.println("No classfiles specified; output will have no warnings");
+ } else if (codebase.isEmpty()) {
+ throw new IOException("No files to analyze could be opened");
+ } else {
+ throw new NoClassesFoundToAnalyzeException(classPath);
+ }
}
- }
- // Analyze the application
- analyzeApplication();
- } catch (CheckedAnalysisException e) {
- IOException ioe = new IOException("IOException while scanning codebases");
- ioe.initCause(e);
- throw ioe;
- } catch (OutOfMemoryError e) {
- System.err.println("Out of memory");
- System.err.println("Total memory: " + Runtime.getRuntime().maxMemory() / 1000000 + "M");
- System.err.println(" free memory: " + Runtime.getRuntime().freeMemory() / 1000000 + "M");
-
- for (String s : project.getFileList()) {
- System.err.println("Analyzed: " + s);
- }
- for (String s : project.getAuxClasspathEntryList()) {
- System.err.println(" Aux: " + s);
+ // Analyze the application
+ analyzeApplication();
+ } catch (CheckedAnalysisException e) {
+ IOException ioe = new IOException("IOException while scanning codebases");
+ ioe.initCause(e);
+ throw ioe;
+ } catch (OutOfMemoryError e) {
+ System.err.println("Out of memory");
+ System.err.println("Total memory: " + Runtime.getRuntime().maxMemory() / 1000000 + "M");
+ System.err.println(" free memory: " + Runtime.getRuntime().freeMemory() / 1000000 + "M");
+
+ for (String s : project.getFileList()) {
+ System.err.println("Analyzed: " + s);
+ }
+ for (String s : project.getAuxClasspathEntryList()) {
+ System.err.println(" Aux: " + s);
+ }
+ throw e;
+ } finally {
+ clearCaches();
+ profiler.end(this.getClass());
+ profiler.report();
}
- throw e;
- } finally {
- clearCaches();
- profiler.end(this.getClass());
- profiler.report();
- }
} catch (IOException e) {
bugReporter.reportQueuedErrors();
throw e;
@@ -329,14 +330,18 @@ public class FindBugs2 implements IFindBugsEngine {
* needed. (used by Eclipse plugin)
*/
public void dispose() {
- if (executionPlan != null)
+ if (executionPlan != null) {
executionPlan.dispose();
- if (appClassList != null)
+ }
+ if (appClassList != null) {
appClassList.clear();
- if (classObserverList != null)
+ }
+ if (classObserverList != null) {
classObserverList.clear();
- if (referencedClassSet != null)
+ }
+ if (referencedClassSet != null) {
referencedClassSet.clear();
+ }
analysisOptions.analysisFeatureSettingList = null;
bugReporter = null;
classFactory = null;
@@ -349,215 +354,119 @@ public class FindBugs2 implements IFindBugsEngine {
analysisOptions.userPreferences = null;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#getBugReporter()
- */
+ @Override
public BugReporter getBugReporter() {
return bugReporter;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#getProject()
- */
+ @Override
public Project getProject() {
return project;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.IFindBugsEngine#addClassObserver(edu.umd.cs.findbugs
- * .classfile.IClassObserver)
- */
+ @Override
public void addClassObserver(IClassObserver classObserver) {
classObserverList.add(classObserver);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#addFilter(java.lang.String,
- * boolean)
- */
+ @Override
public void addFilter(String filterFileName, boolean include) throws IOException, FilterException {
bugReporter = FindBugs.configureFilter(bugReporter, filterFileName, include);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.IFindBugsEngine#addBaselineBugs(java.lang.String)
- */
+ @Override
public void excludeBaselineBugs(String baselineBugs) throws IOException, DocumentException {
bugReporter = FindBugs.configureBaselineFilter(bugReporter, baselineBugs);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.IFindBugsEngine#enableTrainingInput(java.lang.String)
- */
+ @Override
public void enableTrainingInput(String trainingInputDir) {
this.analysisOptions.trainingInputDir = trainingInputDir;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.IFindBugsEngine#enableTrainingOutput(java.lang.String
- * )
- */
+ @Override
public void enableTrainingOutput(String trainingOutputDir) {
this.analysisOptions.trainingOutputDir = trainingOutputDir;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#getBugCount()
- */
+ @Override
public int getBugCount() {
return errorCountingBugReporter.getBugCount();
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#getCurrentClass()
- */
+ @Override
public String getCurrentClass() {
return currentClassName;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#getErrorCount()
- */
+ @Override
public int getErrorCount() {
return errorCountingBugReporter.getErrorCount();
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#getMissingClassCount()
- */
+ @Override
public int getMissingClassCount() {
return errorCountingBugReporter.getMissingClassCount();
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#getReleaseName()
- */
-
+ @Override
public String getReleaseName() {
return analysisOptions.releaseName;
}
+ @Override
public String getProjectName() {
return analysisOptions.projectName;
}
+ @Override
public void setProjectName(String name) {
analysisOptions.projectName = name;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.IFindBugsEngine#setAnalysisFeatureSettings(edu.umd
- * .cs.findbugs.config.AnalysisFeatureSetting[])
- */
+ @Override
public void setAnalysisFeatureSettings(AnalysisFeatureSetting[] settingList) {
this.analysisOptions.analysisFeatureSettingList = settingList;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.IFindBugsEngine#setBugReporter(edu.umd.cs.findbugs
- * .BugReporter)
- */
+ @Override
public void setBugReporter(BugReporter bugReporter) {
this.bugReporter = this.errorCountingBugReporter = new ErrorCountingBugReporter(bugReporter);
addClassObserver(bugReporter);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.IFindBugsEngine#setClassScreener(edu.umd.cs.findbugs
- * .ClassScreener)
- */
+ @Override
public void setClassScreener(IClassScreener classScreener) {
this.classScreener = classScreener;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.IFindBugsEngine#setProgressCallback(edu.umd.cs.findbugs
- * .FindBugsProgress)
- */
+ @Override
public void setProgressCallback(FindBugsProgress progressCallback) {
this.progress = progressCallback;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.IFindBugsEngine#setProject(edu.umd.cs.findbugs.Project
- * )
- */
+ @Override
public void setProject(Project project) {
this.project = project;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#setRelaxedReportingMode(boolean)
- */
+ @Override
public void setRelaxedReportingMode(boolean relaxedReportingMode) {
this.analysisOptions.relaxedReportingMode = relaxedReportingMode;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#setReleaseName(java.lang.String)
- */
+ @Override
public void setReleaseName(String releaseName) {
this.analysisOptions.releaseName = releaseName;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.IFindBugsEngine#setSourceInfoFile(java.lang.String)
- */
+ @Override
public void setSourceInfoFile(String sourceInfoFile) {
this.analysisOptions.sourceInfoFileName = sourceInfoFile;
}
+ @Override
public void setUserPreferences(UserPreferences userPreferences) {
this.analysisOptions.userPreferences = userPreferences;
// TODO should set it here too, but gui2 seems to have issues with it
@@ -601,7 +510,7 @@ public class FindBugs2 implements IFindBugsEngine {
}
}
Set<Entry<String, Boolean>> excludeFilterFiles = userPreferences.getExcludeFilterFiles().entrySet();
-
+
for (Entry<String, Boolean> entry : excludeFilterFiles) {
Boolean value = entry.getValue();
if (value == null || !value) {
@@ -619,24 +528,17 @@ public class FindBugs2 implements IFindBugsEngine {
}
}
}
- if (deferredError != null)
+ if (deferredError != null) {
throw deferredError;
+ }
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#emitTrainingOutput()
- */
+ @Override
public boolean emitTrainingOutput() {
return analysisOptions.trainingOutputDir != null;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#getUserPreferences()
- */
+ @Override
public UserPreferences getUserPreferences() {
return analysisOptions.userPreferences;
}
@@ -648,47 +550,27 @@ public class FindBugs2 implements IFindBugsEngine {
classPath = classFactory.createClassPath();
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#getTrainingInputDir()
- */
+ @Override
public String getTrainingInputDir() {
return analysisOptions.trainingInputDir;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#getTrainingOutputDir()
- */
+ @Override
public String getTrainingOutputDir() {
return analysisOptions.trainingOutputDir;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#useTrainingInput()
- */
+ @Override
public boolean useTrainingInput() {
return analysisOptions.trainingInputDir != null;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#setScanNestedArchives(boolean)
- */
+ @Override
public void setScanNestedArchives(boolean scanNestedArchives) {
this.analysisOptions.scanNestedArchives = scanNestedArchives;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.IFindBugsEngine#setNoClassOk(boolean)
- */
+ @Override
public void setNoClassOk(boolean noClassOk) {
this.analysisOptions.noClassOk = noClassOk;
}
@@ -723,7 +605,6 @@ public class FindBugs2 implements IFindBugsEngine {
* @param analysisCache
* an IAnalysisCache
*/
- @SuppressWarnings({"UnusedDeclaration"})
public static void registerBuiltInAnalysisEngines(IAnalysisCache analysisCache) {
new edu.umd.cs.findbugs.classfile.engine.EngineRegistrar().registerAnalysisEngines(analysisCache);
new edu.umd.cs.findbugs.classfile.engine.asm.EngineRegistrar().registerAnalysisEngines(analysisCache);
@@ -740,7 +621,6 @@ public class FindBugs2 implements IFindBugsEngine {
* an IAnalysisCache
* @throws IOException
*/
- @SuppressWarnings({"UnusedDeclaration"})
public static void registerPluginAnalysisEngines(DetectorFactoryCollection detectorFactoryCollection,
IAnalysisCache analysisCache) throws IOException {
for (Iterator<Plugin> i = detectorFactoryCollection.pluginIterator(); i.hasNext();) {
@@ -779,15 +659,17 @@ public class FindBugs2 implements IFindBugsEngine {
IClassPathBuilder builder = classFactory.createClassPathBuilder(bugReporter);
{
- HashSet<String> seen = new HashSet<String>();
- for (String path : project.getFileArray()) {
- if (seen.add(path))
- builder.addCodeBase(classFactory.createFilesystemCodeBaseLocator(path), true);
- }
- for (String path : project.getAuxClasspathEntryList()) {
- if (seen.add(path))
- builder.addCodeBase(classFactory.createFilesystemCodeBaseLocator(path), false);
- }
+ HashSet<String> seen = new HashSet<String>();
+ for (String path : project.getFileArray()) {
+ if (seen.add(path)) {
+ builder.addCodeBase(classFactory.createFilesystemCodeBaseLocator(path), true);
+ }
+ }
+ for (String path : project.getAuxClasspathEntryList()) {
+ if (seen.add(path)) {
+ builder.addCodeBase(classFactory.createFilesystemCodeBaseLocator(path), false);
+ }
+ }
}
builder.scanNestedArchives(analysisOptions.scanNestedArchives);
@@ -819,7 +701,7 @@ public class FindBugs2 implements IFindBugsEngine {
}
- private void buildReferencedClassSet() throws CheckedAnalysisException, InterruptedException {
+ private void buildReferencedClassSet() throws InterruptedException {
// XXX: should drive progress dialog (scanning phase)?
if (PROGRESS) {
@@ -841,6 +723,7 @@ public class FindBugs2 implements IFindBugsEngine {
// add fields
//noinspection ConstantIfStatement
+ /*
if (false)
for (ClassDescriptor classDesc : appClassList) {
try {
@@ -864,7 +747,7 @@ public class FindBugs2 implements IFindBugsEngine {
}
}
}
-
+ */
while (!workList.isEmpty()) {
if (Thread.interrupted()) {
throw new InterruptedException();
@@ -896,13 +779,15 @@ public class FindBugs2 implements IFindBugsEngine {
}
for (ClassDescriptor ifaceDesc : classNameAndInfo.getInterfaceDescriptorList()) {
- if (addedToWorkList.add(ifaceDesc))
+ if (addedToWorkList.add(ifaceDesc)) {
workList.addLast(ifaceDesc);
+ }
}
ClassDescriptor enclosingClass = classNameAndInfo.getImmediateEnclosingClass();
- if (enclosingClass != null && addedToWorkList.add(enclosingClass))
+ if (enclosingClass != null && addedToWorkList.add(enclosingClass)) {
workList.addLast(enclosingClass);
+ }
} catch (RuntimeException e) {
bugReporter.logError("Error scanning " + classDesc + " for referenced classes", e);
@@ -939,11 +824,10 @@ public class FindBugs2 implements IFindBugsEngine {
referencedPackageSet.remove("");
System.out.println("Added " + count + " referenced classes");
System.out.println("Total of " + referencedPackageSet.size() + " packages");
- for (ClassDescriptor d : referencedClassSet)
+ for (ClassDescriptor d : referencedClassSet) {
System.out.println(" " + d);
-
+ }
}
-
}
public List<ClassDescriptor> sortByCallGraph(Collection<ClassDescriptor> classList, OutEdges<ClassDescriptor> outEdges) {
@@ -953,10 +837,8 @@ public class FindBugs2 implements IFindBugsEngine {
}
- @SuppressWarnings({"UnusedDeclaration"})
public static void clearAnalysisContext() {
AnalysisContext.removeCurrentAnalysisContext();
-
}
/**
@@ -970,10 +852,9 @@ public class FindBugs2 implements IFindBugsEngine {
* @param sourceInfoFileName
* name of source info file (null if none)
*/
- @SuppressWarnings({"UnusedDeclaration"})
public static void createAnalysisContext(Project project, List<ClassDescriptor> appClassList,
@CheckForNull String sourceInfoFileName) throws IOException {
- AnalysisContext analysisContext = new AnalysisContext();
+ AnalysisContext analysisContext = new AnalysisContext(project);
// Make this the current analysis context
AnalysisContext.setCurrentAnalysisContext(analysisContext);
@@ -987,7 +868,6 @@ public class FindBugs2 implements IFindBugsEngine {
SourceInfoMap sourceInfoMap = analysisContext.getSourceInfoMap();
sourceInfoMap.read(new FileInputStream(sourceInfoFileName));
}
- analysisContext.setProject(project);
}
public static void setAppClassList(List<ClassDescriptor> appClassList) {
@@ -1021,20 +901,16 @@ public class FindBugs2 implements IFindBugsEngine {
DetectorFactoryChooser detectorFactoryChooser = new DetectorFactoryChooser() {
HashSet<DetectorFactory> forcedEnabled = new HashSet<DetectorFactory>();
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.DetectorFactoryChooser#choose(edu.umd.cs.
- * findbugs.DetectorFactory)
- */
+ @Override
public boolean choose(DetectorFactory factory) {
boolean result = FindBugs.isDetectorEnabled(FindBugs2.this, factory, rankThreshold) || forcedEnabled.contains(factory);
- if (ExecutionPlan.DEBUG)
+ if (ExecutionPlan.DEBUG) {
System.out.printf(" %6s %s %n", result, factory.getShortName());
+ }
return result;
}
+ @Override
public void enable(DetectorFactory factory) {
forcedEnabled.add(factory);
factory.setEnabledButNonReporting(true);
@@ -1043,8 +919,9 @@ public class FindBugs2 implements IFindBugsEngine {
};
executionPlan.setDetectorFactoryChooser(detectorFactoryChooser);
- if (ExecutionPlan.DEBUG)
+ if (ExecutionPlan.DEBUG) {
System.out.println("rank threshold is " + rankThreshold);
+ }
// Add plugins
for (Iterator<Plugin> i = detectorFactoryCollection.pluginIterator(); i.hasNext();) {
Plugin plugin = i.next();
@@ -1124,12 +1001,14 @@ public class FindBugs2 implements IFindBugsEngine {
AnalysisContext.currentXFactory().canonicalizeAll();
if (PROGRESS || LIST_ORDER) {
System.out.printf("%6d : Pass %d: %d classes%n", (System.currentTimeMillis() - startTime)/1000, passCount, classCollection.size());
- if (DEBUG)
+ if (DEBUG) {
XFactory.profile();
+ }
}
if (!isNonReportingFirstPass) {
OutEdges<ClassDescriptor> outEdges = new OutEdges<ClassDescriptor>() {
+ @Override
public Collection<ClassDescriptor> getOutEdges(ClassDescriptor e) {
try {
XClass classNameAndInfo = Global.getAnalysisCache().getClassAnalysis(XClass.class, e);
@@ -1165,10 +1044,11 @@ public class FindBugs2 implements IFindBugsEngine {
passCount, executionPlan.getNumPasses(), count,
classCollection.size(), classDescriptor);
}
- count++;
- if (!isNonReportingFirstPass && count % 1000 == 0)
- yourkitController.advanceGeneration(String.format("Pass %d.%02d", passCount, count/1000));
-
+ count++;
+ if (!isNonReportingFirstPass && count % 1000 == 0) {
+ yourkitController.advanceGeneration(String.format("Pass %d.%02d", passCount, count/1000));
+ }
+
// Check to see if class is excluded by the class screener.
// In general, we do not want to screen classes from the
@@ -1183,7 +1063,7 @@ public class FindBugs2 implements IFindBugsEngine {
boolean isHuge = currentAnalysisContext.isTooBig(classDescriptor);
if (isHuge && currentAnalysisContext.isApplicationClass(classDescriptor)) {
bugReporter.reportBug(new BugInstance("SKIPPED_CLASS_TOO_BIG", Priorities.NORMAL_PRIORITY)
- .addClass(classDescriptor));
+ .addClass(classDescriptor));
}
currentClassName = ClassName.toDottedClassName(classDescriptor.getClassName());
notifyClassObservers(classDescriptor);
@@ -1191,34 +1071,34 @@ public class FindBugs2 implements IFindBugsEngine {
currentAnalysisContext.setClassBeingAnalyzed(classDescriptor);
try {
- for (Detector2 detector : detectorList) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- if (isHuge && !FirstPassDetector.class.isAssignableFrom(detector.getClass())) {
- continue;
- }
- if (DEBUG) {
- System.out.println("Applying " + detector.getDetectorClassName() + " to " + classDescriptor);
- // System.out.println("foo: " +
- // NonReportingDetector.class.isAssignableFrom(detector.getClass())
- // + ", bar: " + detector.getClass().getName());
- }
- try {
- profiler.start(detector.getClass());
- detector.visitClass(classDescriptor);
- } catch (ClassFormatException e) {
- logRecoverableException(classDescriptor, detector, e);
- } catch (MissingClassException e) {
- Global.getAnalysisCache().getErrorLogger().reportMissingClass(e.getClassDescriptor());
- } catch (CheckedAnalysisException e) {
- logRecoverableException(classDescriptor, detector, e);
- } catch (RuntimeException e) {
- logRecoverableException(classDescriptor, detector, e);
- } finally {
- profiler.end(detector.getClass());
+ for (Detector2 detector : detectorList) {
+ if (Thread.interrupted()) {
+ throw new InterruptedException();
+ }
+ if (isHuge && !FirstPassDetector.class.isAssignableFrom(detector.getClass())) {
+ continue;
+ }
+ if (DEBUG) {
+ System.out.println("Applying " + detector.getDetectorClassName() + " to " + classDescriptor);
+ // System.out.println("foo: " +
+ // NonReportingDetector.class.isAssignableFrom(detector.getClass())
+ // + ", bar: " + detector.getClass().getName());
+ }
+ try {
+ profiler.start(detector.getClass());
+ detector.visitClass(classDescriptor);
+ } catch (ClassFormatException e) {
+ logRecoverableException(classDescriptor, detector, e);
+ } catch (MissingClassException e) {
+ Global.getAnalysisCache().getErrorLogger().reportMissingClass(e.getClassDescriptor());
+ } catch (CheckedAnalysisException e) {
+ logRecoverableException(classDescriptor, detector, e);
+ } catch (RuntimeException e) {
+ logRecoverableException(classDescriptor, detector, e);
+ } finally {
+ profiler.end(detector.getClass());
+ }
}
- }
} finally {
progress.finishClass();
@@ -1229,17 +1109,19 @@ public class FindBugs2 implements IFindBugsEngine {
if (usecs > 15000) {
int classSize = currentAnalysisContext.getClassSize(classDescriptor);
long speed = usecs /classSize;
- if (speed > 15)
- System.out.printf(" %6d usecs/byte %6d msec %6d bytes %d pass %s%n", speed, usecs/1000, classSize, passCount,
- classDescriptor);
+ if (speed > 15) {
+ System.out.printf(" %6d usecs/byte %6d msec %6d bytes %d pass %s%n", speed, usecs/1000, classSize, passCount,
+ classDescriptor);
+ }
}
}
}
}
- if (!passIterator.hasNext())
+ if (!passIterator.hasNext()) {
yourkitController.captureMemorySnapshot();
+ }
// Call finishPass on each detector
for (Detector2 detector : detectorList) {
detector.finishPass();
@@ -1256,8 +1138,9 @@ public class FindBugs2 implements IFindBugsEngine {
bugReporter.finish();
bugReporter.reportQueuedErrors();
profiler.end(this.getClass());
- if (PROGRESS)
+ if (PROGRESS) {
System.out.println("Analysis completed");
+ }
}
}
@@ -1314,27 +1197,32 @@ public class FindBugs2 implements IFindBugsEngine {
// Away we go!
- FindBugs.runMain(findBugs, commandLine);
+ FindBugs.runMain(findBugs, commandLine);
}
+ @Override
public void setAbridgedMessages(boolean xmlWithAbridgedMessages) {
analysisOptions.abridgedMessages = xmlWithAbridgedMessages;
}
+ @Override
public void setMergeSimilarWarnings(boolean mergeSimilarWarnings) {
this.analysisOptions.mergeSimilarWarnings = mergeSimilarWarnings;
}
+ @Override
public void setApplySuppression(boolean applySuppression) {
this.analysisOptions.applySuppression = applySuppression;
}
+ @Override
public void setRankThreshold(int rankThreshold) {
this.rankThreshold = rankThreshold;
}
+ @Override
public void finishSettings() {
if (analysisOptions.applySuppression) {
bugReporter = new FilterBugReporter(bugReporter, getProject().getSuppressionFilter(), false);
@@ -1347,6 +1235,7 @@ public class FindBugs2 implements IFindBugsEngine {
@Nonnull
Set<String> explicitlyDisabledBugReporterDecorators = Collections.emptySet();
+ @Override
public void setBugReporterDecorators(Set<String> explicitlyEnabled, Set<String> explicitlyDisabled) {
explicitlyEnabledBugReporterDecorators = explicitlyEnabled;
explicitlyDisabledBugReporterDecorators = explicitlyDisabled;
diff --git a/src/java/edu/umd/cs/findbugs/FindBugsAnnotationDescriptions.properties b/src/java/edu/umd/cs/findbugs/FindBugsAnnotationDescriptions.properties
index 0b08966..e4ca0a4 100644
--- a/src/java/edu/umd/cs/findbugs/FindBugsAnnotationDescriptions.properties
+++ b/src/java/edu/umd/cs/findbugs/FindBugsAnnotationDescriptions.properties
@@ -23,7 +23,7 @@ SHOULD_CALL =Should call {0} instead
METHOD_DANGEROUS_TARGET =Dangerous method call target {0}
METHOD_DANGEROUS_TARGET_ACTUAL_GUARANTEED_NULL =Definite null passed to dangerous method call target {0}
METHOD_EQUALS_USED ={0} used to determine equality
-METHOD_RETURN_VALUE_OF =Return value of {0}
+METHOD_RETURN_VALUE_OF =Return value of {0} of type {0.returnType}
METHOD_COMPUTED_IN =Value computed in {0}
METHOD_INHERITED =Inherited method {0}
METHOD_OVERRIDDEN =Overrides {0}
@@ -59,6 +59,8 @@ STRING_FORMAT_STRING =Format string "{0}"
STRING_FORMAT_SPECIFIER =Format specifier "{0}"
INT_OCCURRENCES =Occurs {0} times
INT_VALUE =Value {0}
+INT_MIN_VALUE =Minimum valid value {0}
+INT_MAX_VALUE =Maximum valid value {0}
INT_SHIFT =Shifted by {0} bits
INT_SYNC_PERCENT =Synchronized {0}% of the time
INT_BYTECODE_OFFSET =At bytecode offset {0}
@@ -97,6 +99,7 @@ SOURCE_LINE_OBLIGATION_CREATED=Obligation to clean up resource created at {0} is
SOURCE_LINE_OBLIGATION_CREATED_BY_WILLCLOSE_PARAMETER=Obligation to clean up resource passed via a @WillClose parameter (near {0}) is not discharged
SOURCE_LINE_PATH_CONTINUES=Path continues at {0}
SOURCE_LINE_LOCK_OBTAINED_AT=Lock obtained at {0}
+SOURCE_UNREACHABLE_CODE=Unreachable code at {0}
LOCAL_VARIABLE_DEFAULT =Local variable {0}
LOCAL_VARIABLE_NAMED =Local variable named {0.name}
LOCAL_VARIABLE_UNKNOWN =Local variable stored in JVM register {0.register}
diff --git a/src/java/edu/umd/cs/findbugs/FindBugsAnnotationDescriptions_ja.properties b/src/java/edu/umd/cs/findbugs/FindBugsAnnotationDescriptions_ja.properties
index f444aae..515b466 100644
--- a/src/java/edu/umd/cs/findbugs/FindBugsAnnotationDescriptions_ja.properties
+++ b/src/java/edu/umd/cs/findbugs/FindBugsAnnotationDescriptions_ja.properties
@@ -1,94 +1,112 @@
-CLASS_DEFAULT=\u30af\u30e9\u30b9 {0}
-CLASS_EXCEPTION=\u4f8b\u5916\u30af\u30e9\u30b9 {0}
-CLASS_REFTYPE=\u53c2\u7167\u578b {0}
-CLASS_SUBCLASS=\u30b5\u30d6\u30af\u30e9\u30b9 {0}
-INTERFACE_TYPE=\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9 {0}
-TYPE_DEFAULT=\u578b
-TYPE_EXPECTED=\u4e88\u671f\u3055\u308c\u308b\u5024 {0}
-TYPE_FOUND=\u5b9f\u969b\u306e\u578b {0}
-TYPE_CLOSEIT=\u30af\u30ed\u30fc\u30ba\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b {0}
-TYPE_UNHASHABLE=Unhashable class {0}
-TYPE_ANNOTATION=\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u30af\u30e9\u30b9 {0}
-METHOD_DEFAULT=\u30e1\u30bd\u30c3\u30c9 {0}
-METHOD_CALLED=\u547c\u3073\u51fa\u3055\u308c\u305f\u30e1\u30bd\u30c3\u30c9 {0}
-SHOULD_CALL=\u4ee3\u308f\u308a\u306b {0} \u3092\u547c\u3073\u51fa\u3059\u3079\u304d
-METHOD_DANGEROUS_TARGET=\u5371\u967a\u306a\u30e1\u30bd\u30c3\u30c9\u547c\u3073\u51fa\u3057\u5148 {0}
-METHOD_DANGEROUS_TARGET_ACTUAL_GUARANTEED_NULL=\u660e\u78ba\u306bnull\u304c\u6e21\u3055\u308c\u308b\u5371\u967a\u306a\u30e1\u30bd\u30c3\u30c9\u547c\u3073\u51fa\u3057\u5148 {0}
-METHOD_EQUALS_USED={0} \u304c\u540c\u5024\u6027\u306e\u5224\u5b9a\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u308b
-METHOD_RETURN_VALUE_OF=\u623b\u308a\u5024 {0}
-METHOD_INHERITED=\u7d99\u627f\u30e1\u30bd\u30c3\u30c9 {0}
-METHOD_ALTERNATIVE_TARGET=\u547c\u3073\u51fa\u3057\u305f\u304b\u3063\u305f\u3067\u3042\u308d\u3046\u30e1\u30bd\u30c3\u30c9 {0}
-METHOD_SAFE_TARGET=\u5b89\u5168\u306a\u30e1\u30bd\u30c3\u30c9\u547c\u3073\u51fa\u3057\u5148 {0}
-METHOD_DECLARED_NONNULL=\u30e1\u30bd\u30c3\u30c9 {0} \u306f @NonNull \u3092\u5ba3\u8a00\u3057\u3066\u3044\u308b
-FIELD_DEFAULT=\u30d5\u30a3\u30fc\u30eb\u30c9 {0}
-FIELD_LOADED_FROM=\u5024\u306e\u8aad\u307f\u8fbc\u307f\u5143 {0}
-FIELD_CONTAINS_VALUE=\u5024\u306e\u53d6\u5f97\u5143 {0}
-FIELD_ON=\u30d5\u30a3\u30fc\u30eb\u30c9 {0}
-FIELD_SUPER=\u30b9\u30fc\u30d1\u30fc\u30af\u30e9\u30b9\u306e\u30d5\u30a3\u30fc\u30eb\u30c9 {0}
-FIELD_MASKED=\u30de\u30b9\u30af\u3055\u308c\u305f\u30d5\u30a3\u30fc\u30eb\u30c9 {0}
-FIELD_MASKING=\u30de\u30b9\u30af\u3057\u3066\u3044\u308b\u30d5\u30a3\u30fc\u30eb\u30c9 {0}
-FIELD_STORED=\u683c\u7d0d\u3055\u308c\u305f\u30d5\u30a3\u30fc\u30eb\u30c9 {0}
-FIELD_LOADED_FROM=\u8aad\u307f\u8fbc\u307e\u308c\u305f\u30d5\u30a3\u30fc\u30eb\u30c9 {0}
-FIELD_DID_YOU_MEAN=\u53c2\u7167\u3059\u308b\u306e\u306f\u30d5\u30a3\u30fc\u30eb\u30c9 {0} \u3067\u672c\u5f53\u306b\u3044\u3044\u3067\u3059\u304b?
-FIELD_INVOKED_ON=\u547c\u3073\u51fa\u3057\u5834\u6240 {0}
-FIELD_ARGUMENT={0} \u306f\u5f15\u6570\u3068\u3057\u3066\u6e21\u3055\u308c\u3066\u3044\u308b
-FIELD_VALUE_OF=\u5024\u306e\u8aad\u307f\u8fbc\u307f\u5143 {0}
-FILE_NAME=\u30d5\u30a1\u30a4\u30eb\u540d {0}
-FileName=\u30d5\u30a1\u30a4\u30eb\u540d {0}
-INT_DEFAULT=\u5024 {0}
-STRING_DEFAULT=\u5024 {0}
-STRING_CONSTANT=\u6587\u5b57\u5217\u5b9a\u6570 "{0}"
-STRING_PARAMETER_NAME=\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc "{0}"
-STRING_TYPE_QUALIFIER=\u578b\u4fee\u98fe\u5b50 {0}
-STRING_REMAINING_OBLIGATIONS=\u7fa9\u52d9\u304c\u679c\u305f\u3055\u308c\u3066\u3044\u306a\u3044: {0}
-STRING_FORMAT_STRING=\u66f8\u5f0f\u6587\u5b57\u5217 "{0}"
-STRING_FORMAT_SPECIFIER=\u66f8\u5f0f\u6307\u793a\u5b50 "{0}"
-INT_OCCURRENCES=\ {0} \u56de\u767a\u751f
-INT_VALUE=\u5024 {0}
-INT_SHIFT={0} \u30d3\u30c3\u30c8\u5206\u30b7\u30d5\u30c8\u3057\u3066\u3044\u308b
-INT_SYNC_PERCENT={0} % \u306e\u5834\u5408\u540c\u671f\u30a2\u30af\u30bb\u30b9\u3057\u3066\u3044\u308b
-INT_BYTECODE_OFFSET=At bytecode offset {0}
-INT_BIASED_LOCKED={0} biased locked accesses
-INT_BIASED_UNLOCKED={0} biased unlocked accesses
-INT_NULL_ARG=\u5f15\u6570 {0} \u306f null \u3067\u3042\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093 \u304c\u3001\u9593\u9055\u3044\u306a\u304f null \u3067\u3059
-INT_MAYBE_NULL_ARG=\u5f15\u6570 {0} \u306f null \u3067\u3042\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093 \u304c\u3001 null \u306e\u6050\u308c\u304c\u3042\u308a\u307e\u3059
-INT_NONNULL_PARAM=\u5f15\u6570 {0} \u306f null \u3067\u3042\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093
-INT_EXPECTED_ARGUMENTS=\u4e88\u671f\u3055\u308c\u308b\u5f15\u6570\u306e\u6570 {0}
-INT_ACTUAL_ARGUMENTS=\u5b9f\u969b\u306e\u5f15\u6570\u306e\u6570 {0}
-INT_OBLIGATIONS_REMAINING={0} \u500b\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306b\u3064\u3044\u3066\u7fa9\u52d9\u3092\u679c\u305f\u3057\u3066\u3044\u307e\u305b\u3093
-SOURCE_LINE_DEFAULT=\u8a72\u5f53\u7b87\u6240 {0}
-SOURCE_LINE_DEFAULT_UNKNOWN_LINE=\u8a72\u5f53\u5834\u6240 {0}
-SOURCE_LINE_UNSYNC_ACCESS=\u540c\u671f\u3057\u3066\u3044\u306a\u3044\u7b87\u6240 {0}
-SOURCE_LINE_SYNC_ACCESS=\u540c\u671f\u3057\u3066\u3044\u308b\u7b87\u6240 {0}
-SOURCE_REDUNDANT_NULL_CHECK=\u5197\u9577\u306a null \u30c1\u30a7\u30c3\u30af\u304c\u884c\u308f\u308c\u3066\u3044\u308b\u5834\u6240 {0}
-SOURCE_NOTIFICATION_DEADLOCK=\u901a\u77e5\u4e2d\u306b\u30c7\u30c3\u30c9\u30ed\u30c3\u30af\u304c\u8d77\u3053\u308a\u3046\u308b\u5834\u6240 {0}
-SOURCE_LINE_NULL_VALUE=Null value at {0}
-SOURCE_LINE_KNOWN_NULL=Known null at {0}
-SOURCE_LINE_DEREF=Dereferenced at {0}
-SOURCE_LINE_RETURNED=\u30ea\u30bf\u30fc\u30f3\u7b87\u6240 {0}
-SOURCE_LINE_INVOKED=\u30e1\u30bd\u30c3\u30c9\u547c\u3073\u51fa\u3057\u7b87\u6240 {0}
-SOURCE_LINE_STORED=\u683c\u7d0d\u3092\u884c\u3063\u305f\u7b87\u6240 {0}
-SOURCE_LINE_LAST_CHANGE=\u6700\u5f8c\u306b\u5909\u66f4\u3055\u308c\u305f\u7b87\u6240 {0}
-SOURCE_LINE_LOOP_BOTTOM=\u30eb\u30fc\u30d7\u306e\u6700\u4e0b\u90e8 {0}
-SOURCE_LINE_UNKNOWN=At unknown source line
-SOURCE_LINE_ANOTHER_INSTANCE=\u4ed6\u306e\u51fa\u73fe\u7b87\u6240 {0}
-SOURCE_LINE_VALUE_SOURCE=\u5024\u306e\u63d0\u4f9b\u7b87\u6240 {0}
-SOURCE_LINE_VALUE_SINK=Value consumed at {0}
-SOURCE_LINE_VALUE_DOOMED=Value is doomed at {0}
-SOURCE_LINE_GENERATED_AT=\u5024\u306e\u751f\u6210\u7b87\u6240 {0}
-SOURCE_LINE_OBLIGATION_CREATED={0} \u3067\u4f5c\u6210\u3055\u308c\u305f\u30ea\u30bd\u30fc\u30b9\u306e\u30af\u30ea\u30fc\u30f3\u30a2\u30c3\u30d7\u304c\u884c\u308f\u308c\u3066\u3044\u306a\u3044
-SOURCE_LINE_OBLIGATION_CREATED_BY_WILLCLOSE_PARAMETER={0} \u5468\u8fba\u306b\u304a\u3044\u3066\u3001 at WillClose \u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u3068\u3057\u3066\u6e21\u3055\u308c\u305f\u308a\u30bd\u30fc\u30b9\u306e\u30af\u30ea\u30fc\u30f3\u30a2\u30c3\u30d7\u304c\u884c\u308f\u308c\u3066\u3044\u306a\u3044
-SOURCE_LINE_PATH_CONTINUES=\u8a72\u5f53\u30d1\u30b9 {0}
-LOCAL_VARIABLE_DEFAULT=\u30ed\u30fc\u30ab\u30eb\u5909\u6570 {0}
-LOCAL_VARIABLE_NAMED=\u30ed\u30fc\u30ab\u30eb\u5909\u6570\u540d {0.name}
-LOCAL_VARIABLE_UNKNOWN=Local variable stored in JVM register {0.register}
-LOCAL_VARIABLE_PARAMETER=\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc {0}
-LOCAL_VARIABLE_PARAMETER_NAMED=\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc {0.name}
-LOCAL_VARIABLE_PARAMETER_VALUE_SOURCE=\u5024\u306e\u8aad\u307f\u8fbc\u307f\u5143\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc {0}
-LOCAL_VARIABLE_PARAMETER_VALUE_SOURCE_NAMED=\u5024\u306e\u8aad\u307f\u8fbc\u307f\u5143\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc {0.name}
-LOCAL_VARIABLE_VALUE_DOOMED=Doomed value in local variable {0}
-LOCAL_VARIABLE_VALUE_DOOMED_NAMED=Doomed value in local variable named {0.name}
-LOCAL_VARIABLE_DID_YOU_MEAN=Did you mean to refer to the local variable {0.name}
-LOCAL_VARIABLE_INVOKED_ON=Invoked on {0.name}
-LOCAL_VARIABLE_ARGUMENT={0.name} \u306f\u5f15\u6570\u3068\u3057\u3066\u6e21\u3055\u308c\u3066\u3044\u308b
-LOCAL_VARIABLE_VALUE_OF=\u5024\u306e\u8aad\u307f\u8fbc\u307f\u5143\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc {0.name}
+CLASS_ANNOTATION = {0.simpleName} \u3067\u30a2\u30ce\u30c6\u30fc\u30c8\u3055\u308c\u305f
+CLASS_DEFAULT = \u30af\u30e9\u30b9 {0}
+CLASS_EXCEPTION = \u4f8b\u5916\u30af\u30e9\u30b9 {0}
+CLASS_IMPLEMENTED_INTERFACE = \u5b9f\u88c5\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9 {0}
+CLASS_RECOMMENDED_SUPERCLASS = \u304a\u305d\u3089\u304f\u3001\u30af\u30e9\u30b9\u3092\u62e1\u5f35\u3059\u308b\u305f\u3081\u306b\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059 {0}
+CLASS_REFTYPE = \u53c2\u7167\u578b {0}
+CLASS_SUBCLASS = \u30b5\u30d6\u30af\u30e9\u30b9 {0} \u304c\u3042\u308a\u307e\u3059
+CLASS_SUPERCLASS = \u30b9\u30fc\u30d1\u30fc\u30af\u30e9\u30b9 {0}
+CLASS_TYPE_QUALIFIER = \u578b\u4fee\u98fe\u5b50 {0.simpleName}
+FIELD_ARGUMENT = {0} \u306f\u5f15\u6570\u3068\u3057\u3066\u6e21\u3055\u308c\u3066\u3044\u308b
+FIELD_CONTAINS_VALUE = {0} \u306b\u542b\u307e\u308c\u308b\u5024
+FIELD_DEFAULT = \u30d5\u30a3\u30fc\u30eb\u30c9 {0}
+FIELD_DID_YOU_MEAN = \u30d5\u30a3\u30fc\u30eb\u30c9 {0} \u3092\u53c2\u7167\u3059\u308b\u3064\u3082\u308a\u3060\u3063\u305f\u306e\u3067\u3059\u304b?
+FIELD_INVOKED_ON = {0} \u3067\u547c\u3073\u51fa\u3055\u308c\u305f
+FIELD_LOADED_FROM = \u30d5\u30a3\u30fc\u30eb\u30c9 {0} \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u305f
+FIELD_MASKED = \u30de\u30b9\u30af\u3055\u308c\u305f\u30d5\u30a3\u30fc\u30eb\u30c9 {0}
+FIELD_MASKING = \u30de\u30b9\u30af\u3057\u3066\u3044\u308b\u30d5\u30a3\u30fc\u30eb\u30c9 {0}
+FIELD_ON = \u30d5\u30a3\u30fc\u30eb\u30c9 {0}
+FIELD_STORED = \u30d5\u30a3\u30fc\u30eb\u30c9 {0} \u306b\u683c\u7d0d\u3055\u308c\u305f
+FIELD_SUPER = \u30b9\u30fc\u30d1\u30fc\u30af\u30e9\u30b9\u306e\u30d5\u30a3\u30fc\u30eb\u30c9 {0}
+FIELD_VALUE_OF = \u30d5\u30a3\u30fc\u30eb\u30c9 {0} \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u305f\u5024
+FILE_NAME = \u30d5\u30a1\u30a4\u30eb\u540d {0}
+FileName = \u30d5\u30a1\u30a4\u30eb\u540d {0}
+INTERFACE_TYPE = \u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9 {0}
+INT_ACTUAL_ARGUMENTS = {0} \u500b\u306e\u5f15\u6570\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f
+INT_BIASED_LOCKED = {0} \u500b\u306e\u30d0\u30a4\u30a2\u30b9\u30fb\u30ed\u30c3\u30af\u30fb\u30a2\u30af\u30bb\u30b9
+INT_BIASED_UNLOCKED = {0} \u500b\u306e\u30d0\u30a4\u30a2\u30b9\u30fb\u30a2\u30f3\u30ed\u30c3\u30af\u30fb\u30a2\u30af\u30bb\u30b9
+INT_BYTECODE_OFFSET = \u30d0\u30a4\u30c8\u30b3\u30fc\u30c9\u30fb\u30aa\u30d5\u30bb\u30c3\u30c8 {0}
+INT_DEFAULT = \u5024 {0}
+INT_EXPECTED_ARGUMENTS = {0} \u500b\u306e\u671f\u5f85\u3055\u308c\u308b\u5f15\u6570
+INT_MAYBE_NULL_ARG = \u5f15\u6570 {0} \u306f null \u304b\u3082\u3057\u308c\u307e\u305b\u3093\u304c\u3001null \u3067\u3042\u3063\u3066\u306f\u306a\u308a\u307e\u305b\u3093
+INT_NONNULL_PARAM = \u5f15\u6570 {0} \u306f null \u3067\u3042\u3063\u3066\u306f\u306a\u308a\u307e\u305b\u3093
+INT_NULL_ARG = \u5f15\u6570 {0} \u306f\u9593\u9055\u3044\u306a\u304f null \u3067\u3059\u304c\u3001null \u3067\u3042\u3063\u3066\u306f\u306a\u308a\u307e\u305b\u3093\u304c\u3001
+INT_OBLIGATIONS_REMAINING = {0} \u500b\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306b\u3064\u3044\u3066\u7fa9\u52d9\u3092\u679c\u305f\u3057\u3066\u3044\u307e\u305b\u3093
+INT_OCCURRENCES = {0} \u56de\u767a\u751f
+INT_SHIFT = {0} \u30d3\u30c3\u30c8\u30fb\u30b7\u30d5\u30c8
+INT_SYNC_PERCENT = {0} % \u306e\u78ba\u7387\u3067\u540c\u671f\u5316\u3057\u3066\u3044\u308b
+INT_VALUE = \u5024 {0}
+LOCAL_VARIABLE_ARGUMENT = {0.name} \u306f\u5f15\u6570\u3068\u3057\u3066\u6e21\u3055\u308c\u3066\u3044\u308b
+LOCAL_VARIABLE_DEFAULT = \u30ed\u30fc\u30ab\u30eb\u5909\u6570 {0}
+LOCAL_VARIABLE_DID_YOU_MEAN = \u30ed\u30fc\u30ab\u30eb\u5909\u6570 {0.name} \u3092\u53c2\u7167\u3059\u308b\u3064\u3082\u308a\u3060\u3063\u305f\u306e\u3067\u3059\u304b?
+LOCAL_VARIABLE_INVOKED_ON = {0.name} \u3067\u547c\u3073\u51fa\u3055\u308c\u305f
+LOCAL_VARIABLE_NAMED = \u30ed\u30fc\u30ab\u30eb\u5909\u6570\u540d {0.name}
+LOCAL_VARIABLE_PARAMETER = \u30d1\u30e9\u30e1\u30fc\u30bf\u30fc {0}
+LOCAL_VARIABLE_PARAMETER_NAMED = \u30d1\u30e9\u30e1\u30fc\u30bf\u30fc {0.name}
+LOCAL_VARIABLE_PARAMETER_VALUE_SOURCE = \u30d1\u30e9\u30e1\u30fc\u30bf\u30fc {0} \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u305f\u5024
+LOCAL_VARIABLE_PARAMETER_VALUE_SOURCE_NAMED = \u30d1\u30e9\u30e1\u30fc\u30bf\u30fc {0.name} \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u305f\u5024
+LOCAL_VARIABLE_UNKNOWN = JVM \u30ec\u30b8\u30b9\u30bf\u30fc {0.register} \u306b\u683c\u7d0d\u3055\u308c\u305f\u30ed\u30fc\u30ab\u30eb\u5909\u6570
+LOCAL_VARIABLE_VALUE_DOOMED = \u30ed\u30fc\u30ab\u30eb\u5909\u6570 {0} \u306b\u7834\u7dbb\u3057\u305f\u5024
+LOCAL_VARIABLE_VALUE_DOOMED_NAMED = \u30ed\u30fc\u30ab\u30eb\u5909\u6570\u540d {0.name} \u306b\u7834\u7dbb\u3057\u305f\u5024
+LOCAL_VARIABLE_VALUE_OF = {0.name} \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u305f\u5024
+METHOD_ALTERNATIVE_TARGET = {0} \u306e\u547c\u3073\u51fa\u3057\u3092\u610f\u56f3\u3057\u307e\u3057\u305f\u304b
+METHOD_CALLED = \u547c\u3073\u51fa\u3055\u308c\u305f\u30e1\u30bd\u30c3\u30c9 {0}
+METHOD_CALLED_FROM = {0} \u304b\u3089\u547c\u3073\u51fa\u3055\u308c\u305f
+METHOD_COMPUTED_IN = \u5024\u304c\u8a08\u7b97\u3055\u308c\u305f {0}
+METHOD_CONSTRUCTOR = \u30b3\u30f3\u30b9\u30c8\u30e9\u30af\u30bf\u30fc {0}
+METHOD_DANGEROUS_TARGET = \u5371\u967a\u306a\u30e1\u30bd\u30c3\u30c9\u547c\u3073\u51fa\u3057\u5bfe\u8c61 {0}
+METHOD_DANGEROUS_TARGET_ACTUAL_GUARANTEED_NULL = \u660e\u3089\u304b\u306b null \u304c\u6e21\u3055\u308c\u308b\u5371\u967a\u306a\u30e1\u30bd\u30c3\u30c9\u547c\u3073\u51fa\u3057\u5bfe\u8c61 {0}
+METHOD_DECLARED_NONNULL = \u30e1\u30bd\u30c3\u30c9 {0} \u306f @NonNull \u3092\u5ba3\u8a00\u3057\u3066\u3044\u308b
+METHOD_DEFAULT = \u30e1\u30bd\u30c3\u30c9 {0}
+METHOD_DID_YOU_MEAN_TO_OVERRIDE = \u30aa\u30fc\u30d0\u30fc\u30e9\u30a4\u30c9\u3059\u308b\u3064\u3082\u308a\u3060\u3063\u305f {0}
+METHOD_EQUALS_USED = {0} \u304c\u7b49\u4fa1\u6027\u3092\u6c7a\u5b9a\u3059\u308b\u305f\u3081\u306b\u4f7f\u308f\u308c\u308b
+METHOD_INHERITED = \u7d99\u627f\u3055\u308c\u305f\u30e1\u30bd\u30c3\u30c9 {0}
+METHOD_OVERRIDDEN = \u30aa\u30fc\u30d0\u30fc\u30e9\u30a4\u30c9 {0}
+METHOD_RETURN_VALUE_OF = \u623b\u308a\u5024 {0}
+METHOD_SAFE_TARGET = \u5b89\u5168\u306a\u30e1\u30bd\u30c3\u30c9\u547c\u3073\u51fa\u3057\u5bfe\u8c61 {0}
+METHOD_SUPERCLASS_CONSTRUCTOR = \u30b9\u30fc\u30d1\u30fc\u30af\u30e9\u30b9\u306e\u30b3\u30f3\u30b9\u30c8\u30e9\u30af\u30bf\u30fc {0}
+SHOULD_CALL = \u4ee3\u308f\u308a\u306b {0} \u3092\u547c\u3073\u51fa\u3059\u3079\u304d
+SOURCE_LINE_ANOTHER_INSTANCE = \u4ed6\u306e\u51fa\u73fe\u7b87\u6240 {0}
+SOURCE_LINE_CALLED_FROM_SUPERCLASS_AT = \u30b9\u30fc\u30d1\u30fc\u30af\u30e9\u30b9\u306e\u30b3\u30f3\u30b9\u30c8\u30e9\u30af\u30bf\u30fc\u304b\u3089\u547c\u3073\u51fa\u3057\u305f\u7b87\u6240 {0}
+SOURCE_LINE_DEFAULT = \u8a72\u5f53\u7b87\u6240 {0}
+SOURCE_LINE_DEFAULT_UNKNOWN_LINE = \u8a72\u5f53\u5834\u6240 {0}
+SOURCE_LINE_DEREF = \u53c2\u7167\u5916\u3057\u3092\u3057\u305f\u7b87\u6240 {0}
+SOURCE_LINE_FIELD_SET_TOO_LATE_AT = \u30d5\u30a3\u30fc\u30eb\u30c9\u3092\u8a2d\u5b9a\u3057\u305f (\u9045\u3059\u304e\u305f) \u7b87\u6240 {0}
+SOURCE_LINE_GENERATED_AT = \u5024\u306e\u751f\u6210\u7b87\u6240 {0}
+SOURCE_LINE_INVOKED = \u30e1\u30bd\u30c3\u30c9\u547c\u3073\u51fa\u3057\u7b87\u6240 {0}
+SOURCE_LINE_KNOWN_NULL = null \u3068\u308f\u304b\u3063\u3066\u3044\u308b\u7b87\u6240 {0}
+SOURCE_LINE_LAST_CHANGE = \u6700\u5f8c\u306b\u5909\u66f4\u3055\u308c\u305f\u7b87\u6240 {0}
+SOURCE_LINE_LOCK_OBTAINED_AT = \u30ed\u30c3\u30af\u3092\u7372\u5f97\u3057\u305f\u7b87\u6240 {0}
+SOURCE_LINE_LOOP_BOTTOM = \u30eb\u30fc\u30d7\u4e0b\u90e8 {0}
+SOURCE_LINE_NULL_CHECKED = \u30c1\u30a7\u30c3\u30af\u3057\u3066 null \u3067\u3042\u308b\u3053\u3068\u304c\u5224\u660e\u3057\u305f\u7b87\u6240 {0}
+SOURCE_LINE_NULL_VALUE = null \u5024\u306e\u7b87\u6240 {0}
+SOURCE_LINE_OBLIGATION_CREATED = {0} \u3067\u4f5c\u6210\u3055\u308c\u305f\u30ea\u30bd\u30fc\u30b9\u306e\u30af\u30ea\u30fc\u30f3\u30a2\u30c3\u30d7\u304c\u884c\u308f\u308c\u3066\u3044\u306a\u3044
+SOURCE_LINE_OBLIGATION_CREATED_BY_WILLCLOSE_PARAMETER = {0} \u5468\u8fba\u306b\u304a\u3044\u3066\u3001 at WillClose \u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u3068\u3057\u3066\u6e21\u3055\u308c\u305f\u30ea\u30bd\u30fc\u30b9\u306e\u30af\u30ea\u30fc\u30f3\u30a2\u30c3\u30d7\u304c\u884c\u308f\u308c\u3066\u3044\u306a\u3044
+SOURCE_LINE_PATH_CONTINUES = \u30d1\u30b9\u306e\u7d99\u7d9a\u7b87\u6240 {0}
+SOURCE_LINE_RETURNED = \u30ea\u30bf\u30fc\u30f3\u7b87\u6240 {0}
+SOURCE_LINE_STORED = \u683c\u7d0d\u3057\u305f\u7b87\u6240 {0}
+SOURCE_LINE_SYNC_ACCESS = \u540c\u671f\u30a2\u30af\u30bb\u30b9\u3057\u3066\u3044\u308b\u7b87\u6240 {0}
+SOURCE_LINE_UNKNOWN = \u4e0d\u660e\u306a\u30bd\u30fc\u30b9\u884c
+SOURCE_LINE_UNSYNC_ACCESS = \u540c\u671f\u30a2\u30af\u30bb\u30b9\u3057\u3066\u3044\u306a\u3044\u7b87\u6240 {0}
+SOURCE_LINE_VALUE_DOOMED = \u7834\u7dbb\u3057\u305f\u5024\u306e\u7b87\u6240 {0}
+SOURCE_LINE_VALUE_SINK = \u6d88\u8cbb\u3055\u308c\u305f\u5024\u306e\u7b87\u6240 {0}
+SOURCE_LINE_VALUE_SOURCE = \u5024\u306e\u63d0\u4f9b\u7b87\u6240 {0}
+SOURCE_NOTIFICATION_DEADLOCK = \u901a\u77e5\u4e2d\u306b\u30c7\u30c3\u30c9\u30ed\u30c3\u30af\u304c\u8d77\u3053\u308a\u3046\u308b\u7b87\u6240 {0}
+SOURCE_REDUNDANT_NULL_CHECK = \u5197\u9577\u306a null \u30c1\u30a7\u30c3\u30af\u304c\u884c\u308f\u308c\u3066\u3044\u308b\u7b87\u6240 {0}
+STRING_CONSTANT = \u6587\u5b57\u5217\u5b9a\u6570 "{0}"
+STRING_DEFAULT = \u5024 {0}
+STRING_ERROR_MSG = \u30a8\u30e9\u30fc\u30fb\u30e1\u30c3\u30bb\u30fc\u30b8: {0}
+STRING_FORMAT_SPECIFIER = \u66f8\u5f0f\u6307\u793a\u5b50 "{0}"
+STRING_FORMAT_STRING = \u66f8\u5f0f\u6587\u5b57\u5217 "{0}"
+STRING_MESSAGE = {0}
+STRING_NONSTRING_CONSTANT = \u5b9a\u6570\u5024 {0}
+STRING_PARAMETER_NAME = \u30d1\u30e9\u30e1\u30fc\u30bf\u30fc "{0}"
+STRING_REGEX = \u6b63\u898f\u8868\u73fe "{0}"
+STRING_REMAINING_OBLIGATIONS = \u7fa9\u52d9\u304c\u679c\u305f\u3055\u308c\u3066\u3044\u306a\u3044: {0}
+STRING_TYPE_QUALIFIER = \u578b\u4fee\u98fe\u5b50 {0}
+TYPE_ANNOTATION = \u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u30fb\u30af\u30e9\u30b9 {0}
+TYPE_CLOSEIT = {0} \u3092\u30af\u30ed\u30fc\u30ba\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b
+TYPE_DEFAULT = \u578b {0}
+TYPE_EXPECTED = \u671f\u5f85\u3055\u308c\u305f {0}
+TYPE_FOUND = \u5b9f\u969b\u306e\u578b {0}
+TYPE_UNHASHABLE = \u975e\u30cf\u30c3\u30b7\u30e5\u30fb\u30af\u30e9\u30b9 {0}
\ No newline at end of file
diff --git a/src/java/edu/umd/cs/findbugs/FindBugsCommandLine.java b/src/java/edu/umd/cs/findbugs/FindBugsCommandLine.java
index 4e9a4ac..64dd2cd 100644
--- a/src/java/edu/umd/cs/findbugs/FindBugsCommandLine.java
+++ b/src/java/edu/umd/cs/findbugs/FindBugsCommandLine.java
@@ -103,27 +103,28 @@ public abstract class FindBugsCommandLine extends CommandLine {
@Override
protected void handleOption(String option, String optionExtraPart) {
- if (option.equals("-effort")) {
- if (optionExtraPart.equals("min")) {
+ if ("-effort".equals(option)) {
+ if ("min".equals(optionExtraPart)) {
settingList = FindBugs.MIN_EFFORT;
- } else if (optionExtraPart.equals("less")) {
+ } else if ("less".equals(optionExtraPart)) {
settingList = FindBugs.LESS_EFFORT;
- } else if (optionExtraPart.equals("default")) {
+ } else if ("default".equals(optionExtraPart)) {
settingList = FindBugs.DEFAULT_EFFORT;
- } else if (optionExtraPart.equals("more")) {
+ } else if ("more".equals(optionExtraPart)) {
settingList = FindBugs.MORE_EFFORT;
- } else if (optionExtraPart.equals("max")) {
+ } else if ("max".equals(optionExtraPart)) {
settingList = FindBugs.MAX_EFFORT;
} else {
throw new IllegalArgumentException("-effort:<value> must be one of min,default,more,max");
}
- } else if (option.equals("-workHard")) {
- if (settingList != FindBugs.MAX_EFFORT)
+ } else if ("-workHard".equals(option)) {
+ if (settingList != FindBugs.MAX_EFFORT) {
settingList = FindBugs.MORE_EFFORT;
+ }
- } else if (option.equals("-conserveSpace")) {
+ } else if ("-conserveSpace".equals(option)) {
settingList = FindBugs.MIN_EFFORT;
- } else if (option.equals("-adjustExperimental")) {
+ } else if ("-adjustExperimental".equals(option)) {
BugInstance.setAdjustExperimental(true);
} else {
throw new IllegalArgumentException("Don't understand option " + option);
@@ -132,9 +133,9 @@ public abstract class FindBugsCommandLine extends CommandLine {
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-home")) {
+ if ("-home".equals(option)) {
FindBugs.setHome(argument);
- } else if (option.equals("-pluginList")) {
+ } else if ("-pluginList".equals(option)) {
String pluginListStr = argument;
Map<String, Boolean> customPlugins = getProject().getConfiguration().getCustomPlugins();
StringTokenizer tok = new StringTokenizer(pluginListStr, File.pathSeparator);
@@ -151,7 +152,7 @@ public abstract class FindBugsCommandLine extends CommandLine {
}
}
}
- } else if (option.equals("-project")) {
+ } else if ("-project".equals(option)) {
loadProject(argument);
} else {
throw new IllegalStateException();
diff --git a/src/java/edu/umd/cs/findbugs/FindBugsMain.java b/src/java/edu/umd/cs/findbugs/FindBugsMain.java
index 70bb523..2052484 100644
--- a/src/java/edu/umd/cs/findbugs/FindBugsMain.java
+++ b/src/java/edu/umd/cs/findbugs/FindBugsMain.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -56,23 +56,27 @@ public class FindBugsMain implements Comparable<FindBugsMain> {
final boolean analysis;
public void invoke(String[] args) throws Exception {
- if (!analysis)
+ if (!analysis) {
FindBugs.setNoAnalysis();
+ }
mainMethod.invoke(null, (Object) args);
}
+ @Override
public int compareTo(FindBugsMain that) {
int result = kind.compareTo(that.kind);
- if (result != 0)
+ if (result != 0) {
return result;
+ }
return cmd.compareTo(that.cmd);
}
@Override
public boolean equals(Object o) {
- if (!(o instanceof FindBugsMain))
+ if (!(o instanceof FindBugsMain)) {
return false;
+ }
FindBugsMain that = (FindBugsMain) o;
return kind.equals(that.kind) && cmd.equals(that.cmd);
}
diff --git a/src/java/edu/umd/cs/findbugs/FindBugsMessageFormat.java b/src/java/edu/umd/cs/findbugs/FindBugsMessageFormat.java
index e180ed4..b7b5526 100644
--- a/src/java/edu/umd/cs/findbugs/FindBugsMessageFormat.java
+++ b/src/java/edu/umd/cs/findbugs/FindBugsMessageFormat.java
@@ -27,25 +27,25 @@ package edu.umd.cs.findbugs;
* <p/>
* <p>
* Example:
- *
+ *
* <pre>
* new FindBugsMessageFormat("BUG: {1} does something bad to field {2.fullField}")
* </pre>
- *
+ *
* In this example, the method annotation at position 1 is formatted using the
* empty (default) key. The field annotation at position 2 is formatted using
* the "fullField" key, which uses the long format for the field rather than the
* usual "class.fieldname" format.
- *
+ *
* @author David Hovemeyer
* @see BugInstance
*/
public class FindBugsMessageFormat {
- private String pattern;
+ private final String pattern;
/**
* Constructor.
- *
+ *
* @param pattern
* the pattern for the message
*/
@@ -60,7 +60,7 @@ public class FindBugsMessageFormat {
/**
* Format the message using the given array of BugAnnotations as arguments
* to bind to the placeholders in the pattern string.
- *
+ *
* @param args
* the BugAnnotations used as arguments
* @param primaryClass
@@ -82,8 +82,9 @@ public class FindBugsMessageFormat {
pat = pat.substring(subst + 1);
int end = pat.indexOf('}');
- if (end < 0)
+ if (end < 0) {
throw new IllegalStateException("unmatched { in " + pat);
+ }
String substPat = pat.substring(0, end);
@@ -92,8 +93,9 @@ public class FindBugsMessageFormat {
if (dot >= 0) {
key = substPat.substring(dot + 1);
substPat = substPat.substring(0, dot);
- } else if (abridgedMessages && primaryClass != null)
+ } else if (abridgedMessages && primaryClass != null) {
key = "givenClass";
+ }
int fieldNum;
try {
@@ -121,10 +123,10 @@ public class FindBugsMessageFormat {
// unknown key -- not unprecedented when reading xml
// generated by older versions of findbugs
formatted = "\u00BF" + fieldNum + ".(key=" + key + ")?"; // "\u00BF"
- // is
- // inverted
- // question
- // mark
+ // is
+ // inverted
+ // question
+ // mark
// System.err.println(iae.getMessage()+" in FindBugsMessageFormat");
// // FIXME: log this error better
}
@@ -138,4 +140,3 @@ public class FindBugsMessageFormat {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/FindBugsProgress.java b/src/java/edu/umd/cs/findbugs/FindBugsProgress.java
index 6e3261b..14c5a31 100644
--- a/src/java/edu/umd/cs/findbugs/FindBugsProgress.java
+++ b/src/java/edu/umd/cs/findbugs/FindBugsProgress.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.classfile.IClassPathBuilderProgress;
/**
* A callback that may be installed in a FindBugs instance to asynchronously
* keep track of its progress.
- *
+ *
* @author David Hovemeyer
* @see FindBugs
*/
@@ -32,7 +32,7 @@ public interface FindBugsProgress extends IClassPathBuilderProgress {
/**
* Report the total number of archives (Jar or zip files) that will be
* analyzed.
- *
+ *
* @param numArchives
* the number of archives
*/
@@ -42,17 +42,19 @@ public interface FindBugsProgress extends IClassPathBuilderProgress {
* Report that FindBugs has started scanning an archive in order to add its
* classes to the repository.
*/
+ @Override
public void startArchive(String name);
/**
* Report that FindBugs has finished scanning an archive in order to add its
* classes to the repository.
*/
+ @Override
public void finishArchive();
/**
* Provide an array that predicts the number of classes in each pass
- *
+ *
* @param classesPerPass
*/
public void predictPassCount(int[] classesPerPass);
@@ -60,7 +62,7 @@ public interface FindBugsProgress extends IClassPathBuilderProgress {
/**
* Report that FindBugs has finished scanning the archives and will start
* analysing the classes contained therein.
- *
+ *
* @param numClasses
* number of classes found in all of the archives
*/
@@ -78,4 +80,3 @@ public interface FindBugsProgress extends IClassPathBuilderProgress {
public void finishPerClassAnalysis();
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/FirstPassDetector.java b/src/java/edu/umd/cs/findbugs/FirstPassDetector.java
index 84f76ce..4b3ff8d 100644
--- a/src/java/edu/umd/cs/findbugs/FirstPassDetector.java
+++ b/src/java/edu/umd/cs/findbugs/FirstPassDetector.java
@@ -21,13 +21,13 @@ package edu.umd.cs.findbugs;
/**
* A Detector that can be run in the first pass.
- *
+ *
* A detector can be run in the first pass if either:
* <ul>
* <li>It doesn't report any warnings, or
* <li>It doesn't depend upon information from analyzing any other classes
* </ul>
- *
+ *
* @author Bill Pugh
*/
public interface FirstPassDetector {
diff --git a/src/java/edu/umd/cs/findbugs/Footprint.java b/src/java/edu/umd/cs/findbugs/Footprint.java
index b465017..ca7b356 100644
--- a/src/java/edu/umd/cs/findbugs/Footprint.java
+++ b/src/java/edu/umd/cs/findbugs/Footprint.java
@@ -26,10 +26,10 @@ import java.util.List;
/**
* Class to maintain a snapshot of a processes's time and memory usage.
- *
+ *
* This uses some JDK 1.5 APIs so must be careful that it doesn't cause any harm
* when run from 1.4.
- *
+ *
* @see FindBugs
* @author Brian Cole
*/
@@ -89,7 +89,7 @@ public class Footprint {
} // catch possible Error thrown when complied by the Eclipse compiler
clockTime = System.currentTimeMillis(); // or new
- // java.util.Date().getTime() ;
+ // java.util.Date().getTime() ;
try {
peakMem = new MemoryBeanWrapper().getPeakUsage();
@@ -161,9 +161,11 @@ public class Footprint {
try {
java.lang.management.MemoryUsage memUsage = mpBean.getPeakUsage();
if (memUsage != null)
+ {
sum += memUsage.getUsed(); // or getCommitted()
- // System.out.println(mpBean.getType()+", "+mpBean.getName()+", "+memUsage.getUsed());
- // System.out.println("Memory type="+mpBean.getType()+", Pool name="+mpBean.getName()+", Memory usage="+mpBean.getPeakUsage());
+ // System.out.println(mpBean.getType()+", "+mpBean.getName()+", "+memUsage.getUsed());
+ // System.out.println("Memory type="+mpBean.getType()+", Pool name="+mpBean.getName()+", Memory usage="+mpBean.getPeakUsage());
+ }
} catch (RuntimeException e) {
assert true;
// AnalysisContext.logError("Error getting peak usage", e);
diff --git a/src/java/edu/umd/cs/findbugs/FuzzyBugComparator.java b/src/java/edu/umd/cs/findbugs/FuzzyBugComparator.java
index b1ac059..aed1395 100644
--- a/src/java/edu/umd/cs/findbugs/FuzzyBugComparator.java
+++ b/src/java/edu/umd/cs/findbugs/FuzzyBugComparator.java
@@ -46,9 +46,9 @@ public class FuzzyBugComparator implements WarningComparator {
private static final boolean DEBUG = false;
// Don't use hashes for now. Still ironing out issues there.
- private static final boolean USE_HASHES = false;
+ // private static final boolean USE_HASHES = false;
- private static final long serialVersionUID = 1L;
+ // private static final long serialVersionUID = 1L;
/**
* Filter ignored BugAnnotations from given Iterator.
@@ -75,35 +75,24 @@ public class FuzzyBugComparator implements WarningComparator {
}
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.Iterator#hasNext()
- */
+ @Override
public boolean hasNext() {
findNext();
return next != null;
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.Iterator#next()
- */
+ @Override
public BugAnnotation next() {
findNext();
- if (next == null)
+ if (next == null) {
throw new NoSuchElementException();
+ }
BugAnnotation result = next;
next = null;
return result;
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.Iterator#remove()
- */
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -124,8 +113,9 @@ public class FuzzyBugComparator implements WarningComparator {
// private Map<ClassHash, String> classHashToCanonicalClassNameMap;
public FuzzyBugComparator() {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Created fuzzy comparator");
+ }
this.bugCollectionMap = new IdentityHashMap<BugInstance, BugCollection>();
// this.classHashToCanonicalClassNameMap = new TreeMap<ClassHash,
// String>();
@@ -142,41 +132,25 @@ public class FuzzyBugComparator implements WarningComparator {
// For now, nothing to do
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.WarningComparator#setClassNameRewriter(edu.umd.cs
- * .findbugs.model.MovedClassMap)
- */
+ @Override
public void setClassNameRewriter(ClassNameRewriter classNameRewriter) {
this.classNameRewriter = classNameRewriter;
}
+ @Override
public int compare(BugInstance lhs, BugInstance rhs) {
int cmp;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Fuzzy comparison");
+ }
// Bug abbreviations must match.
BugPattern lhsPattern = lhs.getBugPattern();
BugPattern rhsPattern = rhs.getBugPattern();
- if (lhsPattern == null || rhsPattern == null) {
- if (DEBUG) {
- if (lhsPattern == null)
- System.out.println("Missing pattern: " + lhs.getType());
- if (rhsPattern == null)
- System.out.println("Missing pattern: " + rhs.getType());
- }
- String lhsCode = getCode(lhs.getType());
- String rhsCode = getCode(rhs.getType());
- if ((cmp = lhsCode.compareTo(rhsCode)) != 0)
- return cmp;
- } else {
- if ((cmp = lhsPattern.getAbbrev().compareTo(rhsPattern.getAbbrev())) != 0)
- return cmp;
+ if ((cmp = lhsPattern.getAbbrev().compareTo(rhsPattern.getAbbrev())) != 0) {
+ return cmp;
}
BugCollection lhsCollection = bugCollectionMap.get(lhs);
@@ -191,63 +165,70 @@ public class FuzzyBugComparator implements WarningComparator {
BugAnnotation lhsAnnotation = lhsIter.next();
BugAnnotation rhsAnnotation = rhsIter.next();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Compare annotations: " + lhsAnnotation + "," + rhsAnnotation);
+ }
// Annotation classes must match exactly
cmp = lhsAnnotation.getClass().getName().compareTo(rhsAnnotation.getClass().getName());
if (cmp != 0) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("annotation class mismatch: " + lhsAnnotation.getClass().getName() + ","
+ rhsAnnotation.getClass().getName());
+ }
return cmp;
}
- if (lhsAnnotation.getClass() == ClassAnnotation.class)
+ if (lhsAnnotation.getClass() == ClassAnnotation.class) {
cmp = compareClasses(lhsCollection, rhsCollection, (ClassAnnotation) lhsAnnotation,
(ClassAnnotation) rhsAnnotation);
- else if (lhsAnnotation.getClass() == MethodAnnotation.class)
+ } else if (lhsAnnotation.getClass() == MethodAnnotation.class) {
cmp = compareMethods(lhsCollection, rhsCollection, (MethodAnnotation) lhsAnnotation,
(MethodAnnotation) rhsAnnotation);
- else if (lhsAnnotation.getClass() == SourceLineAnnotation.class)
+ } else if (lhsAnnotation.getClass() == SourceLineAnnotation.class) {
cmp = compareSourceLines(lhsCollection, rhsCollection, (SourceLineAnnotation) lhsAnnotation,
(SourceLineAnnotation) rhsAnnotation);
- else
+ } else {
// everything else just compare directly
cmp = lhsAnnotation.compareTo(rhsAnnotation);
+ }
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
}
// Number of bug annotations must match
if (!lhsIter.hasNext() && !rhsIter.hasNext()) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Match!");
+ }
return 0;
- } else
+ } else {
return (lhsIter.hasNext() ? 1 : -1);
+ }
}
- /**
+ /*
* @param type
* @return the code of the Bug
- */
+ *
private String getCode(String type) {
int bar = type.indexOf('_');
if (bar < 0)
return "";
else
return type.substring(0, bar);
- }
+ }*/
private static int compareNullElements(Object a, Object b) {
- if (a != null)
+ if (a != null) {
return 1;
- else if (b != null)
+ } else if (b != null) {
return -1;
- else
+ } else {
return 0;
+ }
}
public int compareClasses(BugCollection lhsCollection, BugCollection rhsCollection, ClassAnnotation lhsClass,
@@ -299,7 +280,7 @@ public class FuzzyBugComparator implements WarningComparator {
* For now, just look at the 2 preceeding and succeeding opcodes for fuzzy
* source line matching.
*/
- private static final int NUM_CONTEXT_OPCODES = 2;
+ // private static final int NUM_CONTEXT_OPCODES = 2;
/**
* Compare source line annotations.
@@ -322,8 +303,9 @@ public class FuzzyBugComparator implements WarningComparator {
// Classes must match fuzzily.
int cmp = compareClassesByName(lhsCollection, rhsCollection, lhs.getClassName(), rhs.getClassName());
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return 0;
}
@@ -342,8 +324,8 @@ public class FuzzyBugComparator implements WarningComparator {
significantDescriptionSet.add("METHOD_DEFAULT");
significantDescriptionSet.add(MethodAnnotation.METHOD_CALLED);
significantDescriptionSet.add("METHOD_DANGEROUS_TARGET"); // but do NOT
- // use safe
- // targets
+ // use safe
+ // targets
significantDescriptionSet.add("METHOD_DECLARED_NONNULL");
significantDescriptionSet.add("FIELD_DEFAULT");
significantDescriptionSet.add("FIELD_ON");
diff --git a/src/java/edu/umd/cs/findbugs/HTMLBugReporter.java b/src/java/edu/umd/cs/findbugs/HTMLBugReporter.java
index 5a65bac..115c744 100644
--- a/src/java/edu/umd/cs/findbugs/HTMLBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/HTMLBugReporter.java
@@ -34,7 +34,7 @@ import org.dom4j.Document;
import org.dom4j.io.DocumentSource;
public class HTMLBugReporter extends BugCollectionBugReporter {
- private String stylesheet;
+ private final String stylesheet;
private Exception fatalException;
@@ -74,8 +74,9 @@ public class HTMLBugReporter extends BugCollectionBugReporter {
} catch (Exception e) {
logError("Could not generate HTML output", e);
fatalException = e;
- if (FindBugs.DEBUG)
+ if (FindBugs.DEBUG) {
e.printStackTrace();
+ }
}
outputStream.close();
}
@@ -85,8 +86,9 @@ public class HTMLBugReporter extends BugCollectionBugReporter {
}
private static InputStream getStylesheetStream(String stylesheet) throws IOException {
- if (FindBugs.DEBUG)
+ if (FindBugs.DEBUG) {
System.out.println("Attempting to load stylesheet " + stylesheet);
+ }
try {
URL u = new URL(stylesheet);
return u.openStream();
@@ -106,4 +108,3 @@ public class HTMLBugReporter extends BugCollectionBugReporter {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/I18N.java b/src/java/edu/umd/cs/findbugs/I18N.java
index 00fc8f3..5afc8f1 100644
--- a/src/java/edu/umd/cs/findbugs/I18N.java
+++ b/src/java/edu/umd/cs/findbugs/I18N.java
@@ -84,8 +84,9 @@ public class I18N {
public @Nonnull
String getMessage(String key) {
BugPattern bugPattern = DetectorFactoryCollection.instance().lookupBugPattern(key);
- if (bugPattern == null)
+ if (bugPattern == null) {
return L10N.getLocalString("err.missing_pattern", "Error: missing bug pattern for key") + " " + key;
+ }
return bugPattern.getAbbrev() + ": " + bugPattern.getLongDescription();
}
@@ -100,16 +101,18 @@ public class I18N {
public @Nonnull
String getShortMessage(String key) {
BugPattern bugPattern = DetectorFactoryCollection.instance().lookupBugPattern(key);
- if (bugPattern == null)
+ if (bugPattern == null) {
return L10N.getLocalString("err.missing_pattern", "Error: missing bug pattern for key") + " " + key;
+ }
return bugPattern.getAbbrev() + ": " + bugPattern.getShortDescription();
}
public @Nonnull
String getShortMessageWithoutCode(String key) {
BugPattern bugPattern = DetectorFactoryCollection.instance().lookupBugPattern(key);
- if (bugPattern == null)
+ if (bugPattern == null) {
return L10N.getLocalString("err.missing_pattern", "Error: missing bug pattern for key") + " " + key;
+ }
return bugPattern.getShortDescription();
}
@@ -122,8 +125,9 @@ public class I18N {
public @Nonnull
String getDetailHTML(String key) {
BugPattern bugPattern = DetectorFactoryCollection.instance().lookupBugPattern(key);
- if (bugPattern == null)
+ if (bugPattern == null) {
return L10N.getLocalString("err.missing_pattern", "Error: missing bug pattern for key") + " " + key;
+ }
return bugPattern.getDetailHTML();
}
@@ -139,14 +143,15 @@ public class I18N {
try {
return annotationDescriptionBundle.getString(key);
} catch (MissingResourceException mre) {
- if (DEBUG)
+ if (DEBUG) {
return "TRANSLATE(" + key + ") (param={0}}";
- else
+ } else {
try {
return englishAnnotationDescriptionBundle.getString(key);
} catch (MissingResourceException mre2) {
return key + " {0}";
}
+ }
}
}
@@ -163,8 +168,9 @@ public class I18N {
public @Nonnull
String getBugTypeDescription(String shortBugType) {
BugCode bugCode = DetectorFactoryCollection.instance().lookupBugCode(shortBugType);
- if (bugCode == null)
+ if (bugCode == null) {
return L10N.getLocalString("err.missing_code", "Error: missing bug code for key") + " " + shortBugType;
+ }
return bugCode.getDescription();
}
@@ -219,8 +225,9 @@ public class I18N {
*/
public List<String> getUserDesignationKeys(boolean sort) {
List<String> result = getUserDesignationKeys();
- if (sort)
+ if (sort) {
Collections.sort(result, designationKeyComparator);
+ }
return result;
}
@@ -236,53 +243,66 @@ public class I18N {
* Returns a negative integer, zero, or a positive integer as the left
* key is less than, equal to, or greater than the right key.
*/
+ @Override
public int compare(String lKey, String rKey) {
int lCat = categoryOf(lKey);
int catDiff = lCat - categoryOf(rKey);
- if (catDiff != 0 || lCat != 0)
+ if (catDiff != 0 || lCat != 0) {
return catDiff;
+ }
// if we get this far we have two unrecognized strings
return lKey.compareTo(rKey);
}
private static int categoryOf(String key) {
- if (key == null)
+ if (key == null) {
return -30;
- if (key.length() <= 0)
+ }
+ if (key.length() <= 0) {
return -29;
+ }
switch (key.charAt(0)) {
case 'U':
- if ("UNCLASSIFIED".equals(key))
+ if ("UNCLASSIFIED".equals(key)) {
return 20;
+ }
break;
case 'I':
- if ("I_WILL_FIX".equals(key))
+ if ("I_WILL_FIX".equals(key)) {
return 12;
+ }
break;
case 'B':
- if ("BAD_ANALYSIS".equals(key))
+ if ("BAD_ANALYSIS".equals(key)) {
return 15;
+ }
break;
case 'N':
- if ("NEEDS_STUDY".equals(key))
+ if ("NEEDS_STUDY".equals(key)) {
return -22;
- if ("NOT_A_BUG".equals(key))
+ }
+ if ("NOT_A_BUG".equals(key)) {
return -15;
+ }
break;
case 'O':
- if ("OBSOLETE_CODE".equals(key))
+ if ("OBSOLETE_CODE".equals(key)) {
return 30;
+ }
break;
case 'M':
- if ("MOSTLY_HARMLESS".equals(key))
+ if ("MOSTLY_HARMLESS".equals(key)) {
return -10;
- if ("MUST_FIX".equals(key))
+ }
+ if ("MUST_FIX".equals(key)) {
return 10;
+ }
break;
case 'S':
- if ("SHOULD_FIX".equals(key))
+ if ("SHOULD_FIX".equals(key)) {
return 5;
+ }
}
return 0; // between MOSTLY_HARMLESS and SHOULD_FIX
}
@@ -293,4 +313,3 @@ public class I18N {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/IClassScreener.java b/src/java/edu/umd/cs/findbugs/IClassScreener.java
index 1aa2230..074fe11 100644
--- a/src/java/edu/umd/cs/findbugs/IClassScreener.java
+++ b/src/java/edu/umd/cs/findbugs/IClassScreener.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs;
/**
* Screen class files to decide which subset of them to analyze.
- *
+ *
* @author David Hovemeyer
*/
public interface IClassScreener {
diff --git a/src/java/edu/umd/cs/findbugs/IFindBugsEngine.java b/src/java/edu/umd/cs/findbugs/IFindBugsEngine.java
index 9a30ff8..a5040bb 100644
--- a/src/java/edu/umd/cs/findbugs/IFindBugsEngine.java
+++ b/src/java/edu/umd/cs/findbugs/IFindBugsEngine.java
@@ -33,21 +33,21 @@ import edu.umd.cs.findbugs.filter.FilterException;
* Interface for a FindBugs engine class. An instance of this interface takes a
* project, user configuration options, orchestrates the analysis of the classes
* in the project, and reports the results to the configured BugReporter.
- *
+ *
* @author David Hovemeyer
*/
public interface IFindBugsEngine {
/**
* Get the BugReporter.
- *
+ *
* @return the BugReporter
*/
public BugReporter getBugReporter();
/**
* Set the BugReporter.
- *
+ *
* @param bugReporter
* The BugReporter to set
*/
@@ -55,7 +55,7 @@ public interface IFindBugsEngine {
/**
* Set the Project.
- *
+ *
* @param project
* The Project to set
*/
@@ -63,7 +63,7 @@ public interface IFindBugsEngine {
/**
* Get the Project.
- *
+ *
* @return the Project
*/
public Project getProject();
@@ -71,7 +71,7 @@ public interface IFindBugsEngine {
/**
* Set the progress callback that will be used to keep track of the progress
* of the analysis.
- *
+ *
* @param progressCallback
* the progress callback
*/
@@ -79,7 +79,7 @@ public interface IFindBugsEngine {
/**
* Set filter of bug instances to include or exclude.
- *
+ *
* @param filterFileName
* the name of the filter file
* @param include
@@ -90,7 +90,7 @@ public interface IFindBugsEngine {
/**
* Provide baseline of bugs not to report
- *
+ *
* @param baselineBugs
* the name of the xml bug baseline file
* @throws DocumentException
@@ -101,7 +101,7 @@ public interface IFindBugsEngine {
* Set the UserPreferences representing which Detectors should be used. If
* UserPreferences are not set explicitly, the default set of Detectors will
* be used.
- *
+ *
* @param userPreferences
* the UserPreferences
*/
@@ -109,7 +109,7 @@ public interface IFindBugsEngine {
/**
* Add an IClassObserver.
- *
+ *
* @param classObserver
* the IClassObserver
*/
@@ -118,7 +118,7 @@ public interface IFindBugsEngine {
/**
* Set the ClassScreener. This object chooses which individual classes to
* analyze. By default, all classes are analyzed.
- *
+ *
* @param classScreener
* the ClassScreener to use
*/
@@ -126,7 +126,7 @@ public interface IFindBugsEngine {
/**
* Set relaxed reporting mode.
- *
+ *
* @param relaxedReportingMode
* true if relaxed reporting mode should be enabled, false if not
*/
@@ -134,7 +134,7 @@ public interface IFindBugsEngine {
/**
* Set whether or not training output should be emitted.
- *
+ *
* @param trainingOutputDir
* directory to save training output in
*/
@@ -143,7 +143,7 @@ public interface IFindBugsEngine {
/**
* Set whether or not training input should be used to make the analysis
* more precise.
- *
+ *
* @param trainingInputDir
* directory to load training input from
*/
@@ -151,7 +151,7 @@ public interface IFindBugsEngine {
/**
* Set analysis feature settings.
- *
+ *
* @param settingList
* list of analysis feature settings
*/
@@ -182,7 +182,7 @@ public interface IFindBugsEngine {
/**
* Set the filename of the source info file containing line numbers for
* fields and classes.
- *
+ *
* @param sourceInfoFile
* the source info filename
*/
@@ -191,7 +191,7 @@ public interface IFindBugsEngine {
/**
* Execute FindBugs on the Project. All bugs found are reported to the
* BugReporter object which was set when this object was constructed.
- *
+ *
* @throws java.io.IOException
* if an I/O exception occurs analyzing one of the files
* @throws InterruptedException
@@ -223,7 +223,7 @@ public interface IFindBugsEngine {
/**
* Get the UserPreferences.
- *
+ *
* @return the UserPreferences
*/
public UserPreferences getUserPreferences();
@@ -231,35 +231,35 @@ public interface IFindBugsEngine {
/**
* Return whether or not training output should be emitted after analysis
* completes.
- *
+ *
* @return true if training output should be emitted, false if not
*/
public boolean emitTrainingOutput();
/**
* Get the training output directory.
- *
+ *
* @return the training output directory
*/
public String getTrainingOutputDir();
/**
* Return whether or not we should make use of training data.
- *
+ *
* @return true if training data should be used, false if not
*/
public boolean useTrainingInput();
/**
* Get the training input database directory.
- *
+ *
* @return the training input database directory
*/
public String getTrainingInputDir();
/**
* Set whether or not nested archives should be scanned.
- *
+ *
* @param scanNestedArchives
* true if nested archives should be scanned, false if not
*/
@@ -268,7 +268,7 @@ public interface IFindBugsEngine {
/**
* Set whether or not to generate an empty output file if there were no
* class files specified.
- *
+ *
* @param noClassOk
* true if FindBugs should generate empty output file
*/
@@ -277,7 +277,7 @@ public interface IFindBugsEngine {
/**
* Set the DetectorFactoryCollection from which plugins/detectors may be
* accessed.
- *
+ *
* @param detectorFactoryCollection
* the DetectorFactoryCollection
*/
diff --git a/src/java/edu/umd/cs/findbugs/IGuiCallback.java b/src/java/edu/umd/cs/findbugs/IGuiCallback.java
index fe2ca34..7f9f770 100644
--- a/src/java/edu/umd/cs/findbugs/IGuiCallback.java
+++ b/src/java/edu/umd/cs/findbugs/IGuiCallback.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.cloud.Cloud;
/**
* Interface for any kind of GUI attached to the current FindBug analysis
- *
+ *
* @author Andrei
*/
public interface IGuiCallback {
@@ -83,18 +83,18 @@ public interface IGuiCallback {
void showMessageDialogAndWait(String message) throws InterruptedException;
public class FormItem {
- private String label;
+ private final String label;
- private String defaultValue;
+ private final String defaultValue;
private boolean password = false;
- private List<String> possibleValues;
+ private final List<String> possibleValues;
private JComponent field;
-
+
private String currentValue;
-
+
private List<FormItem> items;
public FormItem(String label) {
diff --git a/src/java/edu/umd/cs/findbugs/InstructionScanner.java b/src/java/edu/umd/cs/findbugs/InstructionScanner.java
index febda64..24a4756 100644
--- a/src/java/edu/umd/cs/findbugs/InstructionScanner.java
+++ b/src/java/edu/umd/cs/findbugs/InstructionScanner.java
@@ -44,4 +44,3 @@ public interface InstructionScanner {
public boolean isDone();
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/InstructionScannerDriver.java b/src/java/edu/umd/cs/findbugs/InstructionScannerDriver.java
index 82d0f2a..59ab42a 100644
--- a/src/java/edu/umd/cs/findbugs/InstructionScannerDriver.java
+++ b/src/java/edu/umd/cs/findbugs/InstructionScannerDriver.java
@@ -33,15 +33,15 @@ import edu.umd.cs.findbugs.ba.Edge;
* and edge is fed to all scanners so created.
*/
public class InstructionScannerDriver {
- private Iterator<Edge> edgeIter;
+ private final Iterator<Edge> edgeIter;
- private LinkedList<InstructionScanner> scannerList;
+ private final LinkedList<InstructionScanner> scannerList;
private static final boolean DEBUG = SystemProperties.getBoolean("isd.debug");
/**
* Constructor.
- *
+ *
* @param edgeIter
* iterator over Edges specifying path to be scanned
*/
@@ -54,7 +54,7 @@ public class InstructionScannerDriver {
* Execute by driving the InstructionScannerGenerator over all instructions.
* Each generated InstructionScanner is driven over all instructions and
* edges.
- *
+ *
* @param generator
* the InstructionScannerGenerator
*/
@@ -64,8 +64,9 @@ public class InstructionScannerDriver {
while (edgeIter.hasNext()) {
Edge edge = edgeIter.next();
BasicBlock source = edge.getSource();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("ISD: scanning instructions in block " + source.getLabel());
+ }
// Traverse all instructions in the source block
Iterator<InstructionHandle> i = source.instructionIterator();
@@ -74,8 +75,9 @@ public class InstructionScannerDriver {
InstructionHandle handle = i.next();
// Check if the generator wants to create a new scanner
- if (generator.start(handle))
+ if (generator.start(handle)) {
scannerList.add(generator.createScanner());
+ }
// Pump the instruction into all scanners
for (InstructionScanner scanner : scannerList) {
@@ -85,8 +87,9 @@ public class InstructionScannerDriver {
++count;
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("ISD: scanned " + count + " instructions");
+ }
// Now that we've finished the source block, pump the edge
// into all scanners
@@ -97,4 +100,3 @@ public class InstructionScannerDriver {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/InstructionScannerGenerator.java b/src/java/edu/umd/cs/findbugs/InstructionScannerGenerator.java
index 4873084..0c7b6db 100644
--- a/src/java/edu/umd/cs/findbugs/InstructionScannerGenerator.java
+++ b/src/java/edu/umd/cs/findbugs/InstructionScannerGenerator.java
@@ -38,4 +38,3 @@ public interface InstructionScannerGenerator {
public InstructionScanner createScanner();
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/IntAnnotation.java b/src/java/edu/umd/cs/findbugs/IntAnnotation.java
index 37c721e..00f49fa 100644
--- a/src/java/edu/umd/cs/findbugs/IntAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/IntAnnotation.java
@@ -28,7 +28,7 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* Bug annotation class for integer values.
- *
+ *
* @author David Hovemeyer
* @see BugAnnotation
*/
@@ -37,7 +37,7 @@ public class IntAnnotation implements BugAnnotation {
private static final String DEFAULT_ROLE = "INT_DEFAULT";
- private int value;
+ private final int value;
private String description;
@@ -50,6 +50,9 @@ public class IntAnnotation implements BugAnnotation {
public static final String INT_VALUE = "INT_VALUE";
+ public static final String INT_MIN_VALUE = "INT_MIN_VALUE";
+ public static final String INT_MAX_VALUE = "INT_MAX_VALUE";
+
public static final String INT_SHIFT = "INT_SHIFT";
public static final String INT_EXPECTED_ARGUMENTS = "INT_EXPECTED_ARGUMENTS";
@@ -60,7 +63,7 @@ public class IntAnnotation implements BugAnnotation {
/**
* Constructor.
- *
+ *
* @param value
* the integer value
*/
@@ -80,56 +83,64 @@ public class IntAnnotation implements BugAnnotation {
/**
* Get the integer value.
- *
+ *
* @return the integer value
*/
public int getValue() {
return value;
}
+ @Override
public void accept(BugAnnotationVisitor visitor) {
visitor.visitIntAnnotation(this);
}
+ @Override
public String format(String key, ClassAnnotation primaryClass) {
- if (key.equals("hash")) {
- if (isSignificant())
+ if ("hash".equals(key)) {
+ if (isSignificant()) {
return Integer.toString(value);
- else
+ } else {
return "";
+ }
}
return getShortInteger(value);
}
-
+
public static String getShortInteger(int value) {
String base16 = Integer.toHexString(value);
int unique = uniqueDigits(base16);
String base10 = Integer.toString(value);
-
- if (unique <= 3 && base16.length() - unique >= 3 && base10.length() > base16.length())
+
+ if (unique <= 3 && base16.length() - unique >= 3 && base10.length() > base16.length()) {
return "0x"+base16;
+ }
return base10;
}
public static String getShortInteger(long value) {
String base16 = Long.toHexString(value);
int unique = uniqueDigits(base16);
String base10 = Long.toString(value);
-
- if (unique <= 3 && base16.length() - unique >= 3 && base10.length() > base16.length())
+
+ if (unique <= 3 && base16.length() - unique >= 3 && base10.length() > base16.length()) {
return "0x"+base16;
+ }
return base10;
}
private static int uniqueDigits(String value) {
Set<Character> used = new HashSet<Character>();
- for(int i = 0; i < value.length(); i++)
+ for(int i = 0; i < value.length(); i++) {
used.add(value.charAt(i));
+ }
return used.size();
}
+ @Override
public void setDescription(String description) {
this.description = description;
}
+ @Override
public String getDescription() {
return description;
}
@@ -141,15 +152,18 @@ public class IntAnnotation implements BugAnnotation {
@Override
public boolean equals(Object o) {
- if (!(o instanceof IntAnnotation))
+ if (!(o instanceof IntAnnotation)) {
return false;
+ }
return value == ((IntAnnotation) o).value;
}
+ @Override
public int compareTo(BugAnnotation o) {
- if (!(o instanceof IntAnnotation)) // BugAnnotations must be Comparable
- // with any type of BugAnnotation
+ if (!(o instanceof IntAnnotation)) {
+ // with any type of BugAnnotation
return this.getClass().getName().compareTo(o.getClass().getName());
+ }
return value - ((IntAnnotation) o).value;
}
@@ -168,27 +182,31 @@ public class IntAnnotation implements BugAnnotation {
private static final String ELEMENT_NAME = "Int";
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, false, false);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean addMessages, boolean isPrimary) throws IOException {
XMLAttributeList attributeList = new XMLAttributeList().addAttribute("value", String.valueOf(value));
String role = getDescription();
- if (!role.equals(DEFAULT_ROLE))
+ if (!DEFAULT_ROLE.equals(role)) {
attributeList.addAttribute("role", role);
+ }
BugAnnotationUtil.writeXML(xmlOutput, ELEMENT_NAME, this, attributeList, addMessages);
}
+ @Override
public boolean isSignificant() {
- return !description.equals(INT_SYNC_PERCENT) && !description.equals(INT_OCCURRENCES);
+ return !INT_SYNC_PERCENT.equals(description) && !INT_OCCURRENCES.equals(description);
}
+ @Override
public String toString(ClassAnnotation primaryClass) {
return toString();
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/InterproceduralFirstPassDetector.java b/src/java/edu/umd/cs/findbugs/InterproceduralFirstPassDetector.java
index c78c2c5..1bfc815 100644
--- a/src/java/edu/umd/cs/findbugs/InterproceduralFirstPassDetector.java
+++ b/src/java/edu/umd/cs/findbugs/InterproceduralFirstPassDetector.java
@@ -23,7 +23,7 @@ package edu.umd.cs.findbugs;
* Detector implementing a slow first pass to collect interprocedural properties
* for a later detector pass. We assign these a special interface because they
* are probably too slow to be enabled by default.
- *
+ *
* @author David Hovemeyer
*/
public interface InterproceduralFirstPassDetector extends NonReportingDetector {
diff --git a/src/java/edu/umd/cs/findbugs/JavaVersion.java b/src/java/edu/umd/cs/findbugs/JavaVersion.java
index aa5a887..f293cf3 100644
--- a/src/java/edu/umd/cs/findbugs/JavaVersion.java
+++ b/src/java/edu/umd/cs/findbugs/JavaVersion.java
@@ -57,22 +57,24 @@ public class JavaVersion {
/**
* Constructor.
- *
+ *
* @param versionString
* a version string, as returned from the
* <code>java.version</code> system property: e.g., "1.4.2_04"
*/
public JavaVersion(String versionString) throws JavaVersionException {
Matcher matcher = PATTERN.matcher(versionString);
- if (!matcher.matches())
+ if (!matcher.matches()) {
throw new JavaVersionException("Could not parse Java version string: " + versionString);
+ }
try {
major = Integer.parseInt(matcher.group(1));
minor = Integer.parseInt(matcher.group(2));
- if (matcher.group(3) != null)
+ if (matcher.group(3) != null) {
rest = matcher.group(3);
- else
+ } else {
rest = "";
+ }
} catch (NumberFormatException e) {
throw new JavaVersionException("Could not parse Java Version string: " + versionString, e);
}
@@ -80,7 +82,7 @@ public class JavaVersion {
/**
* Constructor.
- *
+ *
* @param major
* major version
* @param minor
@@ -136,7 +138,7 @@ public class JavaVersion {
/**
* Return whether the Java version represented by this object is at least as
* recent as the one given.
- *
+ *
* @param other
* another JavaVersion
* @return true if this Java version is at least as recent as the one given
@@ -146,4 +148,3 @@ public class JavaVersion {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/JavaVersionException.java b/src/java/edu/umd/cs/findbugs/JavaVersionException.java
index 3a5083a..d847cbe 100644
--- a/src/java/edu/umd/cs/findbugs/JavaVersionException.java
+++ b/src/java/edu/umd/cs/findbugs/JavaVersionException.java
@@ -35,4 +35,3 @@ public class JavaVersionException extends Exception {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/L10N.java b/src/java/edu/umd/cs/findbugs/L10N.java
index de84aa5..43e7765 100644
--- a/src/java/edu/umd/cs/findbugs/L10N.java
+++ b/src/java/edu/umd/cs/findbugs/L10N.java
@@ -46,12 +46,13 @@ public class L10N {
private static PrintWriter extraProperties;
static {
try {
- if (GENERATE_MISSING_KEYS)
+ if (GENERATE_MISSING_KEYS) {
try {
extraProperties = UserTextFile.printWriter("/tmp/extra.properties");
} catch (IOException e) {
e.printStackTrace();
}
+ }
bundle = ResourceBundle.getBundle("edu.umd.cs.findbugs.gui.bundle.findbugs");
bundle_en = ResourceBundle.getBundle("edu.umd.cs.findbugs.gui.bundle.findbugs", Locale.ENGLISH);
@@ -64,24 +65,27 @@ public class L10N {
}
private static String lookup(ResourceBundle b, String key) {
- if (b == null || key == null)
+ if (b == null || key == null) {
throw new MissingResourceException(null, null, null);
+ }
return b.getString(key);
}
public static String getLocalString(String key, String defaultString) {
- if (key == null)
+ if (key == null) {
return "TRANSLATE(" + defaultString + ")";
+ }
try {
return lookup(bundle, key);
} catch (MissingResourceException mre) {
try {
String en = lookup(bundle_en, key);
- if (DEBUG)
+ if (DEBUG) {
return "TRANSLATE(" + en + ")";
- else
+ } else {
return en;
+ }
} catch (MissingResourceException mre2) {
if (extraProperties != null) {
extraProperties.println(key + "=" + defaultString);
@@ -89,10 +93,11 @@ public class L10N {
}
// String en = "Default("+defaultString+")";
String en = defaultString;
- if (DEBUG)
+ if (DEBUG) {
return "TRANSLATE(" + en + ")";
- else
+ } else {
return en;
+ }
}
}
}
diff --git a/src/java/edu/umd/cs/findbugs/LaunchAppropriateUI.java b/src/java/edu/umd/cs/findbugs/LaunchAppropriateUI.java
index b1ea78d..dbceedd 100644
--- a/src/java/edu/umd/cs/findbugs/LaunchAppropriateUI.java
+++ b/src/java/edu/umd/cs/findbugs/LaunchAppropriateUI.java
@@ -164,9 +164,11 @@ public class LaunchAppropriateUI {
String s = System.getProperty("findbugs.launchUI");
if (s == null) {
- for (String a : args)
- if (a.equals("-output") || a.equals("-xml") || a.endsWith(".class") || a.endsWith(".jar"))
+ for (String a : args) {
+ if ("-output".equals(a) || "-xml".equals(a) || a.endsWith(".class") || a.endsWith(".jar")) {
return TEXTUI;
+ }
+ }
s = "gui2";
}
diff --git a/src/java/edu/umd/cs/findbugs/LocalVariableAnnotation.java b/src/java/edu/umd/cs/findbugs/LocalVariableAnnotation.java
index 79f2449..b4bf525 100644
--- a/src/java/edu/umd/cs/findbugs/LocalVariableAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/LocalVariableAnnotation.java
@@ -50,7 +50,7 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* Bug annotation class for local variable names
- *
+ *
* @author William Pugh
* @see BugAnnotation
*/
@@ -93,7 +93,7 @@ public class LocalVariableAnnotation implements BugAnnotation {
/**
* Constructor.
- *
+ *
* @param name
* the name of the local variable
* @param register
@@ -108,12 +108,12 @@ public class LocalVariableAnnotation implements BugAnnotation {
this.pc = pc;
this.line = -1;
this.description = DEFAULT_ROLE;
- this.setDescription(name.equals("?") ? "LOCAL_VARIABLE_UNKNOWN" : "LOCAL_VARIABLE_NAMED");
+ this.setDescription("?".equals(name) ? "LOCAL_VARIABLE_UNKNOWN" : "LOCAL_VARIABLE_NAMED");
}
/**
* Constructor.
- *
+ *
* @param name
* the name of the local variable
* @param register
@@ -128,7 +128,7 @@ public class LocalVariableAnnotation implements BugAnnotation {
this.pc = pc;
this.line = line;
this.description = DEFAULT_ROLE;
- this.setDescription(name.equals("?") ? "LOCAL_VARIABLE_UNKNOWN" : "LOCAL_VARIABLE_NAMED");
+ this.setDescription("?".equals(name) ? "LOCAL_VARIABLE_UNKNOWN" : "LOCAL_VARIABLE_NAMED");
}
public static LocalVariableAnnotation getLocalVariableAnnotation(Method method, Location location, IndexedInstruction ins) {
@@ -149,12 +149,12 @@ public class LocalVariableAnnotation implements BugAnnotation {
lv1 = localVariableTable.getLocalVariable(local, position2);
position1 = position2;
}
- if (lv1 != null)
+ if (lv1 != null) {
localName = lv1.getName();
- else
+ } else {
for (LocalVariable lv : localVariableTable.getLocalVariableTable()) {
if (lv.getIndex() == local) {
- if (!localName.equals("?") && !localName.equals(lv.getName())) {
+ if (!"?".equals(localName) && !localName.equals(lv.getName())) {
// not a single consistent name
localName = "?";
break;
@@ -162,17 +162,19 @@ public class LocalVariableAnnotation implements BugAnnotation {
localName = lv.getName();
}
}
+ }
}
LineNumberTable lineNumbers = method.getLineNumberTable();
- if (lineNumbers == null)
+ if (lineNumbers == null) {
return new LocalVariableAnnotation(localName, local, position1);
+ }
int line = lineNumbers.getSourceLine(position1);
return new LocalVariableAnnotation(localName, local, position1, line);
}
/**
* Get a local variable annotation describing a parameter.
- *
+ *
* @param method
* a Method
* @param local
@@ -181,10 +183,11 @@ public class LocalVariableAnnotation implements BugAnnotation {
*/
public static LocalVariableAnnotation getParameterLocalVariableAnnotation(Method method, int local) {
LocalVariableAnnotation lva = getLocalVariableAnnotation(method, local, 0, 0);
- if (lva.isNamed())
+ if (lva.isNamed()) {
lva.setDescription(LocalVariableAnnotation.PARAMETER_NAMED_ROLE);
- else
+ } else {
lva.setDescription(LocalVariableAnnotation.PARAMETER_ROLE);
+ }
return lva;
}
@@ -197,35 +200,42 @@ public class LocalVariableAnnotation implements BugAnnotation {
}
}
+ @Override
public void accept(BugAnnotationVisitor visitor) {
visitor.visitLocalVariableAnnotation(this);
}
+ @Override
public String format(String key, ClassAnnotation primaryClass) {
// System.out.println("format: " + key + " reg: " + register + " name: "
// + value);
- if (key.equals("hash")) {
- if (register < 0)
+ if ("hash".equals(key)) {
+ if (register < 0) {
return "??";
+ }
return name;
}
- if (register < 0)
+ if (register < 0) {
return "?";
- if (key.equals("register"))
+ }
+ if ("register".equals(key)) {
return String.valueOf(register);
- else if (key.equals("pc"))
+ } else if ("pc".equals(key)) {
return String.valueOf(pc);
- else if (key.equals("name") || key.equals("givenClass"))
+ } else if ("name".equals(key) || "givenClass".equals(key)) {
return name;
- else if (!name.equals("?"))
+ } else if (!"?".equals(name)) {
return name;
+ }
return "$L" + register;
}
+ @Override
public void setDescription(String description) {
this.description = description.intern();
}
+ @Override
public String getDescription() {
return description;
}
@@ -237,16 +247,19 @@ public class LocalVariableAnnotation implements BugAnnotation {
@Override
public boolean equals(Object o) {
- if (!(o instanceof LocalVariableAnnotation))
+ if (!(o instanceof LocalVariableAnnotation)) {
return false;
+ }
return name.equals(((LocalVariableAnnotation) o).name);
}
+ @Override
public int compareTo(BugAnnotation o) {
- if (!(o instanceof LocalVariableAnnotation)) // BugAnnotations must be
- // Comparable with any type
- // of BugAnnotation
+ if (!(o instanceof LocalVariableAnnotation)) {
+ // Comparable with any type
+ // of BugAnnotation
return this.getClass().getName().compareTo(o.getClass().getName());
+ }
return name.compareTo(((LocalVariableAnnotation) o).name);
}
@@ -265,23 +278,26 @@ public class LocalVariableAnnotation implements BugAnnotation {
private static final String ELEMENT_NAME = "LocalVariable";
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, false, false);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean addMessages, boolean isPrimary) throws IOException {
XMLAttributeList attributeList = new XMLAttributeList().addAttribute("name", name)
.addAttribute("register", String.valueOf(register)).addAttribute("pc", String.valueOf(pc));
String role = getDescription();
- if (!role.equals(DEFAULT_ROLE))
+ if (!DEFAULT_ROLE.equals(role)) {
attributeList.addAttribute("role", role);
+ }
BugAnnotationUtil.writeXML(xmlOutput, ELEMENT_NAME, this, attributeList, addMessages);
}
public boolean isNamed() {
- return register >= 0 && !name.equals("?");
+ return register >= 0 && !"?".equals(name);
}
/**
@@ -299,21 +315,17 @@ public class LocalVariableAnnotation implements BugAnnotation {
return register;
}
+ @Override
public boolean isSignificant() {
- return !name.equals("?");
+ return !"?".equals(name);
}
- /**
- * @param method
- * @param item
- * @param pc2
- * @return
- */
public static @CheckForNull
LocalVariableAnnotation getLocalVariableAnnotation(Method method, Item item, int pc) {
int reg = item.getRegisterNumber();
- if (reg < 0)
+ if (reg < 0) {
return null;
+ }
return getLocalVariableAnnotation(method, reg, pc, item.getPC());
}
@@ -321,8 +333,9 @@ public class LocalVariableAnnotation implements BugAnnotation {
public static @CheckForNull
LocalVariableAnnotation getLocalVariableAnnotation(DismantleBytecode visitor, Item item) {
int reg = item.getRegisterNumber();
- if (reg < 0)
+ if (reg < 0) {
return null;
+ }
return getLocalVariableAnnotation(visitor.getMethod(), reg, visitor.getPC(), item.getPC());
}
@@ -339,8 +352,9 @@ public class LocalVariableAnnotation implements BugAnnotation {
BitSet liveStoreSetAtEntry = llsaDataflow.getAnalysis().getResultFact(cfg.getEntry());
int localsThatAreParameters = PreorderVisitor.getNumberArguments(method.getSignature());
int startIndex = 0;
- if (!method.isStatic())
+ if (!method.isStatic()) {
startIndex = 1;
+ }
SignatureParser parser = new SignatureParser(method.getSignature());
Iterator<String> signatureIterator = parser.parameterSignatureIterator();
for (int i = startIndex; i < localsThatAreParameters + startIndex; i++) {
@@ -349,8 +363,9 @@ public class LocalVariableAnnotation implements BugAnnotation {
// parameter isn't live and signatures match
LocalVariableAnnotation potentialMatch = LocalVariableAnnotation.getLocalVariableAnnotation(method, i, 0, 0);
potentialMatch.setDescription(DID_YOU_MEAN_ROLE);
- if (!potentialMatch.isNamed())
+ if (!potentialMatch.isNamed()) {
return potentialMatch;
+ }
int distance = EditDistance.editDistance(name, potentialMatch.getName());
if (distance < lowestCost) {
match = potentialMatch;
@@ -378,8 +393,9 @@ public class LocalVariableAnnotation implements BugAnnotation {
LocalVariableAnnotation match = null;
int localsThatAreParameters = PreorderVisitor.getNumberArguments(method.getSignature());
int startIndex = 0;
- if (!method.isStatic())
+ if (!method.isStatic()) {
startIndex = 1;
+ }
SignatureParser parser = new SignatureParser(method.getSignature());
Iterator<String> signatureIterator = parser.parameterSignatureIterator();
int lowestCost = Integer.MAX_VALUE;
@@ -387,8 +403,9 @@ public class LocalVariableAnnotation implements BugAnnotation {
String sig = signatureIterator.next();
if (signature.equals(sig)) {
LocalVariableAnnotation potentialMatch = LocalVariableAnnotation.getLocalVariableAnnotation(method, i, 0, 0);
- if (!potentialMatch.isNamed())
+ if (!potentialMatch.isNamed()) {
continue;
+ }
int distance = EditDistance.editDistance(name, potentialMatch.getName());
if (distance < lowestCost) {
match = potentialMatch;
@@ -401,14 +418,15 @@ public class LocalVariableAnnotation implements BugAnnotation {
// signatures match
}
}
- if (lowestCost < 5)
+ if (lowestCost < 5) {
return match;
+ }
return null;
}
+ @Override
public String toString(ClassAnnotation primaryClass) {
return toString();
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/Lookup.java b/src/java/edu/umd/cs/findbugs/Lookup.java
index 4a220c2..e965477 100644
--- a/src/java/edu/umd/cs/findbugs/Lookup.java
+++ b/src/java/edu/umd/cs/findbugs/Lookup.java
@@ -25,11 +25,9 @@ import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
-import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.XClass;
import edu.umd.cs.findbugs.ba.XFactory;
import edu.umd.cs.findbugs.ba.XMethod;
-import edu.umd.cs.findbugs.ba.ch.Subtypes2;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.DescriptorFactory;
@@ -41,9 +39,11 @@ import edu.umd.cs.findbugs.visitclass.Constants2;
public class Lookup implements Constants2 {
+ /*
private static Subtypes2 subtypes2() {
return AnalysisContext.currentAnalysisContext().getSubtypes2();
}
+ */
public static XClass getXClass(ClassDescriptor c) throws CheckedAnalysisException {
return Global.getAnalysisCache().getClassAnalysis(XClass.class, c);
@@ -86,16 +86,18 @@ public class Lookup implements Constants2 {
throws CheckedAnalysisException {
ClassDescriptor superclassDescriptor = clazz.getSuperclassDescriptor();
- if (superclassDescriptor == null)
+ if (superclassDescriptor == null) {
return clazz;
+ }
return findImplementor(getXClass(superclassDescriptor), name, signature, isStatic);
}
public static XClass findImplementor(XClass clazz, String name, String signature, boolean isStatic)
throws CheckedAnalysisException {
XMethod m = clazz.findMethod(name, signature, isStatic);
- if (m != null)
+ if (m != null) {
return clazz;
+ }
return findSuperImplementor(clazz, name, signature, isStatic);
}
@@ -105,8 +107,9 @@ public class Lookup implements Constants2 {
JavaClass c = clazz;
while (true) {
c = c.getSuperClass();
- if (c == null)
+ if (c == null) {
return null;
+ }
Method m = findImplementation(c, name, signature);
if (m != null) {
return c;
@@ -124,11 +127,13 @@ public class Lookup implements Constants2 {
JavaClass c = clazz;
while (true) {
c = c.getSuperClass();
- if (c == null)
+ if (c == null) {
return null;
+ }
Method m = findImplementation(c, name, signature);
- if (m != null && !m.isAbstract())
+ if (m != null && !m.isAbstract()) {
return c;
+ }
}
} catch (ClassNotFoundException e) {
@@ -143,11 +148,13 @@ public class Lookup implements Constants2 {
JavaClass c = clazz;
while (true) {
c = c.getSuperClass();
- if (c == null)
+ if (c == null) {
return null;
+ }
Method m = findImplementation(c, name, signature);
- if (m != null && !m.isAbstract())
+ if (m != null && !m.isAbstract()) {
return XFactory.createXMethod(c, m);
+ }
}
} catch (ClassNotFoundException e) {
@@ -172,8 +179,9 @@ public class Lookup implements Constants2 {
for (JavaClass aClazz : clazz) {
Method m = findImplementation(aClazz, name, signature);
- if (m != null && !m.isAbstract())
+ if (m != null && !m.isAbstract()) {
return aClazz;
+ }
}
return null;
@@ -181,9 +189,11 @@ public class Lookup implements Constants2 {
public static Method findImplementation(JavaClass clazz, String name, String signature) {
Method[] m = clazz.getMethods();
- for (Method aM : m)
- if (aM.getName().equals(name) && aM.getSignature().equals(signature) && !aM.isPrivate() && !aM.isStatic())
+ for (Method aM : m) {
+ if (aM.getName().equals(name) && aM.getSignature().equals(signature) && !aM.isPrivate() && !aM.isStatic()) {
return aM;
+ }
+ }
return null;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/MethodAnnotation.java b/src/java/edu/umd/cs/findbugs/MethodAnnotation.java
index 1b111bf..256ba66 100644
--- a/src/java/edu/umd/cs/findbugs/MethodAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/MethodAnnotation.java
@@ -85,9 +85,9 @@ public class MethodAnnotation extends PackageMemberAnnotation {
public static final String METHOD_COMPUTED_IN = "METHOD_COMPUTED_IN";
public static final String METHOD_ALTERNATIVE_TARGET = "METHOD_ALTERNATIVE_TARGET";
-
+
public static final String SHOULD_CALL = "SHOULD_CALL";
-
+
/**
* Constructor.
*
@@ -103,9 +103,9 @@ public class MethodAnnotation extends PackageMemberAnnotation {
public MethodAnnotation(@DottedClassName String className, String methodName, String methodSig, boolean isStatic) {
super(className, DEFAULT_ROLE);
this.methodName = methodName;
- if (methodSig.indexOf(".") >= 0) {
+ if (methodSig.indexOf('.') >= 0) {
assert false : "signatures should not be dotted: " + methodSig;
- methodSig = methodSig.replace('.', '/');
+ methodSig = methodSig.replace('.', '/');
}
this.methodSig = methodSig;
this.isStatic = isStatic;
@@ -151,8 +151,9 @@ public class MethodAnnotation extends PackageMemberAnnotation {
if (!oVisitor.getStack().isTop() && oVisitor.getStack().getStackDepth() > params) {
OpcodeStack.Item item = oVisitor.getStack().getStackItem(params);
String cName = ClassName.fromFieldSignature(item.getSignature());
- if (cName != null)
+ if (cName != null) {
className = cName;
+ }
}
@@ -282,10 +283,11 @@ public class MethodAnnotation extends PackageMemberAnnotation {
public String getJavaSourceMethodName() {
- if (methodName.equals("<clinit>"))
+ if ("<clinit>".equals(methodName)) {
return "<static initializer for " + getSimpleClassName() + ">";
+ }
- if (methodName.equals("<init>")) {
+ if ("<init>".equals(methodName)) {
return getSimpleClassName();
}
return methodName;
@@ -320,48 +322,48 @@ public class MethodAnnotation extends PackageMemberAnnotation {
return DescriptorFactory.instance().getMethodDescriptor(this);
}
+ @Override
public void accept(BugAnnotationVisitor visitor) {
visitor.visitMethodAnnotation(this);
}
@Override
protected String formatPackageMember(String key, ClassAnnotation primaryClass) {
- if (key.equals(""))
+ if ("".equals(key)) {
return UGLY_METHODS ? getUglyMethod() : getFullMethod(primaryClass);
- else if (key.equals("givenClass")) {
- if (methodName.equals("<init>")) {
+ } else if ("givenClass".equals(key)) {
+ if ("<init>".equals(methodName)) {
return "new " + shorten(primaryClass.getPackageName(), className) + getSignatureInClass(primaryClass);
}
- if (className.equals(primaryClass.getClassName()))
+ if (className.equals(primaryClass.getClassName())) {
return getNameInClass(primaryClass);
- else
+ } else {
return shorten(primaryClass.getPackageName(), className) + "." + getNameInClass(primaryClass);
- } else if (key.equals("name")) {
+ }
+ } else if ("name".equals(key)) {
return methodName;
- } else if (key.equals("nameAndSignature")) {
+ } else if ("nameAndSignature".equals(key)) {
return getNameInClass(primaryClass);
- } else if (key.equals("shortMethod"))
+ } else if ("shortMethod".equals(key)) {
return className + "." + methodName + "(...)";
- else if (key.equals("hash")) {
+ } else if ("hash".equals(key)) {
String tmp = getNameInClass(false, true, true);
return className + "." + tmp;
- } else if (key.equals("returnType")) {
+ } else if ("returnType".equals(key)) {
int i = methodSig.indexOf(')');
String returnType = methodSig.substring(i + 1);
String pkgName = primaryClass == null ? "" : primaryClass.getPackageName();
SignatureConverter converter = new SignatureConverter(returnType);
return shorten(pkgName, converter.parseNext());
- } else
+ } else {
throw new IllegalArgumentException("unknown key " + key);
+ }
}
/**
* Get the "full" method name. This is a format which looks sort of like a
* method signature that would appear in Java source code.
- *
- * @param primaryClass
- * TODO
*/
public String getNameInClass(ClassAnnotation primaryClass) {
return getNameInClass(true, false, false, false);
@@ -386,40 +388,41 @@ public class MethodAnnotation extends PackageMemberAnnotation {
* @param shortenPackages
* whether to shorten package names if they are in java or in the
* same package as this method.
- * @param useJVMMethodName
- * TODO
- * @param hash
- * TODO
*/
public String getNameInClass(boolean shortenPackages, boolean useJVMMethodName, boolean hash, boolean omitMethodName) {
// Convert to "nice" representation
StringBuilder result = new StringBuilder();
if (!omitMethodName) {
- if (useJVMMethodName)
+ if (useJVMMethodName) {
result.append(getMethodName());
- else
+ } else {
result.append(getJavaSourceMethodName());
+ }
}
result.append('(');
// append args
SignatureConverter converter = new SignatureConverter(methodSig);
- if (converter.getFirst() != '(')
+ if (converter.getFirst() != '(') {
throw new IllegalStateException("bad method signature " + methodSig);
+ }
converter.skip();
boolean needsComma = false;
while (converter.getFirst() != ')') {
- if (needsComma)
- if (hash)
+ if (needsComma) {
+ if (hash) {
result.append(",");
- else
+ } else {
result.append(", ");
- if (shortenPackages)
+ }
+ }
+ if (shortenPackages) {
result.append(removePackageName(converter.parseNext()));
- else
+ } else {
result.append(converter.parseNext());
+ }
needsComma = true;
}
converter.skip();
@@ -431,24 +434,23 @@ public class MethodAnnotation extends PackageMemberAnnotation {
/**
* Get the "full" method name. This is a format which looks sort of like a
* method signature that would appear in Java source code.
- *
- * @param primaryClass
- * TODO
*/
public String getFullMethod(ClassAnnotation primaryClass) {
if (fullMethod == null) {
- if (methodName.equals("<init>"))
+ if ("<init>".equals(methodName)) {
fullMethod = "new " + stripJavaLang(className) + getSignatureInClass(primaryClass);
- else
+ } else {
fullMethod = stripJavaLang(className) + "." + getNameInClass(primaryClass);
+ }
}
return fullMethod;
}
public String stripJavaLang(@DottedClassName String className) {
- if (className.startsWith("java.lang."))
+ if (className.startsWith("java.lang.")) {
return className.substring(10);
+ }
return className;
}
@@ -463,25 +465,30 @@ public class MethodAnnotation extends PackageMemberAnnotation {
@Override
public boolean equals(Object o) {
- if (!(o instanceof MethodAnnotation))
+ if (!(o instanceof MethodAnnotation)) {
return false;
+ }
MethodAnnotation other = (MethodAnnotation) o;
return className.equals(other.className) && methodName.equals(other.methodName) && methodSig.equals(other.methodSig);
}
+ @Override
public int compareTo(BugAnnotation o) {
- if (!(o instanceof MethodAnnotation)) // BugAnnotations must be
- // Comparable with any type of
- // BugAnnotation
+ if (!(o instanceof MethodAnnotation)) {
+ // Comparable with any type of
+ // BugAnnotation
return this.getClass().getName().compareTo(o.getClass().getName());
+ }
MethodAnnotation other = (MethodAnnotation) o;
int cmp;
cmp = className.compareTo(other.className);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
cmp = methodName.compareTo(other.methodName);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return methodSig.compareTo(other.methodSig);
}
@@ -493,19 +500,23 @@ public class MethodAnnotation extends PackageMemberAnnotation {
private static final String ELEMENT_NAME = "Method";
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean addMessages, boolean isPrimary) throws IOException {
XMLAttributeList attributeList = new XMLAttributeList().addAttribute("classname", getClassName())
.addAttribute("name", getMethodName()).addAttribute("signature", getMethodSignature())
.addAttribute("isStatic", String.valueOf(isStatic()));
- if (isPrimary)
+ if (isPrimary) {
attributeList.addAttribute("primary", "true");
+ }
String role = getDescription();
- if (!role.equals(DEFAULT_ROLE))
+ if (!DEFAULT_ROLE.equals(role)) {
attributeList.addAttribute("role", role);
+ }
if (sourceLines == null && !addMessages) {
xmlOutput.openCloseTag(ELEMENT_NAME, attributeList);
@@ -527,10 +538,9 @@ public class MethodAnnotation extends PackageMemberAnnotation {
public boolean isSignificant() {
String role = getDescription();
if (METHOD_DANGEROUS_TARGET.equals(role) || METHOD_DANGEROUS_TARGET_ACTUAL_GUARANTEED_NULL.equals(role)
- || METHOD_SAFE_TARGET.equals(role) || METHOD_EQUALS_USED.equals(role) || METHOD_COMPUTED_IN.equals(role))
+ || METHOD_SAFE_TARGET.equals(role) || METHOD_EQUALS_USED.equals(role) || METHOD_COMPUTED_IN.equals(role)) {
return false;
+ }
return true;
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/MethodWarningSuppressor.java b/src/java/edu/umd/cs/findbugs/MethodWarningSuppressor.java
index 786ae87..17d3aac 100644
--- a/src/java/edu/umd/cs/findbugs/MethodWarningSuppressor.java
+++ b/src/java/edu/umd/cs/findbugs/MethodWarningSuppressor.java
@@ -12,14 +12,17 @@ public class MethodWarningSuppressor extends ClassWarningSuppressor {
@Override
public boolean match(BugInstance bugInstance) {
- if (!super.match(bugInstance))
+ if (!super.match(bugInstance)) {
return false;
+ }
MethodAnnotation bugMethod = bugInstance.getPrimaryMethod();
- if (bugMethod != null && !method.equals(bugMethod))
+ if (bugMethod != null && !method.equals(bugMethod)) {
return false;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("Suppressing " + bugInstance);
+ }
return true;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/NewResults.java b/src/java/edu/umd/cs/findbugs/NewResults.java
index 03e01ae..bb538f3 100644
--- a/src/java/edu/umd/cs/findbugs/NewResults.java
+++ b/src/java/edu/umd/cs/findbugs/NewResults.java
@@ -25,9 +25,9 @@ import org.dom4j.DocumentException;
@Deprecated
public class NewResults {
- private SortedBugCollection origCollection;
+ private final SortedBugCollection origCollection;
- private SortedBugCollection newCollection;
+ private final SortedBugCollection newCollection;
public NewResults(String origFilename, String newFilename) throws IOException, DocumentException {
this(new SortedBugCollection(), new SortedBugCollection());
@@ -72,4 +72,3 @@ public class NewResults {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/NoClassesFoundToAnalyzeException.java b/src/java/edu/umd/cs/findbugs/NoClassesFoundToAnalyzeException.java
index 44d59ee..0464c49 100644
--- a/src/java/edu/umd/cs/findbugs/NoClassesFoundToAnalyzeException.java
+++ b/src/java/edu/umd/cs/findbugs/NoClassesFoundToAnalyzeException.java
@@ -30,7 +30,7 @@ import edu.umd.cs.findbugs.classfile.IClassPath;
* To be consistent with FindBugs 1.3 this exception is an {@link IOException}
* and replicates the message used in that release (because I suspect some tools
* looked for that text pattern to come out at the console).
- *
+ *
* @author Tim Halloran
*/
public class NoClassesFoundToAnalyzeException extends IOException {
@@ -39,7 +39,7 @@ public class NoClassesFoundToAnalyzeException extends IOException {
/**
* Gets the classpath this exception is about.
- *
+ *
* @return Gets the non-null classpath this exception is about.
*/
public IClassPath getClassPath() {
@@ -48,14 +48,15 @@ public class NoClassesFoundToAnalyzeException extends IOException {
/**
* Constructs an {@code NoClassesFoundToAnalyze} on the passed classpath.
- *
+ *
* @param classPath
* the classpath used
*/
public NoClassesFoundToAnalyzeException(final IClassPath classPath) {
super("No classes found to analyze in " + classPath);
- if (classPath == null)
+ if (classPath == null) {
throw new IllegalArgumentException("classpath must be non-null");
+ }
f_classPath = classPath;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/NoOpFindBugsProgress.java b/src/java/edu/umd/cs/findbugs/NoOpFindBugsProgress.java
index 42c2737..9ea060c 100644
--- a/src/java/edu/umd/cs/findbugs/NoOpFindBugsProgress.java
+++ b/src/java/edu/umd/cs/findbugs/NoOpFindBugsProgress.java
@@ -4,25 +4,32 @@ package edu.umd.cs.findbugs;
* @author David Hovemeyer
*/
public class NoOpFindBugsProgress implements FindBugsProgress {
+ @Override
public void reportNumberOfArchives(int numArchives) {
}
+ @Override
public void finishArchive() {
}
+ @Override
public void startAnalysis(int numClasses) {
}
+ @Override
public void finishClass() {
}
+ @Override
public void finishPerClassAnalysis() {
}
+ @Override
public void predictPassCount(int[] classesPerPass) {
// noop
}
+ @Override
public void startArchive(String name) {
// noop
}
diff --git a/src/java/edu/umd/cs/findbugs/NonReportingDetector.java b/src/java/edu/umd/cs/findbugs/NonReportingDetector.java
index 5844c45..127c780 100644
--- a/src/java/edu/umd/cs/findbugs/NonReportingDetector.java
+++ b/src/java/edu/umd/cs/findbugs/NonReportingDetector.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs;
/**
* A Detector which does not report warnings.
- *
+ *
* @author David Hovemeyer
*/
public interface NonReportingDetector extends FirstPassDetector {
diff --git a/src/java/edu/umd/cs/findbugs/Obfuscate.java b/src/java/edu/umd/cs/findbugs/Obfuscate.java
index 338d9c9..c18d973 100644
--- a/src/java/edu/umd/cs/findbugs/Obfuscate.java
+++ b/src/java/edu/umd/cs/findbugs/Obfuscate.java
@@ -56,8 +56,9 @@ public class Obfuscate {
}
public static String hashClass(@DottedClassName String className) {
- if (className.startsWith("java"))
+ if (className.startsWith("java")) {
return className;
+ }
return "obfuscated.H" + hashData(className);
}
@@ -76,12 +77,14 @@ public class Obfuscate {
case 'J':
case 'D':
case 'F':
- if (signature.length() == 1)
+ if (signature.length() == 1) {
return signature;
+ }
throw new IllegalArgumentException("bad signature: " + signature);
case 'L':
- if (!signature.endsWith(";"))
+ if (!signature.endsWith(";")) {
throw new IllegalArgumentException("bad signature: " + signature);
+ }
return hashFieldSignature(signature);
default:
throw new IllegalArgumentException("bad signature: " + signature);
@@ -90,11 +93,12 @@ public class Obfuscate {
public static String hashFieldSignature(String signature) {
signature = signature.substring(1, signature.length() - 1);
- if (!signature.startsWith("java"))
- signature = "obfuscated/H" + hashData(signature);
+ if (!signature.startsWith("java")) {
+ signature = "obfuscated/H" + hashData(signature);
+ }
return "L" + signature + ";";
}
-
+
public static String hashMethodSignature(String signature) {
SignatureParser parser = new SignatureParser(signature);
StringBuilder buf = new StringBuilder("(");
@@ -110,16 +114,17 @@ public class Obfuscate {
static MethodAnnotation obfuscate(MethodAnnotation m) {
String className = m.getClassName();
- if (className.startsWith("java"))
+ if (className.startsWith("java")) {
return m;
+ }
String methodName = m.getMethodName();
String methodSignature = m.getMethodSignature();
- if (methodName.equals("hashCode") && methodSignature.equals("()I") || methodName.equals("equals")
- && methodSignature.equals("(Ljava/lang/Object;)Z") || methodName.equals("compareTo")
- && methodSignature.equals("(Ljava/lang/Object;)I") || methodName.equals("<init>")
- || methodName.equals("<clinit>")) {
+ if ("hashCode".equals(methodName) && "()I".equals(methodSignature) || "equals".equals(methodName)
+ && "(Ljava/lang/Object;)Z".equals(methodSignature) || "compareTo".equals(methodName)
+ && "(Ljava/lang/Object;)I".equals(methodSignature) || "<init>".equals(methodName)
+ || "<clinit>".equals(methodName)) {
// don't need to obfuscate method name
} else {
methodName = hashData(methodName);
@@ -138,7 +143,7 @@ public class Obfuscate {
return result;
}
-
+
static ClassAnnotation obfuscate(ClassAnnotation m) {
ClassAnnotation result = new ClassAnnotation(hashClass(m.getClassName()));
@@ -187,48 +192,57 @@ public class Obfuscate {
final BugInstance result = new BugInstance(b.getType(), b.getPriority());
BugAnnotationVisitor visitor = new BugAnnotationVisitor() {
+ @Override
public void visitTypeAnnotation(TypeAnnotation typeAnnotation) {
result.add(obfuscate(typeAnnotation));
}
+ @Override
public void visitStringAnnotation(StringAnnotation stringAnnotation) {
result.add(obfuscate(stringAnnotation));
}
+ @Override
public void visitSourceLineAnnotation(SourceLineAnnotation sourceLineAnnotation) {
result.add(obfuscate(sourceLineAnnotation));
}
+ @Override
public void visitMethodAnnotation(MethodAnnotation methodAnnotation) {
result.add(obfuscate(methodAnnotation));
}
+ @Override
public void visitLocalVariableAnnotation(LocalVariableAnnotation fieldAnnotation) {
result.add(obfuscate(fieldAnnotation));
}
+ @Override
public void visitIntAnnotation(IntAnnotation fieldAnnotation) {
result.add(obfuscate(fieldAnnotation));
}
+ @Override
public void visitFieldAnnotation(FieldAnnotation fieldAnnotation) {
result.add(obfuscate(fieldAnnotation));
}
+ @Override
public void visitClassAnnotation(ClassAnnotation classAnnotation) {
result.add(obfuscate(classAnnotation));
}
};
- for (BugAnnotation a : b.getAnnotations())
+ for (BugAnnotation a : b.getAnnotations()) {
a.accept(visitor);
+ }
result.setOldInstanceHash(hashData(b.getInstanceHash()));
result.setHistory(b);
return result;
diff --git a/src/java/edu/umd/cs/findbugs/OpcodeStack.java b/src/java/edu/umd/cs/findbugs/OpcodeStack.java
index 724fef2..6564b6c 100644
--- a/src/java/edu/umd/cs/findbugs/OpcodeStack.java
+++ b/src/java/edu/umd/cs/findbugs/OpcodeStack.java
@@ -33,6 +33,8 @@ import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.annotation.meta.TypeQualifier;
import org.apache.bcel.Repository;
@@ -59,6 +61,7 @@ import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.AnalysisFeatures;
import edu.umd.cs.findbugs.ba.ClassMember;
import edu.umd.cs.findbugs.ba.FieldSummary;
+import edu.umd.cs.findbugs.ba.SignatureParser;
import edu.umd.cs.findbugs.ba.XFactory;
import edu.umd.cs.findbugs.ba.XField;
import edu.umd.cs.findbugs.ba.XMethod;
@@ -71,6 +74,7 @@ import edu.umd.cs.findbugs.classfile.IAnalysisCache;
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
import edu.umd.cs.findbugs.classfile.analysis.MethodInfo;
import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
+import edu.umd.cs.findbugs.internalAnnotations.StaticConstant;
import edu.umd.cs.findbugs.util.ClassName;
import edu.umd.cs.findbugs.util.Util;
import edu.umd.cs.findbugs.visitclass.Constants2;
@@ -114,15 +118,15 @@ public class OpcodeStack implements Constants2 {
public @interface CustomUserValue {
}
- /**
- *
- */
private static final String JAVA_UTIL_ARRAYS_ARRAY_LIST = "Ljava/util/Arrays$ArrayList;";
private static final boolean DEBUG = SystemProperties.getBoolean("ocstack.debug");
private static final boolean DEBUG2 = DEBUG;
+ @StaticConstant
+ static final HashMap<String, String> boxedTypes = new HashMap<String, String>();
+
private List<Item> stack;
private List<Item> lvValues;
@@ -142,11 +146,41 @@ public class OpcodeStack implements Constants2 {
int pc;
}
- private boolean seenTransferOfControl = false;
+ private boolean seenTransferOfControl;
private final boolean useIterativeAnalysis = AnalysisContext.currentAnalysisContext().getBoolProperty(
AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS);
+ boolean encountedTop;
+
+ boolean backwardsBranch;
+
+ BitSet exceptionHandlers = new BitSet();
+
+ private boolean jumpInfoChangedByBackwardsBranch;
+
+ private boolean jumpInfoChangedByNewTarget;
+
+ private Map<Integer, List<Item>> jumpEntries = new HashMap<Integer, List<Item>>();
+
+ private Map<Integer, List<Item>> jumpStackEntries = new HashMap<Integer, List<Item>>();
+
+ private BitSet jumpEntryLocations = new BitSet();
+
+ int convertJumpToOneZeroState = 0;
+
+ int convertJumpToZeroOneState = 0;
+
+ int registerTestedFoundToBeNonnegative = -1;
+
+ int zeroOneComing = -1;
+
+ boolean oneMeansNull;
+
+ boolean needToMerge = true;
+
+ private boolean reachOnlyByBranch;
+
public static class Item {
@Documented
@@ -230,7 +264,7 @@ public class OpcodeStack implements Constants2 {
public static final @SpecialKind
int SERVLET_OUTPUT = 23;
-
+
public static final @SpecialKind
int TYPE_ONLY = 24;
@@ -271,9 +305,10 @@ public class OpcodeStack implements Constants2 {
private int registerNumber = -1;
- private Object userValue = null;
+ @Nullable
+ private Object userValue;
- private HttpParameterInjection injection = null;
+ private HttpParameterInjection injection;
private int fieldLoadedFromRegister = -1;
@@ -284,8 +319,9 @@ public class OpcodeStack implements Constants2 {
}
public int getSize() {
- if (signature.equals("J") || signature.equals("D"))
+ if ("J".equals(signature) || "D".equals(signature)) {
return 2;
+ }
return 1;
}
@@ -304,14 +340,17 @@ public class OpcodeStack implements Constants2 {
@Override
public int hashCode() {
int r = 42 + specialKind;
- if (signature != null)
+ if (signature != null) {
r += signature.hashCode();
+ }
r *= 31;
- if (constValue != null)
+ if (constValue != null) {
r += constValue.hashCode();
+ }
r *= 31;
- if (source != null)
+ if (source != null) {
r += source.hashCode();
+ }
r *= 31;
r += flags;
r *= 31;
@@ -325,8 +364,9 @@ public class OpcodeStack implements Constants2 {
}
@Override
public boolean equals(Object o) {
- if (!(o instanceof Item))
+ if (!(o instanceof Item)) {
return false;
+ }
Item that = (Item) o;
return Util.nullSafeEquals(this.signature, that.signature) && Util.nullSafeEquals(this.constValue, that.constValue)
@@ -337,6 +377,12 @@ public class OpcodeStack implements Constants2 {
}
+
+ public boolean sameValue(OpcodeStack.Item that) {
+
+ return this.equals(that) && (this.registerNumber != -1 && this.registerNumber == that.registerNumber || this.fieldLoadedFromRegister != -1);
+ }
+
@Override
public String toString() {
StringBuilder buf = new StringBuilder("< ");
@@ -428,8 +474,9 @@ public class OpcodeStack implements Constants2 {
}
if (source instanceof XField) {
buf.append(", ");
- if (fieldLoadedFromRegister != -1 && fieldLoadedFromRegister != Integer.MAX_VALUE)
+ if (fieldLoadedFromRegister != -1 && fieldLoadedFromRegister != Integer.MAX_VALUE) {
buf.append(fieldLoadedFromRegister).append(':');
+ }
buf.append(source);
}
if (source instanceof XMethod) {
@@ -447,8 +494,9 @@ public class OpcodeStack implements Constants2 {
buf.append(", r");
buf.append(registerNumber);
}
- if (isCouldBeZero() && !isZero())
+ if (isCouldBeZero() && !isZero()) {
buf.append(", cbz");
+ }
if (userValue != null) {
buf.append(", uv: ");
buf.append(userValue.toString());
@@ -459,43 +507,54 @@ public class OpcodeStack implements Constants2 {
}
public static Item merge(Item i1, Item i2) {
- if (i1 == null)
+ if (i1 == null) {
return i2;
- if (i2 == null)
+ }
+ if (i2 == null) {
return i1;
- if (i1.equals(i2))
+ }
+ if (i1.equals(i2)) {
return i1;
+ }
Item m = new Item();
- if (i1.getSpecialKind() == TYPE_ONLY && i2.getSpecialKind() != TYPE_ONLY)
+ if (i1.getSpecialKind() == TYPE_ONLY && i2.getSpecialKind() != TYPE_ONLY) {
return i2;
- else if (i2.getSpecialKind() == TYPE_ONLY && i1.getSpecialKind() != TYPE_ONLY)
+ } else if (i2.getSpecialKind() == TYPE_ONLY && i1.getSpecialKind() != TYPE_ONLY) {
return i1;
+ }
m.flags = i1.flags & i2.flags;
m.setCouldBeZero(i1.isCouldBeZero() || i2.isCouldBeZero());
- if (i1.pc == i2.pc)
+ if (i1.pc == i2.pc) {
m.pc = i1.pc;
- if (Util.nullSafeEquals(i1.signature, i2.signature))
+ }
+ if (Util.nullSafeEquals(i1.signature, i2.signature)) {
m.signature = i1.signature;
- else if (i1.isNull())
+ } else if (i1.isNull()) {
m.signature = i2.signature;
- else if (i2.isNull())
+ } else if (i2.isNull()) {
m.signature = i1.signature;
- if (Util.nullSafeEquals(i1.constValue, i2.constValue))
+ }
+ if (Util.nullSafeEquals(i1.constValue, i2.constValue)) {
m.constValue = i1.constValue;
+ }
if (Util.nullSafeEquals(i1.source, i2.source)) {
m.source = i1.source;
- } else if ("".equals(i1.constValue))
+ } else if ("".equals(i1.constValue)) {
m.source = i2.source;
- else if ("".equals(i2.constValue))
+ } else if ("".equals(i2.constValue)) {
m.source = i1.source;
+ }
- if (Util.nullSafeEquals(i1.userValue, i2.userValue))
+ if (Util.nullSafeEquals(i1.userValue, i2.userValue)) {
m.userValue = i1.userValue;
+ }
- if (i1.registerNumber == i2.registerNumber)
+ if (i1.registerNumber == i2.registerNumber) {
m.registerNumber = i1.registerNumber;
- if (i1.fieldLoadedFromRegister == i2.fieldLoadedFromRegister)
+ }
+ if (i1.fieldLoadedFromRegister == i2.fieldLoadedFromRegister) {
m.fieldLoadedFromRegister = i1.fieldLoadedFromRegister;
+ }
if (i1.specialKind == SERVLET_REQUEST_TAINTED) {
m.specialKind = SERVLET_REQUEST_TAINTED;
@@ -503,14 +562,16 @@ public class OpcodeStack implements Constants2 {
} else if (i2.specialKind == SERVLET_REQUEST_TAINTED) {
m.specialKind = SERVLET_REQUEST_TAINTED;
m.injection = i2.injection;
- } else if (i1.specialKind == i2.specialKind)
+ } else if (i1.specialKind == i2.specialKind) {
m.specialKind = i1.specialKind;
- else if (i1.specialKind == NASTY_FLOAT_MATH || i2.specialKind == NASTY_FLOAT_MATH)
+ } else if (i1.specialKind == NASTY_FLOAT_MATH || i2.specialKind == NASTY_FLOAT_MATH) {
m.specialKind = NASTY_FLOAT_MATH;
- else if (i1.specialKind == FLOAT_MATH || i2.specialKind == FLOAT_MATH)
+ } else if (i1.specialKind == FLOAT_MATH || i2.specialKind == FLOAT_MATH) {
m.specialKind = FLOAT_MATH;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("Merge " + i1 + " and " + i2 + " gives " + m);
+ }
return m;
}
@@ -518,13 +579,13 @@ public class OpcodeStack implements Constants2 {
this(signature, Integer.valueOf(constValue));
}
-
+
public static Item initialArgument(String signature, int reg) {
Item it = new Item(signature);
it.setInitialParameter(true);
it.registerNumber = reg;
return it;
-
+
}
public Item(String signature) {
this(signature, UNKNOWN);
@@ -547,30 +608,32 @@ public class OpcodeStack implements Constants2 {
this.pc = it.pc;
}
-
-
+
+
public Item(Item it, String signature) {
this(it);
this.signature = DescriptorFactory.canonicalizeString(signature);
if (constValue instanceof Number) {
Number constantNumericValue = (Number) constValue;
- if (signature.equals("B"))
+ if ("B".equals(signature)) {
this.constValue = constantNumericValue.byteValue();
- else if (signature.equals("S"))
+ } else if ("S".equals(signature)) {
this.constValue = constantNumericValue.shortValue();
- else if (signature.equals("C"))
+ } else if ("C".equals(signature)) {
this.constValue = (char) constantNumericValue.intValue();
- else if (signature.equals("I"))
+ } else if ("I".equals(signature)) {
this.constValue = constantNumericValue.intValue();
- else if (signature.equals("D"))
+ } else if ("D".equals(signature)) {
this.constValue = constantNumericValue.doubleValue();
- else if (signature.equals("F"))
+ } else if ("F".equals(signature)) {
this.constValue = constantNumericValue.floatValue();
+ }
}
char s = signature.charAt(0);
- if (s != 'L' && s != '[')
+ if (s != 'L' && s != '[') {
this.source = null;
+ }
setSpecialKindFromSignature();
}
@@ -583,15 +646,17 @@ public class OpcodeStack implements Constants2 {
public Item(String signature, FieldAnnotation f) {
this.signature = DescriptorFactory.canonicalizeString(signature);
setSpecialKindFromSignature();
- if (f != null)
+ if (f != null) {
source = XFactory.createXField(f);
+ }
fieldLoadedFromRegister = -1;
}
public Item(String signature, FieldAnnotation f, int fieldLoadedFromRegister) {
this.signature = DescriptorFactory.canonicalizeString(signature);
- if (f != null)
+ if (f != null) {
source = XFactory.createXField(f);
+ }
this.fieldLoadedFromRegister = fieldLoadedFromRegister;
}
@@ -601,8 +666,6 @@ public class OpcodeStack implements Constants2 {
* If Integer.MAX value, the value was loaded from a static field
* If -1, we don't know or don't have the register containing the object that
* the field was loaded from.
- * @return
- *
*/
public int getFieldLoadedFromRegister() {
return fieldLoadedFromRegister;
@@ -616,18 +679,22 @@ public class OpcodeStack implements Constants2 {
public @CheckForNull
String getHttpParameterName() {
- if (!isServletParameterTainted())
+ if (!isServletParameterTainted()) {
throw new IllegalStateException();
- if (injection == null)
+ }
+ if (injection == null) {
return null;
+ }
return injection.parameterName;
}
public int getInjectionPC() {
- if (!isServletParameterTainted())
+ if (!isServletParameterTainted()) {
throw new IllegalStateException();
- if (injection == null)
+ }
+ if (injection == null) {
return -1;
+ }
return injection.pc;
}
@@ -637,33 +704,42 @@ public class OpcodeStack implements Constants2 {
constValue = constantValue;
if (constantValue instanceof Integer) {
int value = ((Integer) constantValue).intValue();
- if (value != 0 && (value & 0xff) == 0)
+ if (value != 0 && (value & 0xff) == 0) {
specialKind = LOW_8_BITS_CLEAR;
- if (value == 0)
+ }
+ if (value == 0) {
setCouldBeZero(true);
+ }
} else if (constantValue instanceof Long) {
long value = ((Long) constantValue).longValue();
- if (value != 0 && (value & 0xff) == 0)
+ if (value != 0 && (value & 0xff) == 0) {
specialKind = LOW_8_BITS_CLEAR;
- if (value == 0)
+ }
+ if (value == 0) {
setCouldBeZero(true);
+ }
}
}
private void setSpecialKindFromSignature() {
- if (false && specialKind != NOT_SPECIAL)
+ /*
+ if (false && specialKind != NOT_SPECIAL) {
return;
- if (signature.equals("B"))
+ }
+ */
+ if ("B".equals(signature)) {
specialKind = SIGNED_BYTE;
- else if (signature.equals("C"))
+ } else if ("C".equals(signature)) {
specialKind = NON_NEGATIVE;
+ }
}
public void setCouldBeNegative() {
- if (specialKind == NON_NEGATIVE)
+ if (specialKind == NON_NEGATIVE) {
specialKind = NOT_SPECIAL;
+ }
}
public Item() {
@@ -684,13 +760,15 @@ public class OpcodeStack implements Constants2 {
JavaClass getJavaClass() throws ClassNotFoundException {
String baseSig;
- if (isPrimitive() || isArray())
+ if (isPrimitive() || isArray()) {
return null;
+ }
baseSig = signature;
- if (baseSig.length() == 0)
+ if (baseSig.length() == 0) {
return null;
+ }
baseSig = baseSig.substring(1, baseSig.length() - 1);
baseSig = baseSig.replace('/', '.');
return Repository.lookupClass(baseSig);
@@ -702,14 +780,15 @@ public class OpcodeStack implements Constants2 {
@Deprecated
public String getElementSignature() {
- if (!isArray())
+ if (!isArray()) {
return signature;
- else {
+ } else {
int pos = 0;
int len = signature.length();
while (pos < len) {
- if (signature.charAt(pos) != '[')
+ if (signature.charAt(pos) != '[') {
break;
+ }
pos++;
}
return signature.substring(pos);
@@ -717,8 +796,9 @@ public class OpcodeStack implements Constants2 {
}
public boolean isNonNegative() {
- if (specialKind == NON_NEGATIVE)
+ if (specialKind == NON_NEGATIVE) {
return true;
+ }
if (constValue instanceof Number) {
double value = ((Number) constValue).doubleValue();
return value >= 0;
@@ -742,6 +822,7 @@ public class OpcodeStack implements Constants2 {
* Returns a constant value for this Item, if known. NOTE: if the value
* is a constant Class object, the constant value returned is the name
* of the class.
+ * if the value is an array of known length, the constant value returned is its length (Integer)
*/
public Object getConstant() {
return constValue;
@@ -754,8 +835,9 @@ public class OpcodeStack implements Constants2 {
}
public XField getXField() {
- if (source instanceof XField)
+ if (source instanceof XField) {
return (XField) source;
+ }
return null;
}
@@ -789,12 +871,14 @@ public class OpcodeStack implements Constants2 {
}
/**
- * attaches a detector specified value to this item
+ * <p>attaches a detector specified value to this item</p>
+ * <p>to use this method, detector should be annotated with {@code CustomUserValue}.</p>
*
* @param value
* the custom value to set
+ * @see OpcodeStack.CustomUserValue
*/
- public void setUserValue(Object value) {
+ public void setUserValue(@Nullable Object value) {
userValue = value;
}
@@ -805,8 +889,9 @@ public class OpcodeStack implements Constants2 {
*/
public @CheckForNull
XMethod getReturnValueOf() {
- if (source instanceof XMethod)
+ if (source instanceof XMethod) {
return (XMethod) source;
+ }
return null;
}
@@ -824,6 +909,7 @@ public class OpcodeStack implements Constants2 {
*
* @return the custom value
*/
+ @Nullable
public Object getUserValue() {
return userValue;
}
@@ -841,22 +927,24 @@ public class OpcodeStack implements Constants2 {
public boolean isServletWriter() {
- if (getSpecialKind() == Item.SERVLET_OUTPUT)
+ if (getSpecialKind() == Item.SERVLET_OUTPUT) {
return true;
- if (getSignature().equals("Ljavax/servlet/ServletOutputStream;"))
+ }
+ if ("Ljavax/servlet/ServletOutputStream;".equals(getSignature())) {
return true;
+ }
XMethod writingToSource = getReturnValueOf();
- return writingToSource != null && writingToSource.getClassName().equals("javax.servlet.http.HttpServletResponse")
- && (writingToSource.getName().equals("getWriter") || writingToSource.getName().equals("getOutputStream"));
+ return writingToSource != null && "javax.servlet.http.HttpServletResponse".equals(writingToSource.getClassName())
+ && ("getWriter".equals(writingToSource.getName()) || "getOutputStream".equals(writingToSource.getName()));
}
public boolean valueCouldBeNegative() {
return !isNonNegative()
&& (getSpecialKind() == Item.RANDOM_INT || getSpecialKind() == Item.SIGNED_BYTE
- || getSpecialKind() == Item.HASHCODE_INT || getSpecialKind() == Item.RANDOM_INT_REMAINDER
- || getSpecialKind() == Item.HASHCODE_INT_REMAINDER || getSpecialKind() == Item.MATH_ABS_OF_RANDOM || getSpecialKind() == Item.MATH_ABS_OF_HASHCODE);
+ || getSpecialKind() == Item.HASHCODE_INT || getSpecialKind() == Item.RANDOM_INT_REMAINDER
+ || getSpecialKind() == Item.HASHCODE_INT_REMAINDER || getSpecialKind() == Item.MATH_ABS_OF_RANDOM || getSpecialKind() == Item.MATH_ABS_OF_HASHCODE);
}
@@ -924,9 +1012,6 @@ public class OpcodeStack implements Constants2 {
|| isZero();
}
- /**
- * @return
- */
private boolean isZero() {
return constValue != null && constValue.equals(0);
}
@@ -940,10 +1025,11 @@ public class OpcodeStack implements Constants2 {
}
private void setFlag(boolean value, int flagBit) {
- if (value)
+ if (value) {
flags |= flagBit;
- else
+ } else {
flags &= ~flagBit;
+ }
}
/**
@@ -958,8 +1044,9 @@ public class OpcodeStack implements Constants2 {
*/
public void clearNewlyAllocated() {
if (specialKind == NEWLY_ALLOCATED) {
- if (signature.startsWith("Ljava/lang/StringB"))
+ if (signature.startsWith("Ljava/lang/StringB")) {
constValue = null;
+ }
specialKind = NOT_SPECIAL;
}
}
@@ -968,27 +1055,26 @@ public class OpcodeStack implements Constants2 {
return specialKind == NEWLY_ALLOCATED;
}
- /**
- * @param i
- * @return
- */
public boolean hasConstantValue(int value) {
- if (constValue instanceof Number)
+ if (constValue instanceof Number) {
return ((Number) constValue).intValue() == value;
+ }
return false;
}
public boolean hasConstantValue(long value) {
- if (constValue instanceof Number)
+ if (constValue instanceof Number) {
return ((Number) constValue).longValue() == value;
+ }
return false;
}
}
@Override
public String toString() {
- if (isTop())
+ if (isTop()) {
return "TOP";
+ }
return stack.toString() + "::" + lvValues.toString();
}
@@ -1003,39 +1089,40 @@ public class OpcodeStack implements Constants2 {
}
- boolean needToMerge = true;
-
- private boolean reachOnlyByBranch = false;
-
public static String getExceptionSig(DismantleBytecode dbc, CodeException e) {
- if (e.getCatchType() == 0)
+ if (e.getCatchType() == 0) {
return "Ljava/lang/Throwable;";
+ }
Constant c = dbc.getConstantPool().getConstant(e.getCatchType());
- if (c instanceof ConstantClass)
+ if (c instanceof ConstantClass) {
return "L" + ((ConstantClass) c).getBytes(dbc.getConstantPool()) + ";";
+ }
return "Ljava/lang/Throwable;";
}
public void mergeJumps(DismantleBytecode dbc) {
- if (!needToMerge)
+ if (!needToMerge) {
return;
+ }
needToMerge = false;
if (dbc.getPC() == zeroOneComing) {
pop();
top = false;
OpcodeStack.Item item = new Item("I");
- if (oneMeansNull)
+ if (oneMeansNull) {
item.setSpecialKind(Item.NONZERO_MEANS_NULL);
- else
+ } else {
item.setSpecialKind(Item.ZERO_MEANS_NULL);
+ }
item.setPC(dbc.getPC() - 8);
item.setCouldBeZero(true);
push(item);
zeroOneComing = -1;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Updated to " + this);
+ }
return;
}
@@ -1050,8 +1137,9 @@ public class OpcodeStack implements Constants2 {
}
List<Item> jumpEntry = null;
- if (jumpEntryLocations.get(dbc.getPC()))
+ if (jumpEntryLocations.get(dbc.getPC())) {
jumpEntry = jumpEntries.get(Integer.valueOf(dbc.getPC()));
+ }
boolean wasReachOnlyByBranch = isReachOnlyByBranch();
if (jumpEntry != null) {
setReachOnlyByBranch(false);
@@ -1060,24 +1148,27 @@ public class OpcodeStack implements Constants2 {
if (DEBUG2) {
if (wasReachOnlyByBranch) {
System.out.println("Reached by branch at " + dbc.getPC() + " with " + jumpEntry);
- if (jumpStackEntry != null)
- System.out.println(" and stack " + jumpStackEntry);
+ if (jumpStackEntry != null) {
+ System.out.println(" and stack " + jumpStackEntry);
+ }
} else if (!jumpEntry.equals(lvValues)
- || jumpStackEntry != null && !jumpStackEntry.equals(stack)) {
+ || jumpStackEntry != null && !jumpStackEntry.equals(stack)) {
System.out.println("Merging at " + dbc.getPC() + " with " + jumpEntry);
- if (jumpStackEntry != null)
- System.out.println(" and stack " + jumpStackEntry);
+ if (jumpStackEntry != null) {
+ System.out.println(" and stack " + jumpStackEntry);
+ }
}
}
if (isTop()) {
lvValues = new ArrayList<Item>(jumpEntry);
- if (jumpStackEntry != null)
+ if (jumpStackEntry != null) {
stack = new ArrayList<Item>(jumpStackEntry);
- else
+ } else {
stack.clear();
+ }
setTop(false);
return;
}
@@ -1085,54 +1176,65 @@ public class OpcodeStack implements Constants2 {
setTop(false);
lvValues = new ArrayList<Item>(jumpEntry);
if (!stackUpdated) {
- if (jumpStackEntry != null)
+ if (jumpStackEntry != null) {
stack = new ArrayList<Item>(jumpStackEntry);
- else
+ } else {
stack.clear();
+ }
}
} else {
setTop(false);
mergeLists(lvValues, jumpEntry, false);
- if (!stackUpdated && jumpStackEntry != null)
+ if (!stackUpdated && jumpStackEntry != null) {
mergeLists(stack, jumpStackEntry, false);
+ }
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" merged lvValues " + lvValues);
+ }
} else if (isReachOnlyByBranch() && !stackUpdated) {
stack.clear();
+ Item item = null;
for (CodeException e : dbc.getCode().getExceptionTable()) {
if (e.getHandlerPC() == dbc.getPC()) {
- push(new Item(getExceptionSig(dbc, e)));
- setReachOnlyByBranch(false);
- setTop(false);
- return;
+ Item newItem = new Item(getExceptionSig(dbc, e));
+ if (item == null) {
+ item = newItem;
+ } else {
+ item = Item.merge(item, newItem);
+ }
+
}
}
- setTop(true);
-
-
- }
- }
+ if (item != null) {
+ push(item);
+ setReachOnlyByBranch(false);
+ setTop(false);
+ } else {
- int convertJumpToOneZeroState = 0;
+ setTop(true);
+ }
- int convertJumpToZeroOneState = 0;
- int registerTestedFoundToBeNonnegative = -1;
+ }
+
+ }
private void setLastUpdate(int reg, int pc) {
- while (lastUpdate.size() <= reg)
+ while (lastUpdate.size() <= reg) {
lastUpdate.add(Integer.valueOf(0));
+ }
lastUpdate.set(reg, Integer.valueOf(pc));
}
public int getLastUpdate(int reg) {
- if (lastUpdate.size() <= reg)
+ if (lastUpdate.size() <= reg) {
return 0;
+ }
return lastUpdate.get(reg).intValue();
}
@@ -1140,10 +1242,6 @@ public class OpcodeStack implements Constants2 {
return lastUpdate.size();
}
- int zeroOneComing = -1;
-
- boolean oneMeansNull;
-
public void sawOpcode(DismantleBytecode dbc, int seen) {
int register;
String signature;
@@ -1152,8 +1250,9 @@ public class OpcodeStack implements Constants2 {
// System.out.printf("%3d %12s%s%n", dbc.getPC(), OPCODE_NAMES[seen],
// this);
- if (dbc.isRegisterStore())
+ if (dbc.isRegisterStore()) {
setLastUpdate(dbc.getRegisterOperand(), dbc.getPC());
+ }
precomputation(dbc);
needToMerge = true;
@@ -1176,15 +1275,16 @@ public class OpcodeStack implements Constants2 {
&& (prevOpcode2 == IFNULL || prevOpcode2 == IFNONNULL)
&& (nextOpcode == ICONST_0 || nextOpcode == ICONST_1) && prevOpcode1 != nextOpcode) {
oneMeansNull = prevOpcode1 == ICONST_0;
- if (prevOpcode2 != IFNULL)
+ if (prevOpcode2 != IFNULL) {
oneMeansNull = !oneMeansNull;
+ }
zeroOneComing = nextPC + 1;
convertJumpToOneZeroState = convertJumpToZeroOneState = 0;
}
} catch (ArrayIndexOutOfBoundsException e) {
throw e; // throw new
- // ArrayIndexOutOfBoundsException(nextPC + " "
- // + dbc.getMaxPC());
+ // ArrayIndexOutOfBoundsException(nextPC + " "
+ // + dbc.getMaxPC());
}
}
}
@@ -1194,16 +1294,18 @@ public class OpcodeStack implements Constants2 {
convertJumpToOneZeroState = 1;
break;
case GOTO:
- if (convertJumpToOneZeroState == 1 && dbc.getBranchOffset() == 4)
+ if (convertJumpToOneZeroState == 1 && dbc.getBranchOffset() == 4) {
convertJumpToOneZeroState = 2;
- else
+ } else {
convertJumpToOneZeroState = 0;
+ }
break;
case ICONST_0:
- if (convertJumpToOneZeroState == 2)
+ if (convertJumpToOneZeroState == 2) {
convertJumpToOneZeroState = 3;
- else
+ } else {
convertJumpToOneZeroState = 0;
+ }
break;
default:
convertJumpToOneZeroState = 0;
@@ -1214,16 +1316,18 @@ public class OpcodeStack implements Constants2 {
convertJumpToZeroOneState = 1;
break;
case GOTO:
- if (convertJumpToZeroOneState == 1 && dbc.getBranchOffset() == 4)
+ if (convertJumpToZeroOneState == 1 && dbc.getBranchOffset() == 4) {
convertJumpToZeroOneState = 2;
- else
+ } else {
convertJumpToZeroOneState = 0;
+ }
break;
case ICONST_1:
- if (convertJumpToZeroOneState == 2)
+ if (convertJumpToZeroOneState == 2) {
convertJumpToZeroOneState = 3;
- else
+ } else {
convertJumpToZeroOneState = 0;
+ }
break;
default:
convertJumpToZeroOneState = 0;
@@ -1301,7 +1405,7 @@ public class OpcodeStack implements Constants2 {
}
FieldAnnotation field = FieldAnnotation.fromReferencedField(dbc);
Item i = new Item(dbc.getSigConstantOperand(), field, Integer.MAX_VALUE);
- if (field.getFieldName().equals("separator") && field.getClassName().equals("java.io.File")) {
+ if ("separator".equals(field.getFieldName()) && "java.io.File".equals(field.getClassName())) {
i.setSpecialKind(Item.FILE_SEPARATOR_STRING);
}
i.setPC(dbc.getPC());
@@ -1354,12 +1458,16 @@ public class OpcodeStack implements Constants2 {
// reset all other such values on the opcode stack
if (topItem.valueCouldBeNegative() && (seen == IFLT || seen == IFLE || seen == IFGT || seen == IFGE)) {
int specialKind = topItem.getSpecialKind();
- for (Item item : stack)
- if (item != null && item.getSpecialKind() == specialKind)
+ for (Item item : stack) {
+ if (item != null && item.getSpecialKind() == specialKind) {
item.setSpecialKind(Item.NOT_SPECIAL);
- for (Item item : lvValues)
- if (item != null && item.getSpecialKind() == specialKind)
+ }
+ }
+ for (Item item : lvValues) {
+ if (item != null && item.getSpecialKind() == specialKind) {
item.setSpecialKind(Item.NOT_SPECIAL);
+ }
+ }
}
}
@@ -1374,8 +1482,9 @@ public class OpcodeStack implements Constants2 {
pop();
addJumpValue(dbc.getPC(), dbc.getBranchTarget());
int pc = dbc.getBranchTarget() - dbc.getBranchOffset();
- for (int offset : dbc.getSwitchOffsets())
+ for (int offset : dbc.getSwitchOffsets()) {
addJumpValue(dbc.getPC(), offset + pc);
+ }
break;
case ARETURN:
@@ -1394,7 +1503,7 @@ public class OpcodeStack implements Constants2 {
case POP:
pop();
break;
-
+
case PUTSTATIC:
pop();
eraseKnowledgeOf(dbc.getXFieldOperand());
@@ -1473,12 +1582,16 @@ public class OpcodeStack implements Constants2 {
}
if (right.hasConstantValue(Integer.MIN_VALUE) && left.mightRarelyBeNegative()
|| left.hasConstantValue(Integer.MIN_VALUE) && right.mightRarelyBeNegative()) {
- for (Item i : stack)
- if (i != null && i.mightRarelyBeNegative())
+ for (Item i : stack) {
+ if (i != null && i.mightRarelyBeNegative()) {
i.setSpecialKind(Item.NOT_SPECIAL);
- for (Item i : lvValues)
- if (i != null && i.mightRarelyBeNegative())
+ }
+ }
+ for (Item i : lvValues) {
+ if (i != null && i.mightRarelyBeNegative()) {
i.setSpecialKind(Item.NOT_SPECIAL);
+ }
+ }
}
int branchTarget = dbc.getBranchTarget();
addJumpValue(dbc.getPC(), branchTarget);
@@ -1487,8 +1600,9 @@ public class OpcodeStack implements Constants2 {
case POP2:
it = pop();
- if (it.getSize() == 1)
+ if (it.getSize() == 1) {
pop();
+ }
break;
@@ -1541,8 +1655,9 @@ public class OpcodeStack implements Constants2 {
case CHECKCAST: {
String castTo = dbc.getClassConstantOperand();
- if (castTo.charAt(0) != '[')
+ if (castTo.charAt(0) != '[') {
castTo = "L" + castTo + ";";
+ }
it = pop();
if (!it.signature.equals(castTo)) {
@@ -1668,15 +1783,15 @@ public class OpcodeStack implements Constants2 {
push(valueLoaded);
}
- break;
+ break;
case ARRAYLENGTH: {
- pop();
- Item newItem = new Item("I");
+ Item array = pop();
+ Item newItem = new Item("I", array.getConstant());
newItem.setSpecialKind(Item.NON_NEGATIVE);
push(newItem);
}
- break;
+ break;
case BALOAD: {
pop(2);
@@ -1685,11 +1800,13 @@ public class OpcodeStack implements Constants2 {
push(newItem);
break;
}
- case CALOAD:
+ case CALOAD: {
pop(2);
- push(new Item("I"));
+ Item newItem = new Item("I");
+ newItem.setSpecialKind(Item.NON_NEGATIVE);
+ push(newItem);
break;
-
+ }
case DALOAD:
pop(2);
push(new Item("D"));
@@ -1829,7 +1946,7 @@ public class OpcodeStack implements Constants2 {
push(newValue);
}
- break;
+ break;
@@ -1839,7 +1956,7 @@ public class OpcodeStack implements Constants2 {
push(newValue);
}
- break;
+ break;
case I2L:
case D2L:
@@ -1849,21 +1966,22 @@ public class OpcodeStack implements Constants2 {
int specialKind = it.getSpecialKind();
- if (specialKind != Item.SIGNED_BYTE && seen == I2L)
+ if (specialKind != Item.SIGNED_BYTE && seen == I2L) {
newValue.setSpecialKind(Item.RESULT_OF_I2L);
+ }
push(newValue);
}
break;
case I2S:
- {
- Item item1 = pop();
- Item newValue = new Item(item1, "S");
- newValue.setCouldBeNegative();
- push(newValue);
- }
- break;
+ {
+ Item item1 = pop();
+ Item newValue = new Item(item1, "S");
+ newValue.setCouldBeNegative();
+ push(newValue);
+ }
+ break;
case L2I:
case D2I:
@@ -1872,8 +1990,9 @@ public class OpcodeStack implements Constants2 {
int oldSpecialKind = it.getSpecialKind();
it = new Item(it, "I");
- if (oldSpecialKind == Item.NOT_SPECIAL)
+ if (oldSpecialKind == Item.NOT_SPECIAL) {
it.setSpecialKind(Item.RESULT_OF_L2I);
+ }
push(it);
break;
@@ -1905,48 +2024,60 @@ public class OpcodeStack implements Constants2 {
item.setSpecialKind(Item.NEWLY_ALLOCATED);
push(item);
}
- break;
+ break;
- case NEWARRAY:
- pop();
+ case NEWARRAY: {
+ Item length = pop();
signature = "[" + BasicType.getType((byte) dbc.getIntConstant()).getSignature();
- pushBySignature(signature, dbc);
+ Item item = new Item(signature, length.getConstant());
+ item.setPC(dbc.getPC());
+ item.setSpecialKind(Item.NEWLY_ALLOCATED);
+ push(item);
break;
+ }
// According to the VM Spec 4.4.1, anewarray and multianewarray
// can refer to normal class/interface types (encoded in
// "internal form"), or array classes (encoded as signatures
// beginning with "[").
- case ANEWARRAY:
- pop();
+ case ANEWARRAY: {
+ Item length = pop();
signature = dbc.getClassConstantOperand();
- if (signature.charAt(0) == '[')
+ if (signature.charAt(0) == '[') {
signature = "[" + signature;
- else
+ } else {
signature = "[L" + signature + ";";
- pushBySignature(signature, dbc);
+ }
+ Item item = new Item(signature, length.getConstant());
+ item.setPC(dbc.getPC());
+ item.setSpecialKind(Item.NEWLY_ALLOCATED);
+ push(item);
break;
+ }
case MULTIANEWARRAY:
int dims = dbc.getIntConstant();
- for (int i = 0; i < dims; i++)
+ for (int i = 0; i < dims; i++) {
pop();
+ }
signature = dbc.getClassConstantOperand();
pushBySignature(signature, dbc);
+ getStackItem(0).setSpecialKind(Item.NEWLY_ALLOCATED);
break;
case AALOAD: {
pop();
it = pop();
String arraySig = it.getSignature();
- if (arraySig.charAt(0) == '[')
+ if (arraySig.charAt(0) == '[') {
pushBySignature(arraySig.substring(1), dbc);
- else
+ } else {
push(new Item());
+ }
}
- break;
+ break;
case JSR:
seenTransferOfControl = true;
@@ -1958,8 +2089,9 @@ public class OpcodeStack implements Constants2 {
// OK, backwards JSRs are weird; reset the stack.
int stackSize = stack.size();
stack.clear();
- for (int i = 0; i < stackSize; i++)
+ for (int i = 0; i < stackSize; i++) {
stack.add(new Item());
+ }
}
setTop(false);
break;
@@ -1970,9 +2102,11 @@ public class OpcodeStack implements Constants2 {
case INVOKEVIRTUAL:
processMethodCall(dbc, seen);
break;
-
+ case INVOKEDYNAMIC:
+ processInvokeDynamic(dbc);
+ break;
default:
- throw new UnsupportedOperationException("OpCode " + OPCODE_NAMES[seen] + " not supported ");
+ throw new UnsupportedOperationException("OpCode " + seen + ":" + OPCODE_NAMES[seen] + " not supported ");
}
}
@@ -1987,9 +2121,11 @@ public class OpcodeStack implements Constants2 {
String msg = "Error processing opcode " + OPCODE_NAMES[seen] + " @ " + dbc.getPC() + " in "
+ dbc.getFullyQualifiedMethodName();
AnalysisContext.logError(msg, e);
- if (DEBUG)
+ if (DEBUG) {
e.printStackTrace();
+ }
clear();
+ setTop(true);
} finally {
if (DEBUG) {
System.out.printf("%4d: %14s %s%n", dbc.getPC(), OPCODE_NAMES[seen] , this);
@@ -1997,42 +2133,41 @@ public class OpcodeStack implements Constants2 {
}
}
- /**
- * @param fieldOperand
- */
private void eraseKnowledgeOf(XField fieldOperand) {
- if (fieldOperand == null) return;
- for (Item item : stack)
- if (item != null && fieldOperand.equals(item.getXField()))
+ if (fieldOperand == null) {
+ return;
+ }
+ for (Item item : stack) {
+ if (item != null && fieldOperand.equals(item.getXField())) {
item.setLoadedFromField(null, -1);
- for (Item item : lvValues)
- if (item != null && fieldOperand.equals(item.getXField()))
+ }
+ }
+ for (Item item : lvValues) {
+ if (item != null && fieldOperand.equals(item.getXField())) {
item.setLoadedFromField(null, -1);
+ }
+ }
}
-
-
public void precomputation(DismantleBytecode dbc) {
if (registerTestedFoundToBeNonnegative >= 0) {
for (int i = 0; i < stack.size(); i++) {
Item item = stack.get(i);
- if (item != null && item.registerNumber == registerTestedFoundToBeNonnegative)
+ if (item != null && item.registerNumber == registerTestedFoundToBeNonnegative) {
stack.set(i, item.cloneAndSetSpecialKind(Item.NON_NEGATIVE));
+ }
}
for (int i = 0; i < lvValues.size(); i++) {
Item item = lvValues.get(i);
- if (item != null && item.registerNumber == registerTestedFoundToBeNonnegative)
+ if (item != null && item.registerNumber == registerTestedFoundToBeNonnegative) {
lvValues.set(i, item.cloneAndSetSpecialKind(Item.NON_NEGATIVE));
+ }
}
}
registerTestedFoundToBeNonnegative = -1;
mergeJumps(dbc);
}
- /**
- * @param it
- * @return
- */
private int constantToInt(Item it) {
Object constant = it.getConstant();
if (constant instanceof Number) {
@@ -2044,34 +2179,18 @@ public class OpcodeStack implements Constants2 {
throw new IllegalArgumentException(String.valueOf(constant));
}
- /**
- * @param it
- * @return
- */
private float constantToFloat(Item it) {
return ((Number) it.getConstant()).floatValue();
}
- /**
- * @param it
- * @return
- */
private double constantToDouble(Item it) {
return ((Number) it.getConstant()).doubleValue();
}
- /**
- * @param it
- * @return
- */
private long constantToLong(Item it) {
return ((Number) it.getConstant()).longValue();
}
- /**
- * handle dcmp
- *
- */
private void handleDcmp(int opcode) {
Item it = pop();
Item it2 = pop();
@@ -2080,26 +2199,24 @@ public class OpcodeStack implements Constants2 {
double d = constantToDouble(it);
double d2 = constantToDouble(it2);
if (Double.isNaN(d) || Double.isNaN(d2)) {
- if (opcode == DCMPG)
+ if (opcode == DCMPG) {
push(new Item("I", Integer.valueOf(1)));
- else
+ } else {
push(new Item("I", Integer.valueOf(-1)));
+ }
}
- if (d2 < d)
+ if (d2 < d) {
push(new Item("I", Integer.valueOf(-1)));
- else if (d2 > d)
+ } else if (d2 > d) {
push(new Item("I", Integer.valueOf(1)));
- else
+ } else {
push(new Item("I", Integer.valueOf(0)));
+ }
} else {
push(new Item("I"));
}
}
- /**
- * handle fcmp
- *
- */
private void handleFcmp(int opcode) {
Item it = pop();
Item it2 = pop();
@@ -2107,25 +2224,24 @@ public class OpcodeStack implements Constants2 {
float f = constantToFloat(it);
float f2 = constantToFloat(it2);
if (Float.isNaN(f) || Float.isNaN(f2)) {
- if (opcode == FCMPG)
+ if (opcode == FCMPG) {
push(new Item("I", Integer.valueOf(1)));
- else
+ } else {
push(new Item("I", Integer.valueOf(-1)));
+ }
}
- if (f2 < f)
+ if (f2 < f) {
push(new Item("I", Integer.valueOf(-1)));
- else if (f2 > f)
+ } else if (f2 > f) {
push(new Item("I", Integer.valueOf(1)));
- else
+ } else {
push(new Item("I", Integer.valueOf(0)));
+ }
} else {
push(new Item("I"));
}
}
- /**
- * handle lcmp
- */
private void handleLcmp() {
Item it = pop();
Item it2 = pop();
@@ -2133,21 +2249,19 @@ public class OpcodeStack implements Constants2 {
if ((it.getConstant() != null) && it2.getConstant() != null) {
long l = constantToLong(it);
long l2 = constantToLong(it2);
- if (l2 < l)
+ if (l2 < l) {
push(new Item("I", Integer.valueOf(-1)));
- else if (l2 > l)
+ } else if (l2 > l) {
push(new Item("I", Integer.valueOf(1)));
- else
+ } else {
push(new Item("I", Integer.valueOf(0)));
+ }
} else {
push(new Item("I"));
}
}
- /**
- * handle swap
- */
private void handleSwap() {
Item i1 = pop();
Item i2 = pop();
@@ -2155,9 +2269,6 @@ public class OpcodeStack implements Constants2 {
push(i2);
}
- /**
- * handleDup
- */
private void handleDup() {
Item it;
it = pop();
@@ -2165,9 +2276,6 @@ public class OpcodeStack implements Constants2 {
push(it);
}
- /**
- * handle dupX1
- */
private void handleDupX1() {
Item it;
Item it2;
@@ -2178,9 +2286,6 @@ public class OpcodeStack implements Constants2 {
push(it);
}
- /**
- * handle dup2
- */
private void handleDup2() {
Item it, it2;
it = pop();
@@ -2196,9 +2301,6 @@ public class OpcodeStack implements Constants2 {
}
}
- /**
- * handle Dup2x1
- */
private void handleDup2X1() {
String signature;
Item it;
@@ -2209,7 +2311,7 @@ public class OpcodeStack implements Constants2 {
it2 = pop();
signature = it.getSignature();
- if (signature.equals("J") || signature.equals("D")) {
+ if ("J".equals(signature) || "D".equals(signature)) {
push(it);
push(it2);
push(it);
@@ -2259,9 +2361,6 @@ public class OpcodeStack implements Constants2 {
}
}
- /**
- * Handle DupX2
- */
private void handleDupX2() {
String signature;
Item it;
@@ -2270,7 +2369,7 @@ public class OpcodeStack implements Constants2 {
it = pop();
it2 = pop();
signature = it2.getSignature();
- if (signature.equals("J") || signature.equals("D")) {
+ if ("J".equals(signature) || "D".equals(signature)) {
push(it);
push(it2);
push(it);
@@ -2283,19 +2382,15 @@ public class OpcodeStack implements Constants2 {
}
}
- @edu.umd.cs.findbugs.internalAnnotations.StaticConstant
- static final HashMap<String, String> boxedTypes = new HashMap<String, String>();
-
static private void addBoxedType(Class<?>... clss) {
for (Class<?> c : clss) {
Class<?> primitiveType;
try {
primitiveType = (Class<?>) c.getField("TYPE").get(null);
boxedTypes.put(ClassName.toSlashedClassName(c.getName()), primitiveType.getName());
- } catch (Exception e) {
+ } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
throw new AssertionError(e);
}
-
}
}
@@ -2308,8 +2403,9 @@ public class OpcodeStack implements Constants2 {
item.constValue = null;
if (item.registerNumber >= 0) {
OpcodeStack.Item sbItem = getLVValue(item.registerNumber);
- if (sbItem != null && sbItem.getSignature().equals(item.getSignature()))
+ if (sbItem.getSignature().equals(item.getSignature())) {
sbItem.constValue = null;
+ }
}
}
@@ -2322,26 +2418,29 @@ public class OpcodeStack implements Constants2 {
boolean sawUnknownAppend = false;
Item sbItem = null;
Item topItem = null;
- if (getStackDepth() > 0)
+ if (getStackDepth() > 0) {
topItem = getStackItem(0);
+ }
int numberArguments = PreorderVisitor.getNumberArguments(signature);
if (boxedTypes.containsKey(clsName)
&& topItem != null
- && (methodName.equals("valueOf") && !signature.contains("String") || methodName.equals(boxedTypes.get(clsName)
+ && ("valueOf".equals(methodName) && !signature.contains("String") || methodName.equals(boxedTypes.get(clsName)
+ "Value"))) {
// boxing/unboxing conversion
Item value = pop();
- String newSignature = Type.getReturnType(signature).getSignature();
+ String newSignature = new SignatureParser(signature).getReturnTypeSignature();
Item newValue = new Item(value, newSignature);
- if (newValue.source == null)
+ if (newValue.source == null) {
newValue.source = XFactory.createReferencedXMethod(dbc);
+ }
if (newValue.specialKind == Item.NOT_SPECIAL) {
- if (newSignature.equals("B") || newSignature.equals("Ljava/lang/Boolean;"))
+ if ("B".equals(newSignature) || "Ljava/lang/Boolean;".equals(newSignature)) {
newValue.specialKind = Item.SIGNED_BYTE;
- else if (newSignature.equals("C") || newSignature.equals("Ljava/lang/Character;"))
+ } else if ("C".equals(newSignature) || "Ljava/lang/Character;".equals(newSignature)) {
newValue.specialKind = Item.NON_NEGATIVE;
+ }
}
push(newValue);
return;
@@ -2349,24 +2448,28 @@ public class OpcodeStack implements Constants2 {
int firstArgument = seen == INVOKESTATIC ? 0 : 1;
for (int i = firstArgument; i < firstArgument + numberArguments; i++) {
- if (i >= getStackDepth())
+ if (i >= getStackDepth()) {
break;
+ }
Item item = getStackItem(i);
String itemSignature = item.getSignature();
- if (itemSignature.equals("Ljava/lang/StringBuilder;") || itemSignature.equals("Ljava/lang/StringBuffer;"))
+ if ("Ljava/lang/StringBuilder;".equals(itemSignature) || "Ljava/lang/StringBuffer;".equals(itemSignature)) {
markConstantValueUnknown(item);
+ }
}
boolean initializingServletWriter = false;
- if (seen == INVOKESPECIAL && methodName.equals("<init>") && clsName.startsWith("java/io") && clsName.endsWith("Writer")
+ if (seen == INVOKESPECIAL && "<init>".equals(methodName) && clsName.startsWith("java/io") && clsName.endsWith("Writer")
&& numberArguments > 0) {
Item firstArg = getStackItem(numberArguments-1);
- if (firstArg.isServletWriter())
+ if (firstArg.isServletWriter()) {
initializingServletWriter = true;
+ }
}
boolean topIsTainted = topItem != null && topItem.isServletParameterTainted();
HttpParameterInjection injection = null;
- if (topIsTainted)
+ if (topIsTainted) {
injection = topItem.injection;
+ }
// TODO: stack merging for trinaries kills the constant.. would be nice
// to maintain.
@@ -2375,28 +2478,32 @@ public class OpcodeStack implements Constants2 {
if ("(Ljava/lang/String;)V".equals(signature)) {
Item i = getStackItem(0);
appenderValue = (String) i.getConstant();
- if (i.isServletParameterTainted())
+ if (i.isServletParameterTainted()) {
servletRequestParameterTainted = true;
+ }
} else if ("()V".equals(signature)) {
appenderValue = "";
}
} else if ("toString".equals(methodName) && getStackDepth() >= 1) {
Item i = getStackItem(0);
appenderValue = (String) i.getConstant();
- if (i.isServletParameterTainted())
+ if (i.isServletParameterTainted()) {
servletRequestParameterTainted = true;
+ }
} else if ("append".equals(methodName)) {
if (signature.indexOf("II)") == -1 && getStackDepth() >= 2) {
sbItem = getStackItem(1);
Item i = getStackItem(0);
- if (i.isServletParameterTainted() || sbItem.isServletParameterTainted())
+ if (i.isServletParameterTainted() || sbItem.isServletParameterTainted()) {
servletRequestParameterTainted = true;
+ }
Object sbVal = sbItem.getConstant();
Object sVal = i.getConstant();
if ((sbVal != null) && (sVal != null)) {
appenderValue = sbVal + sVal.toString();
- } else
+ } else {
markConstantValueUnknown(sbItem);
+ }
} else if (signature.startsWith("([CII)")) {
sawUnknownAppend = true;
sbItem = getStackItem(3);
@@ -2405,25 +2512,25 @@ public class OpcodeStack implements Constants2 {
sawUnknownAppend = true;
}
}
- } else if (seen == INVOKESPECIAL && clsName.equals("java/io/FileOutputStream") && methodName.equals("<init>")
- && (signature.equals("(Ljava/io/File;Z)V") || signature.equals("(Ljava/lang/String;Z)V")) && stack.size() > 3) {
+ } else if (seen == INVOKESPECIAL && "java/io/FileOutputStream".equals(clsName) && "<init>".equals(methodName)
+ && ("(Ljava/io/File;Z)V".equals(signature) || "(Ljava/lang/String;Z)V".equals(signature)) && stack.size() > 3) {
OpcodeStack.Item item = getStackItem(0);
Object value = item.getConstant();
if (value instanceof Integer && ((Integer) value).intValue() == 1) {
pop(3);
Item newTop = getStackItem(0);
- if (newTop.signature.equals("Ljava/io/FileOutputStream;")) {
+ if ("Ljava/io/FileOutputStream;".equals(newTop.signature)) {
newTop.setSpecialKind(Item.FILE_OPENED_IN_APPEND_MODE);
newTop.source = XFactory.createReferencedXMethod(dbc);
newTop.setPC(dbc.getPC());
}
return;
}
- } else if (seen == INVOKESPECIAL && clsName.equals("java/io/BufferedOutputStream") && methodName.equals("<init>")
- && signature.equals("(Ljava/io/OutputStream;)V")) {
+ } else if (seen == INVOKESPECIAL && "java/io/BufferedOutputStream".equals(clsName) && "<init>".equals(methodName)
+ && "(Ljava/io/OutputStream;)V".equals(signature)) {
if (getStackItem(0).getSpecialKind() == Item.FILE_OPENED_IN_APPEND_MODE
- && getStackItem(2).signature.equals("Ljava/io/BufferedOutputStream;")) {
+ && "Ljava/io/BufferedOutputStream;".equals(getStackItem(2).signature)) {
pop(2);
Item newTop = getStackItem(0);
@@ -2432,23 +2539,24 @@ public class OpcodeStack implements Constants2 {
newTop.setPC(dbc.getPC());
return;
}
- } else if (seen == INVOKEINTERFACE && methodName.equals("getParameter")
- && clsName.equals("javax/servlet/http/HttpServletRequest") || clsName.equals("javax/servlet/http/ServletRequest")) {
+ } else if (seen == INVOKEINTERFACE && "getParameter".equals(methodName)
+ && "javax/servlet/http/HttpServletRequest".equals(clsName) || "javax/servlet/http/ServletRequest".equals(clsName)) {
Item requestParameter = pop();
pop();
Item result = new Item("Ljava/lang/String;");
result.setServletParameterTainted();
result.source = XFactory.createReferencedXMethod(dbc);
String parameterName = null;
- if (requestParameter.getConstant() instanceof String)
+ if (requestParameter.getConstant() instanceof String) {
parameterName = (String) requestParameter.getConstant();
+ }
result.injection = new HttpParameterInjection(parameterName, dbc.getPC());
result.setPC(dbc.getPC());
push(result);
return;
- } else if (seen == INVOKEINTERFACE && methodName.equals("getQueryString")
- && clsName.equals("javax/servlet/http/HttpServletRequest") || clsName.equals("javax/servlet/http/ServletRequest")) {
+ } else if (seen == INVOKEINTERFACE && "getQueryString".equals(methodName)
+ && "javax/servlet/http/HttpServletRequest".equals(clsName) || "javax/servlet/http/ServletRequest".equals(clsName)) {
pop();
Item result = new Item("Ljava/lang/String;");
result.setServletParameterTainted();
@@ -2456,8 +2564,8 @@ public class OpcodeStack implements Constants2 {
result.setPC(dbc.getPC());
push(result);
return;
- } else if (seen == INVOKEINTERFACE && methodName.equals("getHeader")
- && clsName.equals("javax/servlet/http/HttpServletRequest") || clsName.equals("javax/servlet/http/ServletRequest")) {
+ } else if (seen == INVOKEINTERFACE && "getHeader".equals(methodName)
+ && "javax/servlet/http/HttpServletRequest".equals(clsName) || "javax/servlet/http/ServletRequest".equals(clsName)) {
/* Item requestParameter = */pop();
pop();
Item result = new Item("Ljava/lang/String;");
@@ -2466,15 +2574,15 @@ public class OpcodeStack implements Constants2 {
result.setPC(dbc.getPC());
push(result);
return;
- } else if (seen == INVOKESTATIC && methodName.equals("asList") && clsName.equals("java/util/Arrays")) {
+ } else if (seen == INVOKESTATIC && "asList".equals(methodName) && "java/util/Arrays".equals(clsName)) {
/* Item requestParameter = */pop();
Item result = new Item(JAVA_UTIL_ARRAYS_ARRAY_LIST);
push(result);
return;
- } else if (seen == INVOKESTATIC && signature.equals("(Ljava/util/List;)Ljava/util/List;")
- && clsName.equals("java/util/Collections")) {
+ } else if (seen == INVOKESTATIC && "(Ljava/util/List;)Ljava/util/List;".equals(signature)
+ && "java/util/Collections".equals(clsName)) {
Item requestParameter = pop();
- if (requestParameter.getSignature().equals(JAVA_UTIL_ARRAYS_ARRAY_LIST)) {
+ if (JAVA_UTIL_ARRAYS_ARRAY_LIST.equals(requestParameter.getSignature())) {
Item result = new Item(JAVA_UTIL_ARRAYS_ARRAY_LIST);
push(result);
return;
@@ -2484,8 +2592,13 @@ public class OpcodeStack implements Constants2 {
pushByInvoke(dbc, seen != INVOKESTATIC);
- if (initializingServletWriter)
+ if (sbItem != null && sbItem.isNewlyAllocated()) {
+ this.getStackItem(0).setSpecialKind(Item.NEWLY_ALLOCATED);
+ }
+
+ if (initializingServletWriter) {
this.getStackItem(0).setIsServletWriter();
+ }
if ((sawUnknownAppend || appenderValue != null || servletRequestParameterTainted) && getStackDepth() > 0) {
Item i = this.getStackItem(0);
@@ -2497,45 +2610,70 @@ public class OpcodeStack implements Constants2 {
if (sbItem != null) {
i.registerNumber = sbItem.registerNumber;
i.source = sbItem.source;
- if (i.injection == null)
+ if (i.injection == null) {
i.injection = sbItem.injection;
- if (sbItem.registerNumber >= 0)
+ }
+ if (sbItem.registerNumber >= 0) {
setLVValue(sbItem.registerNumber, i);
+ }
}
return;
}
- if ((clsName.equals("java/util/Random") || clsName.equals("java/security/SecureRandom")) &&
- (methodName.equals("nextInt") && signature.equals("()I")
- || methodName.equals("nextLong") && signature.equals("()J"))
+ if (("java/util/Random".equals(clsName) || "java/security/SecureRandom".equals(clsName)) &&
+ ("nextInt".equals(methodName) && "()I".equals(signature)
+ || "nextLong".equals(methodName) && "()J".equals(signature))
) {
Item i = new Item(pop());
i.setSpecialKind(Item.RANDOM_INT);
push(i);
- } else if (methodName.equals("size") && signature.equals("()I")
+ } else if ("size".equals(methodName) && "()I".equals(signature)
&& Subtypes2.instanceOf(ClassName.toDottedClassName(clsName), "java.util.Collection")) {
Item i = new Item(pop());
- if (i.getSpecialKind() == Item.NOT_SPECIAL)
- i.setSpecialKind(Item.NON_NEGATIVE);
+ if (i.getSpecialKind() == Item.NOT_SPECIAL) {
+ i.setSpecialKind(Item.NON_NEGATIVE);
+ }
push(i);
- } else if (ClassName.isMathClass(clsName) && methodName.equals("abs")) {
+ } else if("java/lang/String".equals(clsName) && numberArguments == 0 && topItem.getConstant() instanceof String) {
+ String input = (String) topItem.getConstant();
+ Object result;
+ switch(methodName) {
+ case "length":
+ result = input.length();
+ break;
+ case "trim":
+ result = input.trim();
+ break;
+ case "toString":
+ case "intern":
+ result = input;
+ break;
+ default:
+ result = null;
+ }
+ if(result != null) {
+ Item i = new Item(pop());
+ i.constValue = result;
+ push(i);
+ }
+ } else if (ClassName.isMathClass(clsName) && "abs".equals(methodName)) {
Item i = new Item(pop());
- if (i.getSpecialKind() == Item.HASHCODE_INT)
+ if (i.getSpecialKind() == Item.HASHCODE_INT) {
i.setSpecialKind(Item.MATH_ABS_OF_HASHCODE);
- else if (i.getSpecialKind() == Item.RANDOM_INT)
+ } else if (i.getSpecialKind() == Item.RANDOM_INT) {
i.setSpecialKind(Item.MATH_ABS_OF_RANDOM);
- else
+ } else {
i.setSpecialKind(Item.MATH_ABS);
+ }
push(i);
- } else if (seen == INVOKEVIRTUAL && methodName.equals("hashCode") && signature.equals("()I") || seen == INVOKESTATIC
- && clsName.equals("java/lang/System") && methodName.equals("identityHashCode")
- && signature.equals("(Ljava/lang/Object;)I")) {
+ } else if (seen == INVOKEVIRTUAL && "hashCode".equals(methodName) && "()I".equals(signature) || seen == INVOKESTATIC
+ && "java/lang/System".equals(clsName) && "identityHashCode".equals(methodName)
+ && "(Ljava/lang/Object;)I".equals(signature)) {
Item i = new Item(pop());
i.setSpecialKind(Item.HASHCODE_INT);
push(i);
} else if (topIsTainted
- && (methodName.startsWith("encode") && clsName.equals("javax/servlet/http/HttpServletResponse") || methodName
- .equals("trim") && clsName.equals("java/lang/String"))) {
+ && (methodName.startsWith("encode") && "javax/servlet/http/HttpServletResponse".equals(clsName) || "trim".equals(methodName) && "java/lang/String".equals(clsName))) {
Item i = new Item(pop());
i.setSpecialKind(Item.SERVLET_REQUEST_TAINTED);
i.injection = injection;
@@ -2550,7 +2688,15 @@ public class OpcodeStack implements Constants2 {
}
- boolean foobar = false;
+ private void processInvokeDynamic(DismantleBytecode dbc) {
+ String signature = dbc.getSigConstantOperand();
+
+ int numberArguments = PreorderVisitor.getNumberArguments(signature);
+
+ pop(numberArguments);
+ pushBySignature(new SignatureParser(signature).getReturnTypeSignature(), dbc);
+ }
+
private boolean mergeLists(List<Item> mergeInto, List<Item> mergeFrom, boolean errorIfSizesDoNotMatch) {
// merge stacks
int intoSize = mergeInto.size();
@@ -2569,32 +2715,31 @@ public class OpcodeStack implements Constants2 {
System.out.println("current items: " + mergeInto);
System.out.println("jump items: " + mergeFrom);
}
-
+
}
List<Item> mergeIntoCopy = null;
- if (DEBUG2)
+ if (DEBUG2) {
mergeIntoCopy = new ArrayList<Item>(mergeInto);
+ }
int common = Math.min(intoSize, fromSize);
for (int i = 0; i < common; i++) {
Item oldValue = mergeInto.get(i);
Item newValue = mergeFrom.get(i);
Item merged = Item.merge(oldValue, newValue);
if (merged != null && !merged.equals(oldValue)) {
- if (foobar)
- System.out.println("foobar");
mergeInto.set(i, merged);
changed = true;
}
}
+ /*
if (false) for (int i = common; i < fromSize; i++) {
Item newValue = mergeFrom.get(i);
- if (foobar)
- System.out.println("foobar");
mergeInto.add(newValue);
changed = true;
}
+ */
if (DEBUG2 && changed) {
System.out.println("Merge results:");
System.out.println("updating: " + mergeIntoCopy);
@@ -2610,28 +2755,15 @@ public class OpcodeStack implements Constants2 {
lvValues.clear();
}
- boolean encountedTop;
-
- boolean backwardsBranch;
-
- BitSet exceptionHandlers = new BitSet();
-
- private boolean jumpInfoChangedByBackwardsBranch = false;
-
- private Map<Integer, List<Item>> jumpEntries = new HashMap<Integer, List<Item>>();
-
- private Map<Integer, List<Item>> jumpStackEntries = new HashMap<Integer, List<Item>>();
-
- private BitSet jumpEntryLocations = new BitSet();
-
public void printJumpEntries() {
for(int i=jumpEntryLocations.nextSetBit(0); i>=0; i=jumpEntryLocations.nextSetBit(i+1)) {
List<Item> stack = jumpStackEntries.get(i);
List<Item> locals = jumpEntries.get(i);
- if (stack != null)
- System.out.printf("%4d: %s::%s%n", i, stack, locals);
- else
+ if (stack != null) {
+ System.out.printf("%4d: %s::%s%n", i, stack, locals);
+ } else {
System.out.printf("%4d: ::%s%n", i, locals);
+ }
}
}
@@ -2660,6 +2792,7 @@ public class OpcodeStack implements Constants2 {
super("Jump info for opcode stack", JumpInfo.class);
}
+ @Override
public @CheckForNull JumpInfo analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
Method method = analysisCache.getMethodAnalysis(Method.class, descriptor);
JavaClass jclass = getJavaClass(analysisCache, descriptor.getClassDescriptor());
@@ -2667,68 +2800,72 @@ public class OpcodeStack implements Constants2 {
if (code == null) {
return null;
}
-
+
JumpStackComputation branchAnalysis = new JumpStackComputation(descriptor);
-
+
return computeJumpInfo(jclass, method, branchAnalysis);
}
- static class JumpStackComputation extends BytecodeScanningDetector {
+ static class JumpStackComputation extends BytecodeScanningDetector {
- static final boolean DEBUG = false;
- final MethodDescriptor descriptor;
- private JumpStackComputation(MethodDescriptor descriptor) {
- this.descriptor = descriptor;
- }
+ static final boolean DEBUG1 = false;
+ final MethodDescriptor descriptor;
+ private JumpStackComputation(MethodDescriptor descriptor) {
+ this.descriptor = descriptor;
+ }
- protected OpcodeStack stack = new OpcodeStack();
+ protected OpcodeStack stack = new OpcodeStack();
- public OpcodeStack getStack() {
- return stack;
- }
+ public OpcodeStack getStack() {
+ return stack;
+ }
- @Override
- public final void visitCode(Code obj) {
- if (!getMethodDescriptor().equals(descriptor))
- throw new IllegalStateException();
- if (DEBUG) System.out.println(descriptor);
- stack.resetForMethodEntry0(this);
- super.visitCode(obj);
- if (DEBUG) System.out.println();
- }
+ @Override
+ public final void visitCode(Code obj) {
+ if (!getMethodDescriptor().equals(descriptor)) {
+ throw new IllegalStateException();
+ }
+ if (DEBUG1) {
+ System.out.println(descriptor);
+ }
+ stack.resetForMethodEntry0(this);
+ super.visitCode(obj);
+ if (DEBUG1) {
+ System.out.println();
+ }
+ }
- @Override
+ @Override
public void sawOpcode(int seen) {
- stack.precomputation(this);
-
- if (DEBUG) System.out.printf("%4d %-15s %s%n", getPC(), OPCODE_NAMES[seen], stack);
- try {
- stack.sawOpcode(this, seen);
- } catch (RuntimeException e) {
- throw e;
- }
- }
- }
+ stack.precomputation(this);
+
+ if (DEBUG1) {
+ System.out.printf("%4d %-15s %s%n", getPC(), OPCODE_NAMES[seen], stack);
+ }
+ try {
+ stack.sawOpcode(this, seen);
+ } catch (RuntimeException e) {
+ throw e;
+ }
+ }
+ }
- /**
- * @param jclass
- * @param method
- * @param stack
- * @param branchAnalysis
- * @return
- */
public static @CheckForNull JumpInfo computeJumpInfo(JavaClass jclass, Method method,
JumpStackComputation branchAnalysis) {
branchAnalysis.setupVisitorForClass(jclass);
XMethod createXMethod = XFactory.createXMethod(jclass, method);
- if (!(createXMethod instanceof MethodInfo))
+ if (!(createXMethod instanceof MethodInfo)) {
return null;
+ }
MethodInfo xMethod = (MethodInfo) createXMethod;
-
+
int iteration = 1;
OpcodeStack myStack = branchAnalysis.stack;
- if (false)
+ /*
+ if (false) {
myStack.learnFrom(myStack.getJumpInfoFromStackMap());
+ }
+ */
do {
if (DEBUG && iteration > 1 ) {
System.out.println("Iterative jump info for " + xMethod +", iteration " + iteration);
@@ -2742,9 +2879,15 @@ public class OpcodeStack implements Constants2 {
String.format("For %s, mismatch on existence of backedge: %s for precomputation, %s for bytecode analysis",
xMethod, xMethod.hasBackBranch(), myStack.backwardsBranch));
}
+ if (myStack.isJumpInfoChangedByNewTarget()) {
+ if (DEBUG) {
+ System.out.println("new target found, resetting iteration count");
+ }
+ iteration = 1;
+ }
if (iteration++ > 40) {
- AnalysisContext.logError("Iterative jump info didn't converge after " + iteration + " iterations in " + xMethod
- + ", size " + method.getCode().getLength());
+ AnalysisContext.logError("Iterative jump info didn't converge after " + iteration + " iterations in " + xMethod
+ + ", size " + method.getCode().getLength());
break;
}
} while (myStack.isJumpInfoChangedByBackwardsBranch() && myStack.backwardsBranch);
@@ -2761,29 +2904,34 @@ public class OpcodeStack implements Constants2 {
}
private void addJumpValue(int from, int target) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Set jump entry at " + methodName + ":" + target + " pc to " + stack + " : " + lvValues);
+ }
- if (from >= target)
+ if (from >= target) {
backwardsBranch = true;
+ }
List<Item> atTarget = jumpEntries.get(Integer.valueOf(target));
if (atTarget == null) {
setJumpInfoChangedByBackwardBranch("new target", from, target);
+ setJumpInfoChangedByNewTarget();
jumpEntries.put(Integer.valueOf(target), new ArrayList<Item>(lvValues));
jumpEntryLocations.set(target);
if (stack.size() > 0) {
jumpStackEntries.put(Integer.valueOf(target), new ArrayList<Item>(stack));
}
} else {
- if (mergeLists(atTarget, lvValues, false))
- setJumpInfoChangedByBackwardBranch("locals", from, target);
- List<Item> stackAtTarget = jumpStackEntries.get(Integer.valueOf(target));
- if (stack.size() > 0 && stackAtTarget != null)
- if (mergeLists(stackAtTarget, stack, false))
- setJumpInfoChangedByBackwardBranch("stack", from, target);
+ if (mergeLists(atTarget, lvValues, false)) {
+ setJumpInfoChangedByBackwardBranch("locals", from, target);
+ }
+ List<Item> stackAtTarget = jumpStackEntries.get(Integer.valueOf(target));
+ if (stack.size() > 0 && stackAtTarget != null) {
+ if (mergeLists(stackAtTarget, stack, false)) {
+ setJumpInfoChangedByBackwardBranch("stack", from, target);
+ }
+ }
}
- if (DEBUG)
- System.out.println("merge target for " + methodName + ":" + target + " pc is " + atTarget);
+
}
private String methodName;
@@ -2791,8 +2939,9 @@ public class OpcodeStack implements Constants2 {
DismantleBytecode v;
public void learnFrom(JumpInfo info) {
- if (info == null)
+ if (info == null) {
return;
+ }
jumpEntries = new HashMap<Integer, List<Item>>(info.jumpEntries);
jumpStackEntries = new HashMap<Integer, List<Item>>(info.jumpStackEntries);
jumpEntryLocations = (BitSet) info.jumpEntryLocations.clone();
@@ -2818,8 +2967,9 @@ public class OpcodeStack implements Constants2 {
int result = resetForMethodEntry0(v);
Code code = v.getMethod().getCode();
- if (code == null)
+ if (code == null) {
return result;
+ }
JumpInfo jump = null;
if (useIterativeAnalysis) {
if (visitor instanceof OpcodeStackDetector.WithCustomJumpInfo) {
@@ -2838,18 +2988,20 @@ public class OpcodeStack implements Constants2 {
}
int nullSafeSize(@CheckForNull Collection<?> c) {
- if (c == null)
+ if (c == null) {
return 0;
+ }
return c.size();
}
-
+
private JumpInfo getJumpInfo() {
IAnalysisCache analysisCache = Global.getAnalysisCache();
XMethod xMethod = XFactory.createXMethod(v.getThisClass(), v.getMethod());
if (xMethod instanceof MethodInfo) {
MethodInfo mi = (MethodInfo) xMethod;
- if (!mi.hasBackBranch())
+ if (!mi.hasBackBranch()) {
return null;
+ }
}
try {
return analysisCache.getMethodAnalysis(JumpInfo.class, xMethod.getMethodDescriptor());
@@ -2863,13 +3015,14 @@ public class OpcodeStack implements Constants2 {
XMethod xMethod = XFactory.createXMethod(v.getThisClass(), v.getMethod());
if (xMethod instanceof MethodInfo) {
MethodInfo mi = (MethodInfo) xMethod;
- if (!mi.hasBackBranch())
+ if (!mi.hasBackBranch()) {
return null;
+ }
}
-
+
try {
return analysisCache.getMethodAnalysis(JumpInfoFromStackMap.class, xMethod.getMethodDescriptor());
-
+
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("Error getting jump information from StackMap", e);
return null;
@@ -2877,12 +3030,14 @@ public class OpcodeStack implements Constants2 {
}
public void setJumpInfoChangedByBackwardBranch(String kind, int from, int to) {
- if (from < to)
+ if (from < to) {
return ;
-
-
- if (DEBUG && !this.isJumpInfoChangedByBackwardsBranch())
+ }
+
+
+ if (DEBUG && !this.isJumpInfoChangedByBackwardsBranch()) {
System.out.printf("%s jump info at %d changed by jump from %d%n", kind, to, from);
+ }
this.setJumpInfoChangedByBackwardsBranch(from,to);
return ;
}
@@ -2891,11 +3046,12 @@ public class OpcodeStack implements Constants2 {
return resetForMethodEntry0(visitor.getClassName(), visitor.getMethod());
}
- int resetForMethodEntry0(@SlashedClassName String className, Method m) {
+ int resetForMethodEntry0(@SlashedClassName String className, Method m) {
methodName = m.getName();
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" --- ");
+ }
String signature = m.getSignature();
stack.clear();
lvValues.clear();
@@ -2903,6 +3059,7 @@ public class OpcodeStack implements Constants2 {
encountedTop = false;
backwardsBranch = false;
clearJumpInfoChangedByBackwardsBranch();
+ clearJumpInfoChangedByNewTarget();
setReachOnlyByBranch(false);
seenTransferOfControl = false;
@@ -2910,12 +3067,15 @@ public class OpcodeStack implements Constants2 {
Code code = m.getCode();
if (code != null) {
CodeException[] exceptionTable = code.getExceptionTable();
- if (exceptionTable != null)
- for (CodeException ex : exceptionTable)
+ if (exceptionTable != null) {
+ for (CodeException ex : exceptionTable) {
exceptionHandlers.set(ex.getHandlerPC());
+ }
+ }
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" --- " + className + " " + m.getName() + " " + signature);
+ }
Type[] argTypes = Type.getArgumentTypes(signature);
int reg = 0;
if (!m.isStatic()) {
@@ -2939,7 +3099,7 @@ public class OpcodeStack implements Constants2 {
if (stackOffset < 0 || stackOffset >= stack.size()) {
AnalysisContext.logError("Can't get stack offset " + stackOffset + " from " + stack.toString() + " @ " + v.getPC()
+ " in " + v.getFullyQualifiedMethodName(), new IllegalArgumentException(stackOffset
- + " is not a value stack offset"));
+ + " is not a value stack offset"));
return new Item("Lfindbugs/OpcodeStackError;");
}
@@ -2958,18 +3118,18 @@ public class OpcodeStack implements Constants2 {
}
public void replace(int stackOffset, Item value) {
- if (stackOffset < 0 || stackOffset >= stack.size()) {
- AnalysisContext.logError("Can't get replace stack offset " + stackOffset + " from " + stack.toString() + " @ " + v.getPC()
- + " in " + v.getFullyQualifiedMethodName(), new IllegalArgumentException(stackOffset
- + " is not a value stack offset"));
+ if (stackOffset < 0 || stackOffset >= stack.size()) {
+ AnalysisContext.logError("Can't get replace stack offset " + stackOffset + " from " + stack.toString() + " @ " + v.getPC()
+ + " in " + v.getFullyQualifiedMethodName(), new IllegalArgumentException(stackOffset
+ + " is not a value stack offset"));
- }
- int tos = stack.size() - 1;
- int pos = tos - stackOffset;
+ }
+ int tos = stack.size() - 1;
+ int pos = tos - stackOffset;
- stack.set(pos, value);
+ stack.set(pos, value);
- }
+ }
public void replaceTop(Item newTop) {
pop();
@@ -2977,8 +3137,9 @@ public class OpcodeStack implements Constants2 {
}
private void pop(int count) {
- while ((count--) > 0)
+ while ((count--) > 0) {
pop();
+ }
}
private void push(Item i) {
@@ -2987,21 +3148,22 @@ public class OpcodeStack implements Constants2 {
private void pushByConstant(DismantleBytecode dbc, Constant c) {
- if (c instanceof ConstantClass)
+ if (c instanceof ConstantClass) {
push(new Item("Ljava/lang/Class;", ((ConstantClass) c).getConstantValue(dbc.getConstantPool())));
- else if (c instanceof ConstantInteger)
+ } else if (c instanceof ConstantInteger) {
push(new Item("I", Integer.valueOf(((ConstantInteger) c).getBytes())));
- else if (c instanceof ConstantString) {
+ } else if (c instanceof ConstantString) {
int s = ((ConstantString) c).getStringIndex();
push(new Item("Ljava/lang/String;", getStringFromIndex(dbc, s)));
- } else if (c instanceof ConstantFloat)
+ } else if (c instanceof ConstantFloat) {
push(new Item("F", Float.valueOf(((ConstantFloat) c).getBytes())));
- else if (c instanceof ConstantDouble)
+ } else if (c instanceof ConstantDouble) {
push(new Item("D", Double.valueOf(((ConstantDouble) c).getBytes())));
- else if (c instanceof ConstantLong)
+ } else if (c instanceof ConstantLong) {
push(new Item("J", Long.valueOf(((ConstantLong) c).getBytes())));
- else
+ } else {
throw new UnsupportedOperationException("StaticConstant type not expected");
+ }
}
private void pushByLocalObjectLoad(DismantleBytecode dbc, int register) {
@@ -3026,9 +3188,10 @@ public class OpcodeStack implements Constants2 {
}
try {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("pushByIntMath " + dbc.getFullyQualifiedMethodName() + " @ " + dbc.getPC() + " : " + lhs
+ OPCODE_NAMES[seen] + rhs);
+ }
if (rhs.getConstant() != null && lhs.getConstant() != null) {
int lhsValue = constantToInt(lhs);
@@ -3056,8 +3219,9 @@ public class OpcodeStack implements Constants2 {
break;
case IAND:
newValue = new Item("I", lhsValue & rhsValue);
- if ((rhsValue & 0xff) == 0 && rhsValue != 0 || (lhsValue & 0xff) == 0 && lhsValue != 0)
+ if ((rhsValue & 0xff) == 0 && rhsValue != 0 || (lhsValue & 0xff) == 0 && lhsValue != 0) {
newValue.setSpecialKind(Item.LOW_8_BITS_CLEAR);
+ }
break;
case IOR:
@@ -3068,8 +3232,9 @@ public class OpcodeStack implements Constants2 {
break;
case ISHL:
newValue = new Item("I", lhsValue << rhsValue);
- if (rhsValue >= 8)
+ if (rhsValue >= 8) {
newValue.setSpecialKind(Item.LOW_8_BITS_CLEAR);
+ }
break;
case ISHR:
@@ -3084,31 +3249,35 @@ public class OpcodeStack implements Constants2 {
} else if ((seen == ISHL || seen == ISHR || seen == IUSHR)) {
if (rhs.getConstant() != null) {
int constant = constantToInt(rhs);
- if ((constant & 0x1f) == 0)
+ if ((constant & 0x1f) == 0) {
newValue = new Item(lhs);
- else if (seen == ISHL && (constant & 0x1f) >= 8)
+ } else if (seen == ISHL && (constant & 0x1f) >= 8) {
newValue.setSpecialKind(Item.LOW_8_BITS_CLEAR);
+ }
} else if (lhs.getConstant() != null) {
int constant = constantToInt(lhs);
- if (constant == 0)
+ if (constant == 0) {
newValue = new Item("I", 0);
+ }
}
} else if (lhs.getConstant() != null && seen == IAND) {
int value = constantToInt(lhs);
- if (value == 0)
+ if (value == 0) {
newValue = new Item("I", 0);
- else if ((value & 0xff) == 0)
+ } else if ((value & 0xff) == 0) {
newValue.setSpecialKind(Item.LOW_8_BITS_CLEAR);
- else if (value >= 0)
+ } else if (value >= 0) {
newValue.setSpecialKind(Item.NON_NEGATIVE);
+ }
} else if (rhs.getConstant() != null && seen == IAND) {
int value = constantToInt(rhs);
- if (value == 0)
+ if (value == 0) {
newValue = new Item("I", 0);
- else if ((value & 0xff) == 0)
+ } else if ((value & 0xff) == 0) {
newValue.setSpecialKind(Item.LOW_8_BITS_CLEAR);
- else if (value >= 0)
+ } else if (value >= 0) {
newValue.setSpecialKind(Item.NON_NEGATIVE);
+ }
} else if (seen == IAND && lhs.getSpecialKind() == Item.ZERO_MEANS_NULL) {
newValue.setSpecialKind(Item.ZERO_MEANS_NULL);
newValue.setPC(lhs.getPC());
@@ -3132,26 +3301,33 @@ public class OpcodeStack implements Constants2 {
}
if (lhs.getSpecialKind() == Item.INTEGER_SUM && rhs.getConstant() != null) {
int rhsValue = constantToInt(rhs);
- if (seen == IDIV && rhsValue == 2 || seen == ISHR && rhsValue == 1)
+ if (seen == IDIV && rhsValue == 2 || seen == ISHR && rhsValue == 1) {
newValue.setSpecialKind(Item.AVERAGE_COMPUTED_USING_DIVISION);
+ }
}
if (seen == IADD && newValue.getSpecialKind() == Item.NOT_SPECIAL && lhs.getConstant() == null
- && rhs.getConstant() == null)
+ && rhs.getConstant() == null) {
newValue.setSpecialKind(Item.INTEGER_SUM);
- if (seen == IREM && lhs.getSpecialKind() == Item.HASHCODE_INT)
+ }
+ if (seen == IREM && lhs.getSpecialKind() == Item.HASHCODE_INT) {
newValue.setSpecialKind(Item.HASHCODE_INT_REMAINDER);
- if (seen == IREM && lhs.getSpecialKind() == Item.RANDOM_INT)
+ }
+ if (seen == IREM && lhs.getSpecialKind() == Item.RANDOM_INT) {
newValue.setSpecialKind(Item.RANDOM_INT_REMAINDER);
+ }
if (seen == IREM && lhs.checkForIntegerMinValue()) {
if (rhs.getConstant() != null) {
int rhsValue = constantToInt(rhs);
- if (!Util.isPowerOfTwo(rhsValue))
+ if (!Util.isPowerOfTwo(rhsValue)) {
newValue.setSpecialKind(lhs.getSpecialKindForRemainder());
- } else
+ }
+ } else {
newValue.setSpecialKind(lhs.getSpecialKindForRemainder());
+ }
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("push: " + newValue);
+ }
newValue.setPC(dbc.getPC());
push(newValue);
}
@@ -3165,40 +3341,43 @@ public class OpcodeStack implements Constants2 {
long lhsValue = constantToLong(lhs);
if (seen == LSHL) {
newValue = new Item("J", Long.valueOf(lhsValue << constantToInt(rhs)));
- if (constantToInt(rhs) >= 8)
+ if (constantToInt(rhs) >= 8) {
newValue.setSpecialKind(Item.LOW_8_BITS_CLEAR);
- } else if (seen == LSHR)
+ }
+ } else if (seen == LSHR) {
newValue = new Item("J", Long.valueOf(lhsValue >> constantToInt(rhs)));
- else if (seen == LUSHR)
+ } else if (seen == LUSHR) {
newValue = new Item("J", Long.valueOf(lhsValue >>> constantToInt(rhs)));
-
- else {
+ } else {
long rhsValue = constantToLong(rhs);
- if (seen == LADD)
+ if (seen == LADD) {
newValue = new Item("J", Long.valueOf(lhsValue + rhsValue));
- else if (seen == LSUB)
+ } else if (seen == LSUB) {
newValue = new Item("J", Long.valueOf(lhsValue - rhsValue));
- else if (seen == LMUL)
+ } else if (seen == LMUL) {
newValue = new Item("J", Long.valueOf(lhsValue * rhsValue));
- else if (seen == LDIV)
+ } else if (seen == LDIV) {
newValue = new Item("J", Long.valueOf(lhsValue / rhsValue));
- else if (seen == LAND) {
+ } else if (seen == LAND) {
newValue = new Item("J", Long.valueOf(lhsValue & rhsValue));
- if ((rhsValue & 0xff) == 0 && rhsValue != 0 || (lhsValue & 0xff) == 0 && lhsValue != 0)
+ if ((rhsValue & 0xff) == 0 && rhsValue != 0 || (lhsValue & 0xff) == 0 && lhsValue != 0) {
newValue.setSpecialKind(Item.LOW_8_BITS_CLEAR);
- } else if (seen == LOR)
+ }
+ } else if (seen == LOR) {
newValue = new Item("J", Long.valueOf(lhsValue | rhsValue));
- else if (seen == LXOR)
+ } else if (seen == LXOR) {
newValue = new Item("J", Long.valueOf(lhsValue ^ rhsValue));
- else if (seen == LREM)
+ } else if (seen == LREM) {
newValue = new Item("J", Long.valueOf(lhsValue % rhsValue));
+ }
}
- } else if (rhs.getConstant() != null && seen == LSHL && constantToInt(rhs) >= 8)
+ } else if (rhs.getConstant() != null && seen == LSHL && constantToInt(rhs) >= 8) {
newValue.setSpecialKind(Item.LOW_8_BITS_CLEAR);
- else if (lhs.getConstant() != null && seen == LAND && (constantToLong(lhs) & 0xff) == 0)
+ } else if (lhs.getConstant() != null && seen == LAND && (constantToLong(lhs) & 0xff) == 0) {
newValue.setSpecialKind(Item.LOW_8_BITS_CLEAR);
- else if (rhs.getConstant() != null && seen == LAND && (constantToLong(rhs) & 0xff) == 0)
+ } else if (rhs.getConstant() != null && seen == LAND && (constantToLong(rhs) & 0xff) == 0) {
newValue.setSpecialKind(Item.LOW_8_BITS_CLEAR);
+ }
} catch (RuntimeException e) {
// ignore it
}
@@ -3209,22 +3388,24 @@ public class OpcodeStack implements Constants2 {
Item result;
@SpecialKind int specialKind = Item.FLOAT_MATH;
if ((it.getConstant() instanceof Float) && it2.getConstant() instanceof Float) {
- if (seen == FADD)
+ if (seen == FADD) {
result = new Item("F", Float.valueOf(constantToFloat(it2) + constantToFloat(it)));
- else if (seen == FSUB)
+ } else if (seen == FSUB) {
result = new Item("F", Float.valueOf(constantToFloat(it2) - constantToFloat(it)));
- else if (seen == FMUL)
+ } else if (seen == FMUL) {
result = new Item("F", Float.valueOf(constantToFloat(it2) * constantToFloat(it)));
- else if (seen == FDIV)
+ } else if (seen == FDIV) {
result = new Item("F", Float.valueOf(constantToFloat(it2) / constantToFloat(it)));
- else if (seen == FREM)
+ } else if (seen == FREM) {
result = new Item("F", Float.valueOf(constantToFloat(it2) % constantToFloat(it)));
- else
+ } else {
result = new Item("F");
+ }
} else {
result = new Item("F");
- if (seen == DDIV)
+ if (seen == DDIV) {
specialKind = Item.NASTY_FLOAT_MATH;
+ }
}
result.setSpecialKind(specialKind);
push(result);
@@ -3234,22 +3415,25 @@ public class OpcodeStack implements Constants2 {
Item result;
@SpecialKind int specialKind = Item.FLOAT_MATH;
if ((it.getConstant() instanceof Double) && it2.getConstant() instanceof Double) {
- if (seen == DADD)
+ if (seen == DADD) {
result = new Item("D", Double.valueOf(constantToDouble(it2) + constantToDouble(it)));
- else if (seen == DSUB)
+ } else if (seen == DSUB) {
result = new Item("D", Double.valueOf(constantToDouble(it2) - constantToDouble(it)));
- else if (seen == DMUL)
+ } else if (seen == DMUL) {
result = new Item("D", Double.valueOf(constantToDouble(it2) * constantToDouble(it)));
- else if (seen == DDIV)
+ } else if (seen == DDIV) {
result = new Item("D", Double.valueOf(constantToDouble(it2) / constantToDouble(it)));
- else if (seen == DREM)
+ } else if (seen == DREM) {
result = new Item("D", Double.valueOf(constantToDouble(it2) % constantToDouble(it)));
- else
+ }
+ else {
result = new Item("D"); // ?
+ }
} else {
result = new Item("D");
- if (seen == DDIV)
+ if (seen == DDIV) {
specialKind = Item.NASTY_FLOAT_MATH;
+ }
}
result.setSpecialKind(specialKind);
push(result);
@@ -3257,7 +3441,7 @@ public class OpcodeStack implements Constants2 {
private void pushByInvoke(DismantleBytecode dbc, boolean popThis) {
String signature = dbc.getSigConstantOperand();
- if (dbc.getNameConstantOperand().equals("<init>") && signature.endsWith(")V") && popThis) {
+ if ("<init>".equals(dbc.getNameConstantOperand()) && signature.endsWith(")V") && popThis) {
pop(PreorderVisitor.getNumberArguments(signature));
Item constructed = pop();
if (getStackDepth() > 0) {
@@ -3272,7 +3456,7 @@ public class OpcodeStack implements Constants2 {
return;
}
pop(PreorderVisitor.getNumberArguments(signature) + (popThis ? 1 : 0));
- pushBySignature(Type.getReturnType(signature).getSignature(), dbc);
+ pushBySignature(new SignatureParser(signature).getReturnTypeSignature(), dbc);
}
public Item getItemMethodInvokedOn(DismantleBytecode dbc) {
@@ -3295,52 +3479,61 @@ public class OpcodeStack implements Constants2 {
}
private void pushBySignature(String s, DismantleBytecode dbc) {
- if ("V".equals(s))
+ if ("V".equals(s)) {
return;
+ }
Item item = new Item(s, (Object) null);
- if (dbc != null)
+ if (dbc != null) {
item.setPC(dbc.getPC());
- if ("B".equals(s))
+ }
+ if ("B".equals(s)) {
item.setSpecialKind(Item.SIGNED_BYTE);
- else if ("C".equals(s))
+ } else if ("C".equals(s)) {
item.setSpecialKind(Item.NON_NEGATIVE);
+ }
push(item);
}
private void pushByLocalStore(int register) {
Item it = new Item(pop());
if (it.getRegisterNumber() != register) {
- for (Item i : lvValues)
- if (i != null) {
- if (i.registerNumber == register)
- i.registerNumber = -1;
- if (i.fieldLoadedFromRegister == register)
- i.fieldLoadedFromRegister = -1;
- }
- for (Item i : stack)
- if (i != null) {
- if (i.registerNumber == register)
- i.registerNumber = -1;
- if (i.fieldLoadedFromRegister == register)
- i.fieldLoadedFromRegister = -1;
- }
- }
- if (it.registerNumber == -1)
+ clearRegisterLoad(lvValues, register);
+ clearRegisterLoad(stack, register);
+ }
+ if (it.registerNumber == -1) {
it.registerNumber = register;
+ }
setLVValue(register, it);
}
+ private static void clearRegisterLoad(List<Item> list, int register) {
+ for (int pos=0; pos<list.size(); pos++) {
+ Item i = list.get(pos);
+ if(i != null && (i.registerNumber == register || i.fieldLoadedFromRegister == register)) {
+ i = new Item(i);
+ if (i.registerNumber == register) {
+ i.registerNumber = -1;
+ }
+ if (i.fieldLoadedFromRegister == register) {
+ i.fieldLoadedFromRegister = -1;
+ }
+ list.set(pos, i);
+ }
+ }
+ }
+
private void pushByLocalLoad(String signature, int register) {
Item oldItem = new Item(getLVValue(register));
Item newItem = oldItem;
- if (newItem.signature.equals("Ljava/lang/Object;") && !signature.equals("Ljava/lang/Object;")) {
+ if ("Ljava/lang/Object;".equals(newItem.signature) && !"Ljava/lang/Object;".equals(signature)) {
newItem = new Item(oldItem);
newItem.signature = signature;
}
if (newItem.getRegisterNumber() < 0) {
- if (newItem == oldItem)
+ if (newItem == oldItem) {
newItem = new Item(oldItem);
+ }
newItem.registerNumber = register;
}
@@ -3350,20 +3543,25 @@ public class OpcodeStack implements Constants2 {
private void setLVValue(int index, Item value) {
int addCount = index - lvValues.size() + 1;
- while ((addCount--) > 0)
+ while ((addCount--) > 0) {
lvValues.add(null);
- if (!useIterativeAnalysis && seenTransferOfControl)
+ }
+ if (!useIterativeAnalysis && seenTransferOfControl) {
value = Item.merge(value, lvValues.get(index));
+ }
lvValues.set(index, value);
}
+ @Nonnull
public Item getLVValue(int index) {
- if (index >= lvValues.size())
+ if (index >= lvValues.size()) {
return new Item();
+ }
Item item = lvValues.get(index);
- if (item != null)
+ if (item != null) {
return item;
+ }
return new Item();
}
@@ -3372,47 +3570,34 @@ public class OpcodeStack implements Constants2 {
return lvValues.size();
}
- /**
- * @param top
- * The top to set.
- */
private void setTop(boolean top) {
if (top) {
- if (!this.top)
+ if (!this.top) {
this.top = true;
- } else if (this.top)
+ }
+ } else if (this.top) {
this.top = false;
+ }
}
- /**
- * @return Returns the top.
- */
public boolean isTop() {
- if (top)
+ if (top) {
return true;
+ }
return false;
}
- /**
- * @param reachOnlyByBranch
- * The reachOnlyByBranch to set.
- */
void setReachOnlyByBranch(boolean reachOnlyByBranch) {
- if (reachOnlyByBranch)
+ if (reachOnlyByBranch) {
setTop(true);
+ }
this.reachOnlyByBranch = reachOnlyByBranch;
}
- /**
- * @return Returns the reachOnlyByBranch.
- */
boolean isReachOnlyByBranch() {
return reachOnlyByBranch;
}
- /**
- * @return Returns the jumpInfoChangedByBackwardsBranch.
- */
boolean isJumpInfoChangedByBackwardsBranch() {
return jumpInfoChangedByBackwardsBranch;
}
@@ -3421,12 +3606,23 @@ public class OpcodeStack implements Constants2 {
void clearJumpInfoChangedByBackwardsBranch() {
this.jumpInfoChangedByBackwardsBranch = false;
}
- /**
- * @param jumpInfoChangedByBackwardsBranch The jumpInfoChangedByBackwardsBranch to set.
- */
+
void setJumpInfoChangedByBackwardsBranch(int from, int to) {
this.jumpInfoChangedByBackwardsBranch = true;
}
-}
-// vim:ts=4
+ /**
+ * @return Returns the jumpInfoChangedByNewTarget.
+ */
+ protected boolean isJumpInfoChangedByNewTarget() {
+ return jumpInfoChangedByNewTarget;
+ }
+
+ void clearJumpInfoChangedByNewTarget() {
+ this.jumpInfoChangedByNewTarget = false;
+ }
+
+ protected void setJumpInfoChangedByNewTarget() {
+ this.jumpInfoChangedByNewTarget = true;
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/PackageMemberAnnotation.java b/src/java/edu/umd/cs/findbugs/PackageMemberAnnotation.java
index d0f2f75..e19f74a 100644
--- a/src/java/edu/umd/cs/findbugs/PackageMemberAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/PackageMemberAnnotation.java
@@ -55,8 +55,9 @@ public abstract class PackageMemberAnnotation extends BugAnnotationWithSourceLin
private static String computeSourceFile(String className) {
AnalysisContext context = AnalysisContext.currentAnalysisContext();
- if (context != null)
+ if (context != null) {
return context.lookupSourceFile(className);
+ }
return SourceLineAnnotation.UNKNOWN_SOURCE_FILE;
}
@@ -68,16 +69,18 @@ public abstract class PackageMemberAnnotation extends BugAnnotationWithSourceLin
* name of the class
*/
protected PackageMemberAnnotation(@DottedClassName String className, String description, String sourceFileName) {
- if (className.length() == 0)
+ if (className.length() == 0) {
throw new IllegalArgumentException("Empty classname not allowed");
+ }
if (className.indexOf('/') >= 0) {
assert false : "classname " + className + " should be dotted";
- className = className.replace('/', '.');
+ className = className.replace('/', '.');
}
this.className = DescriptorFactory.canonicalizeString(className);
this.sourceFileName = sourceFileName;
- if (description != null)
+ if (description != null) {
description = description.intern();
+ }
this.description = description;
}
@@ -114,10 +117,11 @@ public abstract class PackageMemberAnnotation extends BugAnnotationWithSourceLin
public final @DottedClassName
String getPackageName() {
int lastDot = className.lastIndexOf('.');
- if (lastDot < 0)
+ if (lastDot < 0) {
return "";
- else
+ } else {
return className.substring(0, lastDot);
+ }
}
/**
@@ -129,24 +133,32 @@ public abstract class PackageMemberAnnotation extends BugAnnotationWithSourceLin
* the key
* @return the formatted annotation
*/
+ @Override
public final String format(String key, ClassAnnotation primaryClass) {
- if (key.equals("class.givenClass"))
+ if ("class.givenClass".equals(key)) {
return shorten(primaryClass.getPackageName(), className);
- if (key.equals("simpleClass"))
+ }
+ if ("simpleClass".equals(key)) {
return ClassName.extractSimpleName(className);
- if (key.equals("class"))
+ }
+ if ("class".equals(key)) {
return className;
- if (key.equals("package"))
+ }
+ if ("package".equals(key)) {
return getPackageName();
- if (key.equals("") && FindBugsDisplayFeatures.isAbridgedMessages() && primaryClass != null)
+ }
+ if ("".equals(key) && FindBugsDisplayFeatures.isAbridgedMessages() && primaryClass != null) {
return formatPackageMember("givenClass", primaryClass);
+ }
return formatPackageMember(key, primaryClass);
}
+ @Override
public void setDescription(String description) {
this.description = description.intern();
}
+ @Override
public String getDescription() {
return description;
}
@@ -160,8 +172,9 @@ public abstract class PackageMemberAnnotation extends BugAnnotationWithSourceLin
int index = typeName.lastIndexOf('.');
if (index >= 0) {
String otherPkg = typeName.substring(0, index);
- if (otherPkg.equals(pkgName) || otherPkg.equals("java.lang"))
+ if (otherPkg.equals(pkgName) || "java.lang".equals(otherPkg)) {
typeName = typeName.substring(index + 1);
+ }
}
return typeName;
}
@@ -213,10 +226,10 @@ public abstract class PackageMemberAnnotation extends BugAnnotationWithSourceLin
return format.format(new BugAnnotation[] { this }, primaryClass);
}
+ @Override
public boolean isSignificant() {
return true;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/PackageStats.java b/src/java/edu/umd/cs/findbugs/PackageStats.java
index 2af34cb..df91455 100644
--- a/src/java/edu/umd/cs/findbugs/PackageStats.java
+++ b/src/java/edu/umd/cs/findbugs/PackageStats.java
@@ -44,36 +44,39 @@ import edu.umd.cs.findbugs.xml.XMLWriteable;
class BugCounts {
protected int[] nBugs;
-
+
@OverridingMethodsMustInvokeSuper
public void addError(BugInstance bug) {
ensureNonnullBugCounts();
++nBugs[bug.getPriority()];
++nBugs[0];
}
-
+
protected void ensureNonnullBugCounts() {
- if (nBugs == null)
+ if (nBugs == null) {
nBugs = new int[] { 0, 0, 0, 0, 0 };
-
+ }
+
}
public final int getTotalBugs() {
- if (nBugs == null)
+ if (nBugs == null) {
return 0;
+ }
return nBugs[0];
}
public final int getBugsAtPriority(int p) {
- if (nBugs == null)
+ if (nBugs == null) {
return 0;
+ }
return nBugs[p];
}
-
+
public void clearBugCounts() {
nBugs = null;
}
-
+
/**
* Add priority attributes to a started tag. Each priority at offset n,
* where n > 0, is output using attribute priority_n if the value at
@@ -82,13 +85,11 @@ class BugCounts {
* @param xmlOutput
* an output stream for which startTag has been called but
* stopTag has not.
- * @param bugs
- * an array for which the element at offset n is the number of
- * bugs for priority n.
*/
public void writeBugPriorities(XMLOutput xmlOutput) throws IOException {
- if (nBugs == null)
+ if (nBugs == null) {
return;
+ }
writeBugPriorities(xmlOutput, nBugs);
}
public static void writeBugPriorities(XMLOutput xmlOutput, @Nonnull int nBugs[]) throws IOException {
@@ -103,7 +104,7 @@ class BugCounts {
public class PackageStats extends BugCounts implements XMLWriteable {
-
+
public static class ClassStats extends BugCounts implements XMLWriteable, Cloneable {
private final String name;
@@ -149,14 +150,17 @@ public class PackageStats extends BugCounts implements XMLWriteable {
return sourceFile;
}
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
- if (size == 0)
+ if (size == 0) {
return;
+ }
xmlOutput.startTag("ClassStats");
xmlOutput.addAttribute("class", name);
- if (sourceFile != null)
+ if (sourceFile != null) {
xmlOutput.addAttribute("sourceFile", sourceFile);
+ }
xmlOutput.addAttribute("interface", String.valueOf(isInterface));
xmlOutput.addAttribute("size", String.valueOf(size));
xmlOutput.addAttribute("bugs", String.valueOf(getTotalBugs()));
@@ -168,7 +172,7 @@ public class PackageStats extends BugCounts implements XMLWriteable {
/**
*
*/
-
+
}
public static final String ELEMENT_NAME = "PackageStats";
@@ -190,7 +194,7 @@ public class PackageStats extends BugCounts implements XMLWriteable {
// LinkedList<BugInstance>();
// all classes and interfaces in this package
- private Map<String, ClassStats> packageMembers = new HashMap<String, ClassStats>(5);
+ private final Map<String, ClassStats> packageMembers = new HashMap<String, ClassStats>(5);
public PackageStats(String packageName) {
this.packageName = packageName;
@@ -261,8 +265,9 @@ public class PackageStats extends BugCounts implements XMLWriteable {
this.numClasses = 0;
}
packageMembers.put(classStats.getName(), classStats);
- if (updatePackageStats)
+ if (updatePackageStats) {
size += classStats.size();
+ }
}
public String getPackageName() {
@@ -277,17 +282,20 @@ public class PackageStats extends BugCounts implements XMLWriteable {
this.numClasses = numClasses;
}
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
- if (size == 0)
+ if (size == 0) {
return;
+ }
xmlOutput.startTag(ELEMENT_NAME);
xmlOutput.addAttribute("package", packageName);
xmlOutput.addAttribute("total_bugs", String.valueOf(getTotalBugs()));
int numClasses = packageMembers.size();
- if (numClasses == 0)
+ if (numClasses == 0) {
numClasses = this.numClasses;
+ }
xmlOutput.addAttribute("total_types", String.valueOf(numClasses));
xmlOutput.addAttribute("total_size", String.valueOf(size));
writeBugPriorities(xmlOutput);
@@ -307,7 +315,7 @@ public class PackageStats extends BugCounts implements XMLWriteable {
}
-
+
public void recomputeFromClassStats() {
super.clearBugCounts();
@@ -315,8 +323,9 @@ public class PackageStats extends BugCounts implements XMLWriteable {
numClasses = packageMembers.size();
ensureNonnullBugCounts();
for (ClassStats classStats : packageMembers.values()) {
- for (int i = 0; i < nBugs.length; i++)
+ for (int i = 0; i < nBugs.length; i++) {
nBugs[i] += classStats.getBugsAtPriority(i);
+ }
size += classStats.size;
}
}
@@ -340,10 +349,10 @@ public class PackageStats extends BugCounts implements XMLWriteable {
public void purgeClassesThatDontMatch(Pattern classPattern) {
for (Iterator<Map.Entry<String, ClassStats>> i = packageMembers.entrySet().iterator(); i.hasNext();) {
Map.Entry<String, ClassStats> e = i.next();
- if (!classPattern.matcher(e.getKey()).find())
+ if (!classPattern.matcher(e.getKey()).find()) {
i.remove();
+ }
}
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/PackageWarningSuppressor.java b/src/java/edu/umd/cs/findbugs/PackageWarningSuppressor.java
index f311097..526d576 100644
--- a/src/java/edu/umd/cs/findbugs/PackageWarningSuppressor.java
+++ b/src/java/edu/umd/cs/findbugs/PackageWarningSuppressor.java
@@ -16,12 +16,14 @@ public class PackageWarningSuppressor extends WarningSuppressor {
@Override
public boolean match(BugInstance bugInstance) {
- if (!super.match(bugInstance))
+ if (!super.match(bugInstance)) {
return false;
+ }
ClassAnnotation primaryClassAnnotation = bugInstance.getPrimaryClass();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Compare " + primaryClassAnnotation + " with " + packageName);
+ }
String className = primaryClassAnnotation.getClassName();
diff --git a/src/java/edu/umd/cs/findbugs/ParameterWarningSuppressor.java b/src/java/edu/umd/cs/findbugs/ParameterWarningSuppressor.java
index 3590d68..96c2a37 100644
--- a/src/java/edu/umd/cs/findbugs/ParameterWarningSuppressor.java
+++ b/src/java/edu/umd/cs/findbugs/ParameterWarningSuppressor.java
@@ -15,17 +15,21 @@ public class ParameterWarningSuppressor extends ClassWarningSuppressor {
@Override
public boolean match(BugInstance bugInstance) {
- if (!super.match(bugInstance))
+ if (!super.match(bugInstance)) {
return false;
+ }
MethodAnnotation bugMethod = bugInstance.getPrimaryMethod();
LocalVariableAnnotation localVariable = bugInstance.getPrimaryLocalVariableAnnotation();
- if (bugMethod == null || !method.equals(bugMethod))
+ if (bugMethod == null || !method.equals(bugMethod)) {
return false;
- if (localVariable == null || localVariable.getRegister() != register)
+ }
+ if (localVariable == null || localVariable.getRegister() != register) {
return false;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("Suppressing " + bugInstance);
+ }
return true;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/Plugin.java b/src/java/edu/umd/cs/findbugs/Plugin.java
index f65ee86..2a8d66b 100644
--- a/src/java/edu/umd/cs/findbugs/Plugin.java
+++ b/src/java/edu/umd/cs/findbugs/Plugin.java
@@ -58,6 +58,7 @@ public class Plugin {
private static final String USE_FINDBUGS_VERSION = "USE_FINDBUGS_VERSION";
+ static Map<URI, Plugin> allPlugins = new LinkedHashMap<URI, Plugin>();
private final String pluginId;
private final String version;
@@ -81,7 +82,7 @@ public class Plugin {
private final LinkedHashMap<String, BugCategory> bugCategories;
private final LinkedHashSet<CloudPlugin> cloudList;
- private final HashMap<String,String> myGlobalOptions = new HashMap<String, String>();
+ private final HashMap<String,String> myGlobalOptions;
private final DualKeyHashMap<Class<?>, String, ComponentPlugin<?>> componentPlugins;
@@ -102,31 +103,26 @@ public class Plugin {
private final boolean cannotDisable;
- static Map<URI, Plugin> allPlugins = new LinkedHashMap<URI, Plugin>();
-
- enum EnabledState { PLUGIN_DEFAULT, ENABLED, DISABLED}
+ static enum EnabledState { PLUGIN_DEFAULT, ENABLED, DISABLED }
private EnabledState enabled;
-
/**
* Constructor. Creates an empty plugin object.
*
* @param pluginId
* the plugin's unique identifier
- * @param version TODO
- * @param enabled TODO
- * @param cannotDisable TODO
*/
public Plugin(String pluginId, String version, Date releaseDate, @Nonnull PluginLoader pluginLoader, boolean enabled, boolean cannotDisable) {
this.pluginId = pluginId;
if (version == null) {
version = "";
- } else if (version.equals(USE_FINDBUGS_VERSION)) {
+ } else if (USE_FINDBUGS_VERSION.equals(version)) {
version = Version.COMPUTED_RELEASE;
releaseDate = Version.getReleaseDate();
}
assert enabled || !cannotDisable;
+ myGlobalOptions = new HashMap<String, String>();
cloudList = new LinkedHashSet<CloudPlugin>();
componentPlugins = new DualKeyHashMap<Class<?>, String, ComponentPlugin<?>> ();
this.version = version;
@@ -177,7 +173,6 @@ public class Plugin {
return provider;
}
-
public void setUpdateUrl(String url) throws URISyntaxException {
this.updateUrl = new URI(url);
}
@@ -193,6 +188,7 @@ public class Plugin {
Map<String,String> getMyGlobalOptions() {
return Collections.unmodifiableMap(myGlobalOptions);
}
+
/**
* Set plugin website.
*
@@ -210,8 +206,9 @@ public class Plugin {
* @return the website, or null if the was not specified
*/
public @CheckForNull String getWebsite() {
- if (website == null)
+ if (website == null) {
return null;
+ }
return website.toASCIIString();
}
@@ -282,20 +279,22 @@ public class Plugin {
*/
public void addBugCategory(BugCategory bugCategory) {
BugCategory old = bugCategories.get(bugCategory.getCategory());
- if (old != null)
+ if (old != null) {
throw new IllegalArgumentException("Category already exists");
+ }
bugCategories.put(bugCategory.getCategory(), bugCategory);
}
-
public BugCategory addOrCreateBugCategory(String id) {
BugCategory c = bugCategories.get(id);
- if (c != null)
+ if (c != null) {
return c;
+ }
c = new BugCategory(id);
bugCategories.put(id, c);
return c;
}
+
/**
* Add an inter-pass Detector ordering constraint.
*
@@ -325,6 +324,7 @@ public class Plugin {
*/
public DetectorFactory getFactoryByShortName(final String shortName) {
return findFirstMatchingFactory(new FactoryChooser() {
+ @Override
public boolean choose(DetectorFactory factory) {
return factory.getShortName().equals(shortName);
}
@@ -340,6 +340,7 @@ public class Plugin {
*/
public DetectorFactory getFactoryByFullName(final String fullName) {
return findFirstMatchingFactory(new FactoryChooser() {
+ @Override
public boolean choose(DetectorFactory factory) {
return factory.getFullName().equals(fullName);
}
@@ -371,6 +372,7 @@ public class Plugin {
public Set<BugCode> getBugCodes() {
return bugCodeList;
}
+
/**
* Get Iterator over BugCategories objects in the Plugin.
*
@@ -392,6 +394,7 @@ public class Plugin {
public Set<CloudPlugin> getCloudPlugins() {
return cloudList;
}
+
/**
* Return an Iterator over the inter-pass Detector ordering constraints.
*/
@@ -406,15 +409,10 @@ public class Plugin {
return intraPassConstraintList.iterator();
}
- /**
- * @return Returns the pluginId.
- */
public String getPluginId() {
return pluginId;
}
- /**
- * @return Returns the short pluginId.
- */
+
public String getShortPluginId() {
int i = pluginId.lastIndexOf('.');
return pluginId.substring(i+1);
@@ -440,9 +438,6 @@ public class Plugin {
return engineRegistrarClass;
}
- /**
- * @return Returns the pluginLoader.
- */
public PluginLoader getPluginLoader() {
return pluginLoader;
}
@@ -454,15 +449,13 @@ public class Plugin {
private @CheckForNull
DetectorFactory findFirstMatchingFactory(FactoryChooser chooser) {
for (DetectorFactory factory : getDetectorFactories()) {
- if (chooser.choose(factory))
+ if (chooser.choose(factory)) {
return factory;
+ }
}
return null;
}
- /**
- * @param ranker
- */
public void setBugRanker(BugRanker ranker) {
this.bugRanker = ranker;
}
@@ -489,8 +482,9 @@ public class Plugin {
<T> void addComponentPlugin(Class<T> componentKind, ComponentPlugin<T> plugin) {
Class<? extends T> componentClass = plugin.getComponentClass();
- if (componentClass != null && !componentKind.isAssignableFrom(componentClass))
- throw new IllegalArgumentException();
+ if (componentClass != null && !componentKind.isAssignableFrom(componentClass)) {
+ throw new IllegalArgumentException();
+ }
componentPlugins.put(componentKind, plugin.getId(), plugin);
}
@@ -512,14 +506,15 @@ public class Plugin {
}
for(Plugin plugin : allPlugins.values()) {
// the second part is questionable, as this may lead to id collisions
- if (name.equals(plugin.getPluginId()) /*|| name.equals(plugin.getShortPluginId())*/)
+ if (name.equals(plugin.getPluginId()) /*|| name.equals(plugin.getShortPluginId())*/) {
return plugin;
+ }
}
return null;
}
public static synchronized void removePlugin(URI uri) {
- allPlugins.remove(uri);
+ allPlugins.remove(uri);
}
/**
@@ -530,11 +525,13 @@ public class Plugin {
}
public static synchronized Collection<String> getAllPluginIds() {
- ArrayList<String> result = new ArrayList<String>();
- for(Plugin p : allPlugins.values())
- result.add(p.getPluginId());
- return result;
+ ArrayList<String> result = new ArrayList<String>();
+ for(Plugin p : allPlugins.values()) {
+ result.add(p.getPluginId());
+ }
+ return result;
}
+
/**
* @return a copy of the internal plugins collection
*/
@@ -549,9 +546,7 @@ public class Plugin {
try {
URI uri = plugin.getPluginLoader().getURL().toURI();
- if(uri != null) {
- uris.add(uri);
- }
+ uris.add(uri);
} catch (URISyntaxException e) {
AnalysisContext.logError("Unable to get URI", e);
}
@@ -585,8 +580,9 @@ public class Plugin {
}
public boolean isGloballyEnabled() {
- if (isCorePlugin())
+ if (isCorePlugin()) {
return true;
+ }
switch (enabled) {
case ENABLED:
return true;
@@ -601,30 +597,35 @@ public class Plugin {
public void setGloballyEnabled(boolean enabled) {
if (isCorePlugin()) {
- if (!enabled)
+ if (!enabled) {
throw new IllegalArgumentException("Can't disable core plugin");
+ }
return;
}
if (cannotDisable) {
- if (enabled) return;
+ if (enabled) {
+ return;
+ }
throw new IllegalArgumentException("Cannot disable " + pluginId);
}
- EnabledState oldState = this.enabled;
+ // EnabledState oldState = this.enabled;
if (enabled) {
- if (isEnabledByDefault())
+ if (isEnabledByDefault()) {
this.enabled = EnabledState.PLUGIN_DEFAULT;
- else
+ } else {
this.enabled = EnabledState.ENABLED;
+ }
} else {
- if (isEnabledByDefault())
+ if (isEnabledByDefault()) {
this.enabled = EnabledState.DISABLED;
- else
+ } else {
this.enabled = EnabledState.PLUGIN_DEFAULT;
+ }
}
- if(oldState != this.enabled) {
- // TODO update detector factory collection?
- }
+ // if(oldState != this.enabled) {
+ // TODO update detector factory collection?
+ // }
}
public boolean isInitialPlugin() {
@@ -640,8 +641,9 @@ public class Plugin {
}
public @CheckForNull Plugin getParentPlugin() {
- if (getPluginLoader().hasParent())
+ if (getPluginLoader().hasParent()) {
return Plugin.getByPluginId(getPluginLoader().parentId);
+ }
return null;
}
@@ -673,15 +675,17 @@ public class Plugin {
public static @CheckForNull Plugin addCustomPlugin(URL u) throws PluginException {
return addCustomPlugin(u, PluginLoader.class.getClassLoader());
}
+
public static @CheckForNull Plugin addCustomPlugin(URI u) throws PluginException {
return addCustomPlugin(u, PluginLoader.class.getClassLoader());
}
+
public static @CheckForNull Plugin addCustomPlugin(URL u, ClassLoader parent) throws PluginException {
PluginLoader pluginLoader = PluginLoader.getPluginLoader(u, parent, false, true);
Plugin plugin = pluginLoader.loadPlugin();
- if (plugin != null)
+ if (plugin != null) {
DetectorFactoryCollection.instance().loadPlugin(plugin);
-
+ }
return plugin;
}
@@ -694,6 +698,7 @@ public class Plugin {
}
return addCustomPlugin(url, parent);
}
+
public static synchronized void removeCustomPlugin(Plugin plugin) {
Set<Entry<URI, Plugin>> entrySet = Plugin.allPlugins.entrySet();
for (Entry<URI, Plugin> entry : entrySet) {
diff --git a/src/java/edu/umd/cs/findbugs/PluginException.java b/src/java/edu/umd/cs/findbugs/PluginException.java
index 4735fc1..0d8f974 100644
--- a/src/java/edu/umd/cs/findbugs/PluginException.java
+++ b/src/java/edu/umd/cs/findbugs/PluginException.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs;
/**
* An exception to indicate that a plugin could not be loaded.
- *
+ *
* @author David Hovemeyer
* @see PluginLoader
*/
@@ -33,7 +33,7 @@ public class PluginException extends Exception {
/**
* Constructor.
- *
+ *
* @param msg
* message describing the exception
*/
@@ -43,7 +43,7 @@ public class PluginException extends Exception {
/**
* Constructor.
- *
+ *
* @param msg
* message describing the exception
* @param cause
@@ -54,4 +54,3 @@ public class PluginException extends Exception {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/PluginLoader.java b/src/java/edu/umd/cs/findbugs/PluginLoader.java
index 4c95744..efc3fdb 100644
--- a/src/java/edu/umd/cs/findbugs/PluginLoader.java
+++ b/src/java/edu/umd/cs/findbugs/PluginLoader.java
@@ -212,8 +212,9 @@ public class PluginLoader {
if (!hasParent()) {
classLoader = new URLClassLoader(loaderURLs, parent);
} else {
- if (parent != PluginLoader.class.getClassLoader())
+ if (parent != PluginLoader.class.getClassLoader()) {
throw new IllegalArgumentException("Can't specify parentid " + parentId + " and provide a seperate class loader");
+ }
Plugin parentPlugin = Plugin.getByPluginId(parentId);
if (parentPlugin != null) {
parent = parentPlugin.getClassLoader();
@@ -221,8 +222,9 @@ public class PluginLoader {
}
}
if (classLoader == null) {
- if (!lazyInitialization)
+ if (!lazyInitialization) {
throw new IllegalStateException("Can't find parent plugin " + parentId);
+ }
partiallyInitialized.add(this);
} else {
loadPluginComponents();
@@ -231,8 +233,9 @@ public class PluginLoader {
}
private static void finishLazyInitialization() {
- if (!lazyInitialization)
+ if (!lazyInitialization) {
throw new IllegalStateException("Not in lazy initialization mode");
+ }
while (!partiallyInitialized.isEmpty()) {
boolean changed = false;
LinkedList<String> unresolved = new LinkedList<String>();
@@ -345,7 +348,7 @@ public class PluginLoader {
String classPath = atts.getValue(Attributes.Name.CLASS_PATH);
if (classPath != null) {
String jarRoot = url.toString();
- jarRoot = jarRoot.substring(0, jarRoot.lastIndexOf("/") + 1);
+ jarRoot = jarRoot.substring(0, jarRoot.lastIndexOf('/') + 1);
String[] jars = classPath.split(",");
for (String jar : jars) {
jar = jarRoot + jar.trim();
@@ -424,8 +427,9 @@ public class PluginLoader {
URL from;
String findBugsClassFile = ClassName.toSlashedClassName(FindBugs.class) + ".class";
URL me = FindBugs.class.getClassLoader().getResource(findBugsClassFile);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("FindBugs.class loaded from " + me);
+ }
if(me == null) {
throw new IllegalStateException("Failed to load " + findBugsClassFile);
}
@@ -446,8 +450,9 @@ public class PluginLoader {
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Failed to parse url: " + me);
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Core class files loaded from " + from);
+ }
return from;
}
@@ -469,14 +474,15 @@ public class PluginLoader {
private static String getJarName(URL url) {
String location = url.getPath();
- int i = location.lastIndexOf("/");
+ int i = location.lastIndexOf('/');
location = location.substring(i + 1);
return location;
}
public ClassLoader getClassLoader() {
- if (classLoader == null)
+ if (classLoader == null) {
throw new IllegalStateException("Plugin not completely initialized; classloader not set yet");
+ }
return classLoader;
}
@@ -491,8 +497,9 @@ public class PluginLoader {
}
public Plugin getPlugin() {
- if (plugin == null)
+ if (plugin == null) {
throw new AssertionError("plugin not already loaded");
+ }
return plugin;
}
@@ -524,8 +531,9 @@ public class PluginLoader {
public URL getResource(String name) {
if (isCorePlugin()) {
URL url = getCoreResource(name);
- if (url != null && IO.verifyURL(url))
+ if (url != null && IO.verifyURL(url)) {
return url;
+ }
}
if (loadedFrom != null) {
try {
@@ -533,8 +541,9 @@ public class PluginLoader {
if (DEBUG) {
System.out.println("Trying to load " + name + " from " + url);
}
- if (IO.verifyURL(url))
+ if (IO.verifyURL(url)) {
return url;
+ }
} catch (MalformedURLException e) {
assert true;
}
@@ -549,20 +558,24 @@ public class PluginLoader {
System.out.println(" from urls: " + Arrays.asList(urlClassLoader.getURLs()));
}
URL url = urlClassLoader.findResource(name);
- if (url == null)
+ if (url == null) {
url = urlClassLoader.findResource("/" + name);
- if (IO.verifyURL(url))
+ }
+ if (IO.verifyURL(url)) {
return url;
+ }
}
if (DEBUG) {
System.out.println("Trying to load " + name + " using ClassLoader.getResource");
}
URL url = classLoaderForResources.getResource(name);
- if (url == null)
+ if (url == null) {
url = classLoaderForResources.getResource("/" + name);
- if (IO.verifyURL(url))
+ }
+ if (IO.verifyURL(url)) {
return url;
+ }
return null;
}
@@ -570,14 +583,17 @@ public class PluginLoader {
static @CheckForNull
URL getCoreResource(String name) {
URL u = loadFromFindBugsPluginDir(name);
- if (u != null)
+ if (u != null) {
return u;
+ }
u = loadFromFindBugsEtcDir(name);
- if (u != null)
+ if (u != null) {
return u;
+ }
u = PluginLoader.class.getResource(name);
- if (u != null)
+ if (u != null) {
return u;
+ }
u = PluginLoader.class.getResource("/"+name);
return u;
}
@@ -629,8 +645,9 @@ public class PluginLoader {
}
private Plugin init() throws PluginException {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Loading plugin from " + loadedFrom);
+ }
// Plugin descriptor (a.k.a, "findbugs.xml"). Defines
// the bug detectors and bug patterns that the plugin provides.
Document pluginDescriptor = getPluginDescriptor();
@@ -639,8 +656,9 @@ public class PluginLoader {
Plugin constructedPlugin = constructMinimalPlugin(pluginDescriptor, messageCollectionList);
// Success!
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Loaded " + constructedPlugin.getPluginId() + " from " + loadedFrom);
+ }
return constructedPlugin;
}
@@ -657,8 +675,9 @@ public class PluginLoader {
boolean onlineStorage = Boolean.valueOf(cloudNode.valueOf("@onlineStorage"));
String propertiesLocation = cloudNode.valueOf("@properties");
boolean disabled = Boolean.valueOf(cloudNode.valueOf("@disabled")) && !cloudId.equals(CloudFactory.DEFAULT_CLOUD);
- if (disabled)
+ if (disabled) {
continue;
+ }
boolean hidden = Boolean.valueOf(cloudNode.valueOf("@hidden")) && !cloudId.equals(CloudFactory.DEFAULT_CLOUD);
Class<? extends Cloud> cloudClass = getClass(classLoader, cloudClassname, Cloud.class);
@@ -671,8 +690,9 @@ public class PluginLoader {
PropertyBundle properties = new PropertyBundle();
if (propertiesLocation != null && propertiesLocation.length() > 0) {
URL properiesURL = classLoader.getResource(propertiesLocation);
- if (properiesURL == null)
+ if (properiesURL == null) {
continue;
+ }
properties.loadPropertiesFromURL(properiesURL);
}
List<Node> propertyNodes = XMLUtil.selectNodes(cloudNode, "Property");
@@ -703,8 +723,10 @@ public class PluginLoader {
+ " loaded from " + loadedFrom);
}
String componentId = componentNode.valueOf("@id");
- if (componentId == null) throw new PluginException("Missing @id for " + plugin.getPluginId()
- + " loaded from " + loadedFrom);
+ if (componentId == null) {
+ throw new PluginException("Missing @id for " + plugin.getPluginId()
+ + " loaded from " + loadedFrom);
+ }
try {
String propertiesLocation = componentNode.valueOf("@properties");
@@ -800,7 +822,7 @@ public class PluginLoader {
throw new PluginException("Class " + className + " does not implement Detector or Detector2");
}
}
- DetectorFactory factory = new DetectorFactory(plugin, className, detectorClass, !disabled.equals("true"), speed,
+ DetectorFactory factory = new DetectorFactory(plugin, className, detectorClass, !"true".equals(disabled), speed,
reports, requireJRE);
if (Boolean.valueOf(hidden).booleanValue()) {
factory.setHidden(true);
@@ -844,7 +866,7 @@ public class PluginLoader {
constraint.setSingleSource(earlierSelector instanceof SingleDetectorFactorySelector);
// Add the constraint to the plugin
- if (constraintElement.getName().equals("SplitPass")) {
+ if ("SplitPass".equals(constraintElement.getName())) {
plugin.addInterPassOrderingConstraint(constraint);
} else {
plugin.addIntraPassOrderingConstraint(constraint);
@@ -857,7 +879,7 @@ public class PluginLoader {
List<Node> categoryNodeListGlobal = XMLUtil.selectNodes(pluginDescriptor, "/FindbugsPlugin/BugCategory");
for(Node categoryNode : categoryNodeListGlobal) {
String key = categoryNode.valueOf("@category");
- if (key.equals("")) {
+ if ("".equals(key)) {
throw new PluginException("BugCategory element with missing category attribute");
}
BugCategory bc = plugin.addOrCreateBugCategory(key);
@@ -871,11 +893,12 @@ public class PluginLoader {
for (Document messageCollection : messageCollectionList) {
List<Node> categoryNodeList = XMLUtil.selectNodes(messageCollection, "/MessageCollection/BugCategory");
- if (DEBUG)
+ if (DEBUG) {
System.out.println("found " + categoryNodeList.size() + " categories in " + plugin.getPluginId());
+ }
for (Node categoryNode : categoryNodeList) {
String key = categoryNode.valueOf("@category");
- if (key.equals("")) {
+ if ("".equals(key)) {
throw new PluginException("BugCategory element with missing category attribute");
}
BugCategory bc = plugin.addOrCreateBugCategory(key);
@@ -885,25 +908,31 @@ public class PluginLoader {
String abbrev = getChildText(categoryNode, "Abbreviation");
if (bc.getAbbrev() == null) {
bc.setAbbrev(abbrev);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("category " + key + " abbrev -> " + abbrev);
- } else if (DEBUG)
+ }
+ } else if (DEBUG) {
System.out.println("rejected abbrev '" + abbrev + "' for category " + key + ": " + bc.getAbbrev());
+ }
} catch (PluginException pe) {
if (DEBUG)
+ {
System.out.println("missing Abbreviation for category " + key + "/" + shortDesc);
- // do nothing else -- Abbreviation is required, but handle
- // its omission gracefully
+ // do nothing else -- Abbreviation is required, but handle
+ // its omission gracefully
+ }
}
try {
String details = getChildText(categoryNode, "Details");
if (bc.getDetailText() == null) {
bc.setDetailText(details);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("category " + key + " details -> " + details);
- } else if (DEBUG)
+ }
+ } else if (DEBUG) {
System.out.println("rejected details [" + details + "] for category " + key + ": [" + bc.getDetailText()
+ ']');
+ }
} catch (PluginException pe) {
// do nothing -- LongDescription is optional
}
@@ -917,12 +946,15 @@ public class PluginLoader {
String type = bugPatternNode.valueOf("@type");
String abbrev = bugPatternNode.valueOf("@abbrev");
String category = bugPatternNode.valueOf("@category");
- String experimental = bugPatternNode.valueOf("@experimental");
+ boolean experimental = Boolean.parseBoolean(bugPatternNode.valueOf("@experimental"));
// Find the matching element in messages.xml (or translations)
String query = "/MessageCollection/BugPattern[@type='" + type + "']";
Node messageNode = findMessageNode(messageCollectionList, query, "messages.xml missing BugPattern element for type "
+ type);
+ Node bugsUrlNode = messageNode.getDocument().selectSingleNode("/MessageCollection/Plugin/"+(experimental?"AllBugsUrl":"BugsUrl"));
+
+ String bugsUrl = bugsUrlNode == null ? null : bugsUrlNode.getText();
String shortDesc = getChildText(messageNode, "ShortDescription");
String longDesc = getChildText(messageNode, "LongDescription");
@@ -930,14 +962,14 @@ public class PluginLoader {
int cweid = 0;
try {
String cweString = bugPatternNode.valueOf("@cweid");
- if (cweString.length() > 0)
+ if (cweString.length() > 0) {
cweid = Integer.parseInt(cweString);
+ }
} catch (RuntimeException e) {
assert true; // ignore
}
- BugPattern bugPattern = new BugPattern(type, abbrev, category, Boolean.valueOf(experimental).booleanValue(),
- shortDesc, longDesc, detailText, cweid);
+ BugPattern bugPattern = new BugPattern(type, abbrev, category, experimental, shortDesc, longDesc, detailText, bugsUrl, cweid);
try {
String deprecatedStr = bugPatternNode.valueOf("@deprecated");
@@ -959,7 +991,7 @@ public class PluginLoader {
List<Node> bugCodeNodeList = XMLUtil.selectNodes(messageCollection, "/MessageCollection/BugCode");
for (Node bugCodeNode : bugCodeNodeList) {
String abbrev = bugCodeNode.valueOf("@abbrev");
- if (abbrev.equals("")) {
+ if ("".equals(abbrev)) {
throw new PluginException("BugCode element with missing abbrev attribute");
}
if (definedBugCodes.contains(abbrev)) {
@@ -970,12 +1002,13 @@ public class PluginLoader {
String query = "/FindbugsPlugin/BugCode[@abbrev='" + abbrev + "']";
Node fbNode = pluginDescriptor.selectSingleNode(query);
int cweid = 0;
- if (fbNode != null)
+ if (fbNode != null) {
try {
cweid = Integer.parseInt(fbNode.valueOf("@cweid"));
} catch (RuntimeException e) {
assert true; // ignore
}
+ }
BugCode bugCode = new BugCode(abbrev, description, cweid);
plugin.addBugCode(bugCode);
definedBugCodes.add(abbrev);
@@ -1012,8 +1045,9 @@ public class PluginLoader {
// https://sourceforge.net/tracker/?func=detail&aid=2816102&group_id=96405&atid=614693
// plugin can not have bugrank.txt. In this case, an empty
// bugranker will be created
- if (DEBUG)
+ if (DEBUG) {
System.out.println("No " + BugRanker.FILENAME + " for plugin " + plugin.getPluginId());
+ }
}
BugRanker ranker = new BugRanker(bugRankURL);
plugin.setBugRanker(ranker);
@@ -1027,7 +1061,7 @@ public class PluginLoader {
// Get the unique plugin id (or generate one, if none is present)
// Unique plugin id
String pluginId = pluginDescriptor.valueOf(XPATH_PLUGIN_PLUGINID);
- if (pluginId.equals("")) {
+ if ("".equals(pluginId)) {
synchronized (PluginLoader.class) {
pluginId = "plugin" + nextUnknownId++;
}
@@ -1035,7 +1069,7 @@ public class PluginLoader {
cannotDisable = Boolean.parseBoolean(pluginDescriptor.valueOf("/FindbugsPlugin/@cannotDisable"));
String de = pluginDescriptor.valueOf("/FindbugsPlugin/@defaultenabled");
- if (de != null && de.toLowerCase().trim().equals("false")) {
+ if (de != null && "false".equals(de.toLowerCase().trim())) {
optionalPlugin = true;
}
if (optionalPlugin) {
@@ -1065,11 +1099,11 @@ public class PluginLoader {
Plugin constructedPlugin = new Plugin(pluginId, version, parsedDate, this, !optionalPlugin, cannotDisable);
// Set provider and website, if specified
String provider = pluginDescriptor.valueOf(XPATH_PLUGIN_PROVIDER).trim();
- if (!provider.equals("")) {
+ if (!"".equals(provider)) {
constructedPlugin.setProvider(provider);
}
String website = pluginDescriptor.valueOf(XPATH_PLUGIN_WEBSITE).trim();
- if (!website.equals("")) {
+ if (!"".equals(website)) {
try {
constructedPlugin.setWebsite(website);
} catch (URISyntaxException e1) {
@@ -1078,7 +1112,7 @@ public class PluginLoader {
}
String updateUrl = pluginDescriptor.valueOf("/FindbugsPlugin/@update-url").trim();
- if (!updateUrl.equals("")) {
+ if (!"".equals(updateUrl)) {
try {
constructedPlugin.setUpdateUrl(updateUrl);
} catch (URISyntaxException e1) {
@@ -1125,8 +1159,9 @@ public class PluginLoader {
if (findbugsXML_URL == null) {
throw new PluginException("Couldn't find \"" + name + "\" in plugin " + this);
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("PluginLoader found " + name + " at: " + findbugsXML_URL);
+ }
if (jarName != null && !findbugsXML_URL.toString().contains(jarName)
&& !(corePlugin && findbugsXML_URL.toString().endsWith("etc/findbugs.xml"))) {
@@ -1160,8 +1195,9 @@ public class PluginLoader {
String country = locale.getCountry();
List<String> potential = new ArrayList<String>(3);
- if (country != null)
+ if (country != null) {
potential.add("messages_" + language + "_" + country + ".xml");
+ }
potential.add("messages_" + language + ".xml");
potential.add("messages.xml");
return potential;
@@ -1171,7 +1207,7 @@ public class PluginLoader {
// List of message translation files in decreasing order of precedence
ArrayList<Document> messageCollectionList = new ArrayList<Document>();
PluginException caught = null;
- for (String m : getPotentialMessageFiles())
+ for (String m : getPotentialMessageFiles()) {
try {
addCollection(messageCollectionList, m);
} catch (PluginException e) {
@@ -1179,6 +1215,7 @@ public class PluginLoader {
AnalysisContext.logError(
"Error loading localized message file:" + m, e);
}
+ }
if (messageCollectionList.isEmpty()) {
if (caught != null) {
throw caught;
@@ -1189,7 +1226,7 @@ public class PluginLoader {
}
- private <T> void loadComponentPlugin(@SuppressWarnings("hiding") Plugin plugin,
+ private <T> void loadComponentPlugin(Plugin plugin,
Class<T> componentKind, @DottedClassName String componentClassname, String filterId,
boolean disabled, String description, String details, PropertyBundle properties) throws PluginException {
Class<? extends T> componentClass = null;
@@ -1232,12 +1269,12 @@ public class PluginLoader {
boolean spanPlugins = Boolean.valueOf(node.valueOf("@spanplugins")).booleanValue();
String categoryName = node.valueOf("@name");
- if (!categoryName.equals("")) {
- if (categoryName.equals("reporting")) {
+ if (!"".equals(categoryName)) {
+ if ("reporting".equals(categoryName)) {
return new ReportingDetectorFactorySelector(spanPlugins ? null : plugin);
- } else if (categoryName.equals("training")) {
+ } else if ("training".equals(categoryName)) {
return new ByInterfaceDetectorFactorySelector(spanPlugins ? null : plugin, TrainingDetector.class);
- } else if (categoryName.equals("interprocedural")) {
+ } else if ("interprocedural".equals(categoryName)) {
return new ByInterfaceDetectorFactorySelector(spanPlugins ? null : plugin,
InterproceduralFirstPassDetector.class);
} else {
@@ -1251,7 +1288,7 @@ public class PluginLoader {
boolean spanPlugins = Boolean.valueOf(node.valueOf("@spanplugins")).booleanValue();
String superName = node.valueOf("@super");
- if (!superName.equals("")) {
+ if (!"".equals(superName)) {
try {
Class<?> superClass = Class.forName(superName);
return new ByInterfaceDetectorFactorySelector(spanPlugins ? null : plugin, superClass);
@@ -1276,7 +1313,7 @@ public class PluginLoader {
stream.close();
}
messageCollectionList.add(messageCollection);
- } catch (Exception e) {
+ } catch (IOException | DocumentException e) {
throw new PluginException("Couldn't parse \"" + messageURL + "\"", e);
}
}
@@ -1372,8 +1409,9 @@ public class PluginLoader {
URL url = file.toURI().toURL();
if (IO.verifyURL(url)) {
loadInitialPlugin(url, true, optional);
- if (FindBugs.DEBUG)
+ if (FindBugs.DEBUG) {
System.out.println("Found plugin: " + file.toString());
+ }
}
} catch (MalformedURLException e) {
@@ -1445,8 +1483,9 @@ public class PluginLoader {
assert true;
}catch (PluginException e) {
AnalysisContext.logError("Unable to load plugin from " + u, e);
- if (DEBUG)
+ if (DEBUG) {
e.printStackTrace();
+ }
}
}
@@ -1474,11 +1513,11 @@ public class PluginLoader {
((HttpURLConnection) connection).disconnect();
}
loadInitialPlugin(url, true, false);
- } catch (Exception e) {
+ } catch (IOException e) {
DetectorFactoryCollection.jawsDebugMessage("error loading " + url + " : " + e.getMessage());
}
}
- } catch (Exception e) {
+ } catch (IOException e) {
DetectorFactoryCollection.jawsDebugMessage("error : " + e.getMessage());
} finally {
Util.closeSilently(in);
diff --git a/src/java/edu/umd/cs/findbugs/PrintingBugReporter.java b/src/java/edu/umd/cs/findbugs/PrintingBugReporter.java
index a696864..2eb8a37 100644
--- a/src/java/edu/umd/cs/findbugs/PrintingBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/PrintingBugReporter.java
@@ -43,6 +43,7 @@ import edu.umd.cs.findbugs.util.Bag;
public class PrintingBugReporter extends TextUIBugReporter {
private final HashSet<BugInstance> seenAlready = new HashSet<BugInstance>();
+ @Override
public void observeClass(ClassDescriptor classDescriptor) {
// Don't need to do anything special, since we won't be
// reporting statistics.
@@ -56,6 +57,7 @@ public class PrintingBugReporter extends TextUIBugReporter {
}
}
+ @Override
public void finish() {
outputStream.close();
}
@@ -71,6 +73,8 @@ public class PrintingBugReporter extends TextUIBugReporter {
private final Project project;
+ private boolean setExitCode;
+
public PrintingCommandLine() {
project = new Project();
addSwitch("-longBugCodes", "use long bug codes when generating text");
@@ -83,6 +87,7 @@ public class PrintingBugReporter extends TextUIBugReporter {
addSwitch("-annotationUpload", "generate annotations in upload format");
addSwitchWithOptionalExtraPart("-html", "stylesheet", "Generate HTML output (default stylesheet is default.xsl)");
addOption("-pluginList", "jar1[" + File.pathSeparator + "jar2...]", "specify list of plugin Jar files to load");
+ addSwitch("-exitcode", "set exit code of process");
}
public @Nonnull
@@ -92,31 +97,34 @@ public class PrintingBugReporter extends TextUIBugReporter {
@Override
protected void handleOption(String option, String optionExtraPart) throws IOException {
- if (option.equals("-longBugCodes"))
+ if ("-longBugCodes".equals(option)) {
setUseLongBugCodes(true);
- else if (option.equals("-rank"))
+ } else if ("-rank".equals(option)) {
setShowRank(true);
- else if (option.equals("-designations"))
+ } else if ("-designations".equals(option)) {
setReportUserDesignations(true);
- else if (option.equals("-applySuppression"))
+ } else if ("-applySuppression".equals(option)) {
setApplySuppressions(true);
- else if (option.equals("-history"))
+ } else if ("-history".equals(option)) {
setReportHistory(true);
- else if (option.equals("-annotationUpload"))
+ } else if ("-annotationUpload".equals(option)) {
annotationUploadFormat = true;
- else if (option.equals("-html")) {
- if (!optionExtraPart.equals("")) {
+ } else if ("-html".equals(option)) {
+ if (!"".equals(optionExtraPart)) {
stylesheet = optionExtraPart;
} else {
stylesheet = "default.xsl";
}
- } else
+ } else if ("-exitcode".equals(option)) {
+ setExitCode = true;
+ } else {
throw new IllegalArgumentException("Unknown option '" + option + "'");
+ }
}
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-pluginList")) {
+ if ("-pluginList".equals(option)) {
String pluginListStr = argument;
Map<String, Boolean> customPlugins = getProject().getConfiguration().getCustomPlugins();
StringTokenizer tok = new StringTokenizer(pluginListStr, File.pathSeparator);
@@ -133,9 +141,9 @@ public class PrintingBugReporter extends TextUIBugReporter {
}
}
}
- } else if (option.equals("-maxRank")) {
+ } else if ("-maxRank".equals(option)) {
maxRank = Integer.parseInt(argument);
- } else if (option.equals("-summarizeMaxRank")) {
+ } else if ("-summarizeMaxRank".equals(option)) {
summarizeMaxRank = Integer.parseInt(argument);
} else {
throw new IllegalStateException();
@@ -161,13 +169,16 @@ public class PrintingBugReporter extends TextUIBugReporter {
}
SortedBugCollection bugCollection = new SortedBugCollection(commandLine.getProject());
- if (argCount < args.length)
+ if (argCount < args.length) {
bugCollection.readXML(args[argCount++]);
- else
+ } else {
bugCollection.readXML(System.in);
+ }
- if (argCount < args.length)
+ if (argCount < args.length) {
reporter.setOutputStream(UTF8.printStream(new FileOutputStream(args[argCount++]), true));
+ }
+ boolean bugsReported = false;
RuntimeException storedException = null;
if (commandLine.annotationUploadFormat) {
bugCollection.computeBugHashes();
@@ -179,39 +190,45 @@ public class PrintingBugReporter extends TextUIBugReporter {
System.out.print("#" + fHash);
String key = warning.getUserDesignationKey();
- if (key.equals(BugDesignation.UNCLASSIFIED) || key.equals("NEEDS_FURTHER_STUDY"))
+ if (key.equals(BugDesignation.UNCLASSIFIED) || "NEEDS_FURTHER_STUDY".equals(key)) {
System.out.print("#-1#" + key);
- else if (key.equals("MUST_FIX") || key.equals("SHOULD_FIX") || key.equals("I_WILL_FIX"))
+ } else if ("MUST_FIX".equals(key) || "SHOULD_FIX".equals(key) || "I_WILL_FIX".equals(key)) {
System.out.print("#7#" + key);
- else
+ } else {
System.out.print("#0#" + key);
+ }
SourceLineAnnotation sourceLine = warning.getPrimarySourceLineAnnotation();
System.out.println("#" + sourceLine.getSourceFile() + "#" + sourceLine.getStartLine());
System.out.println(warning.getAnnotationText());
} catch (RuntimeException e) {
- if (storedException == null)
+ if (storedException == null) {
storedException = e;
+ }
}
}
} else {
Bag<String> lowRank = new Bag<String>(new TreeMap<String, Integer>());
- for (BugInstance warning : bugCollection.getCollection())
+ for (BugInstance warning : bugCollection.getCollection()) {
if (!reporter.isApplySuppressions() || !bugCollection.getProject().getSuppressionFilter().match(warning)) {
int rank = warning.getBugRank();
BugPattern pattern = warning.getBugPattern();
if (rank <= commandLine.maxRank) {
+ bugsReported = true;
try {
reporter.printBug(warning);
} catch (RuntimeException e) {
- if (storedException == null)
+ if (storedException == null) {
storedException = e;
+ }
}
} else if (rank <= commandLine.summarizeMaxRank) {
+ bugsReported = true;
lowRank.add(pattern.getCategory());
}
}
+ }
reporter.finish();
for (Map.Entry<String, Integer> e : lowRank.entrySet()) {
@@ -220,8 +237,24 @@ public class PrintingBugReporter extends TextUIBugReporter {
}
}
- if (storedException != null)
- throw storedException;
+ if(commandLine.setExitCode){
+ int exitCode = 0;
+ System.err.println("Calculating exit code...");
+ if (storedException != null) {
+ exitCode |= ExitCodes.ERROR_FLAG;
+ System.err.println("Setting 'errors encountered' flag (" + ExitCodes.ERROR_FLAG + ")");
+ storedException.printStackTrace(System.err);
+ }
+ if (bugsReported) {
+ exitCode |= ExitCodes.BUGS_FOUND_FLAG;
+ System.err.println("Setting 'bugs found' flag (" + ExitCodes.BUGS_FOUND_FLAG + ")");
+ }
+ System.err.println("Exit code set to: " + exitCode);
+ System.exit(exitCode);
+ } else
+ if (storedException != null) {
+ throw storedException;
+ }
}
@@ -233,22 +266,25 @@ public class PrintingBugReporter extends TextUIBugReporter {
bugCollection.setApplySuppressions(applySuppression);
if (argCount < args.length) {
bugCollection.readXML(args[argCount++]);
- } else
+ } else {
bugCollection.readXML(System.in);
+ }
- if (argCount < args.length)
+ if (argCount < args.length) {
reporter.setOutputStream(UTF8.printStream(new FileOutputStream(args[argCount++]), true));
+ }
reporter.finish();
Exception e = reporter.getFatalException();
- if (e != null)
+ if (e != null) {
throw e;
+ }
}
+ @Override
public @CheckForNull
BugCollection getBugCollection() {
return null;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ProgramPoint.java b/src/java/edu/umd/cs/findbugs/ProgramPoint.java
index e6cc1dc..092d38c 100644
--- a/src/java/edu/umd/cs/findbugs/ProgramPoint.java
+++ b/src/java/edu/umd/cs/findbugs/ProgramPoint.java
@@ -31,7 +31,7 @@ public class ProgramPoint {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
@@ -45,25 +45,31 @@ public class ProgramPoint {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
ProgramPoint other = (ProgramPoint) obj;
if (method == null) {
- if (other.method != null)
+ if (other.method != null) {
return false;
- } else if (!method.equals(other.method))
+ }
+ } else if (!method.equals(other.method)) {
return false;
- if (pc != other.pc)
+ }
+ if (pc != other.pc) {
return false;
+ }
return true;
}
diff --git a/src/java/edu/umd/cs/findbugs/Project.java b/src/java/edu/umd/cs/findbugs/Project.java
index eada3b2..0ea2ada 100644
--- a/src/java/edu/umd/cs/findbugs/Project.java
+++ b/src/java/edu/umd/cs/findbugs/Project.java
@@ -24,11 +24,10 @@
*/
package edu.umd.cs.findbugs;
-
import static edu.umd.cs.findbugs.xml.XMLOutputUtil.writeElementList;
+import static java.util.Objects.requireNonNull;
import java.io.BufferedInputStream;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -138,35 +137,29 @@ public class Project implements XMLWriteable {
* @param configuration The configuration to set, non null
*/
public void setConfiguration(@Nonnull UserPreferences configuration) {
- if (configuration == null)
- throw new NullPointerException();
+ requireNonNull(configuration);
this.configuration = configuration;
}
- /**
- * @return Returns the cloudId.
- */
public @CheckForNull String getCloudId() {
return cloudId;
}
- /**
- * @param cloudId
- * The cloudId to set.
- */
public void setCloudId(@Nullable String cloudId) {
if (cloudId != null && cloudId.indexOf('.') == -1) {
Map<String, CloudPlugin> registeredClouds = DetectorFactoryCollection.instance().getRegisteredClouds();
String check = "." + cloudId;
int count = 0;
String result = cloudId;
- for(String name : registeredClouds.keySet())
+ for(String name : registeredClouds.keySet()) {
if (name.endsWith(check)) {
count++;
result = name;
}
- if (count == 1)
+ }
+ if (count == 1) {
cloudId = result;
+ }
}
this.cloudId = cloudId;
}
@@ -260,8 +253,9 @@ public class Project implements XMLWriteable {
}
public void setCurrentWorkingDirectory(File f) {
- if (f != null)
+ if (f != null) {
addWorkingDir(f.toString());
+ }
}
/**
@@ -316,8 +310,9 @@ public class Project implements XMLWriteable {
* directory was already present
*/
public boolean addWorkingDir(String dirName) {
- if (dirName == null)
+ if (dirName == null) {
throw new NullPointerException();
+ }
return addToListInternal(currentWorkingDirectoryList, new File(dirName));
}
@@ -712,9 +707,9 @@ public class Project implements XMLWriteable {
try {
String tag = Util.getXMLType(in);
SAXBugCollectionHandler handler;
- if (tag.equals("Project")) {
+ if ("Project".equals(tag)) {
handler = new SAXBugCollectionHandler(project, f);
- } else if (tag.equals("BugCollection")) {
+ } else if ("BugCollection".equals(tag)) {
SortedBugCollection bugs = new SortedBugCollection(project);
handler = new SAXBugCollectionHandler(bugs, f);
} else {
@@ -776,7 +771,7 @@ public class Project implements XMLWriteable {
/**
* Read a line from a BufferedReader, ignoring blank lines and comments.
- */
+ *
private static String getLine(BufferedReader reader) throws IOException {
String line;
while ((line = reader.readLine()) != null) {
@@ -786,7 +781,7 @@ public class Project implements XMLWriteable {
}
}
return line;
- }
+ }*/
/**
* Convert to a string in a nice (displayable) format.
@@ -833,11 +828,12 @@ public class Project implements XMLWriteable {
static final String PLUGIN_STATUS_ELEMENT_NAME = "enabled";
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, null, null);
}
- public void writeXML(XMLOutput xmlOutput, @CheckForNull File destination, @CheckForNull BugCollection bugCollection)
+ public void writeXML(XMLOutput xmlOutput, @CheckForNull File destination, @CheckForNull BugCollection bugCollection)
throws IOException {
{
XMLAttributeList attributeList = new XMLAttributeList();
@@ -854,8 +850,9 @@ public class Project implements XMLWriteable {
writeElementList(xmlOutput, AUX_CLASSPATH_ENTRY_ELEMENT_NAME, convertToRelative(auxClasspathEntryList, base));
writeElementList(xmlOutput, SRC_DIR_ELEMENT_NAME, convertToRelative(srcDirList, base));
List<String> cwdStrings = new ArrayList<String>();
- for (File file : currentWorkingDirectoryList)
+ for (File file : currentWorkingDirectoryList) {
cwdStrings.add(file.getPath());
+ }
XMLOutputUtil.writeElementList(xmlOutput, WRK_DIR_ELEMENT_NAME, convertToRelative(cwdStrings, base));
} else {
// TODO to allow relative paths: refactor the code which uses null
@@ -866,7 +863,7 @@ public class Project implements XMLWriteable {
XMLOutputUtil.writeFileList(xmlOutput, WRK_DIR_ELEMENT_NAME, currentWorkingDirectoryList);
}
- if (suppressionFilter != null && !suppressionFilter.isEmpty()) {
+ if (!suppressionFilter.isEmpty()) {
xmlOutput.openTag("SuppressionFilter");
suppressionFilter.writeBodyAsXML(xmlOutput);
xmlOutput.closeTag("SuppressionFilter");
@@ -887,15 +884,17 @@ public class Project implements XMLWriteable {
CloudPlugin cloudPlugin = bugCollection == null ? null : CloudFactory.getCloudPlugin(bugCollection);
if (cloudPlugin != null) {
String id = cloudPlugin.getId();
- if (id == null)
+ if (id == null) {
id = cloudId;
+ }
xmlOutput.startTag(CLOUD_ELEMENT_NAME);
xmlOutput.addAttribute(CLOUD_ID_ATTRIBUTE_NAME, id);
boolean onlineCloud = cloudPlugin.isOnline();
xmlOutput.addAttribute("online", Boolean.toString(onlineCloud));
String url = cloudPlugin.getProperties().getProperty("cloud.detailsUrl");
- if (url != null)
+ if (url != null) {
xmlOutput.addAttribute("detailsUrl", url);
+ }
xmlOutput.stopTag(false);
for (Map.Entry<?,?> e : cloudProperties.entrySet()) {
xmlOutput.startTag(CLOUD_PROPERTY_ELEMENT_NAME);
@@ -990,9 +989,7 @@ public class Project implements XMLWriteable {
return path.toString();
}
}
-
return srcFile;
-
}
/**
@@ -1001,7 +998,7 @@ public class Project implements XMLWriteable {
* @param fileName
* path to convert
* @return the converted filename
- */
+ *
private String convertToAbsolute(String fileName) {
// At present relative paths are only calculated if the fileName is
// below the project file. This need not be the case, and we could use
@@ -1013,13 +1010,14 @@ public class Project implements XMLWriteable {
if (!file.isAbsolute()) {
for (File cwd : currentWorkingDirectoryList) {
File test = new File(cwd, fileName);
- if (test.canRead())
+ if (test.canRead()) {
return test.getAbsolutePath();
+ }
}
return file.getAbsolutePath();
}
return fileName;
- }
+ }*/
/**
* Make the given filename absolute relative to the current working
@@ -1094,7 +1092,7 @@ public class Project implements XMLWriteable {
/**
* Make the given list of pathnames absolute relative to the absolute path
* of the project file.
- */
+ *
private void makeListAbsoluteProject(List<String> list) {
List<String> replace = new LinkedList<String>();
for (String fileName : list) {
@@ -1104,12 +1102,8 @@ public class Project implements XMLWriteable {
list.clear();
list.addAll(replace);
- }
+ }*/
- /**
- * @param timestamp
- * The timestamp to set.
- */
public void setTimestamp(long timestamp) {
this.timestampForAnalyzedClasses = timestamp;
}
@@ -1120,41 +1114,24 @@ public class Project implements XMLWriteable {
}
}
- /**
- * @return Returns the timestamp.
- */
public long getTimestamp() {
return timestampForAnalyzedClasses;
}
- /**
- * @param projectName
- * The projectName to set.
- */
public void setProjectName(String projectName) {
this.projectName = projectName;
}
- /**
- * @return Returns the projectName.
- */
public String getProjectName() {
return projectName;
}
- /**
- * @param suppressionFilter
- * The suppressionFilter to set.
- */
public void setSuppressionFilter(@Nonnull Filter suppressionFilter) {
- if (suppressionFilter == null)
- throw new NullPointerException();
+ requireNonNull(suppressionFilter);
this.suppressionFilter = suppressionFilter;
}
- /**
- * @return Returns the suppressionFilter.
- */
+ @Nonnull
public Filter getSuppressionFilter() {
return suppressionFilter;
}
@@ -1164,14 +1141,12 @@ public class Project implements XMLWriteable {
}
public IGuiCallback getGuiCallback() {
- if (guiCallback == null)
+ if (guiCallback == null) {
guiCallback = new CommandLineUiCallback();
+ }
return guiCallback;
}
- /**
- * @return
- */
public Iterable<String> getResolvedSourcePaths() {
List<String> result = new ArrayList<String>();
for (String s : srcDirList) {
@@ -1182,21 +1157,22 @@ public class Project implements XMLWriteable {
}
File f = new File(s);
if (f.isAbsolute() || currentWorkingDirectoryList.isEmpty()) {
- if (f.canRead())
+ if (f.canRead()) {
result.add(s);
+ }
continue;
}
- for (File d : currentWorkingDirectoryList)
+ for (File d : currentWorkingDirectoryList) {
if (d.canRead() && d.isDirectory()) {
File a = new File(d, s);
- if (a.canRead())
+ if (a.canRead()) {
result.add(a.getAbsolutePath());
+ }
}
+ }
}
return result;
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ProjectPackagePrefixes.java b/src/java/edu/umd/cs/findbugs/ProjectPackagePrefixes.java
index 74d674e..1c56841 100644
--- a/src/java/edu/umd/cs/findbugs/ProjectPackagePrefixes.java
+++ b/src/java/edu/umd/cs/findbugs/ProjectPackagePrefixes.java
@@ -47,18 +47,22 @@ public class ProjectPackagePrefixes {
PrefixFilter(String prefixes) {
prefixes = prefixes.replace('/', '.').trim();
- if (prefixes.length() == 0)
+ if (prefixes.length() == 0) {
parts = new String[0];
- else
+ } else {
parts = prefixes.split("[ ,:]+");
+ }
}
boolean matches(@DottedClassName String className) {
- if (parts.length == 0)
+ if (parts.length == 0) {
return true;
- for (String p : parts)
- if (p.length() > 0 && className.startsWith(p))
+ }
+ for (String p : parts) {
+ if (p.length() > 0 && className.startsWith(p)) {
return true;
+ }
+ }
return false;
}
@@ -110,8 +114,9 @@ public class ProjectPackagePrefixes {
public TreeSet<String> getProjects(@DottedClassName String className) {
TreeSet<String> results = new TreeSet<String>();
for (Map.Entry<String, PrefixFilter> e : map.entrySet()) {
- if (e.getValue().matches(className))
+ if (e.getValue().matches(className)) {
results.add(e.getKey());
+ }
}
return results;
}
@@ -122,10 +127,11 @@ public class ProjectPackagePrefixes {
static <T> void incrementCount(Map<T, Integer> counter, T t, int valueToAdd) {
Integer v = counter.get(t);
- if (v == null)
+ if (v == null) {
counter.put(t, valueToAdd);
- else
+ } else {
counter.put(t, v + valueToAdd);
+ }
}
static final Pattern FORBIDDEN_PACKAGE_PREFIXES = Pattern.compile(SystemProperties.getProperty(
@@ -138,15 +144,17 @@ public class ProjectPackagePrefixes {
for (Map.Entry<String, Integer> e : rawPackageCount.entrySet()) {
String packageName = e.getKey();
- if (e.getValue() > 5)
+ if (e.getValue() > 5) {
System.out.printf("%5d %s%n", e.getValue(), packageName);
+ }
}
System.out.println("Count by project");
for (Map.Entry<Set<String>, Integer> e : count.entrySet()) {
Set<String> projects = e.getKey();
- if (e.getValue() > 5)
+ if (e.getValue() > 5) {
System.out.printf("%5d %s%n", e.getValue(), projects);
+ }
}
System.out.println("Count by package for items not associated with a project");
@@ -157,22 +165,24 @@ public class ProjectPackagePrefixes {
for (String p1 : packages) {
int num = missingProjectCount.get(p1);
if (num < 3) {
- int x = p1.lastIndexOf(".");
+ int x = p1.lastIndexOf('.');
String p2 = p1.substring(0, x);
- if (FORBIDDEN_PACKAGE_PREFIXES.matcher(p2).matches())
+ if (FORBIDDEN_PACKAGE_PREFIXES.matcher(p2).matches()) {
continue;
+ }
extraSuperPackages.add(p2);
}
}
- for (String p1 : extraSuperPackages)
+ for (String p1 : extraSuperPackages) {
missingProjectCount.put(p1, 0);
+ }
for (Iterator<String> i = packages.iterator(); i.hasNext();) {
String p1 = i.next();
int num = missingProjectCount.get(p1);
- for (String p2 : packages)
+ for (String p2 : packages) {
if (p2.length() < p1.length() && p1.startsWith(p2)) {
// p1 is a subpackage of p2
// System.out.printf("%s is a subpackage of %s\n", p1,
@@ -181,14 +191,16 @@ public class ProjectPackagePrefixes {
incrementCount(missingProjectCount, p2, num);
break;
}
+ }
}
}
System.out.println("Count of missing files in packages not associated with a project");
for (Map.Entry<String, Integer> e : missingProjectCount.entrySet()) {
- if (e.getValue() > 5)
+ if (e.getValue() > 5) {
System.out.printf("%5d %s%n", e.getValue(), e.getKey());
+ }
}
}
@@ -198,20 +210,22 @@ public class ProjectPackagePrefixes {
BufferedReader in = null;
try {
- in = UTF8.bufferedReader(u.openStream());
+ in = UTF8.bufferedReader(u.openStream());
while (true) {
String s = in.readLine();
- if (s == null)
+ if (s == null) {
break;
+ }
String[] parts = s.split("=");
- if (parts.length == 2 && !map.containsKey(parts[0]))
+ if (parts.length == 2 && !map.containsKey(parts[0])) {
map.put(parts[0], new PrefixFilter(parts[1]));
+ }
}
} catch (IOException e1) {
AnalysisContext.logError("Error loading projects paths", e1);
} finally {
- Util.closeSilently(in);
+ Util.closeSilently(in);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ProjectStats.java b/src/java/edu/umd/cs/findbugs/ProjectStats.java
index 4f53168..3193f5b 100644
--- a/src/java/edu/umd/cs/findbugs/ProjectStats.java
+++ b/src/java/edu/umd/cs/findbugs/ProjectStats.java
@@ -67,9 +67,9 @@ public class ProjectStats implements XMLWriteable, Cloneable {
private static final boolean OMIT_PACKAGE_STATS = SystemProperties.getBoolean("findbugs.packagestats.omit");
- private SortedMap<String, PackageStats> packageStatsMap;
+ private final SortedMap<String, PackageStats> packageStatsMap;
- private int[] totalErrors = new int[] { 0, 0, 0, 0, 0 };
+ private final int[] totalErrors = new int[] { 0, 0, 0, 0, 0 };
private int totalClasses;
@@ -87,8 +87,9 @@ public class ProjectStats implements XMLWriteable, Cloneable {
private boolean hasPackageStats;
- private Footprint baseFootprint;
+ private final Footprint baseFootprint;
+ private final String java_version = SystemProperties.getProperty("java.version");
private String java_vm_version = SystemProperties.getProperty("java.vm.version");
private final Profiler profiler;
@@ -97,9 +98,11 @@ public class ProjectStats implements XMLWriteable, Cloneable {
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(getNumClasses()).append(" classes: ");
- for (PackageStats pStats : getPackageStats())
- for (ClassStats cStats : pStats.getSortedClassStats())
+ for (PackageStats pStats : getPackageStats()) {
+ for (ClassStats cStats : pStats.getSortedClassStats()) {
buf.append(cStats.getName()).append(" ");
+ }
+ }
return buf.toString();
}
@@ -133,8 +136,9 @@ public class ProjectStats implements XMLWriteable, Cloneable {
}
public int getCodeSize() {
- if (totalSizeFromPackageStats > 0)
+ if (totalSizeFromPackageStats > 0) {
return totalSizeFromPackageStats;
+ }
return totalSize;
}
@@ -149,7 +153,7 @@ public class ProjectStats implements XMLWriteable, Cloneable {
/**
* Set the timestamp for this analysis run.
- *
+ *
* @param timestamp
* the time of the analysis run this ProjectStats represents, as
* previously reported by writeXML.
@@ -170,8 +174,9 @@ public class ProjectStats implements XMLWriteable, Cloneable {
* Get the number of classes analyzed.
*/
public int getNumClasses() {
- if (totalClassesFromPackageStats > 0)
+ if (totalClassesFromPackageStats > 0) {
return totalClassesFromPackageStats;
+ }
return totalClasses;
}
@@ -184,7 +189,7 @@ public class ProjectStats implements XMLWriteable, Cloneable {
/**
* Report that a class has been analyzed.
- *
+ *
* @param className
* the full name of the class
* @param sourceFile
@@ -201,7 +206,7 @@ public class ProjectStats implements XMLWriteable, Cloneable {
/**
* Report that a class has been analyzed.
- *
+ *
* @param className
* the full name of the class
* @param sourceFile
@@ -214,13 +219,19 @@ public class ProjectStats implements XMLWriteable, Cloneable {
* @param updatePackageStats TODO
*/
public void addClass(@DottedClassName String className, @CheckForNull String sourceFile, boolean isInterface, int size, boolean updatePackageStats) {
+ if(!hasClassStats) {
+ // totalClasses/totalSize might be set from FindBugsSummary before when parsing XML: reset them
+ totalClasses = 0;
+ totalSize = 0;
+ }
hasClassStats = true;
String packageName;
int lastDot = className.lastIndexOf('.');
- if (lastDot < 0)
+ if (lastDot < 0) {
packageName = "";
- else
+ } else {
packageName = className.substring(0, lastDot);
+ }
PackageStats stat = getPackageStats(packageName);
stat.addClass(className, sourceFile, isInterface, size, updatePackageStats);
totalClasses++;
@@ -231,20 +242,22 @@ public class ProjectStats implements XMLWriteable, Cloneable {
/**
* Report that a class has been analyzed.
- *
+ *
* @param className
* the full name of the class
*/
public @CheckForNull
ClassStats getClassStats(@DottedClassName String className) {
- if (hasClassStats)
+ if (hasClassStats) {
return null;
+ }
String packageName;
int lastDot = className.lastIndexOf('.');
- if (lastDot < 0)
+ if (lastDot < 0) {
packageName = "";
- else
+ } else {
packageName = className.substring(0, lastDot);
+ }
PackageStats stat = getPackageStats(packageName);
return stat.getClassStatsOrNull(className);
}
@@ -268,23 +281,25 @@ public class ProjectStats implements XMLWriteable, Cloneable {
* Clear bug counts
*/
public void clearBugCounts() {
- for (int i = 0; i < totalErrors.length; i++)
+ for (int i = 0; i < totalErrors.length; i++) {
totalErrors[i] = 0;
+ }
for (PackageStats stats : packageStatsMap.values()) {
stats.clearBugCounts();
}
}
public void purgeClassesThatDontMatch(Pattern classPattern) {
- if (hasClassStats)
+ if (hasClassStats) {
for (Iterator<Map.Entry<String, PackageStats>> i = packageStatsMap.entrySet().iterator(); i.hasNext();) {
Map.Entry<String, PackageStats> e = i.next();
PackageStats stats = e.getValue();
stats.purgeClassesThatDontMatch(classPattern);
- if (stats.getClassStats().isEmpty())
+ if (stats.getClassStats().isEmpty()) {
i.remove();
+ }
}
- else if (hasPackageStats) {
+ } else if (hasPackageStats) {
boolean matchAny = false;
for (String packageName : packageStatsMap.keySet()) {
Matcher m = classPattern.matcher(packageName);
@@ -293,7 +308,7 @@ public class ProjectStats implements XMLWriteable, Cloneable {
break;
}
}
- if (matchAny)
+ if (matchAny) {
for (Iterator<String> i = packageStatsMap.keySet().iterator(); i.hasNext();) {
String packageName = i.next();
Matcher m = classPattern.matcher(packageName);
@@ -302,15 +317,18 @@ public class ProjectStats implements XMLWriteable, Cloneable {
}
}
+ }
}
}
public void purgeClassStats() {
hasClassStats = false;
- if (totalClassesFromPackageStats == 0)
+ if (totalClassesFromPackageStats == 0) {
totalClassesFromPackageStats = totalClasses;
- if (totalSizeFromPackageStats == 0)
+ }
+ if (totalSizeFromPackageStats == 0) {
totalSizeFromPackageStats = totalSize;
+ }
for (PackageStats ps : getPackageStats()) {
ps.getClassStats().clear();
@@ -319,45 +337,53 @@ public class ProjectStats implements XMLWriteable, Cloneable {
public void purgePackageStats() {
hasPackageStats = false;
- if (totalClassesFromPackageStats == 0)
+ if (totalClassesFromPackageStats == 0) {
totalClassesFromPackageStats = totalClasses;
- if (totalSizeFromPackageStats == 0)
+ }
+ if (totalSizeFromPackageStats == 0) {
totalSizeFromPackageStats = totalSize;
+ }
getPackageStats().clear();
}
public void recomputeFromComponents() {
- if (!hasClassStats && !hasPackageStats)
+ if (!hasClassStats && !hasPackageStats) {
return;
- for (int i = 0; i < totalErrors.length; i++)
+ }
+ for (int i = 0; i < totalErrors.length; i++) {
totalErrors[i] = 0;
+ }
totalSize = 0;
totalClasses = 0;
totalSizeFromPackageStats = 0;
totalClassesFromPackageStats = 0;
for (PackageStats stats : packageStatsMap.values()) {
- if (hasClassStats)
+ if (hasClassStats) {
stats.recomputeFromClassStats();
+ }
totalSize += stats.size();
totalClasses += stats.getNumClasses();
- for (int i = 0; i < totalErrors.length; i++)
+ for (int i = 0; i < totalErrors.length; i++) {
totalErrors[i] += stats.getBugsAtPriority(i);
+ }
}
}
FileBugHash fileBugHashes;
public void computeFileStats(BugCollection bugs) {
- if (bugs.getProjectStats() != this)
+ if (bugs.getProjectStats() != this) {
throw new IllegalArgumentException("Collection doesn't own stats");
+ }
fileBugHashes = FileBugHash.compute(bugs);
}
/**
* Output as XML.
*/
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, true);
}
@@ -376,8 +402,12 @@ public class ProjectStats implements XMLWriteable, Cloneable {
xmlOutput.addAttribute("total_size", String.valueOf(getCodeSize()));
xmlOutput.addAttribute("num_packages", String.valueOf(packageStatsMap.size()));
- if (java_vm_version != null)
+ if (java_version != null) {
+ xmlOutput.addAttribute("java_version", java_version);
+ }
+ if (java_vm_version != null) {
xmlOutput.addAttribute("vm_version", java_vm_version);
+ }
Footprint delta = new Footprint(baseFootprint);
NumberFormat twoPlaces = NumberFormat.getInstance(Locale.ENGLISH);
twoPlaces.setMinimumFractionDigits(2);
@@ -401,7 +431,7 @@ public class ProjectStats implements XMLWriteable, Cloneable {
xmlOutput.addAttribute("gc_seconds", twoPlaces.format(gcTime / 1000.0));
}
- PackageStats.writeBugPriorities(xmlOutput, totalErrors);
+ BugCounts.writeBugPriorities(xmlOutput, totalErrors);
xmlOutput.stopTag(false);
@@ -413,28 +443,32 @@ public class ProjectStats implements XMLWriteable, Cloneable {
xmlOutput.addAttribute("size", String.valueOf(fileBugHashes.getSize(sourceFile)));
String hash = fileBugHashes.getHash(sourceFile);
- if (hash != null)
+ if (hash != null) {
xmlOutput.addAttribute("bugHash", hash);
+ }
xmlOutput.stopTag(true);
}
}
- if (!OMIT_PACKAGE_STATS)
+ if (!OMIT_PACKAGE_STATS) {
for (PackageStats stats : packageStatsMap.values()) {
stats.writeXML(xmlOutput);
}
+ }
getProfiler().writeXML(xmlOutput);
xmlOutput.closeTag("FindBugsSummary");
}
public Map<String, String> getFileHashes(BugCollection bugs) {
- if (bugs.getProjectStats() != this)
+ if (bugs.getProjectStats() != this) {
throw new IllegalArgumentException("Collection doesn't own stats");
+ }
- if (fileBugHashes == null)
+ if (fileBugHashes == null) {
computeFileStats(bugs);
+ }
HashMap<String, String> result = new HashMap<String, String>();
for (String sourceFile : fileBugHashes.getSourceFiles()) {
@@ -458,7 +492,7 @@ public class ProjectStats implements XMLWriteable, Cloneable {
/**
* Transform summary information to HTML.
- *
+ *
* @param htmlWriter
* the Writer to write the HTML output to
*/
@@ -470,8 +504,9 @@ public class ProjectStats implements XMLWriteable, Cloneable {
StreamSource in = new StreamSource(new ByteArrayInputStream(summaryOut.toByteArray()));
StreamResult out = new StreamResult(htmlWriter);
InputStream xslInputStream = this.getClass().getClassLoader().getResourceAsStream("summary.xsl");
- if (xslInputStream == null)
+ if (xslInputStream == null) {
throw new IOException("Could not load summary stylesheet");
+ }
StreamSource xsl = new StreamSource(xslInputStream);
TransformerFactory tf = TransformerFactory.newInstance();
@@ -479,12 +514,14 @@ public class ProjectStats implements XMLWriteable, Cloneable {
transformer.transform(in, out);
Reader rdr = in.getReader();
- if (rdr != null)
+ if (rdr != null) {
rdr.close();
+ }
htmlWriter.close();
InputStream is = xsl.getInputStream();
- if (is != null)
+ if (is != null) {
is.close();
+ }
}
public Collection<PackageStats> getPackageStats() {
@@ -522,19 +559,24 @@ public class ProjectStats implements XMLWriteable, Cloneable {
* @param stats2
*/
public void addStats(ProjectStats stats2) {
- if (totalSize == totalSizeFromPackageStats)
+ if (totalSize == totalSizeFromPackageStats) {
totalSizeFromPackageStats += stats2.getCodeSize();
+ }
totalSize += stats2.getCodeSize();
- if (totalClasses == totalClassesFromPackageStats)
+ if (totalClasses == totalClassesFromPackageStats) {
totalClassesFromPackageStats += stats2.getNumClasses();
+ }
totalClasses += stats2.getNumClasses();
- for (int i = 0; i < totalErrors.length; i++)
+ for (int i = 0; i < totalErrors.length; i++) {
totalErrors[i] += stats2.totalErrors[i];
+ }
- if (stats2.hasPackageStats)
+ if (stats2.hasPackageStats) {
hasPackageStats = true;
- if (stats2.hasClassStats)
+ }
+ if (stats2.hasClassStats) {
hasClassStats = true;
+ }
for (Map.Entry<String, PackageStats> entry : stats2.packageStatsMap.entrySet()) {
String key = entry.getKey();
@@ -568,16 +610,10 @@ public class ProjectStats implements XMLWriteable, Cloneable {
return profiler;
}
- /**
- * @param parseInt
- */
public void setTotalClasses(int totalClasses) {
this.totalClasses = totalClasses;
}
- /**
- * @param parseInt
- */
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
diff --git a/src/java/edu/umd/cs/findbugs/PropertyBundle.java b/src/java/edu/umd/cs/findbugs/PropertyBundle.java
index 56b07a5..c2812b3 100644
--- a/src/java/edu/umd/cs/findbugs/PropertyBundle.java
+++ b/src/java/edu/umd/cs/findbugs/PropertyBundle.java
@@ -46,12 +46,13 @@ public class PropertyBundle {
Rewriter() {
Pattern p = null;
- if (urlRewritePatternString != null && urlRewriteFormat != null)
+ if (urlRewritePatternString != null && urlRewriteFormat != null) {
try {
p = Pattern.compile(urlRewritePatternString);
- } catch (Exception e) {
+ } catch (Throwable e) {
assert true;
}
+ }
urlRewritePattern = p;
}
@@ -62,8 +63,9 @@ public class PropertyBundle {
Rewriter getRewriter() {
if (rewriter == null) {
synchronized (this) {
- if (rewriter == null)
+ if (rewriter == null) {
rewriter = new Rewriter();
+ }
}
}
return rewriter;
@@ -123,7 +125,7 @@ public class PropertyBundle {
/**
* Get boolean property, returning false if a security manager prevents us
* from accessing system properties
- *
+ *
* @return true if the property exists and is set to true
*/
public boolean getBoolean(String name) {
@@ -134,8 +136,9 @@ public class PropertyBundle {
boolean result = defaultValue;
try {
String value = getProperty(name);
- if (value == null)
+ if (value == null) {
return defaultValue;
+ }
result = toBoolean(value);
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
@@ -144,7 +147,7 @@ public class PropertyBundle {
}
private boolean toBoolean(String name) {
- return ((name != null) && name.equalsIgnoreCase("true"));
+ return ((name != null) && "true".equalsIgnoreCase(name));
}
/**
@@ -157,8 +160,9 @@ public class PropertyBundle {
public int getInt(String name, int defaultValue) {
try {
String value = getProperty(name);
- if (value != null)
+ if (value != null) {
return Integer.decode(value);
+ }
} catch (Exception e) {
assert true;
}
@@ -173,8 +177,9 @@ public class PropertyBundle {
public String getOSDependentProperty(String name) {
String osDependentName = name + SystemProperties.OS_NAME;
String value = getProperty(osDependentName);
- if (value != null)
+ if (value != null) {
return value;
+ }
return getProperty(name);
}
@@ -186,8 +191,9 @@ public class PropertyBundle {
public String getProperty(String name) {
try {
String value = SystemProperties.getProperty(name);
- if (value != null)
+ if (value != null) {
return value;
+ }
return properties.getProperty(name);
} catch (Exception e) {
return null;
@@ -213,17 +219,20 @@ public class PropertyBundle {
*/
public String getProperty(String name, String defaultValue) {
String value = getProperty(name);
- if (value != null)
+ if (value != null) {
return value;
+ }
return defaultValue;
}
public String rewriteURLAccordingToProperties(String u) {
- if (getRewriter().urlRewritePattern == null || getRewriter().urlRewriteFormat == null)
+ if (getRewriter().urlRewritePattern == null || getRewriter().urlRewriteFormat == null) {
return u;
+ }
Matcher m = getRewriter().urlRewritePattern.matcher(u);
- if (!m.matches())
+ if (!m.matches()) {
return u;
+ }
String result = String.format(getRewriter().urlRewriteFormat, m.group(1));
return result;
}
diff --git a/src/java/edu/umd/cs/findbugs/QueryBugAnnotations.java b/src/java/edu/umd/cs/findbugs/QueryBugAnnotations.java
index 947cdbd..1fd3c5d 100644
--- a/src/java/edu/umd/cs/findbugs/QueryBugAnnotations.java
+++ b/src/java/edu/umd/cs/findbugs/QueryBugAnnotations.java
@@ -30,12 +30,12 @@ import java.util.Set;
public abstract class QueryBugAnnotations {
// Bug's text annotation must contain one of the key
// words in order to match
- private HashSet<String> keywordSet = new HashSet<String>();
+ private final HashSet<String> keywordSet = new HashSet<String>();
/**
* Add a keyword to the query. A BugInstance's text annotation must contain
* at least one keyword in order to match the query.
- *
+ *
* @param keyword
* the keyword
*/
@@ -46,7 +46,7 @@ public abstract class QueryBugAnnotations {
/**
* Scan bug instances contained in given file, reporting those whose text
* annotations contain at least one of the keywords in the query.
- *
+ *
* @param filename
* an XML file containing bug instances
*/
@@ -59,7 +59,7 @@ public abstract class QueryBugAnnotations {
/**
* Scan bug instances contained in given bug collection, reporting those
* whose text annotations contain at least one of the keywords in the query.
- *
+ *
* @param bugCollection
* the bug collection
* @param filename
@@ -82,7 +82,7 @@ public abstract class QueryBugAnnotations {
/**
* Called when a bug instance contains a query keyword.
- *
+ *
* @param bugInstance
* the bug instance containing the keyword
* @param filename
@@ -91,4 +91,3 @@ public abstract class QueryBugAnnotations {
protected abstract void match(BugInstance bugInstance, String filename) throws Exception;
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/RecursiveFileSearch.java b/src/java/edu/umd/cs/findbugs/RecursiveFileSearch.java
index f51e684..8d4b67f 100644
--- a/src/java/edu/umd/cs/findbugs/RecursiveFileSearch.java
+++ b/src/java/edu/umd/cs/findbugs/RecursiveFileSearch.java
@@ -33,25 +33,25 @@ import java.util.List;
* Recursively search a directory, its subdirectories, etc. Note that the search
* algorithm uses a worklist, so its implementation does not use recursive
* method calls.
- *
+ *
* @author David Hovemeyer
*/
public class RecursiveFileSearch {
- private String baseDir;
+ private final String baseDir;
- private FileFilter fileFilter;
+ private final FileFilter fileFilter;
- private LinkedList<File> directoryWorkList;
+ private final LinkedList<File> directoryWorkList;
- private HashSet<String> directoriesScanned = new HashSet<String>();
+ private final HashSet<String> directoriesScanned = new HashSet<String>();
- private List<String> directoriesScannedList = new LinkedList<String>();
+ private final List<String> directoriesScannedList = new LinkedList<String>();
- private ArrayList<String> resultList;
+ private final ArrayList<String> resultList;
/**
* Constructor.
- *
+ *
* @param baseDir
* the base directory for the search
* @param fileFilter
@@ -75,7 +75,7 @@ public class RecursiveFileSearch {
/**
* Perform the search.
- *
+ *
* @return this object
* @throws InterruptedException
* if the thread is interrupted before the search completes
@@ -89,15 +89,18 @@ public class RecursiveFileSearch {
while (!directoryWorkList.isEmpty()) {
File dir = directoryWorkList.removeFirst();
- if (!dir.isDirectory())
+ if (!dir.isDirectory()) {
continue;
+ }
File[] contentList = dir.listFiles();
- if (contentList == null)
+ if (contentList == null) {
continue;
+ }
for (File aContentList : contentList) {
- if (Thread.interrupted())
+ if (Thread.interrupted()) {
throw new InterruptedException();
+ }
File file = aContentList;
@@ -137,4 +140,3 @@ public class RecursiveFileSearch {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ResourceCollection.java b/src/java/edu/umd/cs/findbugs/ResourceCollection.java
index 7de005c..55bb99f 100644
--- a/src/java/edu/umd/cs/findbugs/ResourceCollection.java
+++ b/src/java/edu/umd/cs/findbugs/ResourceCollection.java
@@ -38,13 +38,13 @@ import edu.umd.cs.findbugs.ba.Location;
* This distinction is important because some resources which exist in the
* method aren't created in the method: for example, resources passed in as
* parameters.
- *
+ *
* @author David Hovemeyer
*/
public class ResourceCollection<Resource> {
- private List<Resource> resourceList;
+ private final List<Resource> resourceList;
- private Map<Location, Resource> locationToResourceMap;
+ private final Map<Location, Resource> locationToResourceMap;
/**
* Constructor. Creates empty collection.
@@ -58,7 +58,7 @@ public class ResourceCollection<Resource> {
* Add a preexisting resource. That is, one that is not created within the
* analyzed method. Resources passed to the method as parameters fall into
* this category.
- *
+ *
* @param resource
* the preexisting resource
*/
@@ -68,7 +68,7 @@ public class ResourceCollection<Resource> {
/**
* Add a resource created within the analyzed method.
- *
+ *
* @param location
* the location
* @param resource
@@ -96,7 +96,7 @@ public class ResourceCollection<Resource> {
/**
* Get the resource that is created at given location.
- *
+ *
* @param location
* the Location
* @return the Resource created at that location, or null if no resource is
@@ -107,4 +107,3 @@ public class ResourceCollection<Resource> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ResourceCreationPoint.java b/src/java/edu/umd/cs/findbugs/ResourceCreationPoint.java
index ad9ba5d..7f990b5 100644
--- a/src/java/edu/umd/cs/findbugs/ResourceCreationPoint.java
+++ b/src/java/edu/umd/cs/findbugs/ResourceCreationPoint.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.ba.Location;
/**
* A resource creation point. This serves as an embodiment of the resource for
* use with ResourceValueAnalysis.
- *
+ *
* @author David Hovemeyer
* @see edu.umd.cs.findbugs.ba.ResourceValueAnalysis
* @see ResourceTrackingDetector
@@ -42,7 +42,7 @@ public class ResourceCreationPoint {
/**
* Constructor.
- *
+ *
* @param location
* location where resource is created
* @param resourceClass
@@ -68,4 +68,3 @@ public class ResourceCreationPoint {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ResourceTrackingDetector.java b/src/java/edu/umd/cs/findbugs/ResourceTrackingDetector.java
index 2ea9234..084a235 100644
--- a/src/java/edu/umd/cs/findbugs/ResourceTrackingDetector.java
+++ b/src/java/edu/umd/cs/findbugs/ResourceTrackingDetector.java
@@ -46,11 +46,11 @@ import edu.umd.cs.findbugs.log.Profiler;
* of created resource is not cleaned up or closed properly. Subclasses should
* override the abstract methods to determine what kinds of resources are
* tracked by the detector.
- *
+ *
* @author David Hovemeyer
*/
public abstract class ResourceTrackingDetector<Resource, ResourceTrackerType extends ResourceTracker<Resource>> implements
- Detector {
+Detector {
private static final boolean DEBUG = SystemProperties.getBoolean("rtd.debug");
@@ -73,20 +73,24 @@ public abstract class ResourceTrackingDetector<Resource, ResourceTrackerType ext
public abstract void inspectResult(ClassContext classContext, MethodGen methodGen, CFG cfg,
Dataflow<ResourceValueFrame, ResourceValueAnalysis<Resource>> dataflow, Resource resource);
+ @Override
public void visitClassContext(ClassContext classContext) {
final JavaClass jclass = classContext.getJavaClass();
Method[] methodList = jclass.getMethods();
for (Method method : methodList) {
- if (method.isAbstract() || method.isNative())
+ if (method.isAbstract() || method.isNative()) {
continue;
+ }
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
continue;
+ }
- if (DEBUG_METHOD_NAME != null && !DEBUG_METHOD_NAME.equals(method.getName()))
+ if (DEBUG_METHOD_NAME != null && !DEBUG_METHOD_NAME.equals(method.getName())) {
continue;
+ }
if (DEBUG) {
System.out.println("----------------------------------------------------------------------");
@@ -98,12 +102,14 @@ public abstract class ResourceTrackingDetector<Resource, ResourceTrackerType ext
ResourceTrackerType resourceTracker = getResourceTracker(classContext, method);
boolean mightClose = mightCloseResource(classContext, method, resourceTracker);
- if (!prescreen(classContext, method, mightClose))
+ if (!prescreen(classContext, method, mightClose)) {
continue;
+ }
ResourceCollection<Resource> resourceCollection = buildResourceCollection(classContext, method, resourceTracker);
- if (resourceCollection.isEmpty())
+ if (resourceCollection.isEmpty()) {
continue;
+ }
analyzeMethod(classContext, method, resourceTracker, resourceCollection);
} catch (CFGBuilderException e) {
@@ -127,8 +133,9 @@ public abstract class ResourceTrackingDetector<Resource, ResourceTrackerType ext
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
Resource resource = resourceTracker.isResourceCreation(location.getBasicBlock(), location.getHandle(), cpg);
- if (resource != null)
+ if (resource != null) {
resourceCollection.addCreatedResource(location, resource);
+ }
}
return resourceCollection;
@@ -142,8 +149,9 @@ public abstract class ResourceTrackingDetector<Resource, ResourceTrackerType ext
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
- if (resourceTracker.mightCloseResource(location.getBasicBlock(), location.getHandle(), cpg))
+ if (resourceTracker.mightCloseResource(location.getBasicBlock(), location.getHandle(), cpg)) {
return true;
+ }
}
@@ -154,14 +162,16 @@ public abstract class ResourceTrackingDetector<Resource, ResourceTrackerType ext
ResourceCollection<Resource> resourceCollection) throws CFGBuilderException, DataflowAnalysisException {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
try {
CFG cfg = classContext.getCFG(method);
DepthFirstSearch dfs = classContext.getDepthFirstSearch(method);
- if (DEBUG)
+ if (DEBUG) {
System.out.println(SignatureConverter.convertMethodSignature(methodGen));
+ }
for (Iterator<Resource> i = resourceCollection.resourceIterator(); i.hasNext();) {
Resource resource = i.next();
@@ -186,9 +196,9 @@ public abstract class ResourceTrackingDetector<Resource, ResourceTrackerType ext
}
}
+ @Override
public void report() {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/SAXBugCollectionHandler.java b/src/java/edu/umd/cs/findbugs/SAXBugCollectionHandler.java
index 8005270..2357743 100644
--- a/src/java/edu/umd/cs/findbugs/SAXBugCollectionHandler.java
+++ b/src/java/edu/umd/cs/findbugs/SAXBugCollectionHandler.java
@@ -40,11 +40,11 @@ import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
-import edu.umd.cs.findbugs.ba.ClassHash;
import edu.umd.cs.findbugs.filter.AndMatcher;
import edu.umd.cs.findbugs.filter.BugMatcher;
import edu.umd.cs.findbugs.filter.ClassMatcher;
import edu.umd.cs.findbugs.filter.CompoundMatcher;
+import edu.umd.cs.findbugs.filter.ConfidenceMatcher;
import edu.umd.cs.findbugs.filter.DesignationMatcher;
import edu.umd.cs.findbugs.filter.FieldMatcher;
import edu.umd.cs.findbugs.filter.Filter;
@@ -57,6 +57,8 @@ import edu.umd.cs.findbugs.filter.NotMatcher;
import edu.umd.cs.findbugs.filter.OrMatcher;
import edu.umd.cs.findbugs.filter.PriorityMatcher;
import edu.umd.cs.findbugs.filter.RankMatcher;
+import edu.umd.cs.findbugs.filter.SourceMatcher;
+import edu.umd.cs.findbugs.filter.TypeMatcher;
import edu.umd.cs.findbugs.model.ClassFeatureSet;
import edu.umd.cs.findbugs.util.MapCache;
import edu.umd.cs.findbugs.util.Strings;
@@ -76,11 +78,6 @@ public class SAXBugCollectionHandler extends DefaultHandler {
private static final Logger LOGGER = Logger.getLogger(SAXBugCollectionHandler.class.getName());
- /**
- * @param attributes
- * @param qName
- * @return
- */
public String getOptionalAttribute(Attributes attributes, String qName) {
return memoized(attributes.getValue(qName));
}
@@ -163,18 +160,19 @@ public class SAXBugCollectionHandler extends DefaultHandler {
}
private String memoized(String s) {
- if (s == null)
+ if (s == null) {
return s;
+ }
String result = cache.get(s);
- if (result != null)
+ if (result != null) {
return result;
+ }
cache.put(s, s);
return s;
}
private static boolean DEBUG = false;
- @SuppressWarnings("hiding")
@Override
public void startElement(String uri, String name, String qName, Attributes attributes) throws SAXException {
// URI should always be empty.
@@ -186,16 +184,18 @@ public class SAXBugCollectionHandler extends DefaultHandler {
// ignore it
} else {
// We should be parsing the outer BugCollection element.
- if (elementStack.isEmpty() && !qName.equals(topLevelName))
+ if (elementStack.isEmpty() && !qName.equals(topLevelName)) {
throw new SAXException("Invalid top-level element (expected " + topLevelName + ", saw " + qName + ")");
+ }
- if (qName.equals(BUG_COLLECTION)) {
+ if (BUG_COLLECTION.equals(qName)) {
BugCollection bugCollection = this.bugCollection;
assert bugCollection != null;
// Read and set the sequence number.
String version = getOptionalAttribute(attributes, "version");
- if (bugCollection instanceof SortedBugCollection)
+ if (bugCollection instanceof SortedBugCollection) {
bugCollection.setAnalysisVersion(version);
+ }
// Read and set the sequence number.
String sequence = getOptionalAttribute(attributes, "sequence");
@@ -226,19 +226,20 @@ public class SAXBugCollectionHandler extends DefaultHandler {
}
matcherStack.clear();
pushCompoundMatcher(filter);
- } else if (qName.equals(PROJECT)) {
+ } else if (PROJECT.equals(qName)) {
Project project = this.project;
assert project != null;
// Project element
String projectName = getOptionalAttribute(attributes, Project.PROJECTNAME_ATTRIBUTE_NAME);
- if (projectName != null)
+ if (projectName != null) {
project.setProjectName(projectName);
+ }
} else {
String outerElement = elementStack.get(elementStack.size() - 1);
- if (outerElement.equals(BUG_COLLECTION)) {
+ if (BUG_COLLECTION.equals(outerElement)) {
// Parsing a top-level element of the BugCollection
- if (qName.equals("BugInstance")) {
+ if ("BugInstance".equals(qName)) {
// BugInstance element - get required type and priority
// attributes
String type = getRequiredAttribute(attributes, "type", qName);
@@ -260,8 +261,9 @@ public class SAXBugCollectionHandler extends DefaultHandler {
bugInstance.setLastVersion(Long.parseLong(lastVersion));
}
- if (bugInstance.isDead() && bugInstance.getFirstVersion() > bugInstance.getLastVersion())
+ if (bugInstance.isDead() && bugInstance.getFirstVersion() > bugInstance.getLastVersion()) {
throw new IllegalStateException("huh");
+ }
String introducedByChange = getOptionalAttribute(attributes, "introducedByChange");
if (introducedByChange != null) {
@@ -272,8 +274,9 @@ public class SAXBugCollectionHandler extends DefaultHandler {
bugInstance.setRemovedByChangeOfPersistingClass(Boolean.parseBoolean(removedByChange));
}
String oldInstanceHash = getOptionalAttribute(attributes, "instanceHash");
- if (oldInstanceHash == null)
+ if (oldInstanceHash == null) {
oldInstanceHash = getOptionalAttribute(attributes, "oldInstanceHash");
+ }
if (oldInstanceHash != null) {
bugInstance.setOldInstanceHash(oldInstanceHash);
}
@@ -289,8 +292,9 @@ public class SAXBugCollectionHandler extends DefaultHandler {
}
String isInCloud = getOptionalAttribute(attributes, "isInCloud");
- if (isInCloud != null)
+ if (isInCloud != null) {
bugInstance.getXmlProps().setIsInCloud(Boolean.parseBoolean(isInCloud));
+ }
String reviewCount = getOptionalAttribute(attributes, "reviews");
if (reviewCount != null) {
@@ -302,22 +306,25 @@ public class SAXBugCollectionHandler extends DefaultHandler {
bugInstance.getXmlProps().setConsensus(consensus);
}
- } else if (qName.equals("FindBugsSummary")) {
+ } else if ("FindBugsSummary".equals(qName)) {
BugCollection bugCollection = this.bugCollection;
assert bugCollection != null;
String timestamp = getRequiredAttribute(attributes, "timestamp", qName);
String vmVersion = getOptionalAttribute(attributes, "vm_version");
String totalClasses = getOptionalAttribute(attributes, "total_classes");
- if (totalClasses != null && totalClasses.length() > 0)
+ if (totalClasses != null && totalClasses.length() > 0) {
bugCollection.getProjectStats().setTotalClasses(Integer.parseInt(totalClasses));
+ }
String totalSize = getOptionalAttribute(attributes, "total_size");
- if (totalSize != null && totalSize.length() > 0)
+ if (totalSize != null && totalSize.length() > 0) {
bugCollection.getProjectStats().setTotalSize(Integer.parseInt(totalSize));
+ }
String referencedClasses = getOptionalAttribute(attributes, "referenced_classes");
- if (referencedClasses != null && referencedClasses.length() > 0)
+ if (referencedClasses != null && referencedClasses.length() > 0) {
bugCollection.getProjectStats().setReferencedClasses(Integer.parseInt(referencedClasses));
+ }
bugCollection.getProjectStats().setVMVersion(vmVersion);
try {
bugCollection.getProjectStats().setTimestamp(timestamp);
@@ -325,21 +332,21 @@ public class SAXBugCollectionHandler extends DefaultHandler {
throw new SAXException("Unparseable sequence number: '" + timestamp + "'", e);
}
}
- } else if (outerElement.equals("BugInstance")) {
+ } else if ("BugInstance".equals(outerElement)) {
parseBugInstanceContents(qName, attributes);
- } else if (outerElement.equals("Method") || outerElement.equals("Field") || outerElement.equals("Class")
- || outerElement.equals("Type")) {
- if (qName.equals("SourceLine")) {
+ } else if ("Method".equals(outerElement) || "Field".equals(outerElement) || "Class".equals(outerElement)
+ || "Type".equals(outerElement)) {
+ if ("SourceLine".equals(qName)) {
// package member elements can contain nested SourceLine
// elements.
bugAnnotationWithSourceLines.setSourceLines(createSourceLineAnnotation(qName, attributes));
}
- } else if (outerElement.equals(BugCollection.ERRORS_ELEMENT_NAME)) {
- if (qName.equals(BugCollection.ANALYSIS_ERROR_ELEMENT_NAME) || qName.equals(BugCollection.ERROR_ELEMENT_NAME)) {
+ } else if (BugCollection.ERRORS_ELEMENT_NAME.equals(outerElement)) {
+ if (BugCollection.ANALYSIS_ERROR_ELEMENT_NAME.equals(qName) || BugCollection.ERROR_ELEMENT_NAME.equals(qName)) {
analysisError = new AnalysisError("Unknown error");
stackTrace.clear();
}
- } else if (outerElement.equals("FindBugsSummary") && qName.equals("PackageStats")) {
+ } else if ("FindBugsSummary".equals(outerElement) && "PackageStats".equals(qName)) {
BugCollection bugCollection = this.bugCollection;
assert bugCollection != null;
String packageName = getRequiredAttribute(attributes, "package", qName);
@@ -347,10 +354,10 @@ public class SAXBugCollectionHandler extends DefaultHandler {
int size = Integer.parseInt(getRequiredAttribute(attributes, "total_size", qName));
bugCollection.getProjectStats().putPackageStats(packageName, numClasses, size);
- } else if (outerElement.equals("PackageStats")) {
+ } else if ("PackageStats".equals(outerElement)) {
BugCollection bugCollection = this.bugCollection;
assert bugCollection != null;
- if (qName.equals("ClassStats")) {
+ if ("ClassStats".equals(qName)) {
String className = getRequiredAttribute(attributes, "class", qName);
Boolean isInterface = Boolean.valueOf(getRequiredAttribute(attributes, "interface", qName));
int size = Integer.parseInt(getRequiredAttribute(attributes, "size", qName));
@@ -360,19 +367,19 @@ public class SAXBugCollectionHandler extends DefaultHandler {
} else if (isTopLevelFilter(outerElement) || isCompoundElementTag(outerElement)) {
parseMatcher(qName, attributes);
- } else if (outerElement.equals("ClassFeatures")) {
- if (qName.equals(ClassFeatureSet.ELEMENT_NAME)) {
+ } else if ("ClassFeatures".equals(outerElement)) {
+ if (ClassFeatureSet.ELEMENT_NAME.equals(qName)) {
String className = getRequiredAttribute(attributes, "class", qName);
classFeatureSet = new ClassFeatureSet();
classFeatureSet.setClassName(className);
}
- } else if (outerElement.equals(ClassFeatureSet.ELEMENT_NAME)) {
- if (qName.equals(ClassFeatureSet.FEATURE_ELEMENT_NAME)) {
+ } else if (ClassFeatureSet.ELEMENT_NAME.equals(outerElement)) {
+ if (ClassFeatureSet.FEATURE_ELEMENT_NAME.equals(qName)) {
String value = getRequiredAttribute(attributes, "value", qName);
classFeatureSet.addFeature(value);
}
- } else if (outerElement.equals(BugCollection.HISTORY_ELEMENT_NAME)) {
- if (qName.equals(AppVersion.ELEMENT_NAME)) {
+ } else if (BugCollection.HISTORY_ELEMENT_NAME.equals(outerElement)) {
+ if (AppVersion.ELEMENT_NAME.equals(qName)) {
BugCollection bugCollection = this.bugCollection;
assert bugCollection != null;
@@ -383,24 +390,28 @@ public class SAXBugCollectionHandler extends DefaultHandler {
String codeSize = getOptionalAttribute(attributes, "codeSize");
String numClasses = getOptionalAttribute(attributes, "numClasses");
AppVersion appVersion = new AppVersion(Long.parseLong(sequence));
- if (timestamp != null)
+ if (timestamp != null) {
appVersion.setTimestamp(Long.parseLong(timestamp));
- if (releaseName != null)
+ }
+ if (releaseName != null) {
appVersion.setReleaseName(releaseName);
- if (codeSize != null)
+ }
+ if (codeSize != null) {
appVersion.setCodeSize(Integer.parseInt(codeSize));
- if (numClasses != null)
+ }
+ if (numClasses != null) {
appVersion.setNumClasses(Integer.parseInt(numClasses));
+ }
bugCollection.addAppVersion(appVersion);
} catch (NumberFormatException e) {
throw new SAXException("Invalid AppVersion element", e);
}
}
- } else if (outerElement.equals(BugCollection.PROJECT_ELEMENT_NAME)) {
+ } else if (BugCollection.PROJECT_ELEMENT_NAME.equals(outerElement)) {
Project project = this.project;
assert project != null;
- if (qName.equals(Project.CLOUD_ELEMENT_NAME)) {
+ if (Project.CLOUD_ELEMENT_NAME.equals(qName)) {
String cloudId = getRequiredAttribute(attributes, Project.CLOUD_ID_ATTRIBUTE_NAME, qName);
project.setCloudId(cloudId);
if(bugCollection != null){
@@ -410,14 +421,14 @@ public class SAXBugCollectionHandler extends DefaultHandler {
}
bugCollection.setXmlCloudDetails(Collections.unmodifiableMap(map));
}
- } else if (qName.equals(Project.PLUGIN_ELEMENT_NAME)) {
+ } else if (Project.PLUGIN_ELEMENT_NAME.equals(qName)) {
String pluginId = getRequiredAttribute(attributes, Project.PLUGIN_ID_ATTRIBUTE_NAME, qName);
Boolean enabled = Boolean.valueOf(getRequiredAttribute(attributes, Project.PLUGIN_STATUS_ELEMENT_NAME, qName));
project.setPluginStatusTrinary(pluginId, enabled);
}
- } else if (outerElement.equals(Project.CLOUD_ELEMENT_NAME)) {
- if (qName.equals(Project.CLOUD_PROPERTY_ELEMENT_NAME)) {
+ } else if (Project.CLOUD_ELEMENT_NAME.equals(outerElement)) {
+ if (Project.CLOUD_PROPERTY_ELEMENT_NAME.equals(qName)) {
cloudPropertyKey = getRequiredAttribute(attributes, "key", qName);
}
@@ -434,22 +445,25 @@ public class SAXBugCollectionHandler extends DefaultHandler {
}
private boolean isTopLevelFilter(String qName) {
- return qName.equals(FIND_BUGS_FILTER) || qName.equals("SuppressionFilter");
+ return FIND_BUGS_FILTER.equals(qName) || "SuppressionFilter".equals(qName);
}
private void addMatcher(Matcher m) {
- if (m == null)
+ if (m == null) {
throw new IllegalArgumentException("matcher must not be null");
+ }
CompoundMatcher peek = matcherStack.peek();
- if (peek == null)
+ if (peek == null) {
throw new NullPointerException("Top of stack is null");
+ }
peek.addChild(m);
if (nextMatchedIsDisabled) {
- if (peek instanceof Filter)
+ if (peek instanceof Filter) {
((Filter) peek).disable(m);
- else
+ } else {
assert false;
+ }
nextMatchedIsDisabled = false;
}
}
@@ -460,8 +474,9 @@ public class SAXBugCollectionHandler extends DefaultHandler {
}
private void pushCompoundMatcher(CompoundMatcher m) {
- if (m == null)
+ if (m == null) {
throw new IllegalArgumentException("matcher must not be null");
+ }
matcherStack.push(m);
}
@@ -469,65 +484,77 @@ public class SAXBugCollectionHandler extends DefaultHandler {
private final Set<String> outerElementTags = unmodifiableSet(new HashSet<String>(asList("And", "Match", "Or", "Not")));
private void parseMatcher(String qName, Attributes attributes) throws SAXException {
- if (DEBUG)
+ if (DEBUG) {
System.out.println(elementStack + " " + qName + " " + matcherStack);
+ }
String disabled = getOptionalAttribute(attributes, "disabled");
nextMatchedIsDisabled = "true".equals(disabled);
- if (qName.equals("Bug")) {
+ if ("Bug".equals(qName)) {
addMatcher(new BugMatcher(getOptionalAttribute(attributes, "code"), getOptionalAttribute(attributes, "pattern"),
getOptionalAttribute(attributes, "category")));
- } else if (qName.equals("Class")) {
- addMatcher(new ClassMatcher(getRequiredAttribute(attributes, "name", qName)));
- } else if (qName.equals("FirstVersion")) {
+ } else if ("Class".equals(qName)) {
+ String role = getOptionalAttribute(attributes, "role");
+ addMatcher(new ClassMatcher(getRequiredAttribute(attributes, "name", qName), role));
+ } else if ("Type".equals(qName)) {
+ String role = getOptionalAttribute(attributes, "role");
+ String typeParameters = getOptionalAttribute(attributes, "typeParameters");
+ addMatcher(new TypeMatcher(getRequiredAttribute(attributes, "descriptor", qName), role, typeParameters));
+ } else if ("FirstVersion".equals(qName)) {
addMatcher(new FirstVersionMatcher(getRequiredAttribute(attributes, "value", qName), getRequiredAttribute(attributes,
"relOp", qName)));
- } else if (qName.equals("LastVersion")) {
+ } else if ("LastVersion".equals(qName)) {
addMatcher(new LastVersionMatcher(getRequiredAttribute(attributes, "value", qName), getRequiredAttribute(attributes,
"relOp", qName)));
- } else if (qName.equals("Designation")) {
+ } else if ("Designation".equals(qName)) {
addMatcher(new DesignationMatcher(getRequiredAttribute(attributes, "designation", qName)));
- } else if (qName.equals("BugCode")) {
+ } else if ("BugCode".equals(qName)) {
addMatcher(new BugMatcher(getRequiredAttribute(attributes, "name", qName), "", ""));
- } else if (qName.equals("Local")) {
+ } else if ("Local".equals(qName)) {
addMatcher(new LocalMatcher(getRequiredAttribute(attributes, "name", qName)));
- } else if (qName.equals("BugPattern")) {
+ } else if ("BugPattern".equals(qName)) {
addMatcher(new BugMatcher("", getRequiredAttribute(attributes, "name", qName), ""));
- } else if (qName.equals("Priority") || qName.equals("Confidence")) {
+ } else if ("Priority".equals(qName)) {
addMatcher(new PriorityMatcher(getRequiredAttribute(attributes, "value", qName)));
- } else if (qName.equals("Rank")) {
+ } else if ("Confidence".equals(qName)) {
+ addMatcher(new ConfidenceMatcher(getRequiredAttribute(attributes, "value", qName)));
+ } else if ("Rank".equals(qName)) {
addMatcher(new RankMatcher(getRequiredAttribute(attributes, "value", qName)));
- } else if (qName.equals("Package")) {
+ } else if ("Package".equals(qName)) {
String pName = getRequiredAttribute(attributes, "name", qName);
pName = pName.startsWith("~") ? pName : "~" + pName.replace(".", "\\.");
addMatcher(new ClassMatcher(pName + "\\.[^.]+"));
- } else if (qName.equals("Method")) {
+ } else if ("Method".equals(qName)) {
String name = getOptionalAttribute(attributes, "name");
String params = getOptionalAttribute(attributes, "params");
String returns = getOptionalAttribute(attributes, "returns");
String role = getOptionalAttribute(attributes, "role");
addMatcher(new MethodMatcher(name, params, returns, role));
- } else if (qName.equals("Field")) {
+ } else if ("Field".equals(qName)) {
String name = getOptionalAttribute(attributes, "name");
String type = getOptionalAttribute(attributes, "type");
- addMatcher(new FieldMatcher(name, type));
- } else if (qName.equals("Or")) {
+ String role = getOptionalAttribute(attributes, "role");
+ addMatcher(new FieldMatcher(name, type, role));
+ } else if ("Or".equals(qName)) {
CompoundMatcher matcher = new OrMatcher();
pushCompoundMatcherAsChild(matcher);
- } else if (qName.equals("And") || qName.equals("Match")) {
+ } else if ("And".equals(qName) || "Match".equals(qName)) {
AndMatcher matcher = new AndMatcher();
pushCompoundMatcherAsChild(matcher);
- if (qName.equals("Match")) {
+ if ("Match".equals(qName)) {
String classregex = getOptionalAttribute(attributes, "classregex");
String classMatch = getOptionalAttribute(attributes, "class");
- if (classregex != null)
+ if (classregex != null) {
addMatcher(new ClassMatcher("~" + classregex));
- else if (classMatch != null)
+ } else if (classMatch != null) {
addMatcher(new ClassMatcher(classMatch));
+ }
}
- } else if(qName.equals("Not")) {
+ } else if("Not".equals(qName)) {
NotMatcher matcher = new NotMatcher();
pushCompoundMatcherAsChild(matcher);
+ } else if ("Source".equals(qName)) {
+ addMatcher(new SourceMatcher(getRequiredAttribute(attributes, "name", qName)));
}
nextMatchedIsDisabled = false;
}
@@ -535,22 +562,23 @@ public class SAXBugCollectionHandler extends DefaultHandler {
private void parseBugInstanceContents(String qName, Attributes attributes) throws SAXException {
// Parsing an attribute or property of a BugInstance
BugAnnotation bugAnnotation = null;
- if (qName.equals("Class")) {
+ if ("Class".equals(qName)) {
String className = getRequiredAttribute(attributes, "classname", qName);
bugAnnotation = bugAnnotationWithSourceLines = new ClassAnnotation(className);
- } else if (qName.equals("Type")) {
+ } else if ("Type".equals(qName)) {
String typeDescriptor = getRequiredAttribute(attributes, "descriptor", qName);
TypeAnnotation typeAnnotation;
bugAnnotation = bugAnnotationWithSourceLines = typeAnnotation = new TypeAnnotation(typeDescriptor);
String typeParameters = getOptionalAttribute(attributes, "typeParameters");
- if (typeParameters != null)
+ if (typeParameters != null) {
typeAnnotation.setTypeParameters(Strings.unescapeXml(typeParameters));
+ }
- } else if (qName.equals("Method") || qName.equals("Field")) {
+ } else if ("Method".equals(qName) || "Field".equals(qName)) {
String classname = getRequiredAttribute(attributes, "classname", qName);
String fieldOrMethodName = getRequiredAttribute(attributes, "name", qName);
String signature = getRequiredAttribute(attributes, "signature", qName);
- if (qName.equals("Method")) {
+ if ("Method".equals(qName)) {
String isStatic = getOptionalAttribute(attributes, "isStatic");
if (isStatic == null) {
isStatic = "false"; // Hack for old data
@@ -561,25 +589,27 @@ public class SAXBugCollectionHandler extends DefaultHandler {
} else {
String isStatic = getRequiredAttribute(attributes, "isStatic", qName);
+ String sourceSignature = getOptionalAttribute(attributes, "sourceSignature");
bugAnnotation = bugAnnotationWithSourceLines = new FieldAnnotation(classname, fieldOrMethodName, signature,
- Boolean.valueOf(isStatic));
+ sourceSignature, Boolean.valueOf(isStatic));
}
- } else if (qName.equals("SourceLine")) {
+ } else if ("SourceLine".equals(qName)) {
SourceLineAnnotation sourceAnnotation = createSourceLineAnnotation(qName, attributes);
- if (!sourceAnnotation.isSynthetic())
+ if (!sourceAnnotation.isSynthetic()) {
bugAnnotation = sourceAnnotation;
- } else if (qName.equals("Int")) {
+ }
+ } else if ("Int".equals(qName)) {
try {
String value = getRequiredAttribute(attributes, "value", qName);
bugAnnotation = new IntAnnotation(Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new SAXException("Bad integer value in Int");
}
- } else if (qName.equals("String")) {
+ } else if ("String".equals(qName)) {
String value = getRequiredAttribute(attributes, "value", qName);
bugAnnotation = StringAnnotation.fromXMLEscapedString(value);
- } else if (qName.equals("LocalVariable")) {
+ } else if ("LocalVariable".equals(qName)) {
try {
String varName = getRequiredAttribute(attributes, "name", qName);
int register = Integer.parseInt(getRequiredAttribute(attributes, "register", qName));
@@ -588,22 +618,23 @@ public class SAXBugCollectionHandler extends DefaultHandler {
} catch (NumberFormatException e) {
throw new SAXException("Invalid integer value in attribute of LocalVariable element");
}
- } else if (qName.equals("Property")) {
+ } else if ("Property".equals(qName)) {
// A BugProperty.
String propName = getRequiredAttribute(attributes, "name", qName);
String propValue = getRequiredAttribute(attributes, "value", qName);
bugInstance.setProperty(propName, propValue);
- } else if (qName.equals("UserAnnotation")) {
+ } else if ("UserAnnotation".equals(qName)) {
// ignore AnnotationText for now; will handle in endElement
String s = getOptionalAttribute(attributes, "designation"); // optional
if (s != null) {
bugInstance.setUserDesignationKey(s, null);
}
s = getOptionalAttribute(attributes, "user"); // optional
- if (s != null)
+ if (s != null) {
bugInstance.setUser(s);
+ }
s = getOptionalAttribute(attributes, "timestamp"); // optional
- if (s != null)
+ if (s != null) {
try {
long timestamp = Long.parseLong(s);
bugInstance.setUserAnnotationTimestamp(timestamp);
@@ -612,17 +643,17 @@ public class SAXBugCollectionHandler extends DefaultHandler {
// designation.
// but is there anyplace to report this?
}
+ }
s = getOptionalAttribute(attributes, "needsSync"); // optional
- if (s == null || s.equals("false"))
+ if (s == null || "false".equals(s)) {
bugInstance.setUserAnnotationDirty(false);
+ }
- } else
+ } else {
throw new SAXException("Unknown bug annotation named " + qName);
+ }
if (bugAnnotation != null) {
- String role = getOptionalAttribute(attributes, "role");
- if (role != null)
- bugAnnotation.setDescription(role);
setAnnotationRole(attributes, bugAnnotation);
bugInstance.add(bugAnnotation);
}
@@ -638,7 +669,7 @@ public class SAXBugCollectionHandler extends DefaultHandler {
return value;
}
- /**
+ /*
* Extract a hash value from an element.
*
* @param qName
@@ -647,7 +678,7 @@ public class SAXBugCollectionHandler extends DefaultHandler {
* element attributes
* @return the decoded hash value
* @throws SAXException
- */
+ *
private byte[] extractHash(String qName, Attributes attributes) throws SAXException {
String encodedHash = getRequiredAttribute(attributes, "value", qName);
byte[] hash;
@@ -658,25 +689,27 @@ public class SAXBugCollectionHandler extends DefaultHandler {
throw new SAXException("Invalid class hash", e);
}
return hash;
- }
+ }*/
private void setAnnotationRole(Attributes attributes, BugAnnotation bugAnnotation) {
String role = getOptionalAttribute(attributes, "role");
- if (role != null)
+ if (role != null) {
bugAnnotation.setDescription(role);
+ }
}
private SourceLineAnnotation createSourceLineAnnotation(String qName, Attributes attributes) throws SAXException {
String classname = getRequiredAttribute(attributes, "classname", qName);
String sourceFile = getOptionalAttribute(attributes, "sourcefile");
- if (sourceFile == null)
+ if (sourceFile == null) {
sourceFile = SourceLineAnnotation.UNKNOWN_SOURCE_FILE;
+ }
String startLine = getOptionalAttribute(attributes, "start"); // "start"/"end"
- // are now
- // optional
+ // are now
+ // optional
String endLine = getOptionalAttribute(attributes, "end"); // (were too
- // many "-1"s
- // in the xml)
+ // many "-1"s
+ // in the xml)
String startBytecode = getOptionalAttribute(attributes, "startBytecode");
String endBytecode = getOptionalAttribute(attributes, "endBytecode");
String synthetic = getOptionalAttribute(attributes, "synthetic");
@@ -688,15 +721,15 @@ public class SAXBugCollectionHandler extends DefaultHandler {
int eb = endBytecode != null ? Integer.parseInt(endBytecode) : -1;
SourceLineAnnotation s = new SourceLineAnnotation(classname, sourceFile, sl, el, sb, eb);
- if ("true".equals(synthetic))
+ if ("true".equals(synthetic)) {
s.setSynthetic(true);
+ }
return s;
} catch (NumberFormatException e) {
throw new SAXException("Bad integer value in SourceLine element", e);
}
}
- @SuppressWarnings("hiding")
@Override
public void endElement(String uri, String name, String qName) throws SAXException {
// URI should always be empty.
@@ -706,69 +739,71 @@ public class SAXBugCollectionHandler extends DefaultHandler {
nestingOfIgnoredElements--;
} else if (nestingOfIgnoredElements > 0) {
// ignore it
- } else if (qName.equals("Project")) {
+ } else if ("Project".equals(qName)) {
// noop
} else if (elementStack.size() > 1) {
String outerElement = elementStack.get(elementStack.size() - 2);
if (isTopLevelFilter(qName) || isCompoundElementTag(qName)) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" ending " + elementStack + " " + qName + " " + matcherStack);
+ }
matcherStack.pop();
- } else if (outerElement.equals(BUG_COLLECTION)) {
+ } else if (BUG_COLLECTION.equals(outerElement)) {
BugCollection bugCollection = this.bugCollection;
assert bugCollection != null;
- if (qName.equals("BugInstance")) {
+ if ("BugInstance".equals(qName)) {
bugCollection.add(bugInstance, false);
}
- } else if (outerElement.equals(PROJECT)) {
+ } else if (PROJECT.equals(outerElement)) {
Project project = this.project;
assert project != null;
- if (qName.equals("Jar"))
+ if ("Jar".equals(qName)) {
project.addFile(makeAbsolute(getTextContents()));
- else if (qName.equals("SrcDir"))
+ } else if ("SrcDir".equals(qName)) {
project.addSourceDir(makeAbsolute(getTextContents()));
- else if (qName.equals("AuxClasspathEntry"))
+ } else if ("AuxClasspathEntry".equals(qName)) {
project.addAuxClasspathEntry(makeAbsolute(getTextContents()));
+ }
- } else if (outerElement.equals(Project.CLOUD_ELEMENT_NAME) && qName.equals(Project.CLOUD_PROPERTY_ELEMENT_NAME)) {
+ } else if (Project.CLOUD_ELEMENT_NAME.equals(outerElement) && Project.CLOUD_PROPERTY_ELEMENT_NAME.equals(qName)) {
Project project = this.project;
assert project != null;
assert cloudPropertyKey != null;
project.getCloudProperties().setProperty(cloudPropertyKey, getTextContents());
cloudPropertyKey = null;
- } else if (outerElement.equals("BugInstance")) {
- if (qName.equals("UserAnnotation")) {
+ } else if ("BugInstance".equals(outerElement)) {
+ if ("UserAnnotation".equals(qName)) {
bugInstance.setAnnotationText(getTextContents(), null);
}
- } else if (outerElement.equals(BugCollection.ERRORS_ELEMENT_NAME)) {
+ } else if (BugCollection.ERRORS_ELEMENT_NAME.equals(outerElement)) {
BugCollection bugCollection = this.bugCollection;
assert bugCollection != null;
- if (qName.equals(BugCollection.ANALYSIS_ERROR_ELEMENT_NAME)) {
+ if (BugCollection.ANALYSIS_ERROR_ELEMENT_NAME.equals(qName)) {
analysisError.setMessage(getTextContents());
bugCollection.addError(analysisError);
- } else if (qName.equals(BugCollection.ERROR_ELEMENT_NAME)) {
+ } else if (BugCollection.ERROR_ELEMENT_NAME.equals(qName)) {
if (stackTrace.size() > 0) {
analysisError.setStackTrace(stackTrace.toArray(new String[stackTrace.size()]));
}
bugCollection.addError(analysisError);
- } else if (qName.equals(BugCollection.MISSING_CLASS_ELEMENT_NAME)) {
+ } else if (BugCollection.MISSING_CLASS_ELEMENT_NAME.equals(qName)) {
bugCollection.addMissingClass(getTextContents());
}
- } else if (outerElement.equals(BugCollection.ERROR_ELEMENT_NAME)) {
- if (qName.equals(BugCollection.ERROR_MESSAGE_ELEMENT_NAME)) {
+ } else if (BugCollection.ERROR_ELEMENT_NAME.equals(outerElement)) {
+ if (BugCollection.ERROR_MESSAGE_ELEMENT_NAME.equals(qName)) {
analysisError.setMessage(getTextContents());
- } else if (qName.equals(BugCollection.ERROR_EXCEPTION_ELEMENT_NAME)) {
+ } else if (BugCollection.ERROR_EXCEPTION_ELEMENT_NAME.equals(qName)) {
analysisError.setExceptionMessage(getTextContents());
- } else if (qName.equals(BugCollection.ERROR_STACK_TRACE_ELEMENT_NAME)) {
+ } else if (BugCollection.ERROR_STACK_TRACE_ELEMENT_NAME.equals(qName)) {
stackTrace.add(getTextContents());
}
- } else if (outerElement.equals("ClassFeatures")) {
- if (qName.equals(ClassFeatureSet.ELEMENT_NAME)) {
+ } else if ("ClassFeatures".equals(outerElement)) {
+ if (ClassFeatureSet.ELEMENT_NAME.equals(qName)) {
BugCollection bugCollection = this.bugCollection;
assert bugCollection != null;
@@ -783,12 +818,15 @@ public class SAXBugCollectionHandler extends DefaultHandler {
private String makeAbsolute(String possiblyRelativePath) {
if (possiblyRelativePath.contains("://") || possiblyRelativePath.startsWith("http:")
- || possiblyRelativePath.startsWith("https:") || possiblyRelativePath.startsWith("file:"))
+ || possiblyRelativePath.startsWith("https:") || possiblyRelativePath.startsWith("file:")) {
return possiblyRelativePath;
- if (base == null)
+ }
+ if (base == null) {
return possiblyRelativePath;
- if (new File(possiblyRelativePath).isAbsolute())
+ }
+ if (new File(possiblyRelativePath).isAbsolute()) {
return possiblyRelativePath;
+ }
return new File(base.getParentFile(), possiblyRelativePath).getAbsolutePath();
}
@@ -800,11 +838,10 @@ public class SAXBugCollectionHandler extends DefaultHandler {
private String getRequiredAttribute(Attributes attributes, String attrName, String elementName) throws SAXException {
String value = attributes.getValue(attrName);
- if (value == null)
+ if (value == null) {
throw new SAXException(elementName + " element missing " + attrName + " attribute");
+ }
return memoized(Strings.unescapeXml(value));
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/SelfCalls.java b/src/java/edu/umd/cs/findbugs/SelfCalls.java
index 28db135..74b2380 100644
--- a/src/java/edu/umd/cs/findbugs/SelfCalls.java
+++ b/src/java/edu/umd/cs/findbugs/SelfCalls.java
@@ -44,17 +44,17 @@ import edu.umd.cs.findbugs.ba.ClassContext;
public class SelfCalls {
private static final boolean DEBUG = SystemProperties.getBoolean("selfcalls.debug");
- private ClassContext classContext;
+ private final ClassContext classContext;
- private CallGraph callGraph;
+ private final CallGraph callGraph;
- private HashSet<Method> calledMethodSet;
+ private final HashSet<Method> calledMethodSet;
private boolean hasSynchronization;
/**
* Constructor.
- *
+ *
* @param classContext
* the ClassContext for the class
*/
@@ -72,27 +72,31 @@ public class SelfCalls {
JavaClass jclass = classContext.getJavaClass();
Method[] methods = jclass.getMethods();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Class has " + methods.length + " methods");
+ }
// Add call graph nodes for all methods
for (Method method : methods) {
callGraph.addNode(method);
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Added " + callGraph.getNumVertices() + " nodes to graph");
+ }
// Scan methods for self calls
for (Method method : methods) {
MethodGen mg = classContext.getMethodGen(method);
- if (mg == null)
+ if (mg == null) {
continue;
+ }
scan(callGraph.getNodeForMethod(method));
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Found " + callGraph.getNumEdges() + " self calls");
+ }
}
/**
@@ -113,7 +117,7 @@ public class SelfCalls {
* Determine whether we are interested in calls for the given method.
* Subclasses may override. The default version returns true for every
* method.
- *
+ *
* @param method
* the method
* @return true if we want call sites for the method, false if not
@@ -127,16 +131,19 @@ public class SelfCalls {
*/
public Iterator<CallSite> callSiteIterator() {
return new Iterator<CallSite>() {
- private Iterator<CallGraphEdge> iter = callGraph.edgeIterator();
+ private final Iterator<CallGraphEdge> iter = callGraph.edgeIterator();
+ @Override
public boolean hasNext() {
return iter.hasNext();
}
+ @Override
public CallSite next() {
return iter.next().getCallSite();
}
+ @Override
public void remove() {
iter.remove();
}
@@ -152,7 +159,7 @@ public class SelfCalls {
/**
* Scan a method for self call sites.
- *
+ *
* @param node
* the CallGraphNode for the method to be scanned
*/
@@ -160,8 +167,9 @@ public class SelfCalls {
Method method = node.getMethod();
CFG cfg = classContext.getCFG(method);
- if (method.isSynchronized())
+ if (method.isSynchronized()) {
hasSynchronization = true;
+ }
Iterator<BasicBlock> i = cfg.blockIterator();
while (i.hasNext()) {
@@ -202,8 +210,9 @@ public class SelfCalls {
// Not a big deal for now, as we are mostly just interested in calls
// to private methods, for which we will definitely see the right
// called class name.
- if (!calledClassName.equals(jclass.getClassName()))
+ if (!calledClassName.equals(jclass.getClassName())) {
return null;
+ }
String calledMethodName = inv.getMethodName(cpg);
String calledMethodSignature = inv.getSignature(cpg);
@@ -225,10 +234,10 @@ public class SelfCalls {
// Hmm...no matching method found.
// This is almost certainly because the named method
// was inherited from a superclass.
- if (DEBUG)
+ if (DEBUG) {
System.out.println("No method found for " + calledClassName + "." + calledMethodName + " : " + calledMethodSignature);
+ }
return null;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ShowHelp.java b/src/java/edu/umd/cs/findbugs/ShowHelp.java
index 354527a..bb0e7cd 100644
--- a/src/java/edu/umd/cs/findbugs/ShowHelp.java
+++ b/src/java/edu/umd/cs/findbugs/ShowHelp.java
@@ -22,36 +22,39 @@ import java.util.TreeSet;
/**
* Show command line help.
- *
+ *
* @author David Hovemeyer
*/
public class ShowHelp {
-
+
public static void main(String[] args) {
System.out.println("FindBugs version " + Version.RELEASE + ", " + Version.WEBSITE);
-
+
DetectorFactoryCollection.instance();
System.out.println("Command line options");
-
+
TreeSet<FindBugsMain> cmds = new TreeSet<FindBugsMain>();
- for(Plugin p : Plugin.getAllPlugins())
- for(FindBugsMain m : p.getAllFindBugsMain())
+ for(Plugin p : Plugin.getAllPlugins()) {
+ for(FindBugsMain m : p.getAllFindBugsMain()) {
cmds.add(m);
- for(FindBugsMain m : cmds)
- System.out.printf("fb %-12s %-12s %s%n", m.cmd, m.kind, m.description);
-
-// System.out.println();
-// System.out.println("GUI Options:");
-// FindBugsCommandLine guiCmd = new FindBugsCommandLine(true) {
-// };
-// guiCmd.printUsage(System.out);
-// System.out.println();
-// System.out.println("TextUI Options:");
-// FindBugs.showCommandLineOptions();
+ }
+ }
+ for(FindBugsMain m : cmds) {
+ System.out.printf("fb %-12s %-12s %s%n", m.cmd, m.kind, m.description);
+ }
+
+ // System.out.println();
+ // System.out.println("GUI Options:");
+ // FindBugsCommandLine guiCmd = new FindBugsCommandLine(true) {
+ // };
+ // guiCmd.printUsage(System.out);
+ // System.out.println();
+ // System.out.println("TextUI Options:");
+ // FindBugs.showCommandLineOptions();
System.out.println();
showGeneralOptions();
-
+
}
public static void showSynopsis() {
@@ -59,11 +62,11 @@ public class ShowHelp {
}
public static void showGeneralOptions() {
-
+
System.out.println("General options:");
System.out.println(" -jvmArgs args Pass args to JVM");
System.out.println(" -maxHeap size Maximum Java heap size in megabytes (default=768)");
System.out.println(" -javahome <dir> Specify location of JRE");
-
+
}
}
diff --git a/src/java/edu/umd/cs/findbugs/SloppyBugComparator.java b/src/java/edu/umd/cs/findbugs/SloppyBugComparator.java
index e7aece8..26177a6 100644
--- a/src/java/edu/umd/cs/findbugs/SloppyBugComparator.java
+++ b/src/java/edu/umd/cs/findbugs/SloppyBugComparator.java
@@ -26,37 +26,34 @@ import edu.umd.cs.findbugs.model.IdentityClassNameRewriter;
/**
* Very sloppy bug comparator: if the warnings are of the same type, and in the
* same class/method/field, assume they are the same.
- *
+ *
* @author David Hovemeyer
*/
public class SloppyBugComparator implements WarningComparator {
private static final boolean DEBUG = SystemProperties.getBoolean("sloppyComparator.debug");
- private static final long serialVersionUID = 1L;
-
private ClassNameRewriter classNameRewriter = IdentityClassNameRewriter.instance();
- /**
- * Constructor.
- */
public SloppyBugComparator() {
}
+ @Override
public void setClassNameRewriter(ClassNameRewriter classNameRewriter) {
this.classNameRewriter = classNameRewriter;
}
private int compareNullElements(Object lhs, Object rhs) {
- if (lhs == null && rhs == null)
+ if (lhs == null && rhs == null) {
return 0;
- else
+ } else {
return (lhs == null) ? -1 : 1;
+ }
}
/**
* Compare class annotations.
- *
+ *
* @param lhs
* left hand class annotation
* @param rhs
@@ -71,12 +68,14 @@ public class SloppyBugComparator implements WarningComparator {
String lhsClassName = classNameRewriter.rewriteClassName(lhs.getClassName());
String rhsClassName = classNameRewriter.rewriteClassName(rhs.getClassName());
- if (DEBUG)
+ if (DEBUG) {
System.err.println("Comparing " + lhsClassName + " and " + rhsClassName);
+ }
int cmp = lhsClassName.compareTo(rhsClassName);
- if (DEBUG)
+ if (DEBUG) {
System.err.println("\t==> " + cmp);
+ }
return cmp;
}
@@ -84,10 +83,8 @@ public class SloppyBugComparator implements WarningComparator {
if (lhs == null || rhs == null) {
return compareNullElements(lhs, rhs);
}
-
lhs = convertMethod(lhs);
rhs = convertMethod(rhs);
-
return lhs.compareTo(rhs);
}
@@ -95,13 +92,11 @@ public class SloppyBugComparator implements WarningComparator {
if (lhs == null || rhs == null) {
return compareNullElements(lhs, rhs);
}
-
lhs = convertField(lhs);
rhs = convertField(rhs);
-
- if (DEBUG)
+ if (DEBUG) {
System.err.println("Compare fields: " + lhs + " and " + rhs);
-
+ }
return lhs.compareTo(rhs);
}
@@ -113,13 +108,7 @@ public class SloppyBugComparator implements WarningComparator {
return ClassNameRewriterUtil.convertFieldAnnotation(classNameRewriter, fieldAnnotation);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.WarningComparator#compare(edu.umd.cs.findbugs.BugInstance
- * , edu.umd.cs.findbugs.BugInstance)
- */
+ @Override
public int compare(BugInstance lhs, BugInstance rhs) {
int cmp;
@@ -128,31 +117,29 @@ public class SloppyBugComparator implements WarningComparator {
BugPattern lhsPattern = lhs.getBugPattern();
BugPattern rhsPattern = rhs.getBugPattern();
String lhsAbbrev, rhsAbbrev;
- if (lhsPattern == null || rhsPattern == null) {
- lhsAbbrev = getAbbrevFromBugType(lhs.getType());
- rhsAbbrev = getAbbrevFromBugType(rhs.getType());
- } else {
- lhsAbbrev = lhsPattern.getAbbrev();
- rhsAbbrev = rhsPattern.getAbbrev();
- }
+ lhsAbbrev = lhsPattern.getAbbrev();
+ rhsAbbrev = rhsPattern.getAbbrev();
cmp = lhsAbbrev.compareTo(rhsAbbrev);
if (cmp != 0) {
- if (DEBUG)
+ if (DEBUG) {
System.err.println("bug abbrevs do not match");
+ }
return cmp;
}
// Primary class must match
cmp = compareClassesAllowingNull(lhs.getPrimaryClass(), rhs.getPrimaryClass());
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
boolean havePrimaryMethods = lhs.getPrimaryMethod() != null && rhs.getPrimaryMethod() != null;
// Primary method must match (if any)
cmp = compareMethodsAllowingNull(lhs.getPrimaryMethod(), rhs.getPrimaryMethod());
if (cmp != 0) {
- if (DEBUG)
+ if (DEBUG) {
System.err.println("primary methods do not match");
+ }
return cmp;
}
@@ -160,8 +147,9 @@ public class SloppyBugComparator implements WarningComparator {
// Primary field must match (if any)
cmp = compareFieldsAllowingNull(lhs.getPrimaryField(), rhs.getPrimaryField());
if (cmp != 0) {
- if (DEBUG)
+ if (DEBUG) {
System.err.println("primary fields do not match");
+ }
return cmp;
}
}
@@ -170,12 +158,10 @@ public class SloppyBugComparator implements WarningComparator {
return 0;
}
- /**
- * @param type
- * @return
- */
+ /*
private static String getAbbrevFromBugType(String type) {
int bar = type.indexOf('_');
return (bar >= 0) ? type.substring(0, bar) : "";
}
+ */
}
diff --git a/src/java/edu/umd/cs/findbugs/SortedBugCollection.java b/src/java/edu/umd/cs/findbugs/SortedBugCollection.java
index a0fc877..eda3311 100644
--- a/src/java/edu/umd/cs/findbugs/SortedBugCollection.java
+++ b/src/java/edu/umd/cs/findbugs/SortedBugCollection.java
@@ -168,16 +168,20 @@ public class SortedBugCollection implements BugCollection {
return dataSource;
}
+ @Override
public Project getProject() {
return project;
}
+ @Override
public @CheckForNull Cloud getCloudLazily() {
- if (cloud != null && bugsPopulated)
- cloud.bugsPopulated();
+ if (cloud != null && bugsPopulated) {
+ cloud.bugsPopulated();
+ }
return cloud;
}
+ @Override
public @Nonnull Cloud getCloud() {
if (shouldNotUsePlugin) {
return CloudFactory.getPlainCloud(this);
@@ -186,14 +190,15 @@ public class SortedBugCollection implements BugCollection {
if (result == null) {
IGuiCallback callback = getProject().getGuiCallback();
result = cloud = CloudFactory.createCloudWithoutInitializing(this);
- try {
+ try {
CloudFactory.initializeCloud(this, result);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Could not load cloud plugin "+ result.getCloudName(), e);
callback.showMessageDialog("Unable to connect to " + result.getCloudName() + ": " + Util.getNetworkErrorMessage(e));
- if (CloudFactory.FAIL_ON_CLOUD_ERROR)
+ if (CloudFactory.FAIL_ON_CLOUD_ERROR) {
throw new IllegalStateException("Could not load FindBugs Cloud plugin - to avoid this message, " +
"set -D" + CloudFactory.FAIL_ON_CLOUD_ERROR_PROP + "=false", e);
+ }
result = cloud = CloudFactory.getPlainCloud(this);
}
callback.registerCloud(getProject(), this, result);
@@ -203,23 +208,28 @@ public class SortedBugCollection implements BugCollection {
if (!result.isInitialized()) {
LOGGER.log(Level.SEVERE, "Cloud " + result.getCloudName() + " is not initialized ");
}
- if (bugsPopulated)
+ if (bugsPopulated) {
result.bugsPopulated();
+ }
return result;
}
+ @Override
public boolean isApplySuppressions() {
return applySuppressions;
}
+ @Override
public void setApplySuppressions(boolean applySuppressions) {
this.applySuppressions = applySuppressions;
}
+ @Override
public long getAnalysisTimestamp() {
return analysisTimestamp;
}
+ @Override
public void setAnalysisTimestamp(long timestamp) {
analysisTimestamp = timestamp;
}
@@ -261,6 +271,7 @@ public class SortedBugCollection implements BugCollection {
* @return true if the BugInstance was added, or false if a matching
* BugInstance was already in the BugCollection
*/
+ @Override
public boolean add(BugInstance bugInstance) {
return add(bugInstance,
bugInstance.getFirstVersion() == 0L && bugInstance.getLastVersion() == 0L);
@@ -272,6 +283,7 @@ public class SortedBugCollection implements BugCollection {
* @param message
* the error message
*/
+ @Override
public void addError(String message) {
addError(message, null);
}
@@ -279,6 +291,7 @@ public class SortedBugCollection implements BugCollection {
/**
* Get the current AppVersion.
*/
+ @Override
public AppVersion getCurrentAppVersion() {
return new AppVersion(getSequenceNumber()).setReleaseName(getReleaseName()).setTimestamp(getTimestamp())
.setNumClasses(getProjectStats().getNumClasses()).setCodeSize(getProjectStats().getCodeSize());
@@ -291,6 +304,7 @@ public class SortedBugCollection implements BugCollection {
* @param fileName
* name of the file to read
*/
+ @Override
public void readXML(String fileName) throws IOException, DocumentException {
readXML(new File(fileName));
}
@@ -349,12 +363,14 @@ public class SortedBugCollection implements BugCollection {
}
}
+ @Override
public void readXML(@WillClose InputStream in) throws IOException, DocumentException {
assert project != null;
assert in != null;
doReadXML(in, null);
}
+ @Override
public void readXML(@WillClose Reader reader) throws IOException, DocumentException {
assert project != null;
assert reader != null;
@@ -395,14 +411,16 @@ public class SortedBugCollection implements BugCollection {
xr.parse(new InputSource(reader));
} catch (SAXParseException e) {
- if (base != null)
+ if (base != null) {
throw new DocumentException("Parse error at line " + e.getLineNumber() + " : " + e.getColumnNumber() + " of "
+ base, e);
+ }
throw new DocumentException("Parse error at line " + e.getLineNumber() + " : " + e.getColumnNumber(), e);
} catch (SAXException e) {
// FIXME: throw SAXException from method?
- if (base != null)
+ if (base != null) {
throw new DocumentException("Sax error while parsing " + base, e);
+ }
throw new DocumentException("Sax error ", e);
} finally {
Util.closeSilently(reader);
@@ -415,6 +433,7 @@ public class SortedBugCollection implements BugCollection {
}
+ @Override
public void writeXML(OutputStream out) throws IOException {
writeXML(UTF8.writer(out));
}
@@ -425,10 +444,12 @@ public class SortedBugCollection implements BugCollection {
* @param fileName
* the file to write to
*/
+ @Override
public void writeXML(String fileName) throws IOException {
OutputStream out = new FileOutputStream(fileName);
- if (fileName.endsWith(".gz"))
+ if (fileName.endsWith(".gz")) {
out = new GZIPOutputStream(out);
+ }
writeXML(out);
}
@@ -440,8 +461,9 @@ public class SortedBugCollection implements BugCollection {
*/
public void writeXML(File file) throws IOException {
OutputStream out = new FileOutputStream(file);
- if (file.getName().endsWith(".gz"))
+ if (file.getName().endsWith(".gz")) {
out = new GZIPOutputStream(out);
+ }
writeXML(out);
}
@@ -450,6 +472,7 @@ public class SortedBugCollection implements BugCollection {
*
* @return the Document representing the BugCollection as a dom4j tree
*/
+ @Override
public Document toDocument() {
// if (project == null) throw new NullPointerException("No project");
assert project != null;
@@ -473,6 +496,7 @@ public class SortedBugCollection implements BugCollection {
* @param out
* the OutputStream to write to
*/
+ @Override
public void writeXML(@WillClose Writer out) throws IOException {
assert project != null;
bugsPopulated();
@@ -497,21 +521,23 @@ public class SortedBugCollection implements BugCollection {
writeXML(xmlOutput);
}
+ @Override
public void writePrologue(XMLOutput xmlOutput) throws IOException {
xmlOutput.beginDocument();
xmlOutput.openTag(
ROOT_ELEMENT_NAME,
new XMLAttributeList().addAttribute("version", analysisVersion)
- .addAttribute("sequence", String.valueOf(getSequenceNumber()))
- .addAttribute("timestamp", String.valueOf(getTimestamp()))
- .addAttribute("analysisTimestamp", String.valueOf(getAnalysisTimestamp()))
- .addAttribute("release", getReleaseName()));
+ .addAttribute("sequence", String.valueOf(getSequenceNumber()))
+ .addAttribute("timestamp", String.valueOf(getTimestamp()))
+ .addAttribute("analysisTimestamp", String.valueOf(getAnalysisTimestamp()))
+ .addAttribute("release", getReleaseName()));
project.writeXML(xmlOutput, null, this);
}
public void computeBugHashes() {
- if (preciseHashOccurrenceNumbersAvailable)
+ if (preciseHashOccurrenceNumbersAvailable) {
return;
+ }
invalidateHashes();
HashMap<String, Integer> seen = new HashMap<String, Integer>();
@@ -527,8 +553,9 @@ public class SortedBugCollection implements BugCollection {
seen.put(hash, count + 1);
}
}
- for (BugInstance bugInstance : getCollection())
+ for (BugInstance bugInstance : getCollection()) {
bugInstance.setInstanceOccurrenceMax(seen.get(bugInstance.getInstanceHash()));
+ }
preciseHashOccurrenceNumbersAvailable = true;
}
@@ -544,6 +571,7 @@ public class SortedBugCollection implements BugCollection {
* @param xmlOutput
* the XMLOutput object
*/
+ @Override
public void writeXML(@WillClose XMLOutput xmlOutput) throws IOException {
assert project != null;
try {
@@ -553,27 +581,33 @@ public class SortedBugCollection implements BugCollection {
getProjectStats().computeFileStats(this);
String commonBase = null;
for (String s : project.getSourceDirList()) {
- if (commonBase == null)
+ if (commonBase == null) {
commonBase = s;
- else
+ } else {
commonBase = commonBase.substring(0, commonPrefix(commonBase, s));
+ }
}
if (commonBase != null && commonBase.length() > 0) {
- if (commonBase.indexOf("/./") > 0)
+ if (commonBase.indexOf("/./") > 0) {
commonBase = commonBase.substring(0, commonBase.indexOf("/."));
+ }
File base = new File(commonBase);
- if (base.exists() && base.isDirectory() && base.canRead())
+ if (base.exists() && base.isDirectory() && base.canRead()) {
SourceLineAnnotation.generateRelativeSource(base, project);
+ }
}
}
- if (earlyStats && !minimalXML)
+ if (earlyStats && !minimalXML) {
getProjectStats().writeXML(xmlOutput, withMessages);
+ }
// Write BugInstances
- for (BugInstance bugInstance : getCollection())
- if (!applySuppressions || !project.getSuppressionFilter().match(bugInstance))
+ for (BugInstance bugInstance : getCollection()) {
+ if (!applySuppressions || !project.getSuppressionFilter().match(bugInstance)) {
bugInstance.writeXML(xmlOutput, this, withMessages);
+ }
+ }
writeEpilogue(xmlOutput);
@@ -585,11 +619,13 @@ public class SortedBugCollection implements BugCollection {
int commonPrefix(String s1, String s2) {
int pos = 0;
- while (pos < s1.length() && pos < s2.length() && s1.charAt(pos) == s2.charAt(pos))
+ while (pos < s1.length() && pos < s2.length() && s1.charAt(pos) == s2.charAt(pos)) {
pos++;
+ }
return pos;
}
+ @Override
public void writeEpilogue(XMLOutput xmlOutput) throws IOException {
if (withMessages) {
writeBugCategories(xmlOutput);
@@ -597,8 +633,9 @@ public class SortedBugCollection implements BugCollection {
writeBugCodes(xmlOutput);
}
// Errors, missing classes
- if (!minimalXML)
+ if (!minimalXML) {
emitErrors(xmlOutput);
+ }
if (!earlyStats && !minimalXML) {
// Statistics
@@ -632,7 +669,7 @@ public class SortedBugCollection implements BugCollection {
// Summary HTML
if (REPORT_SUMMARY_HTML) {
String html = getSummaryHTML();
- if (html != null && !html.equals("")) {
+ if (html != null && !"".equals(html)) {
xmlOutput.openTag(SUMMARY_HTML_ELEMENT_NAME);
xmlOutput.writeCDATA(html);
xmlOutput.closeTag(SUMMARY_HTML_ELEMENT_NAME);
@@ -652,8 +689,9 @@ public class SortedBugCollection implements BugCollection {
// Emit element describing each reported bug pattern
for (String bugType : bugTypeSet) {
BugPattern bugPattern = DetectorFactoryCollection.instance().lookupBugPattern(bugType);
- if (bugPattern == null)
+ if (bugPattern == null) {
continue;
+ }
XMLAttributeList attributeList = new XMLAttributeList();
attributeList.addAttribute("type", bugType);
@@ -690,8 +728,9 @@ public class SortedBugCollection implements BugCollection {
for (String bugCodeAbbrev : bugCodeSet) {
BugCode bugCode = DetectorFactoryCollection.instance().getBugCode(bugCodeAbbrev);
String bugCodeDescription = bugCode.getDescription();
- if (bugCodeDescription == null)
+ if (bugCodeDescription == null) {
continue;
+ }
XMLAttributeList attributeList = new XMLAttributeList();
attributeList.addAttribute("abbrev", bugCodeAbbrev);
@@ -719,8 +758,9 @@ public class SortedBugCollection implements BugCollection {
// Emit element describing each reported bug code
for (String bugCat : bugCatSet) {
String bugCatDescription = I18N.instance().getBugCategoryDescription(bugCat);
- if (bugCatDescription == null)
+ if (bugCatDescription == null) {
continue;
+ }
XMLAttributeList attributeList = new XMLAttributeList();
attributeList.addAttribute("category", bugCat);
@@ -764,20 +804,20 @@ public class SortedBugCollection implements BugCollection {
}
}
-// if (false && error.getNestedExceptionMessage() != null) {
-// xmlOutput.openTag(ERROR_EXCEPTION_ELEMENT_NAME);
-// xmlOutput.writeText(error.getNestedExceptionMessage());
-// xmlOutput.closeTag(ERROR_EXCEPTION_ELEMENT_NAME);
-//
-// stackTrace = error.getNestedStackTrace();
-// if (stackTrace != null) {
-// for (String aStackTrace : stackTrace) {
-// xmlOutput.openTag(ERROR_STACK_TRACE_ELEMENT_NAME);
-// xmlOutput.writeText(aStackTrace);
-// xmlOutput.closeTag(ERROR_STACK_TRACE_ELEMENT_NAME);
-// }
-// }
-// }
+ // if (false && error.getNestedExceptionMessage() != null) {
+ // xmlOutput.openTag(ERROR_EXCEPTION_ELEMENT_NAME);
+ // xmlOutput.writeText(error.getNestedExceptionMessage());
+ // xmlOutput.closeTag(ERROR_EXCEPTION_ELEMENT_NAME);
+ //
+ // stackTrace = error.getNestedStackTrace();
+ // if (stackTrace != null) {
+ // for (String aStackTrace : stackTrace) {
+ // xmlOutput.openTag(ERROR_STACK_TRACE_ELEMENT_NAME);
+ // xmlOutput.writeText(aStackTrace);
+ // xmlOutput.closeTag(ERROR_STACK_TRACE_ELEMENT_NAME);
+ // }
+ // }
+ // }
}
xmlOutput.closeTag(ERROR_ELEMENT_NAME);
}
@@ -789,8 +829,9 @@ public class SortedBugCollection implements BugCollection {
}
private static void checkInputStream(@WillNotClose InputStream in) throws IOException {
- if (!in.markSupported())
+ if (!in.markSupported()) {
return;
+ }
byte[] buf = new byte[200];
in.mark(buf.length);
@@ -842,8 +883,9 @@ public class SortedBugCollection implements BugCollection {
private static final class BoundedLinkedHashSet extends LinkedHashSet<AnalysisError> {
@Override
public boolean add(AnalysisError a) {
- if (this.size() > 1000)
+ if (this.size() > 1000) {
return false;
+ }
return super.add(a);
}
}
@@ -853,14 +895,17 @@ public class SortedBugCollection implements BugCollection {
private BugInstanceComparator() {
}
+ @Override
public int compare(BugInstance lhs, BugInstance rhs) {
ClassAnnotation lca = lhs.getPrimaryClass();
ClassAnnotation rca = rhs.getPrimaryClass();
- if (lca == null || rca == null)
+ if (lca == null || rca == null) {
throw new IllegalStateException("null class annotation: " + lca + "," + rca);
+ }
int cmp = lca.getClassName().compareTo(rca.getClassName());
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return lhs.compareTo(rhs);
}
@@ -875,15 +920,19 @@ public class SortedBugCollection implements BugCollection {
@Override
public int compare(BugInstance lhs, BugInstance rhs) {
int result = super.compare(lhs, rhs);
- if (result != 0)
+ if (result != 0) {
return result;
+ }
long diff = lhs.getFirstVersion() - rhs.getFirstVersion();
- if (diff == 0)
+ if (diff == 0) {
diff = lhs.getLastVersion() - rhs.getLastVersion();
- if (diff < 0)
+ }
+ if (diff < 0) {
return -1;
- if (diff > 0)
+ }
+ if (diff > 0) {
return 1;
+ }
return 0;
}
@@ -954,6 +1003,7 @@ public class SortedBugCollection implements BugCollection {
timestamp = -1L;
}
+ @Override
public boolean add(BugInstance bugInstance, boolean updateActiveTime) {
assert !bugsPopulated;
@@ -968,8 +1018,9 @@ public class SortedBugCollection implements BugCollection {
}
invalidateHashes();
- if (!bugInstance.isDead())
+ if (!bugInstance.isDead()) {
projectStats.addBug(bugInstance);
+ }
return bugSet.add(bugInstance);
}
@@ -982,10 +1033,12 @@ public class SortedBugCollection implements BugCollection {
return bugSet.remove(bugInstance);
}
+ @Override
public Iterator<BugInstance> iterator() {
return bugSet.iterator();
}
+ @Override
public Collection<BugInstance> getCollection() {
return Collections.unmodifiableCollection(bugSet);
}
@@ -1009,6 +1062,7 @@ public class SortedBugCollection implements BugCollection {
errorList.add(new AnalysisError(message, exception));
}
+ @Override
public void addError(AnalysisError error) {
errorList.add(error);
}
@@ -1017,17 +1071,20 @@ public class SortedBugCollection implements BugCollection {
errorList.clear();
}
+ @Override
public void addMissingClass(String className) {
- if (className == null || className.length() == 0)
+ if (className == null || className.length() == 0) {
return;
+ }
if (className.startsWith("[")) {
assert false : "Bad class name " + className;
- return;
+ return;
}
- if (className.endsWith(";"))
+ if (className.endsWith(";")) {
addError("got signature rather than classname: " + className, new IllegalArgumentException());
- else
+ } else {
missingClassSet.add(className);
+ }
}
public Collection<? extends AnalysisError> getErrors() {
@@ -1044,8 +1101,9 @@ public class SortedBugCollection implements BugCollection {
public BugInstance getMatching(BugInstance bugInstance) {
SortedSet<BugInstance> tailSet = bugSet.tailSet(bugInstance);
- if (tailSet.isEmpty())
+ if (tailSet.isEmpty()) {
return null;
+ }
BugInstance first = tailSet.first();
return bugInstance.equals(first) ? first : null;
}
@@ -1066,40 +1124,49 @@ public class SortedBugCollection implements BugCollection {
return summaryHTML;
}
+ @Override
public ProjectStats getProjectStats() {
return projectStats;
}
+ @Override
@Deprecated
public BugInstance lookupFromUniqueId(String uniqueId) {
- for (BugInstance bug : bugSet)
- if (bug.getInstanceHash().equals(uniqueId))
+ for (BugInstance bug : bugSet) {
+ if (bug.getInstanceHash().equals(uniqueId)) {
return bug;
+ }
+ }
return null;
}
/** Returns whether this bug collection contains results from multiple analysis runs,
* either of different version of the software or from different versions of FindBugs.
- *
- * @return
*/
+ @Override
public boolean isMultiversion() {
return sequence > 0;
}
+ @Override
public boolean hasDeadBugs() {
- if (sequence == 0)
+ if (sequence == 0) {
return false;
- for(BugInstance b : bugSet)
- if (b.isDead())
+ }
+ for(BugInstance b : bugSet) {
+ if (b.isDead()) {
return true;
+ }
+ }
return false;
}
+ @Override
public long getSequenceNumber() {
return sequence;
}
+ @Override
public void setSequenceNumber(long sequence) {
this.sequence = sequence;
}
@@ -1110,6 +1177,7 @@ public class SortedBugCollection implements BugCollection {
return dup;
}
+ @Override
public SortedBugCollection createEmptyCollectionWithMetadata() {
SortedBugCollection dup = new SortedBugCollection(projectStats.clone(), comparator, project);
dup.projectStats.clearBugCounts();
@@ -1133,43 +1201,53 @@ public class SortedBugCollection implements BugCollection {
invalidateHashes();
}
+ @Override
public void clearMissingClasses() {
missingClassSet.clear();
}
+ @Override
public String getReleaseName() {
- if (releaseName == null)
+ if (releaseName == null) {
return "";
+ }
return releaseName;
}
+ @Override
public void setReleaseName(String releaseName) {
this.releaseName = releaseName;
}
+ @Override
public Iterator<AppVersion> appVersionIterator() {
return appVersionList.iterator();
}
+ @Override
public void addAppVersion(AppVersion appVersion) {
appVersionList.add(appVersion);
}
+ @Override
public void clearAppVersions() {
appVersionList.clear();
sequence = 0;
}
public void trimAppVersions(long numberToRetain) {
- while (appVersionList.size() > numberToRetain)
+ while (appVersionList.size() > numberToRetain) {
appVersionList.remove(appVersionList.size() - 1);
+ }
sequence = appVersionList.size();
}
+ @Override
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
+ @Override
public long getTimestamp() {
return timestamp;
}
@@ -1178,6 +1256,7 @@ public class SortedBugCollection implements BugCollection {
return classFeatureSetMap.get(className);
}
+ @Override
public void setClassFeatureSet(ClassFeatureSet classFeatureSet) {
classFeatureSetMap.put(classFeatureSet.getClassName(), classFeatureSet);
}
@@ -1186,35 +1265,46 @@ public class SortedBugCollection implements BugCollection {
return classFeatureSetMap.values().iterator();
}
+ @Override
public void clearClassFeatures() {
classFeatureSetMap.clear();
}
+ @Override
public void setWithMessages(boolean withMessages) {
this.withMessages = withMessages;
}
+ @Override
public boolean getWithMessages() {
return withMessages;
}
+ @Override
public AppVersion getAppVersionFromSequenceNumber(long target) {
- for (AppVersion av : appVersionList)
- if (av.getSequenceNumber() == target)
+ for (AppVersion av : appVersionList) {
+ if (av.getSequenceNumber() == target) {
return av;
- if (target == this.getSequenceNumber())
+ }
+ }
+ if (target == this.getSequenceNumber()) {
return this.getCurrentAppVersion();
+ }
return null;
}
+ @Override
public BugInstance findBug(String instanceHash, String bugType, int lineNumber) {
- for (BugInstance bug : bugSet)
+ for (BugInstance bug : bugSet) {
if (bug.getInstanceHash().equals(instanceHash) && bug.getBugPattern().getType().equals(bugType)
- && bug.getPrimarySourceLineAnnotation().getStartLine() == lineNumber)
+ && bug.getPrimarySourceLineAnnotation().getStartLine() == lineNumber) {
return bug;
+ }
+ }
return null;
}
+ @Override
public void setAnalysisVersion(String version) {
this.analysisVersion = version;
}
@@ -1239,8 +1329,9 @@ public class SortedBugCollection implements BugCollection {
}
public InputStream progressMonitoredInputStream(InputStream in, int length, String msg) {
- if (GraphicsEnvironment.isHeadless())
+ if (GraphicsEnvironment.isHeadless()) {
return in;
+ }
IGuiCallback guiCallback = project.getGuiCallback();
return guiCallback.getProgressMonitorInputStream(in, length, msg);
}
@@ -1275,6 +1366,7 @@ public class SortedBugCollection implements BugCollection {
cloud = null;
}
+ @Override
public @Nonnull Cloud reinitializeCloud() {
Cloud oldCloud = cloud;
IGuiCallback callback = project.getGuiCallback();
@@ -1294,14 +1386,17 @@ public class SortedBugCollection implements BugCollection {
return cloud;
}
+ @Override
public void setXmlCloudDetails(Map<String, String> map) {
this.xmlCloudDetails = map;
}
+ @Override
public Map<String, String> getXmlCloudDetails() {
return xmlCloudDetails;
}
+ @Override
public void setMinimalXML(boolean minimalXML) {
this.minimalXML = minimalXML;
}
@@ -1310,10 +1405,10 @@ public class SortedBugCollection implements BugCollection {
this.shouldNotUsePlugin = b;
}
+ @Override
public void bugsPopulated() {
bugsPopulated = true;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/SortingBugReporter.java b/src/java/edu/umd/cs/findbugs/SortingBugReporter.java
index 4ba2a93..5f21e64 100644
--- a/src/java/edu/umd/cs/findbugs/SortingBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/SortingBugReporter.java
@@ -30,8 +30,9 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
* by class name before printing them.
*/
public class SortingBugReporter extends TextUIBugReporter {
- private SortedBugCollection bugCollection = new SortedBugCollection();
+ private final SortedBugCollection bugCollection = new SortedBugCollection();
+ @Override
public void observeClass(ClassDescriptor classDescriptor) {
// Don't need to do anything special, since we won't be
// reporting statistics.
@@ -39,10 +40,12 @@ public class SortingBugReporter extends TextUIBugReporter {
@Override
public void doReportBug(BugInstance bugInstance) {
- if (bugCollection.add(bugInstance))
+ if (bugCollection.add(bugInstance)) {
notifyObservers(bugInstance);
+ }
}
+ @Override
public void finish() {
Iterator<BugInstance> i = bugCollection.iterator();
while (i.hasNext()) {
@@ -53,10 +56,10 @@ public class SortingBugReporter extends TextUIBugReporter {
outputStream.close();
}
+ @Override
public @Nonnull
BugCollection getBugCollection() {
return bugCollection;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/SourceLineAnnotation.java b/src/java/edu/umd/cs/findbugs/SourceLineAnnotation.java
index 511631c..d672da4 100644
--- a/src/java/edu/umd/cs/findbugs/SourceLineAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/SourceLineAnnotation.java
@@ -21,6 +21,7 @@ package edu.umd.cs.findbugs;
import java.io.File;
import java.io.IOException;
+import java.util.Objects;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
@@ -80,6 +81,8 @@ public class SourceLineAnnotation implements BugAnnotation {
public static final String ROLE_LOCK_OBTAINED_AT = "SOURCE_LINE_LOCK_OBTAINED_AT";
+ public static final String ROLE_UNREACHABLE_CODE = "SOURCE_UNREACHABLE_CODE";
+
/**
* String returned if the source file is unknown. This must match what BCEL
* uses when the source file is unknown.
@@ -108,6 +111,12 @@ public class SourceLineAnnotation implements BugAnnotation {
public static final String DESCRIPTION_LOOP_BOTTOM = "SOURCE_LINE_LOOP_BOTTOM";
+ static final ThreadLocal<Project> myProject = new ThreadLocal<Project>();
+
+ static final ThreadLocal<String> relativeSourceBase = new ThreadLocal<String>();
+
+ private static final String ELEMENT_NAME = "SourceLine";
+
/**
* Constructor.
*
@@ -126,10 +135,8 @@ public class SourceLineAnnotation implements BugAnnotation {
*/
public SourceLineAnnotation(@Nonnull @DottedClassName String className, @Nonnull String sourceFile, int startLine, int endLine,
int startBytecode, int endBytecode) {
- if (className == null)
- throw new IllegalArgumentException("class name is null");
- if (sourceFile == null)
- throw new IllegalArgumentException("source file is null");
+ Objects.requireNonNull(className, "class name is null");
+ Objects.requireNonNull(sourceFile, "source file is null");
this.description = DEFAULT_ROLE;
this.className = className;
this.sourceFile = sourceFile;
@@ -196,6 +203,7 @@ public class SourceLineAnnotation implements BugAnnotation {
* the source file name
* @return the SourceLineAnnotation
*/
+ @Nonnull
public static SourceLineAnnotation createUnknown(@DottedClassName String className, String sourceFile, int startBytecode, int endBytecode) {
SourceLineAnnotation result = new SourceLineAnnotation(className, sourceFile, -1, -1, startBytecode, endBytecode);
// result.setDescription("SOURCE_LINE_UNKNOWN");
@@ -230,8 +238,9 @@ public class SourceLineAnnotation implements BugAnnotation {
LineNumberTable lineNumberTable = methodGen.getLineNumberTable(methodGen.getConstantPool());
String className = methodGen.getClassName();
int codeSize = methodGen.getInstructionList().getLength();
- if (lineNumberTable == null)
+ if (lineNumberTable == null) {
return createUnknown(className, sourceFile, 0, codeSize - 1);
+ }
return forEntireMethod(className, sourceFile, lineNumberTable, codeSize);
}
@@ -271,8 +280,9 @@ public class SourceLineAnnotation implements BugAnnotation {
*/
public static SourceLineAnnotation forEntireMethod(JavaClass javaClass, @CheckForNull Method method) {
String sourceFile = javaClass.getSourceFileName();
- if (method == null)
+ if (method == null) {
return createUnknown(javaClass.getClassName(), sourceFile);
+ }
Code code = method.getCode();
LineNumberTable lineNumberTable = method.getLineNumberTable();
if (code == null || lineNumberTable == null) {
@@ -459,8 +469,9 @@ public class SourceLineAnnotation implements BugAnnotation {
LineNumberTable lineNumberTable = method.getCode().getLineNumberTable();
String className = jclass.getClassName();
String sourceFile = jclass.getSourceFileName();
- if (lineNumberTable == null)
+ if (lineNumberTable == null) {
return createUnknown(className, sourceFile, pc, pc);
+ }
int startLine = lineNumberTable.getSourceLine(pc);
return new SourceLineAnnotation(className, sourceFile, startLine, startLine, pc, pc);
@@ -485,8 +496,9 @@ public class SourceLineAnnotation implements BugAnnotation {
String className = visitor.getDottedClassName();
String sourceFile = visitor.getSourceFile();
- if (lineNumberTable == null)
+ if (lineNumberTable == null) {
return createUnknown(className, sourceFile, startPC, endPC);
+ }
int startLine = lineNumberTable.getSourceLine(startPC);
int endLine = lineNumberTable.getSourceLine(endPC);
@@ -511,15 +523,17 @@ public class SourceLineAnnotation implements BugAnnotation {
*/
public static @Nonnull SourceLineAnnotation fromVisitedInstructionRange(ClassContext classContext, PreorderVisitor visitor,
int startPC, int endPC) {
- if (startPC > endPC)
+ if (startPC > endPC) {
throw new IllegalArgumentException("Start pc " + startPC + " greater than end pc " + endPC);
+ }
LineNumberTable lineNumberTable = getLineNumberTable(visitor);
String className = visitor.getDottedClassName();
String sourceFile = visitor.getSourceFile();
- if (lineNumberTable == null)
+ if (lineNumberTable == null) {
return createUnknown(className, sourceFile, startPC, endPC);
+ }
int startLine = lineNumberTable.getSourceLine(startPC);
int endLine = lineNumberTable.getSourceLine(endPC);
@@ -528,8 +542,9 @@ public class SourceLineAnnotation implements BugAnnotation {
public static SourceLineAnnotation fromRawData(String className, String sourceFile, int startLine, int endLine, int startPC,
int endPC) {
- if (startLine == -1)
+ if (startLine == -1) {
return createUnknown(className, sourceFile, startPC, endPC);
+ }
return new SourceLineAnnotation(className, sourceFile, startLine, endLine, startPC, endPC);
}
@@ -560,6 +575,7 @@ public class SourceLineAnnotation implements BugAnnotation {
* @return the SourceLineAnnotation, or null if we do not have line number
* information for the instruction
*/
+ @Nonnull
public static SourceLineAnnotation fromVisitedInstruction(ClassContext classContext, MethodGen methodGen, String sourceFile,
@Nonnull InstructionHandle handle) {
LineNumberTable table = methodGen.getLineNumberTable(methodGen.getConstantPool());
@@ -567,8 +583,9 @@ public class SourceLineAnnotation implements BugAnnotation {
int bytecodeOffset = handle.getPosition();
- if (table == null)
+ if (table == null) {
return createUnknown(className, sourceFile, bytecodeOffset, bytecodeOffset);
+ }
int lineNumber = table.getSourceLine(handle.getPosition());
return new SourceLineAnnotation(className, sourceFile, lineNumber, lineNumber, bytecodeOffset, bytecodeOffset);
@@ -592,8 +609,9 @@ public class SourceLineAnnotation implements BugAnnotation {
LineNumberTable lineNumberTable = methodGen.getLineNumberTable(methodGen.getConstantPool());
String className = methodGen.getClassName();
- if (lineNumberTable == null)
+ if (lineNumberTable == null) {
return createUnknown(className, sourceFile, start.getPosition(), end.getPosition());
+ }
int startLine = lineNumberTable.getSourceLine(start.getPosition());
int endLine = lineNumberTable.getSourceLine(end.getPosition());
@@ -602,21 +620,22 @@ public class SourceLineAnnotation implements BugAnnotation {
private static LineNumberTable getLineNumberTable(PreorderVisitor visitor) {
Code code = visitor.getMethod().getCode();
- if (code == null)
+ if (code == null) {
return null;
+ }
return code.getLineNumberTable();
}
- /**
- * Get the class name.
- */
- public @DottedClassName String getClassName() {
+ @Nonnull
+ @DottedClassName
+ public String getClassName() {
return className;
}
/**
* Get the source file name.
*/
+ @Nonnull
public String getSourceFile() {
return sourceFile;
}
@@ -625,7 +644,7 @@ public class SourceLineAnnotation implements BugAnnotation {
* Is the source file known?
*/
public boolean isSourceFileKnown() {
- return !sourceFile.equals(UNKNOWN_SOURCE_FILE);
+ return !UNKNOWN_SOURCE_FILE.equals(sourceFile);
}
/**
@@ -646,15 +665,13 @@ public class SourceLineAnnotation implements BugAnnotation {
return className.substring(lastDot + 1);
}
- /**
- * Get the package name.
- */
public String getPackageName() {
int lastDot = className.lastIndexOf('.');
- if (lastDot < 0)
+ if (lastDot < 0) {
return "";
- else
+ } else {
return className.substring(0, lastDot);
+ }
}
/**
@@ -692,47 +709,53 @@ public class SourceLineAnnotation implements BugAnnotation {
return startLine < 0 || endLine < 0;
}
+ @Override
public void accept(BugAnnotationVisitor visitor) {
visitor.visitSourceLineAnnotation(this);
}
+ @Override
public String format(String key, ClassAnnotation primaryClass) {
- if (key.equals("hash"))
+ if ("hash".equals(key)) {
return "";
- if (key.equals("")) {
+ }
+ if ("".equals(key)) {
StringBuilder buf = new StringBuilder();
buf.append(sourceFile);
appendLines(buf);
return buf.toString();
- } else if (key.equals("lineNumber")) {
+ } else if ("lineNumber".equals(key)) {
StringBuilder buf = new StringBuilder();
appendLinesRaw(buf);
return buf.toString();
- } else if (key.equals("full")) {
+ } else if ("full".equals(key)) {
StringBuilder buf = new StringBuilder();
String pkgName = getPackageName();
- if (!pkgName.equals("")) {
+ if (!"".equals(pkgName)) {
buf.append(pkgName.replace('.', CANONICAL_PACKAGE_SEPARATOR));
buf.append(CANONICAL_PACKAGE_SEPARATOR);
}
buf.append(sourceFile);
appendLines(buf);
return buf.toString();
- } else
+ } else {
throw new IllegalArgumentException("Unknown format key " + key);
+ }
}
private void appendLines(StringBuilder buf) {
- if (isUnknown())
+ if (isUnknown()) {
return;
+ }
buf.append(":[");
appendLinesRaw(buf);
buf.append(']');
}
private void appendLinesRaw(StringBuilder buf) {
- if (isUnknown())
+ if (isUnknown()) {
return;
+ }
if (startLine == endLine) {
buf.append("line ");
buf.append(startLine);
@@ -745,10 +768,12 @@ public class SourceLineAnnotation implements BugAnnotation {
}
+ @Override
public String getDescription() {
return description;
}
+ @Override
public void setDescription(String description) {
this.description = description.intern();
}
@@ -756,53 +781,65 @@ public class SourceLineAnnotation implements BugAnnotation {
@Override
public String toString() {
String desc = description;
- if (desc.equals(DEFAULT_ROLE) && isUnknown())
+ if (DEFAULT_ROLE.equals(desc) && isUnknown()) {
desc = DEFAULT_ROLE_UNKNOWN_LINE;
+ }
String pattern = I18N.instance().getAnnotationDescription(desc);
FindBugsMessageFormat format = new FindBugsMessageFormat(pattern);
return format.format(new BugAnnotation[] { this }, null);
}
+ @Override
public int compareTo(BugAnnotation o) {
- if (!(o instanceof SourceLineAnnotation)) // All BugAnnotations must be
- // comparable
+ if (!(o instanceof SourceLineAnnotation)) {
+ // comparable
return this.getClass().getName().compareTo(o.getClass().getName());
+ }
SourceLineAnnotation other = (SourceLineAnnotation) o;
int cmp = className.compareTo(other.className);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
cmp = startLine - other.startLine;
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
cmp = endLine - other.endLine;
- if (startLine != -1)
+ if (startLine != -1) {
return 0;
- if (cmp != 0)
+ }
+ if (cmp != 0) {
return cmp;
+ }
cmp = startBytecode - other.startBytecode;
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return endBytecode - other.endBytecode;
}
@Override
public int hashCode() {
- if (startLine != -1)
+ if (startLine != -1) {
return className.hashCode() + startLine + 3 * endLine + getDescription().hashCode();
+ }
return className.hashCode() + startBytecode + 3 * endBytecode + getDescription().hashCode();
}
@Override
public boolean equals(Object o) {
- if (!(o instanceof SourceLineAnnotation))
+ if (!(o instanceof SourceLineAnnotation)) {
return false;
+ }
SourceLineAnnotation other = (SourceLineAnnotation) o;
- if (!getDescription().equals(other.getDescription()))
+ if (!getDescription().equals(other.getDescription())) {
return false;
- if (startLine != -1)
+ }
+ if (startLine != -1) {
return className.equals(other.className) && startLine == other.startLine && endLine == other.endLine;
+ }
return className.equals(other.className) && startBytecode == other.startBytecode && endBytecode == other.endBytecode;
}
@@ -813,16 +850,11 @@ public class SourceLineAnnotation implements BugAnnotation {
* ----------------------------------------------------------------------
*/
- private static final String ELEMENT_NAME = "SourceLine";
-
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, false, false);
}
- static final ThreadLocal<Project> myProject = new ThreadLocal<Project>();
-
- static final ThreadLocal<String> relativeSourceBase = new ThreadLocal<String>();
-
public static void generateRelativeSource(File relativeSourceBase, Project project) {
try {
SourceLineAnnotation.relativeSourceBase.set(relativeSourceBase.getCanonicalPath());
@@ -837,28 +869,34 @@ public class SourceLineAnnotation implements BugAnnotation {
relativeSourceBase.remove();
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean addMessages, boolean isPrimary) throws IOException {
String classname = getClassName();
String sourcePath = getSourcePath();
XMLAttributeList attributeList = new XMLAttributeList().addAttribute("classname", classname);
- if (isPrimary)
+ if (isPrimary) {
attributeList.addAttribute("primary", "true");
+ }
int n = getStartLine(); // start/end are now optional (were too many
- // "-1"s in the xml)
- if (n >= 0)
+ // "-1"s in the xml)
+ if (n >= 0) {
attributeList.addAttribute("start", String.valueOf(n));
+ }
n = getEndLine();
- if (n >= 0)
+ if (n >= 0) {
attributeList.addAttribute("end", String.valueOf(n));
+ }
n = getStartBytecode(); // startBytecode/endBytecode haven't been set
- // for a while now
- if (n >= 0)
+ // for a while now
+ if (n >= 0) {
attributeList.addAttribute("startBytecode", String.valueOf(n));
+ }
n = getEndBytecode();
- if (n >= 0)
+ if (n >= 0) {
attributeList.addAttribute("endBytecode", String.valueOf(n));
+ }
if (isSourceFileKnown()) {
attributeList.addAttribute("sourcefile", sourceFile);
@@ -869,20 +907,22 @@ public class SourceLineAnnotation implements BugAnnotation {
SourceFinder mySourceFinder = project.getSourceFinder();
String fullPath = new File(mySourceFinder.findSourceFile(this).getFullFileName()).getCanonicalPath();
String myRelativeSourceBase = relativeSourceBase.get();
- if (fullPath.startsWith(myRelativeSourceBase) && fullPath.length() > myRelativeSourceBase.length())
- attributeList.addAttribute("relSourcepath", fullPath.substring(myRelativeSourceBase.length() + 1));
+ if (fullPath.startsWith(myRelativeSourceBase) && fullPath.length() > myRelativeSourceBase.length()) {
+ attributeList.addAttribute("relSourcepath", fullPath.substring(myRelativeSourceBase.length() + 1));
+ }
} catch (IOException e) {
assert true;
}
-
}
}
String role = getDescription();
- if (!role.equals(DEFAULT_ROLE))
+ if (!DEFAULT_ROLE.equals(role)) {
attributeList.addAttribute("role", getDescription());
- if (synthetic)
+ }
+ if (synthetic) {
attributeList.addAttribute("synthetic", "true");
+ }
if (addMessages) {
xmlOutput.openTag(ELEMENT_NAME, attributeList);
xmlOutput.openTag("Message");
@@ -897,37 +937,26 @@ public class SourceLineAnnotation implements BugAnnotation {
public String getSourcePath() {
String classname = getClassName();
String packageName = "";
- if (classname.indexOf('.') > 0)
+ if (classname.indexOf('.') > 0) {
packageName = classname.substring(0, 1 + classname.lastIndexOf('.'));
+ }
String sourcePath = packageName.replace('.', CANONICAL_PACKAGE_SEPARATOR) + sourceFile;
return sourcePath;
}
- /**
- * @param synthetic
- * The synthetic to set.
- */
public void setSynthetic(boolean synthetic) {
this.synthetic = synthetic;
}
- /**
- * @return Returns the synthetic.
- */
public boolean isSynthetic() {
return synthetic;
}
+ @Override
public boolean isSignificant() {
return false;
}
- /**
- * @param className
- * @param methodName
- * @param methodSig
- * @return
- */
static SourceLineAnnotation getSourceAnnotationForMethod(String className, String methodName, String methodSig) {
JavaClassAndMethod targetMethod = null;
Code code = null;
@@ -937,8 +966,9 @@ public class SourceLineAnnotation implements BugAnnotation {
targetMethod = Hierarchy.findMethod(targetClass, methodName, methodSig);
if (targetMethod != null) {
Method method = targetMethod.getMethod();
- if (method != null)
+ if (method != null) {
code = method.getCode();
+ }
}
} catch (ClassNotFoundException e) {
@@ -947,12 +977,14 @@ public class SourceLineAnnotation implements BugAnnotation {
SourceInfoMap sourceInfoMap = AnalysisContext.currentAnalysisContext().getSourceInfoMap();
SourceInfoMap.SourceLineRange range = sourceInfoMap.getMethodLine(className, methodName, methodSig);
- if (range != null)
+ if (range != null) {
return new SourceLineAnnotation(className, AnalysisContext.currentAnalysisContext().lookupSourceFile(className),
range.getStart(), range.getEnd(), 0, code == null ? -1 : code.getLength());
+ }
- if (sourceInfoMap.fallBackToClassfile() && targetMethod != null)
+ if (sourceInfoMap.fallBackToClassfile() && targetMethod != null) {
return forEntireMethod(targetMethod.getJavaClass(), targetMethod.getMethod());
+ }
// If we couldn't find the source lines,
// create an unknown source line annotation referencing
@@ -961,10 +993,6 @@ public class SourceLineAnnotation implements BugAnnotation {
return createUnknown(className);
}
- /**
- * @param className
- * @return
- */
static SourceLineAnnotation getSourceAnnotationForClass(String className, String sourceFileName) {
int lastLine = -1;
@@ -976,23 +1004,25 @@ public class SourceLineAnnotation implements BugAnnotation {
Code c = m.getCode();
if (c != null) {
LineNumberTable table = c.getLineNumberTable();
- if (table != null)
+ if (table != null) {
for (LineNumber line : table.getLineNumberTable()) {
lastLine = Math.max(lastLine, line.getLineNumber());
firstLine = Math.min(firstLine, line.getLineNumber());
}
+ }
}
}
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
- if (firstLine < Integer.MAX_VALUE)
+ if (firstLine < Integer.MAX_VALUE) {
return new SourceLineAnnotation(className, sourceFileName, firstLine, lastLine, -1, -1);
+ }
return SourceLineAnnotation.createUnknown(className, sourceFileName);
}
+ @Override
public String toString(ClassAnnotation primaryClass) {
return toString();
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/StackMapAnalyzer.java b/src/java/edu/umd/cs/findbugs/StackMapAnalyzer.java
index c95eeb6..91b54b7 100644
--- a/src/java/edu/umd/cs/findbugs/StackMapAnalyzer.java
+++ b/src/java/edu/umd/cs/findbugs/StackMapAnalyzer.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -52,30 +52,31 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
* @author pugh
*/
public class StackMapAnalyzer {
-
-
-
+
+
+
public static class StackMapAnalysisFactory extends edu.umd.cs.findbugs.classfile.engine.bcel.AnalysisFactory<JumpInfoFromStackMap> {
public StackMapAnalysisFactory() {
super("Jump info for opcode stack from stack map analysis", JumpInfoFromStackMap.class);
}
-
+
+ @Override
public JumpInfoFromStackMap analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) {
-
+
return getFromStackMap( analysisCache, descriptor);
-
-
+
+
}
}
-
+
static class JumpInfoFromStackMap extends JumpInfo {
JumpInfoFromStackMap(Map<Integer, List<Item>> jumpEntries, Map<Integer, List<Item>> jumpStackEntries, BitSet jumpEntryLocations) {
super(jumpEntries, jumpStackEntries, jumpEntryLocations);
}
-
+
}
static final boolean DEBUG = false;
@@ -106,12 +107,14 @@ public class StackMapAnalyzer {
}
static @CheckForNull StackMapTable getStackMapTable(Code code) {
- for(Attribute a : code.getAttributes())
- if (a instanceof StackMapTable)
+ for(Attribute a : code.getAttributes()) {
+ if (a instanceof StackMapTable) {
return (StackMapTable) a;
+ }
+ }
return null;
}
-
+
static List<Item> getInitialLocals(MethodDescriptor descriptor) {
List<Item> locals = new ArrayList<Item>();
Type[] argTypes = Type.getArgumentTypes(descriptor.getSignature());
@@ -125,56 +128,62 @@ public class StackMapAnalyzer {
Item it = Item.typeOnly(argType.getSignature());
locals.add(it);
reg += it.getSize();
- if (it.usesTwoSlots())
+ if (it.usesTwoSlots()) {
locals.add(null);
+ }
}
return locals;
}
-
+
static final @CheckForNull Field frame_type_field;
static {
Field f;
try {
- f = AccessController.doPrivileged(new PrivilegedAction<Field>() {
-
- public Field run() {
- Class<StackMapTableEntry> c = StackMapTableEntry.class;
- Field result;
- try {
- result = c.getDeclaredField("frame_type");
- result.setAccessible(true);
- return result;
- } catch (NoSuchFieldException e) {
- throw new AssertionError("frame_type field doesn't exist");
- } catch (SecurityException e) {
- return null;
+ f = AccessController.doPrivileged(new PrivilegedAction<Field>() {
+
+ @Override
+ public Field run() {
+ Class<StackMapTableEntry> c = StackMapTableEntry.class;
+ Field result;
+ try {
+ result = c.getDeclaredField("frame_type");
+ result.setAccessible(true);
+ return result;
+ } catch (NoSuchFieldException e) {
+ throw new AssertionError("frame_type field doesn't exist");
+ } catch (SecurityException e) {
+ return null;
+ }
+
}
-
- }
-
- });
+
+ });
} catch (Exception e) {
AnalysisContext.logError("Unable to create frame_type accessor",e );
f = null;
}
- System.out.println("Frame type field is null:" + (f == null));
- frame_type_field = f;
+ if (DEBUG) {
+ System.out.println("Frame type field is null:" + (f == null));
+ }
+ frame_type_field = f;
}
-
+
static int getFrameType(StackMapTableEntry e) {
- if (frame_type_field == null)
+ if (frame_type_field == null) {
return -1;
+ }
try {
return (Integer) frame_type_field.get(e);
} catch (IllegalArgumentException e1) {
- return -1;
+ return -1;
} catch (IllegalAccessException e1) {
- return -1;
+ return -1;
}
}
static private @CheckForNull JumpInfoFromStackMap getFromStackMap(IAnalysisCache analysisCache, MethodDescriptor descriptor) {
- if (frame_type_field == null)
+ if (frame_type_field == null) {
return null;
+ }
Method method;
try {
@@ -183,86 +192,91 @@ public class StackMapAnalyzer {
analysisCache.getErrorLogger().logError("Unable to get method for " + descriptor, e1);
return null;
}
-
+
Code code = method.getCode();
if (code == null) {
return null;
}
StackMapTable stackMapTable = getStackMapTable(code);
- if (stackMapTable == null)
+ if (stackMapTable == null) {
return null;
- Map<Integer, List<Item>> jumpEntries = new HashMap<Integer, List<Item>>();
-
- Map<Integer, List<Item>> jumpStackEntries = new HashMap<Integer, List<Item>>();
-
- List<Item> locals = getInitialLocals(descriptor);
- List<Item> stack = new ArrayList<Item>();
- BitSet jumpEntryLocations = new BitSet();
- if (DEBUG) {
- System.out.println(descriptor);
- System.out.println(locals);
- }
- int pc = 0;
- for(StackMapTableEntry e : stackMapTable.getStackMapTable()) {
- pc += e.getByteCodeOffsetDelta();
- StackFrameType stackFrameType = StackFrameType.get(getFrameType(e));
- switch (stackFrameType) {
- case SAME_FRAME:
- stack.clear();
- break;
- case SAME_LOCALS_1_STACK_ITEM_FRAME:
- stack.clear();
- addStack(stack, e.getTypesOfStackItems());
- break;
- case CHOP_FRAME :
- stack.clear();
- for(int i = 0; i < e.getNumberOfLocals(); i++) {
- Item it = locals.remove(locals.size()-1);
- if (it == null) {
- it = locals.remove(locals.size()-1);
- assert it.usesTwoSlots();
- }
- }
- break;
-
- case APPEND_FRAME:
-
- stack.clear();
- addLocals(locals, e.getTypesOfLocals());
-
- break;
- case FULL_FRAME:
- stack.clear();
- locals.clear();
- addLocals(locals, e.getTypesOfLocals());
- addStack(stack, e.getTypesOfStackItems());
- break;
-
- }
- if (DEBUG) {
- System.out.printf("%4d %2d %2d %12s %s%n",
-
- pc, e.getNumberOfLocals(), e.getNumberOfStackItems(), stackFrameType, e);
- System.out.printf(" %s :: %s%n", stack, locals);
- }
- if (pc > 0) {
- jumpEntries.put(pc, new ArrayList<Item>(locals));
- if (!stack.isEmpty())
- jumpStackEntries.put(pc, new ArrayList<Item>(stack));
- jumpEntryLocations.set(pc);
- }
- pc++;
- }
- if (DEBUG)
- System.out.println("\n");
- return new JumpInfoFromStackMap(jumpEntries, jumpStackEntries, jumpEntryLocations);
-
+ }
+ Map<Integer, List<Item>> jumpEntries = new HashMap<Integer, List<Item>>();
+
+ Map<Integer, List<Item>> jumpStackEntries = new HashMap<Integer, List<Item>>();
+
+ List<Item> locals = getInitialLocals(descriptor);
+ List<Item> stack = new ArrayList<Item>();
+ BitSet jumpEntryLocations = new BitSet();
+ if (DEBUG) {
+ System.out.println(descriptor);
+ System.out.println(locals);
+ }
+ int pc = 0;
+ for(StackMapTableEntry e : stackMapTable.getStackMapTable()) {
+ pc += e.getByteCodeOffsetDelta();
+ int rawFrameType = getFrameType(e);
+ StackFrameType stackFrameType = StackFrameType.get(rawFrameType);
+ switch (stackFrameType) {
+ case SAME_FRAME:
+ stack.clear();
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME:
+ stack.clear();
+ addStack(stack, e.getTypesOfStackItems());
+ break;
+ case CHOP_FRAME :
+ stack.clear();
+ int n = Constants.CHOP_FRAME_MAX+1-rawFrameType;
+ for(int i = 0; i < n; i++) {
+ Item it = locals.remove(locals.size()-1);
+ if (it == null) {
+ it = locals.remove(locals.size()-1);
+ assert it.usesTwoSlots();
+ }
+ }
+ break;
+
+ case APPEND_FRAME:
+
+ stack.clear();
+ addLocals(locals, e.getTypesOfLocals());
+
+ break;
+ case FULL_FRAME:
+ stack.clear();
+ locals.clear();
+ addLocals(locals, e.getTypesOfLocals());
+ addStack(stack, e.getTypesOfStackItems());
+ break;
+
+ }
+ if (DEBUG) {
+ System.out.printf("%4d %2d %2d %12s %s%n",
+
+ pc, e.getNumberOfLocals(), e.getNumberOfStackItems(), stackFrameType, e);
+ System.out.printf(" %s :: %s%n", stack, locals);
+ }
+ if (pc > 0) {
+ jumpEntries.put(pc, new ArrayList<Item>(locals));
+ if (!stack.isEmpty()) {
+ jumpStackEntries.put(pc, new ArrayList<Item>(stack));
+ }
+ jumpEntryLocations.set(pc);
+ }
+ pc++;
+ }
+ if (DEBUG) {
+ System.out.println("\n");
+ }
+ return new JumpInfoFromStackMap(jumpEntries, jumpStackEntries, jumpEntryLocations);
+
}
-
+
static private Item getItem(StackMapType t) {
switch (t.getType()) {
-
+
case Constants.ITEM_Double:
return Item.typeOnly("D");
case Constants.ITEM_Float:
@@ -284,7 +298,9 @@ public class StackMapAnalyzer {
int index = t.getIndex();
ConstantClass c = (ConstantClass) t.getConstantPool().getConstant(index);
String name = c.getBytes(t.getConstantPool());
- if (name.charAt(0) != '[') name = "L" + name + ";";
+ if (name.charAt(0) != '[') {
+ name = "L" + name + ";";
+ }
return Item.typeOnly(name);
default:
throw new IllegalArgumentException("Bad item type: " + t.getType());
@@ -295,17 +311,18 @@ public class StackMapAnalyzer {
for(StackMapType t : typesOfStackItems) {
Item item = getItem(t);
lst.add(item);
- if (item.usesTwoSlots())
+ if (item.usesTwoSlots()) {
lst.add(null);
+ }
}
-
+
}
static private void addStack(List<Item> lst, StackMapType[] typesOfStackItems) {
for(StackMapType t : typesOfStackItems) {
Item item = getItem(t);
lst.add(item);
}
-
+
}
}
diff --git a/src/java/edu/umd/cs/findbugs/StatelessDetector.java b/src/java/edu/umd/cs/findbugs/StatelessDetector.java
index e128ff1..840b970 100644
--- a/src/java/edu/umd/cs/findbugs/StatelessDetector.java
+++ b/src/java/edu/umd/cs/findbugs/StatelessDetector.java
@@ -23,14 +23,14 @@ package edu.umd.cs.findbugs;
/**
* is a marker interface for detectors that don't save state from one class file
* to the next.
- *
+ *
* If a detector implements this interface, a clone will be generated for each
* element it is applied to.
- *
+ *
* The idea of using this interface is questionable. Better for people writing
* stateless detectors to just not keep around state they don't need, rather
* than depending on cloning and garbage collection.
- *
+ *
*/
public interface StatelessDetector extends Cloneable {
diff --git a/src/java/edu/umd/cs/findbugs/StringAnnotation.java b/src/java/edu/umd/cs/findbugs/StringAnnotation.java
index 091f8f2..fefd346 100644
--- a/src/java/edu/umd/cs/findbugs/StringAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/StringAnnotation.java
@@ -103,19 +103,23 @@ public class StringAnnotation implements BugAnnotation {
return value;
}
+ @Override
public void accept(BugAnnotationVisitor visitor) {
visitor.visitStringAnnotation(this);
}
+ @Override
public String format(String key, ClassAnnotation primaryClass) {
String txt = value;
return txt;
}
+ @Override
public void setDescription(String description) {
this.description = description;
}
+ @Override
public String getDescription() {
return description;
}
@@ -127,16 +131,19 @@ public class StringAnnotation implements BugAnnotation {
@Override
public boolean equals(Object o) {
- if (!(o instanceof StringAnnotation))
+ if (!(o instanceof StringAnnotation)) {
return false;
+ }
return value.equals(((StringAnnotation) o).value);
}
+ @Override
public int compareTo(BugAnnotation o) {
- if (!(o instanceof StringAnnotation)) // BugAnnotations must be
- // Comparable with any type of
- // BugAnnotation
+ if (!(o instanceof StringAnnotation)) {
+ // Comparable with any type of
+ // BugAnnotation
return this.getClass().getName().compareTo(o.getClass().getName());
+ }
return value.compareTo(((StringAnnotation) o).value);
}
@@ -155,27 +162,31 @@ public class StringAnnotation implements BugAnnotation {
private static final String ELEMENT_NAME = "String";
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, false, false);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean addMessages, boolean isPrimary) throws IOException {
XMLAttributeList attributeList = new XMLAttributeList().addAttribute("value", value);
String role = getDescription();
- if (!role.equals(DEFAULT_ROLE))
+ if (!DEFAULT_ROLE.equals(role)) {
attributeList.addAttribute("role", role);
+ }
BugAnnotationUtil.writeXML(xmlOutput, ELEMENT_NAME, this, attributeList, addMessages);
}
+ @Override
public boolean isSignificant() {
return true;
}
+ @Override
public String toString(ClassAnnotation primaryClass) {
return toString();
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/SuppressionMatcher.java b/src/java/edu/umd/cs/findbugs/SuppressionMatcher.java
index 89840f3..e7d6e08 100644
--- a/src/java/edu/umd/cs/findbugs/SuppressionMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/SuppressionMatcher.java
@@ -29,9 +29,9 @@ import edu.umd.cs.findbugs.filter.Matcher;
import edu.umd.cs.findbugs.xml.XMLOutput;
public class SuppressionMatcher implements Matcher {
- private Map<ClassAnnotation, Collection<WarningSuppressor>> suppressedWarnings = new HashMap<ClassAnnotation, Collection<WarningSuppressor>>();
+ private final Map<ClassAnnotation, Collection<WarningSuppressor>> suppressedWarnings = new HashMap<ClassAnnotation, Collection<WarningSuppressor>>();
- private Map<String, Collection<WarningSuppressor>> suppressedPackageWarnings = new HashMap<String, Collection<WarningSuppressor>>();
+ private final Map<String, Collection<WarningSuppressor>> suppressedPackageWarnings = new HashMap<String, Collection<WarningSuppressor>>();
int count = 0;
@@ -60,29 +60,33 @@ public class SuppressionMatcher implements Matcher {
return count;
}
+ @Override
public boolean match(BugInstance b) {
ClassAnnotation clazz = b.getPrimaryClass().getTopLevelClass();
Collection<WarningSuppressor> c = suppressedWarnings.get(clazz);
- if (c != null)
- for (WarningSuppressor w : c)
+ if (c != null) {
+ for (WarningSuppressor w : c) {
if (w.match(b)) {
count++;
return true;
}
- for (Collection<WarningSuppressor> c2 : suppressedPackageWarnings.values())
+ }
+ }
+ for (Collection<WarningSuppressor> c2 : suppressedPackageWarnings.values()) {
for (WarningSuppressor w : c2) {
if (w.match(b)) {
count++;
return true;
}
}
+ }
return false;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
// no-op; these aren't saved to XML
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/SwitchHandler.java b/src/java/edu/umd/cs/findbugs/SwitchHandler.java
index 0cab8dd..976f1e9 100644
--- a/src/java/edu/umd/cs/findbugs/SwitchHandler.java
+++ b/src/java/edu/umd/cs/findbugs/SwitchHandler.java
@@ -37,19 +37,21 @@ public class SwitchHandler {
public SwitchHandler() {
switchOffsetStack = new ArrayList<SwitchDetails>();
}
-
+
public int stackSize() {
return switchOffsetStack.size();
}
int numEnumValues(@CheckForNull XClass c) {
- if (c == null)
+ if (c == null) {
return -1;
+ }
int total = 0;
String enumSignature = ClassName.toSignature(c.getClassDescriptor().getClassName());
for(XField f : c.getXFields()) {
if (f.getSignature().equals(enumSignature)
- && f.isPublic() && f.isFinal())
+ && f.isPublic() && f.isFinal()) {
total++;
+ }
}
return total;
}
@@ -60,20 +62,22 @@ public class SwitchHandler {
int[] switchOffsets = dbc.getSwitchOffsets();
SwitchDetails details = new SwitchDetails(dbc.getPC(), switchOffsets, dbc.getDefaultSwitchOffset(), switchOffsets.length == numEnumValues(enumType));
-
+
int size = switchOffsetStack.size();
while (--size >= 0) {
SwitchDetails existingDetail = switchOffsetStack.get(size);
- if (details.switchPC > (existingDetail.switchPC + existingDetail.swOffsets[existingDetail.swOffsets.length - 1]))
+ if (details.switchPC > (existingDetail.switchPC + existingDetail.swOffsets[existingDetail.swOffsets.length - 1])) {
switchOffsetStack.remove(size);
+ }
}
switchOffsetStack.add(details);
}
public boolean isOnSwitchOffset(DismantleBytecode dbc) {
int pc = dbc.getPC();
- if (pc == getDefaultOffset())
+ if (pc == getDefaultOffset()) {
return false;
+ }
return (pc == getNextSwitchOffset(dbc));
}
@@ -84,11 +88,13 @@ public class SwitchHandler {
SwitchDetails details = switchOffsetStack.get(size - 1);
int nextSwitchOffset = details.getNextSwitchOffset(dbc.getPC());
- if (nextSwitchOffset >= 0)
+ if (nextSwitchOffset >= 0) {
return nextSwitchOffset;
+ }
- if (dbc.getPC() <= details.getDefaultOffset())
+ if (dbc.getPC() <= details.getDefaultOffset()) {
return -1;
+ }
switchOffsetStack.remove(size - 1);
size--;
}
@@ -98,16 +104,18 @@ public class SwitchHandler {
public int getDefaultOffset() {
int size = switchOffsetStack.size();
- if (size == 0)
+ if (size == 0) {
return -1;
+ }
SwitchDetails details = switchOffsetStack.get(size - 1);
return details.getDefaultOffset();
}
public SourceLineAnnotation getCurrentSwitchStatement(BytecodeScanningDetector detector) {
- if (switchOffsetStack.isEmpty())
+ if (switchOffsetStack.isEmpty()) {
throw new IllegalStateException("No current switch statement");
+ }
SwitchDetails details = switchOffsetStack.get(switchOffsetStack.size()-1);
return SourceLineAnnotation.fromVisitedInstructionRange(
detector.getClassContext(), detector, details.switchPC, details.switchPC + details.maxOffset-1);
@@ -121,7 +129,7 @@ public class SwitchHandler {
final int maxOffset;
int nextOffset;
-
+
final boolean exhaustive;
public SwitchDetails(int pc, int[] offsets, int defOffset, boolean exhaustive) {
@@ -130,8 +138,9 @@ public class SwitchHandler {
int lastValue = -1;
int maxOffset = defOffset;
for (int offset : offsets) {
- if (maxOffset < offset)
+ if (maxOffset < offset) {
maxOffset = offset;
+ }
if (offset == defOffset) {
exhaustive = false;
}
@@ -157,18 +166,21 @@ public class SwitchHandler {
}
public int getNextSwitchOffset(int currentPC) {
- while ((nextOffset < swOffsets.length) && (currentPC > (switchPC + swOffsets[nextOffset])))
+ while ((nextOffset < swOffsets.length) && (currentPC > (switchPC + swOffsets[nextOffset]))) {
nextOffset++;
+ }
- if (nextOffset >= swOffsets.length)
+ if (nextOffset >= swOffsets.length) {
return -1;
+ }
return switchPC + swOffsets[nextOffset];
}
public int getDefaultOffset() {
- if (exhaustive)
+ if (exhaustive) {
return Short.MIN_VALUE;
+ }
return switchPC + defaultOffset;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/SystemProperties.java b/src/java/edu/umd/cs/findbugs/SystemProperties.java
index 8833118..2f2e063 100644
--- a/src/java/edu/umd/cs/findbugs/SystemProperties.java
+++ b/src/java/edu/umd/cs/findbugs/SystemProperties.java
@@ -42,9 +42,9 @@ public class SystemProperties {
public final static boolean ASSERTIONS_ENABLED;
- public static boolean RUNNING_IN_ECLIPSE = SystemProperties.class.getClassLoader().getClass().getCanonicalName()
- .startsWith("org.eclipse.osgi");
-
+ public final static boolean RUNNING_IN_ECLIPSE = SystemProperties.class.getClassLoader().getClass().getCanonicalName()
+ .startsWith("org.eclipse.osgi");
+
final static String OS_NAME;
static {
boolean tmp = false;
@@ -77,7 +77,7 @@ public class SystemProperties {
URL systemProperties = DetectorFactoryCollection.getCoreResource("systemProperties.properties");
loadPropertiesFromURL(systemProperties);
String u = System.getProperty("findbugs.loadPropertiesFrom");
- if (u != null)
+ if (u != null) {
try {
URL configURL = new URL(u);
loadPropertiesFromURL(configURL);
@@ -85,6 +85,7 @@ public class SystemProperties {
AnalysisContext.logError("Unable to load properties from " + u, e);
}
+ }
}
public static Properties getLocalProperties() {
@@ -140,8 +141,9 @@ public class SystemProperties {
boolean result = defaultValue;
try {
String value = getProperty(name);
- if (value == null)
+ if (value == null) {
return defaultValue;
+ }
result = toBoolean(value);
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
@@ -150,7 +152,7 @@ public class SystemProperties {
}
private static boolean toBoolean(String name) {
- return ((name != null) && name.equalsIgnoreCase("true"));
+ return ((name != null) && "true".equalsIgnoreCase(name));
}
/**
@@ -176,8 +178,9 @@ public class SystemProperties {
public static int getInt(String name, int defaultValue) {
try {
String value = getProperty(name);
- if (value != null)
+ if (value != null) {
return Integer.decode(value);
+ }
} catch (Exception e) {
assert true;
}
@@ -192,8 +195,9 @@ public class SystemProperties {
public static String getOSDependentProperty(String name) {
String osDependentName = name + OS_NAME;
String value = getProperty(osDependentName);
- if (value != null)
+ if (value != null) {
return value;
+ }
return getProperty(name);
}
@@ -205,8 +209,9 @@ public class SystemProperties {
public static String getProperty(String name) {
try {
String value = properties.getProperty(name);
- if (value != null)
+ if (value != null) {
return value;
+ }
return System.getProperty(name);
} catch (Exception e) {
return null;
@@ -228,8 +233,9 @@ public class SystemProperties {
public static String getProperty(String name, String defaultValue) {
try {
String value = properties.getProperty(name);
- if (value != null)
+ if (value != null) {
return value;
+ }
return System.getProperty(name, defaultValue);
} catch (Exception e) {
return defaultValue;
@@ -241,7 +247,7 @@ public class SystemProperties {
private static final String URL_REWRITE_FORMAT = getOSDependentProperty("findbugs.urlRewriteFormat");
private static final Pattern URL_REWRITE_PATTERN;
-
+
static {
Pattern p = null;
if (URL_REWRITE_PATTERN_STRING != null && URL_REWRITE_FORMAT != null) {
@@ -264,11 +270,13 @@ public class SystemProperties {
}
public static String rewriteURLAccordingToProperties(String u) {
- if (URL_REWRITE_PATTERN == null || URL_REWRITE_FORMAT == null)
+ if (URL_REWRITE_PATTERN == null || URL_REWRITE_FORMAT == null) {
return u;
+ }
Matcher m = URL_REWRITE_PATTERN.matcher(u);
- if (!m.matches() || m.groupCount() == 0)
+ if (!m.matches() || m.groupCount() == 0) {
return u;
+ }
String result = String.format(URL_REWRITE_FORMAT, m.group(1));
return result;
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/ComparableMethod.java b/src/java/edu/umd/cs/findbugs/Test.java
similarity index 78%
copy from src/java/edu/umd/cs/findbugs/ba/ComparableMethod.java
copy to src/java/edu/umd/cs/findbugs/Test.java
index e8ed264..abb89c5 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ComparableMethod.java
+++ b/src/java/edu/umd/cs/findbugs/Test.java
@@ -1,27 +1,33 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package edu.umd.cs.findbugs.ba;
+package edu.umd.cs.findbugs;
+
+import org.objectweb.asm.tree.ClassNode;
/**
* @author pugh
*/
-public interface ComparableMethod extends Comparable<ComparableMethod> {
+public class Test {
+ public static void main(String args[]) {
+ Class<?> c = ClassNode.class;
+ System.out.println(c.getName());
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/TextUIBugReporter.java b/src/java/edu/umd/cs/findbugs/TextUIBugReporter.java
index d3d2516..5f9aeb7 100644
--- a/src/java/edu/umd/cs/findbugs/TextUIBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/TextUIBugReporter.java
@@ -51,7 +51,7 @@ public abstract class TextUIBugReporter extends AbstractBugReporter {
static final String OTHER_CATEGORY_ABBREV = "X";
- protected PrintWriter outputStream = UTF8.printWriter(System.out, true);
+ protected PrintWriter outputStream = UTF8.printWriter(System.out, true);
public TextUIBugReporter() {
reportStackTrace = true;
@@ -113,10 +113,12 @@ public abstract class TextUIBugReporter extends AbstractBugReporter {
if (pattern != null) {
String categoryAbbrev = null;
BugCategory bcat = DetectorFactoryCollection.instance().getBugCategory(pattern.getCategory());
- if (bcat != null)
+ if (bcat != null) {
categoryAbbrev = bcat.getAbbrev();
- if (categoryAbbrev == null)
+ }
+ if (categoryAbbrev == null) {
categoryAbbrev = OTHER_CATEGORY_ABBREV;
+ }
outputStream.print(categoryAbbrev);
outputStream.print(" ");
}
@@ -151,8 +153,9 @@ public abstract class TextUIBugReporter extends AbstractBugReporter {
boolean errors = analysisErrors || missingClasses || getQueuedErrors().size() > 0;
analysisErrors = missingClasses = false;
super.reportQueuedErrors();
- if (errors)
+ if (errors) {
emitLine("");
+ }
}
@Override
@@ -253,4 +256,3 @@ public abstract class TextUIBugReporter extends AbstractBugReporter {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/TextUICommandLine.java b/src/java/edu/umd/cs/findbugs/TextUICommandLine.java
index ef965b7..ffc5155 100644
--- a/src/java/edu/umd/cs/findbugs/TextUICommandLine.java
+++ b/src/java/edu/umd/cs/findbugs/TextUICommandLine.java
@@ -205,10 +205,12 @@ public class TextUICommandLine extends FindBugsCommandLine {
startOptionGroup("Project configuration options:");
addOption("-auxclasspath", "classpath", "set aux classpath for analysis");
addSwitch("-auxclasspathFromInput", "read aux classpath from standard input");
+ addOption("-auxclasspathFromFile", "filepath", "read aux classpaths from a designated file");
addOption("-sourcepath", "source path", "set source path for analyzed classes");
addSwitch("-exitcode", "set exit code of process");
addSwitch("-noClassOk", "output empty warning file if no classes are specified");
addSwitch("-xargs", "get list of classfiles/jarfiles from standard input rather than command line");
+ addOption("-analyzeFromFile", "filepath", "get the list of class/jar files from a designated file");
addOption("-cloud", "id", "set cloud id");
addOption("-cloudProperty", "key=value", "set cloud property");
addOption("-bugReporters", "name,name2,-name3", "bug reporter decorators to explicitly enable/disable");
@@ -257,109 +259,115 @@ public class TextUICommandLine extends FindBugsCommandLine {
protected void handleOption(String option, String optionExtraPart) {
parsedOptions.put(option, optionExtraPart);
if (DEBUG) {
- if (optionExtraPart != null)
+ if (optionExtraPart != null) {
System.out.println("option " + option + ":" + optionExtraPart);
- else
+ } else {
System.out.println("option " + option);
+ }
}
- if (option.equals("-showPlugins")) {
+ if ("-showPlugins".equals(option)) {
System.out.println("Available plugins:");
int count = 0;
for (Iterator<Plugin> i = DetectorFactoryCollection.instance().pluginIterator(); i.hasNext();) {
Plugin plugin = i.next();
System.out.println(" " + plugin.getPluginId() + " (default: " + (plugin.isEnabledByDefault() ? "enabled" : "disabled")
+ ")");
- if (plugin.getShortDescription() != null)
+ if (plugin.getShortDescription() != null) {
System.out.println(" Description: " + plugin.getShortDescription());
- if (plugin.getProvider() != null)
+ }
+ if (plugin.getProvider() != null) {
System.out.println(" Provider: " + plugin.getProvider());
- if (plugin.getWebsite() != null)
+ }
+ if (plugin.getWebsite() != null) {
System.out.println(" Website: " + plugin.getWebsite());
+ }
++count;
}
if (count == 0) {
System.out.println(" No plugins are available (FindBugs installed incorrectly?)");
}
System.exit(0);
- } else if (option.equals("-experimental"))
- priorityThreshold = Detector.EXP_PRIORITY;
- else if (option.equals("-longBugCodes"))
+ } else if ("-experimental".equals(option)) {
+ priorityThreshold = Priorities.EXP_PRIORITY;
+ } else if ("-longBugCodes".equals(option)) {
useLongBugCodes = true;
- else if (option.equals("-progress")) {
+ } else if ("-progress".equals(option)) {
showProgress = true;
- } else if (option.equals("-timestampNow"))
+ } else if ("-timestampNow".equals(option)) {
project.setTimestamp(System.currentTimeMillis());
- else if (option.equals("-low"))
- priorityThreshold = Detector.LOW_PRIORITY;
- else if (option.equals("-medium"))
- priorityThreshold = Detector.NORMAL_PRIORITY;
- else if (option.equals("-high"))
- priorityThreshold = Detector.HIGH_PRIORITY;
- else if (option.equals("-dontCombineWarnings"))
+ } else if ("-low".equals(option)) {
+ priorityThreshold = Priorities.LOW_PRIORITY;
+ } else if ("-medium".equals(option)) {
+ priorityThreshold = Priorities.NORMAL_PRIORITY;
+ } else if ("-high".equals(option)) {
+ priorityThreshold = Priorities.HIGH_PRIORITY;
+ } else if ("-dontCombineWarnings".equals(option)) {
mergeSimilarWarnings = false;
- else if (option.equals("-sortByClass"))
+ } else if ("-sortByClass".equals(option)) {
bugReporterType = SORTING_REPORTER;
- else if (option.equals("-xml")) {
+ } else if ("-xml".equals(option)) {
bugReporterType = XML_REPORTER;
- if (!optionExtraPart.equals("")) {
- if (optionExtraPart.equals("withMessages"))
+ if (!"".equals(optionExtraPart)) {
+ if ("withMessages".equals(optionExtraPart)) {
xmlWithMessages = true;
- else if (optionExtraPart.equals("withAbridgedMessages")) {
+ } else if ("withAbridgedMessages".equals(optionExtraPart)) {
xmlWithMessages = true;
xmlWithAbridgedMessages = true;
- } else if (optionExtraPart.equals("minimal")) {
+ } else if ("minimal".equals(optionExtraPart)) {
xmlWithMessages = false;
xmlMinimal = true;
- } else
+ } else {
throw new IllegalArgumentException("Unknown option: -xml:" + optionExtraPart);
+ }
}
- } else if (option.equals("-emacs")) {
+ } else if ("-emacs".equals(option)) {
bugReporterType = EMACS_REPORTER;
- } else if (option.equals("-relaxed")) {
+ } else if ("-relaxed".equals(option)) {
relaxedReportingMode = true;
- } else if (option.equals("-train")) {
- trainingOutputDir = !optionExtraPart.equals("") ? optionExtraPart : ".";
- } else if (option.equals("-useTraining")) {
- trainingInputDir = !optionExtraPart.equals("") ? optionExtraPart : ".";
- } else if (option.equals("-html")) {
+ } else if ("-train".equals(option)) {
+ trainingOutputDir = !"".equals(optionExtraPart) ? optionExtraPart : ".";
+ } else if ("-useTraining".equals(option)) {
+ trainingInputDir = !"".equals(optionExtraPart) ? optionExtraPart : ".";
+ } else if ("-html".equals(option)) {
bugReporterType = HTML_REPORTER;
- if (!optionExtraPart.equals("")) {
+ if (!"".equals(optionExtraPart)) {
stylesheet = optionExtraPart;
} else {
stylesheet = "default.xsl";
}
- } else if (option.equals("-xdocs")) {
+ } else if ("-xdocs".equals(option)) {
bugReporterType = XDOCS_REPORTER;
- } else if (option.equals("-applySuppression")) {
+ } else if ("-applySuppression".equals(option)) {
applySuppression = true;
- } else if (option.equals("-quiet")) {
+ } else if ("-quiet".equals(option)) {
quiet = true;
- } else if (option.equals("-nested")) {
- scanNestedArchives = optionExtraPart.equals("") || Boolean.valueOf(optionExtraPart).booleanValue();
- } else if (option.equals("-exitcode")) {
+ } else if ("-nested".equals(option)) {
+ scanNestedArchives = "".equals(optionExtraPart) || Boolean.valueOf(optionExtraPart).booleanValue();
+ } else if ("-exitcode".equals(option)) {
setExitCode = true;
- } else if (option.equals("-auxclasspathFromInput")) {
+ } else if ("-auxclasspathFromInput".equals(option)) {
try {
BufferedReader in = UTF8.bufferedReader(System.in);
while (true) {
String s = in.readLine();
- if (s == null)
+ if (s == null) {
break;
+ }
addAuxClassPathEntries(s);
}
in.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
- } else if (option.equals("-noClassOk")) {
+ } else if ("-noClassOk".equals(option)) {
noClassOk = true;
- } else if (option.equals("-xargs")) {
+ } else if ("-xargs".equals(option)) {
xargs = true;
- } else if (option.equals("-justListOptions")) {
+ } else if ("-justListOptions".equals(option)) {
throw new RuntimeException("textui options are: " + parsedOptions);
- } else if (option.equals("-printConfiguration")) {
+ } else if ("-printConfiguration".equals(option)) {
printConfiguration = true;
- } else if (option.equals("-version")) {
+ } else if ("-version".equals(option)) {
printVersion = true;
} else {
if(DEBUG) {
@@ -378,57 +386,62 @@ public class TextUICommandLine extends FindBugsCommandLine {
if (DEBUG) {
System.out.println("option " + option + " is " + argument);
}
- if (option.equals("-outputFile") || option.equals("-output")) {
- if (outputFile != null)
+ if ("-outputFile".equals(option) || "-output".equals(option)) {
+ if (outputFile != null) {
throw new IllegalArgumentException("output set twice; to " + outputFile + " and to " + argument);
+ }
outputFile = new File(argument);
String fileName = outputFile.getName();
String extension = Util.getFileExtensionIgnoringGz(outputFile);
- if (bugReporterType == PRINTING_REPORTER && (extension.equals("xml") || extension.equals("fba")))
+ if (bugReporterType == PRINTING_REPORTER && ("xml".equals(extension) || "fba".equals(extension))) {
bugReporterType = XML_REPORTER;
+ }
try {
OutputStream oStream = new BufferedOutputStream(new FileOutputStream(outputFile));
- if (fileName.endsWith(".gz"))
+ if (fileName.endsWith(".gz")) {
oStream = new GZIPOutputStream(oStream);
+ }
outputStream = UTF8.printStream(oStream);
} catch (IOException e) {
System.err.println("Couldn't open " + outputFile + " for output: " + e.toString());
System.exit(1);
}
- } else if (option.equals("-cloud"))
+ } else if ("-cloud".equals(option)) {
project.setCloudId(argument);
- else if (option.equals("-cloudProperty")) {
+ } else if ("-cloudProperty".equals(option)) {
int e = argument.indexOf('=');
- if (e == -1)
+ if (e == -1) {
throw new IllegalArgumentException("Bad cloud property: " + argument);
+ }
String key = argument.substring(0, e);
String value = argument.substring(e + 1);
project.getCloudProperties().setProperty(key, value);
- } else if (option.equals("-bugReporters")) {
+ } else if ("-bugReporters".equals(option)) {
for (String s : argument.split(",")) {
- if (s.charAt(0) == '-')
+ if (s.charAt(0) == '-') {
disabledBugReporterDecorators.add(s.substring(1));
- else if (s.charAt(0) == '+')
+ } else if (s.charAt(0) == '+') {
enabledBugReporterDecorators.add(s.substring(1));
- else
+ } else {
enabledBugReporterDecorators.add(s);
+ }
}
- } else if (option.equals("-maxRank")) {
+ } else if ("-maxRank".equals(option)) {
this.rankThreshold = Integer.parseInt(argument);
- } else if (option.equals("-projectName")) {
+ } else if ("-projectName".equals(option)) {
this.projectName = argument;
- } else if (option.equals("-release")) {
+ } else if ("-release".equals(option)) {
this.releaseName = argument;
- } else if (option.equals("-redoAnalysis")) {
+ } else if ("-redoAnalysis".equals(option)) {
redoAnalysisFile = argument;
- } else if (option.equals("-sourceInfo")) {
+ } else if ("-sourceInfo".equals(option)) {
sourceInfoFile = argument;
- } else if (option.equals("-visitors") || option.equals("-omitVisitors")) {
- boolean omit = option.equals("-omitVisitors");
+ } else if ("-visitors".equals(option) || "-omitVisitors".equals(option)) {
+ boolean omit = "-omitVisitors".equals(option);
if (!omit) {
// Selecting detectors explicitly, so start out by
@@ -442,20 +455,23 @@ public class TextUICommandLine extends FindBugsCommandLine {
while (tok.hasMoreTokens()) {
String visitorName = tok.nextToken().trim();
DetectorFactory factory = DetectorFactoryCollection.instance().getFactory(visitorName);
- if (factory == null)
+ if (factory == null) {
throw new IllegalArgumentException("Unknown detector: " + visitorName);
+ }
getUserPreferences().enableDetector(factory, !omit);
}
- } else if (option.equals("-chooseVisitors")) {
+ } else if ("-chooseVisitors".equals(option)) {
// This is like -visitors and -omitVisitors, but
// you can selectively enable and disable detectors,
// starting from the default set (or whatever set
// happens to be in effect).
choose(argument, "Detector choices", new Chooser() {
+ @Override
public void choose(boolean enabled, String what) {
DetectorFactory factory = DetectorFactoryCollection.instance().getFactory(what);
- if (factory == null)
+ if (factory == null) {
throw new IllegalArgumentException("Unknown detector: " + what);
+ }
if (FindBugs.DEBUG) {
System.err.println("Detector " + factory.getShortName() + " " + (enabled ? "enabled" : "disabled")
+ ", userPreferences=" + System.identityHashCode(getUserPreferences()));
@@ -463,17 +479,19 @@ public class TextUICommandLine extends FindBugsCommandLine {
getUserPreferences().enableDetector(factory, enabled);
}
});
- } else if (option.equals("-choosePlugins")) {
+ } else if ("-choosePlugins".equals(option)) {
// Selectively enable/disable plugins
choose(argument, "Plugin choices", new Chooser() {
+ @Override
public void choose(boolean enabled, String what) {
Plugin plugin = DetectorFactoryCollection.instance().getPluginById(what);
- if (plugin == null)
+ if (plugin == null) {
throw new IllegalArgumentException("Unknown plugin: " + what);
+ }
plugin.setGloballyEnabled(enabled);
}
});
- } else if (option.equals("-adjustPriority")) {
+ } else if ("-adjustPriority".equals(option)) {
// Selectively raise or lower the priority of warnings
// produced by specified detectors.
@@ -481,64 +499,73 @@ public class TextUICommandLine extends FindBugsCommandLine {
while (tok.hasMoreTokens()) {
String token = tok.nextToken();
int eq = token.indexOf('=');
- if (eq < 0)
+ if (eq < 0) {
throw new IllegalArgumentException("Illegal priority adjustment: " + token);
+ }
String adjustmentTarget = token.substring(0, eq);
String adjustment = token.substring(eq + 1);
int adjustmentAmount;
- if (adjustment.equals("raise"))
+ if ("raise".equals(adjustment)) {
adjustmentAmount = -1;
- else if (adjustment.equals("lower"))
+ } else if ("lower".equals(adjustment)) {
adjustmentAmount = +1;
- else if (adjustment.equals("suppress"))
+ } else if ("suppress".equals(adjustment)) {
adjustmentAmount = +100;
- else
+ } else {
throw new IllegalArgumentException("Illegal priority adjustment value: " + adjustment);
+ }
DetectorFactory factory = DetectorFactoryCollection.instance().getFactory(adjustmentTarget);
- if (factory != null)
+ if (factory != null) {
factory.setPriorityAdjustment(adjustmentAmount);
- else {
+ } else {
//
DetectorFactoryCollection i18n = DetectorFactoryCollection.instance();
BugPattern pattern = i18n.lookupBugPattern(adjustmentTarget);
- if (pattern == null)
+ if (pattern == null) {
throw new IllegalArgumentException("Unknown detector: " + adjustmentTarget);
+ }
pattern.adjustPriority(adjustmentAmount);
}
}
- } else if (option.equals("-bugCategories")) {
+ } else if ("-bugCategories".equals(option)) {
this.bugCategorySet = FindBugs.handleBugCategories(argument);
- } else if (option.equals("-onlyAnalyze")) {
+ } else if ("-onlyAnalyze".equals(option)) {
// The argument is a comma-separated list of classes and packages
// to select to analyze. (If a list item ends with ".*",
// it specifies a package, otherwise it's a class.)
StringTokenizer tok = new StringTokenizer(argument, ",");
while (tok.hasMoreTokens()) {
String item = tok.nextToken();
- if (item.endsWith(".-"))
+ if (item.endsWith(".-")) {
classScreener.addAllowedPrefix(item.substring(0, item.length() - 1));
- else if (item.endsWith(".*"))
+ } else if (item.endsWith(".*")) {
classScreener.addAllowedPackage(item.substring(0, item.length() - 1));
- else
+ } else {
classScreener.addAllowedClass(item);
+ }
}
- } else if (option.equals("-exclude")) {
+ } else if ("-exclude".equals(option)) {
project.getConfiguration().getExcludeFilterFiles().put(argument, true);
- } else if (option.equals("-excludeBugs")) {
+ } else if ("-excludeBugs".equals(option)) {
project.getConfiguration().getExcludeBugsFiles().put(argument, true);
- } else if (option.equals("-include")) {
+ } else if ("-include".equals(option)) {
project.getConfiguration().getIncludeFilterFiles().put(argument, true);
- } else if (option.equals("-auxclasspath")) {
+ } else if ("-auxclasspathFromFile".equals(option)) {
+ handleAuxClassPathFromFile(argument);
+ } else if ("-analyzeFromFile".equals(option)) {
+ handleAnalyzeFromFile(argument);
+ } else if ("-auxclasspath".equals(option)) {
addAuxClassPathEntries(argument);
- } else if (option.equals("-sourcepath")) {
+ } else if ("-sourcepath".equals(option)) {
StringTokenizer tok = new StringTokenizer(argument, File.pathSeparator);
- while (tok.hasMoreTokens())
+ while (tok.hasMoreTokens()) {
project.addSourceDir(new File(tok.nextToken()).getAbsolutePath());
- } else if(option.equals("-userPrefs")){
+ }
+ } else if("-userPrefs".equals(option)){
UserPreferences prefs = UserPreferences.createDefaultUserPreferences();
prefs.read(new FileInputStream(argument));
project.setConfiguration(prefs);
@@ -554,8 +581,9 @@ public class TextUICommandLine extends FindBugsCommandLine {
*/
private void addAuxClassPathEntries(String argument) {
StringTokenizer tok = new StringTokenizer(argument, File.pathSeparator);
- while (tok.hasMoreTokens())
+ while (tok.hasMoreTokens()) {
project.addAuxClasspathEntry(tok.nextToken());
+ }
}
/**
@@ -572,8 +600,9 @@ public class TextUICommandLine extends FindBugsCommandLine {
StringTokenizer tok = new StringTokenizer(argument, ",");
while (tok.hasMoreTokens()) {
String what = tok.nextToken().trim();
- if (!what.startsWith("+") && !what.startsWith("-"))
+ if (!what.startsWith("+") && !what.startsWith("-")) {
throw new IllegalArgumentException(desc + " must start with " + "\"+\" or \"-\" (saw " + what + ")");
+ }
boolean enabled = what.startsWith("+");
chooser.choose(enabled, what.substring(1));
}
@@ -613,7 +642,7 @@ public class TextUICommandLine extends FindBugsCommandLine {
textuiBugReporter = xmlBugReporter;
}
- break;
+ break;
case EMACS_REPORTER:
textuiBugReporter = new EmacsBugReporter();
break;
@@ -627,16 +656,18 @@ public class TextUICommandLine extends FindBugsCommandLine {
throw new IllegalStateException();
}
- if (quiet)
+ if (quiet) {
textuiBugReporter.setErrorVerbosity(BugReporter.SILENT);
+ }
textuiBugReporter.setPriorityThreshold(priorityThreshold);
textuiBugReporter.setRankThreshold(rankThreshold);
textuiBugReporter.setUseLongBugCodes(useLongBugCodes);
findBugs.setRankThreshold(rankThreshold);
- if (outputStream != null)
+ if (outputStream != null) {
textuiBugReporter.setOutputStream(outputStream);
+ }
BugReporter bugReporter = textuiBugReporter;
@@ -695,15 +726,58 @@ public class TextUICommandLine extends FindBugsCommandLine {
if (getXargs()) {
BufferedReader in = UTF8.bufferedReader(System.in);
try {
+ while (true) {
+ String s = in.readLine();
+ if (s == null) {
+ break;
+ }
+ project.addFile(s);
+ }
+ } finally {
+ Util.closeSilently(in);
+ }
+ }
+ }
+
+ /**
+ * Handle -readAuxFromFile command line option by reading classpath entries
+ * from a file and adding them to the project.
+ *
+ * @throws IOException
+ */
+ private void handleAuxClassPathFromFile(String filePath) throws IOException {
+ BufferedReader in = new BufferedReader(UTF8.fileReader(filePath));
+ try {
while (true) {
String s = in.readLine();
- if (s == null)
+ if (s == null) {
break;
- project.addFile(s);
+ }
+ project.addAuxClasspathEntry(s);
}
- } finally {
- Util.closeSilently(in);
+ } finally {
+ Util.closeSilently(in);
+ }
+ }
+
+ /**
+ * Handle -analyzeFromFile command line option by reading jar file names
+ * from a file and adding them to the project.
+ *
+ * @throws IOException
+ */
+ private void handleAnalyzeFromFile(String filePath) throws IOException {
+ BufferedReader in = new BufferedReader(UTF8.fileReader(filePath));
+ try {
+ while (true) {
+ String s = in.readLine();
+ if (s == null) {
+ break;
+ }
+ project.addFile(s);
}
+ } finally {
+ Util.closeSilently(in);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/TextUIProgressCallback.java b/src/java/edu/umd/cs/findbugs/TextUIProgressCallback.java
index 5398663..ca95ebb 100644
--- a/src/java/edu/umd/cs/findbugs/TextUIProgressCallback.java
+++ b/src/java/edu/umd/cs/findbugs/TextUIProgressCallback.java
@@ -24,11 +24,11 @@ import java.io.PrintStream;
/**
* Display FindBugs progress in the terminal window using ASCII codes. We assume
* that the terminal window is at least 80 characters wide.
- *
+ *
* @author David Hovemeyer
*/
public class TextUIProgressCallback implements FindBugsProgress {
- private PrintStream out;
+ private final PrintStream out;
private int goal;
@@ -42,16 +42,19 @@ public class TextUIProgressCallback implements FindBugsProgress {
this.out = out;
}
+ @Override
public void reportNumberOfArchives(int numArchives) {
this.goal = numArchives;
this.count = 0;
scanningArchives(0);
}
+ @Override
public void finishArchive() {
scanningArchives(++count);
}
+ @Override
public void predictPassCount(int[] classesPerPass) {
out.println();
printMessage(classesPerPass.length + " analysis passes to perform");
@@ -59,6 +62,7 @@ public class TextUIProgressCallback implements FindBugsProgress {
this.pass = 0;
}
+ @Override
public void startAnalysis(int numClasses) {
if (pass == 0) {
out.println();
@@ -68,10 +72,12 @@ public class TextUIProgressCallback implements FindBugsProgress {
analyzingClasses(0);
}
+ @Override
public void finishClass() {
analyzingClasses(++count);
}
+ @Override
public void finishPerClassAnalysis() {
out.println();
++pass;
@@ -97,6 +103,7 @@ public class TextUIProgressCallback implements FindBugsProgress {
out.print("\r" + msg);
}
+ @Override
public void startArchive(String name) {
// noop
}
diff --git a/src/java/edu/umd/cs/findbugs/Token.java b/src/java/edu/umd/cs/findbugs/Token.java
index d42211c..d1ed0a3 100644
--- a/src/java/edu/umd/cs/findbugs/Token.java
+++ b/src/java/edu/umd/cs/findbugs/Token.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs;
/**
* Simple token class.
- *
+ *
* @author David Hovemeyer
* @see Tokenizer
*/
@@ -56,13 +56,13 @@ public class Token {
*/
public static final int COMMENT = 3;
- private int kind;
+ private final int kind;
- private String lexeme;
+ private final String lexeme;
/**
* Constructor.
- *
+ *
* @param kind
* the kind of token
* @param lexeme
@@ -75,7 +75,7 @@ public class Token {
/**
* Constructor when there is no text. E.g., EOF and EOL.
- *
+ *
* @param kind
* the kind of token
*/
@@ -99,4 +99,3 @@ public class Token {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/Tokenizer.java b/src/java/edu/umd/cs/findbugs/Tokenizer.java
index 3138bf0..fef484f 100644
--- a/src/java/edu/umd/cs/findbugs/Tokenizer.java
+++ b/src/java/edu/umd/cs/findbugs/Tokenizer.java
@@ -27,7 +27,7 @@ import java.util.BitSet;
/**
* A simple tokenizer for Java source text. This is not intended to be a
* compliant lexer; instead, it is for quick and dirty scanning.
- *
+ *
* @author David Hovemeyer
* @see Token
*/
@@ -69,11 +69,11 @@ public class Tokenizer {
single.set('~');
}
- private PushbackReader reader;
+ private final PushbackReader reader;
/**
* Constructor.
- *
+ *
* @param reader
* the Reader for the Java source text
*/
@@ -83,23 +83,23 @@ public class Tokenizer {
/**
* Get the next Token in the stream.
- *
+ *
* @return the Token
*/
public Token next() throws IOException {
skipWhitespace();
int c = reader.read();
- if (c < 0)
+ if (c < 0) {
return new Token(Token.EOF);
- else if (c == '\n')
+ } else if (c == '\n') {
return new Token(Token.EOL);
- else if (c == '\'' || c == '"')
+ } else if (c == '\'' || c == '"') {
return munchString(c);
- else if (c == '/')
+ } else if (c == '/') {
return maybeComment();
- else if (single.get(c))
+ } else if (single.get(c)) {
return new Token(Token.SINGLE, String.valueOf((char) c));
- else {
+ } else {
reader.unread(c);
return parseWord();
}
@@ -108,8 +108,9 @@ public class Tokenizer {
private void skipWhitespace() throws IOException {
for (;;) {
int c = reader.read();
- if (c < 0)
+ if (c < 0) {
break;
+ }
if (!whiteSpace.get(c)) {
reader.unread(c);
break;
@@ -128,19 +129,23 @@ public class Tokenizer {
while (state != DONE) {
int c = reader.read();
- if (c < 0)
+ if (c < 0) {
break;
+ }
result.append((char) c);
switch (state) {
case SCAN:
- if (c == delimiter)
+ if (c == delimiter) {
state = DONE;
- else if (c == '\\')
+ } else if (c == '\\') {
state = ESCAPE;
+ }
break;
case ESCAPE:
state = SCAN;
break;
+ default:
+ break;
}
}
return new Token(Token.STRING, result.toString());
@@ -154,9 +159,9 @@ public class Tokenizer {
result.append("//");
for (;;) {
c = reader.read();
- if (c < 0)
+ if (c < 0) {
break;
- else if (c == '\n') {
+ } else if (c == '\n') {
reader.unread(c);
break;
}
@@ -173,20 +178,23 @@ public class Tokenizer {
int state = SCAN;
while (state != DONE) {
c = reader.read();
- if (c < 0)
+ if (c < 0) {
state = DONE;
- else
+ } else {
result.append((char) c);
+ }
switch (state) {
case SCAN:
- if (c == '*')
+ if (c == '*') {
state = STAR;
+ }
break;
case STAR:
- if (c == '/')
+ if (c == '/') {
state = DONE;
- else if (c != '*')
+ } else if (c != '*') {
state = SCAN;
+ }
break;
case DONE:
break;
@@ -194,8 +202,9 @@ public class Tokenizer {
}
return new Token(Token.COMMENT, result.toString());
} else {
- if (c >= 0)
+ if (c >= 0) {
reader.unread(c);
+ }
return new Token(Token.SINGLE, "/");
}
}
@@ -204,8 +213,9 @@ public class Tokenizer {
StringBuilder result = new StringBuilder();
for (;;) {
int c = reader.read();
- if (c < 0)
+ if (c < 0) {
break;
+ }
if (whiteSpace.get(c) || c == '\n' || single.get(c)) {
reader.unread(c);
break;
@@ -216,4 +226,3 @@ public class Tokenizer {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/TrainingDetector.java b/src/java/edu/umd/cs/findbugs/TrainingDetector.java
index 2ca9e43..5e729c4 100644
--- a/src/java/edu/umd/cs/findbugs/TrainingDetector.java
+++ b/src/java/edu/umd/cs/findbugs/TrainingDetector.java
@@ -20,7 +20,7 @@ package edu.umd.cs.findbugs;
/**
* Interface to mark Detector classes which are used only as a training pass.
- *
+ *
* @author David Hovemeyer
*/
public interface TrainingDetector {
diff --git a/src/java/edu/umd/cs/findbugs/TypeAnnotation.java b/src/java/edu/umd/cs/findbugs/TypeAnnotation.java
index d5ec80c..eac125d 100644
--- a/src/java/edu/umd/cs/findbugs/TypeAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/TypeAnnotation.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* Bug annotation class for java types. This is of lighter weight than
* ClassAnnotation, and can be used for things like array types.
- *
+ *
* @see ClassAnnotation
*/
public class TypeAnnotation extends BugAnnotationWithSourceLines {
@@ -56,14 +56,14 @@ public class TypeAnnotation extends BugAnnotationWithSourceLines {
/**
* constructor.
- *
+ *
* <p>
* For information on type descriptors, <br>
* see http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.
* html#14152 <br>
* or http://www.murrayc.com/learning/java/java_classfileformat.shtml#
* TypeDescriptors
- *
+ *
* @param typeDescriptor
* a jvm type descriptor, such as "[I"
*/
@@ -79,8 +79,9 @@ public class TypeAnnotation extends BugAnnotationWithSourceLines {
this(objectType.getSignature(), roleDescription);
if (objectType instanceof GenericObjectType) {
GenericObjectType genericObjectType = (GenericObjectType) objectType;
- if (genericObjectType.getTypeCategory() == GenericUtilities.TypeCategory.PARAMETERIZED)
+ if (genericObjectType.getTypeCategory() == GenericUtilities.TypeCategory.PARAMETERIZED) {
typeParameters = genericObjectType.getGenericParametersAsString();
+ }
}
}
@@ -93,40 +94,47 @@ public class TypeAnnotation extends BugAnnotationWithSourceLines {
if (context != null) {
this.sourceFileName = context.lookupSourceFile(className);
this.sourceLines = ClassAnnotation.getSourceLinesForClass(className, sourceFileName);
- } else
+ } else {
this.sourceFileName = SourceLineAnnotation.UNKNOWN_SOURCE_FILE;
+ }
}
}
/**
* Get the type descriptor.
- *
+ *
* @return the jvm type descriptor, such as "[I"
*/
public String getTypeDescriptor() {
return descriptor;
}
+ @Override
public void accept(BugAnnotationVisitor visitor) {
visitor.visitTypeAnnotation(this);
}
+ @Override
public String format(String key, ClassAnnotation primaryClass) {
String name = new SignatureConverter(descriptor).parseNext().replace("java.lang.", "");
- if (key.equals("givenClass"))
+ if ("givenClass".equals(key)) {
name = PackageMemberAnnotation.shorten(primaryClass.getPackageName(), name);
- else if (key.equals("excludingPackage"))
+ } else if ("excludingPackage".equals(key)) {
name = PackageMemberAnnotation.removePackage(name);
+ }
- if (typeParameters != null && !key.equals("hash"))
+ if (typeParameters != null && !"hash".equals(key)) {
name = name + typeParameters;
+ }
return name;
}
+ @Override
public void setDescription(String roleDescription) {
this.roleDescription = roleDescription.intern();
}
+ @Override
public String getDescription() {
return roleDescription;
}
@@ -135,6 +143,10 @@ public class TypeAnnotation extends BugAnnotationWithSourceLines {
this.typeParameters = typeParameters;
}
+ public String getTypeParameters() {
+ return typeParameters;
+ }
+
@Override
public int hashCode() {
return descriptor.hashCode();
@@ -142,15 +154,18 @@ public class TypeAnnotation extends BugAnnotationWithSourceLines {
@Override
public boolean equals(Object o) {
- if (!(o instanceof TypeAnnotation))
+ if (!(o instanceof TypeAnnotation)) {
return false;
+ }
return descriptor.equals(((TypeAnnotation) o).descriptor);
}
+ @Override
public int compareTo(BugAnnotation o) {
- if (!(o instanceof TypeAnnotation)) // BugAnnotations must be Comparable
- // with any type of BugAnnotation
+ if (!(o instanceof TypeAnnotation)) {
+ // with any type of BugAnnotation
return this.getClass().getName().compareTo(o.getClass().getName());
+ }
return descriptor.compareTo(((TypeAnnotation) o).descriptor);
// could try to determine equivalence with ClassAnnotation, but don't
// see how this would be useful
@@ -171,22 +186,27 @@ public class TypeAnnotation extends BugAnnotationWithSourceLines {
private static final String ELEMENT_NAME = "Type";
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, false, false);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean addMessages, boolean isPrimary) throws IOException {
XMLAttributeList attributeList = new XMLAttributeList().addAttribute("descriptor", descriptor);
String role = getDescription();
- if (!role.equals(DEFAULT_ROLE))
+ if (!DEFAULT_ROLE.equals(role)) {
attributeList.addAttribute("role", role);
- if (typeParameters != null)
+ }
+ if (typeParameters != null) {
attributeList.addAttribute("typeParameters", typeParameters);
+ }
BugAnnotationUtil.writeXML(xmlOutput, ELEMENT_NAME, this, attributeList, addMessages);
}
+ @Override
public boolean isSignificant() {
return true;
}
diff --git a/src/java/edu/umd/cs/findbugs/UseAnnotationDatabase.java b/src/java/edu/umd/cs/findbugs/UseAnnotationDatabase.java
index d778847..0b89bc6 100644
--- a/src/java/edu/umd/cs/findbugs/UseAnnotationDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/UseAnnotationDatabase.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs;
/**
* A marker interface for detectors which use an AnnotationDatabase.
- *
+ *
* @author David Hovemeyer
*/
public interface UseAnnotationDatabase {
diff --git a/src/java/edu/umd/cs/findbugs/UserDesignations_ja.properties b/src/java/edu/umd/cs/findbugs/UserDesignations_ja.properties
index daee9b7..7fc3b2a 100644
--- a/src/java/edu/umd/cs/findbugs/UserDesignations_ja.properties
+++ b/src/java/edu/umd/cs/findbugs/UserDesignations_ja.properties
@@ -1,7 +1,9 @@
-UNCLASSIFIED=\u672a\u5206\u985e(unclassified)
-NEEDS_STUDY=\u8abf\u67fb\u304c\u5fc5\u8981(needs further study)
-BAD_ANALYSIS=\u8aa4\u691c\u51fa(bad analysis)
-NOT_A_BUG=\u30d0\u30b0\u3067\u306f\u306a\u3044(not a bug)
-MOSTLY_HARMLESS=\u307b\u3068\u3093\u3069\u7121\u5bb3(mostly harmless)
-SHOULD_FIX=\u4fee\u6b63\u3057\u305f\u307b\u3046\u304c\u3088\u3044(should fix)
-MUST_FIX=\u4fee\u6b63\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044(must fix)
+BAD_ANALYSIS = \u8aa4\u691c\u51fa (bad analysis)
+I_WILL_FIX = \u4fee\u6b63\u3059\u308b (I will fix)
+MOSTLY_HARMLESS = \u307b\u3068\u3093\u3069\u7121\u5bb3 (mostly harmless)
+MUST_FIX = \u4fee\u6b63\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044 (must fix)
+NEEDS_STUDY = \u8abf\u67fb\u304c\u5fc5\u8981 (needs further study)
+NOT_A_BUG = \u30d0\u30b0\u3067\u306f\u306a\u3044 (not a bug)
+OBSOLETE_CODE = \u5ec3\u6b62/\u4f7f\u308f\u308c\u306a\u3044\u30b3\u30fc\u30c9 (obsolete/unused code)
+SHOULD_FIX = \u4fee\u6b63\u3059\u3079\u304d (should fix)
+UNCLASSIFIED = \u672a\u5206\u985e (unclassified)
\ No newline at end of file
diff --git a/src/java/edu/umd/cs/findbugs/Version.java b/src/java/edu/umd/cs/findbugs/Version.java
index 7844a36..40c7905 100644
--- a/src/java/edu/umd/cs/findbugs/Version.java
+++ b/src/java/edu/umd/cs/findbugs/Version.java
@@ -44,7 +44,7 @@ public class Version {
/**
* Major version number.
*/
- public static final int MAJOR = 2;
+ public static final int MAJOR = 3;
/**
* Minor version number.
@@ -54,12 +54,12 @@ public class Version {
/**
* Patch level.
*/
- public static final int PATCHLEVEL = 3;
+ public static final int PATCHLEVEL = 1;
/**
* Development version or release candidate?
*/
- public static final boolean IS_DEVELOPMENT = false;
+ public static final boolean IS_DEVELOPMENT = true;
/**
* Release candidate number. "0" indicates that the version is not a release
@@ -68,7 +68,8 @@ public class Version {
public static final int RELEASE_CANDIDATE = 0;
- public static final String SVN_REVISION = System.getProperty("svn.revision", "Unknown");
+ public static final String GIT_REVISION = System.getProperty("git.revision", "UNKNOWN");
+
/**
* Release date.
*/
@@ -90,7 +91,6 @@ public class Version {
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss z, dd MMMM, yyyy", Locale.ENGLISH);
SimpleDateFormat eclipseDateFormat = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
SimpleDateFormat releaseDateFormat = new SimpleDateFormat(UpdateChecker.PLUGIN_RELEASE_DATE_FMT, Locale.ENGLISH);
-
Date now = new Date();
COMPUTED_DATE = dateFormat.format(now);
COMPUTED_ECLIPSE_DATE = eclipseDateFormat.format(now);
@@ -107,14 +107,15 @@ public class Version {
private static final String RELEASE_SUFFIX_WORD;
static {
String suffix;
- if (RELEASE_CANDIDATE > 0)
+ if (RELEASE_CANDIDATE > 0) {
suffix = "rc" + RELEASE_CANDIDATE;
- else if (PREVIEW > 0)
+ } else if (PREVIEW > 0) {
suffix = "preview" + PREVIEW;
- else {
+ } else {
suffix = "dev-" + COMPUTED_ECLIPSE_DATE;
- if (!SVN_REVISION.equals("Unknown"))
- suffix += "-r" + SVN_REVISION;
+ if (!"Unknown".equals(GIT_REVISION)) {
+ suffix += "-" + GIT_REVISION;
+ }
}
RELEASE_SUFFIX_WORD = suffix;
}
@@ -139,12 +140,12 @@ public class Version {
static {
Class<Version> c = Version.class;
URL u = c.getResource(c.getSimpleName() + ".class");
- boolean fromFile = u.getProtocol().equals("file");
+ boolean fromFile = "file".equals(u.getProtocol());
InputStream in = null;
String release = null;
String date = null;
String plugin_release_date = null;
- if (!fromFile)
+ if (!fromFile) {
try {
Properties versionProperties = new Properties();
in = Version.class.getResourceAsStream("version.properties");
@@ -159,12 +160,16 @@ public class Version {
} finally {
Util.closeSilently(in);
}
- if (release == null)
+ }
+ if (release == null) {
release = COMPUTED_RELEASE;
- if (date == null)
+ }
+ if (date == null) {
date = COMPUTED_DATE;
- if (plugin_release_date == null)
+ }
+ if (plugin_release_date == null) {
plugin_release_date = COMPUTED_PLUGIN_RELEASE_DATE;
+ }
RELEASE = release;
DATE = date;
@@ -175,8 +180,9 @@ public class Version {
parsedDate = fmt.parse(CORE_PLUGIN_RELEASE_DATE);
} catch (ParseException e) {
- if (SystemProperties.ASSERTIONS_ENABLED)
+ if (SystemProperties.ASSERTIONS_ENABLED) {
e.printStackTrace();
+ }
parsedDate = null;
}
releaseDate = parsedDate;
@@ -223,11 +229,11 @@ public class Version {
String arg = argv[0];
- if (arg.equals("-release"))
+ if ("-release".equals(arg)) {
System.out.println(RELEASE);
- else if (arg.equals("-date"))
+ } else if ("-date".equals(arg)) {
System.out.println(DATE);
- else if (arg.equals("-props")) {
+ } else if ("-props".equals(arg)) {
System.out.println("release.base=" + RELEASE_BASE);
System.out.println("release.number=" + COMPUTED_RELEASE);
System.out.println("release.date=" + COMPUTED_DATE);
@@ -235,22 +241,24 @@ public class Version {
System.out.println("eclipse.ui.version=" + COMPUTED_ECLIPSE_UI_VERSION);
System.out.println("findbugs.website=" + WEBSITE);
System.out.println("findbugs.downloads.website=" + DOWNLOADS_WEBSITE);
- System.out.println("findbugs.svn.revision=" + SVN_REVISION);
- } else if (arg.equals("-plugins")) {
+ System.out.println("findbugs.git.revision=" + GIT_REVISION);
+ } else if ("-plugins".equals(arg)) {
DetectorFactoryCollection.instance();
for(Plugin p : Plugin.getAllPlugins()) {
System.out.println("Plugin: " + p.getPluginId());
System.out.println(" description: " + p.getShortDescription());
System.out.println(" provider: " + p.getProvider());
String version = p.getVersion();
- if (version != null && version.length() > 0)
+ if (version != null && version.length() > 0) {
System.out.println(" version: " + version);
+ }
String website = p.getWebsite();
- if (website != null && website.length() > 0)
- System.out.println(" website: " + website);
+ if (website != null && website.length() > 0) {
+ System.out.println(" website: " + website);
+ }
System.out.println();
}
- } else if (arg.equals("-configuration")){
+ } else if ("-configuration".equals(arg)){
printVersion(true);
} else {
@@ -264,8 +272,9 @@ public class Version {
}
public static String getReleaseWithDateIfDev() {
- if (IS_DEVELOPMENT)
+ if (IS_DEVELOPMENT) {
return RELEASE + " (" + DATE + ")";
+ }
return RELEASE;
}
@@ -283,14 +292,18 @@ public class Version {
for (Plugin plugin : Plugin.getAllPlugins()) {
System.out.printf("Plugin %s, version %s, loaded from %s%n", plugin.getPluginId(), plugin.getVersion(),
plugin.getPluginLoader().getURL());
- if (plugin.isCorePlugin())
+ if (plugin.isCorePlugin()) {
System.out.println(" is core plugin");
- if (plugin.isInitialPlugin())
+ }
+ if (plugin.isInitialPlugin()) {
System.out.println(" is initial plugin");
- if (plugin.isEnabledByDefault())
+ }
+ if (plugin.isEnabledByDefault()) {
System.out.println(" is enabled by default");
- if (plugin.isGloballyEnabled())
+ }
+ if (plugin.isGloballyEnabled()) {
System.out.println(" is globally enabled");
+ }
Plugin parent = plugin.getParentPlugin();
if (parent != null) {
System.out.println(" has parent plugin " + parent.getPluginId());
@@ -306,8 +319,9 @@ public class Version {
System.out.println();
}
printPluginUpdates(true, 10);
- } else
+ } else {
printPluginUpdates(false, 3);
+ }
}
private static void printPluginUpdates(boolean verbose, int secondsToWait) throws InterruptedException {
@@ -330,8 +344,9 @@ public class Version {
try {
Collection<UpdateChecker.PluginUpdate> updates = updateHolder.get(secondsToWait, TimeUnit.SECONDS);
if (updates.isEmpty()) {
- if (verbose)
+ if (verbose) {
System.out.println("none!");
+ }
} else {
System.out.println();
for (UpdateChecker.PluginUpdate update : updates) {
@@ -341,12 +356,12 @@ public class Version {
}
}
} catch (TimeoutException e) {
- if (verbose)
+ if (verbose) {
System.out.println("Timeout while trying to get updates");
+ }
}
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/VersionInsensitiveBugComparator.java b/src/java/edu/umd/cs/findbugs/VersionInsensitiveBugComparator.java
index 8ca1a7f..d85aa87 100644
--- a/src/java/edu/umd/cs/findbugs/VersionInsensitiveBugComparator.java
+++ b/src/java/edu/umd/cs/findbugs/VersionInsensitiveBugComparator.java
@@ -36,11 +36,12 @@ public class VersionInsensitiveBugComparator implements WarningComparator {
private boolean exactBugPatternMatch = true;
- private boolean comparePriorities = false;
+ private boolean comparePriorities;
public VersionInsensitiveBugComparator() {
}
+ @Override
public void setClassNameRewriter(ClassNameRewriter classNameRewriter) {
this.classNameRewriter = classNameRewriter;
}
@@ -54,7 +55,7 @@ public class VersionInsensitiveBugComparator implements WarningComparator {
* don't care about.
*/
private class FilteringAnnotationIterator implements Iterator<BugAnnotation> {
- private Iterator<BugAnnotation> iter;
+ private final Iterator<BugAnnotation> iter;
private BugAnnotation next;
@@ -63,28 +64,33 @@ public class VersionInsensitiveBugComparator implements WarningComparator {
this.next = null;
}
+ @Override
public boolean hasNext() {
findNext();
return next != null;
}
+ @Override
public BugAnnotation next() {
findNext();
- if (next == null)
+ if (next == null) {
throw new NoSuchElementException();
+ }
BugAnnotation result = next;
next = null;
return result;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
private void findNext() {
while (next == null) {
- if (!iter.hasNext())
+ if (!iter.hasNext()) {
break;
+ }
BugAnnotation candidate = iter.next();
if (!isBoring(candidate)) {
next = candidate;
@@ -99,6 +105,7 @@ public class VersionInsensitiveBugComparator implements WarningComparator {
return !(annotation instanceof LocalVariableAnnotation || annotation.isSignificant());
}
+ /*
private static int compareNullElements(Object a, Object b) {
if (a != null)
return 1;
@@ -110,8 +117,9 @@ public class VersionInsensitiveBugComparator implements WarningComparator {
private static String getCode(String pattern) {
int sep = pattern.indexOf('_');
- if (sep < 0)
+ if (sep < 0) {
return "";
+ }
return pattern.substring(0, sep);
}
@@ -121,9 +129,9 @@ public class VersionInsensitiveBugComparator implements WarningComparator {
while (i.hasNext()) {
System.out.println(" " + i.next());
}
+ }*/
- }
-
+ @Override
public int compare(BugInstance lhs, BugInstance rhs) {
// Attributes of BugInstance.
// Compare abbreviation
@@ -135,46 +143,34 @@ public class VersionInsensitiveBugComparator implements WarningComparator {
BugPattern lhsPattern = lhs.getBugPattern();
BugPattern rhsPattern = rhs.getBugPattern();
- if (lhsPattern == null || rhsPattern == null) {
- // One of the patterns is missing.
- // However, we can still accurately match by abbrev (usually) by
- // comparing
- // the part of the type before the first '_' character.
- // This is almost always equivalent to the abbrev.
-
- String lhsCode = getCode(lhs.getType());
- String rhsCode = getCode(rhs.getType());
-
- if ((cmp = lhsCode.compareTo(rhsCode)) != 0) {
- return cmp;
- }
- } else {
- // Compare by abbrev instead of type. The specific bug type can
- // change
- // (e.g., "definitely null" to "null on simple path"). Also, we
- // often
- // change bug pattern types from one version of FindBugs to the
- // next.
- //
- // Source line and field name are still matched precisely, so this
- // shouldn't
- // cause loss of precision.
- if ((cmp = lhsPattern.getAbbrev().compareTo(rhsPattern.getAbbrev())) != 0)
- return cmp;
- if (isExactBugPatternMatch() && (cmp = lhsPattern.getType().compareTo(rhsPattern.getType())) != 0)
- return cmp;
+ // Compare by abbrev instead of type. The specific bug type can
+ // change
+ // (e.g., "definitely null" to "null on simple path"). Also, we
+ // often
+ // change bug pattern types from one version of FindBugs to the
+ // next.
+ //
+ // Source line and field name are still matched precisely, so this
+ // shouldn't
+ // cause loss of precision.
+ if ((cmp = lhsPattern.getAbbrev().compareTo(rhsPattern.getAbbrev())) != 0) {
+ return cmp;
+ }
+ if (isExactBugPatternMatch() && (cmp = lhsPattern.getType().compareTo(rhsPattern.getType())) != 0) {
+ return cmp;
}
if (comparePriorities) {
cmp = lhs.getPriority() - rhs.getPriority();
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
}
Iterator<BugAnnotation> lhsIter = new FilteringAnnotationIterator(lhs.annotationIterator());
Iterator<BugAnnotation> rhsIter = new FilteringAnnotationIterator(rhs.annotationIterator());
- annotationLoop: while (lhsIter.hasNext() && rhsIter.hasNext()) {
+ while (lhsIter.hasNext() && rhsIter.hasNext()) {
BugAnnotation lhsAnnotation = lhsIter.next();
BugAnnotation rhsAnnotation = rhsIter.next();
Class<? extends BugAnnotation> lhsClass;
@@ -183,16 +179,18 @@ public class VersionInsensitiveBugComparator implements WarningComparator {
// so just compare by class name.
lhsClass = lhsAnnotation.getClass();
Class<? extends BugAnnotation> rhsClass = rhsAnnotation.getClass();
- if (lhsClass == rhsClass)
+ if (lhsClass == rhsClass) {
break;
+ }
if (lhsClass == LocalVariableAnnotation.class && !((LocalVariableAnnotation) lhsAnnotation).isSignificant()
- && lhsIter.hasNext())
+ && lhsIter.hasNext()) {
lhsAnnotation = lhsIter.next();
- else if (rhsClass == LocalVariableAnnotation.class && !((LocalVariableAnnotation) rhsAnnotation).isSignificant()
- && rhsIter.hasNext())
+ } else if (rhsClass == LocalVariableAnnotation.class && !((LocalVariableAnnotation) rhsAnnotation).isSignificant()
+ && rhsIter.hasNext()) {
rhsAnnotation = rhsIter.next();
- else
+ } else {
return lhsClass.getName().compareTo(rhsClass.getName());
+ }
}
if (lhsClass == ClassAnnotation.class) {
@@ -228,8 +226,9 @@ public class VersionInsensitiveBugComparator implements WarningComparator {
} else if (lhsClass == LocalVariableAnnotation.class) {
String lhsName = ((LocalVariableAnnotation) lhsAnnotation).getName();
String rhsName = ((LocalVariableAnnotation) rhsAnnotation).getName();
- if (lhsName.equals("?") || rhsName.equals("?"))
+ if ("?".equals(lhsName) || "?".equals(rhsName)) {
continue;
+ }
cmp = lhsName.compareTo(rhsName);
} else if (lhsClass == TypeAnnotation.class) {
@@ -246,47 +245,44 @@ public class VersionInsensitiveBugComparator implements WarningComparator {
} else if (isBoring(lhsAnnotation)) {
throw new IllegalStateException("Impossible");
- } else
+ } else {
throw new IllegalStateException("Unknown annotation type: " + lhsClass.getName());
- if (cmp != 0)
+ }
+ if (cmp != 0) {
return cmp;
+ }
}
- if (interestingNext(rhsIter))
+ if (interestingNext(rhsIter)) {
return -1;
- else if (interestingNext(lhsIter))
+ } else if (interestingNext(lhsIter)) {
return 1;
- else
+ } else {
return 0;
+ }
}
private boolean interestingNext(Iterator<BugAnnotation> i) {
while (i.hasNext()) {
BugAnnotation a = i.next();
- if (isBoring(a))
+ if (isBoring(a)) {
continue;
- if (!(a instanceof LocalVariableAnnotation))
+ }
+ if (!(a instanceof LocalVariableAnnotation)) {
return true;
- if (((LocalVariableAnnotation) a).isSignificant())
+ }
+ if (((LocalVariableAnnotation) a).isSignificant()) {
return true;
+ }
}
return false;
}
- /**
- * @param exactBugPatternMatch
- * The exactBugPatternMatch to set.
- */
public void setExactBugPatternMatch(boolean exactBugPatternMatch) {
this.exactBugPatternMatch = exactBugPatternMatch;
}
- /**
- * @return Returns the exactBugPatternMatch.
- */
public boolean isExactBugPatternMatch() {
return exactBugPatternMatch;
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/WarningComparator.java b/src/java/edu/umd/cs/findbugs/WarningComparator.java
index 33bde90..d9cd892 100644
--- a/src/java/edu/umd/cs/findbugs/WarningComparator.java
+++ b/src/java/edu/umd/cs/findbugs/WarningComparator.java
@@ -19,6 +19,7 @@
package edu.umd.cs.findbugs;
+import java.io.Serializable;
import java.util.Comparator;
import edu.umd.cs.findbugs.model.ClassNameRewriter;
@@ -26,19 +27,11 @@ import edu.umd.cs.findbugs.model.ClassNameRewriter;
/**
* @author David Hovemeyer
*/
-public interface WarningComparator extends Comparator<BugInstance> {
+public interface WarningComparator extends Comparator<BugInstance>, Serializable {
- /**
- * @param classNameRewriter
- * The classNameRewriter to set.
- */
public abstract void setClassNameRewriter(ClassNameRewriter classNameRewriter);
- /*
- * (non-Javadoc)
- *
- * @see java.util.Comparator#compare(T, T)
- */
+ @Override
public abstract int compare(BugInstance lhs, BugInstance rhs);
}
diff --git a/src/java/edu/umd/cs/findbugs/WarningSuppressor.java b/src/java/edu/umd/cs/findbugs/WarningSuppressor.java
index 8d5e7d5..eaa5b72 100644
--- a/src/java/edu/umd/cs/findbugs/WarningSuppressor.java
+++ b/src/java/edu/umd/cs/findbugs/WarningSuppressor.java
@@ -13,10 +13,12 @@ abstract public class WarningSuppressor implements Matcher {
public WarningSuppressor(String bugPattern) {
this.bugPattern = bugPattern;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Suppressing " + bugPattern);
+ }
}
+ @Override
public boolean match(BugInstance bugInstance) {
if (DEBUG) {
@@ -27,13 +29,16 @@ abstract public class WarningSuppressor implements Matcher {
}
if (!(bugPattern == null || bugInstance.getType().startsWith(bugPattern)
|| bugInstance.getBugPattern().getCategory().equalsIgnoreCase(bugPattern) || bugInstance.getBugPattern()
- .getAbbrev().equalsIgnoreCase(bugPattern)))
+ .getAbbrev().equalsIgnoreCase(bugPattern))) {
return false;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println(" pattern matches");
+ }
return true;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
// no-op; these aren't saved to XML
}
diff --git a/src/java/edu/umd/cs/findbugs/XDocsBugReporter.java b/src/java/edu/umd/cs/findbugs/XDocsBugReporter.java
index e16b62e..6a02e24 100644
--- a/src/java/edu/umd/cs/findbugs/XDocsBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/XDocsBugReporter.java
@@ -43,9 +43,9 @@ public class XDocsBugReporter extends TextUIBugReporter {
final private Project project;
- private Document document;
+ private final Document document;
- private Element root;
+ private final Element root;
private static final String ROOT_ELEMENT_NAME = "BugCollection";
@@ -72,6 +72,7 @@ public class XDocsBugReporter extends TextUIBugReporter {
}
+ @Override
public void observeClass(ClassDescriptor classDescriptor) {
}
@@ -108,6 +109,7 @@ public class XDocsBugReporter extends TextUIBugReporter {
}
}
+ @Override
public void finish() {
try {
@@ -215,6 +217,7 @@ public class XDocsBugReporter extends TextUIBugReporter {
* }
*/
+ @Override
public @Nonnull
BugCollection getBugCollection() {
return bugCollection;
@@ -222,4 +225,3 @@ public class XDocsBugReporter extends TextUIBugReporter {
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/XMLBugReporter.java b/src/java/edu/umd/cs/findbugs/XMLBugReporter.java
index bcf55ef..0f36b25 100644
--- a/src/java/edu/umd/cs/findbugs/XMLBugReporter.java
+++ b/src/java/edu/umd/cs/findbugs/XMLBugReporter.java
@@ -40,8 +40,9 @@ public class XMLBugReporter extends BugCollectionBugReporter {
public void finish() {
try {
Project project = getProject();
- if (project == null)
+ if (project == null) {
throw new NullPointerException("No project");
+ }
getBugCollection().bugsPopulated();
getBugCollection().writeXML(outputStream);
outputStream.close();
@@ -61,4 +62,3 @@ public class XMLBugReporter extends BugCollectionBugReporter {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/XMLWriteableWithMessages.java b/src/java/edu/umd/cs/findbugs/XMLWriteableWithMessages.java
index ab5b508..94ff3c0 100644
--- a/src/java/edu/umd/cs/findbugs/XMLWriteableWithMessages.java
+++ b/src/java/edu/umd/cs/findbugs/XMLWriteableWithMessages.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.xml.XMLWriteable;
/**
* Write an object to XMLOutput while optionally adding descriptive messages.
- *
+ *
* @author David Hovemeyer
*/
public interface XMLWriteableWithMessages extends XMLWriteable {
diff --git a/src/java/edu/umd/cs/findbugs/annotations/CheckForNull.java b/src/java/edu/umd/cs/findbugs/annotations/CheckForNull.java
index 1d637f2..51edf58 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/CheckForNull.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/CheckForNull.java
@@ -30,11 +30,11 @@ import javax.annotation.meta.When;
/**
* The annotated element might be null, and uses of the element should check for
* null.
- *
+ *
* When this annotation is applied to a method it applies to the method return
* value.
- *
- * @deprecated - use {@link javax.annotation.CheckForNull} instead.
+ *
+ * @deprecated - use {@link javax.annotation.CheckForNull} instead.
**/
@Documented
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
diff --git a/src/java/edu/umd/cs/findbugs/annotations/CheckReturnValue.java b/src/java/edu/umd/cs/findbugs/annotations/CheckReturnValue.java
index 5e86543..af21cdc 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/CheckReturnValue.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/CheckReturnValue.java
@@ -27,10 +27,10 @@ import java.lang.annotation.Target;
/**
* This annotation is used to denote a method whose return value should always
* be checked when invoking the method.
- *
+ *
* The checker treats this annotation as inherited by overriding methods.
- *
- * @deprecated - use {@link javax.annotation.CheckReturnValue} instead.
+ *
+ * @deprecated - use {@link javax.annotation.CheckReturnValue} instead.
*/
@Documented
@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
diff --git a/src/java/edu/umd/cs/findbugs/annotations/CleanupObligation.java b/src/java/edu/umd/cs/findbugs/annotations/CleanupObligation.java
index ac62786..5ea0763 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/CleanupObligation.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/CleanupObligation.java
@@ -27,7 +27,7 @@ import java.lang.annotation.Target;
/**
* Mark a class or interface as a resource type requiring cleanup.
- *
+ *
* @author David Hovemeyer
*/
@Documented
diff --git a/src/java/edu/umd/cs/findbugs/annotations/CreatesObligation.java b/src/java/edu/umd/cs/findbugs/annotations/CreatesObligation.java
index 0a7348f..f921870 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/CreatesObligation.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/CreatesObligation.java
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
* Mark a constructor or method as creating a resource which requires cleanup.
* The marked method must be a member of a class marked with the
* CleanupObligation annotation.
- *
+ *
* @author David Hovemeyer
*/
@Documented
diff --git a/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotation.java b/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotation.java
index 6aa11f6..e97955a 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotation.java
@@ -33,14 +33,14 @@ import javax.annotation.meta.TypeQualifierDefault;
/**
* Indicates that all members of the class or package should be annotated with
* the default value of the supplied annotation class.
- *
+ *
* This would be used for behavior annotations such as @NonNull, @CheckForNull,
* or @CheckReturnValue.
- *
+ *
* In particular, you can use @DefaultAnnotation(NonNull.class) on a class or
* package, and then use @Nullable only on those parameters, methods or fields
* that you want to allow to be null.
- *
+ *
* @deprecated - Use the JSR305 annotations instead.
* For example, you can use {@link javax.annotation.ParametersAreNonnullByDefault} instead
* of @DefaultAnnotation(NonNull.class) so that method parameters are nonnull by default in the annotated
@@ -51,11 +51,11 @@ import javax.annotation.meta.TypeQualifierDefault;
* {@link TypeQualifierDefault}({@link ElementType#PARAMETER})
* public @interface ParametersAreNonnegativeByDefault {}
* </code></pre>
- *
+ *
* <p>The JSR305 {@link javax.annotation.CheckReturnValue}
* annotation can be applied to a type or package, and it will act as a default for all methods
* in that class or package unless otherwise overridden.
- *
+ *
* @author William Pugh
*/
@@ -68,6 +68,6 @@ public @interface DefaultAnnotation {
@Deprecated
Priority priority() default Priority.MEDIUM;
-
+
Confidence confidence() default Confidence.MEDIUM;
}
diff --git a/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForFields.java b/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForFields.java
index 95d8b90..fc5ade2 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForFields.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForFields.java
@@ -29,14 +29,14 @@ import java.lang.annotation.Target;
/**
* Indicates that all members of the class or package should be annotated with
* the default value of the supplied annotation class.
- *
+ *
* This would be used for behavior annotations such as @NonNull, @CheckForNull,
* or @CheckReturnValue.
- *
+ *
* In particular, you can use @DefaultAnnotation(NonNull.class) on a class or
* package, and then use @Nullable only on those parameters, methods or fields
* that you want to allow to be null.
- *
+ *
* @author William Pugh
*/
@@ -49,6 +49,6 @@ public @interface DefaultAnnotationForFields {
@Deprecated
Priority priority() default Priority.MEDIUM;
-
+
Confidence confidence() default Confidence.MEDIUM;
}
diff --git a/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForMethods.java b/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForMethods.java
index 2a51711..b92f9bc 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForMethods.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForMethods.java
@@ -29,14 +29,14 @@ import java.lang.annotation.Target;
/**
* Indicates that all members of the class or package should be annotated with
* the default value of the supplied annotation class.
- *
+ *
* This would be used for behavior annotations such as @NonNull, @CheckForNull,
* or @CheckReturnValue.
- *
+ *
* In particular, you can use @DefaultAnnotation(NonNull.class) on a class or
* package, and then use @Nullable only on those parameters, methods or fields
* that you want to allow to be null.
- *
+ *
* @author William Pugh
*/
@@ -49,6 +49,6 @@ public @interface DefaultAnnotationForMethods {
@Deprecated
Priority priority() default Priority.MEDIUM;
-
+
Confidence confidence() default Confidence.MEDIUM;
}
diff --git a/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForParameters.java b/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForParameters.java
index 8a78b64..5dc418b 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForParameters.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/DefaultAnnotationForParameters.java
@@ -29,21 +29,21 @@ import java.lang.annotation.Target;
/**
* Indicates that all members of the class or package should be annotated with
* the default value of the supplied annotation class.
- *
+ *
* This would be used for behavior annotations such as @NonNull, @CheckForNull,
* or @CheckReturnValue.
- *
+ *
* In particular, you can use @DefaultAnnotation(NonNull.class) on a class or
* package, and then use @Nullable only on those parameters, methods or fields
* that you want to allow to be null.
- *
+ *
* @deprecated - use the JSR305 annotations instead,
* For example, you can use {@link javax.annotation.ParametersAreNonnullByDefault} instead
* of @DefaultAnnotation(NonNull.class), and {@link javax.annotation.meta.TypeQualifierDefault}
* in general to define a type qualifier default. The JSR305 {@link javax.annotation.CheckReturnValue}
* annotation can be applied to a type or package, and it will act as a default for all methods
* in that class or package unless otherwise overridden.
- *
+ *
* @author William Pugh
*/
@@ -56,6 +56,6 @@ public @interface DefaultAnnotationForParameters {
@Deprecated
Priority priority() default Priority.MEDIUM;
-
+
Confidence confidence() default Confidence.MEDIUM;
}
diff --git a/src/java/edu/umd/cs/findbugs/annotations/DesireNoWarning.java b/src/java/edu/umd/cs/findbugs/annotations/DesireNoWarning.java
index c27e2e6..5aef01c 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/DesireNoWarning.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/DesireNoWarning.java
@@ -9,8 +9,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
- * Annotation indicating that <em>no</em> FindBugs warning of the specified type
- * is not desired.
+ * Annotation indicating that <em>no</em> FindBugs warnings of the specified type
+ * is desired.
*
* See http://code.google.com/p/findbugs/wiki/FindbugsTestCases
*
diff --git a/src/java/edu/umd/cs/findbugs/annotations/DesireWarning.java b/src/java/edu/umd/cs/findbugs/annotations/DesireWarning.java
index d2b66d4..e003b7f 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/DesireWarning.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/DesireWarning.java
@@ -28,7 +28,9 @@ public @interface DesireWarning {
/** Want a warning at this priority or higher */
public Confidence confidence() default Confidence.LOW;
- /** Expect a warning at least this scary */
+ /** Desire a warning at least this scary */
public int rank() default BugRanker.VISIBLE_RANK_MAX;
+ /** Desire at least this many warnings */
+ public int num() default 1;
}
diff --git a/src/java/edu/umd/cs/findbugs/annotations/DischargesObligation.java b/src/java/edu/umd/cs/findbugs/annotations/DischargesObligation.java
index 8cd1e4d..2b84e56 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/DischargesObligation.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/DischargesObligation.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
/**
* Mark a method as cleaning up a resource. The marked method must be a member
* of a class marked with the CleanupObligation annotation.
- *
+ *
* @author David Hovemeyer
*/
@Documented
diff --git a/src/java/edu/umd/cs/findbugs/annotations/NonNull.java b/src/java/edu/umd/cs/findbugs/annotations/NonNull.java
index c73309e..74e47de 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/NonNull.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/NonNull.java
@@ -29,11 +29,11 @@ import javax.annotation.meta.When;
/**
* The annotated element must not be null.
- *
+ *
* Annotated Fields must only not be null after construction has completed.
* Annotated methods must have non-null return values.
- *
- * @deprecated - use {@link javax.annotation.Nonnull} instead.
+ *
+ * @deprecated - use {@link javax.annotation.Nonnull} instead.
**/
@Documented
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
diff --git a/src/java/edu/umd/cs/findbugs/annotations/Nullable.java b/src/java/edu/umd/cs/findbugs/annotations/Nullable.java
index 41e97d5..f6bbff4 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/Nullable.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/Nullable.java
@@ -29,15 +29,15 @@ import javax.annotation.meta.When;
/**
* The annotated element could be null under some circumstances.
- *
+ *
* In general, this means developers will have to read the documentation to
* determine when a null value is acceptable and whether it is necessary to
* check for a null value.
- *
+ *
* When this annotation is applied to a method it applies to the method return
* value.
- *
- * @deprecated - use {@link javax.annotation.Nullable} instead.
+ *
+ * @deprecated - use {@link javax.annotation.Nullable} instead.
**/
@Documented
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
diff --git a/src/java/edu/umd/cs/findbugs/annotations/OverrideMustInvoke.java b/src/java/edu/umd/cs/findbugs/annotations/OverrideMustInvoke.java
index 0aa0029..4fb70bf 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/OverrideMustInvoke.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/OverrideMustInvoke.java
@@ -29,13 +29,13 @@ import java.lang.annotation.Target;
* Used to annotate a method that, if overridden, must (or should) be invoked by
* an invocation on super in the overriding method. Examples of such methods
* include finalize() and clone().
- *
+ *
* The argument to the method indicates when the super invocation should occur:
* at any time, at the beginning of the overriding method, or at the end of the
* overriding method.
- *
+ *
* @see edu.umd.cs.findbugs.annotations.When
- *
+ *
* @deprecated - Use {@link javax.annotation.OverridingMethodsMustInvokeSuper} instead
**/
@Documented
diff --git a/src/java/edu/umd/cs/findbugs/annotations/PossiblyNull.java b/src/java/edu/umd/cs/findbugs/annotations/PossiblyNull.java
index e0346cd..34767c4 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/PossiblyNull.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/PossiblyNull.java
@@ -30,10 +30,10 @@ import javax.annotation.meta.When;
/**
* The annotated element should might be null, and uses of the element should
* check for null.
- *
+ *
* When this annotation is applied to a method it applies to the method return
* value.
- *
+ *
* @deprecated - use CheckForNull instead; the name of which more clearly
* indicates that not only could the value be null, but that good
* coding practice requires that the value be checked for null.
diff --git a/src/java/edu/umd/cs/findbugs/annotations/ReturnValuesAreNonnullByDefault.java b/src/java/edu/umd/cs/findbugs/annotations/ReturnValuesAreNonnullByDefault.java
index fd40fd5..1742644 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/ReturnValuesAreNonnullByDefault.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/ReturnValuesAreNonnullByDefault.java
@@ -37,7 +37,7 @@ import javax.annotation.meta.TypeQualifierDefault;
* annotation of the corresponding parameter in the superclass applies)
* <li>there is a default annotation applied to a more tightly nested element.
* </ul>
- *
+ *
*/
@Documented
@Nonnull
diff --git a/src/java/edu/umd/cs/findbugs/annotations/SuppressFBWarnings.java b/src/java/edu/umd/cs/findbugs/annotations/SuppressFBWarnings.java
index aebe58f..dd8af4c 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/SuppressFBWarnings.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/SuppressFBWarnings.java
@@ -24,18 +24,18 @@ import java.lang.annotation.RetentionPolicy;
/**
* Used to suppress FindBugs warnings.
- *
+ *
* It should be used instead of
* {@link edu.umd.cs.findbugs.annotations.SuppressWarnings} to avoid conflicts with
* {@link java.lang.SuppressWarnings}.
- *
+ *
*/
@Retention(RetentionPolicy.CLASS)
public @interface SuppressFBWarnings {
/**
* The set of FindBugs warnings that are to be suppressed in
* annotated element. The value can be a bug category, kind or pattern.
- *
+ *
*/
String[] value() default {};
diff --git a/src/java/edu/umd/cs/findbugs/annotations/SuppressWarnings.java b/src/java/edu/umd/cs/findbugs/annotations/SuppressWarnings.java
index c13e1ab..78d0431 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/SuppressWarnings.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/SuppressWarnings.java
@@ -26,8 +26,8 @@ import java.lang.annotation.Target;
/**
* Was used to suppress FindBugs warnings but generates name conflicts with {@link java.lang.SuppressWarnings}.
- *
- *
+ *
+ *
* @deprecated - Use {@link SuppressFBWarnings} instead
* @author pugh
*/
@@ -39,7 +39,7 @@ public @interface SuppressWarnings {
/**
* The set of FindBugs warnings that are to be suppressed by the compiler in the
* annotated element.
- *
+ *
*/
String[] value() default {};
diff --git a/src/java/edu/umd/cs/findbugs/annotations/package-info.java b/src/java/edu/umd/cs/findbugs/annotations/package-info.java
index 9856be6..8d61ca8 100644
--- a/src/java/edu/umd/cs/findbugs/annotations/package-info.java
+++ b/src/java/edu/umd/cs/findbugs/annotations/package-info.java
@@ -1,6 +1,6 @@
/**
* Annotations for FindBugs (mostly deprecated except for {@link edu.umd.cs.findbugs.annotations.SuppressFBWarnings}).
- *
+ *
* This annotations are mostly deprecated and replaced by JSR 305 annotations
* defined in javax.annotation. The annotations still actively supported are:
* <ul>
@@ -12,7 +12,7 @@
* <li> {@link edu.umd.cs.findbugs.annotations.DesireWarning} Warnings we wish to generated
* <li> {@link edu.umd.cs.findbugs.annotations.DesireNoWarning} Warnings we wish to not generate generated
* </ul></ul>
- *
+ *
* There are another set of annotations used by an experimental detector for unclosed resources:
* <ul>
* <li>{@link edu.umd.cs.findbugs.annotations.CleanupObligation}
diff --git a/src/java/edu/umd/cs/findbugs/asm/AbstractFBMethodVisitor.java b/src/java/edu/umd/cs/findbugs/asm/AbstractFBMethodVisitor.java
index 5cd69c1..1c27617 100644
--- a/src/java/edu/umd/cs/findbugs/asm/AbstractFBMethodVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/asm/AbstractFBMethodVisitor.java
@@ -19,20 +19,19 @@
package edu.umd.cs.findbugs.asm;
-import org.objectweb.asm.MethodAdapter;
-import org.objectweb.asm.commons.EmptyVisitor;
/**
* @author pugh
*/
-public abstract class AbstractFBMethodVisitor extends MethodAdapter implements FBMethodVisitor {
+public abstract class AbstractFBMethodVisitor extends FBMethodVisitor {
public AbstractFBMethodVisitor() {
- super(new EmptyVisitor());
+ super();
}
int pc;
+ @Override
public void visitOffset(int offset) {
pc = offset;
}
diff --git a/src/java/edu/umd/cs/findbugs/asm/ClassNodeDetector.java b/src/java/edu/umd/cs/findbugs/asm/ClassNodeDetector.java
index 8020721..f96c05b 100644
--- a/src/java/edu/umd/cs/findbugs/asm/ClassNodeDetector.java
+++ b/src/java/edu/umd/cs/findbugs/asm/ClassNodeDetector.java
@@ -28,11 +28,12 @@ import edu.umd.cs.findbugs.Detector2;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.classfile.engine.asm.FindBugsASM;
/**
* Abstract base class to to reduce boilerplate needed for writing ASM-based
* Detectors implemented as ClassNode visitors
- *
+ *
* @author pugh
*/
abstract public class ClassNodeDetector extends ClassNode implements Detector2 {
@@ -42,29 +43,33 @@ abstract public class ClassNodeDetector extends ClassNode implements Detector2 {
/**
* Construct a ClassNodeDetector. The bugReporter is passed to the
* constructor and stored in a protected final field.
- *
+ *
* @param bugReporter
* the BugReporter that bug should be reporter to.
*/
public ClassNodeDetector(BugReporter bugReporter) {
+ super(FindBugsASM.ASM_VERSION);
this.bugReporter = bugReporter;
}
+ @Override
public String getDetectorClassName() {
return this.getClass().getName();
}
+ @Override
@SuppressWarnings("rawtypes")
public void visitClass(ClassDescriptor classDescriptor) throws CheckedAnalysisException {
FBClassReader cr = Global.getAnalysisCache().getClassAnalysis(FBClassReader.class, classDescriptor);
- this.interfaces = new ArrayList();
- this.innerClasses = new ArrayList();
- this.fields = new ArrayList();
- this.methods = new ArrayList();
+ this.interfaces = new ArrayList<>();
+ this.innerClasses = new ArrayList<>();
+ this.fields = new ArrayList<>();
+ this.methods = new ArrayList<>();
cr.accept(this, 0);
}
+ @Override
public void finishPass() {
// do nothing
}
diff --git a/src/java/edu/umd/cs/findbugs/asm/FBClassReader.java b/src/java/edu/umd/cs/findbugs/asm/FBClassReader.java
index 5e4720b..f6fcf0a 100644
--- a/src/java/edu/umd/cs/findbugs/asm/FBClassReader.java
+++ b/src/java/edu/umd/cs/findbugs/asm/FBClassReader.java
@@ -20,13 +20,13 @@
package edu.umd.cs.findbugs.asm;
import org.objectweb.asm.Attribute;
-import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
+import edu.umd.cs.findbugs.classfile.engine.asm.FindBugsASM;
+
public class FBClassReader extends ClassReader {
// boolean needOffsets; // optional optimization (not thread safe)
@@ -56,10 +56,10 @@ public class FBClassReader extends ClassReader {
return labels[offset];
}
- private static class MyClassAdapter extends ClassAdapter {
+ private static class MyClassAdapter extends ClassVisitor {
public MyClassAdapter(ClassVisitor cv) {
- super(cv);
+ super(FindBugsASM.ASM_VERSION, cv);
}
@Override
@@ -73,10 +73,10 @@ public class FBClassReader extends ClassReader {
}
}
- private static class MyMethodAdapter extends MethodAdapter {
+ private static class MyMethodAdapter extends MethodVisitor {
public MyMethodAdapter(FBMethodVisitor mv) {
- super(mv);
+ super(FindBugsASM.ASM_VERSION, mv);
}
@Override
diff --git a/src/java/edu/umd/cs/findbugs/asm/FBMethodVisitor.java b/src/java/edu/umd/cs/findbugs/asm/FBMethodVisitor.java
index 2124ea5..d77f00a 100644
--- a/src/java/edu/umd/cs/findbugs/asm/FBMethodVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/asm/FBMethodVisitor.java
@@ -21,6 +21,17 @@ package edu.umd.cs.findbugs.asm;
import org.objectweb.asm.MethodVisitor;
-public interface FBMethodVisitor extends MethodVisitor {
- void visitOffset(int offset);
+import edu.umd.cs.findbugs.classfile.engine.asm.FindBugsASM;
+
+public abstract class FBMethodVisitor extends MethodVisitor {
+
+ public FBMethodVisitor() {
+ super(FindBugsASM.ASM_VERSION);
+ }
+
+ public FBMethodVisitor(MethodVisitor mv) {
+ super(FindBugsASM.ASM_VERSION, mv);
+ }
+
+ public abstract void visitOffset(int offset);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/AbstractBlockOrder.java b/src/java/edu/umd/cs/findbugs/ba/AbstractBlockOrder.java
index c31855f..5fdb3b7 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AbstractBlockOrder.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AbstractBlockOrder.java
@@ -28,7 +28,7 @@ import java.util.Iterator;
* Abstract base class for BlockOrder variants. It allows the subclass to
* specify just a Comparator for BasicBlocks, and handles the work of doing the
* sorting and providing Iterators.
- *
+ *
* @see BlockOrder
*/
public abstract class AbstractBlockOrder implements BlockOrder {
@@ -50,17 +50,19 @@ public abstract class AbstractBlockOrder implements BlockOrder {
// Put the ordered blocks into an array list
blockList = new ArrayList<BasicBlock>(numBlocks);
- for (int i = 0; i < numBlocks; ++i)
+ for (int i = 0; i < numBlocks; ++i) {
blockList.add(blocks[i]);
+ }
}
+ @Override
public Iterator<BasicBlock> blockIterator() {
return blockList.iterator();
}
-
+
+ @Override
public int compare(BasicBlock b1, BasicBlock b2) {
return comparator.compare(b1, b2);
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/AbstractClassMember.java b/src/java/edu/umd/cs/findbugs/ba/AbstractClassMember.java
index 29d3b68..5459c92 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AbstractClassMember.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AbstractClassMember.java
@@ -38,61 +38,62 @@ public abstract class AbstractClassMember implements ClassMember {
private int cachedHashCode = 0;
- static int slashCountClass = 0;
-
- static int dottedCountClass = 0;
-
- static int slashCountSignature = 0;
-
- static int dottedCountSignature = 0;
+ // static int slashCountClass = 0;
+ // static int dottedCountClass = 0;
+ // static int slashCountSignature = 0;
+ // static int dottedCountSignature = 0;
protected AbstractClassMember(@DottedClassName String className, String name, String signature, int accessFlags) {
if (className.indexOf('.') >= 0) {
// className = className.replace('.','/');
- dottedCountClass++;
+ // dottedCountClass++;
} else if (className.indexOf('/') >= 0) {
assert false;
- slashCountClass++;
+ // slashCountClass++;
className = className.replace('/', '.');
}
+
if (signature.indexOf('.') >= 0) {
assert false;
signature = signature.replace('.', '/');
- dottedCountSignature++;
- } else if (signature.indexOf('/') >= 0)
- slashCountSignature++;
+ // dottedCountSignature++;
+ }
+ // else if (signature.indexOf('/') >= 0) {
+ // slashCountSignature++;
+ // }
this.className = DescriptorFactory.canonicalizeString(className);
this.name = DescriptorFactory.canonicalizeString(name);
this.signature = DescriptorFactory.canonicalizeString(signature);
this.accessFlags = accessFlags;
}
- public @DottedClassName
- String getClassName() {
+ @Override
+ @DottedClassName
+ public String getClassName() {
return className;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.AccessibleEntity#getClassDescriptor()
- */
+ @Override
public ClassDescriptor getClassDescriptor() {
return DescriptorFactory.instance().getClassDescriptorForDottedClassName(className);
}
+ @Override
public String getName() {
return name;
}
- public @DottedClassName
- String getPackageName() {
+ @Override
+ @DottedClassName
+ public String getPackageName() {
int lastDot = className.lastIndexOf('.');
- if (lastDot == -1)
+ if (lastDot == -1) {
return className;
+ }
return className.substring(0, lastDot);
}
+ @Override
public String getSignature() {
return signature;
}
@@ -101,26 +102,32 @@ public abstract class AbstractClassMember implements ClassMember {
return signature.startsWith("L") || signature.startsWith("[");
}
+ @Override
public int getAccessFlags() {
return accessFlags;
}
+ @Override
public boolean isStatic() {
return (accessFlags & Constants.ACC_STATIC) != 0;
}
+ @Override
public boolean isFinal() {
return (accessFlags & Constants.ACC_FINAL) != 0;
}
+ @Override
public boolean isPublic() {
return (accessFlags & Constants.ACC_PUBLIC) != 0;
}
+ @Override
public boolean isProtected() {
return (accessFlags & Constants.ACC_PROTECTED) != 0;
}
+ @Override
public boolean isPrivate() {
return (accessFlags & Constants.ACC_PRIVATE) != 0;
}
@@ -158,6 +165,7 @@ public abstract class AbstractClassMember implements ClassMember {
// public int compareTo(Object other) {
// return compareTo((FieldOrMethodName) other);
// }
+ @Override
public boolean isResolved() {
return resolved;
}
@@ -176,8 +184,9 @@ public abstract class AbstractClassMember implements ClassMember {
@Override
public boolean equals(Object o) {
- if (o == null || this.getClass() != o.getClass())
+ if (o == null || this.getClass() != o.getClass()) {
return false;
+ }
AbstractClassMember other = (AbstractClassMember) o;
return className.equals(other.className) && name.equals(other.name) && signature.equals(other.signature);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/AbstractDataflow.java b/src/java/edu/umd/cs/findbugs/ba/AbstractDataflow.java
index 9ecb856..f14e555 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AbstractDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AbstractDataflow.java
@@ -24,17 +24,17 @@ package edu.umd.cs.findbugs.ba;
* BasicAbstractDataflowAnalysis subtype. The main functionality is offering
* getFact{At,After}Location() methods which forward to the actual analysis
* object.
- *
+ *
* @see edu.umd.cs.findbugs.ba.Dataflow
* @see edu.umd.cs.findbugs.ba.BasicAbstractDataflowAnalysis
* @author David Hovemeyer
*/
public class AbstractDataflow<Fact, AnalysisType extends BasicAbstractDataflowAnalysis<Fact>> extends
- Dataflow<Fact, AnalysisType> {
+Dataflow<Fact, AnalysisType> {
/**
* Constructor.
- *
+ *
* @param cfg
* CFG of the method on which dfa is performed
* @param analysis
@@ -46,7 +46,7 @@ public class AbstractDataflow<Fact, AnalysisType extends BasicAbstractDataflowAn
/**
* Get the fact that is true on the given control edge.
- *
+ *
* @param edge
* the edge
* @return the fact that is true on the edge
diff --git a/src/java/edu/umd/cs/findbugs/ba/AbstractDataflowAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/AbstractDataflowAnalysis.java
index 4427969..c21b709 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AbstractDataflowAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AbstractDataflowAnalysis.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.annotations.CheckReturnValue;
* Abstract base class providing functionality that will be useful for most
* dataflow analysis implementations that model instructions within basic
* blocks.
- *
+ *
* @author David Hovemeyer
* @see Dataflow
* @see DataflowAnalysis
@@ -48,7 +48,7 @@ public abstract class AbstractDataflowAnalysis<Fact> extends BasicAbstractDatafl
/**
* Transfer function for a single instruction.
- *
+ *
* @param handle
* the instruction
* @param basicBlock
@@ -71,7 +71,7 @@ public abstract class AbstractDataflowAnalysis<Fact> extends BasicAbstractDatafl
* Get the dataflow fact representing the point just before given Location.
* Note "before" is meant in the logical sense, so for backward analyses,
* before means after the location in the control flow sense.
- *
+ *
* @param location
* the location
* @return the fact at the point just before the location
@@ -89,7 +89,7 @@ public abstract class AbstractDataflowAnalysis<Fact> extends BasicAbstractDatafl
* Get the dataflow fact representing the point just after given Location.
* Note "after" is meant in the logical sense, so for backward analyses,
* after means before the location in the control flow sense.
- *
+ *
* @param location
* the location
* @return the fact at the point just after the location
@@ -99,10 +99,11 @@ public abstract class AbstractDataflowAnalysis<Fact> extends BasicAbstractDatafl
BasicBlock basicBlock = location.getBasicBlock();
InstructionHandle handle = location.getHandle();
- if (handle == (isForwards() ? basicBlock.getLastInstruction() : basicBlock.getFirstInstruction()))
+ if (handle == (isForwards() ? basicBlock.getLastInstruction() : basicBlock.getFirstInstruction())) {
return getResultFact(basicBlock);
- else
+ } else {
return getFactAtLocation(new Location(isForwards() ? handle.getNext() : handle.getPrev(), basicBlock));
+ }
}
/*
@@ -111,6 +112,7 @@ public abstract class AbstractDataflowAnalysis<Fact> extends BasicAbstractDatafl
* ----------------------------------------------------------------------
*/
+ @Override
public void transfer(BasicBlock basicBlock, @CheckForNull InstructionHandle end, Fact start, Fact result)
throws DataflowAnalysisException {
copy(start, result);
@@ -121,21 +123,23 @@ public abstract class AbstractDataflowAnalysis<Fact> extends BasicAbstractDatafl
while (i.hasNext()) {
InstructionHandle handle = i.next();
- if (handle == end)
+ if (handle == end) {
break;
+ }
- if (DEBUG && end == null)
+ if (DEBUG && end == null) {
System.out.print("Transfer " + handle);
+ }
// Transfer the dataflow value
transferInstruction(handle, basicBlock, result);
- if (DEBUG && end == null)
+ if (DEBUG && end == null) {
System.out.println(" ==> " + result.toString());
+ }
}
}
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/AbstractDominatorsAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/AbstractDominatorsAnalysis.java
index 8963466..66e5fad 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AbstractDominatorsAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AbstractDominatorsAnalysis.java
@@ -41,7 +41,7 @@ import org.apache.bcel.generic.InstructionHandle;
* An EdgeChooser may be specified to select which edges to take into account.
* For example, exception edges could be ignored.
* </p>
- *
+ *
* @author David Hovemeyer
* @see DataflowAnalysis
* @see CFG
@@ -50,11 +50,11 @@ import org.apache.bcel.generic.InstructionHandle;
public abstract class AbstractDominatorsAnalysis extends BasicAbstractDataflowAnalysis<BitSet> {
private final CFG cfg;
- private EdgeChooser edgeChooser;
+ private final EdgeChooser edgeChooser;
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG to compute dominator relationships for
* @param ignoreExceptionEdges
@@ -62,18 +62,20 @@ public abstract class AbstractDominatorsAnalysis extends BasicAbstractDataflowAn
*/
public AbstractDominatorsAnalysis(CFG cfg, final boolean ignoreExceptionEdges) {
this(cfg, new EdgeChooser() {
+ @Override
public boolean choose(Edge edge) {
- if (ignoreExceptionEdges && edge.isExceptionEdge())
+ if (ignoreExceptionEdges && edge.isExceptionEdge()) {
return false;
- else
+ } else {
return true;
+ }
}
});
}
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG to compute dominator relationships for
* @param edgeChooser
@@ -84,34 +86,41 @@ public abstract class AbstractDominatorsAnalysis extends BasicAbstractDataflowAn
this.edgeChooser = edgeChooser;
}
+ @Override
public BitSet createFact() {
return new BitSet();
}
+ @Override
public void copy(BitSet source, BitSet dest) {
dest.clear();
dest.or(source);
}
+ @Override
public void initEntryFact(BitSet result) {
// No blocks dominate the entry block
result.clear();
}
+ @Override
public boolean isTop(BitSet fact) {
// We represent TOP as a bitset with an illegal bit set
return fact.get(cfg.getNumBasicBlocks());
}
+ @Override
public void makeFactTop(BitSet fact) {
// We represent TOP as a bitset with an illegal bit set
fact.set(cfg.getNumBasicBlocks());
}
+ @Override
public boolean same(BitSet fact1, BitSet fact2) {
return fact1.equals(fact2);
}
+ @Override
public void transfer(BasicBlock basicBlock, @CheckForNull InstructionHandle end, BitSet start, BitSet result)
throws DataflowAnalysisException {
// Start with intersection of dominators of predecessors
@@ -123,23 +132,26 @@ public abstract class AbstractDominatorsAnalysis extends BasicAbstractDataflowAn
}
}
+ @Override
public void meetInto(BitSet fact, Edge edge, BitSet result) throws DataflowAnalysisException {
- if (!edgeChooser.choose(edge))
+ if (!edgeChooser.choose(edge)) {
return;
+ }
- if (isTop(fact))
+ if (isTop(fact)) {
return;
- else if (isTop(result))
+ } else if (isTop(result)) {
copy(fact, result);
- else
+ } else {
// Meet is intersection
result.and(fact);
+ }
}
/**
* Get a bitset containing the unique IDs of all blocks which dominate (or
* postdominate) the given block.
- *
+ *
* @param block
* a BasicBlock
* @return BitSet of the unique IDs of all blocks that dominate (or
@@ -152,7 +164,7 @@ public abstract class AbstractDominatorsAnalysis extends BasicAbstractDataflowAn
/**
* Get a bitset containing the unique IDs of all blocks in CFG dominated (or
* postdominated, depending on how the analysis was done) by given block.
- *
+ *
* @param dominator
* we want to get all blocks dominated (or postdominated) by this
* block
@@ -163,12 +175,12 @@ public abstract class AbstractDominatorsAnalysis extends BasicAbstractDataflowAn
for (Iterator<BasicBlock> i = cfg.blockIterator(); i.hasNext();) {
BasicBlock block = i.next();
BitSet dominators = getResultFact(block);
- if (dominators.get(dominator.getLabel()))
+ if (dominators.get(dominator.getLabel())) {
allDominated.set(block.getLabel());
+ }
}
return allDominated;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/AbstractField.java b/src/java/edu/umd/cs/findbugs/ba/AbstractField.java
index 97da387..203b242 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AbstractField.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AbstractField.java
@@ -31,23 +31,25 @@ public abstract class AbstractField extends AbstractClassMember implements XFiel
super(className, fieldName, fieldSig, accessFlags);
}
+ @Override
public boolean isVolatile() {
return (getAccessFlags() & Constants.ACC_VOLATILE) != 0;
}
+ @Override
public final boolean isSynthetic() {
return (getAccessFlags() & Constants.ACC_SYNTHETIC) != 0;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.XField#getFieldDescriptor()
*/
+ @Override
public FieldDescriptor getFieldDescriptor() {
return DescriptorFactory.instance().getFieldDescriptor(getClassDescriptor().getClassName(), getName(), getSignature(),
isStatic());
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/AbstractFrameModelingVisitor.java b/src/java/edu/umd/cs/findbugs/ba/AbstractFrameModelingVisitor.java
index 0eb1060..52468c9 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AbstractFrameModelingVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AbstractFrameModelingVisitor.java
@@ -50,7 +50,7 @@ import edu.umd.cs.findbugs.bcel.generic.NULL2Z;
* @see Frame
* @see DataflowAnalysis
*/
-public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Frame<Value>> implements Visitor {
+public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Frame<Value>> implements VisitorSupportsInvokeDynamic {
private FrameType frame;
private Location location;
@@ -79,13 +79,14 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
* analyzed is invalid
*/
public void analyzeInstruction(Instruction ins) throws DataflowAnalysisException {
- if (frame.isValid())
+ if (frame.isValid()) {
try {
ins.accept(this);
} catch (InvalidBytecodeException e) {
String message = "Invalid bytecode: could not analyze instr. " + ins + " at frame " + frame;
throw new DataflowAnalysisException(message, e);
}
+ }
}
/**
@@ -138,8 +139,9 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
*/
public int getNumWordsConsumed(Instruction ins) {
int numWordsConsumed = ins.consumeStack(cpg);
- if (numWordsConsumed == Constants.UNPREDICTABLE)
+ if (numWordsConsumed == Constants.UNPREDICTABLE) {
throw new InvalidBytecodeException("Unpredictable stack consumption");
+ }
return numWordsConsumed;
}
@@ -149,8 +151,9 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
public int getNumWordsProduced(Instruction ins) {
int numWordsProduced = ins.produceStack(cpg);
- if (numWordsProduced == Constants.UNPREDICTABLE)
+ if (numWordsProduced == Constants.UNPREDICTABLE) {
throw new InvalidBytecodeException("Unpredictable stack productions");
+ }
return numWordsProduced;
}
@@ -169,99 +172,128 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
* ----------------------------------------------------------------------
*/
+ @Override
public void visitStackInstruction(StackInstruction obj) {
}
+ @Override
public void visitLocalVariableInstruction(LocalVariableInstruction obj) {
}
+ @Override
public void visitBranchInstruction(BranchInstruction obj) {
}
+ @Override
public void visitLoadClass(LoadClass obj) {
}
+ @Override
public void visitFieldInstruction(FieldInstruction obj) {
}
+ @Override
public void visitIfInstruction(IfInstruction obj) {
}
/** To allow for calls to visitNULL2Z and visitNONNULL2Z, this method is made final.
* If you want to override it, override visitConversionInstruction2 instead.
*/
+ @Override
public final void visitConversionInstruction(ConversionInstruction obj) {
visitConversionInstruction2(obj);
- if (obj instanceof NULL2Z)
+ if (obj instanceof NULL2Z) {
visitNULL2Z((NULL2Z) obj);
- else if (obj instanceof NONNULL2Z)
+ } else if (obj instanceof NONNULL2Z) {
visitNONNULL2Z((NONNULL2Z) obj);
+ }
}
public final void visitConversionInstruction2(ConversionInstruction obj) {
}
+ @Override
public void visitPopInstruction(PopInstruction obj) {
}
+ @Override
public void visitJsrInstruction(JsrInstruction obj) {
}
+ @Override
public void visitGotoInstruction(GotoInstruction obj) {
}
+ @Override
public void visitStoreInstruction(StoreInstruction obj) {
}
+ @Override
public void visitTypedInstruction(TypedInstruction obj) {
}
+ @Override
public void visitSelect(Select obj) {
}
+ @Override
public void visitUnconditionalBranch(UnconditionalBranch obj) {
}
+ @Override
public void visitPushInstruction(PushInstruction obj) {
}
+ @Override
public void visitArithmeticInstruction(ArithmeticInstruction obj) {
}
+ @Override
public void visitCPInstruction(CPInstruction obj) {
}
+ @Override
public void visitInvokeInstruction(InvokeInstruction obj) {
}
+ @Override
public void visitArrayInstruction(ArrayInstruction obj) {
}
+ @Override
public void visitAllocationInstruction(AllocationInstruction obj) {
}
+ @Override
public void visitReturnInstruction(ReturnInstruction obj) {
}
+ @Override
public void visitFieldOrMethod(FieldOrMethod obj) {
}
+ @Override
public void visitConstantPushInstruction(ConstantPushInstruction obj) {
}
+ @Override
public void visitExceptionThrower(ExceptionThrower obj) {
}
+ @Override
public void visitLoadInstruction(LoadInstruction obj) {
}
+ @Override
public void visitVariableLengthInstruction(VariableLengthInstruction obj) {
}
+ @Override
public void visitStackProducer(StackProducer obj) {
}
+ @Override
public void visitStackConsumer(StackConsumer obj) {
}
@@ -279,8 +311,9 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
public void handleStoreInstruction(StoreInstruction obj) {
try {
int numConsumed = obj.consumeStack(cpg);
- if (numConsumed == Constants.UNPREDICTABLE)
+ if (numConsumed == Constants.UNPREDICTABLE) {
throw new InvalidBytecodeException("Unpredictable stack consumption");
+ }
int index = obj.getIndex();
@@ -302,8 +335,9 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
*/
public void handleLoadInstruction(LoadInstruction obj) {
int numProduced = obj.produceStack(cpg);
- if (numProduced == Constants.UNPREDICTABLE)
+ if (numProduced == Constants.UNPREDICTABLE) {
throw new InvalidBytecodeException("Unpredictable stack production");
+ }
int index = obj.getIndex() + numProduced;
@@ -364,14 +398,16 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
}
}
try {
- while (numWordsConsumed-- > 0)
+ while (numWordsConsumed-- > 0) {
frame.popValue();
+ }
} catch (DataflowAnalysisException e) {
throw new InvalidBytecodeException("Not enough values on the stack", e);
}
- while (numWordsProduced-- > 0)
+ while (numWordsProduced-- > 0) {
frame.pushValue(pushValue);
+ }
}
/*
@@ -380,22 +416,27 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
* ----------------------------------------------------------------------
*/
+ @Override
public void visitASTORE(ASTORE obj) {
handleStoreInstruction(obj);
}
+ @Override
public void visitDSTORE(DSTORE obj) {
handleStoreInstruction(obj);
}
+ @Override
public void visitFSTORE(FSTORE obj) {
handleStoreInstruction(obj);
}
+ @Override
public void visitISTORE(ISTORE obj) {
handleStoreInstruction(obj);
}
+ @Override
public void visitLSTORE(LSTORE obj) {
handleStoreInstruction(obj);
}
@@ -406,22 +447,27 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
* ----------------------------------------------------------------------
*/
+ @Override
public void visitALOAD(ALOAD obj) {
handleLoadInstruction(obj);
}
+ @Override
public void visitDLOAD(DLOAD obj) {
handleLoadInstruction(obj);
}
+ @Override
public void visitFLOAD(FLOAD obj) {
handleLoadInstruction(obj);
}
+ @Override
public void visitILOAD(ILOAD obj) {
handleLoadInstruction(obj);
}
+ @Override
public void visitLLOAD(LLOAD obj) {
handleLoadInstruction(obj);
}
@@ -432,14 +478,17 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
* ----------------------------------------------------------------------
*/
+ @Override
public void visitPOP(POP obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitPOP2(POP2 obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDUP(DUP obj) {
try {
Value value = frame.popValue();
@@ -450,6 +499,7 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
}
}
+ @Override
public void visitDUP_X1(DUP_X1 obj) {
try {
Value value1 = frame.popValue();
@@ -462,6 +512,7 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
}
}
+ @Override
public void visitDUP_X2(DUP_X2 obj) {
try {
Value value1 = frame.popValue();
@@ -476,6 +527,7 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
}
}
+ @Override
public void visitDUP2(DUP2 obj) {
try {
Value value1 = frame.popValue();
@@ -489,6 +541,7 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
}
}
+ @Override
public void visitDUP2_X1(DUP2_X1 obj) {
try {
Value value1 = frame.popValue();
@@ -504,6 +557,7 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
}
}
+ @Override
public void visitDUP2_X2(DUP2_X2 obj) {
try {
Value value1 = frame.popValue();
@@ -521,6 +575,7 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
}
}
+ @Override
public void visitSWAP(SWAP obj) {
try {
Value value1 = frame.popValue();
@@ -538,14 +593,17 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
* ----------------------------------------------------------------------
*/
+ @Override
public void visitIMPDEP1(IMPDEP1 obj) {
illegalBytecode(obj);
}
+ @Override
public void visitIMPDEP2(IMPDEP2 obj) {
illegalBytecode(obj);
}
+ @Override
public void visitBREAKPOINT(BREAKPOINT obj) {
illegalBytecode(obj);
}
@@ -556,230 +614,287 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
* ----------------------------------------------------------------------
*/
+ @Override
public void visitACONST_NULL(ACONST_NULL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitGETSTATIC(GETSTATIC obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIF_ICMPLT(IF_ICMPLT obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitMONITOREXIT(MONITOREXIT obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIFLT(IFLT obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitBASTORE(BASTORE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitCHECKCAST(CHECKCAST obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFCMPG(FCMPG obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitI2F(I2F obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitATHROW(ATHROW obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDCMPL(DCMPL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitARRAYLENGTH(ARRAYLENGTH obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitINVOKESTATIC(INVOKESTATIC obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLCONST(LCONST obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDREM(DREM obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIFGE(IFGE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitCALOAD(CALOAD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLASTORE(LASTORE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitI2D(I2D obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDADD(DADD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitINVOKESPECIAL(INVOKESPECIAL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIAND(IAND obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitPUTFIELD(PUTFIELD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDCONST(DCONST obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitNEW(NEW obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIFNULL(IFNULL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLSUB(LSUB obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitL2I(L2I obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitISHR(ISHR obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitTABLESWITCH(TABLESWITCH obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIINC(IINC obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDRETURN(DRETURN obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDASTORE(DASTORE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIALOAD(IALOAD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDDIV(DDIV obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIF_ICMPGE(IF_ICMPGE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLAND(LAND obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIDIV(IDIV obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLOR(LOR obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitCASTORE(CASTORE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFREM(FREM obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLDC(LDC obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitBIPUSH(BIPUSH obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitF2L(F2L obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFMUL(FMUL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitJSR(JSR obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFSUB(FSUB obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitSASTORE(SASTORE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitRETURN(RETURN obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDALOAD(DALOAD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitSIPUSH(SIPUSH obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDSUB(DSUB obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitL2F(L2F obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIF_ICMPGT(IF_ICMPGT obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitF2D(F2D obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitI2L(I2L obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIF_ACMPNE(IF_ACMPNE obj) {
handleNormalInstruction(obj);
}
@@ -793,297 +908,373 @@ public abstract class AbstractFrameModelingVisitor<Value, FrameType extends Fram
handleNormalInstruction(obj);
}
+ @Override
public void visitI2S(I2S obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIFEQ(IFEQ obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIOR(IOR obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIREM(IREM obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIASTORE(IASTORE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitNEWARRAY(NEWARRAY obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitINEG(INEG obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLCMP(LCMP obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitJSR_W(JSR_W obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitMULTIANEWARRAY(MULTIANEWARRAY obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitSALOAD(SALOAD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIFNONNULL(IFNONNULL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDMUL(DMUL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIFNE(IFNE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIF_ICMPLE(IF_ICMPLE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLDC2_W(LDC2_W obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitGETFIELD(GETFIELD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLADD(LADD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitNOP(NOP obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFALOAD(FALOAD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitINSTANCEOF(INSTANCEOF obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIFLE(IFLE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLXOR(LXOR obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLRETURN(LRETURN obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFCONST(FCONST obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIUSHR(IUSHR obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitBALOAD(BALOAD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIF_ACMPEQ(IF_ACMPEQ obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitMONITORENTER(MONITORENTER obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLSHL(LSHL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDCMPG(DCMPG obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitD2L(D2L obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitL2D(L2D obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitRET(RET obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIFGT(IFGT obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIXOR(IXOR obj) {
handleNormalInstruction(obj);
}
+ @Override
+ public void visitINVOKEDYNAMIC(INVOKEDYNAMIC obj) {
+ handleNormalInstruction(obj);
+ }
+ @Override
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFASTORE(FASTORE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIRETURN(IRETURN obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIF_ICMPNE(IF_ICMPNE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLDIV(LDIV obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitPUTSTATIC(PUTSTATIC obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitAALOAD(AALOAD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitD2I(D2I obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIF_ICMPEQ(IF_ICMPEQ obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitAASTORE(AASTORE obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitARETURN(ARETURN obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFNEG(FNEG obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitGOTO_W(GOTO_W obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitD2F(D2F obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitGOTO(GOTO obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitISUB(ISUB obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitF2I(F2I obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitDNEG(DNEG obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitICONST(ICONST obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFDIV(FDIV obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitI2B(I2B obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLNEG(LNEG obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLREM(LREM obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIMUL(IMUL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitIADD(IADD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLSHR(LSHR obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLOOKUPSWITCH(LOOKUPSWITCH obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFCMPL(FCMPL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitI2C(I2C obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLMUL(LMUL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLUSHR(LUSHR obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitISHL(ISHL obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitLALOAD(LALOAD obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitANEWARRAY(ANEWARRAY obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFRETURN(FRETURN obj) {
handleNormalInstruction(obj);
}
+ @Override
public void visitFADD(FADD obj) {
handleNormalInstruction(obj);
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/AbstractMethod.java b/src/java/edu/umd/cs/findbugs/ba/AbstractMethod.java
index 5080157..499ea00 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AbstractMethod.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AbstractMethod.java
@@ -31,38 +31,49 @@ public abstract class AbstractMethod extends AbstractClassMember implements XMet
super(className, methodName, methodSig, accessFlags);
}
+ @Override
public int getNumParams() {
// FIXME: cache this?
return new SignatureParser(getSignature()).getNumParameters();
}
+ @Override
public boolean isNative() {
return (getAccessFlags() & Constants.ACC_NATIVE) != 0;
}
+ @Override
public boolean isSynchronized() {
return (getAccessFlags() & Constants.ACC_SYNCHRONIZED) != 0;
}
@Override
+ public boolean isBridge() {
+ return (getAccessFlags() & Constants.ACC_BRIDGE) != 0;
+ }
+
+ @Override
public String toString() {
return SignatureConverter.convertMethodSignature(this);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.XMethod#getMethodDescriptor()
*/
+ @Override
public MethodDescriptor getMethodDescriptor() {
return DescriptorFactory.instance().getMethodDescriptor(ClassName.toSlashedClassName(getClassName()), getName(),
getSignature(), isStatic());
}
-
+
+ @Override
public XMethod resolveAccessMethodForMethod() {
MethodDescriptor access = getAccessMethodForMethod();
- if (access != null)
+ if (access != null) {
return XFactory.createXMethod(access);
+ }
return this;
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/AccessibleEntity.java b/src/java/edu/umd/cs/findbugs/ba/AccessibleEntity.java
index d4f6c4c..e142285 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AccessibleEntity.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AccessibleEntity.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
/**
* Common superinterface for code entities having access flags: classes, fields,
* and methods.
- *
+ *
* @author David Hovemeyer
*/
public interface AccessibleEntity {
diff --git a/src/java/edu/umd/cs/findbugs/ba/AnalysisContext.java b/src/java/edu/umd/cs/findbugs/ba/AnalysisContext.java
index 935fecc..8b53002 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AnalysisContext.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AnalysisContext.java
@@ -18,6 +18,7 @@
*/
package edu.umd.cs.findbugs.ba;
+import static java.util.Objects.requireNonNull;
import java.io.File;
import java.io.IOException;
@@ -122,21 +123,19 @@ public class AnalysisContext {
}
};
-
-
/**
* save the original SyntheticRepository so we may obtain JavaClass objects
* which we can reuse. (A URLClassPathRepository gets closed after
* analysis.)
*/
private static final org.apache.bcel.util.Repository originalRepository = Repository.getRepository(); // BCEL
- // SyntheticRepository
+ // SyntheticRepository
/**
* Default maximum number of ClassContext objects to cache. FIXME: need to
* evaluate this parameter. Need to keep stats about accesses.
*/
- private static final int DEFAULT_CACHE_SIZE = 3;
+ // private static final int DEFAULT_CACHE_SIZE = 3;
// Instance fields
private BitSet boolPropertySet;
@@ -145,10 +144,46 @@ public class AnalysisContext {
private String databaseOutputDir;
- public AnalysisContext() {
+ boolean missingClassWarningsSuppressed;
+
+ private ClassSummary classSummary;
+
+ private ClassDescriptor classBeingAnalyzed;
+
+ private FieldSummary fieldSummary;
+
+ private UnreadFields unreadFields;
+
+ private TypeQualifierNullnessAnnotationDatabase tqNullnessDatabase;
+
+ private final HashSet<MethodDescriptor> skippedDueToInvokeDynamic;
+
+ private final Project project;
+
+ private final EqualsKindSummary equalsKindSummary;
+
+ private final UnreadFieldsData unreadFieldsData;
+
+ private final SuppressionMatcher suppressionMatcher;
+
+ protected final RepositoryLookupFailureCallback lookupFailureCallback;
+
+ private final Map<MethodInfo, MethodInfo> bridgeTo;
+
+ private final Map<MethodInfo, MethodInfo> bridgeFrom;
+
+
+ public AnalysisContext(@Nonnull Project project) {
+ requireNonNull(project);
+ this.project = project;
this.boolPropertySet = new BitSet();
this.lookupFailureCallback = new DelegatingRepositoryLookupFailureCallback();
-
+ skippedDueToInvokeDynamic = new HashSet<>();
+ equalsKindSummary = new EqualsKindSummary();
+ unreadFieldsData = new UnreadFieldsData();
+ suppressionMatcher = new SuppressionMatcher();
+ bridgeTo = new IdentityHashMap<>();
+ bridgeFrom = new IdentityHashMap<>();
}
private void clear() {
@@ -157,7 +192,6 @@ public class AnalysisContext {
databaseOutputDir = null;
}
-
/**
* Get the AnalysisContext associated with this thread
*/
@@ -169,10 +203,6 @@ public class AnalysisContext {
return currentXFactory.get();
}
- ClassSummary classSummary;
-
- ClassDescriptor classBeingAnalyzed;
-
public ClassDescriptor getClassBeingAnalyzed() {
return classBeingAnalyzed;
}
@@ -180,29 +210,29 @@ public class AnalysisContext {
public void setClassBeingAnalyzed(@Nonnull ClassDescriptor classBeingAnalyzed) {
this.classBeingAnalyzed = classBeingAnalyzed;
}
+
public void clearClassBeingAnalyzed() {
this.classBeingAnalyzed = null;
}
+
public ClassSummary getClassSummary() {
- if (classSummary == null)
+ if (classSummary == null) {
throw new IllegalStateException("ClassSummary not set");
+ }
return classSummary;
}
public void setClassSummary(@Nonnull ClassSummary classSummary) {
- if (this.classSummary != null)
+ if (this.classSummary != null) {
throw new IllegalStateException("ClassSummary already set");
+ }
this.classSummary = classSummary;
}
- final EqualsKindSummary equalsKindSummary = new EqualsKindSummary();
-
public EqualsKindSummary getEqualsKindSummary() {
return equalsKindSummary;
}
- FieldSummary fieldSummary;
-
public FieldSummary getFieldSummary() {
if (fieldSummary == null) {
AnalysisContext.logError("Field Summary not set", new IllegalStateException());
@@ -218,16 +248,14 @@ public class AnalysisContext {
this.fieldSummary = fieldSummary;
}
- final UnreadFieldsData unreadFieldsData = new UnreadFieldsData();
- UnreadFields unreadFields;
-
public @Nonnull UnreadFieldsData getUnreadFieldsData() {
return unreadFieldsData;
}
public @Nonnull UnreadFields getUnreadFields() {
- if (unreadFieldsAvailable())
+ if (!unreadFieldsAvailable()) {
throw new IllegalStateException();
+ }
return unreadFields;
}
@@ -236,22 +264,25 @@ public class AnalysisContext {
}
public void setUnreadFields(@Nonnull UnreadFields unreadFields) {
- if (this.unreadFields != null)
+ if (this.unreadFields != null) {
throw new IllegalStateException("UnreadFields detector already set");
+ }
this.unreadFields = unreadFields;
}
- private static boolean skipReportingMissingClass(@CheckForNull @DottedClassName String missing) {
+ private static boolean skipReportingMissingClass(@CheckForNull @DottedClassName String missing) {
return missing == null || missing.length() == 0 || missing.charAt(0) == '[' || missing.endsWith("package-info");
}
private static @CheckForNull
RepositoryLookupFailureCallback getCurrentLookupFailureCallback() {
AnalysisContext currentAnalysisContext2 = currentAnalysisContext();
- if (currentAnalysisContext2 == null)
+ if (currentAnalysisContext2 == null) {
return null;
- if (currentAnalysisContext2.missingClassWarningsSuppressed)
+ }
+ if (currentAnalysisContext2.missingClassWarningsSuppressed) {
return null;
+ }
return currentAnalysisContext2.getLookupFailureCallback();
}
@@ -261,54 +292,59 @@ public class AnalysisContext {
* @see #getLookupFailureCallback()
*/
static public void reportMissingClass(ClassNotFoundException e) {
- if (e == null)
- throw new NullPointerException("argument is null");
+ requireNonNull(e, "argument is null");
String missing = AbstractBugReporter.getMissingClassName(e);
- if (skipReportingMissingClass(missing))
+ if (skipReportingMissingClass(missing)) {
return;
- if (!analyzingApplicationClass())
+ }
+ if (!analyzingApplicationClass()) {
return;
+ }
RepositoryLookupFailureCallback lookupFailureCallback = getCurrentLookupFailureCallback();
- if (lookupFailureCallback != null)
+ if (lookupFailureCallback != null) {
lookupFailureCallback.reportMissingClass(e);
+ }
}
static public void reportMissingClass(edu.umd.cs.findbugs.ba.MissingClassException e) {
- if (e == null)
- throw new NullPointerException("argument is null");
+ requireNonNull(e, "argument is null");
reportMissingClass(e.getClassDescriptor());
}
static public boolean analyzingApplicationClass() {
AnalysisContext context = AnalysisContext.currentAnalysisContext();
- if (context == null)
+ if (context == null) {
return false;
+ }
ClassDescriptor clazz = context.getClassBeingAnalyzed();
- if (clazz == null)
+ if (clazz == null) {
return false;
+ }
return context.isApplicationClass(clazz);
}
+
static public void reportMissingClass(edu.umd.cs.findbugs.classfile.MissingClassException e) {
- if (e == null)
- throw new NullPointerException("argument is null");
+ requireNonNull(e, "argument is null");
reportMissingClass(e.getClassDescriptor());
}
-
static public void reportMissingClass(ClassDescriptor c) {
- if (c == null)
- throw new NullPointerException("argument is null");
- if (!analyzingApplicationClass())
+ requireNonNull(c, "argument is null");
+ if (!analyzingApplicationClass()) {
return;
+ }
String missing = c.getDottedClassName();
- if (missing.length() == 1)
+ if (missing.length() == 1) {
System.out.println(c);
- if (skipReportingMissingClass(missing))
+ }
+ if (skipReportingMissingClass(missing)) {
return;
+ }
RepositoryLookupFailureCallback lookupFailureCallback = getCurrentLookupFailureCallback();
- if (lookupFailureCallback != null)
+ if (lookupFailureCallback != null) {
lookupFailureCallback.reportMissingClass(c);
+ }
}
/**
@@ -317,13 +353,16 @@ public class AnalysisContext {
static public void logError(String msg, Exception e) {
AnalysisContext currentAnalysisContext2 = currentAnalysisContext();
if (currentAnalysisContext2 == null) {
- if (e instanceof NoSuchBugPattern)
+ if (e instanceof NoSuchBugPattern) {
return;
+ }
+ /*
if (false && SystemProperties.ASSERTIONS_ENABLED) {
AssertionError e2 = new AssertionError("Exception logged with no analysis context");
e2.initCause(e);
throw e2;
}
+ */
e.printStackTrace(System.err);
return;
}
@@ -337,8 +376,9 @@ public class AnalysisContext {
}
RepositoryLookupFailureCallback lookupFailureCallback = currentAnalysisContext2.getLookupFailureCallback();
- if (lookupFailureCallback != null)
+ if (lookupFailureCallback != null) {
lookupFailureCallback.logError(msg, e);
+ }
}
/**
@@ -346,16 +386,28 @@ public class AnalysisContext {
*/
static public void logError(String msg) {
AnalysisContext currentAnalysisContext2 = currentAnalysisContext();
- if (currentAnalysisContext2 == null)
+ if (currentAnalysisContext2 == null) {
return;
- RepositoryLookupFailureCallback lookupFailureCallback = currentAnalysisContext2.getLookupFailureCallback();
- if (lookupFailureCallback != null)
+ }
+ currentAnalysisContext2.logAnError(msg);
+ }
+
+ public void logAnError(String msg) {
+ RepositoryLookupFailureCallback lookupFailureCallback = getLookupFailureCallback();
+ if (lookupFailureCallback != null) {
lookupFailureCallback.logError(msg);
+ }
}
- boolean missingClassWarningsSuppressed = false;
+ public void analysisSkippedDueToInvokeDynamic(XMethod m) {
+ if (!m.usesInvokeDynamic()) {
+ throw new IllegalArgumentException();
+ }
+ if (skippedDueToInvokeDynamic.add(m.getMethodDescriptor())) {
+ logAnError(m + " skipped due to invoke_dynamic");
+ }
- protected Project project;
+ }
public boolean setMissingClassWarningsSuppressed(boolean value) {
boolean oldValue = missingClassWarningsSuppressed;
@@ -363,14 +415,6 @@ public class AnalysisContext {
return oldValue;
}
-
- /**
- * Set the source path.
- */
- public final void setProject(Project project) {
- this.project = project;
- }
-
// /**
// * Add an application class to the repository.
// *
@@ -419,7 +463,7 @@ public class AnalysisContext {
IAnalysisCache analysisCache = Global.getAnalysisCache();
try {
- ClassContext classContext = analysisCache.getClassAnalysis(ClassContext.class, desc);
+ /* ClassContext classContext =*/ analysisCache.getClassAnalysis(ClassContext.class, desc);
ClassData classData = analysisCache.getClassAnalysis(ClassData.class, desc);
return classData.getData().length;
@@ -430,7 +474,6 @@ public class AnalysisContext {
AnalysisContext.logError("Could not get class context for " + desc, e);
return 10000;
}
-
}
public boolean isTooBig(ClassDescriptor desc) {
@@ -439,12 +482,14 @@ public class AnalysisContext {
try {
ClassContext classContext = analysisCache.getClassAnalysis(ClassContext.class, desc);
ClassData classData = analysisCache.getClassAnalysis(ClassData.class, desc);
- if (classData.getData().length > 1000000)
+ if (classData.getData().length > 1000000) {
return true;
+ }
try {
- JavaClass javaClass = classContext.getJavaClass();
- if (javaClass.getMethods().length > 1000)
- return true;
+ JavaClass javaClass = classContext.getJavaClass();
+ if (javaClass.getMethods().length > 1000) {
+ return true;
+ }
} catch (RuntimeException e) {
AnalysisContext.logError("Error parsing class " + desc
+ " from " + classData.getCodeBaseEntry().getCodeBase(), e);
@@ -459,7 +504,6 @@ public class AnalysisContext {
return true;
}
return false;
-
}
/**
@@ -492,10 +536,10 @@ public class AnalysisContext {
public static JavaClass lookupSystemClass(@Nonnull String className) throws ClassNotFoundException {
// TODO: eventually we should move to our own thread-safe repository
// implementation
- if (className == null)
- throw new IllegalArgumentException("className is null");
- if (originalRepository == null)
+ requireNonNull (className, "className is null");
+ if (originalRepository == null) {
throw new IllegalStateException("originalRepository is null");
+ }
JavaClass clazz = originalRepository.findClass(className);
return (clazz == null ? originalRepository.loadClass(className) : clazz);
@@ -511,8 +555,7 @@ public class AnalysisContext {
* determine
*/
public final String lookupSourceFile(@Nonnull @DottedClassName String dottedClassName) {
- if (dottedClassName == null)
- throw new IllegalArgumentException("className is null");
+ requireNonNull(dottedClassName, "className is null");
try {
XClass xClass = Global.getAnalysisCache().getClassAnalysis(XClass.class,
DescriptorFactory.createClassDescriptorFromDottedClassName(dottedClassName));
@@ -542,8 +585,9 @@ public class AnalysisContext {
* dereference parameters.
*/
public final void loadDefaultInterproceduralDatabases() {
- if (IGNORE_BUILTIN_MODELS)
+ if (IGNORE_BUILTIN_MODELS) {
return;
+ }
loadPropertyDatabaseFromResource(getUnconditionalDerefParamDatabase(), UNCONDITIONAL_DEREF_DB_RESOURCE,
"unconditional param deref database");
loadPropertyDatabaseFromResource(getReturnValueNullnessPropertyDatabase(), NONNULL_RETURN_DB_RESOURCE,
@@ -581,8 +625,9 @@ public class AnalysisContext {
* the interprocedural database input directory
*/
public final void setDatabaseInputDir(String databaseInputDir) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Setting database input directory: " + databaseInputDir);
+ }
this.databaseInputDir = databaseInputDir;
}
@@ -602,8 +647,9 @@ public class AnalysisContext {
* the interprocedural database output directory
*/
public final void setDatabaseOutputDir(String databaseOutputDir) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Setting database output directory: " + databaseOutputDir);
+ }
this.databaseOutputDir = databaseOutputDir;
}
@@ -616,8 +662,6 @@ public class AnalysisContext {
return databaseOutputDir;
}
-
-
/**
* Load an interprocedural property database.
*
@@ -639,8 +683,9 @@ public class AnalysisContext {
DatabaseType database, String fileName, String description) {
try {
File dbFile = new File(getDatabaseInputDir(), fileName);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Loading " + description + " from " + dbFile.getPath() + "...");
+ }
database.readFromFile(dbFile.getPath());
return database;
@@ -649,7 +694,6 @@ public class AnalysisContext {
} catch (PropertyDatabaseFormatException e) {
getLookupFailureCallback().logError("Invalid " + description, e);
}
-
return null;
}
@@ -673,15 +717,16 @@ public class AnalysisContext {
public <DatabaseType extends PropertyDatabase<KeyType, Property>, KeyType extends FieldOrMethodDescriptor, Property> DatabaseType loadPropertyDatabaseFromResource(
DatabaseType database, String resourceName, String description) {
try {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Loading default " + description + " from " + resourceName + " @ "
+ database.getClass().getResource(resourceName) + " ... ");
- InputStream in = database.getClass().getResourceAsStream(resourceName);
- if (in == null) {
- AnalysisContext.logError("Unable to load " + description + " from resource " + resourceName);
- } else {
- database.read(in);
- in.close();
+ }
+ try(InputStream in = database.getClass().getResourceAsStream(resourceName)){
+ if (in == null) {
+ AnalysisContext.logError("Unable to load " + description + " from resource " + resourceName);
+ } else {
+ database.read(in);
+ }
}
return database;
} catch (IOException e) {
@@ -689,7 +734,6 @@ public class AnalysisContext {
} catch (PropertyDatabaseFormatException e) {
getLookupFailureCallback().logError("Invalid " + description, e);
}
-
return null;
}
@@ -714,8 +758,9 @@ public class AnalysisContext {
try {
File dbFile = new File(getDatabaseOutputDir(), fileName);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Writing " + description + " to " + dbFile.getPath() + "...");
+ }
database.writeToFile(dbFile.getPath());
} catch (IOException e) {
getLookupFailureCallback().logError("Error writing " + description, e);
@@ -730,18 +775,19 @@ public class AnalysisContext {
*/
public static void setCurrentAnalysisContext(AnalysisContext analysisContext) {
currentAnalysisContext.set(analysisContext);
- if (Global.getAnalysisCache() != null)
+ if (Global.getAnalysisCache() != null) {
currentXFactory.set(new XFactory());
+ }
}
public static void removeCurrentAnalysisContext() {
AnalysisContext context = currentAnalysisContext();
- if (context != null)
+ if (context != null) {
context.clear();
+ }
currentAnalysisContext.remove();
}
-
/**
* Get Collection of all XClass objects seen so far.
*
@@ -751,16 +797,6 @@ public class AnalysisContext {
return getSubtypes2().getXClassCollection();
}
- private final SuppressionMatcher suppressionMatcher = new SuppressionMatcher();
-
- private TypeQualifierNullnessAnnotationDatabase tqNullnessDatabase;
-
- protected final RepositoryLookupFailureCallback lookupFailureCallback;
-
- final Map<MethodInfo, MethodInfo> bridgeTo = new IdentityHashMap<MethodInfo, MethodInfo>();
-
- final Map<MethodInfo, MethodInfo> bridgeFrom = new IdentityHashMap<MethodInfo, MethodInfo>();
-
public SuppressionMatcher getSuppressionMatcher() {
return suppressionMatcher;
}
@@ -793,12 +829,10 @@ public class AnalysisContext {
Repository.setRepository(new AnalysisCacheToRepositoryAdapter());
}
-
public AnnotationRetentionDatabase getAnnotationRetentionDatabase() {
return getDatabase(AnnotationRetentionDatabase.class);
}
-
public CheckReturnAnnotationDatabase getCheckReturnAnnotationDatabase() {
return getDatabase(CheckReturnAnnotationDatabase.class);
}
@@ -904,8 +938,9 @@ public class AnalysisContext {
*/
public JavaClass lookupClass(@Nonnull @DottedClassName String className) throws ClassNotFoundException {
try {
- if (className.length() == 0)
+ if (className.length() == 0) {
throw new IllegalArgumentException("Class name is empty");
+ }
if (!ClassName.isValidClassName(className)) {
throw new ClassNotFoundException("Invalid class name: " + className);
}
@@ -921,28 +956,30 @@ public class AnalysisContext {
}
public void setAppClassList(List<ClassDescriptor> appClassCollection) {
-
// FIXME: we really should drive the progress callback here
HashSet<ClassDescriptor> appSet = new HashSet<ClassDescriptor>(appClassCollection);
Collection<ClassDescriptor> allClassDescriptors = new ArrayList<ClassDescriptor>(DescriptorFactory.instance()
.getAllClassDescriptors());
- for (ClassDescriptor appClass : allClassDescriptors)
+ for (ClassDescriptor appClass : allClassDescriptors) {
try {
XClass xclass = currentXFactory().getXClass(appClass);
- if (xclass == null)
+ if (xclass == null) {
continue;
+ }
// Add the application class to the database
- if (appSet.contains(appClass))
+ if (appSet.contains(appClass)) {
getSubtypes2().addApplicationClass(xclass);
- else if (xclass instanceof ClassInfo)
+ } else if (xclass instanceof ClassInfo) {
getSubtypes2().addClass(xclass);
+ }
} catch (Exception e) {
AnalysisContext.logError("Unable to get XClass for " + appClass, e);
}
+ }
if (true && Subtypes2.DEBUG) {
System.out.println(getSubtypes2().getGraph().getNumVertices() + " vertices in inheritance graph");
@@ -1005,11 +1042,11 @@ public class AnalysisContext {
}
public TypeQualifierNullnessAnnotationDatabase getNullnessAnnotationDatabase() {
- if (tqNullnessDatabase == null) {
- tqNullnessDatabase = new TypeQualifierNullnessAnnotationDatabase();
- }
- return tqNullnessDatabase;
-
+ if (tqNullnessDatabase == null) {
+ tqNullnessDatabase = new TypeQualifierNullnessAnnotationDatabase();
+ }
+ return tqNullnessDatabase;
+
}
protected <E> E getDatabase(Class<E> cls) {
@@ -1018,56 +1055,27 @@ public class AnalysisContext {
static class DelegatingRepositoryLookupFailureCallback implements RepositoryLookupFailureCallback {
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IErrorLogger#logError(java.lang.String)
- */
+ @Override
public void logError(String message) {
Global.getAnalysisCache().getErrorLogger().logError(message);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IErrorLogger#logError(java.lang.String,
- * java.lang.Throwable)
- */
+ @Override
public void logError(String message, Throwable e) {
Global.getAnalysisCache().getErrorLogger().logError(message, e);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IErrorLogger#reportMissingClass(java
- * .lang.ClassNotFoundException)
- */
+ @Override
public void reportMissingClass(ClassNotFoundException ex) {
Global.getAnalysisCache().getErrorLogger().reportMissingClass(ex);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IErrorLogger#reportMissingClass(edu
- * .umd.cs.findbugs.classfile.ClassDescriptor)
- */
+ @Override
public void reportMissingClass(ClassDescriptor classDescriptor) {
Global.getAnalysisCache().getErrorLogger().reportMissingClass(classDescriptor);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IErrorLogger#reportSkippedAnalysis(
- * edu.umd.cs.findbugs.classfile.MethodDescriptor)
- */
+ @Override
public void reportSkippedAnalysis(MethodDescriptor method) {
Global.getAnalysisCache().getErrorLogger().reportSkippedAnalysis(method);
}
@@ -1076,4 +1084,3 @@ public class AnalysisContext {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/AnalysisException.java b/src/java/edu/umd/cs/findbugs/ba/AnalysisException.java
index 01a1236..409b3b4 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AnalysisException.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AnalysisException.java
@@ -38,7 +38,7 @@ public class AnalysisException extends UncheckedAnalysisException {
/**
* Constructor.
- *
+ *
* @param message
* reason for the error
*/
@@ -49,7 +49,7 @@ public class AnalysisException extends UncheckedAnalysisException {
/**
* Constructor from another Throwable object. This is useful for chaining
* exceptions.
- *
+ *
* @param message
* reason for the error
* @param throwable
@@ -62,7 +62,7 @@ public class AnalysisException extends UncheckedAnalysisException {
/**
* Constructor from MethodGen and another Throwable object. This is useful
* for chaining exceptions.
- *
+ *
* @param message
* reason for the error
* @param methodGen
@@ -76,7 +76,7 @@ public class AnalysisException extends UncheckedAnalysisException {
/**
* Constructor from method and instruction.
- *
+ *
* @param message
* reason for the error
* @param methodGen
@@ -90,7 +90,7 @@ public class AnalysisException extends UncheckedAnalysisException {
/**
* Constructor from method and instruction.
- *
+ *
* @param message
* reason for the error
* @param methodGen
@@ -104,7 +104,7 @@ public class AnalysisException extends UncheckedAnalysisException {
/**
* Constructor from method, instruction, and causing Throwable object.
- *
+ *
* @param message
* reason for the error
* @param methodGen
@@ -120,7 +120,7 @@ public class AnalysisException extends UncheckedAnalysisException {
/**
* Constructor from method, instruction, and causing Throwable object.
- *
+ *
* @param message
* reason for the error
* @param methodGen
@@ -135,4 +135,3 @@ public class AnalysisException extends UncheckedAnalysisException {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/AnalysisFeatures.java b/src/java/edu/umd/cs/findbugs/ba/AnalysisFeatures.java
index 21723dc..e88abb2 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AnalysisFeatures.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AnalysisFeatures.java
@@ -122,4 +122,3 @@ public interface AnalysisFeatures {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/AnnotationDatabase.java b/src/java/edu/umd/cs/findbugs/ba/AnnotationDatabase.java
index ad44166..0f1eb4a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AnnotationDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AnnotationDatabase.java
@@ -34,7 +34,6 @@ import org.apache.bcel.classfile.Method;
import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
-import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.DescriptorFactory;
import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
@@ -56,7 +55,7 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
CLASS, ANY
}
- private static final String DEFAULT_ANNOTATION_ANNOTATION_CLASS = "DefaultAnnotation";
+ // private static final String DEFAULT_ANNOTATION_ANNOTATION_CLASS = "DefaultAnnotation";
private final Map<Object, AnnotationEnum> directAnnotations = new HashMap<Object, AnnotationEnum>();
@@ -86,10 +85,12 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
}
public void addDefaultAnnotation(Target target, String c, AnnotationEnum n) {
- if (!defaultAnnotation.containsKey(target))
+ if (!defaultAnnotation.containsKey(target)) {
return;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("Default annotation " + target + " " + c + " " + n);
+ }
defaultAnnotation.get(target).put(c, n);
seen.add(n);
}
@@ -122,17 +123,19 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
}
}
Map<Object, AnnotationEnum> cache;
- if (getMinimal)
+ if (getMinimal) {
cache = cachedMinimal;
- else
+ } else {
cache = cachedMaximal;
+ }
if (cache.containsKey(o)) {
return cache.get(o);
}
AnnotationEnum n = getUncachedResolvedAnnotation(o, getMinimal);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("TTT: " + o + " " + n);
+ }
cache.put(o, n);
return n;
}
@@ -145,8 +148,9 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
public AnnotationEnum getUncachedResolvedAnnotation(final Object o, boolean getMinimal) {
AnnotationEnum n = getDirectAnnotation(o);
- if (n != null)
+ if (n != null) {
return n;
+ }
try {
@@ -168,36 +172,43 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
isSyntheticMethod = m.isSynthetic();
className = m.getClassName();
kind = Target.PARAMETER;
- if (m.getName().equals("<init>")) {
- int i = className.lastIndexOf("$");
- if (i + 1 < className.length() && Character.isDigit(className.charAt(i + 1)))
+ if ("<init>".equals(m.getName())) {
+ int i = className.lastIndexOf('$');
+ if (i + 1 < className.length() && Character.isDigit(className.charAt(i + 1))) {
isParameterToInitMethodofAnonymousInnerClass = true;
+ }
}
- } else
+ } else {
throw new IllegalStateException("impossible");
+ }
- if (!m.isStatic() && !m.getName().equals("<init>")) {
+ if (!m.isStatic() && !"<init>".equals(m.getName())) {
JavaClass c = Repository.lookupClass(className);
// get inherited annotation
TreeSet<AnnotationEnum> inheritedAnnotations = new TreeSet<AnnotationEnum>();
if (c.getSuperclassNameIndex() > 0) {
n = lookInOverriddenMethod(o, c.getSuperclassName(), m, getMinimal);
- if (n != null)
+ if (n != null) {
inheritedAnnotations.add(n);
+ }
}
for (String implementedInterface : c.getInterfaceNames()) {
n = lookInOverriddenMethod(o, implementedInterface, m, getMinimal);
- if (n != null)
+ if (n != null) {
inheritedAnnotations.add(n);
+ }
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("# of inherited annotations : " + inheritedAnnotations.size());
+ }
if (!inheritedAnnotations.isEmpty()) {
- if (inheritedAnnotations.size() == 1)
+ if (inheritedAnnotations.size() == 1) {
return inheritedAnnotations.first();
- if (!getMinimal)
+ }
+ if (!getMinimal) {
return inheritedAnnotations.last();
+ }
AnnotationEnum min = inheritedAnnotations.first();
if (min.getIndex() == 0) {
@@ -208,10 +219,12 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
}
// check to see if method is defined in this class;
// if not, on't consider default annotations
- if (!classDefinesMethod(c, m))
+ if (!classDefinesMethod(c, m)) {
return null;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("looking for default annotations: " + c.getClassName() + " defines " + m);
+ }
} // if not static
} // associated with method
else if (o instanceof XField) {
@@ -222,54 +235,66 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
assert false;
className = (String) o;
kind = Target.CLASS;
- } else
+ } else {
throw new IllegalArgumentException("Can't look up annotation for " + o.getClass().getName());
+ }
// <init> method parameters for inner classes don't inherit default
// annotations
// since some of them are synthetic
- if (isParameterToInitMethodofAnonymousInnerClass)
+ if (isParameterToInitMethodofAnonymousInnerClass) {
return null;
+ }
// synthetic elements should not inherit default annotations
- if (isSyntheticMethod)
+ if (isSyntheticMethod) {
return null;
+ }
try {
XClass c = Global.getAnalysisCache().getClassAnalysis(XClass.class,
DescriptorFactory.createClassDescriptorFromDottedClassName(className));
- if (c != null && c.isSynthetic())
+ if (c != null && c.isSynthetic()) {
return null;
+ }
} catch (CheckedAnalysisException e) {
assert true;
}
// look for default annotation
n = defaultAnnotation.get(kind).get(className);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Default annotation for " + kind + " is " + n);
- if (n != null)
+ }
+ if (n != null) {
return n;
+ }
n = defaultAnnotation.get(Target.ANY).get(className);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Default annotation for any is " + n);
- if (n != null)
+ }
+ if (n != null) {
return n;
+ }
int p = className.lastIndexOf('.');
className = className.substring(0, p + 1) + "package-info";
n = defaultAnnotation.get(kind).get(className);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Default annotation for " + kind + " is " + n);
- if (n != null)
+ }
+ if (n != null) {
return n;
+ }
n = defaultAnnotation.get(Target.ANY).get(className);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Default annotation for any is " + n);
- if (n != null)
+ }
+ if (n != null) {
return n;
+ }
return n;
} catch (ClassNotFoundException e) {
@@ -279,19 +304,17 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
}
- /**
- * @param o
- * @return
- */
public AnnotationEnum getDirectAnnotation(final Object o) {
return directAnnotations.get(o);
}
private boolean classDefinesMethod(JavaClass c, XMethod m) {
- for (Method definedMethod : c.getMethods())
+ for (Method definedMethod : c.getMethods()) {
if (definedMethod.getName().equals(m.getName()) && definedMethod.getSignature().equals(m.getSignature())
- && definedMethod.isStatic() == m.isStatic())
+ && definedMethod.isStatic() == m.isStatic()) {
return true;
+ }
+ }
return false;
}
@@ -302,18 +325,21 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
// Look in supermethod
XMethod superMethod = XFactory.createXMethod(classToLookIn, originalMethod.getName(), originalMethod.getSignature(),
originalMethod.isStatic());
- if (!superMethod.isResolved())
+ if (!superMethod.isResolved()) {
return null;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("Looking for overridden method " + superMethod);
+ }
Object probe;
- if (originalQuery instanceof XMethod)
+ if (originalQuery instanceof XMethod) {
probe = superMethod;
- else if (originalQuery instanceof XMethodParameter)
+ } else if (originalQuery instanceof XMethodParameter) {
probe = new XMethodParameter(superMethod, ((XMethodParameter) originalQuery).getParameterNumber());
- else
+ } else {
throw new IllegalStateException("impossible");
+ }
n = getResolvedAnnotation(probe, getMinimal);
return n;
@@ -335,35 +361,36 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
// if (!Subtypes.DO_NOT_USE) {
// subtypes.addNamedClass(cName);
// }
-
- if (addClassOnly)
+ if (addClassOnly) {
return;
-
+ }
addDefaultAnnotation(AnnotationDatabase.Target.METHOD, cName, annotation);
-
}
protected void addFieldAnnotation(String cName, String mName, String mSig, boolean isStatic, AnnotationEnum annotation) {
// if (!Subtypes.DO_NOT_USE) {
// subtypes.addNamedClass(cName);
// }
- if (addClassOnly)
+ if (addClassOnly) {
return;
+ }
XField m = XFactory.createXField(cName, mName, mSig, isStatic);
addDirectAnnotation(m, annotation);
}
- protected void addMethodAnnotation(Class<?> clazz, String mName, String mSig, boolean isStatic,
- AnnotationEnum annotation) {
+ protected void addMethodAnnotation(Class<?> clazz, String mName, String mSig, boolean isStatic, AnnotationEnum annotation) {
addMethodAnnotation(clazz.getName(), mName, mSig, isStatic, annotation);
}
- protected void addMethodAnnotation(@DottedClassName String cName, String mName, String mSig, boolean isStatic,
- AnnotationEnum annotation) {
- if (addClassOnly)
+
+ protected void addMethodAnnotation(@DottedClassName String cName, String mName, String mSig, boolean isStatic, AnnotationEnum annotation) {
+ if (addClassOnly) {
return;
+ }
XMethod m = XFactory.createXMethod(cName, mName, mSig, isStatic);
- if (!m.getClassName().equals(cName))
+ if (!m.getClassName().equals(cName)){
return;
+ }
+ /*
if (false && !m.isResolved()) {
System.out.println("Unable to add annotation " + annotation + " to " + m);
ClassDescriptor c = DescriptorFactory.createClassDescriptorFromDottedClassName(cName);
@@ -379,7 +406,7 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
e.printStackTrace();
}
}
-
+ */
addDirectAnnotation(m, annotation);
}
@@ -393,11 +420,13 @@ public class AnnotationDatabase<AnnotationEnum extends AnnotationEnumeration<Ann
// if (!Subtypes.DO_NOT_USE) {
// subtypes.addNamedClass(cName);
// }
- if (addClassOnly)
+ if (addClassOnly) {
return;
+ }
SignatureParser parser = new SignatureParser(mSig);
- if (param < 0 || param >= parser.getNumParameters())
+ if (param < 0 || param >= parser.getNumParameters()) {
throw new IllegalArgumentException("can't annotation parameter #" + param + " of " + cName + "." + mName + mSig);
+ }
String signature = parser.getParameter(param);
char firstChar = signature.charAt(0);
boolean isReference = firstChar == 'L' || firstChar == '[';
diff --git a/src/java/edu/umd/cs/findbugs/ba/AnnotationEnumeration.java b/src/java/edu/umd/cs/findbugs/ba/AnnotationEnumeration.java
index a3b2001..410fed3 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AnnotationEnumeration.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AnnotationEnumeration.java
@@ -34,8 +34,9 @@ public class AnnotationEnumeration<E extends AnnotationEnumeration<E>> implement
@Override
public final boolean equals(Object o) {
- if (!(o instanceof AnnotationEnumeration<?>))
+ if (!(o instanceof AnnotationEnumeration<?>)) {
return false;
+ }
return index == ((AnnotationEnumeration<?>) o).getIndex();
}
@@ -58,9 +59,10 @@ public class AnnotationEnumeration<E extends AnnotationEnumeration<E>> implement
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Comparable#compareTo(T)
*/
+ @Override
public int compareTo(E a) {
return index - a.getIndex();
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/AnnotationRetentionDatabase.java b/src/java/edu/umd/cs/findbugs/ba/AnnotationRetentionDatabase.java
index e6f9b0a..1dc1523 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AnnotationRetentionDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AnnotationRetentionDatabase.java
@@ -22,20 +22,22 @@ package edu.umd.cs.findbugs.ba;
import java.util.HashMap;
public class AnnotationRetentionDatabase {
- private HashMap<String, Boolean> annotationRetention = new HashMap<String, Boolean>();
+ private final HashMap<String, Boolean> annotationRetention = new HashMap<String, Boolean>();
public boolean hasRuntimeRetention(String dottedClassName) {
Boolean result = annotationRetention.get(dottedClassName);
- if (result == null)
+ if (result == null) {
return false;
+ }
return result;
}
/** return false if it has class retention *or* if the retention is unknown */
public boolean lacksRuntimeRetention(String dottedClassName) {
Boolean result = annotationRetention.get(dottedClassName);
- if (result == null)
+ if (result == null) {
return false;
+ }
return !result;
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/AssertionMethods.java b/src/java/edu/umd/cs/findbugs/ba/AssertionMethods.java
index d2ff158..036b7a3 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AssertionMethods.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AssertionMethods.java
@@ -87,8 +87,9 @@ public class AssertionMethods implements Constants {
while (tok.hasMoreTokens()) {
String fullyQualifiedName = tok.nextToken();
int lastDot = fullyQualifiedName.lastIndexOf('.');
- if (lastDot < 0)
+ if (lastDot < 0) {
continue;
+ }
String className = fullyQualifiedName.substring(0, lastDot);
String methodName = fullyQualifiedName.substring(lastDot + 1);
userAssertionMethodList.add(new UserAssertionMethod(className, methodName));
@@ -138,15 +139,15 @@ public class AssertionMethods implements Constants {
&& methodName.startsWith("is")
|| (voidReturnType || boolReturnType)
&& (classNameLC.indexOf("assert") >= 0 || methodNameLC.startsWith("throw")
- || methodName.startsWith("affirm") || methodName.startsWith("panic")
- || methodName.equals("logTerminal") || methodName.startsWith("logAndThrow")
- || methodNameLC.equals("insist") || methodNameLC.equals("usage")
- || methodNameLC.equals("exit") || methodNameLC.startsWith("fail")
- || methodNameLC.startsWith("fatal") || methodNameLC.indexOf("assert") >= 0
- || methodNameLC.indexOf("legal") >= 0 || methodNameLC.indexOf("error") >= 0
- || methodNameLC.indexOf("abort") >= 0
- // || methodNameLC.indexOf("check") >= 0
- || methodNameLC.indexOf("failed") >= 0) || methodName.equals("addOrThrowException")) {
+ || methodName.startsWith("affirm") || methodName.startsWith("panic")
+ || "logTerminal".equals(methodName) || methodName.startsWith("logAndThrow")
+ || "insist".equals(methodNameLC) || "usage".equals(methodNameLC)
+ || "exit".equals(methodNameLC) || methodNameLC.startsWith("fail")
+ || methodNameLC.startsWith("fatal") || methodNameLC.indexOf("assert") >= 0
+ || methodNameLC.indexOf("legal") >= 0 || methodNameLC.indexOf("error") >= 0
+ || methodNameLC.indexOf("abort") >= 0
+ // || methodNameLC.indexOf("check") >= 0
+ || methodNameLC.indexOf("failed") >= 0) || "addOrThrowException".equals(methodName)) {
assertionMethodRefSet.set(i);
if (DEBUG) {
System.out.println("==> YES");
@@ -165,16 +166,18 @@ public class AssertionMethods implements Constants {
private static boolean isUserAssertionMethod(String className, String methodName) {
for (UserAssertionMethod uam : userAssertionMethodList) {
- if (className.equals(uam.getClassName()) && methodName.equals(uam.getMethodName()))
+ if (className.equals(uam.getClassName()) && methodName.equals(uam.getMethodName())) {
return true;
+ }
}
return false;
}
public boolean isAssertionHandle(InstructionHandle handle, ConstantPoolGen cpg) {
Instruction ins = handle.getInstruction();
- if (isAssertionInstruction(ins, cpg))
+ if (isAssertionInstruction(ins, cpg)) {
return true;
+ }
if (ins instanceof SIPUSH) {
int v = ((SIPUSH) ins).getValue().intValue();
@@ -184,8 +187,9 @@ public class AssertionMethods implements Constants {
INVOKEINTERFACE iInterface = (INVOKEINTERFACE) next;
String className = iInterface.getClassName(cpg);
String fieldName = iInterface.getMethodName(cpg);
- if (className.equals("javax.servlet.http.HttpServletResponse") && fieldName.equals("setStatus"))
+ if ("javax.servlet.http.HttpServletResponse".equals(className) && "setStatus".equals(fieldName)) {
return true;
+ }
}
}
@@ -204,16 +208,19 @@ public class AssertionMethods implements Constants {
public boolean isAssertionInstruction(Instruction ins, ConstantPoolGen cpg) {
- if (ins instanceof InvokeInstruction)
+ if (ins instanceof InvokeInstruction) {
return isAssertionCall((InvokeInstruction) ins);
+ }
if (ins instanceof GETSTATIC) {
GETSTATIC getStatic = (GETSTATIC) ins;
String className = getStatic.getClassName(cpg);
String fieldName = getStatic.getFieldName(cpg);
- if (className.equals("java.util.logging.Level") && fieldName.equals("SEVERE"))
+ if ("java.util.logging.Level".equals(className) && "SEVERE".equals(fieldName)) {
return true;
- if (className.equals("org.apache.log4j.Level") && (fieldName.equals("ERROR") || fieldName.equals("FATAL")))
+ }
+ if ("org.apache.log4j.Level".equals(className) && ("ERROR".equals(fieldName) || "FATAL".equals(fieldName))) {
return true;
+ }
return false;
}
@@ -228,4 +235,3 @@ public class AssertionMethods implements Constants {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/AssignedFieldMap.java b/src/java/edu/umd/cs/findbugs/ba/AssignedFieldMap.java
index fdbab88..4916cb7 100644
--- a/src/java/edu/umd/cs/findbugs/ba/AssignedFieldMap.java
+++ b/src/java/edu/umd/cs/findbugs/ba/AssignedFieldMap.java
@@ -25,11 +25,11 @@ public class AssignedFieldMap implements Constants {
/*
* private final Map<Method, Set<XField>> assignedFieldSetForMethodMap;
* private final JavaClass myClass;
- *
+ *
* public AssignedFieldMap(JavaClass jclass) {
* this.assignedFieldSetForMethodMap = new IdentityHashMap<Method,
* Set<XField>>(); this.myClass = jclass; }
- *
+ *
* public void build() throws ClassNotFoundException { // Build a set of all
* fields that could be assigned // by methods in this class Set<XField>
* assignableFieldSet = new HashSet<XField>(); scanFields(myClass,
@@ -37,62 +37,61 @@ public class AssignedFieldMap implements Constants {
* myClass.getSuperClasses(); if (superClassList != null) { for (JavaClass
* aSuperClassList : superClassList) { scanFields(aSuperClassList,
* assignableFieldSet); } }
- *
+ *
* Method[] methodList = myClass.getMethods(); for (Method method :
* methodList) {
- *
+ *
* scanMethod(method, assignableFieldSet); } }
- *
+ *
* public Set<XField> getAssignedFieldSetForMethod(Method method) {
* Set<XField> set = assignedFieldSetForMethodMap.get(method); if (set ==
* null) { set = new HashSet<XField>();
* assignedFieldSetForMethodMap.put(method, set); } return set; }
- *
+ *
* private void scanFields(JavaClass jclass, Set<XField> assignableFieldSet)
* { // JavaClass myClass = classContext.getJavaClass(); String myClassName
* = myClass.getClassName(); String myPackageName =
* myClass.getPackageName();
- *
+ *
* String superClassName = jclass.getClassName(); String superPackageName =
* jclass.getPackageName();
- *
+ *
* Field[] fieldList = jclass.getFields(); for (Field field : fieldList) {
* if (field.isStatic()) continue; boolean assignable; if (field.isPublic()
* || field.isProtected()) assignable = true; else if (field.isPrivate())
* assignable = myClassName.equals(superClassName); else // package
* protected assignable = myPackageName.equals(superPackageName);
- *
+ *
* if (assignable) { assignableFieldSet.add(new
* InstanceField(superClassName, field.getName(), field.getSignature(),
* field.getAccessFlags())); } } }
- *
+ *
* private void scanMethod(Method method, Set<XField> assignableFieldSet)
* throws ClassNotFoundException { //MethodGen methodGen =
* classContext.getMethodGen(method);
- *
+ *
* MethodGen methodGen; try { methodGen=
* Global.getAnalysisCache().getMethodAnalysis(MethodGen.class,
* BCELUtil.getMethodDescriptor(myClass, method)); } catch
* (CheckedAnalysisException e) { // Should not happen throw new
* AnalysisException("Could not get MethodGen for Method", e); }
- *
+ *
* if (methodGen == null) return; InstructionList il =
* methodGen.getInstructionList(); InstructionHandle handle = il.getStart();
- *
+ *
* ConstantPoolGen cpg = methodGen.getConstantPool();
- *
+ *
* while (handle != null) { Instruction ins = handle.getInstruction(); short
* opcode = ins.getOpcode(); if (opcode == Constants.PUTFIELD) { PUTFIELD
* putfield = (PUTFIELD) ins;
- *
+ *
* XField instanceField = Hierarchy.findXField(putfield, cpg); if
* (instanceField != null && assignableFieldSet.contains(instanceField)) {
* Set<XField> assignedFieldSetForMethod =
* getAssignedFieldSetForMethod(method);
* assignedFieldSetForMethod.add(instanceField); } }
- *
+ *
* handle = handle.getNext(); } }
*/
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/BackwardDataflowAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/BackwardDataflowAnalysis.java
index d1ca636..2af1204 100644
--- a/src/java/edu/umd/cs/findbugs/ba/BackwardDataflowAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/BackwardDataflowAnalysis.java
@@ -22,19 +22,20 @@ package edu.umd.cs.findbugs.ba;
/**
* Abstract base class for backward dataflow analyses. Provides convenient
* implementations for isForwards() and getBlockOrder() methods.
- *
+ *
* @author David Hovemeyer
* @see Dataflow
* @see DataflowAnalysis
*/
public abstract class BackwardDataflowAnalysis<Fact> extends AbstractDataflowAnalysis<Fact> {
- private ReverseDepthFirstSearch rdfs;
+ private final ReverseDepthFirstSearch rdfs;
- private DepthFirstSearch dfs;
+ private final DepthFirstSearch dfs;
public BackwardDataflowAnalysis(ReverseDepthFirstSearch rdfs, DepthFirstSearch dfs) {
- if (rdfs == null || dfs == null)
+ if (rdfs == null || dfs == null) {
throw new IllegalArgumentException();
+ }
this.rdfs = rdfs;
this.dfs = dfs;
}
@@ -43,13 +44,14 @@ public abstract class BackwardDataflowAnalysis<Fact> extends AbstractDataflowAna
return rdfs;
}
+ @Override
public boolean isForwards() {
return false;
}
+ @Override
public BlockOrder getBlockOrder(CFG cfg) {
return new ReverseDFSOrder(cfg, rdfs, dfs);
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/BasicAbstractDataflowAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/BasicAbstractDataflowAnalysis.java
index 8ebae4a..2bcebd4 100644
--- a/src/java/edu/umd/cs/findbugs/ba/BasicAbstractDataflowAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/BasicAbstractDataflowAnalysis.java
@@ -38,9 +38,9 @@ import edu.umd.cs.findbugs.ba.deref.UnconditionalValueDerefSet;
* @author David Hovemeyer
*/
public abstract class BasicAbstractDataflowAnalysis<Fact> implements DataflowAnalysis<Fact> {
- private IdentityHashMap<BasicBlock, Fact> startFactMap;
+ private final IdentityHashMap<BasicBlock, Fact> startFactMap;
- private IdentityHashMap<BasicBlock, Fact> resultFactMap;
+ private final IdentityHashMap<BasicBlock, Fact> resultFactMap;
/**
* Constructor.
@@ -60,14 +60,17 @@ public abstract class BasicAbstractDataflowAnalysis<Fact> implements DataflowAna
/*
* Default implementation - subclasses may override.
*/
+ @Override
public String factToString(Fact fact) {
return fact.toString();
}
+ @Override
public/* final */Fact getStartFact(BasicBlock block) {
return lookupOrCreateFact(startFactMap, block);
}
+ @Override
public/* final */Fact getResultFact(BasicBlock block) {
return lookupOrCreateFact(resultFactMap, block);
}
@@ -87,6 +90,7 @@ public abstract class BasicAbstractDataflowAnalysis<Fact> implements DataflowAna
* @return the dataflow value at given Location
* @throws DataflowAnalysisException
*/
+ @Override
public Fact getFactAtLocation(Location location) throws DataflowAnalysisException {
return getStartFact(location.getBasicBlock());
}
@@ -106,6 +110,7 @@ public abstract class BasicAbstractDataflowAnalysis<Fact> implements DataflowAna
* @return the dataflow value after given Location
* @throws DataflowAnalysisException
*/
+ @Override
public Fact getFactAfterLocation(Location location) throws DataflowAnalysisException {
return getResultFact(location.getBasicBlock());
}
@@ -119,6 +124,7 @@ public abstract class BasicAbstractDataflowAnalysis<Fact> implements DataflowAna
* @return the fact that is true after applying the edge transfer function
* @throws DataflowAnalysisException
*/
+ @Override
public/* final */Fact getFactOnEdge(Edge edge) throws DataflowAnalysisException {
BasicBlock block = isForwards() ? edge.getSource() : edge.getTarget();
@@ -129,11 +135,12 @@ public abstract class BasicAbstractDataflowAnalysis<Fact> implements DataflowAna
Fact result = createFact();
makeFactTop(result);
- if (this instanceof UnconditionalValueDerefAnalysis)
+ if (this instanceof UnconditionalValueDerefAnalysis) {
((UnconditionalValueDerefAnalysis)this).meetInto((UnconditionalValueDerefSet)predFact,
edge, (UnconditionalValueDerefSet)result, true);
- else
+ } else {
meetInto(predFact, edge, result);
+ }
return result;
@@ -144,6 +151,7 @@ public abstract class BasicAbstractDataflowAnalysis<Fact> implements DataflowAna
*
* @see edu.umd.cs.findbugs.ba.DataflowAnalysis#startIteration()
*/
+ @Override
public void startIteration() {
// Do nothing - subclass may override
}
@@ -153,6 +161,7 @@ public abstract class BasicAbstractDataflowAnalysis<Fact> implements DataflowAna
*
* @see edu.umd.cs.findbugs.ba.DataflowAnalysis#finishIteration()
*/
+ @Override
public void finishIteration() {
// Do nothing - subclass may override
}
@@ -164,6 +173,7 @@ public abstract class BasicAbstractDataflowAnalysis<Fact> implements DataflowAna
* edu.umd.cs.findbugs.ba.DataflowAnalysis#edgeTransfer(edu.umd.cs.findbugs
* .ba.Edge, java.lang.Object)
*/
+ @Override
public void edgeTransfer(Edge edge, Fact fact) throws DataflowAnalysisException {
// By default, edge transfer function is identity.
// Subclasses may override.
@@ -178,10 +188,12 @@ public abstract class BasicAbstractDataflowAnalysis<Fact> implements DataflowAna
return fact;
}
+ @Override
public int getLastUpdateTimestamp(Fact fact) {
return 0;
}
+ @Override
public void setLastUpdateTimestamp(Fact fact, int lastUpdateTimestamp) {
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/BasicBlock.java b/src/java/edu/umd/cs/findbugs/ba/BasicBlock.java
index 0b72a61..8362b82 100644
--- a/src/java/edu/umd/cs/findbugs/ba/BasicBlock.java
+++ b/src/java/edu/umd/cs/findbugs/ba/BasicBlock.java
@@ -24,6 +24,7 @@ import java.util.Iterator;
import java.util.NoSuchElementException;
import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.CodeExceptionGen;
@@ -34,7 +35,7 @@ import edu.umd.cs.findbugs.graph.AbstractVertex;
/**
* Simple basic block abstraction for BCEL.
- *
+ *
* @author David Hovemeyer
* @see CFG
*/
@@ -77,7 +78,7 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
nullCheckInstructionSet.set(Constants.ARRAYLENGTH);
// nullCheckInstructionSet.set(Constants.MONITOREXIT);
nullCheckInstructionSet.set(Constants.ATHROW);
-
+
// Any others?
}
@@ -92,10 +93,10 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
private InstructionHandle lastInstruction;
private InstructionHandle exceptionThrower; // instruction for which this
- // block is the ETB
+ // block is the ETB
private CodeExceptionGen exceptionGen; // set if this block is the entry
- // point of an exception handler
+ // point of an exception handler
private boolean inJSRSubroutine;
@@ -129,7 +130,7 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
/**
* Get the basic block's integer label.
- *
+ *
* @deprecated call getLabel() instead
* @return the BasicBlock's integer label
*/
@@ -145,7 +146,7 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
/**
* Set the instruction for which this block is the ETB.
- *
+ *
* @param exceptionThrower
* the instruction
*/
@@ -162,7 +163,7 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
/**
* Get the instruction for which this block is an exception thrower.
- *
+ *
* @return the instruction, or null if this block is not an exception
* thrower
*/
@@ -177,8 +178,9 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
// Null check blocks must be exception throwers,
// and are always empty. (The only kind of non-empty
// exception throwing block is one terminated by an ATHROW).
- if (!isExceptionThrower() || getFirstInstruction() != null)
+ if (!isExceptionThrower() || getFirstInstruction() != null) {
return false;
+ }
short opcode = exceptionThrower.getInstruction().getOpcode();
return nullCheckInstructionSet.get(opcode);
}
@@ -199,7 +201,7 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
/**
* Get the successor of given instruction within the basic block.
- *
+ *
* @param handle
* the instruction
* @return the instruction's successor, or null if the instruction is the
@@ -208,15 +210,16 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
public @CheckForNull
InstructionHandle getSuccessorOf(InstructionHandle handle) {
if (VERIFY_INTEGRITY) {
- if (!containsInstruction(handle))
+ if (!containsInstruction(handle)) {
throw new IllegalStateException();
+ }
}
return handle == lastInstruction ? null : handle.getNext();
}
/**
* Get the predecessor of given instruction within the basic block.
- *
+ *
* @param handle
* the instruction
* @return the instruction's predecessor, or null if the instruction is the
@@ -224,15 +227,16 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
*/
public InstructionHandle getPredecessorOf(InstructionHandle handle) {
if (VERIFY_INTEGRITY) {
- if (!containsInstruction(handle))
+ if (!containsInstruction(handle)) {
throw new IllegalStateException();
+ }
}
return handle == firstInstruction ? null : handle.getPrev();
}
/**
* Add an InstructionHandle to the basic block.
- *
+ *
* @param handle
* the InstructionHandle
*/
@@ -240,8 +244,9 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
if (firstInstruction == null) {
firstInstruction = lastInstruction = handle;
} else {
- if (VERIFY_INTEGRITY && handle != lastInstruction.getNext())
+ if (VERIFY_INTEGRITY && handle != lastInstruction.getNext()) {
throw new IllegalStateException("Adding non-consecutive instruction");
+ }
lastInstruction = handle;
}
}
@@ -253,25 +258,30 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
* versa.
*/
public class InstructionIterator implements Iterator<InstructionHandle> {
- private InstructionHandle next, last;
+ private InstructionHandle next;
+ private final InstructionHandle last;
public InstructionIterator(InstructionHandle first, InstructionHandle last) {
this.next = first;
this.last = last;
}
+ @Override
public boolean hasNext() {
return next != null;
}
+ @Override
public InstructionHandle next() {
- if (!hasNext())
+ if (!hasNext()) {
throw new NoSuchElementException();
+ }
InstructionHandle result = next;
next = (result == last) ? null : next.getNext();
return result;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -282,8 +292,9 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
@Override
public boolean equals(Object o) {
- if (!(o instanceof InstructionIterator))
+ if (!(o instanceof InstructionIterator)) {
return false;
+ }
InstructionIterator other = (InstructionIterator) o;
return this.next == other.next && this.last == other.last;
}
@@ -291,8 +302,9 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
@Override
public int hashCode() {
int code = getBasicBlock().hashCode() * 227;
- if (next != null)
+ if (next != null) {
code += next.getPosition() + 1;
+ }
return code;
}
@@ -328,25 +340,30 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
* A reverse Iterator over the instructions in a basic block.
*/
private static class InstructionReverseIterator implements Iterator<InstructionHandle> {
- private InstructionHandle next, first;
+ private InstructionHandle next;
+ private final InstructionHandle first;
public InstructionReverseIterator(InstructionHandle last, InstructionHandle first) {
this.next = last;
this.first = first;
}
+ @Override
public boolean hasNext() {
return next != null;
}
+ @Override
public InstructionHandle next() throws NoSuchElementException {
- if (!hasNext())
+ if (!hasNext()) {
throw new NoSuchElementException();
+ }
InstructionHandle result = next;
next = (result == first) ? null : next.getPrev();
return result;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -369,8 +386,9 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
public int pos() {
- if (isEmpty())
+ if (isEmpty()) {
return getExceptionThrower().getPosition();
+ }
return firstInstruction.getPosition();
}
@@ -384,7 +402,7 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
/**
* Get CodeExceptionGen object; returns null if this basic block is not the
* entry point of an exception handler.
- *
+ *
* @return the CodeExceptionGen object, or null
*/
public CodeExceptionGen getExceptionGen() {
@@ -394,21 +412,21 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
/**
* Set the CodeExceptionGen object. Marks this basic block as the entry
* point of an exception handler.
- *
+ *
* @param exceptionGen
* the CodeExceptionGen object for the block
*/
- public void setExceptionGen(TypeMerger m, CodeExceptionGen exceptionGen) {
+ public void setExceptionGen(@Nullable TypeMerger m, CodeExceptionGen exceptionGen) {
if (this.exceptionGen != null) {
AnalysisContext.logError("Multiple exception handlers");
}
-
- this.exceptionGen = exceptionGen;
+
+ this.exceptionGen = exceptionGen;
}
- /**
+ /**
* Return whether or not the basic block contains the given instruction.
- *
+ *
* @param handle
* the instruction
* @return true if the block contains the instruction, false otherwise
@@ -416,8 +434,9 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
public boolean containsInstruction(InstructionHandle handle) {
Iterator<InstructionHandle> i = instructionIterator();
while (i.hasNext()) {
- if (i.next() == handle)
+ if (i.next() == handle) {
return true;
+ }
}
return false;
}
@@ -425,7 +444,7 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
/**
* Return whether or not the basic block contains the instruction with the
* given bytecode offset.
- *
+ *
* @param offset
* the bytecode offset
* @return true if the block contains an instruction with the given offset,
@@ -434,8 +453,9 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
public boolean containsInstructionWithOffset(int offset) {
Iterator<InstructionHandle> i = instructionIterator();
while (i.hasNext()) {
- if (i.next().getPosition() == offset)
+ if (i.next().getPosition() == offset) {
return true;
+ }
}
return false;
}
@@ -456,4 +476,3 @@ public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debu
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/BetterCFGBuilder2.java b/src/java/edu/umd/cs/findbugs/ba/BetterCFGBuilder2.java
index 083775f..8ec8e6d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/BetterCFGBuilder2.java
+++ b/src/java/edu/umd/cs/findbugs/ba/BetterCFGBuilder2.java
@@ -45,6 +45,7 @@ import org.apache.bcel.generic.ExceptionThrower;
import org.apache.bcel.generic.GETFIELD;
import org.apache.bcel.generic.GETSTATIC;
import org.apache.bcel.generic.GOTO;
+import org.apache.bcel.generic.GotoInstruction;
import org.apache.bcel.generic.ICONST;
import org.apache.bcel.generic.IFNONNULL;
import org.apache.bcel.generic.IFNULL;
@@ -187,7 +188,7 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
private final BitSet instructionSet;
- private final CFG cfg;
+ private final CFG cfgSub;
private final IdentityHashMap<InstructionHandle, BasicBlock> blockMap;
@@ -210,7 +211,7 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
public Subroutine(InstructionHandle start) {
this.start = start;
this.instructionSet = new BitSet();
- this.cfg = new CFG();
+ this.cfgSub = new CFG();
this.blockMap = new IdentityHashMap<InstructionHandle, BasicBlock>();
this.escapeTargetListMap = new IdentityHashMap<BasicBlock, List<EscapeTarget>>();
this.returnBlockSet = new BitSet();
@@ -230,7 +231,7 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
* Allocate a new basic block in the subroutine.
*/
public BasicBlock allocateBasicBlock() {
- return cfg.allocate();
+ return cfgSub.allocate();
}
/**
@@ -258,14 +259,14 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
* Get the entry block for the subroutine's CFG.
*/
public BasicBlock getEntry() {
- return cfg.getEntry();
+ return cfgSub.getEntry();
}
/**
* Get the exit block for the subroutine's CFG.
*/
public BasicBlock getExit() {
- return cfg.getExit();
+ return cfgSub.getExit();
}
/**
@@ -280,7 +281,7 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
* Get the subroutine's CFG.
*/
public CFG getCFG() {
- return cfg;
+ return cfgSub;
}
/**
@@ -293,8 +294,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
*/
public void addInstruction(InstructionHandle handle) throws CFGBuilderException {
int position = handle.getPosition();
- if (usedInstructionSet.get(position))
+ if (usedInstructionSet.get(position)) {
throw new CFGBuilderException("Instruction " + handle + " visited in multiple subroutines");
+ }
instructionSet.set(position);
usedInstructionSet.set(position);
}
@@ -324,8 +326,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
// Block is an exception handler?
CodeExceptionGen exceptionGen = exceptionHandlerMap.getHandlerForStartInstruction(start);
- if (exceptionGen != null)
+ if (exceptionGen != null) {
block.setExceptionGen(null, exceptionGen);
+ }
addItem(new WorkListItem(start, block));
}
@@ -425,12 +428,13 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
*/
public void addEdge(BasicBlock sourceBlock, BasicBlock destBlock, @Edge.Type int edgeType) {
if (VERIFY_INTEGRITY) {
- if (destBlock.isExceptionHandler() && edgeType != HANDLED_EXCEPTION_EDGE)
+ if (destBlock.isExceptionHandler() && edgeType != HANDLED_EXCEPTION_EDGE) {
throw new IllegalStateException("In method " + SignatureConverter.convertMethodSignature(methodGen)
+ ": exception handler " + destBlock.getFirstInstruction() + " reachable by non exception edge type "
+ edgeType);
+ }
}
- cfg.createEdge(sourceBlock, destBlock, edgeType);
+ cfgSub.createEdge(sourceBlock, destBlock, edgeType);
}
/**
@@ -442,8 +446,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
*/
public Iterator<EscapeTarget> escapeTargetIterator(BasicBlock sourceBlock) {
List<EscapeTarget> escapeTargetList = escapeTargetListMap.get(sourceBlock);
- if (escapeTargetList == null)
+ if (escapeTargetList == null) {
escapeTargetList = Collections.emptyList();
+ }
return escapeTargetList.iterator();
}
}
@@ -505,10 +510,10 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
/**
* Add a basic block to the inlining work list.
- */
+ *
public void addItem(BasicBlock item) {
workList.add(item);
- }
+ }*/
/**
* Are there more work list items?
@@ -562,8 +567,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
Context callerContext = caller;
while (callerContext != null) {
- if (callerContext.subroutine == this.subroutine)
+ if (callerContext.subroutine == this.subroutine) {
throw new CFGBuilderException("JSR recursion detected!");
+ }
callerContext = callerContext.caller;
}
}
@@ -617,8 +623,8 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("Unable to generate exceptionSetFactory for " + descriptor, e);
}
-
-
+
+
this.exceptionHandlerMap = new ExceptionHandlerMap(methodGen, merger);
this.usedInstructionSet = new BitSet();
this.jsrSubroutineMap = new IdentityHashMap<InstructionHandle, Subroutine>();
@@ -627,8 +633,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
public int getIndex(FieldDescriptor f) {
Integer i = addedFields.get(f);
- if (i != null)
+ if (i != null) {
return i;
+ }
int index = cpg.addFieldref(f.getSlashedClassName(), f.getName(), f.getSignature());
addedFields.put(f, index);
return index;
@@ -650,24 +657,28 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
FieldDescriptor field = invoked.getAccessMethodForField();
if (field != null) {
boolean isSetter = signature.endsWith("V");
- Instruction replacement;
- int index = getIndex(field);
- if (field.isStatic()) {
- if (isSetter)
- replacement = new PUTSTATIC(index);
- else
- replacement = new GETSTATIC(index);
+ Instruction replacement;
+ int index = getIndex(field);
+ if (field.isStatic()) {
+ if (isSetter) {
+ replacement = new PUTSTATIC(index);
+ } else {
+ replacement = new GETSTATIC(index);
+ }
+ } else {
+ if (isSetter) {
+ replacement = new PUTFIELD(index);
} else {
- if (isSetter)
- replacement = new PUTFIELD(index);
- else
- replacement = new GETFIELD(index);
+ replacement = new GETFIELD(index);
}
- head.swapInstruction(replacement);
+ }
+ head.swapInstruction(replacement);
+ /*
if (false)
System.out.println("Substituting " + (isSetter ? "set" : "get") + " of " + field + " for call of "
+ invoked + " in " + methodGen.getClassName() + "." + methodGen.getName()
+ methodGen.getSignature());
+ */
}
@@ -679,8 +690,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
InstructionHandle next = head.getNext();
if (target.equals(next)) {
int consumed = ii.consumeStack(methodGen.getConstantPool());
- if (consumed != 1 && consumed != 2)
+ if (consumed != 1 && consumed != 2) {
throw new IllegalStateException();
+ }
head.swapInstruction(consumed == 1 ? new POP() : new POP2());
}
@@ -689,14 +701,22 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
IfInstruction ii = (IfInstruction) i;
InstructionHandle target = ii.getTarget();
InstructionHandle next1 = head.getNext(); // ICONST
- if (next1 == null) break;
+ if (next1 == null) {
+ break;
+ }
if (next1.getInstruction() instanceof ICONST) {
InstructionHandle next2 = next1.getNext(); // GOTO
- if (next2 == null) break;
+ if (next2 == null) {
+ break;
+ }
InstructionHandle next3 = next2.getNext(); // ICONST
- if (next3== null) break;
+ if (next3== null) {
+ break;
+ }
InstructionHandle next4 = next3.getNext();
- if (next4 == null) break;
+ if (next4 == null) {
+ break;
+ }
if (target.equals(next3) && next2.getInstruction() instanceof GOTO
&& next3.getInstruction() instanceof ICONST && next1.getTargeters().length == 0
&& next2.getTargeters().length == 0 && next3.getTargeters().length == 1
@@ -735,18 +755,19 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
// need to update
head.swapInstruction(new NOP());
IfInstruction ifTest = (IfInstruction) check;
- if (check instanceof IF_ACMPNE)
+ if (check instanceof IF_ACMPNE) {
next2.swapInstruction(new IFNONNULL(ifTest.getTarget()));
- else
+ } else {
next2.swapInstruction(new IFNULL(ifTest.getTarget()));
+ }
}
}
}
head = head.getNext();
}
-
}
+ @Override
public void build() throws CFGBuilderException {
InstructionList instructionList = methodGen.getInstructionList();
optimize(instructionList);
@@ -756,8 +777,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
// Build top level subroutine and all JSR subroutines
while (!subroutineWorkList.isEmpty()) {
Subroutine subroutine = subroutineWorkList.removeFirst();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Starting subroutine " + subroutine.getStartInstruction());
+ }
build(subroutine);
}
@@ -771,8 +793,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
InstructionList il = new InstructionList();
entryBlock.addInstruction(il.append(new NOP()));
- if (VERIFY_INTEGRITY)
+ if (VERIFY_INTEGRITY) {
cfg.checkIntegrity();
+ }
if (true) {
cfg.checkIntegrity();
@@ -780,6 +803,7 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
}
}
+ @Override
public CFG getCFG() {
return cfg;
}
@@ -813,19 +837,22 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
// Add exception handler block (ETB) for exception-throwing
// instructions
if (isPEI(handle)) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("ETB block " + basicBlock.getLabel() + " for " + handle);
+ }
handleExceptions(subroutine, handle, basicBlock);
BasicBlock body = subroutine.allocateBasicBlock();
subroutine.addEdge(basicBlock, body, FALL_THROUGH_EDGE);
basicBlock = body;
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("BODY block " + basicBlock.getLabel() + " for " + handle);
+ }
- if (!basicBlock.isEmpty())
+ if (!basicBlock.isEmpty()) {
throw new IllegalStateException("Block isn't empty!");
+ }
// Add instructions until we get to the end of the block
boolean endOfBasicBlock = false;
@@ -833,8 +860,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
Instruction ins = handle.getInstruction();
// Add the instruction to the block
- if (DEBUG)
+ if (DEBUG) {
System.out.println("BB " + basicBlock.getLabel() + ": adding" + handle);
+ }
basicBlock.addInstruction(handle);
subroutine.addInstruction(handle);
@@ -891,8 +919,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
if (!endOfBasicBlock) {
InstructionHandle next = handle.getNext();
- if (next == null)
+ if (next == null) {
throw new CFGBuilderException("Control falls off end of method: " + handle);
+ }
// Is the next instruction a control merge or a PEI?
if (isMerge(next) || isPEI(next)) {
@@ -932,8 +961,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
InstructionHandle handlerStart = exceptionHandler.getHandlerPC();
subroutine.addEdgeAndExplore(etb, handlerStart, HANDLED_EXCEPTION_EDGE);
- if (Hierarchy.isUniversalExceptionHandler(exceptionHandler.getCatchType()))
+ if (Hierarchy.isUniversalExceptionHandler(exceptionHandler.getCatchType())) {
sawUniversalExceptionHandler = true;
+ }
}
}
@@ -942,8 +972,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
// ANY exception type, then the exception can be thrown out of the
// method.
if (!sawUniversalExceptionHandler) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Adding unhandled exception edge from " + pei);
+ }
subroutine.setUnhandledExceptionBlock(etb);
}
}
@@ -954,30 +985,98 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
* @param handle
* the instruction
* @return true if the instruction can throw an exception, false otherwise
+ * @throws CFGBuilderException
*/
- private boolean isPEI(InstructionHandle handle) {
+ private boolean isPEI(InstructionHandle handle) throws CFGBuilderException {
Instruction ins = handle.getInstruction();
- if (!(ins instanceof ExceptionThrower))
+ if (!(ins instanceof ExceptionThrower)) {
return false;
+ }
- if (ins instanceof NEW)
+ if (ins instanceof NEW) {
return false;
+ }
// if (ins instanceof ATHROW) return false;
- if (ins instanceof GETSTATIC)
+ if (ins instanceof GETSTATIC) {
return false;
- if (ins instanceof PUTSTATIC)
+ }
+ if (ins instanceof PUTSTATIC) {
return false;
- if (ins instanceof ReturnInstruction)
+ }
+ if (ins instanceof ReturnInstruction) {
return false;
- if (ins instanceof INSTANCEOF)
+ }
+ if (ins instanceof INSTANCEOF) {
return false;
- if (ins instanceof MONITOREXIT)
+ }
+ if (ins instanceof MONITOREXIT) {
return false;
- if (ins instanceof LDC)
+ }
+ if (ins instanceof LDC) {
return false;
+ }
+ if (ins instanceof GETFIELD && !methodGen.isStatic()) {
+ // Assume that GETFIELD on this object is not PEI
+ return !isSafeFieldSource(handle.getPrev());
+ }
+ if (ins instanceof PUTFIELD && !methodGen.isStatic()) {
+ // Assume that PUTFIELD on this object is not PEI
+ int depth = ins.consumeStack(cpg);
+ for(InstructionHandle prev = handle.getPrev(); prev != null; prev = prev.getPrev()) {
+ Instruction prevInst = prev.getInstruction();
+ if(prevInst instanceof BranchInstruction) {
+ if(prevInst instanceof GotoInstruction) {
+ // Currently we support only jumps to the PUTFIELD itself
+ // This will cover simple cases like this.a = flag ? foo : bar
+ if(((BranchInstruction) prevInst).getTarget() == handle) {
+ depth = ins.consumeStack(cpg);
+ } else {
+ return true;
+ }
+ } else if (!(prevInst instanceof IfInstruction)) {
+ // As IF instructions may fall through then the stack depth remains unchanged
+ // Actually we should not go here for normal Java bytecode: switch or jsr should not appear in this context
+ return true;
+ }
+ }
+ depth = depth - prevInst.produceStack(cpg) + prevInst.consumeStack(cpg);
+ if(depth < 1) {
+ throw new CFGBuilderException("Invalid stack at "+prev+" when checking "+handle);
+ }
+ if(depth == 1) {
+ InstructionHandle prevPrev = prev.getPrev();
+ if(prevPrev != null && prevPrev.getInstruction() instanceof BranchInstruction) {
+ continue;
+ }
+ return !isSafeFieldSource(prevPrev);
+ }
+ }
+ }
return true;
+ }
+ /**
+ * @param handle instruction handle which loads the object for further GETFIELD/PUTFIELD operation
+ * @return true if this object is known to be non-null
+ */
+ private boolean isSafeFieldSource(InstructionHandle handle) {
+ while(handle != null && handle.getInstruction().getOpcode() == Constants.DUP) {
+ // Some compilers generate DUP for field increment code like
+ // ALOAD_0 / DUP / GETFIELD x / ICONST_1 / IADD / PUTFIELD x
+ handle = handle.getPrev();
+ }
+ if(handle == null) {
+ return false;
+ }
+ Instruction inst = handle.getInstruction();
+ if(inst.getOpcode() == Constants.ALOAD_0) {
+ return true;
+ }
+ if(inst instanceof GETFIELD && ((GETFIELD)inst).getFieldName(cpg).startsWith("this$")) {
+ return true;
+ }
+ return false;
}
/**
@@ -993,8 +1092,9 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
// of them are branches. If so, the instruction is a merge.
InstructionTargeter[] targeterList = handle.getTargeters();
for (InstructionTargeter targeter : targeterList) {
- if (targeter instanceof BranchInstruction)
+ if (targeter instanceof BranchInstruction) {
return true;
+ }
}
}
return false;
@@ -1054,12 +1154,14 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
}
// Set exception thrower status
- if (subBlock.isExceptionThrower())
+ if (subBlock.isExceptionThrower()) {
resultBlock.setExceptionThrower(subBlock.getExceptionThrower());
+ }
// Set exception handler status
- if (subBlock.isExceptionHandler())
+ if (subBlock.isExceptionHandler()) {
resultBlock.setExceptionGen(null, subBlock.getExceptionGen());
+ }
// Add control edges (including inlining JSR subroutines)
Iterator<Edge> edgeIter = subCFG.outgoingEdgeIterator(subBlock);
@@ -1109,14 +1211,16 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
// Look for the calling context which has the target instruction
Context caller = context.getCaller();
while (caller != null) {
- if (caller.getSubroutine().containsInstruction(targetInstruction))
+ if (caller.getSubroutine().containsInstruction(targetInstruction)) {
break;
+ }
caller = caller.getCaller();
}
- if (caller == null)
+ if (caller == null) {
throw new CFGBuilderException("Unknown caller for escape target " + targetInstruction + " referenced by "
+ context.getSubroutine().getStartInstruction());
+ }
// Find result block in caller
BasicBlock subCallerTargetBlock = caller.getSubroutine().getBlock(targetInstruction);
@@ -1189,11 +1293,13 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
Method[] methodList = jclass.getMethods();
for (Method method : methodList) {
- if (method.isAbstract() || method.isNative())
+ if (method.isAbstract() || method.isNative()) {
continue;
+ }
- if (methodName != null && !method.getName().equals(methodName))
+ if (methodName != null && !method.getName().equals(methodName)) {
continue;
+ }
MethodDescriptor descriptor = DescriptorFactory.instance().getMethodDescriptor(jclass, method);
MethodGen methodGen = new MethodGen(method, jclass.getClassName(), classGen.getConstantPool());
@@ -1212,5 +1318,3 @@ public class BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/BlockOrder.java b/src/java/edu/umd/cs/findbugs/ba/BlockOrder.java
index 2569267..62b4a70 100644
--- a/src/java/edu/umd/cs/findbugs/ba/BlockOrder.java
+++ b/src/java/edu/umd/cs/findbugs/ba/BlockOrder.java
@@ -29,11 +29,10 @@ public interface BlockOrder {
* Return an Iterator which visits the basic blocks in order.
*/
public Iterator<BasicBlock> blockIterator();
-
+
/** Return relative order of blocks.
* If b1.compareTo(b2) < 0, then b1 should occur before b2 in iteration.
*/
public int compare(BasicBlock b1, BasicBlock b2);
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/BlockType.java b/src/java/edu/umd/cs/findbugs/ba/BlockType.java
index ed25555..f5f984c 100644
--- a/src/java/edu/umd/cs/findbugs/ba/BlockType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/BlockType.java
@@ -27,25 +27,25 @@ import java.util.BitSet;
* block, and any catch block with an empty catch type (i.e., catch all
* exceptions) is a finally block. This assumption isn't quite accurate, but it
* seems to be a reasonable first approximation.
- *
+ *
* <p>
* If valid (isValid() returns true), a BlockType value is a stack of elements,
* which are either CATCH or FINALLY values. Call getDepth() to get the current
* nesting depth. Call get(int <i>n</i>) to get the <i>n</i>th stack item. Call
* getTopValue() to get the current top of the stack.
* </p>
- *
+ *
* <p>
* If invalid (isValid() returns false), a BlockType value is either <i>top</i>
* or <i>bottom</i>. These are the special values at the top and bottom of the
* dataflow lattice.
* </p>
- *
+ *
* <p>
* The dataflow lattice is effectively finite-height because real Java methods
* are guaranteed to have a finite catch and finally block nesting level.
* </p>
- *
+ *
* @see BlockTypeAnalysis
* @author David Hovemeyer
*/
@@ -83,19 +83,25 @@ public class BlockType extends BitSet {
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (!super.equals(obj))
+ }
+ if (!super.equals(obj)) {
return false;
- if (!(obj instanceof BlockType))
+ }
+ if (!(obj instanceof BlockType)) {
return false;
+ }
final BlockType other = (BlockType) obj;
- if (depth != other.depth)
+ if (depth != other.depth) {
return false;
- if (isTop != other.isTop)
+ }
+ if (isTop != other.isTop) {
return false;
- if (isValid != other.isValid)
+ }
+ if (isValid != other.isValid) {
return false;
+ }
return true;
}
@@ -111,8 +117,9 @@ public class BlockType extends BitSet {
* Get the current nesting depth. The value must be valid.
*/
public int getDepth() {
- if (!isValid)
+ if (!isValid) {
throw new IllegalStateException();
+ }
return depth;
}
@@ -120,8 +127,9 @@ public class BlockType extends BitSet {
* Get the top value on the catch and finally block nesting stack.
*/
public boolean getTopValue() {
- if (depth == 0)
+ if (depth == 0) {
throw new IllegalStateException();
+ }
return get(depth - 1);
}
@@ -130,8 +138,9 @@ public class BlockType extends BitSet {
* control flow are all blocks outside any catch or finally block.
*/
public boolean isNormal() {
- if (!isValid)
+ if (!isValid) {
throw new IllegalStateException();
+ }
return getDepth() == 0;
}
@@ -175,7 +184,7 @@ public class BlockType extends BitSet {
/**
* Make this object an exact duplicate of given object.
- *
+ *
* @param other
* the other BlockType object
*/
@@ -191,7 +200,7 @@ public class BlockType extends BitSet {
/**
* Return whether or not this object is identical to the one given.
- *
+ *
* @param other
* the other BlockType object
* @return true if this object is identical to the one given, false
@@ -201,17 +210,19 @@ public class BlockType extends BitSet {
if (!this.isValid) {
return !other.isValid && (this.isTop == other.isTop);
} else {
- if (!other.isValid)
+ if (!other.isValid) {
return false;
- else {
+ } else {
// Both facts are valid
- if (this.depth != other.depth)
+ if (this.depth != other.depth) {
return false;
+ }
// Compare bits
for (int i = 0; i < this.depth; ++i) {
- if (this.get(i) != other.get(i))
+ if (this.get(i) != other.get(i)) {
return false;
+ }
}
return true;
@@ -221,7 +232,7 @@ public class BlockType extends BitSet {
/**
* Merge other dataflow value into this value.
- *
+ *
* @param other
* the other BlockType value
*/
@@ -233,8 +244,9 @@ public class BlockType extends BitSet {
int pfxLen = Math.min(this.depth, other.depth);
int commonLen;
for (commonLen = 0; commonLen < pfxLen; ++commonLen) {
- if (this.get(commonLen) != other.get(commonLen))
+ if (this.get(commonLen) != other.get(commonLen)) {
break;
+ }
}
this.depth = commonLen;
}
@@ -256,11 +268,11 @@ public class BlockType extends BitSet {
@Override
public String toString() {
- if (isTop())
+ if (isTop()) {
return "<top>";
- else if (isBottom())
+ } else if (isBottom()) {
return "<bottom>";
- else {
+ } else {
StringBuilder buf = new StringBuilder();
buf.append("N");
for (int i = 0; i < depth; ++i) {
@@ -276,4 +288,3 @@ public class BlockType extends BitSet {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/BlockTypeAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/BlockTypeAnalysis.java
index ec44b74..ff1f9d0 100644
--- a/src/java/edu/umd/cs/findbugs/ba/BlockTypeAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/BlockTypeAnalysis.java
@@ -30,16 +30,16 @@ import org.apache.bcel.generic.ObjectType;
/**
* Dataflow analysis to determine the nesting of catch and finally blocks within
* a method.
- *
+ *
* @see BlockType
* @author David Hovemeyer
*/
public class BlockTypeAnalysis extends BasicAbstractDataflowAnalysis<BlockType> {
- private DepthFirstSearch dfs;
+ private final DepthFirstSearch dfs;
/**
* Constructor.
- *
+ *
* @param dfs
* a DepthFirstSearch for the method to be analyzed
*/
@@ -47,38 +47,47 @@ public class BlockTypeAnalysis extends BasicAbstractDataflowAnalysis<BlockType>
this.dfs = dfs;
}
+ @Override
public BlockType createFact() {
return new BlockType();
}
+ @Override
public void copy(BlockType source, BlockType dest) {
dest.copyFrom(source);
}
+ @Override
public void initEntryFact(BlockType result) throws DataflowAnalysisException {
result.setNormal();
}
+ @Override
public void makeFactTop(BlockType fact) {
fact.setTop();
}
+ @Override
public boolean isTop(BlockType fact) {
return fact.isTop();
}
+ @Override
public boolean isForwards() {
return true;
}
+ @Override
public BlockOrder getBlockOrder(CFG cfg) {
return new ReversePostOrder(cfg, dfs);
}
+ @Override
public boolean same(BlockType fact1, BlockType fact2) {
return fact1.sameAs(fact2);
}
+ @Override
public void transfer(BasicBlock basicBlock, @CheckForNull InstructionHandle end, BlockType start, BlockType result)
throws DataflowAnalysisException {
result.copyFrom(start);
@@ -100,6 +109,7 @@ public class BlockTypeAnalysis extends BasicAbstractDataflowAnalysis<BlockType>
}
}
+ @Override
public void meetInto(BlockType fact, Edge edge, BlockType result) throws DataflowAnalysisException {
result.mergeWith(fact);
}
@@ -130,4 +140,3 @@ public class BlockTypeAnalysis extends BasicAbstractDataflowAnalysis<BlockType>
// }
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/BytecodeScanner.java b/src/java/edu/umd/cs/findbugs/ba/BytecodeScanner.java
index ad4c969..62149f1 100644
--- a/src/java/edu/umd/cs/findbugs/ba/BytecodeScanner.java
+++ b/src/java/edu/umd/cs/findbugs/ba/BytecodeScanner.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.SystemProperties;
/**
* Scan the raw bytecodes of a method. This is useful in order to find out
* quickly whether or not a method uses particular instructions.
- *
+ *
* @author David Hovemeyer
*/
public class BytecodeScanner implements org.apache.bcel.Constants {
@@ -36,7 +36,7 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
public interface Callback {
/**
* Called to indicate that a particular bytecode has been scanned.
- *
+ *
* @param opcode
* the opcode of the instruction
* @param index
@@ -47,7 +47,7 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
/**
* Convert the unsigned value of a byte into a short.
- *
+ *
* @param value
* the byte
* @return the byte's unsigned value as a short
@@ -65,7 +65,7 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
/**
* Extract an int from bytes at the given offset in the array.
- *
+ *
* @param arr
* the array
* @param offset
@@ -80,7 +80,7 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
/**
* Scan the raw bytecodes of a method.
- *
+ *
* @param instructionList
* the bytecodes
* @param callback
@@ -94,8 +94,9 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
short opcode = unsignedValueOf(instructionList[index]);
callback.handleInstruction(opcode, index);
- if (DEBUG)
+ if (DEBUG) {
System.out.println(index + ": " + OPCODE_NAMES[opcode]);
+ }
switch (opcode) {
@@ -250,14 +251,14 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
++index;
break;
- // Two byte instructions.
+ // Two byte instructions.
case BIPUSH:
case LDC:
case NEWARRAY:
index += 2;
break;
- // Instructions that can be used with the WIDE prefix.
+ // Instructions that can be used with the WIDE prefix.
case ILOAD:
case LLOAD:
case FLOAD:
@@ -279,7 +280,7 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
}
break;
- // IINC is a special case for WIDE handling
+ // IINC is a special case for WIDE handling
case IINC:
if (wide) {
// Skip opcode, two byte index, and two byte immediate
@@ -292,7 +293,7 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
}
break;
- // Three byte instructions.
+ // Three byte instructions.
case SIPUSH:
case LDC_W:
case LDC2_W:
@@ -328,19 +329,20 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
index += 3;
break;
- // Four byte instructions.
+ // Four byte instructions.
case MULTIANEWARRAY:
index += 4;
break;
- // Five byte instructions.
+ // Five byte instructions.
case INVOKEINTERFACE:
+ case INVOKEDYNAMIC:
case GOTO_W:
case JSR_W:
index += 5;
break;
- // TABLESWITCH - variable length.
+ // TABLESWITCH - variable length.
case TABLESWITCH: {
// Skip padding.
int offset = index + 1; // skip the opcode
@@ -353,13 +355,14 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
int low = extractInt(instructionList, offset + 4);
int high = extractInt(instructionList, offset + 8);
int tableSize = (high - low) + 1;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("tableswitch: low=" + low + ", high=" + high + ", tableSize=" + tableSize);
+ }
// Skip to next instruction.
index = offset + 12 + (tableSize * 4);
}
- break;
+ break;
// LOOKUPSWITCH - variable length.
case LOOKUPSWITCH: {
@@ -372,13 +375,14 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
// Extract number of value/offset pairs.
int numPairs = extractInt(instructionList, offset + 4);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("lookupswitch: numPairs=" + numPairs);
+ }
// Skip to next instruction.
index = offset + 8 + (numPairs * 8);
}
- break;
+ break;
// Wide prefix.
case WIDE:
@@ -390,11 +394,11 @@ public class BytecodeScanner implements org.apache.bcel.Constants {
throw new IllegalArgumentException("Bad opcode " + opcode + " at offset " + index);
}
- if (index < 0)
+ if (index < 0) {
throw new IllegalStateException("index=" + index + ", opcode=" + opcode);
+ }
}
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/CFG.java b/src/java/edu/umd/cs/findbugs/ba/CFG.java
index 625feac..53c7681 100644
--- a/src/java/edu/umd/cs/findbugs/ba/CFG.java
+++ b/src/java/edu/umd/cs/findbugs/ba/CFG.java
@@ -37,7 +37,7 @@ import edu.umd.cs.findbugs.util.NullIterator;
/**
* Simple control flow graph abstraction for BCEL.
- *
+ *
* @see BasicBlock
* @see Edge
*/
@@ -87,7 +87,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
* both the instruction and the basic block.
*/
private class LocationIterator implements Iterator<Location> {
- private Iterator<BasicBlock> blockIter;
+ private final Iterator<BasicBlock> blockIter;
private BasicBlock curBlock;
@@ -100,20 +100,24 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
findNext();
}
+ @Override
public boolean hasNext() {
findNext();
return next != null;
}
+ @Override
public Location next() {
findNext();
- if (next == null)
+ if (next == null) {
throw new NoSuchElementException();
+ }
Location result = next;
next = null;
return result;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -123,15 +127,19 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
// Make sure we have an instruction iterator
if (instructionIter == null) {
if (!blockIter.hasNext())
+ {
return; // At end
+ }
curBlock = blockIter.next();
instructionIter = curBlock.instructionIterator();
}
- if (instructionIter.hasNext())
+ if (instructionIter.hasNext()) {
next = new Location(instructionIter.next(), curBlock);
- else
+ }
+ else {
instructionIter = null; // Go to next block
+ }
}
}
}
@@ -235,7 +243,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Add a unique edge to the graph. There must be no other edge already in
* the CFG with the same source and destination blocks.
- *
+ *
* @param source
* the source basic block
* @param dest
@@ -255,7 +263,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Look up an Edge by its id.
- *
+ *
* @param id
* the id of the edge to look up
* @return the Edge, or null if no matching Edge was found
@@ -264,15 +272,16 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
Iterator<Edge> i = edgeIterator();
while (i.hasNext()) {
Edge edge = i.next();
- if (edge.getId() == id)
+ if (edge.getId() == id) {
return edge;
+ }
}
return null;
}
/**
* Look up a BasicBlock by its unique label.
- *
+ *
* @param blockLabel
* the label of a BasicBlock
* @return the BasicBlock with the given label, or null if there is no such
@@ -315,6 +324,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
*/
public Iterable<Location> locations() {
return new Iterable<Location>() {
+ @Override
public Iterator<Location> iterator() {
return locationIterator();
}
@@ -325,7 +335,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
* Returns a collection of locations, ordered according to the compareTo
* ordering over locations. If you want to list all the locations in a CFG
* for debugging purposes, this is a good order to do so in.
- *
+ *
* @return collection of locations
*/
public Collection<Location> orderedLocations() {
@@ -339,7 +349,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Get Collection of basic blocks whose IDs are specified by given BitSet.
- *
+ *
* @param labelSet
* BitSet of block labels
* @return a Collection containing the blocks whose IDs are given
@@ -348,8 +358,9 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
LinkedList<BasicBlock> result = new LinkedList<BasicBlock>();
for (Iterator<BasicBlock> i = blockIterator(); i.hasNext();) {
BasicBlock block = i.next();
- if (labelSet.get(block.getLabel()))
+ if (labelSet.get(block.getLabel())) {
result.add(block);
+ }
}
return result;
}
@@ -357,7 +368,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Get a Collection of basic blocks which contain the bytecode instruction
* with given offset.
- *
+ *
* @param offset
* the bytecode offset of an instruction
* @return Collection of BasicBlock objects which contain the instruction
@@ -367,8 +378,9 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
LinkedList<BasicBlock> result = new LinkedList<BasicBlock>();
for (Iterator<BasicBlock> i = blockIterator(); i.hasNext();) {
BasicBlock block = i.next();
- if (block.containsInstructionWithOffset(offset))
+ if (block.containsInstructionWithOffset(offset)) {
result.add(block);
+ }
}
return result;
}
@@ -376,7 +388,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Get a Collection of Locations which specify the instruction at given
* bytecode offset.
- *
+ *
* @param offset
* the bytecode offset
* @return all Locations referring to the instruction at that offset
@@ -394,7 +406,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Get the first predecessor reachable from given edge type.
- *
+ *
* @param target
* the target block
* @param edgeType
@@ -409,7 +421,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Get the first successor reachable from given edge type.
- *
+ *
* @param source
* the source block
* @param edgeType
@@ -425,18 +437,20 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Get the Location where exception(s) thrown on given exception edge are
* thrown.
- *
+ *
* @param exceptionEdge
* the exception Edge
* @return Location where exception(s) are thrown from
*/
public Location getExceptionThrowerLocation(Edge exceptionEdge) {
- if (!exceptionEdge.isExceptionEdge())
+ if (!exceptionEdge.isExceptionEdge()) {
throw new IllegalArgumentException();
+ }
InstructionHandle handle = exceptionEdge.getSource().getExceptionThrower();
- if (handle == null)
+ if (handle == null) {
throw new IllegalStateException();
+ }
BasicBlock basicBlock = (handle.getInstruction() instanceof ATHROW) ? exceptionEdge.getSource()
: getSuccessorWithEdgeType(exceptionEdge.getSource(), EdgeTypes.FALL_THROUGH_EDGE);
@@ -465,7 +479,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Get an Iterator over Edges removed from this CFG.
- *
+ *
* @return Iterator over Edges removed from this CFG
*/
public Iterator<Edge> removedEdgeIterator() {
@@ -474,7 +488,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Get the first incoming edge in basic block with given type.
- *
+ *
* @param basicBlock
* the basic block
* @param edgeType
@@ -487,7 +501,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Get the first outgoing edge in basic block with given type.
- *
+ *
* @param basicBlock
* the basic block
* @param edgeType
@@ -501,8 +515,9 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
private Edge getEdgeWithType(Iterator<Edge> iter, @Type int edgeType) {
while (iter.hasNext()) {
Edge edge = iter.next();
- if (edge.getType() == edgeType)
+ if (edge.getType() == edgeType) {
return edge;
+ }
}
return null;
}
@@ -540,9 +555,10 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
InstructionHandle prev = null;
for (Iterator<InstructionHandle> j = basicBlock.instructionIterator(); j.hasNext();) {
InstructionHandle handle = j.next();
- if (prev != null && prev.getNext() != handle)
+ if (prev != null && prev.getNext() != handle) {
throw new IllegalStateException("Non-consecutive instructions in block " + basicBlock.getLabel() + ": prev="
+ prev + ", handle=" + handle);
+ }
prev = handle;
}
}
@@ -555,7 +571,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.graph.AbstractGraph#removeEdge(edu.umd.cs.findbugs
* .graph.AbstractEdge)
@@ -573,7 +589,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
/**
* Get number of non-exception control successors of given basic block.
- *
+ *
* @param block
* a BasicBlock
* @return number of non-exception control successors of the basic block
@@ -597,7 +613,7 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
* Get the Location representing the entry to the CFG. Note that this is a
* "fake" Location, and shouldn't be relied on to yield source line
* information.
- *
+ *
* @return Location at entry to CFG
*/
public Location getLocationAtEntry() {
@@ -615,12 +631,14 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
while (true) {
prevBlock = getPredecessorWithEdgeType(prevBlock, EdgeTypes.FALL_THROUGH_EDGE);
- if (prevBlock == null)
+ if (prevBlock == null) {
return loc;
+ }
handle = prevBlock.getLastInstruction();
- if (handle != null)
+ if (handle != null) {
return new Location(handle, prevBlock);
+ }
}
} else {
@@ -633,4 +651,3 @@ public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/CFGBuilder.java b/src/java/edu/umd/cs/findbugs/ba/CFGBuilder.java
index c7dbcdf..d7f9eaa 100644
--- a/src/java/edu/umd/cs/findbugs/ba/CFGBuilder.java
+++ b/src/java/edu/umd/cs/findbugs/ba/CFGBuilder.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.ba;
/**
* Abstract interface for CFG builder classes.
- *
+ *
* @author David Hovemeyer
* @see CFG
* @see CFGBuilderFactory
@@ -35,10 +35,9 @@ public interface CFGBuilder {
/**
* Get the CFG built by this object. Assumes that the build() method has
* already been called.
- *
+ *
* @return the CFG
*/
public CFG getCFG();
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/CFGBuilderFactory.java b/src/java/edu/umd/cs/findbugs/ba/CFGBuilderFactory.java
index 8cdff24..51564c3 100644
--- a/src/java/edu/umd/cs/findbugs/ba/CFGBuilderFactory.java
+++ b/src/java/edu/umd/cs/findbugs/ba/CFGBuilderFactory.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
* is preferable to direct instantiation of CFGBuilders, because it gives us an
* easy hook for plugging in new CFGBuilder implementations. (CFGs for Java are
* a little tricky to get right.)
- *
+ *
* @author David Hovemeyer
* @see CFG
* @see CFGBuilder
@@ -40,7 +40,7 @@ public class CFGBuilderFactory {
/**
* Create a CFGBuilder to build a CFG for given method.
- *
+ *
* @param methodGen
* the method
* @return a CFGBuilder for the method
@@ -50,4 +50,3 @@ public class CFGBuilderFactory {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/CFGPrinter.java b/src/java/edu/umd/cs/findbugs/ba/CFGPrinter.java
index c04731c..61d173a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/CFGPrinter.java
+++ b/src/java/edu/umd/cs/findbugs/ba/CFGPrinter.java
@@ -27,12 +27,12 @@ import org.apache.bcel.generic.InstructionHandle;
/**
* Print out a representation of a control-flow graph. For debugging.
- *
+ *
* @see CFG
* @see CFGBuilder
*/
public class CFGPrinter {
- private CFG cfg;
+ private final CFG cfg;
private boolean isForwards;
@@ -97,10 +97,11 @@ public class CFGPrinter {
}
protected Iterator<InstructionHandle> instructionIterator(BasicBlock bb) {
- if (isForwards)
+ if (isForwards) {
return bb.instructionIterator();
- else
+ } else {
return bb.instructionReverseIterator();
+ }
}
// public static void main(String[] argv) throws Exception {
@@ -147,4 +148,3 @@ public class CFGPrinter {
// }
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/CheckReturnAnnotationDatabase.java b/src/java/edu/umd/cs/findbugs/ba/CheckReturnAnnotationDatabase.java
index b47b9a6..2d1f9c6 100644
--- a/src/java/edu/umd/cs/findbugs/ba/CheckReturnAnnotationDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/CheckReturnAnnotationDatabase.java
@@ -42,8 +42,9 @@ public class CheckReturnAnnotationDatabase extends AnnotationDatabase<CheckRetur
@Override
public void loadAuxiliaryAnnotations() {
- if (IGNORE_BUILTIN_ANNOTATIONS)
+ if (IGNORE_BUILTIN_ANNOTATIONS) {
return;
+ }
boolean missingClassWarningsSuppressed = AnalysisContext.currentAnalysisContext().setMissingClassWarningsSuppressed(true);
addMethodAnnotation("java.util.Iterator", "hasNext", "()Z", false, CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW);
@@ -119,7 +120,7 @@ public class CheckReturnAnnotationDatabase extends AnnotationDatabase<CheckRetur
addWarningAboutSubmit(ThreadPoolExecutor.class);
addWarningAboutSubmit(ScheduledThreadPoolExecutor.class);
addWarningAboutSubmit(AbstractExecutorService.class);
-
+
addMethodAnnotation("java.util.concurrent.BlockingQueue", "poll", "(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;",
false, CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
addMethodAnnotation("java.util.Queue", "poll", "()Ljava/lang/Object;", false,
@@ -146,7 +147,7 @@ public class CheckReturnAnnotationDatabase extends AnnotationDatabase<CheckRetur
CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
addMethodAnnotation("java.math.BigDecimal", "precision", "()I", false,
CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
-
+
addMethodAnnotation("java.math.BigDecimal", "toBigIntegerExact", "()Ljava/math/BigInteger;", false,
CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
addMethodAnnotation("java.math.BigDecimal", "longValueExact", "()J", false,
@@ -184,12 +185,12 @@ public class CheckReturnAnnotationDatabase extends AnnotationDatabase<CheckRetur
CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
addMethodAnnotation("java.lang.ProcessBuilder", "redirectErrorStream", "()Z", false,
CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
-
+
addDefaultMethodAnnotation("jsr166z.forkjoin.ParallelArray", CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
addDefaultMethodAnnotation("jsr166z.forkjoin.ParallelLongArray", CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
addDefaultMethodAnnotation("jsr166z.forkjoin.ParallelDoubleArray", CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
-
-
+
+
addMethodAnnotation(java.sql.Statement.class, "executeQuery", "(Ljava/lang/String;)Ljava/sql/ResultSet;", false,
CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
addMethodAnnotation(java.sql.PreparedStatement.class, "executeQuery", "()Ljava/sql/ResultSet;", false,
@@ -225,32 +226,37 @@ public class CheckReturnAnnotationDatabase extends AnnotationDatabase<CheckRetur
@Override
public CheckReturnValueAnnotation getResolvedAnnotation(Object o, boolean getMinimal) {
- if (!(o instanceof XMethod))
+ if (!(o instanceof XMethod)) {
return null;
+ }
XMethod m = (XMethod) o;
- if (m.getName().startsWith("access$"))
+ if (m.getName().startsWith("access$")) {
return null;
- else if (m.getName().equals("<init>")) {
+ } else if ("<init>".equals(m.getName())) {
try {
- if (throwableClass != null && Repository.instanceOf(m.getClassName(), throwableClass))
+ if (throwableClass != null && Repository.instanceOf(m.getClassName(), throwableClass)) {
return CheckReturnValueAnnotation.CHECK_RETURN_VALUE_VERY_HIGH;
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
- if (m.getClassName().equals("java.lang.Thread"))
+ if ("java.lang.Thread".equals(m.getClassName())) {
return CheckReturnValueAnnotation.CHECK_RETURN_VALUE_VERY_HIGH;
+ }
try {
- if (threadClass != null && Repository.instanceOf(m.getClassName(), threadClass))
+ if (threadClass != null && Repository.instanceOf(m.getClassName(), threadClass)) {
return CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW;
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
- } else if (m.getName().equals("equals") && m.getSignature().equals("(Ljava/lang/Object;)Z") && !m.isStatic())
+ } else if ("equals".equals(m.getName()) && "(Ljava/lang/Object;)Z".equals(m.getSignature()) && !m.isStatic()) {
return CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM;
- else if (m.getSignature().endsWith(")Ljava/lang/String;")
- && (m.getClassName().equals("java.lang.StringBuffer") || m.getClassName().equals("java.lang.StringBuilder")))
+ } else if (m.getSignature().endsWith(")Ljava/lang/String;")
+ && ("java.lang.StringBuffer".equals(m.getClassName()) || "java.lang.StringBuilder".equals(m.getClassName()))) {
return CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM;
+ }
return super.getResolvedAnnotation(o, getMinimal);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/CheckReturnValueAnnotation.java b/src/java/edu/umd/cs/findbugs/ba/CheckReturnValueAnnotation.java
index 5ae9df3..0af6f56 100644
--- a/src/java/edu/umd/cs/findbugs/ba/CheckReturnValueAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/ba/CheckReturnValueAnnotation.java
@@ -55,24 +55,28 @@ public class CheckReturnValueAnnotation extends AnnotationEnumeration<CheckRetur
public final static CheckReturnValueAnnotation CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE = new CheckReturnValueAnnotation(
"CheckReturnValueMediumBadPractice", 7, "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE", Detector.NORMAL_PRIORITY);
-
+
public final static CheckReturnValueAnnotation CHECK_RETURN_VALUE_INFERRED = new CheckReturnValueAnnotation(
"CheckReturnValueInferred", 8, "RV_RETURN_VALUE_IGNORED_INFERRED", Detector.NORMAL_PRIORITY);
private final static CheckReturnValueAnnotation[] myValues = { CHECK_RETURN_VALUE_UNKNOWN, CHECK_RETURN_VALUE_HIGH,
- CHECK_RETURN_VALUE_MEDIUM, CHECK_RETURN_VALUE_LOW, CHECK_RETURN_VALUE_IGNORE, CHECK_RETURN_VALUE_VERY_HIGH,
- CHECK_RETURN_VALUE_LOW_BAD_PRACTICE, CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE, CHECK_RETURN_VALUE_INFERRED};
+ CHECK_RETURN_VALUE_MEDIUM, CHECK_RETURN_VALUE_LOW, CHECK_RETURN_VALUE_IGNORE, CHECK_RETURN_VALUE_VERY_HIGH,
+ CHECK_RETURN_VALUE_LOW_BAD_PRACTICE, CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE, CHECK_RETURN_VALUE_INFERRED};
@CheckForNull
public static CheckReturnValueAnnotation parse(String priority) {
- if (priority == null)
+ if (priority == null) {
return CHECK_RETURN_VALUE_MEDIUM;
- if (priority.endsWith("HIGH"))
+ }
+ if (priority.endsWith("HIGH")) {
return CHECK_RETURN_VALUE_HIGH;
- if (priority.endsWith("MEDIUM"))
+ }
+ if (priority.endsWith("MEDIUM")) {
return CHECK_RETURN_VALUE_MEDIUM;
- if (priority.endsWith("LOW"))
+ }
+ if (priority.endsWith("LOW")) {
return CHECK_RETURN_VALUE_LOW;
+ }
throw new IllegalArgumentException("Bad priority: " + priority);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/ClassContext.java b/src/java/edu/umd/cs/findbugs/ba/ClassContext.java
index 943b012..e0d609b 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ClassContext.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ClassContext.java
@@ -46,6 +46,7 @@ import org.apache.bcel.generic.MethodGen;
import edu.umd.cs.findbugs.AnalysisLocal;
import edu.umd.cs.findbugs.OpcodeStack.JumpInfo;
import edu.umd.cs.findbugs.SystemProperties;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import edu.umd.cs.findbugs.ba.ca.CallListDataflow;
import edu.umd.cs.findbugs.ba.constant.ConstantDataflow;
import edu.umd.cs.findbugs.ba.deref.UnconditionalValueDerefDataflow;
@@ -126,12 +127,13 @@ public class ClassContext {
public Map<MethodDescriptor, Object> getObjectMap(Class<?> analysisClass) {
Map<MethodDescriptor, Object> objectMap = methodAnalysisObjectMap.get(analysisClass);
if (objectMap == null) {
- if (analysisClass == ValueNumberDataflow.class)
+ if (analysisClass == ValueNumberDataflow.class) {
objectMap = new MapCache<MethodDescriptor, Object>(300);
- else if (Dataflow.class.isAssignableFrom(analysisClass))
+ } else if (Dataflow.class.isAssignableFrom(analysisClass)) {
objectMap = new MapCache<MethodDescriptor, Object>(500);
- else
+ } else {
objectMap = new HashMap<MethodDescriptor, Object>();
+ }
methodAnalysisObjectMap.put(analysisClass, objectMap);
}
return objectMap;
@@ -248,8 +250,9 @@ public class ClassContext {
List<Method> methodsInCallOrder = new ArrayList<Method>(xmethodsInCallOrder.size());
for (XMethod x : xmethodsInCallOrder) {
Method m = map.get(x);
- if (m != null)
+ if (m != null) {
methodsInCallOrder.add(m);
+ }
}
return methodsInCallOrder;
}
@@ -318,7 +321,7 @@ public class ClassContext {
* @return the UsagesRequiringNonNullValues
*/
public UsagesRequiringNonNullValues getUsagesRequiringNonNullValues(Method method) throws DataflowAnalysisException,
- CFGBuilderException {
+ CFGBuilderException {
return getMethodAnalysis(UsagesRequiringNonNullValues.class, method);
}
@@ -377,8 +380,8 @@ public class ClassContext {
return getMethodAnalysisNoDataflowAnalysisException(ReverseDepthFirstSearch.class, method);
}
- static final AnalysisLocal<MapCache<XMethod, BitSet>> cachedBitsets_AL
- = new AnalysisLocal<MapCache<XMethod, BitSet>>() {
+ static final AnalysisLocal<MapCache<XMethod, BitSet>> cachedBitsets_AL =
+ new AnalysisLocal<MapCache<XMethod, BitSet>>() {
@Override
protected MapCache<XMethod, BitSet> initialValue() {
return new MapCache<XMethod, BitSet>(64);
@@ -431,8 +434,9 @@ public class ClassContext {
return cachedBitsets().get(xmethod);
}
Code code = method.getCode();
- if (code == null)
+ if (code == null) {
return null;
+ }
byte[] instructionList = code.getCode();
@@ -445,15 +449,13 @@ public class ClassContext {
UnpackedCode unpackedCode = callback.getUnpackedCode();
BitSet result = null;
- if (unpackedCode != null)
+ if (unpackedCode != null) {
result = unpackedCode.getBytecodeSet();
+ }
cachedBitsets().put(xmethod, result);
return result;
}
- /**
- * @return
- */
private static MapCache<XMethod, BitSet> cachedBitsets() {
return cachedBitsets_AL.get();
}
@@ -469,7 +471,7 @@ public class ClassContext {
assert false;
return Collections.<Integer> emptySet();
}
- return result;
+ return result;
}
Code code = method.getCode();
if (code == null) {
@@ -480,19 +482,19 @@ public class ClassContext {
byte[] instructionList = code.getCode();
Set<Integer> result = new HashSet<Integer>();
- for (int i = 0; i < instructionList.length; i++)
- if (checkForBranchExit(instructionList, i))
+ for (int i = 0; i < instructionList.length; i++) {
+ if (checkForBranchExit(instructionList, i)) {
result.add(i);
- if (result.size() == 0)
+ }
+ }
+ if (result.size() == 0) {
result = Collections.<Integer> emptySet();
+ }
cachedLoopExits().put(xmethod, result);
return result;
}
- /**
- * @return
- */
private static MapCache<XMethod, Set<Integer>> cachedLoopExits() {
return cachedLoopExits_AL.get();
}
@@ -506,8 +508,9 @@ public class ClassContext {
}
static boolean checkForBranchExit(byte[] codeBytes, int pos) {
- if (pos < 0 || pos + 2 >= codeBytes.length)
+ if (pos < 0 || pos + 2 >= codeBytes.length) {
return false;
+ }
switch (0xff & codeBytes[pos]) {
case Constants.IF_ACMPEQ:
case Constants.IF_ACMPNE:
@@ -522,13 +525,16 @@ public class ClassContext {
return false;
}
int branchTarget = pos + getBranchOffset(codeBytes, pos + 1);
- if (branchTarget - 3 < pos || branchTarget >= codeBytes.length)
+ if (branchTarget - 3 < pos || branchTarget >= codeBytes.length) {
return false;
- if ((codeBytes[branchTarget - 3] & 0xff) != Constants.GOTO)
+ }
+ if ((codeBytes[branchTarget - 3] & 0xff) != Constants.GOTO) {
return false;
+ }
int backBranchTarget = branchTarget + getBranchOffset(codeBytes, branchTarget - 2);
- if (backBranchTarget <= pos && backBranchTarget + 12 >= pos)
+ if (backBranchTarget <= pos && backBranchTarget + 12 >= pos) {
return true;
+ }
return false;
}
@@ -543,6 +549,8 @@ public class ClassContext {
* @return map of bytecode offsets to opcodes, or null if the method has no
* code
*/
+ @CheckForNull
+ @SuppressFBWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS")
public short[] getOffsetToOpcodeMap(Method method) {
UnpackedCode unpackedCode = getMethodAnalysisNoException(UnpackedCode.class, method);
return unpackedCode != null ? unpackedCode.getOffsetToBytecodeMap() : null;
@@ -594,7 +602,7 @@ public class ClassContext {
* @return the DominatorsAnalysis
*/
public DominatorsAnalysis getNonExceptionDominatorsAnalysis(Method method) throws CFGBuilderException,
- DataflowAnalysisException {
+ DataflowAnalysisException {
return getMethodAnalysis(DominatorsAnalysis.class, method);
}
@@ -607,7 +615,7 @@ public class ClassContext {
* @return the DominatorsAnalysis
*/
public PostDominatorsAnalysis getNonImplicitExceptionDominatorsAnalysis(Method method) throws CFGBuilderException,
- DataflowAnalysisException {
+ DataflowAnalysisException {
return getMethodAnalysis(NonImplicitExceptionPostDominatorsAnalysis.class, method);
}
@@ -620,7 +628,7 @@ public class ClassContext {
* @return the PostDominatorsAnalysis
*/
public PostDominatorsAnalysis getNonExceptionPostDominatorsAnalysis(Method method) throws CFGBuilderException,
- DataflowAnalysisException {
+ DataflowAnalysisException {
return getMethodAnalysis(NonExceptionPostdominatorsAnalysis.class, method);
}
@@ -768,39 +776,46 @@ public class ClassContext {
BitSet pcInFinallyBlock = new BitSet();
Code code = method.getCode();
- if (code == null)
+ if (code == null) {
return lineMentionedMultipleTimes;
+ }
CodeException[] exceptionTable = code.getExceptionTable();
- if (exceptionTable == null || exceptionTable.length == 0)
+ if (exceptionTable == null || exceptionTable.length == 0) {
return lineMentionedMultipleTimes;
+ }
int firstHandler = Integer.MAX_VALUE;
- for (CodeException e : exceptionTable)
+ for (CodeException e : exceptionTable) {
if (e.getCatchType() == 0) {
int pc = e.getHandlerPC();
firstHandler = Math.min(firstHandler, pc);
if (jumpInfo != null) {
int end = jumpInfo.getNextJump(pc + 1);
- if (end >= pc)
+ if (end >= pc) {
pcInFinallyBlock.set(pc, end);
+ }
}
}
+ }
BitSet foundOnce = new BitSet();
BitSet afterHandler = new BitSet();
LineNumberTable lineNumberTable = method.getLineNumberTable();
int lineNum = -1;
int prevStartPc = -1;
- if (lineNumberTable != null)
+ if (lineNumberTable != null) {
for (LineNumber line : lineNumberTable.getLineNumberTable()) {
int newLine = line.getLineNumber();
- if (newLine == lineNum || newLine == -1)
+ if (newLine == lineNum || newLine == -1) {
continue;
+ }
if (prevStartPc >= 0) {
int nextPcInFinallyBlock = pcInFinallyBlock.nextSetBit(prevStartPc);
- if (nextPcInFinallyBlock < line.getStartPC())
+ if (nextPcInFinallyBlock < line.getStartPC()) {
lineMentionedMultipleTimes.set(lineNum);
+ }
}
- if (line.getStartPC() >= firstHandler)
+ if (line.getStartPC() >= firstHandler) {
afterHandler.set(lineNum);
+ }
lineNum = newLine;
prevStartPc = line.getStartPC();
@@ -810,6 +825,7 @@ public class ClassContext {
foundOnce.set(lineNum);
}
}
+ }
lineMentionedMultipleTimes.and(afterHandler);
return lineMentionedMultipleTimes;
}
@@ -824,7 +840,7 @@ public class ClassContext {
* @throws DataflowAnalysisException
*/
public UnconditionalValueDerefDataflow getUnconditionalValueDerefDataflow(Method method) throws CFGBuilderException,
- DataflowAnalysisException {
+ DataflowAnalysisException {
return getMethodAnalysis(UnconditionalValueDerefDataflow.class, method);
}
@@ -882,19 +898,9 @@ public class ClassContext {
}
}
- /**
- * @param method
- * @param cfg
- * @param vnd
- * @param inv
- * @param dataflow
- * @param typeDataflow
- * TODO
- * @throws DataflowAnalysisException
- */
public static void dumpDataflowInformation(Method method, CFG cfg, ValueNumberDataflow vnd, IsNullValueDataflow inv,
@CheckForNull UnconditionalValueDerefDataflow dataflow, @CheckForNull TypeDataflow typeDataflow)
- throws DataflowAnalysisException {
+ throws DataflowAnalysisException {
System.out.println("\n\n{ UnconditionalValueDerefAnalysis analysis for " + method.getName());
TreeSet<Location> tree = new TreeSet<Location>();
@@ -904,29 +910,27 @@ public class ClassContext {
}
for (Location loc : tree) {
System.out.println();
- if (dataflow != null)
+ if (dataflow != null) {
System.out.println("\n Pre: " + dataflow.getFactAfterLocation(loc));
+ }
System.out.println("Vna: " + vnd.getFactAtLocation(loc));
System.out.println("inv: " + inv.getFactAtLocation(loc));
- if (typeDataflow != null)
+ if (typeDataflow != null) {
System.out.println("type: " + typeDataflow.getFactAtLocation(loc));
+ }
System.out.println("Location: " + loc);
- if (dataflow != null)
+ if (dataflow != null) {
System.out.println("Post: " + dataflow.getFactAtLocation(loc));
+ }
System.out.println("Vna: " + vnd.getFactAfterLocation(loc));
System.out.println("inv: " + inv.getFactAfterLocation(loc));
- if (typeDataflow != null)
+ if (typeDataflow != null) {
System.out.println("type: " + typeDataflow.getFactAfterLocation(loc));
+ }
}
System.out.println("}\n\n");
}
- /**
- * @param method
- * @param cfg
- * @param typeDataflow
- * @throws DataflowAnalysisException
- */
public static void dumpTypeDataflow(Method method, CFG cfg, TypeDataflow typeDataflow) throws DataflowAnalysisException {
System.out.println("\n\n{ Type analysis for " + cfg.getMethodGen().getClassName() + "." + method.getName()
+ method.getSignature());
@@ -944,12 +948,6 @@ public class ClassContext {
System.out.println("}\n\n");
}
- /**
- * @param method
- * @param cfg
- * @param typeDataflow
- * @throws DataflowAnalysisException
- */
public static void dumpLiveLocalStoreDataflow(MethodDescriptor method, CFG cfg, LiveLocalStoreDataflow dataflow)
throws DataflowAnalysisException {
System.out.println("\n\n{ LiveLocalStore analysis for " + method);
@@ -998,7 +996,7 @@ public class ClassContext {
}
private <Analysis> Analysis getMethodAnalysis(Class<Analysis> analysisClass, Method method) throws DataflowAnalysisException,
- CFGBuilderException {
+ CFGBuilderException {
try {
MethodDescriptor methodDescriptor = BCELUtil.getMethodDescriptor(jclass, method);
return Global.getAnalysisCache().getMethodAnalysis(analysisClass, methodDescriptor);
@@ -1047,5 +1045,3 @@ public class ClassContext {
// }
// }
}
-
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/ba/ClassHash.java b/src/java/edu/umd/cs/findbugs/ba/ClassHash.java
index 9905b0e..ec3136e 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ClassHash.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ClassHash.java
@@ -42,7 +42,7 @@ import edu.umd.cs.findbugs.xml.XMLWriteable;
/**
* Compute a hash of method names and signatures. This allows us to find out
* when a class has been renamed, but not changed in any other obvious way.
- *
+ *
* @author David Hovemeyer
*/
public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
@@ -61,7 +61,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
private byte[] classHash;
- private Map<XMethod, MethodHash> methodHashMap;
+ private final Map<XMethod, MethodHash> methodHashMap;
/**
* Constructor.
@@ -72,7 +72,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
/**
* Constructor.
- *
+ *
* @param classHash
* pre-computed class hash
*/
@@ -85,7 +85,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
/**
* Set method hash for given method.
- *
+ *
* @param method
* the method
* @param methodHash
@@ -104,7 +104,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
/**
* Get class hash.
- *
+ *
* @return the class hash
*/
public byte[] getClassHash() {
@@ -113,7 +113,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
/**
* Set class hash.
- *
+ *
* @param classHash
* the class hash value to set
*/
@@ -124,7 +124,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
/**
* Get method hash for given method.
- *
+ *
* @param method
* the method
* @return the MethodHash
@@ -135,7 +135,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
/**
* Compute hash for given class and all of its methods.
- *
+ *
* @param javaClass
* the class
* @return this object
@@ -148,11 +148,13 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
// Sort methods
System.arraycopy(javaClass.getMethods(), 0, methodList, 0, javaClass.getMethods().length);
Arrays.sort(methodList, new Comparator<Method>() {
+ @Override
public int compare(Method o1, Method o2) {
// sort by name, then signature
int cmp = o1.getName().compareTo(o2.getName());
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return o1.getSignature().compareTo(o2.getSignature());
}
@@ -165,13 +167,15 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
Arrays.sort(fieldList, new Comparator<Field>() {
/*
* (non-Javadoc)
- *
+ *
* @see java.util.Comparator#compare(T, T)
*/
+ @Override
public int compare(Field o1, Field o2) {
int cmp = o1.getName().compareTo(o2.getName());
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return o1.getSignature().compareTo(o2.getSignature());
}
});
@@ -219,6 +223,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
}
}
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
xmlOutput.startTag(CLASS_HASH_ELEMENT_NAME);
xmlOutput.addAttribute("class", className);
@@ -241,7 +246,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
/**
* Convert a hash to a string of hex digits.
- *
+ *
* @param hash
* the hash
* @return a String representation of the hash
@@ -256,26 +261,28 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
}
private static int hexDigitValue(char c) {
- if (c >= '0' && c <= '9')
+ if (c >= '0' && c <= '9') {
return c - '0';
- else if (c >= 'a' && c <= 'f')
+ } else if (c >= 'a' && c <= 'f') {
return 10 + (c - 'a');
- else if (c >= 'A' && c <= 'F')
+ } else if (c >= 'A' && c <= 'F') {
return 10 + (c - 'A');
- else
+ } else {
throw new IllegalArgumentException("Illegal hex character: " + c);
+ }
}
/**
* Convert a string of hex digits to a hash.
- *
+ *
* @param s
* string of hex digits
* @return the hash value represented by the string
*/
public static byte[] stringToHash(String s) {
- if (s.length() % 2 != 0)
+ if (s.length() % 2 != 0) {
throw new IllegalArgumentException("Invalid hash string: " + s);
+ }
byte[] hash = new byte[s.length() / 2];
for (int i = 0; i < s.length(); i += 2) {
byte b = (byte) ((hexDigitValue(s.charAt(i)) << 4) + hexDigitValue(s.charAt(i + 1)));
@@ -287,7 +294,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
/**
* Return whether or not this class hash has the same hash value as the one
* given.
- *
+ *
* @param other
* another ClassHash
* @return true if the hash values are the same, false if not
@@ -298,12 +305,14 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
@Override
public int hashCode() {
- if (classHash == null)
+ if (classHash == null) {
return 0;
+ }
int result = 1;
- for (byte element : classHash)
+ for (byte element : classHash) {
result = 31 * result + element;
+ }
return result;
@@ -311,16 +320,18 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
@Override
public boolean equals(Object o) {
- if (!(o instanceof ClassHash))
+ if (!(o instanceof ClassHash)) {
return false;
+ }
return isSameHash((ClassHash) o);
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Comparable#compareTo(T)
*/
+ @Override
public int compareTo(ClassHash other) {
int cmp = MethodHash.compareHashes(this.classHash, other.classHash);
// System.out.println(this + " <=> " + other + ": compareTo=" + cmp);
@@ -329,7 +340,7 @@ public class ClassHash implements XMLWriteable, Comparable<ClassHash> {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
diff --git a/src/java/edu/umd/cs/findbugs/ba/ClassMember.java b/src/java/edu/umd/cs/findbugs/ba/ClassMember.java
index 58c5254..048b5ec 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ClassMember.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ClassMember.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
/**
* Common super-interface for class members (fields and methods).
- *
+ *
* @see edu.umd.cs.findbugs.ba.XField
* @see edu.umd.cs.findbugs.ba.XMethod
* @author David Hovemeyer
@@ -50,11 +50,13 @@ public interface ClassMember extends Serializable, AccessibleEntity, FieldOrMet
/**
* Get the name of the field/method.
*/
+ @Override
public String getName();
/**
* Get the signature representing the field/method's type.
*/
+ @Override
public String getSignature();
/**
diff --git a/src/java/edu/umd/cs/findbugs/ba/ClassNotFoundExceptionParser.java b/src/java/edu/umd/cs/findbugs/ba/ClassNotFoundExceptionParser.java
index 50879a4..408cd5f 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ClassNotFoundExceptionParser.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ClassNotFoundExceptionParser.java
@@ -95,4 +95,3 @@ public class ClassNotFoundExceptionParser {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ClassSummary.java b/src/java/edu/umd/cs/findbugs/ba/ClassSummary.java
index ab67e3d..7356be7 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ClassSummary.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ClassSummary.java
@@ -27,9 +27,9 @@ import java.util.Set;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
public class ClassSummary {
- private Map<ClassDescriptor, ClassDescriptor> map = new HashMap<ClassDescriptor, ClassDescriptor>();
+ private final Map<ClassDescriptor, ClassDescriptor> map = new HashMap<ClassDescriptor, ClassDescriptor>();
- private Set<ClassDescriptor> veryFunky = new HashSet<ClassDescriptor>();
+ private final Set<ClassDescriptor> veryFunky = new HashSet<ClassDescriptor>();
public boolean mightBeEqualTo(ClassDescriptor checker, ClassDescriptor checkee) {
return checkee.equals(map.get(checker)) || veryFunky.contains(checker);
@@ -37,12 +37,13 @@ public class ClassSummary {
public void checksForEqualTo(ClassDescriptor checker, ClassDescriptor checkee) {
ClassDescriptor existing = map.get(checker);
- if (checkee.equals(existing))
+ if (checkee.equals(existing)) {
return;
- else if (existing != null)
+ } else if (existing != null) {
veryFunky.add(checker);
- else
+ } else {
map.put(checker, checkee);
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/CompactLocationNumbering.java b/src/java/edu/umd/cs/findbugs/ba/CompactLocationNumbering.java
index 0183460..6a7f59a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/CompactLocationNumbering.java
+++ b/src/java/edu/umd/cs/findbugs/ba/CompactLocationNumbering.java
@@ -25,17 +25,17 @@ import java.util.Iterator;
/**
* Compute a compact numbering of Locations in a CFG. This is useful for
* analyses that want to use a BitSet to keep track of Locations.
- *
+ *
* @author David Hovemeyer
*/
public class CompactLocationNumbering {
- private HashMap<Location, Integer> locationToNumberMap;
+ private final HashMap<Location, Integer> locationToNumberMap;
- private HashMap<Integer, Location> numberToLocationMap;
+ private final HashMap<Integer, Location> numberToLocationMap;
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG containing the Locations to number
*/
@@ -48,7 +48,7 @@ public class CompactLocationNumbering {
/**
* Get the size of the numbering, which is the maximum number assigned plus
* one.
- *
+ *
* @return the maximum number assigned plus one
*/
public int getSize() {
@@ -58,7 +58,7 @@ public class CompactLocationNumbering {
/**
* Get the number of given Location, which will be a non-negative integer in
* the range 0..getSize() - 1.
- *
+ *
* @param location
* @return the number of the location
*/
@@ -68,7 +68,7 @@ public class CompactLocationNumbering {
/**
* Get the Location given its number.
- *
+ *
* @param number
* the number
* @return Location corresponding to that number
diff --git a/src/java/edu/umd/cs/findbugs/ba/ComparableField.java b/src/java/edu/umd/cs/findbugs/ba/ComparableField.java
index d5fe347..99b12ff 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ComparableField.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ComparableField.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
diff --git a/src/java/edu/umd/cs/findbugs/ba/ComparableMethod.java b/src/java/edu/umd/cs/findbugs/ba/ComparableMethod.java
index e8ed264..e5e6122 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ComparableMethod.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ComparableMethod.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
diff --git a/src/java/edu/umd/cs/findbugs/ba/CompoundMethodChooser.java b/src/java/edu/umd/cs/findbugs/ba/CompoundMethodChooser.java
index 0a1a22d..740bb1b 100644
--- a/src/java/edu/umd/cs/findbugs/ba/CompoundMethodChooser.java
+++ b/src/java/edu/umd/cs/findbugs/ba/CompoundMethodChooser.java
@@ -30,25 +30,29 @@ public class CompoundMethodChooser implements JavaClassAndMethodChooser {
this.conjunctList = conjunctList;
}
+ @Override
public boolean choose(JavaClassAndMethod javaClassAndMethod) {
for (JavaClassAndMethodChooser chooser : conjunctList) {
- if (!chooser.choose(javaClassAndMethod))
+ if (!chooser.choose(javaClassAndMethod)) {
return false;
+ }
}
return true;
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.JavaClassAndMethodChooser#choose(edu.umd.cs.findbugs
* .ba.XMethod)
*/
+ @Override
public boolean choose(XMethod method) {
for (JavaClassAndMethodChooser chooser : conjunctList) {
- if (!chooser.choose(method))
+ if (!chooser.choose(method)) {
return false;
+ }
}
return true;
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/DFSCFGPrinter.java b/src/java/edu/umd/cs/findbugs/ba/DFSCFGPrinter.java
index b6d977a..6e2eba9 100644
--- a/src/java/edu/umd/cs/findbugs/ba/DFSCFGPrinter.java
+++ b/src/java/edu/umd/cs/findbugs/ba/DFSCFGPrinter.java
@@ -20,7 +20,7 @@
package edu.umd.cs.findbugs.ba;
public class DFSCFGPrinter extends CFGPrinter implements DFSEdgeTypes {
- private DepthFirstSearch dfs;
+ private final DepthFirstSearch dfs;
public DFSCFGPrinter(CFG cfg, DepthFirstSearch dfs) {
super(cfg);
diff --git a/src/java/edu/umd/cs/findbugs/ba/DFSEdgeTypes.java b/src/java/edu/umd/cs/findbugs/ba/DFSEdgeTypes.java
index a1e53eb..88789ad 100644
--- a/src/java/edu/umd/cs/findbugs/ba/DFSEdgeTypes.java
+++ b/src/java/edu/umd/cs/findbugs/ba/DFSEdgeTypes.java
@@ -23,7 +23,7 @@ package edu.umd.cs.findbugs.ba;
* Interface defining depth first search edge type constants. This is just a
* placeholder that forwards to the real interface in the
* edu.umd.cs.findbugs.graph package.
- *
+ *
* @see edu.umd.cs.findbugs.graph.DFSEdgeTypes
* @author David Hovemeyer
*/
diff --git a/src/java/edu/umd/cs/findbugs/ba/Dataflow.java b/src/java/edu/umd/cs/findbugs/ba/Dataflow.java
index 89b7af6..f683dd0 100644
--- a/src/java/edu/umd/cs/findbugs/ba/Dataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/Dataflow.java
@@ -53,13 +53,13 @@ import edu.umd.cs.findbugs.classfile.Global;
* @see DataflowAnalysis
*/
public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
- private CFG cfg;
+ private final CFG cfg;
- private AnalysisType analysis;
+ private final AnalysisType analysis;
- private BlockOrder blockOrder;
+ private final BlockOrder blockOrder;
- private boolean isForwards;
+ private final boolean isForwards;
private int numIterations;
@@ -106,15 +106,17 @@ public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
private String getFullyQualifiedMethodName() {
String methodName;
MethodGen methodGen = cfg.getMethodGen();
- if (methodGen == null)
+ if (methodGen == null) {
methodName = cfg.getMethodName();
- else
+ } else {
methodName = SignatureConverter.convertMethodSignature(methodGen);
+ }
return methodName;
}
static class ForwardProgramOrder implements Comparator<BasicBlock>, Serializable {
+ @Override
public int compare(BasicBlock o1, BasicBlock o2) {
int p1 = o1.getLabel();
int p2 = o2.getLabel();
@@ -202,22 +204,25 @@ public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
}
Iterator<BasicBlock> i = blockOrder.blockIterator();
if (numIterations > 3 && numIterations % 2 == 0 && blockOrder instanceof ReverseDFSOrder) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Trying program order");
+ }
TreeSet<BasicBlock> bb = new TreeSet<BasicBlock>(new BackwardProgramOrder());
Iterator<BasicBlock> j = blockOrder.blockIterator();
while (j.hasNext()) {
BasicBlock block = j.next();
bb.add(block);
}
- if (DEBUG)
+ if (DEBUG) {
for (BasicBlock block : bb) {
debug(block, "\n");
}
+ }
i = bb.iterator();
}
- if (DEBUG)
+ if (DEBUG) {
dumpDataflow(analysis);
+ }
// For each block in CFG...
@@ -243,8 +248,9 @@ public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
if (block == logicalEntryBlock()) {
analysis.makeFactTop(start);
analysis.initEntryFact(start);
- if (DEBUG)
+ if (DEBUG) {
debug(block, "Init entry fact ==> " + analysis.factToString(start) + "\n");
+ }
needToRecompute = true;
} else {
int lastCalculated = analysis.getLastUpdateTimestamp(start);
@@ -262,17 +268,19 @@ public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
} else {
continue;
}
-
+
}
BasicBlock logicalPred = isForwards ? edge.getSource() : edge.getTarget();
int direction = blockOrder.compare(block, logicalPred);
-
- if (DEBUG)
+
+ if (DEBUG) {
debug(block, "direction " + direction + " for " + blockId(logicalPred) + "\n");
- if (direction < 0)
+ }
+ if (direction < 0) {
sawBackEdge = true;
-
+ }
+
// Get the predecessor result fact
Fact predFact = analysis.getResultFact(logicalPred);
int predLastUpdated = analysis.getLastUpdateTimestamp(predFact);
@@ -289,66 +297,69 @@ public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
}
}
}
- if (predCount == 0)
+ if (predCount == 0) {
needToRecompute = true;
+ }
if (!needToRecompute) {
continue;
}
- if (needToRecompute) {
+ analysis.makeFactTop(start);
+ predEdgeIter = logicalPredecessorEdgeIterator(block);
+ while (predEdgeIter.hasNext()) {
+ Edge edge = predEdgeIter.next();
+ BasicBlock logicalPred = isForwards ? edge.getSource() : edge.getTarget();
- analysis.makeFactTop(start);
- predEdgeIter = logicalPredecessorEdgeIterator(block);
- while (predEdgeIter.hasNext()) {
- Edge edge = predEdgeIter.next();
- BasicBlock logicalPred = isForwards ? edge.getSource() : edge.getTarget();
+ // Get the predecessor result fact
+ Fact predFact = analysis.getResultFact(logicalPred);
- // Get the predecessor result fact
- Fact predFact = analysis.getResultFact(logicalPred);
+ // Apply the edge transfer function.
+ Fact edgeFact = analysis.createFact();
+ analysis.copy(predFact, edgeFact);
+ analysis.edgeTransfer(edge, edgeFact);
- // Apply the edge transfer function.
- Fact edgeFact = analysis.createFact();
- analysis.copy(predFact, edgeFact);
- analysis.edgeTransfer(edge, edgeFact);
+ if (DEBUG && !analysis.same(edgeFact, predFact)) {
+ debug(block, logicalPred, edge, "Edge transfer " + analysis.factToString(predFact) + " ==> "
+ + analysis.factToString(edgeFact));
+ }
- if (DEBUG && !analysis.same(edgeFact, predFact)) {
- debug(block, logicalPred, edge, "Edge transfer " + analysis.factToString(predFact) + " ==> "
- + analysis.factToString(edgeFact));
- }
+ // Merge the predecessor fact (possibly transformed
+ // by the edge transfer function)
+ // into the block's start fact.
+ if (DEBUG) {
+ if (analysis.isTop(start)) {
+ debug(block, logicalPred, edge, "\n First pred is " + analysis.factToString(edgeFact)
+ + "\n last updated at " + analysis.getLastUpdateTimestamp(predFact) + "\n");
+ } else {
+ debug(block, logicalPred, edge, "\n Meet " + analysis.factToString(start) + "\n with "
+ + analysis.factToString(edgeFact)
- // Merge the predecessor fact (possibly transformed
- // by the edge transfer function)
- // into the block's start fact.
- if (DEBUG) {
- if (analysis.isTop(start))
- debug(block, logicalPred, edge, "\n First pred is " + analysis.factToString(edgeFact)
- + "\n last updated at " + analysis.getLastUpdateTimestamp(predFact) + "\n");
- else
- debug(block, logicalPred, edge, "\n Meet " + analysis.factToString(start) + "\n with "
- + analysis.factToString(edgeFact)
-
- + "\n pred last updated at " + analysis.getLastUpdateTimestamp(predFact) + "\n");
+ + "\n pred last updated at " + analysis.getLastUpdateTimestamp(predFact) + "\n");
}
+ }
+
+ if (analysis instanceof UnconditionalValueDerefAnalysis) {
+ ((UnconditionalValueDerefAnalysis) analysis).meetInto((UnconditionalValueDerefSet) edgeFact,
+ edge, (UnconditionalValueDerefSet) start, rawPredCount == 1);
+ } else {
+ analysis.meetInto(edgeFact, edge, start);
+ }
+ analysis.setLastUpdateTimestamp(start, timestamp);
- if (analysis instanceof UnconditionalValueDerefAnalysis) {
- ((UnconditionalValueDerefAnalysis) analysis).meetInto((UnconditionalValueDerefSet) edgeFact,
- edge, (UnconditionalValueDerefSet) start, rawPredCount == 1);
- } else
- analysis.meetInto(edgeFact, edge, start);
- analysis.setLastUpdateTimestamp(start, timestamp);
-
- int pos = -1;
- if (block.getFirstInstruction() != null)
- pos = block.getFirstInstruction().getPosition();
- if (DEBUG)
- System.out.println(" [" + pos + "]==> " + analysis.factToString(start) + " @ " + timestamp
- + " \n");
+ int pos = -1;
+ if (block.getFirstInstruction() != null) {
+ pos = block.getFirstInstruction().getPosition();
+ }
+ if (DEBUG) {
+ System.out.println(" [" + pos + "]==> " + analysis.factToString(start) + " @ " + timestamp
+ + " \n");
}
}
}
- if (DEBUG)
+ if (DEBUG) {
debug(block, "start fact is " + analysis.factToString(start) + "\n");
+ }
// making a copy of result facts (so we can detect if it
// changed).
@@ -359,13 +370,13 @@ public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
analysis.copy(result, origResult);
}
- if (true || analysis.isTop(start)) {
- // Apply the transfer function.
+ // if (true || analysis.isTop(start)) {
+ // Apply the transfer function.
- analysis.transfer(block, null, start, result);
- } else {
- analysis.copy(start, result);
- }
+ analysis.transfer(block, null, start, result);
+ // } else {
+ // analysis.copy(start, result);
+ // }
if (DEBUG && SystemProperties.getBoolean("dataflow.blockdebug")) {
debug(block, "Dumping flow values for block:\n");
@@ -379,34 +390,41 @@ public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
}
// See if the result changed.
- if (DEBUG)
+ if (DEBUG) {
debug(block, "orig result is " + (origResult == null ? "TOP" : analysis.factToString(origResult)) + "\n");
+ }
boolean thisResultChanged = false;
- if (resultWasTop)
+ if (resultWasTop) {
thisResultChanged = !analysis.isTop(result);
- else
+ } else {
thisResultChanged = !analysis.same(result, origResult);
+ }
if (thisResultChanged) {
timestamp++;
- if (DEBUG)
+ if (DEBUG) {
debug(block, "result changed at timestamp " + timestamp + "\n");
+ }
if (DEBUG && !needToRecompute) {
System.out.println("I thought I didn't need to recompute");
}
change = true;
analysis.setLastUpdateTimestamp(result, timestamp);
- } else
+ } else {
analysis.setLastUpdateTimestamp(result, originalResultTimestamp);
+ }
- if (DEBUG)
+ if (DEBUG) {
debug(block,
"result is " + analysis.factToString(result) + " @ timestamp "
+ analysis.getLastUpdateTimestamp(result) + "\n");
+ }
}
analysis.finishIteration();
- if (!sawBackEdge) break;
-
+ if (!sawBackEdge) {
+ break;
+ }
+
} while (change);
if (DEBUG) {
@@ -415,17 +433,12 @@ public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
MethodGen mg = cfg.getMethodGen();
System.out.println(mg.getClassName() + "." + mg.getName() + mg.getSignature());
new RuntimeException("Quiescence achieved----------------------------------------------------------------")
- .printStackTrace(System.out);
+ .printStackTrace(System.out);
}
DEBUG = debugWas;
}
- /**
- * @param msg
- * TODO
- *
- */
private void reportAnalysis(String msg) {
String shortAnalysisName = analysis.getClass().getName();
int pkgEnd = shortAnalysisName.lastIndexOf('.');
@@ -437,8 +450,9 @@ public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
private static String blockId(BasicBlock bb) {
InstructionHandle handle = bb.getFirstInstruction();
- if (handle == null)
+ if (handle == null) {
return "" + bb.getLabel();
+ }
return bb.getLabel() + ":" + handle.getPosition() + " " + handle.getInstruction();
}
@@ -561,5 +575,3 @@ public class Dataflow<Fact, AnalysisType extends DataflowAnalysis<Fact>> {
System.out.println("}");
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/DataflowAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/DataflowAnalysis.java
index 3262812..50e10b1 100644
--- a/src/java/edu/umd/cs/findbugs/ba/DataflowAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/DataflowAnalysis.java
@@ -26,14 +26,14 @@ import org.apache.bcel.generic.InstructionHandle;
/**
* A dataflow analysis to be used with the {@link Dataflow} class.
- *
+ *
* <p>
* In order to avoid duplicating functionality (such as caching of start and
* result facts), most analyses should extend the
* {@link BasicAbstractDataflowAnalysis} or {@link AbstractDataflowAnalysis}
* classes rather than directly implementing this interface.
* </p>
- *
+ *
* @author David Hovemeyer
* @see Dataflow
*/
@@ -46,7 +46,7 @@ public interface DataflowAnalysis<Fact> {
/**
* Get the start fact for given basic block.
- *
+ *
* @param block
* the basic block
*/
@@ -54,7 +54,7 @@ public interface DataflowAnalysis<Fact> {
/**
* Get the result fact for given basic block.
- *
+ *
* @param block
* the basic block
*/
@@ -64,7 +64,7 @@ public interface DataflowAnalysis<Fact> {
* Get dataflow fact at (just before) given Location. Note "before" is meant
* in the logical sense, so for backward analyses, before means after the
* location in the control flow sense.
- *
+ *
* @param location
* the Location
* @return the dataflow value at given Location
@@ -76,7 +76,7 @@ public interface DataflowAnalysis<Fact> {
* Get the dataflow fact representing the point just after given Location.
* Note "after" is meant in the logical sense, so for backward analyses,
* after means before the location in the control flow sense.
- *
+ *
* @param location
* the Location
* @return the dataflow value after given Location
@@ -86,7 +86,7 @@ public interface DataflowAnalysis<Fact> {
/**
* Get the fact that is true on the given control edge.
- *
+ *
* @param edge
* the edge
* @return the fact that is true on the edge
@@ -122,7 +122,7 @@ public interface DataflowAnalysis<Fact> {
/**
* Return the BlockOrder specifying the order in which BasicBlocks should be
* visited in the main dataflow loop.
- *
+ *
* @param cfg
* the CFG upon which we're performing dataflow analysis
*/
@@ -138,7 +138,7 @@ public interface DataflowAnalysis<Fact> {
* might be either the entry or exit of the block, depending on whether the
* analysis is forwards or backwards), modify result to be the facts at the
* other end of the block.
- *
+ *
* @param basicBlock
* the basic block
* @param end
@@ -157,12 +157,12 @@ public interface DataflowAnalysis<Fact> {
* Edge transfer function. Modify the given fact that is true on the
* (logical) edge source to modify it so that it is true at the (logical)
* edge target.
- *
+ *
* <p>
* A do-nothing implementation is legal, and appropriate for analyses where
* branches are not significant.
* </p>
- *
+ *
* @param edge
* the Edge
* @param fact
@@ -174,7 +174,7 @@ public interface DataflowAnalysis<Fact> {
/**
* Meet a dataflow fact associated with an incoming edge into another fact.
* This is used to determine the start fact for a basic block.
- *
+ *
* @param fact
* the predecessor fact (incoming edge)
* @param edge
@@ -201,7 +201,7 @@ public interface DataflowAnalysis<Fact> {
/**
* Return a String representation of given Fact. For debugging purposes.
- *
+ *
* @param fact
* a dataflow fact
* @return String representation of the fact
@@ -209,4 +209,3 @@ public interface DataflowAnalysis<Fact> {
public String factToString(Fact fact);
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/DataflowAnalysisException.java b/src/java/edu/umd/cs/findbugs/ba/DataflowAnalysisException.java
index cef8363..0ad3d74 100644
--- a/src/java/edu/umd/cs/findbugs/ba/DataflowAnalysisException.java
+++ b/src/java/edu/umd/cs/findbugs/ba/DataflowAnalysisException.java
@@ -26,7 +26,7 @@ import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
/**
* Exception type to indicate a dataflow analysis failure.
- *
+ *
* @see Dataflow
* @see DataflowAnalysis
*/
@@ -41,7 +41,7 @@ public class DataflowAnalysisException extends CheckedAnalysisException {
/**
* Constructor.
- *
+ *
* @param msg
* message describing the reason for the exception
*/
@@ -51,7 +51,7 @@ public class DataflowAnalysisException extends CheckedAnalysisException {
/**
* Constructor from message and another Throwable object.
- *
+ *
* @param msg
* message describing the reason for the exception
* @param cause
@@ -63,7 +63,7 @@ public class DataflowAnalysisException extends CheckedAnalysisException {
/**
* Constructor from method and instruction.
- *
+ *
* @param message
* reason for the error
* @param methodGen
@@ -78,7 +78,7 @@ public class DataflowAnalysisException extends CheckedAnalysisException {
/**
* Constructor from message, method and instruction, and Throwable object
* (cause).
- *
+ *
* @param message
* reason for the error
* @param methodGen
@@ -94,4 +94,3 @@ public class DataflowAnalysisException extends CheckedAnalysisException {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/DataflowCFGPrinter.java b/src/java/edu/umd/cs/findbugs/ba/DataflowCFGPrinter.java
index 61ca6b2..776fab8 100644
--- a/src/java/edu/umd/cs/findbugs/ba/DataflowCFGPrinter.java
+++ b/src/java/edu/umd/cs/findbugs/ba/DataflowCFGPrinter.java
@@ -28,11 +28,11 @@ import org.apache.bcel.generic.InstructionHandle;
* instruction.
*/
public class DataflowCFGPrinter<Fact, AnalysisType extends DataflowAnalysis<Fact>> extends CFGPrinter {
- private Dataflow<Fact, AnalysisType> dataflow;
+ private final Dataflow<Fact, AnalysisType> dataflow;
/**
* Constructor.
- *
+ *
* @param dataflow
* the Dataflow object whose values should be used to annotate
* the printed CFG
@@ -46,7 +46,7 @@ public class DataflowCFGPrinter<Fact, AnalysisType extends DataflowAnalysis<Fact
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.CFGPrinter#edgeAnnotate(edu.umd.cs.findbugs.ba
* .Edge)
@@ -94,7 +94,7 @@ public class DataflowCFGPrinter<Fact, AnalysisType extends DataflowAnalysis<Fact
/**
* Print CFG annotated with results from given dataflow analysis.
- *
+ *
* @param <Fact>
* Dataflow fact type
* @param <AnalysisType>
@@ -112,4 +112,3 @@ public class DataflowCFGPrinter<Fact, AnalysisType extends DataflowAnalysis<Fact
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/DataflowValueChooser.java b/src/java/edu/umd/cs/findbugs/ba/DataflowValueChooser.java
index bf55736..ae98dec 100644
--- a/src/java/edu/umd/cs/findbugs/ba/DataflowValueChooser.java
+++ b/src/java/edu/umd/cs/findbugs/ba/DataflowValueChooser.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.ba;
/**
* Predicate for dataflow values.
- *
+ *
* @author David Hovemeyer
*/
public interface DataflowValueChooser<Value> {
diff --git a/src/java/edu/umd/cs/findbugs/ba/Debug.java b/src/java/edu/umd/cs/findbugs/ba/Debug.java
index 31cc8c4..e1fab6b 100644
--- a/src/java/edu/umd/cs/findbugs/ba/Debug.java
+++ b/src/java/edu/umd/cs/findbugs/ba/Debug.java
@@ -30,4 +30,3 @@ public interface Debug {
public static final boolean VERIFY_INTEGRITY = SystemProperties.getBoolean("ba.verifyIntegrity");
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/DebugRepositoryLookupFailureCallback.java b/src/java/edu/umd/cs/findbugs/ba/DebugRepositoryLookupFailureCallback.java
index ccb7db1..a26d201 100644
--- a/src/java/edu/umd/cs/findbugs/ba/DebugRepositoryLookupFailureCallback.java
+++ b/src/java/edu/umd/cs/findbugs/ba/DebugRepositoryLookupFailureCallback.java
@@ -27,23 +27,25 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* DebugRepositoryLookupFailureCallback implementation for debugging. (Test
* drivers, etc.) It just prints a message and exits.
- *
+ *
* @author David Hovemeyer
*/
public class DebugRepositoryLookupFailureCallback implements RepositoryLookupFailureCallback {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback#reportMissingClass
* (java.lang.ClassNotFoundException)
*/
+ @Override
@SuppressFBWarnings("DM_EXIT")
public void reportMissingClass(ClassNotFoundException ex) {
String missing = AbstractBugReporter.getMissingClassName(ex);
- if (missing == null || missing.charAt(0) == '[')
+ if (missing == null || missing.charAt(0) == '[') {
return;
+ }
System.out.println("Missing class");
ex.printStackTrace();
@@ -52,11 +54,12 @@ public class DebugRepositoryLookupFailureCallback implements RepositoryLookupFai
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IErrorLogger#reportMissingClass(edu.umd
* .cs.findbugs.classfile.ClassDescriptor)
*/
+ @Override
@SuppressFBWarnings("DM_EXIT")
public void reportMissingClass(ClassDescriptor classDescriptor) {
System.out.println("Missing class: " + classDescriptor);
@@ -65,11 +68,12 @@ public class DebugRepositoryLookupFailureCallback implements RepositoryLookupFai
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback#logError(java.
* lang.String)
*/
+ @Override
@SuppressFBWarnings("DM_EXIT")
public void logError(String message) {
System.err.println("Error: " + message);
@@ -78,11 +82,12 @@ public class DebugRepositoryLookupFailureCallback implements RepositoryLookupFai
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback#logError(java.
* lang.String, java.lang.Throwable)
*/
+ @Override
@SuppressFBWarnings("DM_EXIT")
public void logError(String message, Throwable e) {
if (e instanceof MissingClassException) {
@@ -106,9 +111,10 @@ public class DebugRepositoryLookupFailureCallback implements RepositoryLookupFai
/**
* Report that we skipped some analysis of a method
- *
+ *
* @param method
*/
+ @Override
public void reportSkippedAnalysis(MethodDescriptor method) {
System.err.println("Skipping " + method);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/DefaultNullnessAnnotations.java b/src/java/edu/umd/cs/findbugs/ba/DefaultNullnessAnnotations.java
index 6e24333..ac22356 100644
--- a/src/java/edu/umd/cs/findbugs/ba/DefaultNullnessAnnotations.java
+++ b/src/java/edu/umd/cs/findbugs/ba/DefaultNullnessAnnotations.java
@@ -49,8 +49,28 @@ public class DefaultNullnessAnnotations {
database.addFieldAnnotation("java.math.BigInteger", "ONE", "Ljava/math/BigInteger;", true, NullnessAnnotation.NONNULL);
database.addFieldAnnotation("java.math.BigInteger", "TEN", "Ljava/math/BigInteger;", true, NullnessAnnotation.NONNULL);
+ database.addMethodAnnotation("java.nio.file.Files", "probeContentType", "(Ljava/nio/file/Path;)Ljava/lang/String;", true,
+ NullnessAnnotation.CHECK_FOR_NULL);
+
+ database.addMethodAnnotation("java.nio.file.Path", "getRoot", "()Ljava/nio/file/Path;", false,
+ NullnessAnnotation.CHECK_FOR_NULL);
+ database.addMethodAnnotation("java.nio.file.Path", "getFileName", "()Ljava/nio/file/Path;", false,
+ NullnessAnnotation.CHECK_FOR_NULL);
+ database.addMethodAnnotation("java.nio.file.Path", "getParent", "()Ljava/nio/file/Path;", false,
+ NullnessAnnotation.CHECK_FOR_NULL);
+ database.addMethodAnnotation("java.io.File", "list", "()[Ljava/lang/String;", false,
+ NullnessAnnotation.CHECK_FOR_NULL);
+ database.addMethodAnnotation("java.io.File", "list", "(Ljava/io/FilenameFilter;)[Ljava/lang/String;", false,
+ NullnessAnnotation.CHECK_FOR_NULL);
+ database.addMethodAnnotation("java.io.File", "listFiles", "()[Ljava/io/File;", false,
+ NullnessAnnotation.CHECK_FOR_NULL);
+ database.addMethodAnnotation("java.io.File", "listFiles", "(Ljava/io/FilenameFilter;)[Ljava/io/File;", false,
+ NullnessAnnotation.CHECK_FOR_NULL);
+ database.addMethodAnnotation("java.io.File", "listFiles", "(Ljava/io/FileFilter;)[Ljava/io/File;", false,
+ NullnessAnnotation.CHECK_FOR_NULL);
+
database.addMethodAnnotation("java.lang.ref.ReferenceQueue", "poll", "()Ljava/lang/ref/Reference;", false,
NullnessAnnotation.CHECK_FOR_NULL);
database.addMethodAnnotation("java.lang.ref.Reference", "get", "()Ljava/lang/Object;", false,
@@ -278,7 +298,7 @@ public class DefaultNullnessAnnotations {
0, NullnessAnnotation.CHECK_FOR_NULL);
database.addMethodParameterAnnotation("java.util.concurrent.Phaser", "<init>", "(Ljava/util/concurrent/Phaser;I)V",
false, 0, NullnessAnnotation.CHECK_FOR_NULL);
-
+
database.addMethodAnnotation("java.util.concurrent.locks.ReadWriteLock", "readLock",
"()Ljava/util/concurrent/locks/Lock;", false, NullnessAnnotation.NONNULL);
database.addMethodAnnotation("java.util.concurrent.locks.ReadWriteLock", "writeLock",
@@ -394,13 +414,17 @@ public class DefaultNullnessAnnotations {
database.addMethodAnnotation("java.util.Objects","requireNonNull", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;",
true, NullnessAnnotation.NONNULL);
-
+
database.addMethodAnnotation("org.w3c.dom.Element","getAttribute", "(Ljava/lang/String;)Ljava/lang/String;",
false, NullnessAnnotation.NONNULL);
database.addMethodAnnotation("org.w3c.dom.Element","getAttributeNS", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
false, NullnessAnnotation.NONNULL);
-
-
+ database.addMethodAnnotation("org.w3c.dom.Element","getElementsByTagName", "(Ljava/lang/String;)Lorg/w3c/dom/NodeList;",
+ false, NullnessAnnotation.NONNULL);
+ database.addMethodAnnotation("org.w3c.dom.Element","getElementsByTagNameNS", "(Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/NodeList;",
+ false, NullnessAnnotation.NONNULL);
+
+
addEclipseSpecificAnnotations(database);
AnalysisContext.currentAnalysisContext().setMissingClassWarningsSuppressed(missingClassWarningsSuppressed);
@@ -408,13 +432,13 @@ public class DefaultNullnessAnnotations {
}
private static void addEclipseSpecificAnnotations(INullnessAnnotationDatabase db) {
-// if(true){
-// return;
-// }
+ // if(true){
+ // return;
+ // }
// usually either uses known common services or checks for unknown. Too much noise
-// db.addMethodAnnotation("org.eclipse.core.runtime.IAdaptable","getAdapter","(Ljava/lang/Class;)Ljava/lang/Object;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.runtime.IAdaptable","getAdapter","(Ljava/lang/Class;)Ljava/lang/Object;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.core.runtime.IAdapterFactory","getAdapter","(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;",
false, NullnessAnnotation.CHECK_FOR_NULL);
@@ -427,20 +451,20 @@ public class DefaultNullnessAnnotations {
false, NullnessAnnotation.CHECK_FOR_NULL);
// usually reads are in-sync with writes, so too much noise
-// db.addMethodAnnotation("org.eclipse.ui.IMemento","getChild","(Ljava/lang/String;)Lorg/eclipse/ui/IMemento;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.ui.IMemento","getID","()Ljava/lang/String;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.ui.IMemento","getInteger","(Ljava/lang/String;)Ljava/lang/Integer;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.ui.IMemento","getString","(Ljava/lang/String;)Ljava/lang/String;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.ui.IMemento","getTextData","()Ljava/lang/String;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.ui.IMemento","getChild","(Ljava/lang/String;)Lorg/eclipse/ui/IMemento;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.ui.IMemento","getID","()Ljava/lang/String;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.ui.IMemento","getInteger","(Ljava/lang/String;)Ljava/lang/Integer;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.ui.IMemento","getString","(Ljava/lang/String;)Ljava/lang/String;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.ui.IMemento","getTextData","()Ljava/lang/String;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// too seldom, usually used after job.join.
-// db.addMethodAnnotation("org.eclipse.core.runtime.jobs.Job","getResult","()Lorg/eclipse/core/runtime/IStatus;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.runtime.jobs.Job","getResult","()Lorg/eclipse/core/runtime/IStatus;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.core.runtime.FileLocator","find","(Ljava/net/URL;)Ljava/net/URL;",
false, NullnessAnnotation.CHECK_FOR_NULL);
@@ -459,22 +483,22 @@ public class DefaultNullnessAnnotations {
false, NullnessAnnotation.CHECK_FOR_NULL);
// usually not a problem - and there is a way to ask before if it is not empty
-// db.addMethodAnnotation("org.eclipse.core.runtime.IPath","lastSegment","()Ljava/lang/String;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.runtime.IPath","lastSegment","()Ljava/lang/String;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// too much noise: similar as if annotating List.get(i)
-// db.addMethodAnnotation("org.eclipse.core.runtime.IPath","segment","(I)Ljava/lang/String;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.runtime.IPath","segment","(I)Ljava/lang/String;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// too much noise: usually search results are validated
-// db.addMethodAnnotation("org.eclipse.core.resources.IContainer","findMember","(Ljava/lang/String;)Lorg/eclipse/core/resources/IResource;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.core.resources.IContainer","findMember","(Ljava/lang/String;Z)Lorg/eclipse/core/resources/IResource;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.core.resources.IContainer","findMember","(Lorg/eclipse/core/runtime/IPath;)Lorg/eclipse/core/resources/IResource;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.core.resources.IContainer","findMember","(Lorg/eclipse/core/runtime/IPath;Z)Lorg/eclipse/core/resources/IResource;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IContainer","findMember","(Ljava/lang/String;)Lorg/eclipse/core/resources/IResource;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IContainer","findMember","(Ljava/lang/String;Z)Lorg/eclipse/core/resources/IResource;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IContainer","findMember","(Lorg/eclipse/core/runtime/IPath;)Lorg/eclipse/core/resources/IResource;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IContainer","findMember","(Lorg/eclipse/core/runtime/IPath;Z)Lorg/eclipse/core/resources/IResource;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.core.resources.IContainer","getDefaultCharset","(Z)Ljava/lang/String;",
false, NullnessAnnotation.CHECK_FOR_NULL);
@@ -487,8 +511,8 @@ public class DefaultNullnessAnnotations {
db.addMethodAnnotation("org.eclipse.core.resources.IProject","getNature","(Ljava/lang/String;)Lorg/eclipse/core/resources/IProjectNature;",
false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.core.resources.IProject","getWorkingLocation","(Ljava/lang/String;)Lorg/eclipse/core/runtime/IPath;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IProject","getWorkingLocation","(Ljava/lang/String;)Lorg/eclipse/core/runtime/IPath;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.core.resources.IWorkspaceRoot","getContainerForLocation","(Lorg/eclipse/core/runtime/IPath;)Lorg/eclipse/core/resources/IContainer;",
false, NullnessAnnotation.CHECK_FOR_NULL);
@@ -497,39 +521,39 @@ public class DefaultNullnessAnnotations {
// override annotation from IResource: workspace root is always available
// XXX seems not to work at all...
-// db.addMethodAnnotation("org.eclipse.core.resources.IWorkspaceRoot","getLocation","()Lorg/eclipse/core/runtime/IPath;",
-// false, NullnessAnnotation.NONNULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IWorkspaceRoot","getLocation","()Lorg/eclipse/core/runtime/IPath;",
+ // false, NullnessAnnotation.NONNULL);
// override annotation from IResource: workspace root has no parent
db.addMethodAnnotation("org.eclipse.core.resources.IWorkspaceRoot","getParent","()Lorg/eclipse/core/resources/IContainer;",
false, NullnessAnnotation.CHECK_FOR_NULL);
// XXX too high rate of false positives, due the problem with IWorkspaceRoot.getLocation() above
-// db.addMethodAnnotation("org.eclipse.core.resources.IResource","getLocation","()Lorg/eclipse/core/runtime/IPath;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IResource","getLocation","()Lorg/eclipse/core/runtime/IPath;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// XXX too high rate of false positives, due the problem with IWorkspaceRoot.getLocation() above
-// db.addMethodAnnotation("org.eclipse.core.resources.IResource","getLocationURI","()Ljava/net/URI;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IResource","getLocationURI","()Ljava/net/URI;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.core.resources.IResource","findMarker","(J)Lorg/eclipse/core/resources/IMarker;",
false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.core.resources.IResource","getFileExtension","()Ljava/lang/String;",
false, NullnessAnnotation.CHECK_FOR_NULL);
// only true for workspace root
-// db.addMethodAnnotation("org.eclipse.core.resources.IResource","getParent","()Lorg/eclipse/core/resources/IContainer;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IResource","getParent","()Lorg/eclipse/core/resources/IContainer;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.core.resources.IResource","getPersistentProperty","(Lorg/eclipse/core/runtime/QualifiedName;)Ljava/lang/String;",
false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.core.resources.IResource","getProject","()Lorg/eclipse/core/resources/IProject;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IResource","getProject","()Lorg/eclipse/core/resources/IProject;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.core.resources.IResource","getRawLocation","()Lorg/eclipse/core/runtime/IPath;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IResource","getRawLocation","()Lorg/eclipse/core/runtime/IPath;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.core.resources.IResource","getResourceAttributes","()Lorg/eclipse/core/resources/ResourceAttributes;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IResource","getResourceAttributes","()Lorg/eclipse/core/resources/ResourceAttributes;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.core.resources.IResource","getSessionProperty","(Lorg/eclipse/core/runtime/QualifiedName;)Ljava/lang/Object;",
false, NullnessAnnotation.CHECK_FOR_NULL);
@@ -543,12 +567,12 @@ public class DefaultNullnessAnnotations {
false, NullnessAnnotation.CHECK_FOR_NULL);
// javadoc collision with IFile which claims to implement interface without returning null
-// db.addMethodAnnotation("org.eclipse.core.resources.IStorage","getFullPath","()Lorg/eclipse/core/runtime/IPath;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IStorage","getFullPath","()Lorg/eclipse/core/runtime/IPath;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// Too many false positives
-// db.addMethodAnnotation("org.eclipse.core.resources.IMarker","getAttribute","(Ljava/lang/String;)Ljava/lang/Object;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.core.resources.IMarker","getAttribute","(Ljava/lang/String;)Ljava/lang/Object;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.team.core.RepositoryProvider","getProvider","(Lorg/eclipse/core/resources/IProject;)Lorg/eclipse/team/core/RepositoryProvider;",
false, NullnessAnnotation.CHECK_FOR_NULL);
@@ -558,22 +582,22 @@ public class DefaultNullnessAnnotations {
db.addMethodAnnotation("org.eclipse.swt.widgets.Display","getCurrent","()Lorg/eclipse/swt/widgets/Display;",
false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.swt.widgets.Control","getParent","()Lorg/eclipse/swt/widgets/Composite;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.swt.widgets.Control","getParent","()Lorg/eclipse/swt/widgets/Composite;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// Usually checked or used only if set before
-// db.addMethodAnnotation("org.eclipse.swt.widgets.Widget","getData","()Ljava/lang/Object;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.swt.widgets.Widget","getData","(Ljava/lang/String;)Ljava/lang/Object;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.swt.widgets.Widget","getData","()Ljava/lang/Object;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.swt.widgets.Widget","getData","(Ljava/lang/String;)Ljava/lang/Object;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// there is a way to ask selection before - so we can't just always warn
-// db.addMethodAnnotation("org.eclipse.jface.viewers.IStructuredSelection","getFirstElement","()Ljava/lang/Object;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.viewers.IStructuredSelection","getFirstElement","()Ljava/lang/Object;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// too many false positives
-// db.addMethodAnnotation("org.eclipse.jface.viewers.ISelectionProvider","getSelection","()Lorg/eclipse/jface/viewers/ISelection;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.viewers.ISelectionProvider","getSelection","()Lorg/eclipse/jface/viewers/ISelection;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.jface.viewers.ITreeContentProvider","getParent","(Ljava/lang/Object;)Ljava/lang/Object;",
false, NullnessAnnotation.CHECK_FOR_NULL);
@@ -585,8 +609,8 @@ public class DefaultNullnessAnnotations {
false, NullnessAnnotation.CHECK_FOR_NULL);
// too many false positives
-// db.addMethodAnnotation("org.eclipse.jface.viewers.ILabelProvider","getText","(Ljava/lang/Object;)Ljava/lang/String;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.viewers.ILabelProvider","getText","(Ljava/lang/Object;)Ljava/lang/String;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.jface.viewers.IFontProvider","getFont","(Ljava/lang/Object;)Lorg/eclipse/swt/graphics/Font;",
false, NullnessAnnotation.CHECK_FOR_NULL);
@@ -618,8 +642,8 @@ public class DefaultNullnessAnnotations {
false, NullnessAnnotation.CHECK_FOR_NULL);
// too many false positives
-// db.addMethodAnnotation("org.eclipse.jface.viewers.ITableLabelProvider","getColumnText","(Ljava/lang/Object;I)Ljava/lang/String;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.viewers.ITableLabelProvider","getColumnText","(Ljava/lang/Object;I)Ljava/lang/String;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
db.addMethodAnnotation("org.eclipse.ui.IWorkbenchPage","findView","(Ljava/lang/String;)Lorg/eclipse/ui/IViewPart;",
false, NullnessAnnotation.CHECK_FOR_NULL);
@@ -630,58 +654,58 @@ public class DefaultNullnessAnnotations {
db.addMethodAnnotation("org.eclipse.ui.IWorkbenchPage","findViewReference","(Ljava/lang/String;Ljava/lang/String;)Lorg/eclipse/ui/IViewReference;",
false, NullnessAnnotation.CHECK_FOR_NULL);
- // Too many false positives if used from editor, which is active anyway
-// db.addMethodAnnotation("org.eclipse.ui.IWorkbenchPage","getActiveEditor","()Lorg/eclipse/ui/IEditorPart;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // Too many false positives if used from editor, which is active anyway
+ // db.addMethodAnnotation("org.eclipse.ui.IWorkbenchPage","getActiveEditor","()Lorg/eclipse/ui/IEditorPart;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// too many false positives
-// db.addMethodAnnotation("org.eclipse.ui.IWorkbenchPage","openEditor","(Lorg/eclipse/ui/IEditorInput;Ljava/lang/String;)Lorg/eclipse/ui/IEditorPart;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.ui.IWorkbenchPage","openEditor","(Lorg/eclipse/ui/IEditorInput;Ljava/lang/String;ZI)Lorg/eclipse/ui/IEditorPart;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.ui.IWorkbenchPage","openEditor","(Lorg/eclipse/ui/IEditorInput;Ljava/lang/String;)Lorg/eclipse/ui/IEditorPart;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.ui.IWorkbenchPage","openEditor","(Lorg/eclipse/ui/IEditorInput;Ljava/lang/String;ZI)Lorg/eclipse/ui/IEditorPart;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.ui.IWorkbenchWindow","getActivePage","()Lorg/eclipse/ui/IWorkbenchPage;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.ui.IWorkbenchWindow","getActivePage","()Lorg/eclipse/ui/IWorkbenchPage;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// too much noise because if a class is used in UI context, there is an active window.
-// db.addMethodAnnotation("org.eclipse.ui.IWorkbench","getActiveWorkbenchWindow","()Lorg/eclipse/ui/IWorkbenchWindow;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-
-// db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getContainer","()Lorg/eclipse/jface/wizard/IWizardContainer;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getDialogSettings","()Lorg/eclipse/jface/dialogs/IDialogSettings;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getNextPage","(Lorg/eclipse/jface/wizard/IWizardPage;)Lorg/eclipse/jface/wizard/IWizardPage;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getPreviousPage","(Lorg/eclipse/jface/wizard/IWizardPage;)Lorg/eclipse/jface/wizard/IWizardPage;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getWindowTitle","()Ljava/lang/String;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getPage","(Ljava/lang/String;)Lorg/eclipse/jface/wizard/IWizardPage;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-//
-// db.addMethodAnnotation("org.eclipse.jface.wizard.IWizardPage","getNextPage","()Lorg/eclipse/jface/wizard/IWizardPage;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.jface.wizard.IWizardPage","getPreviousPage","()Lorg/eclipse/jface/wizard/IWizardPage;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.jface.wizard.IWizardPage","getWizard","()Lorg/eclipse/jface/wizard/IWizard;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.ui.IWorkbench","getActiveWorkbenchWindow","()Lorg/eclipse/ui/IWorkbenchWindow;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+
+ // db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getContainer","()Lorg/eclipse/jface/wizard/IWizardContainer;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getDialogSettings","()Lorg/eclipse/jface/dialogs/IDialogSettings;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getNextPage","(Lorg/eclipse/jface/wizard/IWizardPage;)Lorg/eclipse/jface/wizard/IWizardPage;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getPreviousPage","(Lorg/eclipse/jface/wizard/IWizardPage;)Lorg/eclipse/jface/wizard/IWizardPage;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getWindowTitle","()Ljava/lang/String;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.wizard.IWizard","getPage","(Ljava/lang/String;)Lorg/eclipse/jface/wizard/IWizardPage;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ //
+ // db.addMethodAnnotation("org.eclipse.jface.wizard.IWizardPage","getNextPage","()Lorg/eclipse/jface/wizard/IWizardPage;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.wizard.IWizardPage","getPreviousPage","()Lorg/eclipse/jface/wizard/IWizardPage;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.wizard.IWizardPage","getWizard","()Lorg/eclipse/jface/wizard/IWizard;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
// usually statically assigned resources - so either it never worked or always ok. Too noisy
-// db.addMethodAnnotation("org.eclipse.jface.resource.ImageRegistry","getDescriptor","(Ljava/lang/String;)Lorg/eclipse/jface/resource/ImageDescriptor;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.jface.resource.ImageRegistry","get","(Ljava/lang/String;)Lorg/eclipse/swt/graphics/Image;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-//
-// db.addMethodAnnotation("org.eclipse.jface.resource.ColorRegistry","get","(Ljava/lang/String;)Lorg/eclipse/swt/graphics/Color;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-// db.addMethodAnnotation("org.eclipse.jface.resource.ColorRegistry","getRGB","(Ljava/lang/String;)Lorg/eclipse/swt/graphics/RGB;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-//
-// db.addMethodAnnotation("org.eclipse.jface.resource.JFaceResources","getImage","(Ljava/lang/String;)Lorg/eclipse/swt/graphics/Image;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
-
-// db.addMethodAnnotation("org.eclipse.jface.action.IAction","getImageDescriptor","()Lorg/eclipse/jface/resource/ImageDescriptor;",
-// false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.resource.ImageRegistry","getDescriptor","(Ljava/lang/String;)Lorg/eclipse/jface/resource/ImageDescriptor;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.resource.ImageRegistry","get","(Ljava/lang/String;)Lorg/eclipse/swt/graphics/Image;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ //
+ // db.addMethodAnnotation("org.eclipse.jface.resource.ColorRegistry","get","(Ljava/lang/String;)Lorg/eclipse/swt/graphics/Color;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ // db.addMethodAnnotation("org.eclipse.jface.resource.ColorRegistry","getRGB","(Ljava/lang/String;)Lorg/eclipse/swt/graphics/RGB;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+ //
+ // db.addMethodAnnotation("org.eclipse.jface.resource.JFaceResources","getImage","(Ljava/lang/String;)Lorg/eclipse/swt/graphics/Image;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
+
+ // db.addMethodAnnotation("org.eclipse.jface.action.IAction","getImageDescriptor","()Lorg/eclipse/jface/resource/ImageDescriptor;",
+ // false, NullnessAnnotation.CHECK_FOR_NULL);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/DepthFirstSearch.java b/src/java/edu/umd/cs/findbugs/ba/DepthFirstSearch.java
index b40a4f6..0a7a389 100644
--- a/src/java/edu/umd/cs/findbugs/ba/DepthFirstSearch.java
+++ b/src/java/edu/umd/cs/findbugs/ba/DepthFirstSearch.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.ba;
/**
* Algorithm to perform a depth first search on a CFG.
- *
+ *
* @see CFG
* @author David Hovemeyer
*/
@@ -30,7 +30,7 @@ public class DepthFirstSearch extends edu.umd.cs.findbugs.graph.DepthFirstSearch
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG to perform the depth first search on
*/
@@ -47,4 +47,3 @@ public class DepthFirstSearch extends edu.umd.cs.findbugs.graph.DepthFirstSearch
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/DominatorsAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/DominatorsAnalysis.java
index 583150e..ab86a43 100644
--- a/src/java/edu/umd/cs/findbugs/ba/DominatorsAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/DominatorsAnalysis.java
@@ -21,17 +21,17 @@ package edu.umd.cs.findbugs.ba;
/**
* Dataflow analysis to compute dominator sets for a CFG.
- *
+ *
* @author David Hovemeyer
* @see CFG
* @see AbstractDominatorsAnalysis
*/
public class DominatorsAnalysis extends AbstractDominatorsAnalysis {
- private DepthFirstSearch dfs;
+ private final DepthFirstSearch dfs;
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG to compute dominator relationships for
* @param dfs
@@ -44,10 +44,12 @@ public class DominatorsAnalysis extends AbstractDominatorsAnalysis {
this.dfs = dfs;
}
+ @Override
public boolean isForwards() {
return true;
}
+ @Override
public BlockOrder getBlockOrder(CFG cfg) {
return new ReversePostOrder(cfg, dfs);
}
@@ -92,4 +94,3 @@ public class DominatorsAnalysis extends AbstractDominatorsAnalysis {
// }
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/Edge.java b/src/java/edu/umd/cs/findbugs/ba/Edge.java
index 9ce5b36..da9f7f5 100644
--- a/src/java/edu/umd/cs/findbugs/ba/Edge.java
+++ b/src/java/edu/umd/cs/findbugs/ba/Edge.java
@@ -34,7 +34,7 @@ import edu.umd.cs.findbugs.graph.AbstractEdge;
/**
* An edge of a control flow graph.
- *
+ *
* @author David Hovemeyer
* @see BasicBlock
* @see CFG
@@ -66,7 +66,7 @@ public class Edge extends AbstractEdge<Edge, BasicBlock> implements EdgeTypes, D
/**
* Constructor.
- *
+ *
* @param source
* source basic block
* @param dest
@@ -111,7 +111,7 @@ public class Edge extends AbstractEdge<Edge, BasicBlock> implements EdgeTypes, D
/**
* Return if given edge flag is set.
- *
+ *
* @param flag
* the edge flag
* @return true if the flag is set, false otherwise
@@ -129,8 +129,9 @@ public class Edge extends AbstractEdge<Edge, BasicBlock> implements EdgeTypes, D
@Override
public boolean equals(Object o) {
- if (o == null || this.getClass() != o.getClass())
+ if (o == null || this.getClass() != o.getClass()) {
return false;
+ }
Edge other = (Edge) o;
return this.getSource() == other.getSource() && this.getTarget() == other.getTarget()
&& this.getType() == other.getType();
@@ -147,8 +148,9 @@ public class Edge extends AbstractEdge<Edge, BasicBlock> implements EdgeTypes, D
@Override
public int compareTo(Edge other) {
int cmp = super.compareTo(other);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return type - other.type;
}
@@ -164,8 +166,9 @@ public class Edge extends AbstractEdge<Edge, BasicBlock> implements EdgeTypes, D
InstructionHandle sourceInstruction = source.getLastInstruction();
InstructionHandle targetInstruction = target.getFirstInstruction();
- if (targetInstruction == null || sourceInstruction == null)
+ if (targetInstruction == null || sourceInstruction == null) {
return false;
+ }
return targetInstruction.getPosition() < sourceInstruction.getPosition();
}
@@ -179,8 +182,9 @@ public class Edge extends AbstractEdge<Edge, BasicBlock> implements EdgeTypes, D
InstructionHandle sourceInstruction = source.getLastInstruction();
- if (sourceInstruction == null)
+ if (sourceInstruction == null) {
return false;
+ }
return positions.contains(sourceInstruction.getPosition());
}
@@ -215,9 +219,9 @@ public class Edge extends AbstractEdge<Edge, BasicBlock> implements EdgeTypes, D
buf.append(targetInstruction.getPosition());
buf.append(']');
} else if (source.isExceptionThrower()) {
- if (type == FALL_THROUGH_EDGE)
+ if (type == FALL_THROUGH_EDGE) {
buf.append(" [successful check]");
- else {
+ } else {
buf.append(" [failed check for ");
buf.append(source.getExceptionThrower().getPosition());
if (targetInstruction != null) {
@@ -274,37 +278,37 @@ public class Edge extends AbstractEdge<Edge, BasicBlock> implements EdgeTypes, D
int stringToEdgeType(String s) {
s = s.toUpperCase(Locale.ENGLISH);
- if (s.equals("FALL_THROUGH"))
+ if ("FALL_THROUGH".equals(s)) {
return FALL_THROUGH_EDGE;
- else if (s.equals("IFCMP"))
+ } else if ("IFCMP".equals(s)) {
return IFCMP_EDGE;
- else if (s.equals("SWITCH"))
+ } else if ("SWITCH".equals(s)) {
return SWITCH_EDGE;
- else if (s.equals("SWITCH_DEFAULT"))
+ } else if ("SWITCH_DEFAULT".equals(s)) {
return SWITCH_DEFAULT_EDGE;
- else if (s.equals("JSR"))
+ } else if ("JSR".equals(s)) {
return JSR_EDGE;
- else if (s.equals("RET"))
+ } else if ("RET".equals(s)) {
return RET_EDGE;
- else if (s.equals("GOTO"))
+ } else if ("GOTO".equals(s)) {
return GOTO_EDGE;
- else if (s.equals("RETURN"))
+ } else if ("RETURN".equals(s)) {
return RETURN_EDGE;
- else if (s.equals("UNHANDLED_EXCEPTION"))
+ } else if ("UNHANDLED_EXCEPTION".equals(s)) {
return UNHANDLED_EXCEPTION_EDGE;
- else if (s.equals("HANDLED_EXCEPTION"))
+ } else if ("HANDLED_EXCEPTION".equals(s)) {
return HANDLED_EXCEPTION_EDGE;
- else if (s.equals("START"))
+ } else if ("START".equals(s)) {
return START_EDGE;
- else if (s.equals("BACKEDGE_TARGET_EDGE"))
+ } else if ("BACKEDGE_TARGET_EDGE".equals(s)) {
return BACKEDGE_TARGET_EDGE;
- else if (s.equals("BACKEDGE_SOURCE_EDGE"))
+ } else if ("BACKEDGE_SOURCE_EDGE".equals(s)) {
return BACKEDGE_SOURCE_EDGE;
- else if (s.equals("EXIT_EDGE"))
+ } else if ("EXIT_EDGE".equals(s)) {
return EXIT_EDGE;
- else
+ } else {
throw new IllegalArgumentException("Unknown edge type: " + s);
+ }
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/EdgeChooser.java b/src/java/edu/umd/cs/findbugs/ba/EdgeChooser.java
index 245f5d6..dc1f894 100644
--- a/src/java/edu/umd/cs/findbugs/ba/EdgeChooser.java
+++ b/src/java/edu/umd/cs/findbugs/ba/EdgeChooser.java
@@ -21,13 +21,13 @@ package edu.umd.cs.findbugs.ba;
/**
* Interface for choosing CFG Edges.
- *
+ *
* @author David Hovemeyer
*/
public interface EdgeChooser {
/**
* Return whether or not given Edge should be chosen.
- *
+ *
* @param edge
* the Edge
* @return true if the Edge should be chosen, false otherwise
diff --git a/src/java/edu/umd/cs/findbugs/ba/EdgeTypes.java b/src/java/edu/umd/cs/findbugs/ba/EdgeTypes.java
index 7a3dd30..e97bca0 100644
--- a/src/java/edu/umd/cs/findbugs/ba/EdgeTypes.java
+++ b/src/java/edu/umd/cs/findbugs/ba/EdgeTypes.java
@@ -22,7 +22,7 @@ package edu.umd.cs.findbugs.ba;
/**
* Constants defining the type of control flow edges, as well as flags defining
* additional information about the edges.
- *
+ *
* @see Edge
*/
public interface EdgeTypes {
@@ -143,4 +143,3 @@ public interface EdgeTypes {
public static final int EXPLICIT_EXCEPTIONS_FLAG = 2;
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/ba/ExceptionHandlerMap.java b/src/java/edu/umd/cs/findbugs/ba/ExceptionHandlerMap.java
index 023f613..3f94464 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ExceptionHandlerMap.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ExceptionHandlerMap.java
@@ -39,18 +39,18 @@ import edu.umd.cs.findbugs.ba.type.TypeMerger;
* to lists of CodeExceptionGen objects. This class also maps instructions which
* are the start of exception handlers to the CodeExceptionGen object
* representing the handler.
- *
+ *
* @author David Hovemeyer
*/
public class ExceptionHandlerMap {
- private IdentityHashMap<InstructionHandle, List<CodeExceptionGen>> codeToHandlerMap;
+ private final IdentityHashMap<InstructionHandle, List<CodeExceptionGen>> codeToHandlerMap;
- private IdentityHashMap<InstructionHandle, CodeExceptionGen> startInstructionToHandlerMap;
+ private final IdentityHashMap<InstructionHandle, CodeExceptionGen> startInstructionToHandlerMap;
- private TypeMerger merger;
+ private final TypeMerger merger;
/**
* Constructor.
- *
+ *
* @param methodGen
* the method to build the map for
*/
@@ -66,7 +66,7 @@ public class ExceptionHandlerMap {
* specified to handle exceptions for the instruction whose handle is given.
* Note that the handlers in the returned list are <b>in order of
* priority</b>, as defined in the method's exception handler table.
- *
+ *
* @param handle
* the handle of the instruction we want the exception handlers
* for
@@ -80,7 +80,7 @@ public class ExceptionHandlerMap {
/**
* If the given instruction is the start of an exception handler, get the
* CodeExceptionGen object representing the handler.
- *
+ *
* @param start
* the instruction
* @return the CodeExceptionGen object, or null if the instruction is not
@@ -115,8 +115,9 @@ public class ExceptionHandlerMap {
// i.e., an ANY handler, or catch(Throwable...),
// then no further (lower-priority)
// handlers are reachable from the instruction.
- if (Hierarchy.isUniversalExceptionHandler(exceptionHandler.getCatchType()))
+ if (Hierarchy.isUniversalExceptionHandler(exceptionHandler.getCatchType())) {
break handlerLoop;
+ }
}
}
@@ -125,13 +126,18 @@ public class ExceptionHandlerMap {
}
public static CodeExceptionGen merge(@CheckForNull TypeMerger m, CodeExceptionGen e1, CodeExceptionGen e2) {
- if (e1 == null) return e2;
- if (e2 == null) return e1;
- if (m == null)
+ if (e1 == null) {
+ return e2;
+ }
+ if (e2 == null) {
+ return e1;
+ }
+ if (m == null) {
return e1;
+ }
if ( ! e1.getHandlerPC().equals( e2.getHandlerPC() ) ){
// log error
- return e1;
+ return e1;
}
try {
Type t = m.mergeTypes(e1.getCatchType(), e2.getCatchType());
@@ -143,7 +149,7 @@ public class ExceptionHandlerMap {
}
}
-
+
private void addExceptionHandler(CodeExceptionGen exceptionHandler) {
InstructionHandle handlerPC = exceptionHandler.getHandlerPC();
CodeExceptionGen existing = startInstructionToHandlerMap.get(handlerPC);
@@ -152,7 +158,7 @@ public class ExceptionHandlerMap {
}
startInstructionToHandlerMap.put(handlerPC, exceptionHandler);
}
-
+
private void addHandler(InstructionHandle handle, CodeExceptionGen exceptionHandler) {
List<CodeExceptionGen> handlerList = codeToHandlerMap.get(handle);
if (handlerList == null) {
@@ -163,4 +169,3 @@ public class ExceptionHandlerMap {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/FieldSummary.java b/src/java/edu/umd/cs/findbugs/ba/FieldSummary.java
index e9b4740..39f6c73 100644
--- a/src/java/edu/umd/cs/findbugs/ba/FieldSummary.java
+++ b/src/java/edu/umd/cs/findbugs/ba/FieldSummary.java
@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Set;
import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.apache.bcel.generic.Type;
@@ -63,8 +64,9 @@ public class FieldSummary {
private boolean complete = false;
public OpcodeStack.Item getSummary(XField field) {
- if (field == null)
+ if (field == null) {
return new OpcodeStack.Item();
+ }
OpcodeStack.Item result = summary.get(field);
if (result == null || field.isVolatile()) {
@@ -83,10 +85,12 @@ public class FieldSummary {
while (true) {
XClass cx = Global.getAnalysisCache().getClassAnalysis(XClass.class, c);
c = cx.getSuperclassDescriptor();
- if (c == null)
+ if (c == null) {
return false;
- if (callsOverriddenMethodsFromConstructor(c))
+ }
+ if (callsOverriddenMethodsFromConstructor(c)) {
return true;
+ }
}
} catch (CheckedAnalysisException e) {
return false;
@@ -107,8 +111,9 @@ public class FieldSummary {
public Set<ProgramPoint> getCalledFromSuperConstructor(ClassDescriptor superClass, XMethod calledFromConstructor) {
- if (!callsOverriddenMethodsFromConstructor.contains(superClass))
+ if (!callsOverriddenMethodsFromConstructor.contains(superClass)) {
return Collections.emptySet();
+ }
for (Map.Entry<XMethod, Set<ProgramPoint>> e : selfMethodsCalledFromConstructor.entrySet()) {
XMethod m = e.getKey();
if (m.getName().equals(calledFromConstructor.getName())
@@ -117,8 +122,9 @@ public class FieldSummary {
String sig2 = calledFromConstructor.getSignature();
sig1 = sig1.substring(0, sig1.indexOf(')'));
sig2 = sig2.substring(0, sig2.indexOf(')'));
- if (sig1.equals(sig2))
+ if (sig1.equals(sig2)) {
return e.getValue();
+ }
}
}
@@ -127,8 +133,9 @@ public class FieldSummary {
}
public void setFieldsWritten(XMethod method, Collection<XField> fields) {
- if (fields.isEmpty())
+ if (fields.isEmpty()) {
return;
+ }
if (fields.size() == 1) {
fieldsWritten.put(method, Collections.singleton(Util.first(fields)));
return;
@@ -137,23 +144,28 @@ public class FieldSummary {
fieldsWritten.put(method, Util.makeSmallHashSet(fields));
}
- public Set<XField> getFieldsWritten(XMethod method) {
+ public Set<XField> getFieldsWritten(@Nullable XMethod method) {
Set<XField> result = fieldsWritten.get(method);
- if (result == null)
+ if (result == null) {
return Collections.<XField> emptySet();
+ }
return result;
}
public boolean isWrittenOutsideOfConstructor(XField field) {
- if (field.isFinal())
+ if (field.isFinal()) {
return false;
- if (writtenOutsideOfConstructor.contains(field))
+ }
+ if (writtenOutsideOfConstructor.contains(field)) {
return true;
- if (!AnalysisContext.currentAnalysisContext().unreadFieldsAvailable())
+ }
+ if (!AnalysisContext.currentAnalysisContext().unreadFieldsAvailable()) {
return true;
+ }
UnreadFieldsData unreadFields = AnalysisContext.currentAnalysisContext().getUnreadFieldsData();
- if (unreadFields.isReflexive(field))
+ if (unreadFields.isReflexive(field)) {
return true;
+ }
return false;
}
@@ -228,15 +240,13 @@ public class FieldSummary {
return complete;
}
- /**
- * @param method
- * @param methodOperand
- */
public void sawSuperCall(XMethod from, XMethod constructorInSuperClass) {
- if (constructorInSuperClass == null || from == null)
+ if (constructorInSuperClass == null || from == null) {
return;
- if (constructorInSuperClass.getSignature().equals("()V"))
+ }
+ if ("()V".equals(constructorInSuperClass.getSignature())) {
return;
+ }
nonVoidSuperConstructorsCalled.put(from, constructorInSuperClass);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/FileSourceFileDataSource.java b/src/java/edu/umd/cs/findbugs/ba/FileSourceFileDataSource.java
index 65df3f4..101ce4f 100644
--- a/src/java/edu/umd/cs/findbugs/ba/FileSourceFileDataSource.java
+++ b/src/java/edu/umd/cs/findbugs/ba/FileSourceFileDataSource.java
@@ -29,23 +29,25 @@ import java.io.InputStream;
* Data source for source files which are stored in the filesystem.
*/
public class FileSourceFileDataSource implements SourceFileDataSource {
- private String fileName;
+ private final String fileName;
public FileSourceFileDataSource(String fileName) {
this.fileName = fileName;
}
+ @Override
public InputStream open() throws IOException {
return new BufferedInputStream(new FileInputStream(fileName));
}
+ @Override
public String getFullFileName() {
return fileName;
}
- public long getLastModified() {
+ @Override
+ public long getLastModified() {
return new File(fileName).lastModified();
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ForwardDataflowAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/ForwardDataflowAnalysis.java
index 5039851..8e391f6 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ForwardDataflowAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ForwardDataflowAnalysis.java
@@ -22,17 +22,18 @@ package edu.umd.cs.findbugs.ba;
/**
* Abstract base class for forward dataflow analyses. Provides convenient
* implementations for isForwards() and getBlockOrder() methods.
- *
+ *
* @author David Hovemeyer
* @see Dataflow
* @see DataflowAnalysis
*/
public abstract class ForwardDataflowAnalysis<Fact> extends AbstractDataflowAnalysis<Fact> {
- private DepthFirstSearch dfs;
+ private final DepthFirstSearch dfs;
public ForwardDataflowAnalysis(DepthFirstSearch dfs) {
- if (dfs == null)
+ if (dfs == null) {
throw new IllegalArgumentException();
+ }
this.dfs = dfs;
}
@@ -40,13 +41,14 @@ public abstract class ForwardDataflowAnalysis<Fact> extends AbstractDataflowAnal
return dfs;
}
+ @Override
public boolean isForwards() {
return true;
}
+ @Override
public BlockOrder getBlockOrder(CFG cfg) {
return new ReversePostOrder(cfg, dfs);
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/Frame.java b/src/java/edu/umd/cs/findbugs/ba/Frame.java
index ef5f957..6cb0dd1 100644
--- a/src/java/edu/umd/cs/findbugs/ba/Frame.java
+++ b/src/java/edu/umd/cs/findbugs/ba/Frame.java
@@ -111,8 +111,9 @@ public abstract class Frame<ValueType> {
public Frame(int numLocals) {
this.numLocals = numLocals;
this.slotList = new ArrayList<ValueType>(numLocals + DEFAULT_STACK_CAPACITY);
- for (int i = 0; i < numLocals; ++i)
+ for (int i = 0; i < numLocals; ++i) {
slotList.add(null);
+ }
}
/**
@@ -171,10 +172,12 @@ public abstract class Frame<ValueType> {
* the ValueType to push
*/
public void pushValue(ValueType value) {
- if (VERIFY_INTEGRITY && value == null)
+ if (VERIFY_INTEGRITY && value == null) {
throw new IllegalArgumentException();
- if (!isValid())
+ }
+ if (!isValid()) {
throw new IllegalStateException("accessing top or bottom frame");
+ }
slotList.add(value);
}
@@ -186,10 +189,12 @@ public abstract class Frame<ValueType> {
* if the Java operand stack is empty
*/
public ValueType popValue() throws DataflowAnalysisException {
- if (!isValid())
+ if (!isValid()) {
throw new DataflowAnalysisException("accessing top or bottom frame");
- if (slotList.size() == numLocals)
+ }
+ if (slotList.size() == numLocals) {
throw new DataflowAnalysisException("operand stack empty");
+ }
return slotList.remove(slotList.size() - 1);
}
@@ -200,11 +205,13 @@ public abstract class Frame<ValueType> {
* if the Java operand stack is empty
*/
public ValueType getTopValue() throws DataflowAnalysisException {
- if (!isValid())
+ if (!isValid()) {
throw new DataflowAnalysisException("accessing top or bottom frame");
+ }
assert slotList.size() >= numLocals;
- if (slotList.size() == numLocals)
+ if (slotList.size() == numLocals) {
throw new DataflowAnalysisException("operand stack is empty");
+ }
return slotList.get(slotList.size() - 1);
}
@@ -215,8 +222,9 @@ public abstract class Frame<ValueType> {
*/
public void getTopStackWords(ValueType[] valueList) throws DataflowAnalysisException {
int stackDepth = getStackDepth();
- if (valueList.length > stackDepth)
+ if (valueList.length > stackDepth) {
throw new DataflowAnalysisException("not enough values on stack");
+ }
int numSlots = slotList.size();
for (int i = numSlots - valueList.length, j = 0; i < numSlots; ++i, ++j) {
valueList[j] = slotList.get(i);
@@ -231,13 +239,16 @@ public abstract class Frame<ValueType> {
* 0)
*/
public ValueType getStackValue(int loc) throws DataflowAnalysisException {
- if (!isValid())
+ if (!isValid()) {
throw new DataflowAnalysisException("Accessing TOP or BOTTOM frame!");
+ }
int stackDepth = getStackDepth();
- if (loc >= stackDepth)
+ if (loc >= stackDepth) {
throw new DataflowAnalysisException("not enough values on stack: access=" + loc + ", avail=" + stackDepth);
- if (loc < 0)
+ }
+ if (loc < 0) {
throw new DataflowAnalysisException("can't get position " + loc + " of stack");
+ }
int pos = slotList.size() - (loc + 1);
return slotList.get(pos);
}
@@ -251,8 +262,9 @@ public abstract class Frame<ValueType> {
*/
public int getStackLocation(int loc) throws DataflowAnalysisException {
int stackDepth = getStackDepth();
- if (loc >= stackDepth)
+ if (loc >= stackDepth) {
throw new DataflowAnalysisException("not enough values on stack: access=" + loc + ", avail=" + stackDepth);
+ }
return slotList.size() - (loc + 1);
}
@@ -292,8 +304,9 @@ public abstract class Frame<ValueType> {
*/
public int getInstanceStackLocation(Instruction ins, ConstantPoolGen cpg) throws DataflowAnalysisException {
int numConsumed = ins.consumeStack(cpg);
- if (numConsumed == Constants.UNPREDICTABLE)
+ if (numConsumed == Constants.UNPREDICTABLE) {
throw new DataflowAnalysisException("Unpredictable stack consumption in " + ins);
+ }
return numConsumed - 1;
}
@@ -313,10 +326,12 @@ public abstract class Frame<ValueType> {
throw new DataflowAnalysisException("Accessing invalid frame at " + ins);
}
int numConsumed = ins.consumeStack(cpg);
- if (numConsumed == Constants.UNPREDICTABLE)
+ if (numConsumed == Constants.UNPREDICTABLE) {
throw new DataflowAnalysisException("Unpredictable stack consumption in " + ins);
- if (numConsumed > getStackDepth())
+ }
+ if (numConsumed > getStackDepth()) {
throw new DataflowAnalysisException("Stack underflow " + ins);
+ }
return getNumSlots() - numConsumed;
}
@@ -349,8 +364,9 @@ public abstract class Frame<ValueType> {
public int getNumArgumentsIncludingObjectInstance(InvokeInstruction ins, ConstantPoolGen cpg)
throws DataflowAnalysisException {
int numConsumed = ins.consumeStack(cpg);
- if (numConsumed == Constants.UNPREDICTABLE)
+ if (numConsumed == Constants.UNPREDICTABLE) {
throw new DataflowAnalysisException("Unpredictable stack consumption in " + ins);
+ }
return numConsumed;
}
@@ -389,8 +405,9 @@ public abstract class Frame<ValueType> {
*/
public ValueType getArgument(InvokeInstruction ins, ConstantPoolGen cpg, int i, SignatureParser sigParser)
throws DataflowAnalysisException {
- if (i >= sigParser.getNumParameters())
+ if (i >= sigParser.getNumParameters()) {
throw new IllegalArgumentException("requesting parameter # " + i + " of " + sigParser);
+ }
return getStackValue(sigParser.getSlotsFromTopOfStackForParameter(i));
}
@@ -406,8 +423,9 @@ public abstract class Frame<ValueType> {
* @return slot containing the argument value
*/
public int getArgumentSlot(int i, int numArguments) {
- if (i >= numArguments)
+ if (i >= numArguments) {
throw new IllegalArgumentException();
+ }
return (slotList.size() - numArguments) + i;
}
@@ -426,8 +444,9 @@ public abstract class Frame<ValueType> {
*/
public ValueType getOperand(StackConsumer ins, ConstantPoolGen cpg, int i) throws DataflowAnalysisException {
int numOperands = ins.consumeStack(cpg);
- if (numOperands == Constants.UNPREDICTABLE)
+ if (numOperands == Constants.UNPREDICTABLE) {
throw new DataflowAnalysisException("Unpredictable stack consumption in " + ins);
+ }
return getStackValue((numOperands - 1) - i);
}
@@ -453,8 +472,9 @@ public abstract class Frame<ValueType> {
for (int i = 0; i < sigParser.getNumParameters(); ++i) {
ValueType value = getArgument(invokeInstruction, cpg, i, sigParser);
- if (chooser.choose(value))
+ if (chooser.choose(value)) {
chosenArgSet.set(i);
+ }
}
return chosenArgSet;
@@ -465,11 +485,13 @@ public abstract class Frame<ValueType> {
* the frame.
*/
public void clearStack() {
- if (!isValid())
+ if (!isValid()) {
throw new IllegalStateException("accessing top or bottom frame");
+ }
assert slotList.size() >= numLocals;
- if (slotList.size() > numLocals)
+ if (slotList.size() > numLocals) {
slotList.subList(numLocals, slotList.size()).clear();
+ }
}
/**
@@ -494,11 +516,14 @@ public abstract class Frame<ValueType> {
}
public boolean contains(ValueType value) {
- if (!isValid())
+ if (!isValid()) {
throw new IllegalStateException("accessing top or bottom frame");
- for (ValueType v : slotList)
- if (v.equals(value))
+ }
+ for (ValueType v : slotList) {
+ if (v.equals(value)) {
return true;
+ }
+ }
return false;
}
@@ -510,8 +535,9 @@ public abstract class Frame<ValueType> {
* @return the value in the slot
*/
public ValueType getValue(int n) {
- if (!isValid())
+ if (!isValid()) {
throw new IllegalStateException("accessing top or bottom frame");
+ }
return slotList.get(n);
}
@@ -524,10 +550,12 @@ public abstract class Frame<ValueType> {
* the value to set
*/
public void setValue(int n, ValueType value) {
- if (VERIFY_INTEGRITY && value == null)
+ if (VERIFY_INTEGRITY && value == null) {
throw new IllegalArgumentException();
- if (!isValid())
+ }
+ if (!isValid()) {
throw new IllegalStateException("accessing top or bottom frame");
+ }
slotList.set(n, value);
}
@@ -540,24 +568,31 @@ public abstract class Frame<ValueType> {
* @return true if the frames are the same, false otherwise
*/
public boolean sameAs(Frame<ValueType> other) {
- if (isTop != other.isTop)
+ if (isTop != other.isTop) {
return false;
+ }
- if (isTop && other.isTop)
+ if (isTop && other.isTop) {
return true;
+ }
- if (isBottom != other.isBottom)
+ if (isBottom != other.isBottom) {
return false;
+ }
- if (isBottom && other.isBottom)
+ if (isBottom && other.isBottom) {
return true;
+ }
- if (getNumSlots() != other.getNumSlots())
+ if (getNumSlots() != other.getNumSlots()) {
return false;
+ }
- for (int i = 0; i < getNumSlots(); ++i)
- if (!getValue(i).equals(other.getValue(i)))
+ for (int i = 0; i < getNumSlots(); ++i) {
+ if (!getValue(i).equals(other.getValue(i))) {
return false;
+ }
+ }
return true;
}
@@ -573,12 +608,14 @@ public abstract class Frame<ValueType> {
if (true) {
int size = slotList.size();
if (size == other.slotList.size()) {
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < size; i++) {
slotList.set(i, other.slotList.get(i));
+ }
} else {
slotList.clear();
- for (ValueType v : other.slotList)
+ for (ValueType v : other.slotList) {
slotList.add(v);
+ }
}
} else {
slotList.clear();
@@ -603,10 +640,12 @@ public abstract class Frame<ValueType> {
*/
@Override
public String toString() {
- if (isTop())
+ if (isTop()) {
return "[TOP]";
- if (isBottom())
+ }
+ if (isBottom()) {
return "[BOTTOM]";
+ }
StringBuilder buf = new StringBuilder();
buf.append('[');
int numSlots = getNumSlots();
@@ -617,14 +656,16 @@ public abstract class Frame<ValueType> {
// the operand stack.
int last = buf.length() - 1;
if (last >= 0) {
- if (buf.charAt(last) == ',')
+ if (buf.charAt(last) == ',') {
buf.deleteCharAt(last);
+ }
}
buf.append('|');
}
String value = valueToString(getValue(i));
- if (i == numSlots - 1 && value.endsWith(","))
+ if (i == numSlots - 1 && value.endsWith(",")) {
value = value.substring(0, value.length() - 1);
+ }
buf.append(value);
// buf.append(' ');
}
@@ -638,8 +679,9 @@ public abstract class Frame<ValueType> {
* the values.
*/
protected String valueToString(ValueType value) {
- if (value == null)
+ if (value == null) {
return "null";
+ }
return value.toString();
}
@@ -648,8 +690,9 @@ public abstract class Frame<ValueType> {
* stack slots
*/
public Collection<ValueType> allSlots() {
- if (slotList == null)
+ if (slotList == null) {
return Collections.<ValueType> emptyList();
+ }
return Collections.<ValueType> unmodifiableCollection(slotList);
}
@@ -670,4 +713,3 @@ public abstract class Frame<ValueType> {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/FrameDataflowAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/FrameDataflowAnalysis.java
index 76e0519..cf5cba2 100644
--- a/src/java/edu/umd/cs/findbugs/ba/FrameDataflowAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/FrameDataflowAnalysis.java
@@ -26,29 +26,33 @@ import javax.annotation.CheckForNull;
/**
* A convenient base class for dataflow analysis classes which use Frames as
* values.
- *
+ *
* @author David Hovemeyer
* @see Frame
* @see DataflowAnalysis
*/
public abstract class FrameDataflowAnalysis<ValueType, FrameType extends Frame<ValueType>> extends
- ForwardDataflowAnalysis<FrameType> {
+ForwardDataflowAnalysis<FrameType> {
public FrameDataflowAnalysis(DepthFirstSearch dfs) {
super(dfs);
}
+ @Override
public void copy(FrameType source, FrameType dest) {
dest.copyFrom(source);
}
+ @Override
public void makeFactTop(FrameType fact) {
fact.setTop();
}
+ @Override
public boolean isTop(FrameType fact) {
return fact.isTop();
}
+ @Override
public boolean same(FrameType fact1, FrameType fact2) {
return fact1.sameAs(fact2);
}
@@ -57,9 +61,7 @@ public abstract class FrameDataflowAnalysis<ValueType, FrameType extends Frame<V
* Get the dataflow fact representing the point just before given Location.
* Note "before" is meant in the logical sense, so for backward analyses,
* before means after the location in the control flow sense.
- *
- * @param location
- * the location
+ *
* @return the fact at the point just before the location
*/
@@ -70,8 +72,9 @@ public abstract class FrameDataflowAnalysis<ValueType, FrameType extends Frame<V
for (Location l : cfg.locations()) {
if (l.getHandle().getPosition() == pc) {
FrameType fact = getFactAtLocation(l);
- if (isFactValid(fact))
+ if (isFactValid(fact)) {
mergeInto(fact, result);
+ }
}
}
return result;
@@ -81,9 +84,7 @@ public abstract class FrameDataflowAnalysis<ValueType, FrameType extends Frame<V
* Get the dataflow fact representing the point just before given Location.
* Note "before" is meant in the logical sense, so for backward analyses,
* before means after the location in the control flow sense.
- *
- * @param location
- * the location
+ *
* @return the fact at the point just before the location
*/
@@ -91,17 +92,27 @@ public abstract class FrameDataflowAnalysis<ValueType, FrameType extends Frame<V
FrameType result = createFact();
makeFactTop(result);
- for (BasicBlock b : cfg.getBlocksContainingInstructionWithOffset(pc))
+ for (Location loc : cfg.getLocationsContainingInstructionWithOffset(pc)) {
+ BasicBlock b = loc.getBasicBlock();
+ BasicBlock b2 = null;
if (b.getFirstInstruction() != null && b.getFirstInstruction().getPosition() == pc) {
- BasicBlock b2 = cfg.getPredecessorWithEdgeType(b, EdgeTypes.FALL_THROUGH_EDGE);
+ b2 = cfg.getPredecessorWithEdgeType(b, EdgeTypes.FALL_THROUGH_EDGE);
+ }
+ if(b2 != null && b2.isExceptionThrower()) {
for (Iterator<Edge> i = cfg.incomingEdgeIterator(b2); i.hasNext();) {
Edge e = i.next();
FrameType fact = getFactOnEdge(e);
- if (isFactValid(fact))
+ if (isFactValid(fact)) {
mergeInto(fact, result);
+ }
+ }
+ } else {
+ FrameType fact = getFactAtLocation(loc);
+ if (isFactValid(fact)) {
+ mergeInto(fact, result);
}
-
}
+ }
return result;
}
@@ -125,7 +136,7 @@ public abstract class FrameDataflowAnalysis<ValueType, FrameType extends Frame<V
* the frame needs to be modified in a path-sensitive fashion. A typical
* usage pattern is:
* <p/>
- *
+ *
* <pre>
* FrameType copy = null;
* if (someCondition()) {
@@ -145,7 +156,7 @@ public abstract class FrameDataflowAnalysis<ValueType, FrameType extends Frame<V
* The advantage of using modifyFrame() is that new code can be added before
* or after other places where the frame is modified, and the code will
* remain correct.
- *
+ *
* @param orig
* the original frame
* @param copy
@@ -164,7 +175,7 @@ public abstract class FrameDataflowAnalysis<ValueType, FrameType extends Frame<V
/**
* Merge one frame into another.
- *
+ *
* @param other
* the frame to merge with the result
* @param result
@@ -210,7 +221,7 @@ public abstract class FrameDataflowAnalysis<ValueType, FrameType extends Frame<V
/**
* Merge the values contained in a given slot of two Frames.
- *
+ *
* @param otherFrame
* a Frame
* @param resultFrame
@@ -222,4 +233,3 @@ public abstract class FrameDataflowAnalysis<ValueType, FrameType extends Frame<V
protected abstract void mergeValues(FrameType otherFrame, FrameType resultFrame, int slot) throws DataflowAnalysisException;
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/Hierarchy.java b/src/java/edu/umd/cs/findbugs/ba/Hierarchy.java
index d055fde..7c75b80 100644
--- a/src/java/edu/umd/cs/findbugs/ba/Hierarchy.java
+++ b/src/java/edu/umd/cs/findbugs/ba/Hierarchy.java
@@ -128,8 +128,9 @@ public class Hierarchy {
* (RuntimeException or Error).
*/
public static boolean isUncheckedException(ObjectType type) throws ClassNotFoundException {
- if (type.equals(Type.THROWABLE) || type.equals(RUNTIME_EXCEPTION_TYPE) || type.equals(ERROR_TYPE))
+ if (type.equals(Type.THROWABLE) || type.equals(RUNTIME_EXCEPTION_TYPE) || type.equals(ERROR_TYPE)) {
return true;
+ }
ClassDescriptor c = DescriptorFactory.getClassDescriptor(type);
Subtypes2 subtypes2 = Global.getAnalysisCache().getDatabase(Subtypes2.class);
return subtypes2.isSubtype(c, RUNTIME_EXCEPTION, ERROR);
@@ -147,7 +148,7 @@ public class Hierarchy {
* @return true if the method is a monitor wait, false if not
*/
public static boolean isMonitorWait(String methodName, String methodSig) {
- return methodName.equals("wait") && (methodSig.equals("()V") || methodSig.equals("(J)V") || methodSig.equals("(JI)V"));
+ return "wait".equals(methodName) && ("()V".equals(methodSig) || "(J)V".equals(methodSig) || "(JI)V".equals(methodSig));
}
/**
@@ -161,10 +162,12 @@ public class Hierarchy {
* @return true if the instruction is a monitor wait, false if not
*/
public static boolean isMonitorWait(Instruction ins, ConstantPoolGen cpg) {
- if (!(ins instanceof InvokeInstruction))
+ if (!(ins instanceof InvokeInstruction)) {
return false;
- if (ins.getOpcode() == Constants.INVOKESTATIC)
+ }
+ if (ins.getOpcode() == Constants.INVOKESTATIC) {
return false;
+ }
InvokeInstruction inv = (InvokeInstruction) ins;
String methodName = inv.getMethodName(cpg);
@@ -184,7 +187,7 @@ public class Hierarchy {
* @return true if the method is a monitor notify, false if not
*/
public static boolean isMonitorNotify(String methodName, String methodSig) {
- return (methodName.equals("notify") || methodName.equals("notifyAll")) && methodSig.equals("()V");
+ return ("notify".equals(methodName) || "notifyAll".equals(methodName)) && "()V".equals(methodSig);
}
/**
@@ -198,10 +201,12 @@ public class Hierarchy {
* @return true if the instruction is a monitor wait, false if not
*/
public static boolean isMonitorNotify(Instruction ins, ConstantPoolGen cpg) {
- if (!(ins instanceof InvokeInstruction))
+ if (!(ins instanceof InvokeInstruction)) {
return false;
- if (ins.getOpcode() == Constants.INVOKESTATIC)
+ }
+ if (ins.getOpcode() == Constants.INVOKESTATIC) {
return false;
+ }
InvokeInstruction inv = (InvokeInstruction) ins;
String methodName = inv.getMethodName(cpg);
@@ -329,11 +334,13 @@ public class Hierarchy {
short opcode = inv.getOpcode();
if (opcode == Constants.INVOKESTATIC) {
- if (methodChooser == INSTANCE_METHOD)
+ if (methodChooser == INSTANCE_METHOD) {
return null;
+ }
} else {
- if (methodChooser == STATIC_METHOD)
+ if (methodChooser == STATIC_METHOD) {
return null;
+ }
}
// Find the method
@@ -366,18 +373,21 @@ public class Hierarchy {
JavaClassAndMethod findInvocationLeastUpperBound(JavaClass jClass, String methodName, String methodSig,
JavaClassAndMethodChooser methodChooser, boolean invokeInterface) throws ClassNotFoundException {
JavaClassAndMethod result = findMethod(jClass, methodName, methodSig, methodChooser);
- if (result != null)
+ if (result != null) {
return result;
- if (invokeInterface)
+ }
+ if (invokeInterface) {
for (JavaClass i : jClass.getInterfaces()) {
result = findInvocationLeastUpperBound(i, methodName, methodSig, methodChooser, invokeInterface);
- if (result != null)
+ if (result != null) {
return null;
+ }
}
- else {
+ } else {
JavaClass sClass = jClass.getSuperClass();
- if (sClass != null)
+ if (sClass != null) {
return findInvocationLeastUpperBound(sClass, methodName, methodSig, methodChooser, invokeInterface);
+ }
}
return null;
@@ -425,7 +435,7 @@ public class Hierarchy {
System.out.println("Check " + javaClass.getClassName());
}
Method[] methodList = javaClass.getMethods();
- for (Method method : methodList)
+ for (Method method : methodList) {
if (method.getName().equals(methodName) && method.getSignature().equals(methodSig)) {
JavaClassAndMethod m = new JavaClassAndMethod(javaClass, method);
if (chooser.choose(m)) {
@@ -435,6 +445,7 @@ public class Hierarchy {
return m;
}
}
+ }
if (DEBUG_METHOD_LOOKUP) {
System.out.println("\t==> NOT FOUND");
}
@@ -491,7 +502,7 @@ public class Hierarchy {
System.out.println("Check " + javaClass.getClassName());
}
Method[] methodList = javaClass.getMethods();
- for (Method method : methodList)
+ for (Method method : methodList) {
if (method.getName().equals(methodName) && method.getSignature().equals(methodSig)
&& accessFlagsAreConcrete(method.getAccessFlags())) {
JavaClassAndMethod m = new JavaClassAndMethod(javaClass, method);
@@ -499,6 +510,7 @@ public class Hierarchy {
return m;
}
+ }
if (DEBUG_METHOD_LOOKUP) {
System.out.println("\t==> NOT FOUND");
}
@@ -530,10 +542,12 @@ public class Hierarchy {
* JavaClassAndMethodChooser which accepts any method.
*/
public static final JavaClassAndMethodChooser ANY_METHOD = new JavaClassAndMethodChooser() {
+ @Override
public boolean choose(JavaClassAndMethod javaClassAndMethod) {
return true;
}
+ @Override
public boolean choose(XMethod method) {
return true;
}
@@ -550,12 +564,14 @@ public class Hierarchy {
* native) methods.
*/
public static final JavaClassAndMethodChooser CONCRETE_METHOD = new JavaClassAndMethodChooser() {
+ @Override
public boolean choose(JavaClassAndMethod javaClassAndMethod) {
Method method = javaClassAndMethod.getMethod();
int accessFlags = method.getAccessFlags();
return accessFlagsAreConcrete(accessFlags);
}
+ @Override
public boolean choose(XMethod method) {
return accessFlagsAreConcrete(method.getAccessFlags());
}
@@ -565,10 +581,12 @@ public class Hierarchy {
* JavaClassAndMethodChooser which accepts only static methods.
*/
public static final JavaClassAndMethodChooser STATIC_METHOD = new JavaClassAndMethodChooser() {
+ @Override
public boolean choose(JavaClassAndMethod javaClassAndMethod) {
return javaClassAndMethod.getMethod().isStatic();
}
+ @Override
public boolean choose(XMethod method) {
return method.isStatic();
}
@@ -578,10 +596,12 @@ public class Hierarchy {
* JavaClassAndMethodChooser which accepts only instance methods.
*/
public static final JavaClassAndMethodChooser INSTANCE_METHOD = new JavaClassAndMethodChooser() {
+ @Override
public boolean choose(JavaClassAndMethod javaClassAndMethod) {
return !javaClassAndMethod.getMethod().isStatic();
}
+ @Override
public boolean choose(XMethod method) {
return !method.isStatic();
}
@@ -624,8 +644,9 @@ public class Hierarchy {
JavaClassAndMethod m = null;
for (JavaClass cls : classList) {
- if ((m = findMethod(cls, methodName, methodSig, chooser)) != null)
+ if ((m = findMethod(cls, methodName, methodSig, chooser)) != null) {
break;
+ }
}
return m;
@@ -771,8 +792,9 @@ public class Hierarchy {
InvokeInstruction invokeInstruction, ConstantPoolGen cpg, boolean receiverTypeIsExact) throws ClassNotFoundException {
HashSet<JavaClassAndMethod> result = new HashSet<JavaClassAndMethod>();
- if (invokeInstruction.getOpcode() == Constants.INVOKESTATIC)
+ if (invokeInstruction.getOpcode() == Constants.INVOKESTATIC) {
throw new IllegalArgumentException();
+ }
String methodName = invokeInstruction.getName(cpg);
String methodSig = invokeInstruction.getSignature(cpg);
@@ -782,8 +804,9 @@ public class Hierarchy {
if (receiverType instanceof ArrayType) {
JavaClass javaLangObject = AnalysisContext.currentAnalysisContext().lookupClass("java.lang.Object");
JavaClassAndMethod classAndMethod = findMethod(javaLangObject, methodName, methodSig, INSTANCE_METHOD);
- if (classAndMethod != null)
+ if (classAndMethod != null) {
result.add(classAndMethod);
+ }
return result;
}
@@ -817,7 +840,7 @@ public class Hierarchy {
&& !receiverTypeIsExact;
if (virtualCall) {
- if (!receiverClassName.equals("java.lang.Object")) {
+ if (!"java.lang.Object".equals(receiverClassName)) {
// This is a true virtual call: assume that any concrete
// subtype method may be called.
@@ -828,10 +851,11 @@ public class Hierarchy {
result.add(new JavaClassAndMethod(concreteSubtypeMethod));
}
}
- if (false && subTypeSet.size() > 500)
+ if (false && subTypeSet.size() > 500) {
new RuntimeException(receiverClassName + " has " + subTypeSet.size() + " subclasses, " + result.size()
+ " of which implement " + methodName + methodSig + " " + invokeInstruction)
- .printStackTrace(System.out);
+ .printStackTrace(System.out);
+ }
}
}
@@ -894,7 +918,7 @@ public class Hierarchy {
* could be found
*/
public static XField findXField(String className, String fieldName, String fieldSig, boolean isStatic)
- {
+ {
return XFactory.createXField(className, fieldName, fieldSig, isStatic);
}
@@ -922,10 +946,11 @@ public class Hierarchy {
XField xfield = findXField(className, fieldName, fieldSig, isStatic);
short opcode = fins.getOpcode();
if (xfield != null && xfield.isResolved()
- && xfield.isStatic() == (opcode == Constants.GETSTATIC || opcode == Constants.PUTSTATIC))
+ && xfield.isStatic() == (opcode == Constants.GETSTATIC || opcode == Constants.PUTSTATIC)) {
return xfield;
- else
+ } else {
return null;
+ }
}
/**
@@ -967,4 +992,3 @@ public class Hierarchy {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/Hierarchy2.java b/src/java/edu/umd/cs/findbugs/ba/Hierarchy2.java
index 37b0935..0ae4fce 100644
--- a/src/java/edu/umd/cs/findbugs/ba/Hierarchy2.java
+++ b/src/java/edu/umd/cs/findbugs/ba/Hierarchy2.java
@@ -19,9 +19,7 @@
package edu.umd.cs.findbugs.ba;
-import static edu.umd.cs.findbugs.ba.Hierarchy.DEBUG_METHOD_LOOKUP;
-import static edu.umd.cs.findbugs.ba.Hierarchy.INSTANCE_METHOD;
-import static edu.umd.cs.findbugs.ba.Hierarchy.STATIC_METHOD;
+import static edu.umd.cs.findbugs.ba.Hierarchy.*;
import java.util.Collections;
import java.util.HashSet;
@@ -58,7 +56,7 @@ import edu.umd.cs.findbugs.util.Util;
* hierarchy using the {@link org.apache.bcel.Repository} class. Callers should
* generally expect to handle ClassNotFoundException for when referenced classes
* can't be found.
- *
+ *
* @author William Pugh
*/
public class Hierarchy2 {
@@ -69,7 +67,7 @@ public class Hierarchy2 {
* Look up the method referenced by given InvokeInstruction. This method
* does <em>not</em> look for implementations in super or subclasses
* according to the virtual dispatch rules.
- *
+ *
* @param inv
* the InvokeInstruction
* @param cpg
@@ -82,7 +80,7 @@ public class Hierarchy2 {
* the class
*/
public static XMethod findExactMethod(InvokeInstruction inv, ConstantPoolGen cpg, JavaClassAndMethodChooser chooser)
- {
+ {
String className = inv.getClassName(cpg);
String methodName = inv.getName(cpg);
String methodSig = inv.getSignature(cpg);
@@ -95,16 +93,18 @@ public class Hierarchy2 {
private static @CheckForNull
XMethod thisOrNothing(@CheckForNull XMethod m, JavaClassAndMethodChooser chooser) {
- if (m == null)
+ if (m == null) {
return null;
- if (chooser.choose(m))
+ }
+ if (chooser.choose(m)) {
return m;
+ }
return null;
}
public static @CheckForNull
XMethod findInvocationLeastUpperBound(InvokeInstruction inv, ConstantPoolGen cpg, JavaClassAndMethodChooser methodChooser)
- {
+ {
if (DEBUG_METHOD_LOOKUP) {
System.out.println("Find prototype method for " + SignatureConverter.convertMethodSignature(inv, cpg));
@@ -113,11 +113,13 @@ public class Hierarchy2 {
short opcode = inv.getOpcode();
if (opcode == Constants.INVOKESTATIC) {
- if (methodChooser == INSTANCE_METHOD)
+ if (methodChooser == INSTANCE_METHOD) {
return null;
+ }
} else {
- if (methodChooser == STATIC_METHOD)
+ if (methodChooser == STATIC_METHOD) {
return null;
+ }
}
// Find the method
@@ -164,19 +166,22 @@ public class Hierarchy2 {
XMethod findInvocationLeastUpperBound(XClass jClass, String methodName, String methodSig, boolean invokeStatic,
boolean invokeInterface) {
XMethod result = findMethod(jClass.getClassDescriptor(), methodName, methodSig, invokeStatic);
- if (result != null)
+ if (result != null) {
return result;
+ }
ClassDescriptor sClass = jClass.getSuperclassDescriptor();
if (sClass != null) {
result = findInvocationLeastUpperBound(sClass, methodName, methodSig, invokeStatic, invokeInterface);
- if (result != null)
+ if (result != null) {
return result;
+ }
}
for (ClassDescriptor i : jClass.getInterfaceDescriptorList()) {
result = findInvocationLeastUpperBound(i, methodName, methodSig, invokeStatic, invokeInterface);
- if (result != null)
+ if (result != null) {
return result;
+ }
}
return null;
@@ -186,18 +191,21 @@ public class Hierarchy2 {
XMethod findInvocationLeastUpperBound0(XClass jClass, String methodName, String methodSig, boolean invokeStatic,
boolean invokeInterface) {
XMethod result = findMethod(jClass.getClassDescriptor(), methodName, methodSig, invokeStatic);
- if (result != null)
+ if (result != null) {
return result;
- if (invokeInterface)
+ }
+ if (invokeInterface) {
for (ClassDescriptor i : jClass.getInterfaceDescriptorList()) {
result = findInvocationLeastUpperBound(i, methodName, methodSig, invokeStatic, invokeInterface);
- if (result != null)
+ if (result != null) {
return result;
+ }
}
- else {
+ } else {
ClassDescriptor sClass = jClass.getSuperclassDescriptor();
- if (sClass != null)
+ if (sClass != null) {
return findInvocationLeastUpperBound(sClass, methodName, methodSig, invokeStatic, invokeInterface);
+ }
}
return null;
}
@@ -213,7 +221,7 @@ public class Hierarchy2 {
public static @CheckForNull XMethod findFirstSuperMethod(XMethod m) {
-
+
try {
@CheckForNull ClassDescriptor c = m.getClassDescriptor();
XClass xc = getXClass(c);
@@ -221,8 +229,9 @@ public class Hierarchy2 {
while (c != null) {
xc = getXClass(c);
XMethod xm = xc.findMatchingMethod(m.getMethodDescriptor());
- if (xm != null)
+ if (xm != null) {
return xm;
+ }
c = xc.getSuperclassDescriptor();
}
} catch (CheckedAnalysisException e) {
@@ -230,20 +239,24 @@ public class Hierarchy2 {
}
return null;
}
-
+
private static void findSuperMethods(@CheckForNull ClassDescriptor c, XMethod m, Set<XMethod> accumulator) {
- if (c == null)
+ if (c == null) {
return;
+ }
try {
XClass xc = getXClass(c);
XMethod xm = xc.findMatchingMethod(m.getMethodDescriptor());
- if (xm != null && !accumulator.add(xm))
+ if (xm != null && !accumulator.add(xm)) {
return;
+ }
findSuperMethods(xc.getSuperclassDescriptor(), m, accumulator);
- for (ClassDescriptor i : xc.getInterfaceDescriptorList())
+ for (ClassDescriptor i : xc.getInterfaceDescriptorList()) {
findSuperMethods(i, m, accumulator);
- if (!accumulator.add(m))
+ }
+ if (!accumulator.add(m)) {
return;
+ }
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("Error finding super methods for " + m, e);
@@ -274,7 +287,7 @@ public class Hierarchy2 {
/**
* Resolve possible method call targets. This works for both static and
* instance method calls.
- *
+ *
* @param invokeInstruction
* the InvokeInstruction
* @param typeFrame
@@ -329,7 +342,7 @@ public class Hierarchy2 {
/**
* Resolve possible instance method call targets. Assumes that invokevirtual
* and invokeinterface methods may call any subtype of the receiver class.
- *
+ *
* @param receiverType
* type of the receiver object
* @param invokeInstruction
@@ -346,7 +359,7 @@ public class Hierarchy2 {
/**
* Resolve possible instance method call targets.
- *
+ *
* @param receiverType
* type of the receiver object
* @param invokeInstruction
@@ -362,20 +375,22 @@ public class Hierarchy2 {
public static Set<XMethod> resolveMethodCallTargets(ReferenceType receiverType, InvokeInstruction invokeInstruction,
ConstantPoolGen cpg, boolean receiverTypeIsExact) throws ClassNotFoundException {
- if (invokeInstruction.getOpcode() == Constants.INVOKESTATIC)
+ if (invokeInstruction.getOpcode() == Constants.INVOKESTATIC) {
throw new IllegalArgumentException();
+ }
String methodName = invokeInstruction.getName(cpg);
String methodSig = invokeInstruction.getSignature(cpg);
// Array method calls aren't virtual.
// They should just resolve to Object methods.
- if (receiverType instanceof ArrayType)
+ if (receiverType instanceof ArrayType) {
try {
return Util.emptyOrNonnullSingleton(getXClass(objectDescriptor).findMethod(methodName, methodSig, false));
} catch (CheckedAnalysisException e) {
return Collections.<XMethod> emptySet();
}
+ }
if (receiverType instanceof ObjectType) {
// Get the receiver class.
@@ -389,16 +404,6 @@ public class Hierarchy2 {
}
- /**
- * @param receiverClassName
- * @param methodName
- * @param methodSig
- * @param receiverTypeIsExact
- * @param invokeSpecial
- * TODO
- * @return
- * @throws ClassNotFoundException
- */
public static Set<XMethod> resolveVirtualMethodCallTargets(String receiverClassName, String methodName, String methodSig,
boolean receiverTypeIsExact, boolean invokeSpecial) throws ClassNotFoundException {
ClassDescriptor receiverDesc = DescriptorFactory.createClassDescriptorFromDottedClassName(receiverClassName);
@@ -441,13 +446,14 @@ public class Hierarchy2 {
if (OPEN_WORLD_DEBUG) {
System.out.println("OWD: " + receiverDesc + "." + methodName + methodSig);
- if (upperBound != null)
+ if (upperBound != null) {
System.out.println(" upper bound:" + upperBound);
+ }
}
// Is this a virtual call site?
boolean virtualCall = (upperBound == null || !upperBound.isFinal()) && !receiverTypeIsExact && !invokeSpecial;
- if (virtualCall && !receiverDesc.getClassName().equals("java/lang/Object")) {
+ if (virtualCall && !"java/lang/Object".equals(receiverDesc.getClassName())) {
// This is a true virtual call: assume that any concrete
// subtype method may be called.
@@ -455,8 +461,9 @@ public class Hierarchy2 {
for (ClassDescriptor subtype : subTypeSet) {
XMethod concreteSubtypeMethod = findMethod(subtype, methodName, methodSig, false);
if (concreteSubtypeMethod != null && (OPEN_WORLD || !concreteSubtypeMethod.isAbstract())) {
- if (OPEN_WORLD_DEBUG)
+ if (OPEN_WORLD_DEBUG) {
System.out.println(" -> " + concreteSubtypeMethod);
+ }
result.add(concreteSubtypeMethod);
}
@@ -468,7 +475,7 @@ public class Hierarchy2 {
/**
* Find the declared exceptions for the method called by given instruction.
- *
+ *
* @param inv
* the InvokeInstruction
* @param cpg
@@ -482,12 +489,14 @@ public class Hierarchy2 {
XMethod method = findInvocationLeastUpperBound(inv, cpg, inv instanceof INVOKESTATIC ? Hierarchy.STATIC_METHOD
: Hierarchy.INSTANCE_METHOD);
- if (method == null)
+ if (method == null) {
return null;
+ }
String[] exceptions = method.getThrownExceptions();
- if (exceptions == null)
+ if (exceptions == null) {
return new ObjectType[0];
+ }
ObjectType[] result = new ObjectType[exceptions.length];
for (int i = 0; i < exceptions.length; ++i) {
@@ -498,4 +507,3 @@ public class Hierarchy2 {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/INullnessAnnotationDatabase.java b/src/java/edu/umd/cs/findbugs/ba/INullnessAnnotationDatabase.java
index 190272d..1ebf37d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/INullnessAnnotationDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/INullnessAnnotationDatabase.java
@@ -26,14 +26,14 @@ import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
/**
* Interface for querying nullness annotations on methods, fields, and
* parameters.
- *
+ *
* @author David Hovemeyer
*/
public interface INullnessAnnotationDatabase {
/**
* Determine whether given parameter must be non-null.
- *
+ *
* @param m
* a method
* @param param
@@ -45,7 +45,7 @@ public interface INullnessAnnotationDatabase {
/**
* Get a resolved NullnessAnnotation on given XMethod, XField, or
* XMethodParameter.
- *
+ *
* @param o
* an XMethod, XField, or XMethodParameter
* @param getMinimal
@@ -72,7 +72,7 @@ public interface INullnessAnnotationDatabase {
/**
* Add a field annotation to the database.
- *
+ *
* @param cName
* dotted class name
* @param mName
@@ -89,7 +89,7 @@ public interface INullnessAnnotationDatabase {
/**
* Add a method annotation to the database.
- *
+ *
* @param cName
* dotted class name
* @param mName
@@ -106,7 +106,7 @@ public interface INullnessAnnotationDatabase {
/**
* Add a method parameter annotation to the database.
- *
+ *
* @param cName
* dotted class name
* @param mName
@@ -125,7 +125,7 @@ public interface INullnessAnnotationDatabase {
/**
* Add a default annotation to the database.
- *
+ *
* @param target
* one of AnnotationDatabase.METHOD, AnnotationDatabase.FIELD,
* AnnotationDatabase.PARAMETER, or AnnotationDatabase.ANY
diff --git a/src/java/edu/umd/cs/findbugs/ba/IncompatibleTypes.java b/src/java/edu/umd/cs/findbugs/ba/IncompatibleTypes.java
index a9ae3c0..3c2530b 100644
--- a/src/java/edu/umd/cs/findbugs/ba/IncompatibleTypes.java
+++ b/src/java/edu/umd/cs/findbugs/ba/IncompatibleTypes.java
@@ -130,17 +130,17 @@ public class IncompatibleTypes {
static public @Nonnull
IncompatibleTypes getPriorityForAssumingCompatible(Type expectedType, Type actualType, boolean pointerEquality) {
- if (expectedType.equals(actualType))
+ if (expectedType.equals(actualType)) {
return SEEMS_OK;
-
- if (!(expectedType instanceof ReferenceType))
+ }
+
+ if (!(expectedType instanceof ReferenceType)) {
return SEEMS_OK;
- if (!(actualType instanceof ReferenceType))
+ }
+ if (!(actualType instanceof ReferenceType)) {
return SEEMS_OK;
-
- if (expectedType instanceof BasicType ^ actualType instanceof BasicType) {
- return INCOMPATIBLE_CLASSES;
}
+
while (expectedType instanceof ArrayType && actualType instanceof ArrayType) {
expectedType = ((ArrayType) expectedType).getElementType();
actualType = ((ArrayType) actualType).getElementType();
@@ -150,10 +150,11 @@ public class IncompatibleTypes {
return PRIMATIVE_ARRAY_AND_OTHER_ARRAY;
}
if (expectedType instanceof BasicType && actualType instanceof BasicType) {
- if (!expectedType.equals(actualType))
+ if (!expectedType.equals(actualType)) {
return INCOMPATIBLE_PRIMATIVE_ARRAYS;
- else
+ } else {
return SEEMS_OK;
+ }
}
if (expectedType instanceof ArrayType) {
return getPriorityForAssumingCompatibleWithArray(actualType);
@@ -161,24 +162,27 @@ public class IncompatibleTypes {
if (actualType instanceof ArrayType) {
return getPriorityForAssumingCompatibleWithArray(expectedType);
}
- if (expectedType.equals(actualType))
+ if (expectedType.equals(actualType)) {
return SEEMS_OK;
+ }
// For now, ignore the case where either reference is not
// of an object type. (It could be either an array or null.)
- if (!(expectedType instanceof ObjectType) || !(actualType instanceof ObjectType))
+ if (!(expectedType instanceof ObjectType) || !(actualType instanceof ObjectType)) {
return SEEMS_OK;
+ }
return getPriorityForAssumingCompatible((ObjectType) expectedType, (ObjectType) actualType, pointerEquality);
-
}
private static IncompatibleTypes getPriorityForAssumingCompatibleWithArray(Type rhsType) {
- if (rhsType.equals(Type.OBJECT))
+ if (rhsType.equals(Type.OBJECT)) {
return ARRAY_AND_OBJECT;
+ }
String sig = rhsType.getSignature();
- if (sig.equals("Ljava/io/Serializable;") || sig.equals("Ljava/lang/Cloneable;"))
+ if ("Ljava/io/Serializable;".equals(sig) || "Ljava/lang/Cloneable;".equals(sig)) {
return SEEMS_OK;
+ }
return ARRAY_AND_NON_ARRAY;
}
@@ -187,13 +191,16 @@ public class IncompatibleTypes {
IAnalysisCache cache = Global.getAnalysisCache();
while (true) {
XMethod result = xClass.findMethod(name, sig, isStatic);
- if (result != null)
+ if (result != null) {
return result;
- if (isStatic)
+ }
+ if (isStatic) {
throw new CheckedAnalysisException();
+ }
ClassDescriptor superclassDescriptor = xClass.getSuperclassDescriptor();
- if (superclassDescriptor == null)
+ if (superclassDescriptor == null) {
throw new CheckedAnalysisException();
+ }
xClass = cache.getClassAnalysis(XClass.class, superclassDescriptor);
}
@@ -201,21 +208,25 @@ public class IncompatibleTypes {
static public @Nonnull
IncompatibleTypes getPriorityForAssumingCompatible(ObjectType expectedType, ObjectType actualType, boolean pointerEquality) {
- if (expectedType.equals(actualType))
+ if (expectedType.equals(actualType)) {
return SEEMS_OK;
+ }
- if (actualType.equals(Type.OBJECT))
+ if (actualType.equals(Type.OBJECT)) {
return IncompatibleTypes.UNCHECKED;
-
- if (expectedType.equals(Type.OBJECT))
+ }
+
+ if (expectedType.equals(Type.OBJECT)) {
return IncompatibleTypes.SEEMS_OK;
+ }
try {
if (!Hierarchy.isSubtype(expectedType, actualType) && !Hierarchy.isSubtype(actualType, expectedType)) {
if (Hierarchy.isSubtype(expectedType, GWT_JAVASCRIPTOBJECT_TYPE)
- && Hierarchy.isSubtype(actualType, GWT_JAVASCRIPTOBJECT_TYPE))
+ && Hierarchy.isSubtype(actualType, GWT_JAVASCRIPTOBJECT_TYPE)) {
return SEEMS_OK;
+ }
// See if the types are related by inheritance.
ClassDescriptor lhsDescriptor = DescriptorFactory.createClassDescriptorFromDottedClassName(expectedType
.getClassName());
@@ -229,13 +240,15 @@ public class IncompatibleTypes {
&& (Hierarchy.isSubtype(expectedType, COLLECTION_TYPE) || Hierarchy.isSubtype(expectedType, MAP_TYPE))) {
List<? extends ReferenceType> lhsParameters = ((GenericObjectType) expectedType).getParameters();
List<? extends ReferenceType> rhsParameters = ((GenericObjectType) actualType).getParameters();
- if (lhsParameters != null && rhsParameters != null && lhsParameters.size() == rhsParameters.size())
+ if (lhsParameters != null && rhsParameters != null && lhsParameters.size() == rhsParameters.size()) {
for (int i = 0; i < lhsParameters.size(); i++) {
IncompatibleTypes r = getPriorityForAssumingCompatible(lhsParameters.get(i), rhsParameters.get(i),
pointerEquality);
- if (r.getPriority() <= Priorities.NORMAL_PRIORITY)
+ if (r.getPriority() <= Priorities.NORMAL_PRIORITY) {
return r;
+ }
}
+ }
}
@@ -249,17 +262,11 @@ public class IncompatibleTypes {
return SEEMS_OK;
}
- /**
- * @param pointerEquality
- * @param lhsDescriptor
- * @param rhsDescriptor
- * @throws CheckedAnalysisException
- * @throws ClassNotFoundException
- */
public static IncompatibleTypes getPriorityForAssumingCompatible(boolean pointerEquality, ClassDescriptor lhsDescriptor,
ClassDescriptor rhsDescriptor) throws CheckedAnalysisException, ClassNotFoundException {
- if (lhsDescriptor.equals(rhsDescriptor))
+ if (lhsDescriptor.equals(rhsDescriptor)) {
return SEEMS_OK;
+ }
AnalysisContext analysisContext = AnalysisContext.currentAnalysisContext();
Subtypes2 subtypes2 = analysisContext.getSubtypes2();
@@ -272,16 +279,19 @@ public class IncompatibleTypes {
XMethod rhsEquals = getInvokedMethod(rhs, "equals", "(Ljava/lang/Object;)Z", false);
String lhsClassName = lhsEquals.getClassName();
if (lhsEquals.equals(rhsEquals)) {
- if (lhsClassName.equals("java.lang.Enum"))
+ if ("java.lang.Enum".equals(lhsClassName)) {
return INCOMPATIBLE_CLASSES;
- if (!pointerEquality && !lhsClassName.equals("java.lang.Object"))
+ }
+ if (!pointerEquality && !"java.lang.Object".equals(lhsClassName)) {
return SEEMS_OK;
+ }
}
if ((subtypes2.isSubtype(lhsDescriptor, SET_DESCRIPTOR) && subtypes2.isSubtype(rhsDescriptor, SET_DESCRIPTOR)
|| subtypes2.isSubtype(lhsDescriptor, MAP_DESCRIPTOR) && subtypes2.isSubtype(rhsDescriptor, MAP_DESCRIPTOR) || subtypes2
- .isSubtype(lhsDescriptor, LIST_DESCRIPTOR) && subtypes2.isSubtype(rhsDescriptor, LIST_DESCRIPTOR)))
+ .isSubtype(lhsDescriptor, LIST_DESCRIPTOR) && subtypes2.isSubtype(rhsDescriptor, LIST_DESCRIPTOR))) {
return SEEMS_OK;
+ }
if (!lhs.isInterface() && !rhs.isInterface()) {
// Both are class types, and therefore there is no possible
@@ -298,15 +308,18 @@ public class IncompatibleTypes {
if (commonSubtypes.isEmpty()) {
if (lhs.isInterface() && rhs.isInterface()) {
- if (!subtypes2.hasKnownSubclasses(lhsDescriptor) || !subtypes2.hasKnownSubclasses(rhsDescriptor))
+ if (!subtypes2.hasKnownSubclasses(lhsDescriptor) || !subtypes2.hasKnownSubclasses(rhsDescriptor)) {
return UNRELATED_INTERFACES_WITHOUT_IMPLEMENTATIONS;
+ }
return UNRELATED_INTERFACES;
}
- if (lhs.isFinal() || rhs.isFinal())
+ if (lhs.isFinal() || rhs.isFinal()) {
return UNRELATED_FINAL_CLASS_AND_INTERFACE;
+ }
if (lhsDescriptor.getClassName().startsWith("java/util/")
- || rhsDescriptor.getClassName().startsWith("java/util/"))
+ || rhsDescriptor.getClassName().startsWith("java/util/")) {
return UNRELATED_UTIL_INTERFACE;
+ }
return UNRELATED_CLASS_AND_INTERFACE;
}
@@ -314,7 +327,4 @@ public class IncompatibleTypes {
return SEEMS_OK;
}
-
-
-
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/InnerClassAccess.java b/src/java/edu/umd/cs/findbugs/ba/InnerClassAccess.java
index a3b6dbd..5912472 100644
--- a/src/java/edu/umd/cs/findbugs/ba/InnerClassAccess.java
+++ b/src/java/edu/umd/cs/findbugs/ba/InnerClassAccess.java
@@ -22,13 +22,14 @@ package edu.umd.cs.findbugs.ba;
import javax.annotation.Nonnull;
public class InnerClassAccess {
- private String methodName;
+ private final String methodName;
- private String methodSig;
+ private final String methodSig;
- private @Nonnull XField field;
+ private @Nonnull
+ final XField field;
- private boolean isLoad;
+ private final boolean isLoad;
public InnerClassAccess(String methodName, String methodSig, @Nonnull XField field, boolean isLoad) {
this.methodName = methodName;
@@ -58,4 +59,3 @@ public class InnerClassAccess {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/InnerClassAccessMap.java b/src/java/edu/umd/cs/findbugs/ba/InnerClassAccessMap.java
index b579447..f90b57a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/InnerClassAccessMap.java
+++ b/src/java/edu/umd/cs/findbugs/ba/InnerClassAccessMap.java
@@ -141,8 +141,9 @@ public class InnerClassAccessMap {
*/
private static int toInt(byte b) {
int value = b & 0x7F;
- if ((b & 0x80) != 0)
+ if ((b & 0x80) != 0) {
value |= 0x80;
+ }
return value;
}
@@ -153,10 +154,8 @@ public class InnerClassAccessMap {
return (toInt(instructionList[index + 1]) << 8) | toInt(instructionList[index + 2]);
}
+ /*
private static class LookupFailure extends RuntimeException {
- /**
- *
- */
private static final long serialVersionUID = 1L;
private final ClassNotFoundException exception;
@@ -169,6 +168,7 @@ public class InnerClassAccessMap {
return exception;
}
}
+ */
/**
* Callback to scan an access method to determine what field it accesses,
@@ -208,6 +208,7 @@ public class InnerClassAccessMap {
this.accessCount = 0;
}
+ @Override
public void handleInstruction(int opcode, int index) {
switch (opcode) {
case Constants.GETFIELD:
@@ -218,6 +219,8 @@ public class InnerClassAccessMap {
case Constants.PUTSTATIC:
setField(getIndex(instructionList, index), true, opcode == Constants.GETSTATIC);
break;
+ default:
+ break;
}
}
@@ -260,10 +263,10 @@ public class InnerClassAccessMap {
String fieldSig = nameAndType.getSignature(cp);
- XField xfield = Hierarchy.findXField(className, fieldName, fieldSig, isStatic);
- if (xfield != null && xfield.isStatic() == isStatic && isValidAccessMethod(methodSig, xfield, isLoad)) {
- access = new InnerClassAccess(methodName, methodSig, xfield, isLoad);
- }
+ XField xfield = Hierarchy.findXField(className, fieldName, fieldSig, isStatic);
+ if (xfield != null && xfield.isStatic() == isStatic && isValidAccessMethod(methodSig, xfield, isLoad)) {
+ access = new InnerClassAccess(methodName, methodSig, xfield, isLoad);
+ }
}
@@ -284,8 +287,9 @@ public class InnerClassAccessMap {
// Get the method parameters and return type
// (as they appear in the method signature).
int paramsEnd = methodSig.indexOf(')');
- if (paramsEnd < 0)
+ if (paramsEnd < 0) {
return false;
+ }
String methodParams = methodSig.substring(0, paramsEnd + 1);
String methodReturnType = methodSig.substring(paramsEnd + 1);
@@ -293,10 +297,12 @@ public class InnerClassAccessMap {
String classSig = "L" + javaClass.getClassName().replace('.', '/') + ";";
StringBuilder buf = new StringBuilder();
buf.append('(');
- if (!field.isStatic())
+ if (!field.isStatic()) {
buf.append(classSig); // the OuterClass.this reference
- if (!isLoad)
+ }
+ if (!isLoad) {
buf.append(field.getSignature()); // the value being stored
+ }
buf.append(')');
String expectedMethodParams = buf.toString();
@@ -311,7 +317,7 @@ public class InnerClassAccessMap {
}
// Return type can be either the type of the field, or void.
- if (!methodReturnType.equals("V") && !methodReturnType.equals(field.getSignature())) {
+ if (!"V".equals(methodReturnType) && !methodReturnType.equals(field.getSignature())) {
if (DEBUG) {
System.out.println("In " + javaClass.getClassName() + "." + methodName + " expected return type V or "
+ field.getSignature() + ", saw " + methodReturnType);
@@ -344,37 +350,43 @@ public class InnerClassAccessMap {
Method[] methodList = javaClass.getMethods();
for (Method method : methodList) {
String methodName = method.getName();
- if (!methodName.startsWith("access$"))
+ if (!methodName.startsWith("access$")) {
continue;
+ }
Code code = method.getCode();
- if (code == null)
+ if (code == null) {
continue;
+ }
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Analyzing " + className + "." + method.getName()
+ " as an inner-class access method...");
+ }
byte[] instructionList = code.getCode();
String methodSig = method.getSignature();
InstructionCallback callback = new InstructionCallback(javaClass, methodName, methodSig, instructionList);
- try {
- new BytecodeScanner().scan(instructionList, callback);
- } catch (LookupFailure lf) {
- throw lf.getException();
- }
+ // try {
+ new BytecodeScanner().scan(instructionList, callback);
+ // } catch (LookupFailure lf) {
+ // throw lf.getException();
+ // }
InnerClassAccess access = callback.getAccess();
- if (DEBUG)
+ if (DEBUG) {
System.out.println((access != null ? "IS" : "IS NOT") + " an inner-class access method");
- if (access != null)
+ }
+ if (access != null) {
map.put(methodName, access);
+ }
}
}
- if (map.size() == 0)
+ if (map.size() == 0) {
map = Collections.emptyMap();
- else
+ } else {
map = new HashMap<String, InnerClassAccess>(map);
+ }
classToAccessMap.put(className, map);
}
@@ -383,5 +395,3 @@ public class InnerClassAccessMap {
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/InstructionHandleMap.java b/src/java/edu/umd/cs/findbugs/ba/InstructionHandleMap.java
index e25a603..a2014ce 100644
--- a/src/java/edu/umd/cs/findbugs/ba/InstructionHandleMap.java
+++ b/src/java/edu/umd/cs/findbugs/ba/InstructionHandleMap.java
@@ -24,11 +24,11 @@ import org.apache.bcel.generic.MethodGen;
/**
* Map BCEL InstructionHandles to some kind of value type.
- *
+ *
* @author David Hovemeyer
*/
public class InstructionHandleMap<ValueType> {
- private Object[] map;
+ private final Object[] map;
public InstructionHandleMap(MethodGen methodGen) {
map = new Object[methodGen.getMethod().getCode().getLength()];
diff --git a/src/java/edu/umd/cs/findbugs/ba/InvalidBytecodeException.java b/src/java/edu/umd/cs/findbugs/ba/InvalidBytecodeException.java
index 8781b87..426a47d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/InvalidBytecodeException.java
+++ b/src/java/edu/umd/cs/findbugs/ba/InvalidBytecodeException.java
@@ -27,7 +27,7 @@ import org.apache.bcel.generic.MethodGen;
* can be thrown to indicate that a method invocation requires more stack
* operands than are available. AbstractFrameModelingVisitor will catch this
* exception and rethrow it as a checked DataflowAnalysisException.
- *
+ *
* @author David Hovemeyer
*/
public class InvalidBytecodeException extends RuntimeException {
@@ -35,7 +35,7 @@ public class InvalidBytecodeException extends RuntimeException {
/**
* Constructor.
- *
+ *
* @param msg
* reason for the exception
*/
@@ -45,7 +45,7 @@ public class InvalidBytecodeException extends RuntimeException {
/**
* Constructor.
- *
+ *
* @param msg
* reason for the exception
* @param cause
@@ -57,7 +57,7 @@ public class InvalidBytecodeException extends RuntimeException {
/**
* Constructor from method and instruction.
- *
+ *
* @param message
* reason for the error
* @param methodGen
@@ -71,7 +71,7 @@ public class InvalidBytecodeException extends RuntimeException {
/**
* Constructor from method and instruction.
- *
+ *
* @param message
* reason for the error
* @param methodGen
diff --git a/src/java/edu/umd/cs/findbugs/ba/JavaClassAndMethod.java b/src/java/edu/umd/cs/findbugs/ba/JavaClassAndMethod.java
index bc5a627..f7fedb4 100644
--- a/src/java/edu/umd/cs/findbugs/ba/JavaClassAndMethod.java
+++ b/src/java/edu/umd/cs/findbugs/ba/JavaClassAndMethod.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
* A JavaClass and a Method belonging to the class. This is useful for answering
* a method lookup query which must concretely identify both the class and the
* method.
- *
+ *
* @author David Hovemeyer
*/
public class JavaClassAndMethod {
@@ -41,7 +41,7 @@ public class JavaClassAndMethod {
/**
* Constructor.
- *
+ *
* @param javaClass
* the JavaClass
* @param method
@@ -54,7 +54,7 @@ public class JavaClassAndMethod {
/**
* Constructor.
- *
+ *
* @param method
* an XMethod specifying a specific method in a specific class
* @throws ClassNotFoundException
@@ -62,12 +62,13 @@ public class JavaClassAndMethod {
public JavaClassAndMethod(XMethod method) throws ClassNotFoundException {
this.javaClass = Repository.lookupClass(method.getClassName());
- for (Method m : javaClass.getMethods())
+ for (Method m : javaClass.getMethods()) {
if (m.getName().equals(method.getName()) && m.getSignature().equals(method.getSignature())
&& m.isStatic() == method.isStatic()) {
this.method = m;
return;
}
+ }
throw new IllegalArgumentException("Can't find " + method);
}
@@ -94,7 +95,7 @@ public class JavaClassAndMethod {
/**
* Get the MethodDescriptor that (hopefully) uniqely names this method.
- *
+ *
* @return the MethodDescriptor uniquely naming this method
*/
public MethodDescriptor toMethodDescriptor() {
@@ -113,8 +114,9 @@ public class JavaClassAndMethod {
@Override
public boolean equals(Object obj) {
- if (obj == null || obj.getClass() != this.getClass())
+ if (obj == null || obj.getClass() != this.getClass()) {
return false;
+ }
JavaClassAndMethod other = (JavaClassAndMethod) obj;
return javaClass.equals(other.javaClass) && method.equals(other.method);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/LineNumberMap.java b/src/java/edu/umd/cs/findbugs/ba/LineNumberMap.java
index 13d1fdc..7aa9526 100644
--- a/src/java/edu/umd/cs/findbugs/ba/LineNumberMap.java
+++ b/src/java/edu/umd/cs/findbugs/ba/LineNumberMap.java
@@ -43,15 +43,15 @@ public class LineNumberMap {
*/
private static final boolean LINE_NUMBER_BUG = SystemProperties.getBoolean("lineNumberBug");
- private MethodGen methodGen;
+ private final MethodGen methodGen;
- private IdentityHashMap<InstructionHandle, LineNumber> lineNumberMap;
+ private final IdentityHashMap<InstructionHandle, LineNumber> lineNumberMap;
private boolean hasLineNumbers;
/**
* Constructor.
- *
+ *
* @param methodGen
* the method to summarize line numbers for
*/
@@ -81,44 +81,52 @@ public class LineNumberMap {
InstructionHandle handle = methodGen.getInstructionList().getStart();
while (handle != null) {
int bytecodeOffset = handle.getPosition();
- if (bytecodeOffset < 0)
+ if (bytecodeOffset < 0) {
throw new IllegalStateException("Bad bytecode offset: " + bytecodeOffset);
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("Looking for source line for bytecode offset " + bytecodeOffset);
+ }
int sourceLine;
try {
sourceLine = table.getSourceLine(bytecodeOffset);
} catch (ArrayIndexOutOfBoundsException e) {
- if (LINE_NUMBER_BUG)
+ if (LINE_NUMBER_BUG) {
throw e;
- else
+ } else {
sourceLine = -1;
+ }
}
- if (sourceLine >= 0)
+ if (sourceLine >= 0) {
++numGood;
+ }
lineNumberMap.put(handle, new LineNumber(bytecodeOffset, sourceLine));
handle = handle.getNext();
++numBytecodes;
}
hasLineNumbers = true;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\t" + numGood + "/" + numBytecodes + " had valid line numbers");
+ }
}
}
private void checkTable(LineNumberTable table) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("line number table has length " + table.getTableLength());
+ }
LineNumber[] entries = table.getLineNumberTable();
int lastBytecode = -1;
for (int i = 0; i < entries.length; ++i) {
LineNumber ln = entries[i];
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Entry " + i + ": pc=" + ln.getStartPC() + ", line=" + ln.getLineNumber());
+ }
int pc = ln.getStartPC();
- if (pc <= lastBytecode)
+ if (pc <= lastBytecode) {
throw new IllegalStateException("LineNumberTable is not sorted");
+ }
}
}
@@ -131,7 +139,7 @@ public class LineNumberMap {
/**
* Find the line number information for instruction whose handle is given.
- *
+ *
* @param handle
* the InstructionHandle
* @return the LineNumber object containing bytecode offset and source line
diff --git a/src/java/edu/umd/cs/findbugs/ba/LiveLocalStoreAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/LiveLocalStoreAnalysis.java
index 7fa990c..2d98c08 100644
--- a/src/java/edu/umd/cs/findbugs/ba/LiveLocalStoreAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/LiveLocalStoreAnalysis.java
@@ -34,18 +34,18 @@ import org.apache.bcel.generic.StoreInstruction;
/**
* Dataflow analysis to find live stores of locals. This is just a backward
* analysis to see which loads reach stores of the same local.
- *
+ *
* <p>
* This analysis also computes which stores that were killed by a subsequent
* store on any subsequent reachable path. (The FindDeadLocalStores detector
* uses this information to reduce false positives.)
- *
+ *
* @author David Hovemeyer
*/
public class LiveLocalStoreAnalysis extends BackwardDataflowAnalysis<BitSet> implements Debug {
- private int topBit;
+ private final int topBit;
- private int killedByStoreOffset;
+ private final int killedByStoreOffset;
public LiveLocalStoreAnalysis(MethodGen methodGen, ReverseDepthFirstSearch rdfs, DepthFirstSearch dfs) {
super(rdfs, dfs);
@@ -53,28 +53,34 @@ public class LiveLocalStoreAnalysis extends BackwardDataflowAnalysis<BitSet> imp
this.killedByStoreOffset = methodGen.getMaxLocals();
}
+ @Override
public BitSet createFact() {
return new BitSet();
}
+ @Override
public void copy(BitSet source, BitSet dest) {
dest.clear();
dest.or(source);
}
+ @Override
public void initEntryFact(BitSet result) throws DataflowAnalysisException {
result.clear();
}
+ @Override
public void makeFactTop(BitSet fact) {
fact.clear();
fact.set(topBit);
}
+ @Override
public boolean same(BitSet fact1, BitSet fact2) {
return fact1.equals(fact2);
}
+ @Override
public void meetInto(BitSet fact, Edge edge, BitSet result) throws DataflowAnalysisException {
verifyFact(fact);
verifyFact(result);
@@ -95,8 +101,9 @@ public class LiveLocalStoreAnalysis extends BackwardDataflowAnalysis<BitSet> imp
@Override
public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, BitSet fact)
throws DataflowAnalysisException {
- if (!isFactValid(fact))
+ if (!isFactValid(fact)) {
return;
+ }
Instruction ins = handle.getInstruction();
@@ -120,8 +127,9 @@ public class LiveLocalStoreAnalysis extends BackwardDataflowAnalysis<BitSet> imp
fact.clear(local + killedByStoreOffset);
}
- if (!isFactValid(fact))
+ if (!isFactValid(fact)) {
throw new IllegalStateException("Fact become invalid");
+ }
}
@Override
@@ -135,30 +143,36 @@ public class LiveLocalStoreAnalysis extends BackwardDataflowAnalysis<BitSet> imp
*/
private void verifyFact(BitSet fact) {
if (VERIFY_INTEGRITY) {
- if (isTop(fact) && fact.nextSetBit(0) < topBit)
+ if (isTop(fact) && fact.nextSetBit(0) < topBit) {
throw new IllegalStateException();
+ }
}
}
@Override
public String factToString(BitSet fact) {
- if (isTop(fact))
+ if (isTop(fact)) {
return "[TOP]";
+ }
StringBuilder buf = new StringBuilder("[ ");
boolean empty = true;
for (int i = 0; i < killedByStoreOffset; i++) {
boolean killedByStore = killedByStore(fact, i);
boolean storeAlive = isStoreAlive(fact, i);
- if (!storeAlive && !killedByStore)
+ if (!storeAlive && !killedByStore) {
continue;
- if (!empty)
+ }
+ if (!empty) {
buf.append(", ");
+ }
empty = false;
buf.append(i);
- if (storeAlive)
+ if (storeAlive) {
buf.append("L");
- if (killedByStore)
+ }
+ if (killedByStore) {
buf.append("k");
+ }
}
buf.append("]");
return buf.toString();
@@ -167,13 +181,14 @@ public class LiveLocalStoreAnalysis extends BackwardDataflowAnalysis<BitSet> imp
/**
* Return whether or not given fact is the special TOP value.
*/
+ @Override
public boolean isTop(BitSet fact) {
return fact.get(topBit);
}
/**
* Return whether or not a store of given local is alive.
- *
+ *
* @param fact
* a dataflow fact created by this analysis
* @param local
@@ -215,4 +230,3 @@ public class LiveLocalStoreAnalysis extends BackwardDataflowAnalysis<BitSet> imp
// }
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/LiveLocalStoreDataflow.java b/src/java/edu/umd/cs/findbugs/ba/LiveLocalStoreDataflow.java
index 2ca5e7a..376fa77 100644
--- a/src/java/edu/umd/cs/findbugs/ba/LiveLocalStoreDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/LiveLocalStoreDataflow.java
@@ -23,7 +23,7 @@ import java.util.BitSet;
/**
* Dataflow class for LiveLocalStoreAnalysis.
- *
+ *
* @see LiveLocalStoreAnalysis
* @author David Hovemeyer
*/
@@ -33,4 +33,3 @@ public class LiveLocalStoreDataflow extends Dataflow<BitSet, LiveLocalStoreAnaly
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/Location.java b/src/java/edu/umd/cs/findbugs/ba/Location.java
index 762e255..4ac6b0e 100644
--- a/src/java/edu/umd/cs/findbugs/ba/Location.java
+++ b/src/java/edu/umd/cs/findbugs/ba/Location.java
@@ -19,6 +19,8 @@
package edu.umd.cs.findbugs.ba;
+import java.util.Objects;
+
import javax.annotation.Nonnull;
import org.apache.bcel.generic.InstructionHandle;
@@ -35,7 +37,7 @@ import org.apache.bcel.generic.InstructionHandle;
* Location objects may be compared with each other using the equals() method,
* and may be used as keys in tree and hash maps and sets. Note that
* <em>it is only valid to compare Locations produced from the same CFG</em>.
- *
+ *
* @author David Hovemeyer
* @see CFG
*/
@@ -48,25 +50,24 @@ public class Location implements Comparable<Location> {
/**
* Constructor.
- *
+ *
* @param handle
* the instruction
* @param basicBlock
* the basic block containing the instruction
*/
public Location(@Nonnull InstructionHandle handle, @Nonnull BasicBlock basicBlock) {
- if (handle == null)
- throw new NullPointerException("handle cannot be null");
- if (basicBlock == null)
- throw new NullPointerException("basicBlock cannot be null");
+ Objects.requireNonNull(handle, "handle cannot be null");
+ Objects.requireNonNull(basicBlock, "basicBlock cannot be null");
this.handle = handle;
this.basicBlock = basicBlock;
}
public static Location getFirstLocation(@Nonnull BasicBlock basicBlock) {
InstructionHandle location = basicBlock.getFirstInstruction();
- if (location == null)
+ if (location == null) {
return null;
+ }
return new Location(location, basicBlock);
}
@@ -77,8 +78,9 @@ public class Location implements Comparable<Location> {
* basicBlock.getExceptionThrower(); if (lastInstruction == null)
* lastInstruction = basicBlock.getFirstInstruction();
*/
- if (lastInstruction == null)
+ if (lastInstruction == null) {
return null;
+ }
return new Location(lastInstruction, basicBlock);
}
@@ -114,6 +116,7 @@ public class Location implements Comparable<Location> {
return !basicBlock.isEmpty() && handle == basicBlock.getLastInstruction();
}
+ @Override
public int compareTo(Location other) {
int pos = handle.getPosition() - other.handle.getPosition();
return pos;
@@ -129,8 +132,9 @@ public class Location implements Comparable<Location> {
@Override
public boolean equals(Object o) {
- if (!(o instanceof Location))
+ if (!(o instanceof Location)) {
return false;
+ }
Location other = (Location) o;
return basicBlock == other.basicBlock && handle == other.handle;
}
@@ -149,4 +153,3 @@ public class Location implements Comparable<Location> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/LockAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/LockAnalysis.java
index ef266cc..7257d71 100644
--- a/src/java/edu/umd/cs/findbugs/ba/LockAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/LockAnalysis.java
@@ -36,22 +36,22 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
* Analysis to determine where particular values are locked in a method. The
* dataflow values are maps of value numbers to the number of times those values
* are locked.
- *
+ *
* @author David Hovemeyer
* @see ValueNumberAnalysis
*/
public class LockAnalysis extends ForwardDataflowAnalysis<LockSet> {
private static final boolean DEBUG = SystemProperties.getBoolean("la.debug");
- private MethodGen methodGen;
+ private final MethodGen methodGen;
- private ValueNumberDataflow vnaDataflow;
+ private final ValueNumberDataflow vnaDataflow;
- private ValueNumberAnalysis vna;
+ private final ValueNumberAnalysis vna;
- private boolean isSynchronized;
+ private final boolean isSynchronized;
- private boolean isStatic;
+ private final boolean isStatic;
public LockAnalysis(MethodGen methodGen, ValueNumberDataflow vnaDataflow, DepthFirstSearch dfs) {
super(dfs);
@@ -60,18 +60,22 @@ public class LockAnalysis extends ForwardDataflowAnalysis<LockSet> {
this.vna = vnaDataflow.getAnalysis();
this.isSynchronized = methodGen.isSynchronized();
this.isStatic = methodGen.isStatic();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Analyzing Locks in " + methodGen.getClassName() + "." + methodGen.getName());
+ }
}
+ @Override
public LockSet createFact() {
return new LockSet();
}
+ @Override
public void copy(LockSet source, LockSet dest) {
dest.copyFrom(source);
}
+ @Override
public void initEntryFact(LockSet result) {
result.clear();
result.setDefaultLockCount(0);
@@ -85,19 +89,23 @@ public class LockAnalysis extends ForwardDataflowAnalysis<LockSet> {
}
}
+ @Override
public void makeFactTop(LockSet fact) {
fact.clear();
fact.setDefaultLockCount(LockSet.TOP);
}
+ @Override
public boolean isTop(LockSet fact) {
return fact.isTop();
}
+ @Override
public boolean same(LockSet fact1, LockSet fact2) {
return fact1.sameAs(fact2);
}
+ @Override
public void meetInto(LockSet fact, Edge edge, LockSet result) throws DataflowAnalysisException {
result.meetWith(fact);
}
@@ -120,10 +128,11 @@ public class LockAnalysis extends ForwardDataflowAnalysis<LockSet> {
String sig = inv.getSignature(methodGen.getConstantPool());
ValueNumberFrame frame = vnaDataflow.getFactAtLocation(new Location(handle, basicBlock));
- if (sig.equals("()V") && (name.equals("lock") || name.equals("lockInterruptibly")))
+ if ("()V".equals(sig) && ("lock".equals(name) || "lockInterruptibly".equals(name))) {
modifyLock(frame, fact, 1);
- else if (sig.equals("()V") && (name.equals("unlock")))
+ } else if ("()V".equals(sig) && ("unlock".equals(name))) {
modifyLock(frame, fact, -1);
+ }
} else if ((ins instanceof ReturnInstruction) && isSynchronized && !isStatic) {
@@ -140,14 +149,17 @@ public class LockAnalysis extends ForwardDataflowAnalysis<LockSet> {
private void lockOp(LockSet fact, int lockNumber, int delta) {
int value = fact.getLockCount(lockNumber);
- if (value < 0) // can't modify TOP or BOTTOM value
+ if (value < 0) {
return;
+ }
value += delta;
- if (value < 0)
+ if (value < 0) {
value = LockSet.BOTTOM;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("Setting " + lockNumber + " to " + value + " in " + methodGen.getClassName() + "."
+ methodGen.getName());
+ }
fact.setLockCount(lockNumber, value);
}
@@ -177,4 +189,3 @@ public class LockAnalysis extends ForwardDataflowAnalysis<LockSet> {
// }
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/LockChecker.java b/src/java/edu/umd/cs/findbugs/ba/LockChecker.java
index b5ca30c..57b7cd7 100644
--- a/src/java/edu/umd/cs/findbugs/ba/LockChecker.java
+++ b/src/java/edu/umd/cs/findbugs/ba/LockChecker.java
@@ -35,20 +35,20 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
* Front-end for LockDataflow that can avoid doing unnecessary work (e.g.,
* actually performing the lock dataflow) if the method analyzed does not
* contain explicit monitorenter/monitorexit instructions.
- *
+ *
* <p>
* Note that because LockSets use value numbers, ValueNumberAnalysis must be
* performed for all methods that are synchronized or contain explicit
* monitorenter/monitorexit instructions.
* </p>
- *
+ *
* @see LockSet
* @see LockDataflow
* @see LockAnalysis
* @author David Hovemeyer
*/
public class LockChecker {
- private MethodDescriptor methodDescriptor;
+ private final MethodDescriptor methodDescriptor;
private Method method;
@@ -56,7 +56,7 @@ public class LockChecker {
private ValueNumberDataflow vnaDataflow;
- private HashMap<Location, LockSet> cache;
+ private final HashMap<Location, LockSet> cache;
/**
* Constructor.
@@ -68,7 +68,7 @@ public class LockChecker {
/**
* Execute dataflow analyses (only if required).
- *
+ *
* @throws CheckedAnalysisException
*/
public void execute() throws CheckedAnalysisException {
@@ -77,30 +77,31 @@ public class LockChecker {
methodDescriptor.getClassDescriptor());
BitSet bytecodeSet = classContext.getBytecodeSet(method);
- if (bytecodeSet == null)
+ if (bytecodeSet == null) {
return;
+ }
if (bytecodeSet.get(Constants.MONITORENTER) || bytecodeSet.get(Constants.MONITOREXIT)) {
this.lockDataflow = classContext.getLockDataflow(method);
} else if (method.isSynchronized()) {
this.vnaDataflow = classContext.getValueNumberDataflow(method); // will
- // need
- // this
- // later
+ // need
+ // this
+ // later
}
}
/**
* Get LockSet at given Location.
- *
+ *
* @param location
* the Location
* @return the LockSet at that Location
* @throws DataflowAnalysisException
*/
public LockSet getFactAtLocation(Location location) throws DataflowAnalysisException {
- if (lockDataflow != null)
+ if (lockDataflow != null) {
return lockDataflow.getFactAtLocation(location);
- else {
+ } else {
LockSet lockSet = cache.get(location);
if (lockSet == null) {
lockSet = new LockSet();
diff --git a/src/java/edu/umd/cs/findbugs/ba/LockDataflow.java b/src/java/edu/umd/cs/findbugs/ba/LockDataflow.java
index 0db67a4..ccf08ce 100644
--- a/src/java/edu/umd/cs/findbugs/ba/LockDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/LockDataflow.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.ba;
/**
* Dataflow class for LockAnalysis.
- *
+ *
* @author David Hovemeyer
*/
public class LockDataflow extends Dataflow<LockSet, LockAnalysis> {
@@ -30,4 +30,3 @@ public class LockDataflow extends Dataflow<LockSet, LockAnalysis> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/LockSet.java b/src/java/edu/umd/cs/findbugs/ba/LockSet.java
index 8175780..34dc830 100644
--- a/src/java/edu/umd/cs/findbugs/ba/LockSet.java
+++ b/src/java/edu/umd/cs/findbugs/ba/LockSet.java
@@ -30,7 +30,7 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
* Lock counts for values (as produced by ValueNumberAnalysis). A LockSet tells
* us the lock counts for all values in a method, insofar as we can accurately
* determine them.
- *
+ *
* @author David Hovemeyer
* @see edu.umd.cs.findbugs.ba.vna.ValueNumberAnalysis
*/
@@ -74,17 +74,18 @@ public final class LockSet {
/**
* Get the lock count for given lock object.
- *
+ *
* @param valueNumber
* value number of the lock object
* @return the lock count for the lock object
*/
public int getLockCount(int valueNumber) {
int index = findIndex(valueNumber);
- if (index < 0)
+ if (index < 0) {
return defaultLockCount;
- else
+ } else {
return array[index + 1];
+ }
}
public boolean isTop() {
@@ -93,7 +94,7 @@ public final class LockSet {
/**
* Set the lock count for a lock object.
- *
+ *
* @param valueNumber
* value number of the lock object
* @param lockCount
@@ -110,7 +111,7 @@ public final class LockSet {
/**
* Set the default lock count to return for nonexistent lock entries.
- *
+ *
* @param defaultLockCount
* the default lock count value
*/
@@ -124,17 +125,19 @@ public final class LockSet {
public int getNumLockedObjects() {
int result = 0;
for (int i = 0; i < array.length; i += 2) {
- if (array[i] == INVALID)
+ if (array[i] == INVALID) {
break;
- if (array[i + 1] > 0)
+ }
+ if (array[i + 1] > 0) {
++result;
+ }
}
return result;
}
/**
* Make this LockSet the same as the given one.
- *
+ *
* @param other
* the LockSet to copy
*/
@@ -158,15 +161,16 @@ public final class LockSet {
/**
* Meet this LockSet with another LockSet, storing the result in this
* object.
- *
+ *
* @param other
* the other LockSet
*/
public void meetWith(LockSet other) {
for (int i = 0; i < array.length; i += 2) {
int valueNumber = array[i];
- if (valueNumber < 0)
+ if (valueNumber < 0) {
break;
+ }
int mine = array[i + 1];
int his = other.getLockCount(valueNumber);
@@ -175,8 +179,9 @@ public final class LockSet {
for (int i = 0; i < other.array.length; i += 2) {
int valueNumber = other.array[i];
- if (valueNumber < 0)
+ if (valueNumber < 0) {
break;
+ }
int mine = getLockCount(valueNumber);
int his = other.array[i + 1];
@@ -188,7 +193,7 @@ public final class LockSet {
/**
* Return whether or not this LockSet is the same as the one given.
- *
+ *
* @param other
* the other LockSet
*/
@@ -199,18 +204,20 @@ public final class LockSet {
/**
* Determine whether or not this lock set contains any locked values which
* are method return values.
- *
+ *
* @param factory
* the ValueNumberFactory that produced the lock values
*/
public boolean containsReturnValue(ValueNumberFactory factory) {
for (int i = 0; i < array.length; i += 2) {
int valueNumber = array[i];
- if (valueNumber < 0)
+ if (valueNumber < 0) {
break;
+ }
int lockCount = array[i + 1];
- if (lockCount > 0 && factory.forNumber(valueNumber).hasFlag(ValueNumber.RETURN_VALUE))
+ if (lockCount > 0 && factory.forNumber(valueNumber).hasFlag(ValueNumber.RETURN_VALUE)) {
return true;
+ }
}
return false;
}
@@ -219,18 +226,20 @@ public final class LockSet {
* Destructively intersect this lock set with another. Note that this is
* <em>not</em> a dataflow merge: we are interested in finding out which
* locks are held in both sets, not in the exact lock counts.
- *
+ *
* @param other
* the other LockSet
*/
public void intersectWith(LockSet other) {
for (int i = 0; i < array.length; i += 2) {
int valueNumber = array[i];
- if (valueNumber < 0)
+ if (valueNumber < 0) {
break;
+ }
int myLockCount = array[i + 1];
- if (myLockCount <= 0)
+ if (myLockCount <= 0) {
continue;
+ }
int otherLockCount = other.getLockCount(valueNumber);
if (otherLockCount <= 0) {
/* This set holds the lock, but the other one doesn't. */
@@ -242,17 +251,19 @@ public final class LockSet {
/**
* Return whether or not this lock set is empty, meaning that no locks have
* a positive lock count.
- *
+ *
* @return true if no locks are held, false if at least one lock is held
*/
public boolean isEmpty() {
for (int i = 0; i < array.length; i += 2) {
int valueNumber = array[i];
- if (valueNumber < 0)
+ if (valueNumber < 0) {
return true;
+ }
int myLockCount = array[i + 1];
- if (myLockCount > 0)
+ if (myLockCount > 0) {
return false;
+ }
}
return true;
}
@@ -260,42 +271,47 @@ public final class LockSet {
private boolean identicalSubset(LockSet other) {
for (int i = 0; i < array.length; i += 2) {
int valueNumber = array[i];
- if (valueNumber < 0)
+ if (valueNumber < 0) {
break;
+ }
int mine = array[i + 1];
int his = other.getLockCount(valueNumber);
if (mine != his)
+ {
return false;
- // System.out.println("For value " + valueNumber + ", " + mine +
- // "==" + his);
+ // System.out.println("For value " + valueNumber + ", " + mine +
+ // "==" + his);
+ }
}
return true;
}
private static int mergeValues(int a, int b) {
- if (a == TOP)
+ if (a == TOP) {
return b;
- else if (b == TOP)
+ } else if (b == TOP) {
return a;
- else if (a == BOTTOM || b == BOTTOM)
+ } else if (a == BOTTOM || b == BOTTOM) {
return BOTTOM;
- else if (a == b)
+ } else if (a == b) {
return a;
- else
+ } else {
return BOTTOM;
+ }
}
private int findIndex(int valueNumber) {
for (int i = 0; i < array.length; i += 2) {
int value = array[i];
- if (value < 0)
+ if (value < 0) {
return -(i + 1); // didn't find requested valueNumber - return
- // first available slot
- else if (value == valueNumber)
+ } else if (value == valueNumber)
+ {
return i; // found requested valueNumber
+ }
}
return -(array.length + 1); // didn't find requested valueNumber, and
- // array is full
+ // array is full
}
private void addEntry(int negatedIndex, int valueNumber, int lockCount) {
@@ -336,23 +352,27 @@ public final class LockSet {
}
for (int i = 0; i < array.length; i += 2) {
int valueNumber = array[i];
- if (valueNumber < 0)
+ if (valueNumber < 0) {
continue;
+ }
int lockCount = array[i + 1];
- if (lockCount == 0)
+ if (lockCount == 0) {
continue;
- if (first)
+ }
+ if (first) {
first = false;
- else
+ } else {
buf.append(',');
+ }
buf.append(valueNumber);
buf.append('=');
- if (lockCount == TOP)
+ if (lockCount == TOP) {
buf.append("TOP");
- else if (lockCount == BOTTOM)
+ } else if (lockCount == BOTTOM) {
buf.append("BOTTOM");
- else
+ } else {
buf.append(lockCount);
+ }
}
buf.append(']');
return buf.toString();
@@ -363,12 +383,15 @@ public final class LockSet {
* @return a set of the locked value numbers
*/
public Collection<ValueNumber> getLockedValueNumbers(ValueNumberFrame frame) {
- if (frame == null)
+ if (frame == null) {
throw new IllegalArgumentException("Null Frame");
+ }
HashSet<ValueNumber> result = new HashSet<ValueNumber>();
- for (ValueNumber v : frame.allSlots())
- if (v != null && getLockCount(v.getNumber()) > 0)
+ for (ValueNumber v : frame.allSlots()) {
+ if (v != null && getLockCount(v.getNumber()) > 0) {
result.add(v);
+ }
+ }
return result;
}
@@ -380,11 +403,10 @@ public final class LockSet {
* 1); ll.setLockCount(69, 3); LockSet tmp = new LockSet();
* tmp.copyFrom(ll); ll.meetWith(l); System.out.println(l + " merge with " +
* tmp + " ==> " + ll);
- *
+ *
* LockSet dup = new LockSet(); dup.copyFrom(ll); System.out.println(ll +
* " == " + dup + " ==> " + ll.sameAs(dup)); System.out.println(ll + " == "
* + l + " ==> " + ll.sameAs(l)); }
*/
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/MethodBytecodeSet.java b/src/java/edu/umd/cs/findbugs/ba/MethodBytecodeSet.java
index 221e1cc..0178479 100644
--- a/src/java/edu/umd/cs/findbugs/ba/MethodBytecodeSet.java
+++ b/src/java/edu/umd/cs/findbugs/ba/MethodBytecodeSet.java
@@ -25,7 +25,7 @@ import org.apache.bcel.Constants;
/**
* Class representing the set of opcodes used in a method.
- *
+ *
* @author David Hovemeyer
*/
public class MethodBytecodeSet extends BitSet {
diff --git a/src/java/edu/umd/cs/findbugs/ba/MethodChooser.java b/src/java/edu/umd/cs/findbugs/ba/MethodChooser.java
index 432b917..6471a85 100644
--- a/src/java/edu/umd/cs/findbugs/ba/MethodChooser.java
+++ b/src/java/edu/umd/cs/findbugs/ba/MethodChooser.java
@@ -23,13 +23,13 @@ import org.apache.bcel.classfile.Method;
/**
* Interface for choosing methods.
- *
+ *
* @author David Hovemeyer
*/
public interface MethodChooser {
/**
* Determine whether or not given method should be chosen.
- *
+ *
* @param method
* the Method
* @return true if the method should be chosen, false if not
diff --git a/src/java/edu/umd/cs/findbugs/ba/MethodHash.java b/src/java/edu/umd/cs/findbugs/ba/MethodHash.java
index 51c35bc..1cebf79 100644
--- a/src/java/edu/umd/cs/findbugs/ba/MethodHash.java
+++ b/src/java/edu/umd/cs/findbugs/ba/MethodHash.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.util.Util;
/**
* Compute a hash of the bytecode for given method. This can find methods which
* have not been changed other than accessing different constant pool entries.
- *
+ *
* @author David Hovemeyer
*/
public class MethodHash implements Comparable<MethodHash> {
@@ -51,7 +51,7 @@ public class MethodHash implements Comparable<MethodHash> {
/**
* Constructor.
- *
+ *
* @param methodName
* method name
* @param methodSig
@@ -92,7 +92,7 @@ public class MethodHash implements Comparable<MethodHash> {
/**
* Get the computed method hash.
- *
+ *
* @return the method hash
*/
public byte[] getMethodHash() {
@@ -101,7 +101,7 @@ public class MethodHash implements Comparable<MethodHash> {
/**
* Compute hash on given method.
- *
+ *
* @param method
* the method
* @return this object
@@ -117,6 +117,7 @@ public class MethodHash implements Comparable<MethodHash> {
}
BytecodeScanner.Callback callback = new BytecodeScanner.Callback() {
+ @Override
public void handleInstruction(int opcode, int index) {
digest.update((byte) opcode);
}
@@ -133,7 +134,7 @@ public class MethodHash implements Comparable<MethodHash> {
/**
* Return whether or not this method hash has the same value as the one
* given.
- *
+ *
* @param other
* another MethodHash
* @return true if the hash values are the same, false if not
@@ -144,25 +145,28 @@ public class MethodHash implements Comparable<MethodHash> {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Comparable#compareTo(T)
*/
+ @Override
public int compareTo(MethodHash other) {
return MethodHash.compareHashes(this.hash, other.hash);
}
@Override
public boolean equals(Object o) {
- if (o instanceof MethodHash)
+ if (o instanceof MethodHash) {
return isSameHash((MethodHash) o);
+ }
return false;
}
@Override
public int hashCode() {
int result = 0;
- for (byte b : hash)
+ for (byte b : hash) {
result = result * 17 + b;
+ }
return result;
}
@@ -170,15 +174,16 @@ public class MethodHash implements Comparable<MethodHash> {
int pfxlen = Math.min(a.length, b.length);
for (int i = 0; i < pfxlen; ++i) {
int cmp = toUnsigned(a[i]) - toUnsigned(b[i]);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
}
return a.length - b.length;
}
/**
* Convert a byte to an unsigned int.
- *
+ *
* @param b
* a byte value
* @return the unsigned integer value of the byte
diff --git a/src/java/edu/umd/cs/findbugs/ba/MethodUnprofitableException.java b/src/java/edu/umd/cs/findbugs/ba/MethodUnprofitableException.java
index 5bc6b2c..51bf4bf 100644
--- a/src/java/edu/umd/cs/findbugs/ba/MethodUnprofitableException.java
+++ b/src/java/edu/umd/cs/findbugs/ba/MethodUnprofitableException.java
@@ -26,7 +26,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Used to signal a method not analyzed because it seemed unprofitable to do so
- *
+ *
* @author pugh
*/
public class MethodUnprofitableException extends CFGBuilderException {
@@ -36,7 +36,7 @@ public class MethodUnprofitableException extends CFGBuilderException {
/**
* Constructor.
- *
+ *
* @param method
* the method that is unprofitable to analyze
*/
@@ -47,7 +47,7 @@ public class MethodUnprofitableException extends CFGBuilderException {
/**
* Constructor.
- *
+ *
* @param jClass
* the class containing the method that is unprofitable to
* analyze
@@ -61,7 +61,7 @@ public class MethodUnprofitableException extends CFGBuilderException {
/**
* Constructor.
- *
+ *
* @param methodDescriptor
* the MethodDescriptor indicating the method it is unprofitable
* to analyze
diff --git a/src/java/edu/umd/cs/findbugs/ba/MissingClassException.java b/src/java/edu/umd/cs/findbugs/ba/MissingClassException.java
index 5799d8c..e0a933e 100644
--- a/src/java/edu/umd/cs/findbugs/ba/MissingClassException.java
+++ b/src/java/edu/umd/cs/findbugs/ba/MissingClassException.java
@@ -26,13 +26,14 @@ import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
/**
* DataflowAnalysisException variant to report a class lookup failure that
* caused dataflow analysis to abort.
- *
+ *
* @author David Hovemeyer
*/
public class MissingClassException extends DataflowAnalysisException {
private static final long serialVersionUID = 1L;
private @DottedClassName
+ final
String className;
private MissingClassException(String className) {
@@ -42,7 +43,7 @@ public class MissingClassException extends DataflowAnalysisException {
/**
* Constructor.
- *
+ *
* @param exception
* the ClassNotFoundException that caused this exception
*/
@@ -53,7 +54,7 @@ public class MissingClassException extends DataflowAnalysisException {
/**
* Get the name of the missing class.
- *
+ *
* @return name of the missing class, or null if the missing class name is
* unknown
*/
@@ -67,7 +68,7 @@ public class MissingClassException extends DataflowAnalysisException {
/**
* Get the ClassNotFoundException that caused this exception.
- *
+ *
* @return the ClassNotFoundException that caused this exception
*/
public ClassNotFoundException getClassNotFoundException() {
diff --git a/src/java/edu/umd/cs/findbugs/ba/NullnessAnnotation.java b/src/java/edu/umd/cs/findbugs/ba/NullnessAnnotation.java
index 7b5ed8a..3babf9f 100644
--- a/src/java/edu/umd/cs/findbugs/ba/NullnessAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/ba/NullnessAnnotation.java
@@ -42,9 +42,9 @@ public class NullnessAnnotation extends AnnotationEnumeration<NullnessAnnotation
@CheckForNull
public static NullnessAnnotation parse(@DottedClassName String className) {
className = ClassName.toDottedClassName(className);
- if (className.equals("com.google.common.base.Nullable")
- || className.equals("org.eclipse.jdt.annotation.Nullable")
- || className.equals("org.jetbrains.annotations.Nullable")) {
+ if ("com.google.common.base.Nullable".equals(className)
+ || "org.eclipse.jdt.annotation.Nullable".equals(className)
+ || "org.jetbrains.annotations.Nullable".equals(className)) {
return CHECK_FOR_NULL;
}
// Unfortunately there are mixed case Nonnull and NonNull annotations (JSR305, FB and JDT)
diff --git a/src/java/edu/umd/cs/findbugs/ba/NullnessAnnotationDatabase.java b/src/java/edu/umd/cs/findbugs/ba/NullnessAnnotationDatabase.java
index bd0bae1..16619d9 100644
--- a/src/java/edu/umd/cs/findbugs/ba/NullnessAnnotationDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/NullnessAnnotationDatabase.java
@@ -42,20 +42,23 @@ public class NullnessAnnotationDatabase extends AnnotationDatabase<NullnessAnnot
DefaultNullnessAnnotations.addDefaultNullnessAnnotations(this);
}
+ @Override
public boolean parameterMustBeNonNull(XMethod m, int param) {
if (param == 0) {
- if (m.getName().equals("equals") && m.getSignature().equals("(Ljava/lang/Object;)Z") && !m.isStatic())
+ if ("equals".equals(m.getName()) && "(Ljava/lang/Object;)Z".equals(m.getSignature()) && !m.isStatic()) {
return false;
- else if (m.getName().equals("main") && m.getSignature().equals("([Ljava/lang/String;)V") && m.isStatic()
- && m.isPublic())
+ } else if ("main".equals(m.getName()) && "([Ljava/lang/String;)V".equals(m.getSignature()) && m.isStatic()
+ && m.isPublic()) {
return true;
- else if (TypeQualifierNullnessAnnotationDatabase.assertsFirstParameterIsNonnull(m))
+ } else if (TypeQualifierNullnessAnnotationDatabase.assertsFirstParameterIsNonnull(m)) {
return true;
- else if (m.getName().equals("compareTo") && m.getSignature().endsWith(";)Z") && !m.isStatic())
+ } else if ("compareTo".equals(m.getName()) && m.getSignature().endsWith(";)Z") && !m.isStatic()) {
return true;
+ }
}
- if (!anyAnnotations(NullnessAnnotation.NONNULL))
+ if (!anyAnnotations(NullnessAnnotation.NONNULL)) {
return false;
+ }
XMethodParameter xmp = new XMethodParameter(m, param);
NullnessAnnotation resolvedAnnotation = getResolvedAnnotation(xmp, true);
@@ -77,34 +80,37 @@ public class NullnessAnnotationDatabase extends AnnotationDatabase<NullnessAnnot
// bug code for it
int parameterNumber = mp.getParameterNumber();
if (parameterNumber == 0) {
- if (m.getName().equals("equals") && m.getSignature().equals("(Ljava/lang/Object;)Z") && !m.isStatic())
+ if ("equals".equals(m.getName()) && "(Ljava/lang/Object;)Z".equals(m.getSignature()) && !m.isStatic()) {
return NullnessAnnotation.CHECK_FOR_NULL;
- else if (m.getName().equals("main") && m.getSignature().equals("([Ljava/lang/String;)V") && m.isStatic()
- && m.isPublic())
+ } else if ("main".equals(m.getName()) && "([Ljava/lang/String;)V".equals(m.getSignature()) && m.isStatic()
+ && m.isPublic()) {
return NullnessAnnotation.NONNULL;
- else if (TypeQualifierNullnessAnnotationDatabase.assertsFirstParameterIsNonnull(m))
+ } else if (TypeQualifierNullnessAnnotationDatabase.assertsFirstParameterIsNonnull(m)) {
return NullnessAnnotation.NONNULL;
- else if (m.getName().equals("compareTo") && m.getSignature().endsWith(";)Z") && !m.isStatic())
+ } else if ("compareTo".equals(m.getName()) && m.getSignature().endsWith(";)Z") && !m.isStatic()) {
return NullnessAnnotation.NONNULL;
+ }
}
} else if (o instanceof XMethod) {
XMethod m = (XMethod) o;
String name = m.getName();
String signature = m.getSignature();
if (!m.isStatic()
- && (name.equals("clone") && signature.equals("()Ljava/lang/Object;") || name.equals("toString")
- && signature.equals("()Ljava/lang/String;") || m.isPrivate() && name.equals("readResolve")
- && signature.equals("()Ljava/lang/Object;"))) {
+ && ("clone".equals(name) && "()Ljava/lang/Object;".equals(signature) || "toString".equals(name)
+ && "()Ljava/lang/String;".equals(signature) || m.isPrivate() && "readResolve".equals(name)
+ && "()Ljava/lang/Object;".equals(signature))) {
NullnessAnnotation result = super.getDirectAnnotation(m);
- if (result != null)
+ if (result != null) {
return result;
+ }
return NullnessAnnotation.NONNULL;
}
} else if (o instanceof XField) {
XField f = (XField) o;
- if (f.getName().startsWith("this$"))
+ if (f.getName().startsWith("this$")) {
return NullnessAnnotation.NONNULL;
+ }
}
NullnessAnnotation result = super.getResolvedAnnotation(o, getMinimal);
return result;
@@ -113,7 +119,7 @@ public class NullnessAnnotationDatabase extends AnnotationDatabase<NullnessAnnot
}
}
-
+
@Override
public void addDefaultMethodAnnotation(String name, NullnessAnnotation annotation) {
diff --git a/src/java/edu/umd/cs/findbugs/ba/ObjectTypeFactory.java b/src/java/edu/umd/cs/findbugs/ba/ObjectTypeFactory.java
index cc03eab..c415d0a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ObjectTypeFactory.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ObjectTypeFactory.java
@@ -48,22 +48,24 @@ public class ObjectTypeFactory {
public static ObjectType getInstance(Class<?> c) {
return getInstance(c.getName());
}
-
-
+
+
public static ObjectType getInstance(@DottedClassName String s) {
if (FindBugs.DEBUG && s.startsWith("[")) {
throw new IllegalArgumentException("Cannot create an ObjectType to represent an array type: " + s);
}
- if (s.endsWith(";"))
+ if (s.endsWith(";")) {
throw new IllegalArgumentException(s);
- if (s.indexOf("/") >= 0) {
+ }
+ if (s.indexOf('/') >= 0) {
s = s.replace('/', '.');
}
Map<String, ObjectType> map = instance.get();
ObjectType result = map.get(s);
- if (result != null)
+ if (result != null) {
return result;
+ }
result = ObjectType.getInstance(s);
map.put(s, result);
return result;
diff --git a/src/java/edu/umd/cs/findbugs/ba/OpcodeStackScanner.java b/src/java/edu/umd/cs/findbugs/ba/OpcodeStackScanner.java
index b1e4d9c..48b97e5 100644
--- a/src/java/edu/umd/cs/findbugs/ba/OpcodeStackScanner.java
+++ b/src/java/edu/umd/cs/findbugs/ba/OpcodeStackScanner.java
@@ -87,11 +87,17 @@ public class OpcodeStackScanner {
@Override
public void sawOpcode(int seen) {
+ }
+
+ @Override
+ public void afterOpcode(int seen) {
if(DEBUG) {
System.out.printf("%3d: %8s %s%n", getPC(), OPCODE_NAMES[seen], getStack());
}
- if (getPC() == targetPC)
+ if (getPC() == targetPC) {
throw new EarlyExitException(stack);
+ }
+ super.afterOpcode(seen);
}
@Override
diff --git a/src/java/edu/umd/cs/findbugs/ba/Path.java b/src/java/edu/umd/cs/findbugs/ba/Path.java
index 78335c3..8e8bf49 100644
--- a/src/java/edu/umd/cs/findbugs/ba/Path.java
+++ b/src/java/edu/umd/cs/findbugs/ba/Path.java
@@ -25,7 +25,7 @@ import org.apache.bcel.generic.InstructionHandle;
/**
* A Path is a sequence of basic blocks.
- *
+ *
* @author David Hovemeyer
*/
public class Path {
@@ -50,7 +50,7 @@ public class Path {
/**
* Append given BasicBlock id to the path.
- *
+ *
* @param id
* a BasicBlock id (label)
*/
@@ -64,7 +64,7 @@ public class Path {
/**
* Determine whether or not the id of the given BasicBlock appears anywhere
* in the path.
- *
+ *
* @param blockId
* the id (label) of a BasicBlock
* @return true if the BasicBlock's id appears in the path, false if not
@@ -80,7 +80,7 @@ public class Path {
/**
* Get the BasicBlock id at the given index in the path.
- *
+ *
* @param index
* an index in the Path (0 is the first component)
* @return the id of the BasicBlock at the given index
@@ -92,7 +92,7 @@ public class Path {
/**
* Get the number of components (BasicBlock ids) in the Path.
- *
+ *
* @return number of components in the Path
*/
public int getLength() {
@@ -101,7 +101,7 @@ public class Path {
/**
* Return an exact copy of this Path.
- *
+ *
* @return an exact copy of this Path
*/
public Path duplicate() {
@@ -112,7 +112,7 @@ public class Path {
/**
* Make this Path identical to the given one.
- *
+ *
* @param other
* a Path to which this object should be made identical
*/
@@ -125,7 +125,7 @@ public class Path {
/**
* Accept a PathVisitor.
- *
+ *
* @param cfg
* the control flow graph
* @param visitor
@@ -141,7 +141,7 @@ public class Path {
/**
* Accept a PathVisitor, starting from a given BasicBlock and
* InstructionHandle.
- *
+ *
* @param cfg
* the control flow graph
* @param visitor
@@ -206,7 +206,7 @@ public class Path {
/**
* Determine whether or not given Path is a prefix of this one.
- *
+ *
* @param path
* another Path
* @return true if this Path is a prefix of the other Path, false otherwise
@@ -241,14 +241,17 @@ public class Path {
@Override
public boolean equals(Object o) {
- if (o == null || o.getClass() != this.getClass())
+ if (o == null || o.getClass() != this.getClass()) {
return false;
+ }
Path other = (Path) o;
- if (this.length != other.length)
+ if (this.length != other.length) {
return false;
+ }
for (int i = 0; i < this.length; ++i) {
- if (this.blockIdList[i] != other.blockIdList[i])
+ if (this.blockIdList[i] != other.blockIdList[i]) {
return false;
+ }
}
return true;
}
@@ -260,10 +263,11 @@ public class Path {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < length; ++i) {
int block = blockIdList[i];
- if (block < SYMBOLS.length())
+ if (block < SYMBOLS.length()) {
buf.append(SYMBOLS.charAt(block));
- else
+ } else {
buf.append("'" + block + "'");
+ }
}
return buf.toString();
}
@@ -282,4 +286,3 @@ public class Path {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/PathVisitor.java b/src/java/edu/umd/cs/findbugs/ba/PathVisitor.java
index cc72ad5..7939b82 100644
--- a/src/java/edu/umd/cs/findbugs/ba/PathVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/PathVisitor.java
@@ -23,13 +23,13 @@ import org.apache.bcel.generic.InstructionHandle;
/**
* Visit the BasicBlocks, InstructionHandles, and Edges along a Path.
- *
+ *
* @author David Hovemeyer
*/
public interface PathVisitor {
/**
* Start to visit the given BasicBlock.
- *
+ *
* @param basicBlock
* a BasicBlock in the Path being visited
*/
@@ -37,7 +37,7 @@ public interface PathVisitor {
/**
* Visit an InstructionHandle within the BasicBlock currently being visited.
- *
+ *
* @param handle
* an InstructionHandle within the current BasicBlock
*/
@@ -45,7 +45,7 @@ public interface PathVisitor {
/**
* Visit an Edge connecting two BasicBlocks in the Path being visited.
- *
+ *
* @param edge
* an Edge connecting two BasicBlocks in the Path being visited
*/
diff --git a/src/java/edu/umd/cs/findbugs/ba/PostDominatorsAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/PostDominatorsAnalysis.java
index c68c66b..9d491ed 100644
--- a/src/java/edu/umd/cs/findbugs/ba/PostDominatorsAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/PostDominatorsAnalysis.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.ba;
/**
* Dataflow analysis to compute postdominator sets for a CFG.
- *
+ *
* @author David Hovemeyer
* @see CFG
* @see AbstractDominatorsAnalysis
@@ -33,7 +33,7 @@ public class PostDominatorsAnalysis extends AbstractDominatorsAnalysis {
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG to compute dominator relationships for
* @param rdfs
@@ -51,7 +51,7 @@ public class PostDominatorsAnalysis extends AbstractDominatorsAnalysis {
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG to compute dominator relationships for
* @param rdfs
@@ -67,10 +67,12 @@ public class PostDominatorsAnalysis extends AbstractDominatorsAnalysis {
this.dfs = dfs;
}
+ @Override
public boolean isForwards() {
return false;
}
+ @Override
public BlockOrder getBlockOrder(CFG cfg) {
return new ReverseDFSOrder(cfg, rdfs, dfs);
}
@@ -117,4 +119,3 @@ public class PostDominatorsAnalysis extends AbstractDominatorsAnalysis {
// }
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/PruneInfeasibleExceptionEdges.java b/src/java/edu/umd/cs/findbugs/ba/PruneInfeasibleExceptionEdges.java
index 46e678e..6c0a06a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/PruneInfeasibleExceptionEdges.java
+++ b/src/java/edu/umd/cs/findbugs/ba/PruneInfeasibleExceptionEdges.java
@@ -28,6 +28,7 @@ import java.util.Set;
import org.apache.bcel.generic.MethodGen;
import edu.umd.cs.findbugs.SystemProperties;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import edu.umd.cs.findbugs.ba.ch.Subtypes2;
import edu.umd.cs.findbugs.ba.type.ExceptionSet;
import edu.umd.cs.findbugs.ba.type.TypeDataflow;
@@ -36,7 +37,7 @@ import edu.umd.cs.findbugs.ba.type.TypeDataflow;
* Prune a CFG to remove infeasible exception edges. In order to determine what
* kinds of exceptions can be thrown by explicit ATHROW instructions, type
* analysis must first be performed on the unpruned CFG.
- *
+ *
* @author David Hovemeyer
* @see CFG
* @see edu.umd.cs.findbugs.ba.type.TypeAnalysis
@@ -68,9 +69,9 @@ public class PruneInfeasibleExceptionEdges implements EdgeTypes {
* successful.
*/
private static class MarkedEdge {
- private Edge edge;
+ private final Edge edge;
- private int flag;
+ private final int flag;
public MarkedEdge(Edge edge, int flag) {
this.edge = edge;
@@ -84,15 +85,15 @@ public class PruneInfeasibleExceptionEdges implements EdgeTypes {
}
}
- private CFG cfg;
+ private final CFG cfg;
- private TypeDataflow typeDataflow;
+ private final TypeDataflow typeDataflow;
private boolean cfgModified;
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG to prune
* @param methodGen
@@ -116,6 +117,7 @@ public class PruneInfeasibleExceptionEdges implements EdgeTypes {
* runtime exception is thrown, then the CFG may be partially modified and
* should be considered invalid.
*/
+ @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
public void execute() throws ClassNotFoundException {
Set<Edge> deletedEdgeSet = new HashSet<Edge>();
List<MarkedEdge> markedEdgeList = new LinkedList<MarkedEdge>();
@@ -124,8 +126,9 @@ public class PruneInfeasibleExceptionEdges implements EdgeTypes {
// mark edges to set properties of
for (Iterator<Edge> i = cfg.edgeIterator(); i.hasNext();) {
Edge edge = i.next();
- if (!edge.isExceptionEdge())
+ if (!edge.isExceptionEdge()) {
continue;
+ }
ExceptionSet exceptionSet = typeDataflow.getEdgeExceptionSet(edge);
if (exceptionSet.isEmpty()) {
@@ -148,10 +151,12 @@ public class PruneInfeasibleExceptionEdges implements EdgeTypes {
boolean someExplicit = exceptionSet.containsExplicitExceptions();
int flags = 0;
- if (someChecked)
+ if (someChecked) {
flags |= CHECKED_EXCEPTIONS_FLAG;
- if (someExplicit)
+ }
+ if (someExplicit) {
flags |= EXPLICIT_EXCEPTIONS_FLAG;
+ }
markedEdgeList.add(new MarkedEdge(edge, flags));
}
@@ -160,8 +165,9 @@ public class PruneInfeasibleExceptionEdges implements EdgeTypes {
// Remove deleted edges
for (Edge edge : deletedEdgeSet) {
cfg.removeEdge(edge);
- if (STATS)
+ if (STATS) {
++numEdgesPruned;
+ }
cfgModified = true;
}
@@ -179,4 +185,3 @@ public class PruneInfeasibleExceptionEdges implements EdgeTypes {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/PruneUnconditionalExceptionThrowerEdges.java b/src/java/edu/umd/cs/findbugs/ba/PruneUnconditionalExceptionThrowerEdges.java
index 214b530..796bea6 100644
--- a/src/java/edu/umd/cs/findbugs/ba/PruneUnconditionalExceptionThrowerEdges.java
+++ b/src/java/edu/umd/cs/findbugs/ba/PruneUnconditionalExceptionThrowerEdges.java
@@ -50,15 +50,15 @@ public class PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {
private static final String UNCONDITIONAL_THROWER_METHOD_NAMES = SystemProperties.getProperty(
"findbugs.unconditionalThrower", " ").replace(',', '|');
- private MethodGen methodGen;
+ private final MethodGen methodGen;
- private CFG cfg;
+ private final CFG cfg;
- private ConstantPoolGen cpg;
+ private final ConstantPoolGen cpg;
- private TypeDataflow typeDataflow;
+ private final TypeDataflow typeDataflow;
- private AnalysisContext analysisContext;
+ private final AnalysisContext analysisContext;
private boolean cfgModified;
@@ -98,25 +98,29 @@ public class PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {
public void execute() throws DataflowAnalysisException {
AnalysisContext currentAnalysisContext = AnalysisContext.currentAnalysisContext();
- if (currentAnalysisContext.getBoolProperty(AnalysisFeatures.CONSERVE_SPACE))
+ if (currentAnalysisContext.getBoolProperty(AnalysisFeatures.CONSERVE_SPACE)) {
throw new IllegalStateException("This should not happen");
+ }
boolean foundInexact = false;
Set<Edge> deletedEdgeSet = new HashSet<Edge>();
// TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("PruneUnconditionalExceptionThrowerEdges: examining "
+ SignatureConverter.convertMethodSignature(methodGen));
+ }
for (Iterator<BasicBlock> i = cfg.blockIterator(); i.hasNext();) {
BasicBlock basicBlock = i.next();
- if (!basicBlock.isExceptionThrower())
+ if (!basicBlock.isExceptionThrower()) {
continue;
+ }
InstructionHandle instructionHandle = basicBlock.getExceptionThrower();
Instruction exceptionThrower = instructionHandle.getInstruction();
- if (!(exceptionThrower instanceof InvokeInstruction))
+ if (!(exceptionThrower instanceof InvokeInstruction)) {
continue;
+ }
InvokeInstruction inv = (InvokeInstruction) exceptionThrower;
boolean foundThrower = false;
@@ -125,12 +129,14 @@ public class PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {
XMethod primaryXMethod = XFactory.createXMethod(inv, cpg);
final String methodName = primaryXMethod.getName();
final boolean matches = unconditionalThrowerPattern.matcher(methodName).matches();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Checking '" + methodName + "' is " + matches);
+ }
if (matches) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\tmatched for " + instructionHandle + " : " + primaryXMethod);
+ }
foundThrower = true;
} else if (inv instanceof INVOKEINTERFACE) {
@@ -139,8 +145,9 @@ public class PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {
foundThrower = isUnconditionalThrower(primaryXMethod);
} else {
String className = inv.getClassName(cpg);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\tlooking up method for " + instructionHandle + " : " + primaryXMethod);
+ }
Location loc = new Location(instructionHandle, basicBlock);
TypeFrame typeFrame = typeDataflow.getFactAtLocation(loc);
@@ -148,39 +155,46 @@ public class PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {
Set<XMethod> targetSet = null;
try {
- if (className.startsWith("["))
+ if (className.startsWith("[")) {
continue;
+ }
String methodSig = inv.getSignature(cpg);
- if (!methodSig.endsWith("V") && !methodSig.endsWith("Exception;")
- && !methodSig.endsWith("Error;") && !methodSig.endsWith(")Ljava/lang/Object;"))
+ if (!methodSig.endsWith("V") && !methodSig.endsWith("Exception;")
+ && !methodSig.endsWith("Error;") && !methodSig.endsWith(")Ljava/lang/Object;")) {
continue;
+ }
targetSet = Hierarchy2.resolveMethodCallTargets(inv, typeFrame, cpg);
for (XMethod xMethod : targetSet) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\tFound " + xMethod);
+ }
// Ignore abstract and native methods
- if (!(xMethod.isFinal() || xMethod.isStatic() || xMethod.isPrivate()))
- try {
- isExact = false;
- XClass xClass = Global.getAnalysisCache().getClassAnalysis(XClass.class,
- xMethod.getClassDescriptor());
- if (xClass.isAbstract())
- continue;
- } catch (CheckedAnalysisException e) {
- AnalysisContext.logError("Unable to resolve class for " + xMethod, e);
- }
boolean isUnconditionalThrower = isUnconditionalThrower(xMethod);
if (isUnconditionalThrower) {
+ if (!(xMethod.isFinal() || xMethod.isStatic() || xMethod.isPrivate())) {
+ try {
+ isExact = false;
+ XClass xClass = Global.getAnalysisCache().getClassAnalysis(XClass.class,
+ xMethod.getClassDescriptor());
+ if (xClass.isAbstract()) {
+ continue;
+ }
+ } catch (CheckedAnalysisException e) {
+ AnalysisContext.logError("Unable to resolve class for " + xMethod, e);
+ }
+ }
foundThrower = true;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Found thrower");
+ }
} else {
foundNonThrower = true;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Found non thrower");
+ }
}
}
@@ -190,8 +204,9 @@ public class PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {
}
boolean newResult = foundThrower && !foundNonThrower;
if (newResult) {
- if (!isExact)
+ if (!isExact) {
foundInexact = true;
+ }
// Method always throws an unhandled exception
// Remove the normal control flow edge from the CFG.
Edge fallThrough = cfg.getOutgoingEdgeWithType(basicBlock, FALL_THROUGH_EDGE);
@@ -207,8 +222,9 @@ public class PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {
if (!deletedEdgeSet.isEmpty()) {
cfgModified = true;
- if (foundInexact)
+ if (foundInexact) {
cfg.setFlag(CFG.FOUND_INEXACT_UNCONDITIONAL_THROWERS);
+ }
// Remove all edges marked for deletion
for (Edge edge : deletedEdgeSet) {
cfg.removeEdge(edge);
@@ -217,10 +233,6 @@ public class PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {
}
}
- /**
- * @param xMethod
- * @return
- */
private boolean isUnconditionalThrower(XMethod xMethod) {
return xMethod.isUnconditionalThrower() && !xMethod.isUnsupported() && !xMethod.isSynthetic();
}
@@ -248,7 +260,7 @@ public class PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {
/**
* Return whether or not the CFG was modified.
- *
+ *
* @return true if CFG was modified, false otherwise
*/
public boolean wasCFGModified() {
@@ -256,4 +268,3 @@ public class PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/PutfieldScanner.java b/src/java/edu/umd/cs/findbugs/ba/PutfieldScanner.java
index 6127634..942fd3e 100644
--- a/src/java/edu/umd/cs/findbugs/ba/PutfieldScanner.java
+++ b/src/java/edu/umd/cs/findbugs/ba/PutfieldScanner.java
@@ -59,11 +59,13 @@ public class PutfieldScanner {
@Override
public void sawOpcode(int seen) {
- if (seen != PUTFIELD)
+ if (seen != PUTFIELD) {
return;
+ }
XField xFieldOperand = getXFieldOperand();
- if (xFieldOperand != null && xFieldOperand.equals(targetField) && stack.getStackItem(1).getRegisterNumber() == 0)
+ if (xFieldOperand != null && xFieldOperand.equals(targetField) && stack.getStackItem(1).getRegisterNumber() == 0) {
putfields.put(getPC(), new OpcodeStack.Item(stack.getStackItem(0)));
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/RepositoryClassParser.java b/src/java/edu/umd/cs/findbugs/ba/RepositoryClassParser.java
index 8f6ae02..fc54152 100644
--- a/src/java/edu/umd/cs/findbugs/ba/RepositoryClassParser.java
+++ b/src/java/edu/umd/cs/findbugs/ba/RepositoryClassParser.java
@@ -32,11 +32,11 @@ import org.apache.bcel.classfile.JavaClass;
* class hierarchy, based on the current class path.
*/
public class RepositoryClassParser {
- private ClassParser classParser;
+ private final ClassParser classParser;
/**
* Constructor.
- *
+ *
* @param inputStream
* the input stream from which to read the class file
* @param fileName
@@ -48,7 +48,7 @@ public class RepositoryClassParser {
/**
* Constructor.
- *
+ *
* @param fileName
* name of the class file
*/
@@ -58,7 +58,7 @@ public class RepositoryClassParser {
/**
* Constructor.
- *
+ *
* @param zipFile
* name of a zip file containing the class
* @param fileName
@@ -71,7 +71,7 @@ public class RepositoryClassParser {
/**
* Parse the class file into a JavaClass object. If succesful, the new
* JavaClass is entered into the Repository.
- *
+ *
* @return the parsed JavaClass
* @throws IOException
* if the class cannot be parsed
@@ -83,4 +83,3 @@ public class RepositoryClassParser {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/RepositoryLookupFailureCallback.java b/src/java/edu/umd/cs/findbugs/ba/RepositoryLookupFailureCallback.java
index 4a1a1d3..282dd13 100644
--- a/src/java/edu/umd/cs/findbugs/ba/RepositoryLookupFailureCallback.java
+++ b/src/java/edu/umd/cs/findbugs/ba/RepositoryLookupFailureCallback.java
@@ -30,7 +30,7 @@ import edu.umd.cs.findbugs.classfile.IErrorLogger;
* failure. However, it is important to report such lookup failures to the user.
* So, classes that use the Repository should have a callback object to report
* lookup failures to.
- *
+ *
* @author David Hovemeyer
*/
@@ -38,4 +38,3 @@ import edu.umd.cs.findbugs.classfile.IErrorLogger;
public interface RepositoryLookupFailureCallback extends IErrorLogger {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ResourceTracker.java b/src/java/edu/umd/cs/findbugs/ba/ResourceTracker.java
index f09ca2a..79e8122 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ResourceTracker.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ResourceTracker.java
@@ -26,7 +26,7 @@ import org.apache.bcel.generic.InstructionHandle;
* A ResourceTracker is used with ResourceValueAnalysis to determine where in a
* method a certain kind of resource is created, and to model the effect of
* instructions on the state of that resource.
- *
+ *
* @author David Hovemeyer
* @see ResourceValueAnalysis
*/
@@ -34,7 +34,7 @@ public interface ResourceTracker<Resource> {
/**
* Determine if the given instruction is the site where a resource is
* created.
- *
+ *
* @param basicBlock
* basic block containing the instruction
* @param handle
@@ -50,7 +50,7 @@ public interface ResourceTracker<Resource> {
/**
* Determine if the given instruction is the site where a resource is
* closed.
- *
+ *
* @param basicBlock
* basic block containing the instruction
* @param handle
@@ -70,18 +70,13 @@ public interface ResourceTracker<Resource> {
/**
* Determine if the given instruction is the site where a resource is
* closed.
- *
+ *
* @param basicBlock
* basic block containing the instruction
* @param handle
* the instruction
* @param cpg
* the ConstantPoolGen for the method
- * @param resource
- * the resource, as returned by isResourceCreation()
- * @param frame
- * the ResourceValueFrame representing the stack prior to
- * executing the instruction
* @return true if the resource is closed here, false otherwise
*/
public boolean mightCloseResource(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg)
@@ -90,7 +85,7 @@ public interface ResourceTracker<Resource> {
/**
* Create a ResourceValueFrameModelingVisitor to model the effect of
* instructions on the state of the resource.
- *
+ *
* @param resource
* the resource we are tracking
* @param cpg
@@ -105,7 +100,7 @@ public interface ResourceTracker<Resource> {
* types to be tracked with varying precision. For example, we might want to
* ignore implicit exceptions for stream objects, but treat them as
* significant for database resources.
- *
+ *
* @param resource
* the resource being tracked
* @return true if implicit exceptions are significant, false if they should
@@ -117,7 +112,7 @@ public interface ResourceTracker<Resource> {
* Determine whether the analysis should ignore given exception edge. This
* allows the analysis to customize which kinds of exceptions are
* significant.
- *
+ *
* @param edge
* the exception edge
* @param resource
@@ -132,7 +127,7 @@ public interface ResourceTracker<Resource> {
/**
* Return if the given parameter slot contains the resource instance upon
* entry to the method. This is for resources passed as parameters.
- *
+ *
* @param resource
* the resource
* @param slot
@@ -142,4 +137,3 @@ public interface ResourceTracker<Resource> {
public boolean isParamInstance(Resource resource, int slot);
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ResourceValue.java b/src/java/edu/umd/cs/findbugs/ba/ResourceValue.java
index 5c26e3a..8f16867 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ResourceValue.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ResourceValue.java
@@ -36,10 +36,11 @@ public class ResourceValue {
}
public static ResourceValue merge(ResourceValue a, ResourceValue b) {
- if (a == notInstance && b == notInstance)
+ if (a == notInstance && b == notInstance) {
return notInstance;
- else
+ } else {
return instance;
+ }
}
public boolean isInstance() {
@@ -52,4 +53,3 @@ public class ResourceValue {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ResourceValueAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/ResourceValueAnalysis.java
index e6cc321..ae996f8 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ResourceValueAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ResourceValueAnalysis.java
@@ -32,21 +32,21 @@ import edu.umd.cs.findbugs.SystemProperties;
@javax.annotation.ParametersAreNonnullByDefault
public class ResourceValueAnalysis<Resource> extends FrameDataflowAnalysis<ResourceValue, ResourceValueFrame> implements
- EdgeTypes {
+EdgeTypes {
private static final boolean DEBUG = SystemProperties.getBoolean("dataflow.debug");
- private MethodGen methodGen;
+ private final MethodGen methodGen;
- private CFG cfg;
+ private final CFG cfg;
- private ResourceTracker<Resource> resourceTracker;
+ private final ResourceTracker<Resource> resourceTracker;
- private Resource resource;
+ private final Resource resource;
- private ResourceValueFrameModelingVisitor visitor;
+ private final ResourceValueFrameModelingVisitor visitor;
- private boolean ignoreImplicitExceptions;
+ private final boolean ignoreImplicitExceptions;
public ResourceValueAnalysis(MethodGen methodGen, CFG cfg, DepthFirstSearch dfs, ResourceTracker<Resource> resourceTracker,
Resource resource) {
@@ -61,12 +61,14 @@ public class ResourceValueAnalysis<Resource> extends FrameDataflowAnalysis<Resou
this.ignoreImplicitExceptions = resourceTracker.ignoreImplicitExceptions(resource);
}
+ @Override
public ResourceValueFrame createFact() {
ResourceValueFrame fact = new ResourceValueFrame(methodGen.getMaxLocals());
fact.setTop();
return fact;
}
+ @Override
public void initEntryFact(ResourceValueFrame result) {
result.setValid();
result.clearStack();
@@ -77,6 +79,7 @@ public class ResourceValueAnalysis<Resource> extends FrameDataflowAnalysis<Resou
}
}
+ @Override
public void meetInto(ResourceValueFrame fact, Edge edge, ResourceValueFrame result) throws DataflowAnalysisException {
BasicBlock source = edge.getSource();
BasicBlock dest = edge.getTarget();
@@ -90,12 +93,14 @@ public class ResourceValueAnalysis<Resource> extends FrameDataflowAnalysis<Resou
// and the resource tracker says to ignore implicit exceptions
// for this resource, ignore it.
if (AnalysisContext.currentAnalysisContext().getBoolProperty(AnalysisFeatures.ACCURATE_EXCEPTIONS)
- && ignoreImplicitExceptions && !edge.isFlagSet(EXPLICIT_EXCEPTIONS_FLAG))
+ && ignoreImplicitExceptions && !edge.isFlagSet(EXPLICIT_EXCEPTIONS_FLAG)) {
return;
+ }
// The ResourceTracker may veto the exception edge
- if (resourceTracker.ignoreExceptionEdge(edge, resource, methodGen.getConstantPool()))
+ if (resourceTracker.ignoreExceptionEdge(edge, resource, methodGen.getConstantPool())) {
return;
+ }
if (fact.getStatus() == ResourceValueFrame.OPEN) {
// If status is OPEN, downgrade to OPEN_ON_EXCEPTION_PATH
@@ -110,15 +115,17 @@ public class ResourceValueAnalysis<Resource> extends FrameDataflowAnalysis<Resou
// closed anyway.
InstructionHandle exceptionThrower = source.getExceptionThrower();
BasicBlock fallThroughSuccessor = cfg.getSuccessorWithEdgeType(source, FALL_THROUGH_EDGE);
- if (DEBUG && fallThroughSuccessor == null)
+ if (DEBUG && fallThroughSuccessor == null) {
System.out.println("Null fall through successor!");
+ }
if (fallThroughSuccessor != null
&& resourceTracker.isResourceClose(fallThroughSuccessor, exceptionThrower, methodGen.getConstantPool(),
resource, fact)) {
tmpFact = modifyFrame(fact, tmpFact);
tmpFact.setStatus(ResourceValueFrame.CLOSED);
- if (DEBUG)
+ if (DEBUG) {
System.out.print("(failed attempt to close)");
+ }
}
}
@@ -193,8 +200,9 @@ public class ResourceValueAnalysis<Resource> extends FrameDataflowAnalysis<Resou
}
}
- if (tmpFact != null)
+ if (tmpFact != null) {
fact = tmpFact;
+ }
mergeInto(fact, result);
}
@@ -226,4 +234,3 @@ public class ResourceValueAnalysis<Resource> extends FrameDataflowAnalysis<Resou
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ResourceValueFrame.java b/src/java/edu/umd/cs/findbugs/ba/ResourceValueFrame.java
index abd9739..45792d9 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ResourceValueFrame.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ResourceValueFrame.java
@@ -69,8 +69,9 @@ public class ResourceValueFrame extends Frame<ResourceValue> {
@Override
public boolean sameAs(Frame<ResourceValue> other_) {
- if (!super.sameAs(other_))
+ if (!super.sameAs(other_)) {
return false;
+ }
ResourceValueFrame other = (ResourceValueFrame) other_;
return this.status == other.status;
@@ -84,7 +85,7 @@ public class ResourceValueFrame extends Frame<ResourceValue> {
}
private static final String[] statusList = { "(escaped)", "(open)", "(open_exception)", "(closed)", "(created)",
- "(nonexistent)" };
+ "(nonexistent)" };
@Override
public String toString() {
@@ -93,4 +94,3 @@ public class ResourceValueFrame extends Frame<ResourceValue> {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ResourceValueFrameModelingVisitor.java b/src/java/edu/umd/cs/findbugs/ba/ResourceValueFrameModelingVisitor.java
index 93befd4..52baf11 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ResourceValueFrameModelingVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ResourceValueFrameModelingVisitor.java
@@ -62,8 +62,9 @@ public abstract class ResourceValueFrameModelingVisitor extends AbstractFrameMod
// If the resource instance is stored in a field, then it escapes
ResourceValueFrame frame = getFrame();
ResourceValue topValue = frame.getTopValue();
- if (topValue.equals(ResourceValue.instance()))
+ if (topValue.equals(ResourceValue.instance())) {
frame.setStatus(ResourceValueFrame.ESCAPED);
+ }
} catch (DataflowAnalysisException e) {
throw new InvalidBytecodeException("Stack underflow", e);
}
@@ -107,7 +108,7 @@ public abstract class ResourceValueFrameModelingVisitor extends AbstractFrameMod
* Override this to check for methods that it is legal to pass the instance
* to without the instance escaping. By default, we consider all methods to
* be possible escape routes.
- *
+ *
* @param inv
* the InvokeInstruction to which the resource instance is passed
* as an argument
@@ -133,8 +134,9 @@ public abstract class ResourceValueFrameModelingVisitor extends AbstractFrameMod
}
}
- if (instanceArgNum >= 0 && instanceEscapes(inv, instanceArgNum))
+ if (instanceArgNum >= 0 && instanceEscapes(inv, instanceArgNum)) {
frame.setStatus(ResourceValueFrame.ESCAPED);
+ }
handleNormalInstruction(inv);
}
@@ -147,8 +149,9 @@ public abstract class ResourceValueFrameModelingVisitor extends AbstractFrameMod
topValue = frame.getTopValue();
- if (topValue.equals(ResourceValue.instance()))
+ if (topValue.equals(ResourceValue.instance())) {
frame.setStatus(ResourceValueFrame.ESCAPED);
+ }
} catch (DataflowAnalysisException e) {
AnalysisContext.logError("Analysis error", e);
}
@@ -179,8 +182,9 @@ public abstract class ResourceValueFrameModelingVisitor extends AbstractFrameMod
try {
ResourceValueFrame frame = getFrame();
ResourceValue topValue = frame.getTopValue();
- if (topValue.equals(ResourceValue.instance()))
+ if (topValue.equals(ResourceValue.instance())) {
frame.setStatus(ResourceValueFrame.ESCAPED);
+ }
} catch (DataflowAnalysisException e) {
throw new InvalidBytecodeException("Stack underflow", e);
}
@@ -190,4 +194,3 @@ public abstract class ResourceValueFrameModelingVisitor extends AbstractFrameMod
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ReturnPath.java b/src/java/edu/umd/cs/findbugs/ba/ReturnPath.java
index 526d3fd..6b84ad0 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ReturnPath.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ReturnPath.java
@@ -68,12 +68,12 @@ public class ReturnPath {
}
private static final int[][] mergeMatrix = {
- // TOP EXIT UE EXIT_UE RETURNS
- { TOP, }, // TOP
- { EXIT, EXIT, }, // EXIT
- { UE, EXIT_UE, UE, }, // UE
- { EXIT_UE, EXIT_UE, EXIT_UE, EXIT_UE, }, // EXIT_UE
- { RETURNS, RETURNS, RETURNS, RETURNS, RETURNS }, // RETURNS
+ // TOP EXIT UE EXIT_UE RETURNS
+ { TOP, }, // TOP
+ { EXIT, EXIT, }, // EXIT
+ { UE, EXIT_UE, UE, }, // UE
+ { EXIT_UE, EXIT_UE, EXIT_UE, EXIT_UE, }, // EXIT_UE
+ { RETURNS, RETURNS, RETURNS, RETURNS, RETURNS }, // RETURNS
};
public void mergeWith(ReturnPath other) {
@@ -101,4 +101,3 @@ public class ReturnPath {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ReturnPathAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/ReturnPathAnalysis.java
index e41fcd6..cdb8800 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ReturnPathAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ReturnPathAnalysis.java
@@ -26,26 +26,32 @@ public class ReturnPathAnalysis extends ForwardDataflowAnalysis<ReturnPath> impl
super(dfs);
}
+ @Override
public ReturnPath createFact() {
return new ReturnPath(ReturnPath.TOP);
}
+ @Override
public void copy(ReturnPath source, ReturnPath dest) {
dest.copyFrom(source);
}
+ @Override
public void initEntryFact(ReturnPath fact) {
fact.setKind(ReturnPath.RETURNS);
}
+ @Override
public void makeFactTop(ReturnPath fact) {
fact.setKind(ReturnPath.TOP);
}
+ @Override
public boolean isTop(ReturnPath fact) {
return fact.getKind() == ReturnPath.TOP;
}
+ @Override
public boolean same(ReturnPath fact1, ReturnPath fact2) {
return fact1.sameAs(fact2);
}
@@ -61,6 +67,7 @@ public class ReturnPathAnalysis extends ForwardDataflowAnalysis<ReturnPath> impl
return true;
}
+ @Override
public void meetInto(ReturnPath fact, Edge edge, ReturnPath result) throws DataflowAnalysisException {
switch (edge.getType()) {
case UNHANDLED_EXCEPTION_EDGE:
@@ -97,4 +104,3 @@ public class ReturnPathAnalysis extends ForwardDataflowAnalysis<ReturnPath> impl
// }
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ReturnPathDataflow.java b/src/java/edu/umd/cs/findbugs/ba/ReturnPathDataflow.java
index 97161d0..15e00ac 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ReturnPathDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ReturnPathDataflow.java
@@ -25,4 +25,3 @@ public class ReturnPathDataflow extends Dataflow<ReturnPath, ReturnPathAnalysis>
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ReverseDFSOrder.java b/src/java/edu/umd/cs/findbugs/ba/ReverseDFSOrder.java
index 5394b57..b765ea1 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ReverseDFSOrder.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ReverseDFSOrder.java
@@ -25,7 +25,7 @@ import java.util.Comparator;
* A BlockOrder for visiting the blocks of a CFG in the order they would be
* visited in a depth first search of the reversed CFG. This is the most
* efficient visitation order for backwards dataflow analyses.
- *
+ *
* @see BlockOrder
* @see ReverseDepthFirstSearch
* @see CFG
@@ -37,11 +37,13 @@ public class ReverseDFSOrder extends AbstractBlockOrder {
private final DepthFirstSearch dfs;
public ReverseDFSComparator(ReverseDepthFirstSearch rdfs, DepthFirstSearch dfs) {
- if (dfs == null)
+ if (dfs == null) {
throw new IllegalArgumentException();
+ }
this.dfs = dfs;
}
+ @Override
public int compare(BasicBlock a, BasicBlock b) {
return dfs.getFinishTime(a) - dfs.getFinishTime(b);
}
@@ -53,7 +55,7 @@ public class ReverseDFSOrder extends AbstractBlockOrder {
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG
* @param rdfs
@@ -68,4 +70,3 @@ public class ReverseDFSOrder extends AbstractBlockOrder {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ReverseDepthFirstSearch.java b/src/java/edu/umd/cs/findbugs/ba/ReverseDepthFirstSearch.java
index 0b480cd..ea1061d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ReverseDepthFirstSearch.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ReverseDepthFirstSearch.java
@@ -22,7 +22,7 @@ package edu.umd.cs.findbugs.ba;
/**
* Algorithm to perform a reverse depth first search on a CFG. (I.e., depth
* first search on reversed CFG.)
- *
+ *
* @see CFG
* @author David Hovemeyer
*/
@@ -31,7 +31,7 @@ public class ReverseDepthFirstSearch extends edu.umd.cs.findbugs.graph.ReverseDe
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG to perform the reverse depth first search on
*/
@@ -48,4 +48,3 @@ public class ReverseDepthFirstSearch extends edu.umd.cs.findbugs.graph.ReverseDe
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ReversePostOrder.java b/src/java/edu/umd/cs/findbugs/ba/ReversePostOrder.java
index 76aab77..39bbb65 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ReversePostOrder.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ReversePostOrder.java
@@ -25,7 +25,7 @@ import java.util.Comparator;
* A BlockOrder for visiting the blocks of a CFG in the reverse of the order in
* which they are finished in a depth first search. This is the most efficient
* visitation order for forward dataflow analyses.
- *
+ *
* @see BlockOrder
* @see DepthFirstSearch
* @see CFG
@@ -37,12 +37,13 @@ public class ReversePostOrder extends AbstractBlockOrder {
* they would be finished by a depth first search.
*/
private static class ReversePostfixComparator implements Comparator<BasicBlock> {
- private DepthFirstSearch dfs;
+ private final DepthFirstSearch dfs;
public ReversePostfixComparator(DepthFirstSearch dfs) {
this.dfs = dfs;
}
+ @Override
public int compare(BasicBlock aa, BasicBlock bb) {
return dfs.getFinishTime(bb) - dfs.getFinishTime(aa);
}
@@ -50,7 +51,7 @@ public class ReversePostOrder extends AbstractBlockOrder {
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG for the method
* @param dfs
@@ -61,4 +62,3 @@ public class ReversePostOrder extends AbstractBlockOrder {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/SignatureConverter.java b/src/java/edu/umd/cs/findbugs/ba/SignatureConverter.java
index 1a77652..ffa5c04 100644
--- a/src/java/edu/umd/cs/findbugs/ba/SignatureConverter.java
+++ b/src/java/edu/umd/cs/findbugs/ba/SignatureConverter.java
@@ -35,7 +35,7 @@ import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
* For a method signature, parseNext() must be called multiple times, and the
* parens around the arguments must be skipped manually (by calling the skip()
* method).
- *
+ *
* @author David Hovemeyer
*/
@@ -44,7 +44,7 @@ public class SignatureConverter {
/**
* Constructor.
- *
+ *
* @param signature
* the field or method signature to convert
*/
@@ -72,7 +72,7 @@ public class SignatureConverter {
* of the remaining part is "I", then this method will return "int", and the
* "I" will be consumed. Arrays, reference types, and basic types are all
* handled.
- *
+ *
* @return the parsed type string
*/
public String parseNext() {
@@ -91,8 +91,9 @@ public class SignatureConverter {
}
} else if (signature.startsWith("L")) {
int semi = signature.indexOf(';');
- if (semi < 0)
+ if (semi < 0) {
throw new IllegalStateException("missing semicolon in signature " + signature);
+ }
result.append(signature.substring(1, semi).replace('/', '.'));
signature = signature.substring(semi + 1);
} else {
@@ -136,7 +137,7 @@ public class SignatureConverter {
/**
* Convenience method for generating a method signature in human readable
* form.
- *
+ *
* @param javaClass
* the class
* @param method
@@ -149,7 +150,7 @@ public class SignatureConverter {
/**
* Convenience method for generating a method signature in human readable
* form.
- *
+ *
* @param methodGen
* the method to produce a method signature for
*/
@@ -160,7 +161,7 @@ public class SignatureConverter {
/**
* Convenience method for generating a method signature in human readable
* form.
- *
+ *
* @param inv
* an InvokeInstruction
* @param cpg
@@ -173,7 +174,7 @@ public class SignatureConverter {
/**
* Convenience method for generating a method signature in human readable
* form.
- *
+ *
* @param className
* name of the class containing the method
* @param methodName
@@ -188,7 +189,7 @@ public class SignatureConverter {
/**
* Convenience method for generating a method signature in human readable
* form.
- *
+ *
* @param xmethod
* an XMethod
* @return the formatted version of that signature
@@ -203,7 +204,7 @@ public class SignatureConverter {
/**
* Convenience method for generating a method signature in human readable
* form.
- *
+ *
* @param methodDescriptor
* a MethodDescriptor
* @return the formatted version of that signature
@@ -216,7 +217,7 @@ public class SignatureConverter {
/**
* Convenience method for generating a method signature in human readable
* form.
- *
+ *
* @param className
* name of the class containing the method
* @param methodName
@@ -235,8 +236,9 @@ public class SignatureConverter {
args.append('(');
while (converter.getFirst() != ')') {
- if (args.length() > 1)
+ if (args.length() > 1) {
args.append(", ");
+ }
args.append(shorten(pkgName, converter.parseNext()));
}
converter.skip();
@@ -256,7 +258,7 @@ public class SignatureConverter {
/**
* Convenience method for converting a single signature component to
* human-readable form.
- *
+ *
* @param signature
* the signature
*/
@@ -268,11 +270,11 @@ public class SignatureConverter {
int index = typeName.lastIndexOf('.');
if (index >= 0) {
String otherPkg = typeName.substring(0, index);
- if (otherPkg.equals(pkgName) || otherPkg.equals("java.lang"))
+ if (otherPkg.equals(pkgName) || "java.lang".equals(otherPkg)) {
typeName = typeName.substring(index + 1);
+ }
}
return typeName;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/SignatureParser.java b/src/java/edu/umd/cs/findbugs/ba/SignatureParser.java
index 99fa2d8..05f02ed 100644
--- a/src/java/edu/umd/cs/findbugs/ba/SignatureParser.java
+++ b/src/java/edu/umd/cs/findbugs/ba/SignatureParser.java
@@ -38,16 +38,18 @@ public class SignatureParser {
private int totalArgumentSize;
public int getTotalArgumentSize() {
- if ( parameterOffset == null)
+ if ( parameterOffset == null) {
getParameterOffset();
+ }
return totalArgumentSize;
}
- private @CheckForNull int parameterOffset[];
+ private @CheckForNull int parameterOffset[];
- @Nonnull int[] getParameterOffset() {
- if ( parameterOffset != null )
+ @Nonnull int[] getParameterOffset() {
+ if ( parameterOffset != null ) {
return parameterOffset;
+ }
ArrayList<Integer> offsets = new ArrayList<Integer>();
Iterator<String> i = parameterSignatureIterator();
int totalSize = 0;
@@ -55,18 +57,20 @@ public class SignatureParser {
while (i.hasNext()) {
String s = i.next();
- if (s.equals("D") || s.equals("J"))
+ if ("D".equals(s) || "J".equals(s)) {
totalSize += 2;
- else
+ } else {
totalSize += 1;
+ }
offsets.add(totalSize);
}
totalArgumentSize = totalSize;
int numParameters = offsets.size();
parameterOffset = new int[numParameters];
- for (int j = 0; j < numParameters; j++)
+ for (int j = 0; j < numParameters; j++) {
parameterOffset[j] = offsets.get(j);
+ }
return parameterOffset;
}
@@ -79,13 +83,16 @@ public class SignatureParser {
private class ParameterSignatureIterator implements Iterator<String> {
private int index = 1;
+ @Override
public boolean hasNext() {
return index < signature.length() && signature.charAt(index) != ')';
}
+ @Override
public String next() {
- if (!hasNext())
+ if (!hasNext()) {
throw new NoSuchElementException();
+ }
StringBuilder result = new StringBuilder();
boolean done;
do {
@@ -106,8 +113,9 @@ public class SignatureParser {
case 'L':
int semi = signature.indexOf(';', index + 1);
- if (semi < 0)
+ if (semi < 0) {
throw new IllegalStateException("Invalid method signature: " + signature);
+ }
result.append(signature.substring(index, semi + 1));
index = semi + 1;
break;
@@ -127,6 +135,7 @@ public class SignatureParser {
return result.toString();
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -146,8 +155,9 @@ public class SignatureParser {
* the method signature to be parsed
*/
public SignatureParser(String signature) {
- if (!signature.startsWith("("))
+ if (!signature.startsWith("(")) {
throw new IllegalArgumentException("Bad method signature: " + signature);
+ }
this.signature = signature;
@@ -169,13 +179,14 @@ public class SignatureParser {
return new ParameterSignatureIterator();
}
- public Iterable<String> parameterSignatures() {
- return new Iterable<String>() {
+ public Iterable<String> parameterSignatures() {
+ return new Iterable<String>() {
+
+ @Override
+ public Iterator<String> iterator() {
+ return new ParameterSignatureIterator();
+ }};
- public Iterator<String> iterator() {
- return new ParameterSignatureIterator();
- }};
-
}
/**
@@ -185,8 +196,9 @@ public class SignatureParser {
*/
public String getReturnTypeSignature() {
int endOfParams = signature.lastIndexOf(')');
- if (endOfParams < 0)
+ if (endOfParams < 0) {
throw new IllegalArgumentException("Bad method signature: " + signature);
+ }
return signature.substring(endOfParams + 1);
}
@@ -202,8 +214,9 @@ public class SignatureParser {
public boolean hasReferenceParameters() {
for (Iterator<String> i = parameterSignatureIterator(); i.hasNext();) {
char c = i.next().charAt(0);
- if (c == 'L' || c == '[')
+ if (c == 'L' || c == '[') {
return true;
+ }
}
return false;
}
@@ -212,8 +225,9 @@ public class SignatureParser {
int count = 0;
for (Iterator<String> i = parameterSignatureIterator(); i.hasNext();) {
String p = i.next();
- if (pos == count)
+ if (pos == count) {
return p;
+ }
++count;
}
throw new IndexOutOfBoundsException("Asked for parameter " + pos + " of " + signature);
@@ -252,7 +266,7 @@ public class SignatureParser {
* @return number of stack frame slots a value of the given type will occupy
*/
public static int getNumSlotsForType(String sig) {
- if (sig.equals("J") || sig.equals("D")) {
+ if ("J".equals(sig) || "D".equals(sig)) {
return 2;
} else {
return 1;
@@ -272,4 +286,3 @@ public class SignatureParser {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/SimplePathEnumerator.java b/src/java/edu/umd/cs/findbugs/ba/SimplePathEnumerator.java
index d80241e..5e2b9b1 100644
--- a/src/java/edu/umd/cs/findbugs/ba/SimplePathEnumerator.java
+++ b/src/java/edu/umd/cs/findbugs/ba/SimplePathEnumerator.java
@@ -32,22 +32,22 @@ import edu.umd.cs.findbugs.SystemProperties;
* <p>
* FIXME: instead of storing the simple paths, should invoke a callback as each
* simple path is produced. That would save memory.
- *
+ *
* @author David Hovemeyer
* @see CFG
*/
public class SimplePathEnumerator implements EdgeTypes, DFSEdgeTypes {
- private CFG cfg;
+ private final CFG cfg;
- private DepthFirstSearch dfs;
+ private final DepthFirstSearch dfs;
- private int maxPaths;
+ private final int maxPaths;
- private int maxWork;
+ private final int maxWork;
private int work;
- private List<List<Edge>> pathList;
+ private final List<List<Edge>> pathList;
private static final boolean DEBUG = SystemProperties.getBoolean("spe.debug");
@@ -58,7 +58,7 @@ public class SimplePathEnumerator implements EdgeTypes, DFSEdgeTypes {
/**
* Constructor.
- *
+ *
* @param cfg
* the control flow graph to enumerate simple paths of
* @param maxPaths
@@ -79,7 +79,7 @@ public class SimplePathEnumerator implements EdgeTypes, DFSEdgeTypes {
/**
* Constructor; max work is set to DEFAULT_MAX_WORK.
- *
+ *
* @param cfg
* the control flow graph to enumerate simple paths of
* @param maxPaths
@@ -91,21 +91,23 @@ public class SimplePathEnumerator implements EdgeTypes, DFSEdgeTypes {
/**
* Enumerate the simple paths.
- *
+ *
* @return this object
*/
public SimplePathEnumerator enumerate() {
Iterator<Edge> entryOut = cfg.outgoingEdgeIterator(cfg.getEntry());
- if (!entryOut.hasNext())
+ if (!entryOut.hasNext()) {
throw new IllegalStateException();
+ }
Edge entryEdge = entryOut.next();
LinkedList<Edge> init = new LinkedList<Edge>();
init.add(entryEdge);
work(init);
- if (DEBUG && work == maxWork)
+ if (DEBUG && work == maxWork) {
System.out.println("**** Reached max work! ****");
+ }
return this;
}
@@ -118,8 +120,9 @@ public class SimplePathEnumerator implements EdgeTypes, DFSEdgeTypes {
}
private void work(LinkedList<Edge> partialPath) {
- if (pathList.size() == maxPaths)
+ if (pathList.size() == maxPaths) {
return;
+ }
Edge last = partialPath.getLast();
@@ -136,8 +139,9 @@ public class SimplePathEnumerator implements EdgeTypes, DFSEdgeTypes {
Edge outEdge = i.next();
// Ignore back edges and unhandled exception edges
- if (dfs.getDFSEdgeType(outEdge) == BACK_EDGE || outEdge.getType() == UNHANDLED_EXCEPTION_EDGE)
+ if (dfs.getDFSEdgeType(outEdge) == BACK_EDGE || outEdge.getType() == UNHANDLED_EXCEPTION_EDGE) {
continue;
+ }
// Add the edge to the current partial path, and recur
partialPath.add(outEdge);
@@ -145,15 +149,16 @@ public class SimplePathEnumerator implements EdgeTypes, DFSEdgeTypes {
partialPath.removeLast();
// Have we done the maximum amount of work?
- if (work == maxWork)
+ if (work == maxWork) {
return;
+ }
++work;
// Did we reach the maximum number of simple paths?
- if (pathList.size() == maxPaths)
+ if (pathList.size() == maxPaths) {
return;
+ }
}
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/SourceFile.java b/src/java/edu/umd/cs/findbugs/ba/SourceFile.java
index efc6e28..eec717f 100644
--- a/src/java/edu/umd/cs/findbugs/ba/SourceFile.java
+++ b/src/java/edu/umd/cs/findbugs/ba/SourceFile.java
@@ -41,7 +41,7 @@ public class SourceFile {
* file.
*/
private static class LineNumberMapBuilder {
- private SourceFile sourceFile;
+ private final SourceFile sourceFile;
private int offset;
@@ -91,7 +91,7 @@ public class SourceFile {
private static final int DEFAULT_SIZE = 100;
- private SourceFileDataSource dataSource;
+ private final SourceFileDataSource dataSource;
private byte[] data;
@@ -179,14 +179,16 @@ public class SourceFile {
System.err.println("SourceFile.getLineOffset: " + e.getMessage());
return -1;
}
- if (line < 0 || line >= numLines)
+ if (line < 0 || line >= numLines) {
return -1;
+ }
return lineNumberMap[line];
}
private synchronized void loadFileData() throws IOException {
- if (data != null)
+ if (data != null) {
return;
+ }
InputStream in = null;
@@ -209,8 +211,9 @@ public class SourceFile {
setData(out.toByteArray());
} finally {
- if (in != null)
+ if (in != null) {
in.close();
+ }
}
}
@@ -230,4 +233,3 @@ public class SourceFile {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/SourceFileDataSource.java b/src/java/edu/umd/cs/findbugs/ba/SourceFileDataSource.java
index 3ee733d..ed63eca 100644
--- a/src/java/edu/umd/cs/findbugs/ba/SourceFileDataSource.java
+++ b/src/java/edu/umd/cs/findbugs/ba/SourceFileDataSource.java
@@ -39,4 +39,3 @@ public interface SourceFileDataSource {
public long getLastModified();
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/SourceFinder.java b/src/java/edu/umd/cs/findbugs/ba/SourceFinder.java
index 5ab6141..876da97 100644
--- a/src/java/edu/umd/cs/findbugs/ba/SourceFinder.java
+++ b/src/java/edu/umd/cs/findbugs/ba/SourceFinder.java
@@ -97,7 +97,7 @@ public class SourceFinder {
* A directory containing source files.
*/
private static class DirectorySourceRepository implements SourceRepository {
- private String baseDir;
+ private final String baseDir;
public DirectorySourceRepository(String baseDir) {
this.baseDir = baseDir;
@@ -108,18 +108,22 @@ public class SourceFinder {
return "DirectorySourceRepository:" + baseDir;
}
+ @Override
public boolean contains(String fileName) {
File file = new File(getFullFileName(fileName));
boolean exists = file.exists();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Exists " + exists + " for " + file);
+ }
return exists;
}
+ @Override
public boolean isPlatformDependent() {
return true;
}
+ @Override
public SourceFileDataSource getDataSource(String fileName) {
return new FileSourceFileDataSource(getFullFileName(fileName));
}
@@ -139,19 +143,22 @@ public class SourceFinder {
while (true) {
ZipEntry e = in.getNextEntry();
- if (e == null)
+ if (e == null) {
break;
+ }
if (!e.isDirectory()) {
String name = e.getName();
long size = e.getSize();
- if (size > Integer.MAX_VALUE)
+ if (size > Integer.MAX_VALUE) {
throw new IOException(name + " is too big at " + size + " bytes");
+ }
ByteArrayOutputStream out;
- if (size <= 0)
+ if (size <= 0) {
out = new ByteArrayOutputStream();
- else
+ } else {
out = new ByteArrayOutputStream((int) size);
+ }
GZIPOutputStream gOut = new GZIPOutputStream(out);
IO.copy(in, gOut);
gOut.close();
@@ -167,51 +174,37 @@ public class SourceFinder {
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.SourceFinder.SourceRepository#contains(java
- * .lang.String)
- */
+ @Override
public boolean contains(String fileName) {
return contents.containsKey(fileName);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.SourceFinder.SourceRepository#getDataSource
- * (java.lang.String)
- */
+ @Override
public SourceFileDataSource getDataSource(final String fileName) {
return new SourceFileDataSource() {
+ @Override
public String getFullFileName() {
return fileName;
}
+ @Override
public InputStream open() throws IOException {
return new GZIPInputStream(new ByteArrayInputStream(contents.get(fileName)));
}
+ @Override
public long getLastModified() {
- Long when = lastModified.get(fileName);
- if (when == null || when < 0)
- return 0;
- return when;
+ Long when = lastModified.get(fileName);
+ if (when == null || when < 0) {
+ return 0;
+ }
+ return when;
}
};
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.SourceFinder.SourceRepository#isPlatformDependent
- * ()
- */
+ @Override
public boolean isPlatformDependent() {
return false;
}
@@ -221,18 +214,21 @@ public class SourceFinder {
final BlockingSourceRepository r = new BlockingSourceRepository();
Util.runInDameonThread(new Runnable() {
+ @Override
public void run() {
InputStream in = null;
try {
URLConnection connection = new URL(url).openConnection();
in = connection.getInputStream();
- if (getProject().isGuiAvaliable())
+ if (getProject().isGuiAvaliable()) {
in = getProject().getGuiCallback().getProgressMonitorInputStream(in, connection.getContentLength(),
"Downloading project source code...");
+ }
- if (url.endsWith(".z0p.gz"))
+ if (url.endsWith(".z0p.gz")) {
in = new GZIPInputStream(in);
+ }
r.setBase(new InMemorySourceRepository(new ZipInputStream(in)));
@@ -254,6 +250,7 @@ public class SourceFinder {
final BlockingSourceRepository r = new BlockingSourceRepository();
Util.runInDameonThread(new Runnable() {
+ @Override
public void run() {
InputStream in = null;
OutputStream out = null;
@@ -305,16 +302,19 @@ public class SourceFinder {
}
}
+ @Override
public boolean contains(String fileName) {
await();
return base.contains(fileName);
}
+ @Override
public SourceFileDataSource getDataSource(String fileName) {
await();
return base.getDataSource(fileName);
}
+ @Override
public boolean isPlatformDependent() {
await();
return base.isPlatformDependent();
@@ -332,14 +332,17 @@ public class SourceFinder {
this.zipFile = zipFile;
}
+ @Override
public boolean contains(String fileName) {
return zipFile.getEntry(fileName) != null;
}
+ @Override
public boolean isPlatformDependent() {
return false;
}
+ @Override
public SourceFileDataSource getDataSource(String fileName) {
return new ZipSourceFileDataSource(zipFile, fileName);
}
@@ -385,17 +388,18 @@ public class SourceFinder {
if (repos.startsWith("http:") || repos.startsWith("https:") || repos.startsWith("file:")) {
String url = SystemProperties.rewriteURLAccordingToProperties(repos);
repositoryList.add(makeInMemorySourceRepository(url));
- } else
+ } else {
repositoryList.add(new ZipSourceRepository(new ZipFile(repos)));
+ }
} catch (IOException e) {
// Ignored - we won't use this archive
AnalysisContext.logError("Unable to load " + repos, e);
}
} else {
File dir = new File(repos);
- if (dir.canRead() && dir.isDirectory())
+ if (dir.canRead() && dir.isDirectory()) {
repositoryList.add(new DirectorySourceRepository(repos));
- else {
+ } else {
AnalysisContext.logError("Unable to load " + repos);
}
@@ -461,25 +465,29 @@ public class SourceFinder {
// Is the file in the cache already? Always cache it with the canonical
// name
SourceFile sourceFile = cache.get(canonicalName);
- if (sourceFile != null)
+ if (sourceFile != null) {
return sourceFile;
+ }
// Find this source file, add its data to the cache
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Trying " + fileName + " in package " + packageName + "...");
+ }
// Query each element of the source path to find the requested source
// file
for (SourceRepository repos : repositoryList) {
- if (repos instanceof BlockingSourceRepository && !((BlockingSourceRepository) repos).isReady())
+ if (repos instanceof BlockingSourceRepository && !((BlockingSourceRepository) repos).isReady()) {
continue;
+ }
fileName = repos.isPlatformDependent() ? platformName : canonicalName;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Looking in " + repos + " for " + fileName);
+ }
if (repos.contains(fileName)) {
// Found it
sourceFile = new SourceFile(repos.getDataSource(fileName));
cache.put(canonicalName, sourceFile); // always cache with
- // canonicalName
+ // canonicalName
return sourceFile;
}
}
@@ -487,45 +495,39 @@ public class SourceFinder {
throw new FileNotFoundException("Can't find source file " + fileName);
}
- /**
- * @param packageName
- * @param fileName
- * @return
- */
public static String getPlatformName(String packageName, String fileName) {
String platformName = packageName.replace('.', File.separatorChar) + (packageName.length() > 0 ? File.separator : "")
+ fileName;
return platformName;
}
-
+
public static String getPlatformName(SourceLineAnnotation source) {
return getPlatformName(source.getPackageName(), getOrGuessSourceFile(source));
}
-
+
public static String getCanonicalName(SourceLineAnnotation source) {
return getCanonicalName(source.getPackageName(), getOrGuessSourceFile(source));
}
- /**
- * @param packageName
- * @param fileName
- * @return
- */
+
public static String getCanonicalName(String packageName, String fileName) {
String canonicalName = packageName.replace('.', '/') + (packageName.length() > 0 ? "/" : "") + fileName;
return canonicalName;
}
public static String getOrGuessSourceFile(SourceLineAnnotation source) {
- if (source.isSourceFileKnown())
+ if (source.isSourceFileKnown()) {
return source.getSourceFile();
+ }
String baseClassName = source.getClassName();
int i = baseClassName.lastIndexOf('.');
baseClassName = baseClassName.substring(i + 1);
- int j = baseClassName.indexOf("$");
- if (j >= 0)
+ int j = baseClassName.indexOf('$');
+ if (j >= 0) {
baseClassName = baseClassName.substring(0, j);
+ }
return baseClassName + ".java";
}
+
public boolean hasSourceFile(SourceLineAnnotation source) {
return hasSourceFile(source.getPackageName(), getOrGuessSourceFile(source));
}
@@ -552,20 +554,24 @@ public class SourceFinder {
// Is the file in the cache already? Always cache it with the canonical
// name
SourceFile sourceFile = cache.get(canonicalName);
- if (sourceFile != null)
+ if (sourceFile != null) {
return true;
+ }
// Find this source file, add its data to the cache
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Trying " + fileName + " in package " + packageName + "...");
+ }
// Query each element of the source path to find the requested source
// file
for (SourceRepository repos : repositoryList) {
- if (repos instanceof BlockingSourceRepository && !((BlockingSourceRepository) repos).isReady())
+ if (repos instanceof BlockingSourceRepository && !((BlockingSourceRepository) repos).isReady()) {
continue;
+ }
fileName = repos.isPlatformDependent() ? platformName : canonicalName;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Looking in " + repos + " for " + fileName);
+ }
if (repos.contains(fileName)) {
return true;
}
@@ -574,11 +580,6 @@ public class SourceFinder {
return false;
}
-
-
- /**
- * @param project
- */
private void setProject(Project project) {
this.project = project;
repositoryList = new LinkedList<SourceRepository>();
@@ -587,4 +588,3 @@ public class SourceFinder {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/SourceInfoMap.java b/src/java/edu/umd/cs/findbugs/ba/SourceInfoMap.java
index 620a53c..52c79d2 100644
--- a/src/java/edu/umd/cs/findbugs/ba/SourceInfoMap.java
+++ b/src/java/edu/umd/cs/findbugs/ba/SourceInfoMap.java
@@ -41,7 +41,7 @@ import edu.umd.cs.findbugs.util.Util;
* (items we don't get line number information for directly in classfiles), and
* also source line information for methods that don't appear directly in
* classfiles, such as abstract and native methods.
- *
+ *
* @author David Hovemeyer
*/
public class SourceInfoMap {
@@ -62,19 +62,21 @@ public class SourceInfoMap {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Comparable#compareTo(T)
*/
+ @Override
public int compareTo(FieldDescriptor o) {
int cmp = className.compareTo(o.className);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return fieldName.compareTo(o.fieldName);
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
@@ -84,24 +86,25 @@ public class SourceInfoMap {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
- if (obj == null || obj.getClass() != this.getClass())
+ if (obj == null || obj.getClass() != this.getClass()) {
return false;
+ }
FieldDescriptor other = (FieldDescriptor) obj;
return className.equals(other.className) && fieldName.equals(other.fieldName);
}
}
static class MethodDescriptor implements Comparable<MethodDescriptor> {
- private String className;
+ private final String className;
- private String methodName;
+ private final String methodName;
- private String methodSignature;
+ private final String methodSignature;
public MethodDescriptor(String className, String methodName, String methodSignature) {
this.className = className;
@@ -116,21 +119,24 @@ public class SourceInfoMap {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Comparable#compareTo(T)
*/
+ @Override
public int compareTo(MethodDescriptor o) {
int cmp;
- if ((cmp = className.compareTo(o.className)) != 0)
+ if ((cmp = className.compareTo(o.className)) != 0) {
return cmp;
- if ((cmp = methodName.compareTo(o.methodName)) != 0)
+ }
+ if ((cmp = methodName.compareTo(o.methodName)) != 0) {
return cmp;
+ }
return methodSignature.compareTo(o.methodSignature);
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
@@ -140,13 +146,14 @@ public class SourceInfoMap {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
- if (obj == null || obj.getClass() != this.getClass())
+ if (obj == null || obj.getClass() != this.getClass()) {
return false;
+ }
MethodDescriptor other = (MethodDescriptor) obj;
return className.equals(other.className) && methodName.equals(other.methodName)
&& methodSignature.equals(other.methodSignature);
@@ -168,7 +175,7 @@ public class SourceInfoMap {
/**
* Constructor for a range of lines.
- *
+ *
* @param start
* start line in range
* @param end
@@ -197,7 +204,7 @@ public class SourceInfoMap {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
@@ -208,11 +215,11 @@ public class SourceInfoMap {
private static final boolean DEBUG = SystemProperties.getBoolean("sourceinfo.debug");
- private Map<FieldDescriptor, SourceLineRange> fieldLineMap;
+ private final Map<FieldDescriptor, SourceLineRange> fieldLineMap;
- private Map<MethodDescriptor, SourceLineRange> methodLineMap;
+ private final Map<MethodDescriptor, SourceLineRange> methodLineMap;
- private Map<String, SourceLineRange> classLineMap;
+ private final Map<String, SourceLineRange> classLineMap;
public boolean fallBackToClassfile() {
return isEmpty();
@@ -233,7 +240,7 @@ public class SourceInfoMap {
/**
* Add a line number entry for a field.
- *
+ *
* @param className
* name of class containing the field
* @param fieldName
@@ -247,7 +254,7 @@ public class SourceInfoMap {
/**
* Add a line number entry for a method.
- *
+ *
* @param className
* name of class containing the method
* @param methodName
@@ -263,7 +270,7 @@ public class SourceInfoMap {
/**
* Add line number entry for a class.
- *
+ *
* @param className
* name of class
* @param range
@@ -275,7 +282,7 @@ public class SourceInfoMap {
/**
* Look up the line number range for a field.
- *
+ *
* @param className
* name of class containing the field
* @param fieldName
@@ -290,7 +297,7 @@ public class SourceInfoMap {
/**
* Look up the line number range for a method.
- *
+ *
* @param className
* name of class containing the method
* @param methodName
@@ -307,7 +314,7 @@ public class SourceInfoMap {
/**
* Look up the line number range for a class.
- *
+ *
* @param className
* name of the class
* @return the line number range, or null if no line number is known for the
@@ -323,7 +330,7 @@ public class SourceInfoMap {
/**
* Read source info from given InputStream. The stream is guaranteed to be
* closed.
- *
+ *
* @param inputStream
* the InputStream
* @throws IOException
@@ -342,8 +349,9 @@ public class SourceInfoMap {
++lineNumber;
if (lineNumber == 1) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("First line: " + line);
+ }
// Try to parse the version number string from the first
// line.
// null means that the line does not appear to be a version
@@ -352,8 +360,9 @@ public class SourceInfoMap {
if (version != null) {
// Check to see if version is supported.
// Only 1.0 supported for now.
- if (!version.equals("1.0"))
+ if (!"1.0".equals(version)) {
throw new IOException("Unsupported sourceInfo version " + version);
+ }
// Version looks good. Skip to next line of file.
continue;
@@ -368,29 +377,33 @@ public class SourceInfoMap {
// Line number for class
SourceLineRange range = createRange(next, tokenizer.nextToken());
classLineMap.put(className, range);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("class:" + className + "," + range);
+ }
} else if ((lparen = next.indexOf('(')) >= 0) {
// Line number for method
String methodName = next.substring(0, lparen);
String methodSignature = next.substring(lparen);
- if (methodName.equals("init^"))
+ if ("init^".equals(methodName)) {
methodName = "<init>";
- else if (methodName.equals("clinit^"))
+ } else if ("clinit^".equals(methodName)) {
methodName = "<clinit>";
+ }
SourceLineRange range = createRange(tokenizer.nextToken(), tokenizer.nextToken());
methodLineMap.put(new MethodDescriptor(className, methodName, methodSignature), range);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("method:" + methodName + methodSignature + "," + range);
+ }
} else {
// Line number for field
String fieldName = next;
SourceLineRange range = createRange(tokenizer.nextToken(), tokenizer.nextToken());
fieldLineMap.put(new FieldDescriptor(className, fieldName), range);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("field:" + className + "," + fieldName + "," + range);
+ }
}
// Note: we could complain if there are more tokens,
@@ -411,7 +424,7 @@ public class SourceInfoMap {
/**
* Parse the sourceInfo version string.
- *
+ *
* @param line
* the first line of the sourceInfo file
* @return the version number constant, or null if the line does not appear
@@ -420,8 +433,9 @@ public class SourceInfoMap {
private static String parseVersionNumber(String line) {
StringTokenizer tokenizer = new StringTokenizer(line, " \t");
- if (!expect(tokenizer, "sourceInfo") || !expect(tokenizer, "version") || !tokenizer.hasMoreTokens())
+ if (!expect(tokenizer, "sourceInfo") || !expect(tokenizer, "version") || !tokenizer.hasMoreTokens()) {
return null;
+ }
return tokenizer.nextToken();
}
@@ -429,7 +443,7 @@ public class SourceInfoMap {
/**
* Expect a particular token string to be returned by the given
* StringTokenizer.
- *
+ *
* @param tokenizer
* the StringTokenizer
* @param token
@@ -437,11 +451,13 @@ public class SourceInfoMap {
* @return true if the expected token was returned, false if not
*/
private static boolean expect(StringTokenizer tokenizer, String token) {
- if (!tokenizer.hasMoreTokens())
+ if (!tokenizer.hasMoreTokens()) {
return false;
+ }
String s = tokenizer.nextToken();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("token=" + s);
+ }
return s.equals(token);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/StackDepth.java b/src/java/edu/umd/cs/findbugs/ba/StackDepth.java
index f7c33c9..32cbd43 100644
--- a/src/java/edu/umd/cs/findbugs/ba/StackDepth.java
+++ b/src/java/edu/umd/cs/findbugs/ba/StackDepth.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.ba;
/**
* Dataflow fact to represent the depth of the Java operand stack.
- *
+ *
* @see StackDepthAnalysis
*/
public class StackDepth {
@@ -29,7 +29,7 @@ public class StackDepth {
/**
* Constructor.
- *
+ *
* @param depth
* the stack depth
*/
@@ -53,13 +53,13 @@ public class StackDepth {
@Override
public String toString() {
- if (getDepth() == StackDepthAnalysis.TOP)
+ if (getDepth() == StackDepthAnalysis.TOP) {
return "[TOP]";
- else if (getDepth() == StackDepthAnalysis.BOTTOM)
+ } else if (getDepth() == StackDepthAnalysis.BOTTOM) {
return "[BOTTOM]";
- else
+ } else {
return "[" + String.valueOf(depth) + "]";
+ }
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/StackDepthAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/StackDepthAnalysis.java
index 980829a..0cd0472 100644
--- a/src/java/edu/umd/cs/findbugs/ba/StackDepthAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/StackDepthAnalysis.java
@@ -28,7 +28,7 @@ import org.apache.bcel.generic.InstructionHandle;
* A really simple forward dataflow analysis to find the depth of the Java
* operand stack. This is more of a proof of concept for the dataflow analysis
* framework than anything useful.
- *
+ *
* @see Dataflow
* @see DataflowAnalysis
*/
@@ -37,11 +37,11 @@ public class StackDepthAnalysis extends ForwardDataflowAnalysis<StackDepth> {
public static final int BOTTOM = -2;
- private ConstantPoolGen cpg;
+ private final ConstantPoolGen cpg;
/**
* Constructor.
- *
+ *
* @param cpg
* the ConstantPoolGen of the method whose CFG we're performing
* the analysis on
@@ -53,14 +53,17 @@ public class StackDepthAnalysis extends ForwardDataflowAnalysis<StackDepth> {
this.cpg = cpg;
}
+ @Override
public StackDepth createFact() {
return new StackDepth(TOP);
}
+ @Override
public void makeFactTop(StackDepth fact) {
fact.setDepth(TOP);
}
+ @Override
public boolean isTop(StackDepth fact) {
return fact.getDepth() == TOP;
}
@@ -71,14 +74,17 @@ public class StackDepthAnalysis extends ForwardDataflowAnalysis<StackDepth> {
return depth != TOP && depth != BOTTOM;
}
+ @Override
public void copy(StackDepth source, StackDepth dest) {
dest.setDepth(source.getDepth());
}
+ @Override
public void initEntryFact(StackDepth entryFact) {
entryFact.setDepth(0); // stack depth == 0 at entry to CFG
}
+ @Override
public boolean same(StackDepth fact1, StackDepth fact2) {
return fact1.getDepth() == fact2.getDepth();
}
@@ -89,29 +95,33 @@ public class StackDepthAnalysis extends ForwardDataflowAnalysis<StackDepth> {
Instruction ins = handle.getInstruction();
int produced = ins.produceStack(cpg);
int consumed = ins.consumeStack(cpg);
- if (produced == Constants.UNPREDICTABLE || consumed == Constants.UNPREDICTABLE)
+ if (produced == Constants.UNPREDICTABLE || consumed == Constants.UNPREDICTABLE) {
throw new IllegalStateException("Unpredictable stack delta for instruction: " + handle);
+ }
int depth = fact.getDepth();
depth += (produced - consumed);
- if (depth < 0)
+ if (depth < 0) {
fact.setDepth(BOTTOM);
- else
+ } else {
fact.setDepth(depth);
+ }
}
+ @Override
public void meetInto(StackDepth fact, Edge edge, StackDepth result) {
int a = fact.getDepth();
int b = result.getDepth();
int combined;
- if (a == TOP)
+ if (a == TOP) {
combined = b;
- else if (b == TOP)
+ } else if (b == TOP) {
combined = a;
- else if (a == BOTTOM || b == BOTTOM || a != b)
+ } else if (a == BOTTOM || b == BOTTOM || a != b) {
combined = BOTTOM;
- else
+ } else {
combined = a;
+ }
result.setDepth(combined);
}
@@ -150,4 +160,3 @@ public class StackDepthAnalysis extends ForwardDataflowAnalysis<StackDepth> {
// }
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/Target.java b/src/java/edu/umd/cs/findbugs/ba/Target.java
index 7683fa4..b3eb732 100644
--- a/src/java/edu/umd/cs/findbugs/ba/Target.java
+++ b/src/java/edu/umd/cs/findbugs/ba/Target.java
@@ -25,13 +25,14 @@ import org.apache.bcel.generic.InstructionHandle;
* The target of a branch instruction.
*/
public class Target {
- private InstructionHandle targetInstruction;
+ private final InstructionHandle targetInstruction;
- private @Edge.Type int edgeType;
+ private @Edge.Type
+ final int edgeType;
/**
* Constructor.
- *
+ *
* @param targetInstruction
* the handle of the target instruction
* @param edgeType
diff --git a/src/java/edu/umd/cs/findbugs/ba/TargetEnumeratingVisitor.java b/src/java/edu/umd/cs/findbugs/ba/TargetEnumeratingVisitor.java
index 9ad69d5..c612db7 100644
--- a/src/java/edu/umd/cs/findbugs/ba/TargetEnumeratingVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/TargetEnumeratingVisitor.java
@@ -34,23 +34,23 @@ import org.apache.bcel.generic.Select;
/**
* Visitor to find all of the targets of an instruction whose InstructionHandle
* is given. Note that we don't consider exception edges.
- *
+ *
* @author David Hovemeyer
* @author Chadd Williams
*/
public class TargetEnumeratingVisitor extends org.apache.bcel.generic.EmptyVisitor implements EdgeTypes {
- private InstructionHandle handle;
+ private final InstructionHandle handle;
- private ConstantPoolGen constPoolGen;
+ private final ConstantPoolGen constPoolGen;
- private LinkedList<Target> targetList;
+ private final LinkedList<Target> targetList;
private boolean isBranch, isReturn, isThrow, isExit;
/**
* Constructor.
- *
+ *
* @param handle
* the handle of the instruction whose targets should be
* enumerated
@@ -106,8 +106,9 @@ public class TargetEnumeratingVisitor extends org.apache.bcel.generic.EmptyVisit
public void visitGotoInstruction(GotoInstruction ins) {
isBranch = true;
InstructionHandle target = ins.getTarget();
- if (target == null)
+ if (target == null) {
throw new IllegalStateException();
+ }
targetList.add(new Target(target, GOTO_EDGE));
}
@@ -115,8 +116,9 @@ public class TargetEnumeratingVisitor extends org.apache.bcel.generic.EmptyVisit
public void visitIfInstruction(IfInstruction ins) {
isBranch = true;
InstructionHandle target = ins.getTarget();
- if (target == null)
+ if (target == null) {
throw new IllegalStateException();
+ }
targetList.add(new Target(target, IFCMP_EDGE));
InstructionHandle fallThrough = handle.getNext();
targetList.add(new Target(fallThrough, FALL_THROUGH_EDGE));
@@ -159,8 +161,9 @@ public class TargetEnumeratingVisitor extends org.apache.bcel.generic.EmptyVisit
String methodName = ins.getName(constPoolGen);
String methodSig = ins.getSignature(constPoolGen);
- if (className.equals("java.lang.System") && methodName.equals("exit") && methodSig.equals("(I)V"))
+ if ("java.lang.System".equals(className) && "exit".equals(methodName) && "(I)V".equals(methodSig)) {
isExit = true;
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/TestCaseDetector.java b/src/java/edu/umd/cs/findbugs/ba/TestCaseDetector.java
index 17ddbd0..6ecd244 100644
--- a/src/java/edu/umd/cs/findbugs/ba/TestCaseDetector.java
+++ b/src/java/edu/umd/cs/findbugs/ba/TestCaseDetector.java
@@ -33,16 +33,18 @@ public class TestCaseDetector {
private static final ClassDescriptor JUNIT3TESTCASE = DescriptorFactory.createClassDescriptor("junit/framework/TestCase");
public static boolean likelyTestCase(XMethod m) {
- if (m.getAnnotation(JUNIT4TEST) != null)
+ if (m.getAnnotation(JUNIT4TEST) != null) {
return true;
+ }
ClassDescriptor c = m.getClassDescriptor();
if (m.getName().startsWith("test") || m.getName().startsWith("assert")) {
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
try {
- if (subtypes2.isSubtype(c, JUNIT3TESTCASE))
+ if (subtypes2.isSubtype(c, JUNIT3TESTCASE)) {
return true;
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/URLClassPath.java b/src/java/edu/umd/cs/findbugs/ba/URLClassPath.java
index 28273f2..d9d2326 100644
--- a/src/java/edu/umd/cs/findbugs/ba/URLClassPath.java
+++ b/src/java/edu/umd/cs/findbugs/ba/URLClassPath.java
@@ -42,7 +42,7 @@ import edu.umd.cs.findbugs.util.Archive;
/**
* A work-alike class to use instead of BCEL's ClassPath class. The main
* difference is that URLClassPath can load classfiles from URLs.
- *
+ *
* @author David Hovemeyer
*/
public class URLClassPath implements Serializable {
@@ -55,7 +55,7 @@ public class URLClassPath implements Serializable {
/**
* Open an input stream to read a resource in the codebase described by
* this classpath entry.
- *
+ *
* @param resourceName
* name of resource to load: e.g., "java/lang/Object.class"
* @return an InputStream, or null if the resource wasn't found
@@ -94,26 +94,30 @@ public class URLClassPath implements Serializable {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.URLClassPath.Entry#openStream(java.lang.String)
*/
+ @Override
public InputStream openStream(String resourceName) throws IOException {
ZipEntry zipEntry = zipFile.getEntry(resourceName);
- if (zipEntry == null)
+ if (zipEntry == null) {
return null;
+ }
return zipFile.getInputStream(zipEntry);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.URLClassPath.Entry#getURL()
*/
+ @Override
public String getURL() {
return zipFile.getName();
}
+ @Override
public void close() {
try {
zipFile.close();
@@ -128,11 +132,11 @@ public class URLClassPath implements Serializable {
* filesystem.
*/
private static class LocalDirectoryEntry implements Entry {
- private String dirName;
+ private final String dirName;
/**
* Constructor.
- *
+ *
* @param dirName
* name of the local directory
* @throws IOException
@@ -140,32 +144,37 @@ public class URLClassPath implements Serializable {
*/
public LocalDirectoryEntry(String dirName) throws IOException {
this.dirName = dirName;
- if (!(new File(dirName).isDirectory()))
+ if (!(new File(dirName).isDirectory())) {
throw new IOException(dirName + " is not a directory");
+ }
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.URLClassPath.Entry#openStream(java.lang.String)
*/
+ @Override
public InputStream openStream(String resourceName) throws IOException {
File file = new File(dirName, resourceName);
- if (!file.exists())
+ if (!file.exists()) {
return null;
+ }
return new BufferedInputStream(new FileInputStream(file));
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.URLClassPath.Entry#getURL()
*/
+ @Override
public String getURL() {
return dirName;
}
+ @Override
public void close() {
// Nothing to do here
}
@@ -177,11 +186,11 @@ public class URLClassPath implements Serializable {
* jar URLs to specify individual files within the remote archive.
*/
private static class RemoteArchiveEntry implements Entry {
- private URL remoteArchiveURL;
+ private final URL remoteArchiveURL;
/**
* Constructor.
- *
+ *
* @param remoteArchiveURL
* the remote zip/jar file URL
*/
@@ -191,10 +200,11 @@ public class URLClassPath implements Serializable {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.URLClassPath.Entry#openStream(java.lang.String)
*/
+ @Override
public InputStream openStream(String resourceName) throws IOException {
URL remoteFileURL = new URL("jar:" + remoteArchiveURL.toString() + "/" + resourceName);
try {
@@ -206,13 +216,15 @@ public class URLClassPath implements Serializable {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.URLClassPath.Entry#getURL()
*/
+ @Override
public String getURL() {
return remoteArchiveURL.toString();
}
+ @Override
public void close() {
// Nothing to do
}
@@ -223,11 +235,11 @@ public class URLClassPath implements Serializable {
* Classpath entry class to load files from a remote directory URL.
*/
private static class RemoteDirectoryEntry implements Entry {
- private URL remoteDirURL;
+ private final URL remoteDirURL;
/**
* Constructor.
- *
+ *
* @param remoteDirURL
* URL of the remote directory; must end in "/"
*/
@@ -237,10 +249,11 @@ public class URLClassPath implements Serializable {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.URLClassPath.Entry#openStream(java.lang.String)
*/
+ @Override
public InputStream openStream(String resourceName) throws IOException {
URL remoteFileURL = new URL(remoteDirURL.toString() + resourceName);
try {
@@ -252,20 +265,22 @@ public class URLClassPath implements Serializable {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.URLClassPath.Entry#getURL()
*/
+ @Override
public String getURL() {
return remoteDirURL.toString();
}
+ @Override
public void close() {
// Nothing to do
}
}
// Fields
- private List<Entry> entryList;
+ private final List<Entry> entryList;
/**
* Constructor. Creates a classpath with no elements.
@@ -278,7 +293,7 @@ public class URLClassPath implements Serializable {
* Add given filename/URL to the classpath. If no URL protocol is given, the
* filename is assumed to be a local file or directory. Remote directories
* must be specified with a "/" character at the end of the URL.
- *
+ *
* @param fileName
* filename or URL of codebase (directory or archive file)
* @throws IOException
@@ -295,22 +310,24 @@ public class URLClassPath implements Serializable {
boolean isArchive = fileExtension != null && URLClassPath.isArchiveExtension(fileExtension);
Entry entry;
- if (protocol.equals("file")) {
+ if ("file".equals(protocol)) {
String localFileName = fileName.substring("file:".length());
- if (fileName.endsWith("/") || new File(localFileName).isDirectory())
+ if (fileName.endsWith("/") || new File(localFileName).isDirectory()) {
entry = new LocalDirectoryEntry(localFileName);
- else if (isArchive)
+ } else if (isArchive) {
entry = new LocalArchiveEntry(localFileName);
- else
+ } else {
throw new IOException("Classpath entry " + fileName + " is not a directory or archive file");
+ }
} else {
- if (fileName.endsWith("/"))
+ if (fileName.endsWith("/")) {
entry = new RemoteDirectoryEntry(new URL(fileName));
- else if (isArchive)
+ } else if (isArchive) {
entry = new RemoteArchiveEntry(new URL(fileName));
- else
+ } else {
throw new IOException("Classpath entry " + fileName + " is not a remote directory or archive file");
+ }
}
entryList.add(entry);
@@ -318,14 +335,15 @@ public class URLClassPath implements Serializable {
/**
* Return the classpath string.
- *
+ *
* @return the classpath string
*/
public String getClassPath() {
StringBuilder buf = new StringBuilder();
for (Entry entry : entryList) {
- if (buf.length() > 0)
+ if (buf.length() > 0) {
buf.append(File.pathSeparator);
+ }
buf.append(entry.getURL());
}
return buf.toString();
@@ -333,7 +351,7 @@ public class URLClassPath implements Serializable {
/**
* Open a stream to read given resource.
- *
+ *
* @param resourceName
* name of resource to load, e.g. "java/lang/Object.class"
* @return input stream to read resource, or null if resource could not be
@@ -379,11 +397,11 @@ public class URLClassPath implements Serializable {
return null;
}
- private Set<String> classesThatCantBeFound = new HashSet<String>();
+ private final Set<String> classesThatCantBeFound = new HashSet<String>();
/**
* Look up a class from the classpath.
- *
+ *
* @param className
* name of class to look up
* @return the JavaClass object for the class
@@ -437,7 +455,7 @@ public class URLClassPath implements Serializable {
/**
* Get the URL protocol of given URL string.
- *
+ *
* @param urlString
* the URL string
* @return the protocol name ("http", "file", etc.), or null if there is no
@@ -448,15 +466,16 @@ public class URLClassPath implements Serializable {
int firstColon = urlString.indexOf(':');
if (firstColon >= 0) {
String specifiedProtocol = urlString.substring(0, firstColon);
- if (FindBugs.knownURLProtocolSet.contains(specifiedProtocol))
+ if (FindBugs.knownURLProtocolSet.contains(specifiedProtocol)) {
protocol = specifiedProtocol;
+ }
}
return protocol;
}
/**
* Get the file extension of given fileName.
- *
+ *
* @return the file extension, or null if there is no file extension
*/
public static String getFileExtension(String fileName) {
@@ -466,7 +485,7 @@ public class URLClassPath implements Serializable {
/**
* Determine if given file extension indicates an archive file.
- *
+ *
* @param fileExtension
* the file extension (e.g., ".jar")
* @return true if the file extension indicates an archive, false otherwise
@@ -476,4 +495,3 @@ public class URLClassPath implements Serializable {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/URLClassPathRepository.java b/src/java/edu/umd/cs/findbugs/ba/URLClassPathRepository.java
index e85c65d..919afd5 100644
--- a/src/java/edu/umd/cs/findbugs/ba/URLClassPathRepository.java
+++ b/src/java/edu/umd/cs/findbugs/ba/URLClassPathRepository.java
@@ -51,9 +51,9 @@ public class URLClassPathRepository implements Repository {
private static final long serialVersionUID = 1L;
- private Map<String, JavaClass> nameToClassMap;
+ private final Map<String, JavaClass> nameToClassMap;
- private URLClassPath urlClassPath;
+ private final URLClassPath urlClassPath;
public URLClassPathRepository() {
this.nameToClassMap = new HashMap<String, JavaClass>();
@@ -89,19 +89,23 @@ public class URLClassPathRepository implements Repository {
* org.apache.bcel.util.Repository#storeClass(org.apache.bcel.classfile.
* JavaClass)
*/
+ @Override
public void storeClass(JavaClass javaClass) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Storing class " + javaClass.getClassName() + " in repository");
+ }
JavaClass previous = nameToClassMap.put(javaClass.getClassName(), javaClass);
if (DEBUG && previous != null) {
System.out.println("\t==> A previous class was evicted!");
dumpStack();
}
Repository tmp = org.apache.bcel.Repository.getRepository();
- if (tmp != null && tmp != this)
+ if (tmp != null && tmp != this) {
throw new IllegalStateException("Wrong/multiple BCEL repository");
- if (tmp == null)
+ }
+ if (tmp == null) {
org.apache.bcel.Repository.setRepository(this);
+ }
}
/*
@@ -111,6 +115,7 @@ public class URLClassPathRepository implements Repository {
* org.apache.bcel.util.Repository#removeClass(org.apache.bcel.classfile
* .JavaClass)
*/
+ @Override
public void removeClass(JavaClass javaClass) {
nameToClassMap.remove(javaClass.getClassName());
if (DEBUG) {
@@ -128,6 +133,7 @@ public class URLClassPathRepository implements Repository {
*
* @see org.apache.bcel.util.Repository#findClass(java.lang.String)
*/
+ @Override
public JavaClass findClass(/*@Nonnull*/ String className) {
// Make sure we handle class names with slashes.
// If we don't, we can get into serious trouble: a previously
@@ -144,9 +150,11 @@ public class URLClassPathRepository implements Repository {
*
* @see org.apache.bcel.util.Repository#loadClass(java.lang.String)
*/
+ @Override
public JavaClass loadClass(/*@Nonnull*/ String className) throws ClassNotFoundException {
- if (className == null)
+ if (className == null) {
throw new IllegalArgumentException("className is null");
+ }
// if (className.indexOf('/') >= 0) throw new IllegalStateException();
JavaClass javaClass = findClass(className);
if (javaClass == null) {
@@ -165,7 +173,8 @@ public class URLClassPathRepository implements Repository {
*
* @see org.apache.bcel.util.Repository#loadClass(java.lang.Class)
*/
- public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
+ @Override
+ public JavaClass loadClass(Class<?> clazz) throws ClassNotFoundException {
return loadClass(clazz.getName());
}
@@ -174,6 +183,7 @@ public class URLClassPathRepository implements Repository {
*
* @see org.apache.bcel.util.Repository#clear()
*/
+ @Override
public void clear() {
if (DEBUG) {
System.out.println("Clearing Repository!");
@@ -187,9 +197,9 @@ public class URLClassPathRepository implements Repository {
*
* @see org.apache.bcel.util.Repository#getClassPath()
*/
+ @Override
public ClassPath getClassPath() {
return new ClassPath(urlClassPath.getClassPath());
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/UnresolvedXField.java b/src/java/edu/umd/cs/findbugs/ba/UnresolvedXField.java
index e492362..09af419 100644
--- a/src/java/edu/umd/cs/findbugs/ba/UnresolvedXField.java
+++ b/src/java/edu/umd/cs/findbugs/ba/UnresolvedXField.java
@@ -41,8 +41,9 @@ public class UnresolvedXField extends AbstractField {
protected UnresolvedXField(@DottedClassName String className, String methodName, String methodSig, int accessFlags) {
super(className, methodName, methodSig, accessFlags);
- if (methodSig.charAt(0) == '(')
+ if (methodSig.charAt(0) == '(') {
throw new IllegalArgumentException("Bad signature: " + methodSig);
+ }
if (XFactory.DEBUG_UNRESOLVED) {
System.out.println("Unresolved xmethod: " + this);
}
@@ -50,8 +51,9 @@ public class UnresolvedXField extends AbstractField {
protected UnresolvedXField(FieldDescriptor m) {
super(m.getClassDescriptor().getDottedClassName(), m.getName(), m.getSignature(), m.isStatic() ? Constants.ACC_STATIC : 0);
- if (m.getSignature().charAt(0) == '(')
+ if (m.getSignature().charAt(0) == '(') {
throw new IllegalArgumentException("Bad signature: " + m.getSignature());
+ }
if (XFactory.DEBUG_UNRESOLVED) {
System.out.println("Unresolved xmethod: " + this);
}
@@ -59,9 +61,10 @@ public class UnresolvedXField extends AbstractField {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
+ @Override
public int compareTo(ComparableField o) {
if (o instanceof XField) {
return XFactory.compare((XField) this, (XField) o);
@@ -72,42 +75,46 @@ public class UnresolvedXField extends AbstractField {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.analysis.AnnotatedObject#getAnnotation(
* edu.umd.cs.findbugs.classfile.ClassDescriptor)
*/
+ @Override
public AnnotationValue getAnnotation(ClassDescriptor desc) {
return null;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.analysis.AnnotatedObject#
* getAnnotationDescriptors()
*/
+ @Override
public Collection<ClassDescriptor> getAnnotationDescriptors() {
return Collections.<ClassDescriptor> emptyList();
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.analysis.AnnotatedObject#getAnnotations()
*/
+ @Override
public Collection<AnnotationValue> getAnnotations() {
return Collections.<AnnotationValue> emptyList();
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.analysis.AnnotatedObject#getContainingScope
* ()
*/
+ @Override
public AnnotatedObject getContainingScope() {
// TODO Auto-generated method stub
return AnalysisContext.currentXFactory().getXClass(
@@ -116,24 +123,27 @@ public class UnresolvedXField extends AbstractField {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.analysis.AnnotatedObject#getElementType()
*/
+ @Override
public ElementType getElementType() {
return ElementType.FIELD;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isDeprecated()
*/
+ @Override
public boolean isDeprecated() {
// TODO Auto-generated method stub
return false;
}
+ @Override
public @CheckForNull
String getSourceSignature() {
return null;
diff --git a/src/java/edu/umd/cs/findbugs/ba/UnresolvedXMethod.java b/src/java/edu/umd/cs/findbugs/ba/UnresolvedXMethod.java
index 67ecefe..1d84c1f 100644
--- a/src/java/edu/umd/cs/findbugs/ba/UnresolvedXMethod.java
+++ b/src/java/edu/umd/cs/findbugs/ba/UnresolvedXMethod.java
@@ -39,6 +39,7 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#isReturnTypeReferenceType()
*/
+ @Override
public boolean isReturnTypeReferenceType() {
SignatureParser parser = new SignatureParser(getSignature());
String returnTypeSig = parser.getReturnTypeSignature();
@@ -50,6 +51,7 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
+ @Override
public int compareTo(ComparableMethod o) {
if (o instanceof XMethod) {
return XFactory.compare((XMethod) this, (XMethod) o);
@@ -57,12 +59,15 @@ class UnresolvedXMethod extends AbstractMethod {
throw new ClassCastException("Don't know how to compare " + this.getClass().getName() + " to " + o.getClass().getName());
}
+ @Override
public ElementType getElementType() {
- if (getName().equals("<init>"))
+ if ("<init>".equals(getName())) {
return ElementType.CONSTRUCTOR;
+ }
return ElementType.METHOD;
}
+ @Override
public @CheckForNull
AnnotatedObject getContainingScope() {
try {
@@ -77,6 +82,7 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#getThrownExceptions()
*/
+ @Override
public String[] getThrownExceptions() {
return new String[0];
@@ -87,10 +93,12 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#isUnconditionalThrower()
*/
+ @Override
public boolean isUnconditionalThrower() {
return false;
}
+ @Override
public boolean isUnsupported() {
return false;
}
@@ -100,6 +108,7 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#isAbstract()
*/
+ @Override
public boolean isAbstract() {
return false;
}
@@ -109,6 +118,7 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isSynthetic()
*/
+ @Override
public boolean isSynthetic() {
return false;
}
@@ -118,6 +128,7 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isDeprecated()
*/
+ @Override
public boolean isDeprecated() {
return false;
}
@@ -127,6 +138,7 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#isVarArgs()
*/
+ @Override
public boolean isVarArgs() {
return false;
}
@@ -136,10 +148,12 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#usesConcurrency()
*/
+ @Override
public boolean usesConcurrency() {
return false;
}
+ @Override
public @CheckForNull
String getSourceSignature() {
return null;
@@ -150,10 +164,12 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#isStub()
*/
+ @Override
public boolean isStub() {
return false;
}
+ @Override
public boolean isIdentity() {
return false;
}
@@ -166,6 +182,7 @@ class UnresolvedXMethod extends AbstractMethod {
* @see edu.umd.cs.findbugs.ba.XMethod#addParameterAnnotation(int,
* edu.umd.cs.findbugs.classfile.analysis.AnnotationValue)
*/
+ @Override
public void addParameterAnnotation(int param, AnnotationValue annotationValue) {
HashMap<Integer, Map<ClassDescriptor, AnnotationValue>> updatedAnnotations = new HashMap<Integer, Map<ClassDescriptor, AnnotationValue>>(
methodParameterAnnotations);
@@ -180,29 +197,36 @@ class UnresolvedXMethod extends AbstractMethod {
}
+ @Override
public Collection<ClassDescriptor> getParameterAnnotationDescriptors(int param) {
Map<ClassDescriptor, AnnotationValue> map = methodParameterAnnotations.get(param);
- if (map == null)
+ if (map == null) {
return Collections.<ClassDescriptor> emptySet();
+ }
return map.keySet();
}
+ @Override
public boolean hasParameterAnnotations() {
return !methodParameterAnnotations.isEmpty();
}
-
+
+ @Override
public @Nullable
AnnotationValue getParameterAnnotation(int param, ClassDescriptor desc) {
Map<ClassDescriptor, AnnotationValue> map = methodParameterAnnotations.get(param);
- if (map == null)
+ if (map == null) {
return null;
+ }
return map.get(desc);
}
+ @Override
public Collection<AnnotationValue> getParameterAnnotations(int param) {
Map<ClassDescriptor, AnnotationValue> map = methodParameterAnnotations.get(param);
- if (map == null)
+ if (map == null) {
return Collections.<AnnotationValue> emptySet();
+ }
return map.values();
}
@@ -215,6 +239,7 @@ class UnresolvedXMethod extends AbstractMethod {
* edu.umd.cs.findbugs.ba.XMethod#addAnnotation(edu.umd.cs.findbugs.classfile
* .analysis.AnnotationValue)
*/
+ @Override
public void addAnnotation(AnnotationValue annotationValue) {
HashMap<ClassDescriptor, AnnotationValue> updatedAnnotations = new HashMap<ClassDescriptor, AnnotationValue>(
methodAnnotations);
@@ -222,14 +247,17 @@ class UnresolvedXMethod extends AbstractMethod {
methodAnnotations = updatedAnnotations;
}
+ @Override
public Collection<ClassDescriptor> getAnnotationDescriptors() {
return methodAnnotations.keySet();
}
+ @Override
public AnnotationValue getAnnotation(ClassDescriptor desc) {
return methodAnnotations.get(desc);
}
+ @Override
public Collection<AnnotationValue> getAnnotations() {
return methodAnnotations.values();
}
@@ -239,6 +267,7 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#bridgeFrom()
*/
+ @Override
public XMethod bridgeFrom() {
return null;
}
@@ -248,6 +277,7 @@ class UnresolvedXMethod extends AbstractMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#bridgeTo()
*/
+ @Override
public XMethod bridgeTo() {
return null;
}
@@ -255,18 +285,26 @@ class UnresolvedXMethod extends AbstractMethod {
/* (non-Javadoc)
* @see edu.umd.cs.findbugs.ba.XMethod#getAccessMethodFor()
*/
+ @Override
public MethodDescriptor getAccessMethodForMethod() {
return null;
}
+ @Override
public FieldDescriptor getAccessMethodForField() {
return null;
}
/* (non-Javadoc)
* @see edu.umd.cs.findbugs.ba.XMethod#isVariableSynthetic(int)
*/
+ @Override
public boolean isVariableSynthetic(int param) {
return false;
}
+ @Override
+ public boolean usesInvokeDynamic() {
+ return false;
+ }
+
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/XClass.java b/src/java/edu/umd/cs/findbugs/ba/XClass.java
index 98e959c..0a0ab92 100644
--- a/src/java/edu/umd/cs/findbugs/ba/XClass.java
+++ b/src/java/edu/umd/cs/findbugs/ba/XClass.java
@@ -79,8 +79,10 @@ public interface XClass extends Comparable<ClassDescriptor>, AccessibleEntity, A
public @CheckForNull
String getSource();
+ @Override
public Collection<ClassDescriptor> getAnnotationDescriptors();
+ @Override
public AnnotationValue getAnnotation(ClassDescriptor desc);
/**
diff --git a/src/java/edu/umd/cs/findbugs/ba/XFactory.java b/src/java/edu/umd/cs/findbugs/ba/XFactory.java
index ed77bf3..f15cecd 100644
--- a/src/java/edu/umd/cs/findbugs/ba/XFactory.java
+++ b/src/java/edu/umd/cs/findbugs/ba/XFactory.java
@@ -65,35 +65,38 @@ import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
/**
* Factory methods for creating XMethod objects.
- *
+ *
* @author David Hovemeyer
*/
public class XFactory {
public static final boolean DEBUG_UNRESOLVED = SystemProperties.getBoolean("findbugs.xfactory.debugunresolved");
- private Set<ClassDescriptor> reflectiveClasses = new HashSet<ClassDescriptor>();
+ private final Set<ClassDescriptor> reflectiveClasses = new HashSet<ClassDescriptor>();
+
+ private final Map<MethodDescriptor, XMethod> methods = new HashMap<MethodDescriptor, XMethod>();
- private Map<MethodDescriptor, XMethod> methods = new HashMap<MethodDescriptor, XMethod>();
+ private final Map<FieldDescriptor, XField> fields = new HashMap<FieldDescriptor, XField>();
- private Map<FieldDescriptor, XField> fields = new HashMap<FieldDescriptor, XField>();
+ private final Set<XMethod> calledMethods = new HashSet<XMethod>();
- private Set<XMethod> calledMethods = new HashSet<XMethod>();
+ private final Set<XField> emptyArrays = new HashSet<XField>();
- private Set<XField> emptyArrays = new HashSet<XField>();
+ private final Set<String> calledMethodSignatures = new HashSet<String>();
- private Set<String> calledMethodSignatures = new HashSet<String>();
-
- private Set<MethodDescriptor> functionsThatMightBeMistakenForProcedures = new HashSet<MethodDescriptor>();
+ private final Set<MethodDescriptor> functionsThatMightBeMistakenForProcedures = new HashSet<MethodDescriptor>();
public void canonicalizeAll() {
DescriptorFactory descriptorFactory = DescriptorFactory.instance();
- for (XMethod m : methods.values())
+ for (XMethod m : methods.values()) {
if (m instanceof MethodDescriptor) {
descriptorFactory.canonicalize((MethodDescriptor) m);
}
- for (XField f : fields.values())
- if (f instanceof FieldDescriptor)
+ }
+ for (XField f : fields.values()) {
+ if (f instanceof FieldDescriptor) {
descriptorFactory.canonicalize((FieldDescriptor) f);
+ }
+ }
}
/**
@@ -131,15 +134,16 @@ public class XFactory {
}
public boolean isCalled(XMethod m) {
- if (m.getName().equals("<clinit>"))
+ if ("<clinit>".equals(m.getName())) {
return true;
+ }
return calledMethods.contains(m);
}
public Set<XMethod> getCalledMethods() {
return calledMethods;
}
-
+
public void addFunctionThatMightBeMistakenForProcedures(MethodDescriptor m) {
functionsThatMightBeMistakenForProcedures.add(m);
}
@@ -160,18 +164,23 @@ public class XFactory {
}
public boolean isCalledDirectlyOrIndirectly(XMethod m) {
- if (isCalled(m))
+ if (isCalled(m)) {
return true;
- if (m.isStatic() || m.isPrivate() || m.getName().equals("<init>"))
+ }
+ if (m.isStatic() || m.isPrivate() || "<init>".equals(m.getName())) {
return false;
+ }
try {
IAnalysisCache analysisCache = Global.getAnalysisCache();
XClass clazz = analysisCache.getClassAnalysis(XClass.class, m.getClassDescriptor());
- if (isCalledDirectlyOrIndirectly(clazz.getSuperclassDescriptor(), m))
+ if (isCalledDirectlyOrIndirectly(clazz.getSuperclassDescriptor(), m)) {
return true;
- for (ClassDescriptor i : clazz.getInterfaceDescriptorList())
- if (isCalledDirectlyOrIndirectly(i, m))
+ }
+ for (ClassDescriptor i : clazz.getInterfaceDescriptorList()) {
+ if (isCalledDirectlyOrIndirectly(i, m)) {
return true;
+ }
+ }
return false;
} catch (edu.umd.cs.findbugs.classfile.MissingClassException e) {
@@ -186,26 +195,25 @@ public class XFactory {
}
}
- /**
- * @param superclassDescriptor
- * @param m
- * @return
- * @throws CheckedAnalysisException
- */
private boolean isCalledDirectlyOrIndirectly(@CheckForNull ClassDescriptor clazzDescriptor, XMethod m)
throws CheckedAnalysisException {
- if (clazzDescriptor == null)
+ if (clazzDescriptor == null) {
return false;
+ }
IAnalysisCache analysisCache = Global.getAnalysisCache();
XClass clazz = analysisCache.getClassAnalysis(XClass.class, clazzDescriptor);
XMethod m2 = clazz.findMethod(m.getName(), m.getSignature(), m.isStatic());
- if (m2 != null && isCalled(m2))
+ if (m2 != null && isCalled(m2)) {
return true;
- if (isCalledDirectlyOrIndirectly(clazz.getSuperclassDescriptor(), m))
+ }
+ if (isCalledDirectlyOrIndirectly(clazz.getSuperclassDescriptor(), m)) {
return true;
- for (ClassDescriptor i : clazz.getInterfaceDescriptorList())
- if (isCalledDirectlyOrIndirectly(i, m))
+ }
+ for (ClassDescriptor i : clazz.getInterfaceDescriptorList()) {
+ if (isCalledDirectlyOrIndirectly(i, m)) {
return true;
+ }
+ }
return false;
@@ -215,10 +223,6 @@ public class XFactory {
return calledMethodSignatures.contains(getDetailedSignature(m));
}
- /**
- * @param m2
- * @return
- */
private static String getDetailedSignature(XMethod m2) {
return m2.getName() + m2.getSignature() + m2.isStatic();
}
@@ -234,7 +238,7 @@ public class XFactory {
/**
* Create an XMethod object from a BCEL Method.
- *
+ *
* @param className
* the class to which the Method belongs
* @param method
@@ -259,7 +263,7 @@ public class XFactory {
/**
* Create an XMethod object from a BCEL Method.
- *
+ *
* @param javaClass
* the class to which the Method belongs
* @param method
@@ -268,8 +272,9 @@ public class XFactory {
*/
public static XMethod createXMethod(JavaClass javaClass, Method method) {
- if (method == null)
+ if (method == null) {
throw new NullPointerException("method must not be null");
+ }
XMethod xmethod = createXMethod(javaClass.getClassName(), method);
assert xmethod.isResolved();
return xmethod;
@@ -317,14 +322,16 @@ public class XFactory {
XFactory xFactory = AnalysisContext.currentXFactory();
XMethod m = xFactory.methods.get(desc);
- if (m != null)
+ if (m != null) {
return m;
+ }
m = xFactory.resolveXMethod(desc);
if (m instanceof MethodDescriptor) {
xFactory.methods.put((MethodDescriptor) m, m);
DescriptorFactory.instance().canonicalize((MethodDescriptor) m);
- } else
+ } else {
xFactory.methods.put(desc, m);
+ }
return m;
}
@@ -332,8 +339,9 @@ public class XFactory {
XFactory xFactory = AnalysisContext.currentXFactory();
int count = 0;
for (XMethod m : xFactory.methods.values()) {
- if (m instanceof MethodInfo)
+ if (m instanceof MethodInfo) {
count++;
+ }
}
System.out.printf("XFactory cached methods: %d/%d%n", count, xFactory.methods.size());
DescriptorFactory.instance().profile();
@@ -345,14 +353,17 @@ public class XFactory {
try {
while (true) {
XMethod m = methods.get(desc);
- if (m != null)
+ if (m != null) {
return m;
+ }
XClass xClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, desc.getClassDescriptor());
- if (xClass == null)
+ if (xClass == null) {
break;
+ }
ClassDescriptor superClass = xClass.getSuperclassDescriptor();
- if (superClass == null)
+ if (superClass == null) {
break;
+ }
desc = DescriptorFactory.instance().getMethodDescriptor(superClass.getClassName(), desc.getName(),
desc.getSignature(), desc.isStatic());
}
@@ -362,11 +373,11 @@ public class XFactory {
assert true;
}
UnresolvedXMethod xmethod = new UnresolvedXMethod(originalDescriptor);
-
+
ObligationPolicyDatabase database = Global.getAnalysisCache().getOptionalDatabase(ObligationPolicyDatabase.class);
- if (BuildObligationPolicyDatabase.INFER_CLOSE_METHODS && database != null
+ if (BuildObligationPolicyDatabase.INFER_CLOSE_METHODS && database != null
&& !xmethod.getClassName().startsWith("java")) {
boolean methodHasCloseInName = false;
String methodName = xmethod.getName();
@@ -376,14 +387,15 @@ public class XFactory {
for (int i = 0; i < xmethod.getNumParams(); i++) {
Obligation obligationType = paramObligationTypes[i];
- if (obligationType == null)
+ if (obligationType == null) {
continue;
+ }
if (methodHasCloseInName) {
// Method has "close" in its name.
// Assume that it deletes the obligation.
ObligationPolicyDatabaseEntry entry = database.addParameterDeletesObligationDatabaseEntry(xmethod,
obligationType, ObligationPolicyDatabaseEntryType.STRONG);
-
+
} else {
/*
@@ -394,7 +406,7 @@ public class XFactory {
* obligation. If strict checking is performed, // weak
* entries are ignored.
*/
- if (methodName.equals("<init>") || methodName.startsWith("access$") || xmethod.isStatic()
+ if ("<init>".equals(methodName) || methodName.startsWith("access$") || xmethod.isStatic()
|| methodName.toLowerCase().indexOf("close") >= 0
|| xmethod.getSignature().toLowerCase().indexOf("Closeable") >= 0) {
ObligationPolicyDatabaseEntry entry = database.addParameterDeletesObligationDatabaseEntry(xmethod,
@@ -414,7 +426,7 @@ public class XFactory {
/**
* Create an XField object
- *
+ *
* @param className
* @param fieldName
* @param fieldSignature
@@ -431,7 +443,7 @@ public class XFactory {
/**
* Create an XField object
- *
+ *
* @param className
* @param fieldName
* @param fieldSignature
@@ -458,8 +470,9 @@ public class XFactory {
public static XField createReferencedXField(DismantleBytecode visitor) {
int seen = visitor.getOpcode();
- if (seen != Opcodes.GETFIELD && seen != Opcodes.GETSTATIC && seen != Opcodes.PUTFIELD && seen != Opcodes.PUTSTATIC)
+ if (seen != Opcodes.GETFIELD && seen != Opcodes.GETSTATIC && seen != Opcodes.PUTFIELD && seen != Opcodes.PUTSTATIC) {
throw new IllegalArgumentException("Not at a field reference");
+ }
return createXFieldUsingSlashedClassName(visitor.getClassConstantOperand(), visitor.getNameConstantOperand(),
visitor.getSigConstantOperand(), visitor.getRefFieldIsStatic());
}
@@ -480,7 +493,7 @@ public class XFactory {
/**
* Create an XField object from a BCEL Field.
- *
+ *
* @param className
* the name of the Java class containing the field
* @param field
@@ -500,7 +513,7 @@ public class XFactory {
* Get an XField object exactly matching given class, name, and signature.
* May return an unresolved object (if the class can't be found, or does not
* directly declare named field).
- *
+ *
* @param className
* name of class containing the field
* @param name
@@ -529,8 +542,9 @@ public class XFactory {
XFactory xFactory = AnalysisContext.currentXFactory();
XField f = xFactory.fields.get(desc);
- if (f == null)
+ if (f == null) {
return new UnresolvedXField(desc);
+ }
return f;
}
@@ -538,8 +552,9 @@ public class XFactory {
XFactory xFactory = AnalysisContext.currentXFactory();
XField m = xFactory.fields.get(desc);
- if (m != null)
+ if (m != null) {
return m;
+ }
m = xFactory.resolveXField(desc);
xFactory.fields.put(desc, m);
return m;
@@ -553,22 +568,28 @@ public class XFactory {
try {
while (!worklist.isEmpty()) {
ClassDescriptor d = worklist.removeFirst();
- if (!d.equals(originalClassDescriptor))
+ if (!d.equals(originalClassDescriptor)) {
desc = DescriptorFactory.instance().getFieldDescriptor(d.getClassName(), desc.getName(), desc.getSignature(),
desc.isStatic());
+ }
XField f = fields.get(desc);
- if (f != null)
+ if (f != null) {
return f;
+ }
XClass xClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, d);
- if (xClass == null)
+ if (xClass == null) {
break;
+ }
ClassDescriptor superClass = xClass.getSuperclassDescriptor();
- if (superClass != null)
+ if (superClass != null) {
worklist.add(superClass);
- if (originalDescriptor.isStatic())
- for (ClassDescriptor i : xClass.getInterfaceDescriptorList())
+ }
+ if (originalDescriptor.isStatic()) {
+ for (ClassDescriptor i : xClass.getInterfaceDescriptorList()) {
worklist.add(i);
+ }
+ }
}
} catch (CheckedAnalysisException e) {
@@ -579,7 +600,7 @@ public class XFactory {
/**
* Create an XMethod object from an InvokeInstruction.
- *
+ *
* @param invokeInstruction
* the InvokeInstruction
* @param cpg
@@ -597,7 +618,7 @@ public class XFactory {
/**
* Create an XMethod object from the method currently being visited by the
* given PreorderVisitor.
- *
+ *
* @param visitor
* the PreorderVisitor
* @return the XMethod representing the method currently being visited
@@ -612,7 +633,7 @@ public class XFactory {
/**
* Create an XField object from the field currently being visited by the
* given PreorderVisitor.
- *
+ *
* @param visitor
* the PreorderVisitor
* @return the XField representing the method currently being visited
@@ -639,7 +660,7 @@ public class XFactory {
/**
* Get the XClass object providing information about the class named by the
* given ClassDescriptor.
- *
+ *
* @param classDescriptor
* a ClassDescriptor
* @return an XClass object providing information about the class, or null
@@ -660,7 +681,7 @@ public class XFactory {
* <em>All methods that implement XMethod or XField should
* delegate to this method when implementing compareTo(Object)
* if the right-hand object implements XField or XMethod.</em>
- *
+ *
* @param lhs
* an XMethod or XField
* @param rhs
diff --git a/src/java/edu/umd/cs/findbugs/ba/XField.java b/src/java/edu/umd/cs/findbugs/ba/XField.java
index 43ef3af..a0c47bb 100644
--- a/src/java/edu/umd/cs/findbugs/ba/XField.java
+++ b/src/java/edu/umd/cs/findbugs/ba/XField.java
@@ -26,13 +26,13 @@ import edu.umd.cs.findbugs.classfile.analysis.AnnotatedObject;
* Abstract representation of a field. Note that this is called "XField" to
* distinguish it from BCEL's Field class. Also, you can think of the "X" as
* expanding to "Instance" or "Static".
- *
+ *
* <p>
* This interface and its implementations exist because Field objects in BCEL
* are awkward to deal with. They are not Comparable, it is difficult to find
* out what class they belong to, etc.
* </p>
- *
+ *
* <p>
* If the resolved() method returns true, then any information queried from this
* object can be assumed to be accurate. If the resolved() method returns false,
@@ -57,4 +57,3 @@ public interface XField extends ClassMember, AnnotatedObject, ComparableField {
public FieldDescriptor getFieldDescriptor();
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/XMethod.java b/src/java/edu/umd/cs/findbugs/ba/XMethod.java
index 3253398..8788c48 100644
--- a/src/java/edu/umd/cs/findbugs/ba/XMethod.java
+++ b/src/java/edu/umd/cs/findbugs/ba/XMethod.java
@@ -86,8 +86,6 @@ public interface XMethod extends ClassMember, AnnotatedObject, ComparableMethod{
* method in a superclass. This method simply forwards the call to the
* method it bridges to, which is a method with an identical name but possibly co-variant arguments and
* return values.
- *
- * @return
*/
public @CheckForNull
XMethod bridgeTo();
@@ -124,6 +122,11 @@ public interface XMethod extends ClassMember, AnnotatedObject, ComparableMethod{
public boolean isReturnTypeReferenceType();
/**
+ * Is this a bridge method?
+ */
+ public boolean isBridge();
+
+ /**
* Get ClassDescriptors (annotation classes) of annotations applied directly
* to this method's parameters.
*
@@ -158,7 +161,7 @@ public interface XMethod extends ClassMember, AnnotatedObject, ComparableMethod{
* parameter
*/
public Collection<AnnotationValue> getParameterAnnotations(int param);
-
+
public boolean hasParameterAnnotations();
/**
* Get ClassDescriptors (annotation classes) of annotations applied directly
@@ -166,6 +169,7 @@ public interface XMethod extends ClassMember, AnnotatedObject, ComparableMethod{
*
* @return ClassDescriptors of annotations applied directly to this method
*/
+ @Override
public Collection<ClassDescriptor> getAnnotationDescriptors();
/**
@@ -176,6 +180,7 @@ public interface XMethod extends ClassMember, AnnotatedObject, ComparableMethod{
* @return AnnotationValue annotating the method, or null if method is not
* annotated with this kind of annotation
*/
+ @Override
public AnnotationValue getAnnotation(ClassDescriptor desc);
/**
@@ -183,6 +188,7 @@ public interface XMethod extends ClassMember, AnnotatedObject, ComparableMethod{
*
* @return Collection of all AnnotationValues applied directly to the method
*/
+ @Override
public Collection<AnnotationValue> getAnnotations();
/**
@@ -208,6 +214,8 @@ public interface XMethod extends ClassMember, AnnotatedObject, ComparableMethod{
*/
public void addAnnotation(AnnotationValue annotationValue);
+ boolean usesInvokeDynamic();
+
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/XMethodParameter.java b/src/java/edu/umd/cs/findbugs/ba/XMethodParameter.java
index 41b4b05..7f12e85 100644
--- a/src/java/edu/umd/cs/findbugs/ba/XMethodParameter.java
+++ b/src/java/edu/umd/cs/findbugs/ba/XMethodParameter.java
@@ -25,7 +25,7 @@ package edu.umd.cs.findbugs.ba;
public class XMethodParameter implements Comparable<XMethodParameter> {
/**
* Create a new Method parameter reference
- *
+ *
* @param m
* the method of which this is a parameter to
* @param p
@@ -50,8 +50,9 @@ public class XMethodParameter implements Comparable<XMethodParameter> {
@Override
public boolean equals(Object o) {
- if (!(o instanceof XMethodParameter))
+ if (!(o instanceof XMethodParameter)) {
return false;
+ }
XMethodParameter mp2 = (XMethodParameter) o;
return parameter == mp2.parameter && method.equals(mp2.method);
}
@@ -61,11 +62,13 @@ public class XMethodParameter implements Comparable<XMethodParameter> {
return method.hashCode() + parameter;
}
+ @Override
@SuppressWarnings("unchecked")
public int compareTo(XMethodParameter mp2) {
int result = method.compareTo(mp2.method);
- if (result != 0)
+ if (result != 0) {
return result;
+ }
return parameter - mp2.parameter;
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/ZipSourceFileDataSource.java b/src/java/edu/umd/cs/findbugs/ba/ZipSourceFileDataSource.java
index 99595fb..41b3238 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ZipSourceFileDataSource.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ZipSourceFileDataSource.java
@@ -29,11 +29,11 @@ import java.util.zip.ZipFile;
* A source file data source for source files residing in Zip or Jar archives.
*/
public class ZipSourceFileDataSource implements SourceFileDataSource {
- private ZipFile zipFile;
+ private final ZipFile zipFile;
- private String entryName;
+ private final String entryName;
- private ZipEntry zipEntry;
+ private final ZipEntry zipEntry;
public ZipSourceFileDataSource(ZipFile zipFile, String entryName) {
this.zipFile = zipFile;
@@ -41,12 +41,15 @@ public class ZipSourceFileDataSource implements SourceFileDataSource {
this.zipEntry = zipFile.getEntry(entryName);
}
+ @Override
public InputStream open() throws IOException {
- if (zipEntry == null)
+ if (zipEntry == null) {
throw new FileNotFoundException("No zip entry for " + entryName);
+ }
return zipFile.getInputStream(zipEntry);
}
+ @Override
public String getFullFileName() {
return entryName;
}
@@ -54,12 +57,13 @@ public class ZipSourceFileDataSource implements SourceFileDataSource {
/* (non-Javadoc)
* @see edu.umd.cs.findbugs.ba.SourceFileDataSource#getLastModified()
*/
+ @Override
public long getLastModified() {
long time = zipEntry.getTime();
- if (time < 0)
+ if (time < 0) {
return 0;
+ }
return time;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/Binding.java b/src/java/edu/umd/cs/findbugs/ba/bcp/Binding.java
index 027deeb..54bb739 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/Binding.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/Binding.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.ba.bcp;
/**
* A Binding binds a name to a Variable.
- *
+ *
* @author David Hovemeyer
* @see Variable
*/
@@ -32,15 +32,16 @@ public class Binding {
/**
* Constructor.
- *
+ *
* @param varName
* the name of the variable
* @param variable
* the variable
*/
public Binding(String varName, Variable variable) {
- if (variable == null)
+ if (variable == null) {
throw new IllegalArgumentException("No variable!");
+ }
this.varName = varName;
this.variable = variable;
}
@@ -69,4 +70,3 @@ public class Binding {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/BindingSet.java b/src/java/edu/umd/cs/findbugs/ba/bcp/BindingSet.java
index e97bf8a..1f2fb3f 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/BindingSet.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/BindingSet.java
@@ -23,7 +23,7 @@ package edu.umd.cs.findbugs.ba.bcp;
* A set of Bindings, which are definitions of variables occuring in a
* ByteCodePattern. BindingSets are immutable; to add a binding, a new cell is
* allocated. (Are we CONSING yet?)
- *
+ *
* @author David Hovemeyer
* @see Binding
*/
@@ -34,7 +34,7 @@ public class BindingSet {
/**
* Constructor; creates a new BindingSet as an extension of an existing one.
- *
+ *
* @param binding
* a variable binding
* @param parent
@@ -47,14 +47,15 @@ public class BindingSet {
/**
* Look for a Binding for given variable.
- *
+ *
* @param varName
* name of the variable
* @return the Binding, or null if no such Binding is present in the set
*/
public Binding lookup(String varName) {
- if (varName.equals(binding.getVarName()))
+ if (varName.equals(binding.getVarName())) {
return binding;
+ }
return parent != null ? parent.lookup(varName) : null;
}
@@ -64,8 +65,9 @@ public class BindingSet {
BindingSet cur = this;
buf.append('[');
while (cur != null) {
- if (cur != this)
+ if (cur != this) {
buf.append(", ");
+ }
buf.append(cur.binding.toString());
cur = cur.parent;
}
@@ -74,4 +76,3 @@ public class BindingSet {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/ByteCodePattern.java b/src/java/edu/umd/cs/findbugs/ba/bcp/ByteCodePattern.java
index cd9bbfb..84a0136 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/ByteCodePattern.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/ByteCodePattern.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.ba.bcp;
/**
* A ByteCodePattern is a pattern matching a sequence of bytecode instructions.
- *
+ *
* @author David Hovemeyer
* @see PatternElement
* @see PatternMatcher
@@ -37,14 +37,15 @@ public class ByteCodePattern {
/**
* Add a PatternElement to the end of the pattern.
- *
+ *
* @param element
* the PatternElement
* @return this object
*/
public ByteCodePattern add(PatternElement element) {
- if (first != null)
+ if (first != null) {
addInterElementWild();
+ }
addElement(element);
return this;
}
@@ -53,23 +54,24 @@ public class ByteCodePattern {
* Add a wildcard to match between 0 and given number of instructions. If
* there is already a wildcard at the end of the current pattern, resets its
* max value to that given.
- *
+ *
* @param numWild
* maximum number of instructions to be matched by the wildcard
*/
public ByteCodePattern addWild(int numWild) {
Wild wild = isLastWild();
- if (wild != null)
+ if (wild != null) {
wild.setMinAndMax(0, numWild);
- else
+ } else {
addElement(new Wild(numWild));
+ }
return this;
}
/**
* Set number of inter-element wildcards to create between explicit
* PatternElements. By default, no implicit wildcards are created.
- *
+ *
* @param numWild
* the number of wildcard instructions which may be matched
* between explicit PatternElements
@@ -102,8 +104,9 @@ public class ByteCodePattern {
}
private void addInterElementWild() {
- if (interElementWild > 0 && isLastWild() == null)
+ if (interElementWild > 0 && isLastWild() == null) {
addElement(new Wild(interElementWild));
+ }
}
private void addElement(PatternElement element) {
@@ -117,11 +120,11 @@ public class ByteCodePattern {
}
private Wild isLastWild() {
- if (last != null && last instanceof Wild)
+ if (last != null && last instanceof Wild) {
return (Wild) last;
- else
+ } else {
return null;
+ }
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/ByteCodePatternMatch.java b/src/java/edu/umd/cs/findbugs/ba/bcp/ByteCodePatternMatch.java
index be550b5..3458d8f 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/ByteCodePatternMatch.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/ByteCodePatternMatch.java
@@ -26,11 +26,11 @@ import java.util.LinkedList;
import org.apache.bcel.generic.InstructionHandle;
public class ByteCodePatternMatch {
- private BindingSet bindingSet;
+ private final BindingSet bindingSet;
- private PatternElementMatch lastElementMatch;
+ private final PatternElementMatch lastElementMatch;
- private LinkedList<PatternElementMatch> patternElementMatchList;
+ private final LinkedList<PatternElementMatch> patternElementMatchList;
@Override
public String toString() {
@@ -75,4 +75,3 @@ public class ByteCodePatternMatch {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/FieldAccess.java b/src/java/edu/umd/cs/findbugs/ba/bcp/FieldAccess.java
index 7292a17..7145ad9 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/FieldAccess.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/FieldAccess.java
@@ -30,19 +30,19 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
/**
* Base class for Load and Store PatternElements. Handles some of the grunt work
* of representing fields and extracting field values from the stack frame.
- *
+ *
* @author David Hovemeyer
* @see Load
* @see Store
*/
public abstract class FieldAccess extends SingleInstruction implements org.apache.bcel.Constants {
- private String fieldVarName;
+ private final String fieldVarName;
- private String valueVarName;
+ private final String valueVarName;
/**
* Constructor.
- *
+ *
* @param fieldVarName
* name of the variable to bind to the field
* @param valueVarName
@@ -57,7 +57,7 @@ public abstract class FieldAccess extends SingleInstruction implements org.apach
/**
* Check that the Variables determined for the field and the value
* loaded/stored are consistent with previous variable definitions.
- *
+ *
* @param field
* Variable representing the field
* @param value
@@ -71,18 +71,20 @@ public abstract class FieldAccess extends SingleInstruction implements org.apach
// Ensure that the field and value variables are consistent with
// previous definitions (if any)
bindingSet = addOrCheckDefinition(fieldVarName, field, bindingSet);
- if (bindingSet == null)
+ if (bindingSet == null) {
return null;
+ }
bindingSet = addOrCheckDefinition(valueVarName, value, bindingSet);
- if (bindingSet == null)
+ if (bindingSet == null) {
return null;
+ }
return new MatchResult(this, bindingSet);
}
/**
* Return whether the given FieldInstruction accesses a long or double
* field.
- *
+ *
* @param fieldIns
* the FieldInstruction
* @param cpg
@@ -97,7 +99,7 @@ public abstract class FieldAccess extends SingleInstruction implements org.apach
/**
* Get a Variable representing the stack value which will either be stored
* into or loaded from a field.
- *
+ *
* @param fieldIns
* the FieldInstruction accessing the field
* @param cpg
@@ -121,4 +123,3 @@ public abstract class FieldAccess extends SingleInstruction implements org.apach
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/FieldVariable.java b/src/java/edu/umd/cs/findbugs/ba/bcp/FieldVariable.java
index 6c9cc6f..87a7724 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/FieldVariable.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/FieldVariable.java
@@ -34,7 +34,7 @@ public class FieldVariable implements Variable {
/**
* Constructor for static fields.
- *
+ *
* @param className
* the class name
* @param fieldName
@@ -48,7 +48,7 @@ public class FieldVariable implements Variable {
/**
* Constructor for instance fields.
- *
+ *
* @param ref
* ValueNumber of the object reference
* @param className
@@ -93,12 +93,15 @@ public class FieldVariable implements Variable {
return fieldSig;
}
+ @Override
public boolean sameAs(Variable other) {
- if (!(other instanceof FieldVariable))
+ if (!(other instanceof FieldVariable)) {
return false;
+ }
FieldVariable otherField = (FieldVariable) other;
- if (isStatic() != otherField.isStatic())
+ if (isStatic() != otherField.isStatic()) {
return false;
+ }
return (ref == null || ref.equals(otherField.ref)) && className.equals(otherField.className)
&& fieldName.equals(otherField.fieldName) && fieldSig.equals(otherField.fieldSig);
}
@@ -113,4 +116,3 @@ public class FieldVariable implements Variable {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/IfNull.java b/src/java/edu/umd/cs/findbugs/ba/bcp/IfNull.java
index 5db8df2..4a383c1 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/IfNull.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/IfNull.java
@@ -42,8 +42,9 @@ public class IfNull extends OneVariableInstruction implements EdgeTypes {
// Instruction must be IFNULL or IFNONNULL.
Instruction ins = handle.getInstruction();
- if (!(ins instanceof IFNULL || ins instanceof IFNONNULL))
+ if (!(ins instanceof IFNULL || ins instanceof IFNONNULL)) {
return null;
+ }
// Ensure reference used is consistent with previous uses of
// same variable.
@@ -58,4 +59,3 @@ public class IfNull extends OneVariableInstruction implements EdgeTypes {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/Invoke.java b/src/java/edu/umd/cs/findbugs/ba/bcp/Invoke.java
index 2104a78..414443d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/Invoke.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/Invoke.java
@@ -70,7 +70,7 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
* The special mode <code>ORDINARY_METHOD</code> is equivalent to
* <code>INSTANCE|STATIC</code>. The special mode <code>ANY</code> is equivalent
* to <code>INSTANCE|STATIC|CONSTRUCTOR</code>.
- *
+ *
* @author David Hovemeyer
* @see PatternElement
*/
@@ -106,36 +106,39 @@ public class Invoke extends PatternElement {
}
private static class ExactStringMatcher implements StringMatcher {
- private String value;
+ private final String value;
public ExactStringMatcher(String value) {
this.value = value;
}
+ @Override
public boolean match(String s) {
return s.equals(value);
}
}
private static class RegexpStringMatcher implements StringMatcher {
- private Pattern pattern;
+ private final Pattern pattern;
public RegexpStringMatcher(String re) {
pattern = Pattern.compile(re);
}
+ @Override
public boolean match(String s) {
return pattern.matcher(s).matches();
}
}
private static class SubclassMatcher implements StringMatcher {
- private String className;
+ private final String className;
public SubclassMatcher(String className) {
this.className = className;
}
+ @Override
public boolean match(String s) {
try {
return Hierarchy.isSubtype(s, className);
@@ -156,7 +159,7 @@ public class Invoke extends PatternElement {
/**
* Constructor.
- *
+ *
* @param className
* the class name of the method; may be specified exactly, as a
* regexp, or as a subtype match
@@ -183,7 +186,7 @@ public class Invoke extends PatternElement {
private StringMatcher createMatcher(String s) {
return s.startsWith("/") ? (StringMatcher) new RegexpStringMatcher(s.substring(1))
- : (StringMatcher) new ExactStringMatcher(s);
+ : (StringMatcher) new ExactStringMatcher(s);
}
@Override
@@ -192,31 +195,37 @@ public class Invoke extends PatternElement {
// See if the instruction is an InvokeInstruction
Instruction ins = handle.getInstruction();
- if (!(ins instanceof InvokeInstruction))
+ if (!(ins instanceof InvokeInstruction)) {
return null;
+ }
InvokeInstruction inv = (InvokeInstruction) ins;
String methodName = inv.getMethodName(cpg);
boolean isStatic = inv.getOpcode() == Constants.INVOKESTATIC;
- boolean isCtor = methodName.equals("<init>");
+ boolean isCtor = "<init>".equals(methodName);
int actualMode = 0;
- if (isStatic)
+ if (isStatic) {
actualMode |= STATIC;
- if (isCtor)
+ }
+ if (isCtor) {
actualMode |= CONSTRUCTOR;
- if (!isStatic && !isCtor)
+ }
+ if (!isStatic && !isCtor) {
actualMode |= INSTANCE;
+ }
// Intersection of actual and desired modes must be nonempty.
- if ((actualMode & mode) == 0)
+ if ((actualMode & mode) == 0) {
return null;
+ }
// Check class name, method name, and method signature.
if (!methodNameMatcher.match(methodName) || !methodSigMatcher.match(inv.getSignature(cpg))
- || !classNameMatcher.match(inv.getClassName(cpg)))
+ || !classNameMatcher.match(inv.getClassName(cpg))) {
return null;
+ }
// It's a match!
return new MatchResult(this, bindingSet);
@@ -239,4 +248,3 @@ public class Invoke extends PatternElement {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/Load.java b/src/java/edu/umd/cs/findbugs/ba/bcp/Load.java
index 64cf354..70b12a0 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/Load.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/Load.java
@@ -33,7 +33,7 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
/**
* A PatternElement representing a load from a field. Variables represent the
* field and the result of the load.
- *
+ *
* @author David Hovemeyer
* @see PatternElement
*/
@@ -41,7 +41,7 @@ public class Load extends FieldAccess {
/**
* Constructor.
- *
+ *
* @param fieldVarName
* the name of the field variable
* @param resultVarName
@@ -67,8 +67,9 @@ public class Load extends FieldAccess {
} else if (ins instanceof GETSTATIC) {
fieldIns = (GETSTATIC) ins;
field = new FieldVariable(fieldIns.getClassName(cpg), fieldIns.getFieldName(cpg), fieldIns.getSignature(cpg));
- } else
+ } else {
return null;
+ }
Variable result = snarfFieldValue(fieldIns, cpg, after);
@@ -76,4 +77,3 @@ public class Load extends FieldAccess {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/LocalVariable.java b/src/java/edu/umd/cs/findbugs/ba/bcp/LocalVariable.java
index 472e52c..43ec453 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/LocalVariable.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/LocalVariable.java
@@ -28,9 +28,11 @@ public class LocalVariable implements Variable {
this.valueNumber = valueNumber;
}
+ @Override
public boolean sameAs(Variable other) {
- if (!(other instanceof LocalVariable))
+ if (!(other instanceof LocalVariable)) {
return false;
+ }
LocalVariable otherLocal = (LocalVariable) other;
return valueNumber.equals(otherLocal.valueNumber);
}
@@ -41,4 +43,3 @@ public class LocalVariable implements Variable {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/LongOrDoubleLocalVariable.java b/src/java/edu/umd/cs/findbugs/ba/bcp/LongOrDoubleLocalVariable.java
index 4657e49..ef3a58a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/LongOrDoubleLocalVariable.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/LongOrDoubleLocalVariable.java
@@ -22,19 +22,20 @@ package edu.umd.cs.findbugs.ba.bcp;
import edu.umd.cs.findbugs.ba.vna.ValueNumber;
public class LongOrDoubleLocalVariable implements Variable {
- private ValueNumber topValue, nextValue;
+ private final ValueNumber topValue, nextValue;
public LongOrDoubleLocalVariable(ValueNumber topValue, ValueNumber nextValue) {
this.topValue = topValue;
this.nextValue = nextValue;
}
+ @Override
public boolean sameAs(Variable other) {
- if (!(other instanceof LongOrDoubleLocalVariable))
+ if (!(other instanceof LongOrDoubleLocalVariable)) {
return false;
+ }
LongOrDoubleLocalVariable otherLongOrDouble = (LongOrDoubleLocalVariable) other;
return topValue.equals(otherLongOrDouble.topValue) && nextValue.equals(otherLongOrDouble.nextValue);
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/MatchAny.java b/src/java/edu/umd/cs/findbugs/ba/bcp/MatchAny.java
index bbed615..cbb6202 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/MatchAny.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/MatchAny.java
@@ -36,16 +36,16 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
* <p>
* Note that the minOccur() and maxOccur() counts of the child PatternElements
* are ignored. A MatchAny element always matches exactly one instruction.
- *
+ *
* @author David Hovemeyer
* @see PatternElement
*/
public class MatchAny extends PatternElement {
- private PatternElement[] childList;
+ private final PatternElement[] childList;
/**
* Constructor.
- *
+ *
* @param childList
* list of child PatternElements
*/
@@ -67,8 +67,9 @@ public class MatchAny extends PatternElement {
// Just forward this on to all children,
// since it is the children that the PatternMatcher will ask
// about edges.
- for (PatternElement aChildList : childList)
+ for (PatternElement aChildList : childList) {
aChildList.setAllowTrailingEdges(allowTrailingEdges);
+ }
return this;
}
@@ -79,8 +80,9 @@ public class MatchAny extends PatternElement {
for (PatternElement child : childList) {
MatchResult matchResult = child.match(handle, cpg, before, after, bindingSet);
- if (matchResult != null)
+ if (matchResult != null) {
return matchResult;
+ }
}
return null;
@@ -105,4 +107,3 @@ public class MatchAny extends PatternElement {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/MatchResult.java b/src/java/edu/umd/cs/findbugs/ba/bcp/MatchResult.java
index e610b62..4529808 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/MatchResult.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/MatchResult.java
@@ -25,19 +25,19 @@ package edu.umd.cs.findbugs.ba.bcp;
* reason we need this class is because some kinds of PatternElements, such as
* MatchAny, may use it to indicate that a child PatternElement was the one that
* actually matched the instruction.
- *
+ *
* @author David Hovemeyer
* @see PatternElement
* @see BindingSet
*/
public class MatchResult {
- private PatternElement patternElement;
+ private final PatternElement patternElement;
- private BindingSet bindingSet;
+ private final BindingSet bindingSet;
/**
* Constructor.
- *
+ *
* @param patternElement
* the PatternElement that matched the instruction
* @param bindingSet
@@ -64,4 +64,3 @@ public class MatchResult {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/Monitorenter.java b/src/java/edu/umd/cs/findbugs/ba/bcp/Monitorenter.java
index 29fd352..d8b098a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/Monitorenter.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/Monitorenter.java
@@ -29,13 +29,13 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
/**
* A PatternElement for matching a MONITORENTER instruction.
- *
+ *
* @author DavidHovemeyer
*/
public class Monitorenter extends OneVariableInstruction {
/**
* Constructor.
- *
+ *
* @param varName
* name of the variable representing the reference to the object
* being locked
@@ -50,8 +50,9 @@ public class Monitorenter extends OneVariableInstruction {
// Instruction must be MONITORENTER.
Instruction ins = handle.getInstruction();
- if (!(ins instanceof MONITORENTER))
+ if (!(ins instanceof MONITORENTER)) {
return null;
+ }
// Ensure the object being locked matches any previous
// instructions which bound our variable name to a value.
@@ -60,4 +61,3 @@ public class Monitorenter extends OneVariableInstruction {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/New.java b/src/java/edu/umd/cs/findbugs/ba/bcp/New.java
index 99d0062..c35ae83 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/New.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/New.java
@@ -30,14 +30,14 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
/**
* A PatternElement which matches NEW instructions and binds the result to a
* variable.
- *
+ *
* @author David Hovemeyer
* @see PatternElement
*/
public class New extends OneVariableInstruction {
/**
* Constructor.
- *
+ *
* @param resultVarName
* name of the result of the NEW instruction
*/
@@ -50,12 +50,12 @@ public class New extends OneVariableInstruction {
BindingSet bindingSet) throws DataflowAnalysisException {
Instruction ins = handle.getInstruction();
- if (!(ins instanceof NEW))
+ if (!(ins instanceof NEW)) {
return null;
+ }
LocalVariable result = new LocalVariable(after.getTopValue());
return addOrCheckDefinition(result, bindingSet);
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/OneVariableInstruction.java b/src/java/edu/umd/cs/findbugs/ba/bcp/OneVariableInstruction.java
index cfbb6c0..c8f79fb 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/OneVariableInstruction.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/OneVariableInstruction.java
@@ -22,15 +22,15 @@ package edu.umd.cs.findbugs.ba.bcp;
/**
* Abstract PatternElement subclass for matching single instructions which have
* a single Variable.
- *
+ *
* @see PatternElement
*/
public abstract class OneVariableInstruction extends SingleInstruction {
- private String varName;
+ private final String varName;
/**
* Constructor.
- *
+ *
* @param varName
* the name of the Variable used in this instruction
*/
@@ -41,7 +41,7 @@ public abstract class OneVariableInstruction extends SingleInstruction {
/**
* Add a variable definition to the given BindingSet, or if there is an
* existing definition, make sure it is consistent with the new definition.
- *
+ *
* @param variable
* the Variable which should be added or checked for consistency
* @param bindingSet
@@ -57,4 +57,3 @@ public abstract class OneVariableInstruction extends SingleInstruction {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/Opcode.java b/src/java/edu/umd/cs/findbugs/ba/bcp/Opcode.java
index 56c0e5b..7378038 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/Opcode.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/Opcode.java
@@ -28,16 +28,16 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
/**
* PatternElement to match instructions with a particular opcode.
- *
+ *
* @author David Hovemeyer
* @see PatternElement
*/
public class Opcode extends PatternElement {
- private int opcode;
+ private final int opcode;
/**
* Constructor.
- *
+ *
* @param opcode
* the opcode to match
*/
@@ -49,10 +49,11 @@ public class Opcode extends PatternElement {
public MatchResult match(InstructionHandle handle, ConstantPoolGen cpg, ValueNumberFrame before, ValueNumberFrame after,
BindingSet bindingSet) throws DataflowAnalysisException {
- if (handle.getInstruction().getOpcode() == opcode)
+ if (handle.getInstruction().getOpcode() == opcode) {
return new MatchResult(this, bindingSet);
- else
+ } else {
return null;
+ }
}
@@ -72,4 +73,3 @@ public class Opcode extends PatternElement {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/PatternElement.java b/src/java/edu/umd/cs/findbugs/ba/bcp/PatternElement.java
index e0eac86..c9c99f2 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/PatternElement.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/PatternElement.java
@@ -62,7 +62,7 @@ public abstract class PatternElement {
/**
* Set a label for this PatternElement.
- *
+ *
* @param label
* the label
* @return this object
@@ -74,7 +74,7 @@ public abstract class PatternElement {
/**
* Get the label of this PatternElement.
- *
+ *
* @return the label, or null if the PatternElement is not labeled
*/
public String getLabel() {
@@ -110,7 +110,7 @@ public abstract class PatternElement {
* matched. By default, trailing edges may be matched. When this value is
* set to false, it ensures that the successor instruction must be in the
* same basic block.
- *
+ *
* @param allowTrailingEdges
* true if trailing edges may be matched, false if trailing edges
* will never be matched
@@ -129,7 +129,7 @@ public abstract class PatternElement {
/**
* Look up a variable definition in given BindingSet.
- *
+ *
* @param varName
* the name of the variable
* @param bindingSet
@@ -137,8 +137,9 @@ public abstract class PatternElement {
* @return the Variable, or null if no Variable is bound to the name
*/
public static Variable lookup(String varName, BindingSet bindingSet) {
- if (bindingSet == null)
+ if (bindingSet == null) {
return null;
+ }
Binding binding = bindingSet.lookup(varName);
return (binding != null) ? binding.getVariable() : null;
}
@@ -146,7 +147,7 @@ public abstract class PatternElement {
/**
* Return whether or not this element matches the given instruction with the
* given Bindings in effect.
- *
+ *
* @param handle
* the instruction
* @param cpg
@@ -169,7 +170,7 @@ public abstract class PatternElement {
/**
* Return whether or not it is acceptable to take the given branch.
- *
+ *
* @param edge
* the Edge representing the branch
* @param source
@@ -193,7 +194,7 @@ public abstract class PatternElement {
/**
* Add a variable definition to the given BindingSet, or if there is an
* existing definition, make sure it is consistent with the new definition.
- *
+ *
* @param varName
* the name of the variable
* @param variable
@@ -210,8 +211,9 @@ public abstract class PatternElement {
bindingSet = new BindingSet(new Binding(varName, variable), bindingSet);
} else {
if (!existingVariable.sameAs(variable)) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\tConflicting variable " + varName + ": " + variable + " != " + existingVariable);
+ }
return null;
}
}
@@ -231,4 +233,3 @@ public abstract class PatternElement {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/PatternElementMatch.java b/src/java/edu/umd/cs/findbugs/ba/bcp/PatternElementMatch.java
index 8d07c13..9d43935 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/PatternElementMatch.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/PatternElementMatch.java
@@ -42,7 +42,7 @@ public class PatternElementMatch {
/**
* Constructor.
- *
+ *
* @param patternElement
* the PatternElement being matched
* @param matchedInstruction
@@ -118,8 +118,9 @@ public class PatternElementMatch {
PatternElementMatch cur = this, result = null;
while (cur != null) {
String elementLabel = cur.patternElement.getLabel();
- if (elementLabel != null && elementLabel.equals(label))
+ if (elementLabel != null && elementLabel.equals(label)) {
result = cur;
+ }
cur = cur.prev;
}
return result;
@@ -132,8 +133,9 @@ public class PatternElementMatch {
PatternElementMatch cur = this;
while (cur != null) {
String elementLabel = cur.patternElement.getLabel();
- if (elementLabel != null && elementLabel.equals(label))
+ if (elementLabel != null && elementLabel.equals(label)) {
return cur;
+ }
cur = cur.prev;
}
return null;
@@ -167,15 +169,17 @@ public class PatternElementMatch {
@Override
public boolean equals(Object o) {
- if (!(o instanceof PatternElementMatch))
+ if (!(o instanceof PatternElementMatch)) {
return false;
+ }
PatternElementMatch lhs = this;
PatternElementMatch rhs = (PatternElementMatch) o;
while (lhs != null && rhs != null) {
if (lhs.patternElement != rhs.patternElement || lhs.matchedInstruction != rhs.matchedInstruction
- || lhs.matchCount != rhs.matchCount)
+ || lhs.matchCount != rhs.matchCount) {
return false;
+ }
lhs = lhs.prev;
rhs = rhs.prev;
@@ -185,4 +189,3 @@ public class PatternElementMatch {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/PatternMatcher.java b/src/java/edu/umd/cs/findbugs/ba/bcp/PatternMatcher.java
index 071afe1..85944ea 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/PatternMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/PatternMatcher.java
@@ -51,7 +51,7 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
* <p/>
* <p>
* This code is a hack and should probably be rewritten.
- *
+ *
* @author David Hovemeyer
* @see ByteCodePattern
*/
@@ -60,27 +60,27 @@ public class PatternMatcher implements DFSEdgeTypes {
private static final boolean SHOW_WILD = SystemProperties.getBoolean("bcp.showWild");
- private ByteCodePattern pattern;
+ private final ByteCodePattern pattern;
- private CFG cfg;
+ private final CFG cfg;
- private ConstantPoolGen cpg;
+ private final ConstantPoolGen cpg;
- private DepthFirstSearch dfs;
+ private final DepthFirstSearch dfs;
- private ValueNumberDataflow vnaDataflow;
+ private final ValueNumberDataflow vnaDataflow;
- private DominatorsAnalysis domAnalysis;
+ private final DominatorsAnalysis domAnalysis;
- private LinkedList<BasicBlock> workList;
+ private final LinkedList<BasicBlock> workList;
- private IdentityHashMap<BasicBlock, BasicBlock> visitedBlockMap;
+ private final IdentityHashMap<BasicBlock, BasicBlock> visitedBlockMap;
- private LinkedList<ByteCodePatternMatch> resultList;
+ private final LinkedList<ByteCodePatternMatch> resultList;
/**
* Constructor.
- *
+ *
* @param pattern
* the ByteCodePattern to look for examples of
* @param classContext
@@ -89,7 +89,7 @@ public class PatternMatcher implements DFSEdgeTypes {
* the Method to analyze
*/
public PatternMatcher(ByteCodePattern pattern, ClassContext classContext, Method method) throws CFGBuilderException,
- DataflowAnalysisException {
+ DataflowAnalysisException {
this.pattern = pattern;
this.cfg = classContext.getCFG(method);
this.cpg = classContext.getConstantPoolGen();
@@ -103,7 +103,7 @@ public class PatternMatcher implements DFSEdgeTypes {
/**
* Search for examples of the ByteCodePattern.
- *
+ *
* @return this object
* @throws DataflowAnalysisException
* if the ValueNumberAnalysis did not produce useful values for
@@ -128,8 +128,9 @@ public class PatternMatcher implements DFSEdgeTypes {
Iterator<BasicBlock> succIterator = cfg.successorIterator(basicBlock);
while (succIterator.hasNext()) {
BasicBlock succ = succIterator.next();
- if (visitedBlockMap.get(succ) == null)
+ if (visitedBlockMap.get(succ) == null) {
workList.addLast(succ);
+ }
}
}
@@ -146,7 +147,7 @@ public class PatternMatcher implements DFSEdgeTypes {
/**
* Attempt to begin a match.
- *
+ *
* @param basicBlock
* the basic block
* @param instructionIterator
@@ -166,11 +167,11 @@ public class PatternMatcher implements DFSEdgeTypes {
* convenient methods to implement the various steps of the algorithm.
*/
private class State {
- private BasicBlock basicBlock;
+ private final BasicBlock basicBlock;
- private BasicBlock.InstructionIterator instructionIterator;
+ private final BasicBlock.InstructionIterator instructionIterator;
- private PatternElement patternElement;
+ private final PatternElement patternElement;
private int matchCount;
@@ -191,7 +192,7 @@ public class PatternMatcher implements DFSEdgeTypes {
/**
* Constructor. Builds the start state.
- *
+ *
* @param basicBlock
* the initial basic block
* @param instructionIterator
@@ -261,8 +262,9 @@ public class PatternMatcher implements DFSEdgeTypes {
* Get a ByteCodePatternMatch representing the complete match.
*/
public ByteCodePatternMatch getResult() {
- if (!isComplete())
+ if (!isComplete()) {
throw new IllegalStateException("match not complete!");
+ }
return new ByteCodePatternMatch(bindingSet, currentMatch);
}
@@ -272,10 +274,11 @@ public class PatternMatcher implements DFSEdgeTypes {
* current element is not complete.
*/
public State advanceToNextElement() {
- if (!canFork || matchCount < patternElement.minOccur())
+ if (!canFork || matchCount < patternElement.minOccur()) {
// Current element is not complete, or we already
// forked at this point
return null;
+ }
// Create state to advance to matching next pattern element
// at current basic block and instruction.
@@ -309,8 +312,9 @@ public class PatternMatcher implements DFSEdgeTypes {
* Returns MatchResult if match succeeds, null otherwise.
*/
public MatchResult matchNextInBasicBlock() throws DataflowAnalysisException {
- if (!moreInstructionsInBasicBlock())
+ if (!moreInstructionsInBasicBlock()) {
throw new IllegalStateException("At end of BB!");
+ }
// Move to location of next instruction to be matched
Location location = new Location(instructionIterator.next(), basicBlock);
@@ -329,15 +333,16 @@ public class PatternMatcher implements DFSEdgeTypes {
* Get most recently matched instruction.
*/
public InstructionHandle getLastMatchedInstruction() {
- if (currentMatch == null)
+ if (currentMatch == null) {
throw new IllegalStateException("no current match!");
+ }
return currentMatch.getMatchedInstructionInstructionHandle();
}
/**
* Return a new State for continuing the overall pattern match in a
* successor basic block.
- *
+ *
* @param edge
* the Edge leading to the successor basic block
* @param matchResult
@@ -350,8 +355,9 @@ public class PatternMatcher implements DFSEdgeTypes {
// This allows PatternElements to select particular control edges;
// for example, only continue the pattern on the true branch
// of an "if" comparison.
- if (matchResult != null && !matchResult.getPatternElement().acceptBranch(edge, getLastMatchedInstruction()))
+ if (matchResult != null && !matchResult.getPatternElement().acceptBranch(edge, getLastMatchedInstruction())) {
return null;
+ }
return new State(this, edge.getTarget(), edge.getTarget().instructionIterator(), patternElement, matchCount,
currentMatch, bindingSet, canFork);
@@ -370,8 +376,9 @@ public class PatternMatcher implements DFSEdgeTypes {
* continue the match.
*/
public Iterable<State> dominatedInstructionStateIterable() throws DataflowAnalysisException {
- if (!lookForDominatedInstruction())
+ if (!lookForDominatedInstruction()) {
throw new IllegalStateException();
+ }
LinkedList<State> stateList = new LinkedList<State>();
State dup = this.duplicate();
@@ -400,8 +407,9 @@ public class PatternMatcher implements DFSEdgeTypes {
stateList.add(dup);
dup = this.duplicate();
}
- } else if (next.equals(domInstruction))
+ } else if (next.equals(domInstruction)) {
includeInstructions = true;
+ }
}
}
}
@@ -423,8 +431,9 @@ public class PatternMatcher implements DFSEdgeTypes {
+ location.getHandle() + " " + (bindingSet != null ? bindingSet.toString() : "[]") + "...");
}
MatchResult matchResult = patternElement.match(location.getHandle(), cpg, before, after, bindingSet);
- if (debug)
+ if (debug) {
debug("\t" + ((matchResult != null) ? " ==> MATCH" : " ==> NOT A MATCH"));
+ }
if (matchResult != null) {
// Successful match!
// Update state to reflect that the match has occurred.
@@ -439,8 +448,9 @@ public class PatternMatcher implements DFSEdgeTypes {
}
private void debug(String s) {
- if (!DEBUG)
+ if (!DEBUG) {
throw new IllegalStateException("Only call if DEBUG is true");
+ }
System.out.print(" ".substring(0, depth));
System.out.println(s);
}
@@ -461,8 +471,9 @@ public class PatternMatcher implements DFSEdgeTypes {
// Have we reached the end of the pattern?
if (state.isComplete()) {
// This is a complete match.
- if (DEBUG)
+ if (DEBUG) {
debug("FINISHED A MATCH!");
+ }
resultList.add(state.getResult());
return;
}
@@ -483,8 +494,9 @@ public class PatternMatcher implements DFSEdgeTypes {
// If we've reached the maximum number of occurrences for this
// pattern element, then we can't continue.
- if (!state.currentElementCanContinue())
+ if (!state.currentElementCanContinue()) {
return;
+ }
MatchResult matchResult = null;
@@ -493,8 +505,9 @@ public class PatternMatcher implements DFSEdgeTypes {
if (state.lookForDominatedInstruction()) {
Iterable<State> dominatedInstructions = state.dominatedInstructionStateIterable();
for (State s : dominatedInstructions) {
- if (DEBUG)
+ if (DEBUG) {
debug("trying " + s);
+ }
work(s);
}
return;
@@ -504,8 +517,9 @@ public class PatternMatcher implements DFSEdgeTypes {
if (state.moreInstructionsInBasicBlock()) {
// Try to match it.
matchResult = state.matchNextInBasicBlock();
- if (matchResult == null)
+ if (matchResult == null) {
return;
+ }
}
// Continue the match at each successor instruction,
@@ -521,15 +535,17 @@ public class PatternMatcher implements DFSEdgeTypes {
BitSet visitedSuccessorSet = new BitSet();
while (i.hasNext()) {
Edge edge = i.next();
- if (dfs.getDFSEdgeType(edge) == BACK_EDGE)
+ if (dfs.getDFSEdgeType(edge) == BACK_EDGE) {
continue;
+ }
BasicBlock destBlock = edge.getTarget();
int destId = destBlock.getLabel();
// CFGs can have duplicate edges
- if (visitedSuccessorSet.get(destId))
+ if (visitedSuccessorSet.get(destId)) {
continue;
+ }
visitedSuccessorSet.set(destId, true);
// See if we can continue matching in the successor basic
@@ -547,4 +563,3 @@ public class PatternMatcher implements DFSEdgeTypes {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/SingleInstruction.java b/src/java/edu/umd/cs/findbugs/ba/bcp/SingleInstruction.java
index 95301aa..d7bea1c 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/SingleInstruction.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/SingleInstruction.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.ba.Edge;
* An abstract PatternElement subclass for pattern elements which must match
* exactly one instruction and accept any kind of branch. (Subclasses may
* override acceptBranch() to implement more selective handling of branches.)
- *
+ *
* @author David Hovemeyer
* @see PatternElement
*/
@@ -49,4 +49,3 @@ public abstract class SingleInstruction extends PatternElement {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/Store.java b/src/java/edu/umd/cs/findbugs/ba/bcp/Store.java
index 8ebdd60..7d4e7a3 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/Store.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/Store.java
@@ -33,14 +33,14 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
/**
* A PatternElement representing a store to a field. Variables represent the
* field and the value stored.
- *
+ *
* @author David Hovemeyer
* @see PatternElement
*/
public class Store extends FieldAccess {
/**
* Constructor.
- *
+ *
* @param fieldVarName
* the name of the field variable
* @param valueVarName
@@ -67,8 +67,9 @@ public class Store extends FieldAccess {
} else if (ins instanceof PUTSTATIC) {
fieldIns = (PUTSTATIC) ins;
field = new FieldVariable(fieldIns.getClassName(cpg), fieldIns.getFieldName(cpg), fieldIns.getSignature(cpg));
- } else
+ } else {
return null;
+ }
Variable value = snarfFieldValue(fieldIns, cpg, before);
@@ -76,4 +77,3 @@ public class Store extends FieldAccess {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/Variable.java b/src/java/edu/umd/cs/findbugs/ba/bcp/Variable.java
index 73bfe7c..6c3b040 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/Variable.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/Variable.java
@@ -31,4 +31,3 @@ public interface Variable {
public boolean sameAs(Variable other);
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/bcp/Wild.java b/src/java/edu/umd/cs/findbugs/ba/bcp/Wild.java
index 2b7d297..cecf25a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/bcp/Wild.java
+++ b/src/java/edu/umd/cs/findbugs/ba/bcp/Wild.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
/**
* A wildcard PatternElement, which matches any kind of instruction
* indiscriminately.
- *
+ *
* @author David Hovemeyer
* @see PatternElement
*/
@@ -48,7 +48,7 @@ public class Wild extends PatternElement {
/**
* Constructor. Matches any number of instructions from 0 to the maximum
* specified.
- *
+ *
* @param max
* the maximum number of instructions the wildcard may match
*/
@@ -59,7 +59,7 @@ public class Wild extends PatternElement {
/**
* Constructor.
- *
+ *
* @param min
* minimum number of times the wildcard must match
* @param max
@@ -72,7 +72,7 @@ public class Wild extends PatternElement {
/**
* Set min and max values.
- *
+ *
* @param min
* minimum number of times the wildcard must match
* @param max
@@ -105,4 +105,3 @@ public class Wild extends PatternElement {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/ca/Call.java b/src/java/edu/umd/cs/findbugs/ba/ca/Call.java
index c2b68c2..e32d645 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ca/Call.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ca/Call.java
@@ -45,8 +45,9 @@ public class Call {
@Override
public boolean equals(Object obj) {
- if (obj == null || obj.getClass() != this.getClass())
+ if (obj == null || obj.getClass() != this.getClass()) {
return false;
+ }
Call other = (Call) obj;
return this.className.equals(other.className) && this.methodName.equals(other.methodName)
&& this.methodSig.equals(other.methodSig);
diff --git a/src/java/edu/umd/cs/findbugs/ba/ca/CallList.java b/src/java/edu/umd/cs/findbugs/ba/ca/CallList.java
index 97d141a..548d7ff 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ca/CallList.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ca/CallList.java
@@ -24,7 +24,7 @@ import java.util.Iterator;
public class CallList {
private boolean isTop, isBottom;
- private ArrayList<Call> callList;
+ private final ArrayList<Call> callList;
public CallList() {
this.callList = new ArrayList<Call>();
@@ -95,8 +95,9 @@ public class CallList {
// Result is the common prefix
int len = Math.min(a.size(), b.size());
for (int i = 0; i < len; ++i) {
- if (!a.get(i).equals(b.get(i)))
+ if (!a.get(i).equals(b.get(i))) {
break;
+ }
result.add(a.get(i));
}
}
@@ -105,8 +106,9 @@ public class CallList {
@Override
public boolean equals(Object obj) {
- if (obj == null || obj.getClass() != this.getClass())
+ if (obj == null || obj.getClass() != this.getClass()) {
return false;
+ }
CallList other = (CallList) obj;
return this.callList.equals(other.callList);
}
@@ -120,8 +122,9 @@ public class CallList {
public String toString() {
StringBuilder buf = new StringBuilder();
for (Call call : callList) {
- if (buf.length() > 0)
+ if (buf.length() > 0) {
buf.append(',');
+ }
buf.append(call.getMethodName());
}
return buf.toString();
diff --git a/src/java/edu/umd/cs/findbugs/ba/ca/CallListAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/ca/CallListAnalysis.java
index d8b961c..39a228a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ca/CallListAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ca/CallListAnalysis.java
@@ -38,10 +38,10 @@ import edu.umd.cs.findbugs.ba.Location;
import edu.umd.cs.findbugs.ba.ReversePostOrder;
public class CallListAnalysis extends AbstractDataflowAnalysis<CallList> {
- private DepthFirstSearch dfs;
+ private final DepthFirstSearch dfs;
// private ConstantPoolGen cpg;
- private Map<InstructionHandle, Call> callMap;
+ private final Map<InstructionHandle, Call> callMap;
public CallListAnalysis(CFG cfg, DepthFirstSearch dfs, ConstantPoolGen cpg) {
this.dfs = dfs;
@@ -66,6 +66,7 @@ public class CallListAnalysis extends AbstractDataflowAnalysis<CallList> {
return callMap;
}
+ @Override
public void initEntryFact(CallList fact) {
fact.clear();
}
@@ -74,35 +75,43 @@ public class CallListAnalysis extends AbstractDataflowAnalysis<CallList> {
// fact.setTop();
// }
+ @Override
public boolean isForwards() {
return true;
}
+ @Override
public BlockOrder getBlockOrder(CFG cfg) {
return new ReversePostOrder(cfg, dfs);
}
+ @Override
public void makeFactTop(CallList fact) {
fact.setTop();
}
+ @Override
public boolean isTop(CallList fact) {
return fact.isTop();
}
+ @Override
public CallList createFact() {
return new CallList();
}
+ @Override
public boolean same(CallList a, CallList b) {
return a.equals(b);
}
+ @Override
public void meetInto(CallList start, Edge edge, CallList result) throws DataflowAnalysisException {
CallList merge = CallList.merge(start, result);
result.copyFrom(merge);
}
+ @Override
public void copy(CallList source, CallList dest) {
dest.copyFrom(source);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/ca/CallListDataflow.java b/src/java/edu/umd/cs/findbugs/ba/ca/CallListDataflow.java
index 1454a1d..1454030 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ca/CallListDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ca/CallListDataflow.java
@@ -23,7 +23,7 @@ import edu.umd.cs.findbugs.ba.Dataflow;
/**
* Dataflow class for CallListAnalysis.
- *
+ *
* @author David Hovemeyer
*/
public class CallListDataflow extends Dataflow<CallList, CallListAnalysis> {
diff --git a/src/java/edu/umd/cs/findbugs/ba/ch/ClassVertex.java b/src/java/edu/umd/cs/findbugs/ba/ch/ClassVertex.java
index da0a2f6..d62fe2a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ch/ClassVertex.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ch/ClassVertex.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.graph.AbstractVertex;
/**
* Vertex class - represents a class or interface in the InheritanceGraph. Edges
* connect subtypes to supertypes.
- *
+ *
* @author David Hovemeyer
*/
class ClassVertex extends AbstractVertex<InheritanceEdge, ClassVertex> {
@@ -55,8 +55,9 @@ class ClassVertex extends AbstractVertex<InheritanceEdge, ClassVertex> {
@Override
public boolean equals(Object o) {
- if (!(o instanceof ClassVertex))
+ if (!(o instanceof ClassVertex)) {
return false;
+ }
return classDescriptor.equals(((ClassVertex) o).classDescriptor);
}
@@ -85,7 +86,7 @@ class ClassVertex extends AbstractVertex<InheritanceEdge, ClassVertex> {
/**
* Factory method for resolved ClassVertex objects.
- *
+ *
* @param classDescriptor
* ClassDescriptor naming the class or interface
* @param xclass
@@ -98,7 +99,7 @@ class ClassVertex extends AbstractVertex<InheritanceEdge, ClassVertex> {
/**
* Factory method for ClassVertex objects representing missing classes.
- *
+ *
* @param classDescriptor
* ClassDescriptor naming the missing class or interface
* @param isInterface
@@ -178,7 +179,7 @@ class ClassVertex extends AbstractVertex<InheritanceEdge, ClassVertex> {
/**
* Set the ClassVertex representing the direct superclass.
- *
+ *
* @param target
* ClassVertex representing the direct superclass.
*/
diff --git a/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceEdge.java b/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceEdge.java
index 2ab3bd1..c2c9492 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceEdge.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceEdge.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.graph.AbstractEdge;
/**
* An edge in the InheritanceGraph. Source vertex is the subtype, target vertex
* is a direct supertype.
- *
+ *
* @author David Hovemeyer
*/
public class InheritanceEdge extends AbstractEdge<InheritanceEdge, ClassVertex> {
diff --git a/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraph.java b/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraph.java
index 698ea6f..c6b3eaf 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraph.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraph.java
@@ -23,14 +23,14 @@ import edu.umd.cs.findbugs.graph.AbstractGraph;
/**
* Graph of inheritance relationships.
- *
+ *
* @author David Hovemeyer
*/
public class InheritanceGraph extends AbstractGraph<InheritanceEdge, ClassVertex> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.graph.AbstractGraph#allocateEdge(edu.umd.cs.findbugs
* .graph.AbstractVertex, edu.umd.cs.findbugs.graph.AbstractVertex)
@@ -42,7 +42,7 @@ public class InheritanceGraph extends AbstractGraph<InheritanceEdge, ClassVertex
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.graph.AbstractGraph#createEdge(edu.umd.cs.findbugs
* .graph.AbstractVertex, edu.umd.cs.findbugs.graph.AbstractVertex)
diff --git a/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraphVisitor.java b/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraphVisitor.java
index 91e6c37..f06ed03 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraphVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraphVisitor.java
@@ -26,14 +26,14 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
/**
* Visitor interface for traversals of the inheritance graph.
- *
+ *
* @see Subtypes2
* @author David Hovemeyer
*/
public interface InheritanceGraphVisitor {
/**
* Visit a class vertex in the inheritance graph.
- *
+ *
* @param classDescriptor
* ClassDescriptor of the class vertex
* @param xclass
@@ -45,7 +45,7 @@ public interface InheritanceGraphVisitor {
/**
* Visit an inheritance edge in the inheritance graph.
- *
+ *
* @param sourceDesc
* ClassDescriptor of the source class (subtype)
* @param source
diff --git a/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraph.java b/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraph.java
index ee56834..5bf0192 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraph.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraph.java
@@ -27,13 +27,13 @@ import edu.umd.cs.findbugs.graph.AbstractGraph;
/**
* Class representing the interprocedural call graph. Vertices represent
* methods. Edges represent method calls.
- *
+ *
* @author David Hovemeyer
*/
@Deprecated
public class InterproceduralCallGraph extends AbstractGraph<InterproceduralCallGraphEdge, InterproceduralCallGraphVertex> {
- private Map<MethodDescriptor, InterproceduralCallGraphVertex> methodDescToVertexMap;
+ private final Map<MethodDescriptor, InterproceduralCallGraphVertex> methodDescToVertexMap;
/**
* Constructor.
@@ -44,7 +44,7 @@ public class InterproceduralCallGraph extends AbstractGraph<InterproceduralCallG
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.graph.AbstractGraph#addVertex(edu.umd.cs.findbugs
* .graph.AbstractVertex)
@@ -57,7 +57,7 @@ public class InterproceduralCallGraph extends AbstractGraph<InterproceduralCallG
/**
* Look up vertex corresponding to given method.
- *
+ *
* @param methodDesc
* a MethodDescriptor specifying a method
* @return the InterproceduralCallGraphVertex representing that method, or
@@ -69,7 +69,7 @@ public class InterproceduralCallGraph extends AbstractGraph<InterproceduralCallG
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.graph.AbstractGraph#allocateEdge(edu.umd.cs.findbugs
* .graph.AbstractVertex, edu.umd.cs.findbugs.graph.AbstractVertex)
diff --git a/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraphEdge.java b/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraphEdge.java
index 9ef4417..1167368 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraphEdge.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraphEdge.java
@@ -24,14 +24,14 @@ import edu.umd.cs.findbugs.graph.AbstractEdge;
/**
* A class representing an edge in the interprocedural call graph; i.e., a call
* from one method to another.
- *
+ *
* @author David Hovemeyer
*/
public class InterproceduralCallGraphEdge extends AbstractEdge<InterproceduralCallGraphEdge, InterproceduralCallGraphVertex> {
/**
* Constructor.
- *
+ *
* @param source
* source vertex (caller)
* @param target
diff --git a/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraphVertex.java b/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraphVertex.java
index c8c0ce0..a327beb 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraphVertex.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ch/InterproceduralCallGraphVertex.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.graph.AbstractVertex;
/**
* Class representing a vertex in the interprocedural call graph; i.e., a
* method.
- *
+ *
* @author David Hovemeyer
*/
public class InterproceduralCallGraphVertex extends AbstractVertex<InterproceduralCallGraphEdge, InterproceduralCallGraphVertex> {
diff --git a/src/java/edu/umd/cs/findbugs/ba/ch/OverriddenMethodsVisitor.java b/src/java/edu/umd/cs/findbugs/ba/ch/OverriddenMethodsVisitor.java
index 9570caf..0c7b27e 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ch/OverriddenMethodsVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ch/OverriddenMethodsVisitor.java
@@ -29,15 +29,15 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
* the
* {@link Subtypes2#traverseSupertypes(ClassDescriptor, InheritanceGraphVisitor)}
* method.
- *
+ *
* @author David Hovemeyer
*/
-public abstract class OverriddenMethodsVisitor implements InheritanceGraphVisitor {
- private XMethod xmethod;
+public abstract class OverriddenMethodsVisitor implements SupertypeTraversalVisitor {
+ private final XMethod xmethod;
/**
* Constructor.
- *
+ *
* @param xmethod
* a derived method
*/
@@ -55,26 +55,23 @@ public abstract class OverriddenMethodsVisitor implements InheritanceGraphVisito
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.ch.InheritanceGraphVisitor#visitClass(edu.umd.
* cs.findbugs.classfile.ClassDescriptor, edu.umd.cs.findbugs.ba.XClass)
*/
+ @Override
public boolean visitClass(ClassDescriptor classDescriptor, XClass xclass) {
assert xclass != null;
- String methodSignature;
+ String methodSignature = xmethod.getSignature();
XMethod bridgedFrom = xmethod.bridgeFrom();
- if (bridgedFrom != null && !classDescriptor.equals(xmethod.getClassDescriptor())) {
- methodSignature = bridgedFrom.getSignature();
- } else {
- methodSignature = xmethod.getSignature();
- }
// See if this class has an overridden method
+
XMethod xm = xclass.findMethod(xmethod.getName(), methodSignature, false);
- if (xm == null && bridgedFrom != null && xclass.isInterface()) {
- // if the method is bridged and the superclass is an interface,
- // check the exact signature as well
- xm = xclass.findMethod(xmethod.getName(), xmethod.getSignature(), false);
+
+ if (xm == null && bridgedFrom != null && !classDescriptor.equals(xmethod.getClassDescriptor())) {
+ methodSignature = bridgedFrom.getSignature();
+ xm = xclass.findMethod(xmethod.getName(), methodSignature, false);
}
if (xm != null) {
@@ -87,25 +84,12 @@ public abstract class OverriddenMethodsVisitor implements InheritanceGraphVisito
}
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.ch.InheritanceGraphVisitor#visitEdge(edu.umd.cs
- * .findbugs.classfile.ClassDescriptor, edu.umd.cs.findbugs.ba.XClass,
- * edu.umd.cs.findbugs.classfile.ClassDescriptor,
- * edu.umd.cs.findbugs.ba.XClass)
- */
- public boolean visitEdge(ClassDescriptor sourceDesc, XClass source, ClassDescriptor targetDesc, XClass target) {
- return (target != null);
- }
-
/**
* Downcall method: will be called for each method overridden by the derived
* method object passed to the constructor. Note that this method will be
* called <em>for</em> the original derived method, since this is useful for
* some applications.
- *
+ *
* @param xmethod
* a method which is overridden by the original derived method,
* or is the original derived method
diff --git a/src/java/edu/umd/cs/findbugs/ba/ch/Subtypes2.java b/src/java/edu/umd/cs/findbugs/ba/ch/Subtypes2.java
index e4ded6a..79a9016 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ch/Subtypes2.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ch/Subtypes2.java
@@ -85,7 +85,7 @@ public class Subtypes2 {
* Object to record the results of a supertype search.
*/
private static class SupertypeQueryResults {
- private Set<ClassDescriptor> supertypeSet = new HashSet<ClassDescriptor>(4);
+ private final Set<ClassDescriptor> supertypeSet = new HashSet<ClassDescriptor>(4);
private boolean encounteredMissingClasses = false;
@@ -148,15 +148,20 @@ public class Subtypes2 {
public static boolean isJSP(JavaClass javaClass) {
@DottedClassName String className = javaClass.getClassName();
- if ( className.endsWith("_jsp") || className.endsWith("_tag"))
+ if ( className.endsWith("_jsp") || className.endsWith("_tag")) {
return true;
- for(Method m : javaClass.getMethods())
- if (m.getName().startsWith("_jsp"))
+ }
+ for(Method m : javaClass.getMethods()) {
+ if (m.getName().startsWith("_jsp")) {
return true;
-
- for(Field f : javaClass.getFields())
- if (f.getName().startsWith("_jsp"))
+ }
+ }
+
+ for(Field f : javaClass.getFields()) {
+ if (f.getName().startsWith("_jsp")) {
return true;
+ }
+ }
return Subtypes2.instanceOf(className, "javax.servlet.jsp.JspPage")
|| Subtypes2.instanceOf(className, "org.apache.jasper.runtime.HttpJspBase")
|| Subtypes2.instanceOf(className, "javax.servlet.jsp.tagext.SimpleTagSupport")
@@ -191,10 +196,12 @@ public class Subtypes2 {
}
public static boolean instanceOf(JavaClass subtype, @DottedClassName String dottedSupertype) {
- if (subtype.getClassName().equals(dottedSupertype) || subtype.getSuperclassName().equals(dottedSupertype))
+ if (subtype.getClassName().equals(dottedSupertype) || subtype.getSuperclassName().equals(dottedSupertype)) {
return true;
- if (subtype.getSuperclassName().equals("java.lang.Object") && subtype.getInterfaceIndices().length == 0)
+ }
+ if ("java.lang.Object".equals(subtype.getSuperclassName()) && subtype.getInterfaceIndices().length == 0) {
return false;
+ }
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
ClassDescriptor subDescriptor = DescriptorFactory.createClassDescriptor(subtype);
ClassDescriptor superDescriptor = DescriptorFactory.createClassDescriptorFromDottedClassName(dottedSupertype);
@@ -215,8 +222,9 @@ public class Subtypes2 {
*/
public void addApplicationClass(XClass appXClass) {
for (XMethod m : appXClass.getXMethods()) {
- if (m.isStub())
+ if (m.isStub()) {
return;
+ }
}
ClassVertex vertex = addClassAndGetClassVertex(appXClass);
vertex.markAsApplicationClass();
@@ -321,10 +329,12 @@ public class Subtypes2 {
if (type.equals(possibleSupertype)) {
return true;
}
- if (possibleSupertype.equals(Type.OBJECT))
+ if (possibleSupertype.equals(Type.OBJECT)) {
return true;
- if (type.equals(Type.OBJECT))
+ }
+ if (type.equals(Type.OBJECT)) {
return false;
+ }
boolean typeIsObjectType = (type instanceof ObjectType);
boolean possibleSupertypeIsObjectType = (possibleSupertype instanceof ObjectType);
@@ -389,10 +399,11 @@ public class Subtypes2 {
}
ClassDescriptor prevSubDesc, prevSuperDesc;
boolean prevResult;
-
+
public boolean isSubtype(ClassDescriptor subDesc, ClassDescriptor superDesc) throws ClassNotFoundException {
- if (subDesc == prevSubDesc && prevSuperDesc == superDesc)
+ if (subDesc == prevSubDesc && prevSuperDesc == superDesc) {
return prevResult;
+ }
prevResult = isSubtype0(subDesc, superDesc);
prevSubDesc = subDesc;
prevSuperDesc = superDesc;
@@ -401,62 +412,81 @@ public class Subtypes2 {
public boolean isSubtype(ClassDescriptor subDesc, ClassDescriptor... superDesc) throws ClassNotFoundException {
for (ClassDescriptor s : superDesc) {
- if (subDesc.equals(s))
+ if (subDesc.equals(s)) {
return true;
+ }
}
XClass xclass = AnalysisContext.currentXFactory().getXClass(subDesc);
if (xclass != null) {
ClassDescriptor xSuper = xclass.getSuperclassDescriptor();
for (ClassDescriptor s : superDesc) {
- if (s.equals(xSuper))
+ if (s.equals(xSuper)) {
return true;
+ }
}
}
SupertypeQueryResults supertypeQueryResults = getSupertypeQueryResults(subDesc);
- for (ClassDescriptor s : superDesc)
- if (supertypeQueryResults.containsType(s))
+ for (ClassDescriptor s : superDesc) {
+ if (supertypeQueryResults.containsType(s)) {
return true;
+ }
+ }
return false;
}
-
+
public boolean isSubtype0(ClassDescriptor subDesc, ClassDescriptor superDesc) throws ClassNotFoundException {
assert subDesc != null;
assert superDesc != null;
- if (subDesc.equals(superDesc))
+ if (subDesc.equals(superDesc)) {
return true;
+ }
String superName = superDesc.getClassName();
- if (superName.equals("java/lang/Object"))
+ if ("java/lang/Object".equals(superName)) {
return true;
+ }
String subName = subDesc.getClassName();
- if (subName.equals("java/lang/Object"))
+ if ("java/lang/Object".equals(subName)) {
return false;
-
-
- if (true) {
+ }
+
+ // if (true) {
+ // XXX call below causes 88% of all MissingClassException thrown (20000 on java* JDK7 classes)
XClass xclass = AnalysisContext.currentXFactory().getXClass(subDesc);
if (xclass != null) {
ClassDescriptor xSuper = xclass.getSuperclassDescriptor();
- if (superDesc.equals(xSuper))
+ if (superDesc.equals(xSuper)) {
return true;
+ }
ClassDescriptor[] interfaces = xclass.getInterfaceDescriptorList();
if (interfaces.length == 0) {
- if (xSuper == null)
+ if (xSuper == null) {
return false;
- if (xSuper.getClassName().equals("java/lang/Object"))
+ }
+ if ("java/lang/Object".equals(xSuper.getClassName())) {
return false;
- } else for (ClassDescriptor i : interfaces)
- if (superDesc.equals(i))
- return true;
- }
+ }
+ } else {
+ for (ClassDescriptor i : interfaces) {
+ if (superDesc.equals(i)) {
+ return true;
+ }
+ }
+ }
}
+ // }
+
+ /*
if (false) {
- if (subName.equals("java/lang/Error") && superName.equals("java/lang/RuntimeException"))
- System.out.println("huh");
+ if (subName.equals("java/lang/Error") && superName.equals("java/lang/RuntimeException")) {
+ System.out.println("huh");
+ }
System.out.println("sub: " + subDesc);
System.out.println("SUP: " + superDesc);
System.out.println("CHECK: " + subDesc + " " + superDesc);
- }
+ }
+ */
SupertypeQueryResults supertypeQueryResults = getSupertypeQueryResults(subDesc);
+ // XXX call below causes 88% of all ClassNotFoundException thrown (20000 on java* JDK7 classes)
return supertypeQueryResults.containsType(superDesc);
}
@@ -693,10 +723,12 @@ public class Subtypes2 {
Set<ClassDescriptor> aSuperTypes = computeKnownSupertypes(aDesc);
Set<ClassDescriptor> bSuperTypes = computeKnownSupertypes(bDesc);
- if (bSuperTypes.contains(aDesc))
+ if (bSuperTypes.contains(aDesc)) {
return a;
- if (aSuperTypes.contains(bDesc))
+ }
+ if (aSuperTypes.contains(bDesc)) {
return b;
+ }
ArrayList<ClassVertex> aSuperList = getAllSuperclassVertices(aVertex);
ArrayList<ClassVertex> bSuperList = getAllSuperclassVertices(bVertex);
@@ -715,22 +747,26 @@ public class Subtypes2 {
aIndex--;
bIndex--;
}
- if (lastCommonInBackwardsSearch == null)
+ if (lastCommonInBackwardsSearch == null) {
firstCommonSupertype = Type.OBJECT;
- else
+ } else {
firstCommonSupertype = ObjectTypeFactory.getInstance(lastCommonInBackwardsSearch.getClassDescriptor()
.toDottedClassName());
+ }
if (firstCommonSupertype.equals(Type.OBJECT)) {
// see if we can't do better
ClassDescriptor objDesc = DescriptorFactory.getClassDescriptor(Type.OBJECT);
aSuperTypes.retainAll(bSuperTypes);
aSuperTypes.remove(objDesc);
- for (ClassDescriptor c : aSuperTypes)
- if (c.getPackageName().equals(aDesc.getPackageName()) || c.getPackageName().equals(bDesc.getPackageName()))
+ for (ClassDescriptor c : aSuperTypes) {
+ if (c.getPackageName().equals(aDesc.getPackageName()) || c.getPackageName().equals(bDesc.getPackageName())) {
return ObjectTypeFactory.getInstance(c.toDottedClassName());
+ }
+ }
- for (ClassDescriptor c : aSuperTypes)
+ for (ClassDescriptor c : aSuperTypes) {
return ObjectTypeFactory.getInstance(c.toDottedClassName());
+ }
}
return firstCommonSupertype;
@@ -851,7 +887,7 @@ public class Subtypes2 {
return result;
}
-
+
/**
* Get Collection of all XClass objects (resolved classes) seen so far.
*
@@ -957,6 +993,55 @@ public class Subtypes2 {
}
}
+ /**
+ * Starting at the class or interface named by the given ClassDescriptor,
+ * traverse the inheritance graph depth first, visiting each class only
+ * once. This is much faster than traversing all paths in certain circumstances.
+ *
+ * @param start
+ * ClassDescriptor naming the class where the traversal should
+ * start
+ * @param visitor
+ * an InheritanceGraphVisitor
+ * @throws ClassNotFoundException
+ * if the start vertex cannot be resolved
+ */
+ public void traverseSupertypesDepthFirst(ClassDescriptor start, SupertypeTraversalVisitor visitor) throws ClassNotFoundException {
+ this.traverseSupertypesDepthFirstHelper(start, visitor, new HashSet<ClassDescriptor>());
+ }
+
+ private void traverseSupertypesDepthFirstHelper(ClassDescriptor cur, SupertypeTraversalVisitor visitor,
+ Set<ClassDescriptor> seen) throws ClassNotFoundException {
+
+ if (seen.contains(cur)) {
+ return;
+ }
+ seen.add(cur);
+
+ ClassVertex vertex = resolveClassVertex(cur);
+
+ if (!vertex.isResolved()) {
+ // Unknown class - so, we don't know its immediate supertypes
+ return;
+ }
+
+ if (!visitor.visitClass(vertex.getClassDescriptor(), vertex.getXClass())) {
+ // Visitor doesn't want to continue on this path
+ return;
+ }
+
+ // Advance to direct superclass
+ ClassDescriptor superclassDescriptor = vertex.getXClass().getSuperclassDescriptor();
+ if (superclassDescriptor != null) {
+ traverseSupertypesDepthFirstHelper(superclassDescriptor, visitor, seen);
+ }
+
+ // Advance to directly-implemented interfaces
+ for (ClassDescriptor ifaceDesc : vertex.getXClass().getInterfaceDescriptorList()) {
+ traverseSupertypesDepthFirstHelper(ifaceDesc, visitor, seen);
+ }
+ }
+
private void addToWorkList(LinkedList<SupertypeTraversalPath> workList, SupertypeTraversalPath curPath,
ClassDescriptor supertypeDescriptor) {
ClassVertex vertex = classDescriptorToVertexMap.get(supertypeDescriptor);
@@ -1031,13 +1116,14 @@ public class Subtypes2 {
return new HashSet<ClassDescriptor>(result);
}
-
+
public boolean hasKnownSubclasses(ClassDescriptor classDescriptor) throws ClassNotFoundException {
-
+
ClassVertex startVertex = resolveClassVertex(classDescriptor);
- if (!startVertex.isInterface())
+ if (!startVertex.isInterface()) {
return true;
-
+ }
+
LinkedList<ClassVertex> workList = new LinkedList<ClassVertex>();
workList.addLast(startVertex);
@@ -1053,8 +1139,9 @@ public class Subtypes2 {
}
// Add class to the result
- if (current.isResolved() && !current.isInterface())
+ if (current.isResolved() && !current.isInterface()) {
return true;
+ }
// Add all known subtype vertices to the work list
Iterator<InheritanceEdge> i = graph.incomingEdgeIterator(current);
@@ -1121,7 +1208,7 @@ public class Subtypes2 {
* @return SupertypeQueryResults containing known supertypes of the class
*/
private SupertypeQueryResults computeSupertypes(ClassDescriptor classDescriptor) // throws
- // ClassNotFoundException
+ // ClassNotFoundException
{
if (DEBUG_QUERIES) {
System.out.println("Computing supertypes for " + classDescriptor.toDottedClassName());
@@ -1185,10 +1272,6 @@ public class Subtypes2 {
return typeVertex;
}
- /**
- * @param classDescriptor
- * @return
- */
private ClassVertex optionallyResolveClassVertex(ClassDescriptor classDescriptor) {
ClassVertex typeVertex = classDescriptorToVertexMap.get(classDescriptor);
if (typeVertex == null) {
@@ -1225,8 +1308,9 @@ public class Subtypes2 {
// Direct superclass
ClassDescriptor superclassDescriptor = xclass.getSuperclassDescriptor();
- if (superclassDescriptor != null)
+ if (superclassDescriptor != null) {
addInheritanceEdge(vertex, superclassDescriptor, false, workList);
+ }
// Directly implemented interfaces
for (ClassDescriptor ifaceDesc : xclass.getInterfaceDescriptorList()) {
diff --git a/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraphVisitor.java b/src/java/edu/umd/cs/findbugs/ba/ch/SupertypeTraversalVisitor.java
similarity index 55%
copy from src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraphVisitor.java
copy to src/java/edu/umd/cs/findbugs/ba/ch/SupertypeTraversalVisitor.java
index 91e6c37..5e8c7c0 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ch/InheritanceGraphVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/ch/SupertypeTraversalVisitor.java
@@ -19,43 +19,27 @@
package edu.umd.cs.findbugs.ba.ch;
-import javax.annotation.CheckForNull;
-
import edu.umd.cs.findbugs.ba.XClass;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
/**
- * Visitor interface for traversals of the inheritance graph.
- *
+ * Visitor interface for simple traversals of the inheritance graph.
+ *
* @see Subtypes2
- * @author David Hovemeyer
+ * @author Tobias Baum
*/
-public interface InheritanceGraphVisitor {
+public interface SupertypeTraversalVisitor {
/**
* Visit a class vertex in the inheritance graph.
- *
+ * Only called for classes that could be resolved, not called for java.lang.Object.
+ *
* @param classDescriptor
* ClassDescriptor of the class vertex
* @param xclass
- * XClass object containing information about the class; null if
- * class cannot be resolved
+ * XClass object containing information about the class; never null
+ *
* @return true if traversal should continue, false otherwise
*/
- public boolean visitClass(ClassDescriptor classDescriptor, @CheckForNull XClass xclass);
+ public boolean visitClass(ClassDescriptor classDescriptor, XClass xclass);
- /**
- * Visit an inheritance edge in the inheritance graph.
- *
- * @param sourceDesc
- * ClassDescriptor of the source class (subtype)
- * @param source
- * XClass object containing information about source class
- * @param targetDesc
- * ClassDescriptor of the target class (supertype)
- * @param target
- * XClass object containing information about target class; null
- * if class cannot be resolved
- * @return true if traversal should continue, false otherwise
- */
- public boolean visitEdge(ClassDescriptor sourceDesc, XClass source, ClassDescriptor targetDesc, @CheckForNull XClass target);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/constant/Constant.java b/src/java/edu/umd/cs/findbugs/ba/constant/Constant.java
index 1daed12..5dfc0d2 100644
--- a/src/java/edu/umd/cs/findbugs/ba/constant/Constant.java
+++ b/src/java/edu/umd/cs/findbugs/ba/constant/Constant.java
@@ -23,7 +23,7 @@ import javax.annotation.Nullable;
/**
* Abstract dataflow value representing a value which may or may not be a
* constant.
- *
+ *
* @see edu.umd.cs.findbugs.ba.constant.ConstantAnalysis
* @author David Hovemeyer
*/
@@ -37,7 +37,7 @@ public class Constant {
/**
* Constructor for a constant value.
- *
+ *
* @param value
* the constant value; must be a String, Integer, etc.
*/
@@ -50,7 +50,7 @@ public class Constant {
}
/**
* Return whether or not this value is a constant.
- *
+ *
* @return true if the value is a constant, false if not
*/
public boolean isConstant() {
@@ -59,7 +59,7 @@ public class Constant {
/**
* Return whether or not this value is a constant String.
- *
+ *
* @return true if the value is a constant String, false if not
*/
public boolean isConstantString() {
@@ -68,7 +68,7 @@ public class Constant {
/**
* Get the constant String value of this value.
- *
+ *
* @return the constant String value
*/
public String getConstantString() {
@@ -77,7 +77,7 @@ public class Constant {
/**
* Return whether or not this value is a constant int/Integer.
- *
+ *
* @return true if the value is a constant int/Integer, false if not
*/
public boolean isConstantInteger() {
@@ -86,7 +86,7 @@ public class Constant {
/**
* Get the constant int value of this value.
- *
+ *
* @return the constant int value
*/
public int getConstantInt() {
@@ -95,7 +95,7 @@ public class Constant {
/**
* Merge two Constants.
- *
+ *
* @param a
* a StaticConstant
* @param b
@@ -103,24 +103,28 @@ public class Constant {
* @return the merge (dataflow meet) of the two Constants
*/
public static Constant merge(Constant a, Constant b) {
- if (!a.isConstant() || !b.isConstant())
+ if (!a.isConstant() || !b.isConstant()) {
return NOT_CONSTANT;
- if (a.value.getClass() != b.value.getClass() || !a.value.equals(b.value))
+ }
+ if (a.value.getClass() != b.value.getClass() || !a.value.equals(b.value)) {
return NOT_CONSTANT;
+ }
return a;
}
@Override
public boolean equals(Object obj) {
- if (obj == null || obj.getClass() != this.getClass())
+ if (obj == null || obj.getClass() != this.getClass()) {
return false;
+ }
Constant other = (Constant) obj;
- if (other.value == this.value)
+ if (other.value == this.value) {
return true;
- else if (other.value == null || this.value == null)
+ } else if (other.value == null || this.value == null) {
return false;
- else
+ } else {
return this.value.equals(other.value);
+ }
}
@Override
diff --git a/src/java/edu/umd/cs/findbugs/ba/constant/ConstantAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/constant/ConstantAnalysis.java
index fe4e3d3..bb393df 100644
--- a/src/java/edu/umd/cs/findbugs/ba/constant/ConstantAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/constant/ConstantAnalysis.java
@@ -30,14 +30,14 @@ import edu.umd.cs.findbugs.ba.Location;
/**
* Dataflow analysis to find constant values.
- *
+ *
* @see edu.umd.cs.findbugs.ba.constant.Constant
* @author David Hovemeyer
*/
public class ConstantAnalysis extends FrameDataflowAnalysis<Constant, ConstantFrame> {
- private MethodGen methodGen;
+ private final MethodGen methodGen;
- private ConstantFrameModelingVisitor visitor;
+ private final ConstantFrameModelingVisitor visitor;
public ConstantAnalysis(MethodGen methodGen, DepthFirstSearch dfs) {
super(dfs);
@@ -45,10 +45,12 @@ public class ConstantAnalysis extends FrameDataflowAnalysis<Constant, ConstantFr
this.visitor = new ConstantFrameModelingVisitor(methodGen.getConstantPool());
}
+ @Override
public ConstantFrame createFact() {
return new ConstantFrame(methodGen.getMaxLocals());
}
+ @Override
public void initEntryFact(ConstantFrame frame) {
frame.setValid();
frame.clearStack();
@@ -65,13 +67,14 @@ public class ConstantAnalysis extends FrameDataflowAnalysis<Constant, ConstantFr
visitor.analyzeInstruction(handle.getInstruction());
}
+ @Override
public void meetInto(ConstantFrame fact, Edge edge, ConstantFrame result) throws DataflowAnalysisException {
if (fact.isValid()) {
ConstantFrame tmpFact = null;
if (edge.isExceptionEdge()) {
- tmpFact = modifyFrame(fact, tmpFact);
+ tmpFact = modifyFrame(fact, null);
tmpFact.clearStack();
tmpFact.pushValue(Constant.NOT_CONSTANT);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/constant/ConstantDataflow.java b/src/java/edu/umd/cs/findbugs/ba/constant/ConstantDataflow.java
index 8d2404c..f9da6c1 100644
--- a/src/java/edu/umd/cs/findbugs/ba/constant/ConstantDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/constant/ConstantDataflow.java
@@ -23,7 +23,7 @@ import edu.umd.cs.findbugs.ba.Dataflow;
/**
* Dataflow class for ConstantAnalysis.
- *
+ *
* @see edu.umd.cs.findbugs.ba.Dataflow
* @see edu.umd.cs.findbugs.ba.constant.ConstantAnalysis
* @author David Hovemeyer
diff --git a/src/java/edu/umd/cs/findbugs/ba/constant/ConstantFrame.java b/src/java/edu/umd/cs/findbugs/ba/constant/ConstantFrame.java
index ff0399c..8f392cc 100644
--- a/src/java/edu/umd/cs/findbugs/ba/constant/ConstantFrame.java
+++ b/src/java/edu/umd/cs/findbugs/ba/constant/ConstantFrame.java
@@ -22,7 +22,7 @@ import edu.umd.cs.findbugs.ba.Frame;
/**
* Dataflow Frame for Constants.
- *
+ *
* @see edu.umd.cs.findbugs.ba.constant.Constant
* @see edu.umd.cs.findbugs.ba.constant.ConstantAnalysis
* @author David Hovemeyer
diff --git a/src/java/edu/umd/cs/findbugs/ba/constant/ConstantFrameModelingVisitor.java b/src/java/edu/umd/cs/findbugs/ba/constant/ConstantFrameModelingVisitor.java
index 3bf0dcd..ff6bc13 100644
--- a/src/java/edu/umd/cs/findbugs/ba/constant/ConstantFrameModelingVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/constant/ConstantFrameModelingVisitor.java
@@ -30,12 +30,12 @@ import edu.umd.cs.findbugs.ba.AbstractFrameModelingVisitor;
/**
* Visitor to model the effect of bytecode instructions on ConstantFrames.
- *
+ *
* <p>
* For now, only String constants are modeled. In the future we can add other
* kinds of constants.
* </p>
- *
+ *
* @see edu.umd.cs.findbugs.ba.constant.ConstantAnalysis
* @author David Hovemeyer
*/
@@ -57,11 +57,13 @@ public class ConstantFrameModelingVisitor extends AbstractFrameModelingVisitor<C
int amount = obj.getIncrement();
ConstantFrame f = getFrame();
Constant c = f.getValue(v);
- if (c.isConstantInteger())
+ if (c.isConstantInteger()) {
f.setValue(v, new Constant(c.getConstantInt() + amount));
- else
+ }
+ else {
f.setValue(v, Constant.NOT_CONSTANT);
- // System.out.println("after iinc: " + getFrame());
+ // System.out.println("after iinc: " + getFrame());
+ }
}
@Override
diff --git a/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefAnalysis.java
index 818f526..9a5a1ea 100644
--- a/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefAnalysis.java
@@ -83,11 +83,6 @@ import edu.umd.cs.findbugs.visitclass.Util;
*/
public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<UnconditionalValueDerefSet> {
- @Override
- public String toString() {
- return this.getClass().getSimpleName() + " of " + method;
- }
-
public static final boolean DEBUG = SystemProperties.getBoolean("fnd.derefs.debug");
public static final boolean ASSUME_NONZERO_TRIP_LOOPS = SystemProperties.getBoolean("fnd.derefs.nonzerotrip");
@@ -100,6 +95,10 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
public static final boolean DEBUG_CHECK_CALLS = SystemProperties.getBoolean("fnd.derefs.checkcalls.debug");
+ private static final int NULLCHECK1[] = { Opcodes.DUP, Opcodes.INVOKESPECIAL, Opcodes.ATHROW };
+
+ private static final int NULLCHECK2[] = { Opcodes.DUP, Opcodes.LDC, Opcodes.INVOKESPECIAL, Opcodes.ATHROW };
+
private final CFG cfg;
private final Method method;
@@ -119,12 +118,8 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
*
* @param rdfs
* the reverse depth-first-search (for the block order)
- * @param dfs
- * TODO
* @param cfg
* the CFG for the method
- * @param method
- * TODO
* @param methodGen
* the MethodGen for the method
* @param vnaDataflow
@@ -143,7 +138,11 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
System.out.println("UnconditionalValueDerefAnalysis analysis " + methodGen.getClassName() + "." + methodGen.getName()
+ " : " + methodGen.getSignature());
}
+ }
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + " of " + method;
}
/**
@@ -157,34 +156,20 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
this.invDataflow = invDataflow;
}
- /**
- *
- *
- */
public void setTypeDataflow(TypeDataflow typeDataflow) {
this.typeDataflow = typeDataflow;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#isFactValid(java.lang
- * .Object)
- */
@Override
public boolean isFactValid(UnconditionalValueDerefSet fact) {
return !fact.isTop() && !fact.isBottom();
}
- private static final int NULLCHECK1[] = { Opcodes.DUP, Opcodes.INVOKESPECIAL, Opcodes.ATHROW };
-
- private static final int NULLCHECK2[] = { Opcodes.DUP, Opcodes.LDC, Opcodes.INVOKESPECIAL, Opcodes.ATHROW };
-
private static boolean check(InstructionHandle h, int[] opcodes) {
for (int opcode : opcodes) {
- if (h == null)
+ if (h == null) {
return false;
+ }
short opcode2 = h.getInstruction().getOpcode();
if (opcode == Constants.LDC) {
switch (opcode2) {
@@ -198,23 +183,27 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
default:
return false;
}
- } else if (opcode2 != opcode)
+ } else if (opcode2 != opcode) {
return false;
+ }
h = h.getNext();
}
return true;
}
public static boolean isNullCheck(InstructionHandle h, ConstantPoolGen cpg) {
- if (!(h.getInstruction() instanceof IFNONNULL))
+ if (!(h.getInstruction() instanceof IFNONNULL)) {
return false;
+ }
h = h.getNext();
final Instruction newInstruction = h.getInstruction();
- if (!(newInstruction instanceof NEW))
+ if (!(newInstruction instanceof NEW)) {
return false;
+ }
final ObjectType loadClassType = ((NEW) newInstruction).getLoadClassType(cpg);
- if (!loadClassType.getClassName().equals("java.lang.NullPointerException"))
+ if (!"java.lang.NullPointerException".equals(loadClassType.getClassName())) {
return false;
+ }
h = h.getNext();
return check(h, NULLCHECK1) || check(h, NULLCHECK2);
@@ -230,31 +219,27 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
public static boolean reportPotentialDereference(Location location, IsNullValueFrame invFrame)
throws DataflowAnalysisException {
- if (!invFrame.isValid())
+ if (!invFrame.isValid()) {
return false;
+ }
IsNullValue value = invFrame.getTopValue();
- if (value.isDefinitelyNotNull())
+ if (value.isDefinitelyNotNull()) {
return false;
- if (value.isDefinitelyNull())
+ }
+ if (value.isDefinitelyNull()) {
return false;
+ }
return true;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#transferInstruction(org
- * .apache.bcel.generic.InstructionHandle,
- * edu.umd.cs.findbugs.ba.BasicBlock, java.lang.Object)
- */
@Override
public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, UnconditionalValueDerefSet fact)
throws DataflowAnalysisException {
Instruction instruction = handle.getInstruction();
- if (fact.isTop())
+ if (fact.isTop()) {
return;
+ }
Location location = new Location(handle, basicBlock);
// If this is a call to an assertion method,
@@ -264,9 +249,10 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
// returns normally.
// TODO: at some point, evaluate whether we should revisit this
if (isAssertion(handle) // || handle.getInstruction() instanceof ATHROW
- ) {
- if (DEBUG)
+ ) {
+ if (DEBUG) {
System.out.println("MAKING BOTTOM0 AT: " + location);
+ }
fact.clear();
return;
}
@@ -274,8 +260,9 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
// Get value number frame
ValueNumberFrame vnaFrame = vnaDataflow.getFactAtLocation(location);
if (!vnaFrame.isValid()) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("MAKING TOP1 AT: " + location);
+ }
// Probably dead code.
// Assume this location can't be reached.
makeFactTop(fact);
@@ -310,11 +297,14 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
// Check to see if an instance value is dereferenced here
checkInstance(location, vnaFrame, fact);
- if (false)
+ /*
+ if (false) {
fact.cleanDerefSet(location, vnaFrame);
+ }*/
- if (DEBUG && fact.isTop())
+ if (DEBUG && fact.isTop()) {
System.out.println("MAKING TOP2 At: " + location);
+ }
}
@@ -335,59 +325,69 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
ConstantPoolGen constantPool = methodGen.getConstantPool();
for (ValueNumber vn : checkUnconditionalDerefDatabase(location, vnaFrame, constantPool,
- invDataflow.getFactAtLocation(location), typeDataflow))
+ invDataflow.getFactAtLocation(location), typeDataflow)) {
fact.addDeref(vn, location);
+ }
}
public static Set<ValueNumber> checkUnconditionalDerefDatabase(Location location, ValueNumberFrame vnaFrame,
ConstantPoolGen constantPool, @CheckForNull IsNullValueFrame invFrame, TypeDataflow typeDataflow)
- throws DataflowAnalysisException {
- if (invFrame != null && !invFrame.isValid())
+ throws DataflowAnalysisException {
+ if (invFrame != null && !invFrame.isValid()) {
return Collections.emptySet();
+ }
InvokeInstruction inv = (InvokeInstruction) location.getHandle().getInstruction();
SignatureParser sigParser = new SignatureParser(inv.getSignature(constantPool));
int numParams = sigParser.getNumParameters();
- if (numParams == 0 || !sigParser.hasReferenceParameters())
+ if (numParams == 0 || !sigParser.hasReferenceParameters()) {
return Collections.emptySet();
+ }
ParameterNullnessPropertyDatabase database = AnalysisContext.currentAnalysisContext()
.getUnconditionalDerefParamDatabase();
if (database == null) {
- if (DEBUG_CHECK_CALLS)
+ if (DEBUG_CHECK_CALLS) {
System.out.println("no database!");
+ }
return Collections.emptySet();
}
TypeFrame typeFrame = typeDataflow.getFactAtLocation(location);
if (!typeFrame.isValid()) {
- if (DEBUG_CHECK_CALLS)
+ if (DEBUG_CHECK_CALLS) {
System.out.println("invalid type frame!");
+ }
return Collections.emptySet();
}
try {
Set<XMethod> targetSet = Hierarchy2.resolveMethodCallTargets(inv, typeFrame, constantPool);
- if (targetSet.isEmpty())
+ if (targetSet.isEmpty()) {
return Collections.emptySet();
+ }
- if (DEBUG_CHECK_CALLS)
+ if (DEBUG_CHECK_CALLS) {
System.out.println("target set size: " + targetSet.size());
+ }
// Compute the intersection of all properties
ParameterProperty derefParamSet = null;
for (XMethod target : targetSet) {
- if (target.isStub())
+ if (target.isStub()) {
continue;
- if (DEBUG_CHECK_CALLS)
+ }
+ if (DEBUG_CHECK_CALLS) {
System.out.print("Checking: " + target + ": ");
+ }
ParameterProperty targetDerefParamSet = database.getProperty(target.getMethodDescriptor());
if (targetDerefParamSet == null) {
// Hmm...no information for this target.
// assume it doesn't dereference anything
- if (DEBUG_CHECK_CALLS)
+ if (DEBUG_CHECK_CALLS) {
System.out.println("==> no information, assume no guaranteed dereferences");
+ }
return Collections.emptySet();
}
@@ -403,8 +403,9 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
}
if (derefParamSet == null || derefParamSet.isEmpty()) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("** Nothing");
+ }
return Collections.emptySet();
}
if (DEBUG_CHECK_CALLS) {
@@ -417,10 +418,12 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
continue;
}
int argSlot = vnaFrame.getStackLocation(sigParser.getSlotsFromTopOfStackForParameter(i));
- if (invFrame != null && !reportDereference(invFrame, argSlot))
+ if (invFrame != null && !reportDereference(invFrame, argSlot)) {
continue;
- if (DEBUG_CHECK_CALLS)
+ }
+ if (DEBUG_CHECK_CALLS) {
System.out.println(" dereference @ " + location.getHandle().getPosition() + " of parameter " + i);
+ }
requiredToBeNonnull.add(vnaFrame.getValue(argSlot));
}
@@ -438,8 +441,6 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
* If this is a method call instruction, check to see if any of the
* parameters are @NonNull, and treat them as dereferences.
*
- * @param thisMethod
- * TODO
* @param location
* the Location of the instruction
* @param vnaFrame
@@ -453,8 +454,9 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
UnconditionalValueDerefSet fact) throws DataflowAnalysisException {
INullnessAnnotationDatabase database = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase();
- if (database.getResolvedAnnotation(thisMethod, true) != NullnessAnnotation.NONNULL)
+ if (database.getResolvedAnnotation(thisMethod, true) != NullnessAnnotation.NONNULL) {
return;
+ }
if (reportPotentialDereference(location, invDataflow.getFactAtLocation(location))) {
ValueNumber vn = vnaFrame.getTopValue();
fact.addDeref(vn, location);
@@ -481,13 +483,15 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
XField field = XFactory.createXField(fieldIns, methodGen.getConstantPool());
char firstChar = field.getSignature().charAt(0);
- if (firstChar != 'L' && firstChar != '[')
+ if (firstChar != 'L' && firstChar != '[') {
return;
+ }
NullnessAnnotation resolvedAnnotation = database.getResolvedAnnotation(field, true);
if (resolvedAnnotation == NullnessAnnotation.NONNULL) {
IsNullValueFrame invFrame = invDataflow.getFactAtLocation(location);
- if (!invFrame.isValid())
+ if (!invFrame.isValid()) {
return;
+ }
IsNullValue value = invFrame.getTopValue();
if (reportDereference(value)) {
ValueNumber vn = vnaFrame.getTopValue();
@@ -513,8 +517,9 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
ConstantPoolGen constantPool = methodGen.getConstantPool();
Set<ValueNumber> nonNullParams = checkNonNullParams(location, vnaFrame, constantPool, method,
invDataflow.getFactAtLocation(location));
- for (ValueNumber vn : nonNullParams)
+ for (ValueNumber vn : nonNullParams) {
fact.addDeref(vn, location);
+ }
}
public static Set<ValueNumber> checkAllNonNullParams(Location location, ValueNumberFrame vnaFrame,
@@ -526,21 +531,22 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
}
Set<ValueNumber> result1 = checkNonNullParams(location, vnaFrame, constantPool, method, invFrame);
Set<ValueNumber> result2 = checkUnconditionalDerefDatabase(location, vnaFrame, constantPool, invFrame, typeDataflow);
- if (result1.isEmpty())
+ if (result1.isEmpty()) {
return result2;
- if (result2.isEmpty())
+ }
+ if (result2.isEmpty()) {
return result1;
+ }
result1.addAll(result2);
-
return result1;
-
}
public static Set<ValueNumber> checkNonNullParams(Location location, ValueNumberFrame vnaFrame, ConstantPoolGen constantPool,
@CheckForNull Method method, @CheckForNull IsNullValueFrame invFrame) throws DataflowAnalysisException {
- if (invFrame != null && !invFrame.isValid())
+ if (invFrame != null && !invFrame.isValid()) {
return Collections.emptySet();
+ }
INullnessAnnotationDatabase database = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase();
InvokeInstruction inv = (InvokeInstruction) location.getHandle().getInstruction();
@@ -553,13 +559,15 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
for (int i = 0; i < numParams; i++) {
String parameterSignature = parameterIterator.next();
char firstChar = parameterSignature.charAt(0);
- if (firstChar != 'L' && firstChar != '[')
+ if (firstChar != 'L' && firstChar != '[') {
continue;
+ }
int offset = sigParser.getSlotsFromTopOfStackForParameter(i);
if (invFrame != null) {
int slot = invFrame.getStackLocation(offset);
- if (!reportDereference(invFrame, slot))
+ if (!reportDereference(invFrame, slot)) {
continue;
+ }
}
if (database.parameterMustBeNonNull(called, i)) {
int catchSizeNPE = Util.getSizeOfSurroundingTryBlock(method, "java/lang/NullPointerException", location
@@ -567,7 +575,7 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
int catchSizeNFE = Util.getSizeOfSurroundingTryBlock(method, "java/lang/NumberFormatException", location
.getHandle().getPosition());
if (catchSizeNPE == Integer.MAX_VALUE
- && (!called.getClassName().equals("java.lang.Integer") || catchSizeNFE == Integer.MAX_VALUE)) {
+ && (!"java.lang.Integer".equals(called.getClassName()) || catchSizeNFE == Integer.MAX_VALUE)) {
// Get the corresponding value number
ValueNumber vn = vnaFrame.getArgument(inv, constantPool, i, sigParser);
result.add(vn);
@@ -597,8 +605,9 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
if (!location.isFirstInstructionInBasicBlock()) {
return;
}
- if (invDataflow == null)
+ if (invDataflow == null) {
return;
+ }
BasicBlock fallThroughPredecessor = cfg.getPredecessorWithEdgeType(location.getBasicBlock(), EdgeTypes.FALL_THROUGH_EDGE);
if (fallThroughPredecessor == null || !fallThroughPredecessor.isNullCheck()) {
return;
@@ -610,22 +619,26 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
// Ignore dereferences of this
if (!methodGen.isStatic()) {
ValueNumber v = vnaFrame.getValue(0);
- if (v.equals(vn))
+ if (v.equals(vn)) {
return;
+ }
}
- if (vn.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))
+ if (vn.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
return;
+ }
IsNullValueFrame startFact = null;
startFact = invDataflow.getStartFact(fallThroughPredecessor);
- if (!startFact.isValid())
+ if (!startFact.isValid()) {
return;
+ }
int slot = startFact.getInstanceSlot(location.getHandle().getInstruction(), methodGen.getConstantPool());
- if (!reportDereference(startFact, slot))
+ if (!reportDereference(startFact, slot)) {
return;
+ }
if (DEBUG) {
System.out.println("FOUND GUARANTEED DEREFERENCE");
System.out.println("Load: " + vnaFrame.getLoad(vn));
@@ -646,12 +659,15 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
}
private static boolean reportDereference(IsNullValue value) {
- if (value.isDefinitelyNotNull())
+ if (value.isDefinitelyNotNull()) {
return false;
- if (value.isDefinitelyNull())
+ }
+ if (value.isDefinitelyNull()) {
return false;
- if (IGNORE_DEREF_OF_NCP && value.isNullOnComplicatedPath())
+ }
+ if (IGNORE_DEREF_OF_NCP && value.isNullOnComplicatedPath()) {
return false;
+ }
return true;
}
@@ -667,31 +683,17 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#copy(java.lang.Object,
- * java.lang.Object)
- */
+ @Override
public void copy(UnconditionalValueDerefSet source, UnconditionalValueDerefSet dest) {
dest.makeSameAs(source);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#createFact()
- */
+ @Override
public UnconditionalValueDerefSet createFact() {
return new UnconditionalValueDerefSet(vnaDataflow.getAnalysis().getNumValuesAllocated());
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#initEntryFact(java.lang.Object)
- */
+ @Override
public void initEntryFact(UnconditionalValueDerefSet result) throws DataflowAnalysisException {
result.clear();
}
@@ -704,43 +706,27 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
// result.setIsTop();
// }
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#makeFactTop(java.lang.Object)
- */
+ @Override
public void makeFactTop(UnconditionalValueDerefSet fact) {
fact.setIsTop();
}
+ @Override
public boolean isTop(UnconditionalValueDerefSet fact) {
return fact.isTop();
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#meetInto(java.lang.Object,
- * edu.umd.cs.findbugs.ba.Edge, java.lang.Object)
- */
+ @Override
public void meetInto(UnconditionalValueDerefSet fact, Edge edge, UnconditionalValueDerefSet result)
throws DataflowAnalysisException {
meetInto(fact, edge, result, false);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#meetInto(java.lang.Object,
- * edu.umd.cs.findbugs.ba.Edge, java.lang.Object)
- */
- public void meetInto(UnconditionalValueDerefSet fact, Edge edge, UnconditionalValueDerefSet result, boolean onlyEdge)
- {
-
+ public void meetInto(UnconditionalValueDerefSet fact, Edge edge, UnconditionalValueDerefSet result, boolean onlyEdge) {
if (isExceptionEdge(edge) && !onlyEdge) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Skipping exception edge");
+ }
return;
}
@@ -760,8 +746,10 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
Set<Integer> loopExitBranches = ClassContext.getLoopExitBranches(method, methodGen);
assert loopExitBranches != null;
boolean sourceIsTopOfLoop = edge.sourceIsTopOfLoop(loopExitBranches);
- if (sourceIsTopOfLoop && edge.getType() == EdgeTypes.FALL_THROUGH_EDGE)
+ if (sourceIsTopOfLoop && edge.getType() == EdgeTypes.FALL_THROUGH_EDGE) {
isBackEdge = true;
+ }
+ /*
if (false && (edge.getType() == EdgeTypes.IFCMP_EDGE || sourceIsTopOfLoop)) {
System.out.println("Meet into " + edge);
System.out.println(" foo2: " + sourceIsTopOfLoop);
@@ -771,11 +759,13 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
System.out.println(" Initial fact: " + result);
System.out.println(" Edge fact: " + fact);
}
+ */
if (result.isTop() || fact.isBottom()) {
// Make result identical to other fact
copy(fact, result);
- if (ASSUME_NONZERO_TRIP_LOOPS && isBackEdge && !fact.isTop())
+ if (ASSUME_NONZERO_TRIP_LOOPS && isBackEdge && !fact.isTop()) {
result.resultsFromBackEdge = true;
+ }
} else if (ASSUME_NONZERO_TRIP_LOOPS && isBackEdge && !fact.isTop()) {
result.unionWith(fact, vnaDataflow.getAnalysis().getFactory());
result.resultsFromBackEdge = true;
@@ -792,8 +782,9 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
if (ASSUME_NONZERO_TRIP_LOOPS && result.resultsFromBackEdge) {
result.backEdgeUpdateCount++;
if (result.backEdgeUpdateCount < 10) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\n Union update of " + System.identityHashCode(result) + " due to backedge info");
+ }
result.unionWith(fact, vnaDataflow.getAnalysis().getFactory());
return;
}
@@ -808,7 +799,6 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
if (DEBUG && isBackEdge && edge.getType() == EdgeTypes.IFCMP_EDGE) {
System.out.println(" result: " + result);
}
-
}
/**
@@ -833,10 +823,11 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
if (blockValueNumberFrame.isValid() && targetValueNumberFrame.isValid()) {
int slots = 0;
- if (targetValueNumberFrame.getNumSlots() == blockValueNumberFrame.getNumSlots())
+ if (targetValueNumberFrame.getNumSlots() == blockValueNumberFrame.getNumSlots()) {
slots = targetValueNumberFrame.getNumSlots();
- else if (targetValueNumberFrame.getNumLocals() == blockValueNumberFrame.getNumLocals())
+ } else if (targetValueNumberFrame.getNumLocals() == blockValueNumberFrame.getNumLocals()) {
slots = targetValueNumberFrame.getNumLocals();
+ }
if (slots > 0) {
if (DEBUG) {
@@ -848,28 +839,32 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
for (int i = 0; i < slots; i++) {
ValueNumber blockVN = blockValueNumberFrame.getValue(i);
ValueNumber targetVN = targetValueNumberFrame.getValue(i);
- if (blockVN.equals(targetVN))
+ if (blockVN.equals(targetVN)) {
continue;
+ }
fact.clearDerefSet(blockVN);
- if (originalFact.isUnconditionallyDereferenced(targetVN))
+ if (originalFact.isUnconditionallyDereferenced(targetVN)) {
fact.setDerefSet(blockVN, originalFact.getUnconditionalDerefLocationSet(targetVN));
+ }
} // for all slots
for (ValueNumber blockVN : blockValueNumberFrame.valueNumbersForLoads()) {
AvailableLoad load = blockValueNumberFrame.getLoad(blockVN);
- if (load == null)
+ if (load == null) {
continue;
+ }
ValueNumber[] targetVNs = targetValueNumberFrame.getAvailableLoad(load);
- if (targetVNs != null)
- for (ValueNumber targetVN : targetVNs)
+ if (targetVNs != null) {
+ for (ValueNumber targetVN : targetVNs) {
if (targetVN.hasFlag(ValueNumber.PHI_NODE) && fact.isUnconditionallyDereferenced(targetVN)
&& !fact.isUnconditionallyDereferenced(blockVN)) {
// Block VN is also dereferenced
// unconditionally.
AvailableLoad targetLoad = targetValueNumberFrame.getLoad(targetVN);
- if (!load.equals(targetLoad))
+ if (!load.equals(targetLoad)) {
continue;
+ }
if (DEBUG) {
System.out.println("** Copy vn derefs for " + load + " from " + targetVN + " --> " + blockVN);
System.out.println("** block phi for " + System.identityHashCode(blockValueNumberFrame)
@@ -880,6 +875,8 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
fact.setDerefSet(blockVN, fact.getUnconditionalDerefLocationSet(targetVN));
}
+ }
+ }
}
}
@@ -952,26 +949,24 @@ public class UnconditionalValueDerefAnalysis extends BackwardDataflowAnalysis<Un
private boolean isExceptionEdge(Edge edge) {
boolean isExceptionEdge = edge.isExceptionEdge();
if (isExceptionEdge) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("NOT Ignoring " + edge);
+ }
return true; // false
}
- if (edge.getType() != EdgeTypes.FALL_THROUGH_EDGE)
+ if (edge.getType() != EdgeTypes.FALL_THROUGH_EDGE) {
return false;
+ }
InstructionHandle h = edge.getSource().getLastInstruction();
- if (h != null && h.getInstruction() instanceof IFNONNULL && isNullCheck(h, methodGen.getConstantPool()))
+ if (h != null && h.getInstruction() instanceof IFNONNULL && isNullCheck(h, methodGen.getConstantPool())) {
return true;
+ }
return false;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#same(java.lang.Object,
- * java.lang.Object)
- */
+ @Override
public boolean same(UnconditionalValueDerefSet fact1, UnconditionalValueDerefSet fact2) {
return fact1.resultsFromBackEdge || fact1.isSameAs(fact2);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefDataflow.java b/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefDataflow.java
index 458f612..bab012b 100644
--- a/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefDataflow.java
@@ -24,15 +24,15 @@ import edu.umd.cs.findbugs.ba.CFG;
/**
* Dataflow to find value numbers unconditionally dereferenced.
- *
+ *
* @author David Hovemeyer
*/
public class UnconditionalValueDerefDataflow extends
- AbstractDataflow<UnconditionalValueDerefSet, UnconditionalValueDerefAnalysis> {
+AbstractDataflow<UnconditionalValueDerefSet, UnconditionalValueDerefAnalysis> {
/**
* Constructor.
- *
+ *
* @param cfg
* the control flow graph
* @param analysis
diff --git a/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefSet.java b/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefSet.java
index fca1e67..a8b020f 100644
--- a/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefSet.java
+++ b/src/java/edu/umd/cs/findbugs/ba/deref/UnconditionalValueDerefSet.java
@@ -39,18 +39,18 @@ import edu.umd.cs.findbugs.util.Util;
/**
* A set of values unconditionally dereferenced in the future.
- *
+ *
* @author David Hovemeyer
*/
public class UnconditionalValueDerefSet {
/** Number of distinct value numbers in method */
- private int numValueNumbersInMethod;
+ private final int numValueNumbersInMethod;
/** Set of value numbers unconditionally dereferenced */
- private BitSet valueNumbersUnconditionallyDereferenced;
+ private final BitSet valueNumbersUnconditionallyDereferenced;
/** Map of value numbers to locations */
- private Map<ValueNumber, Set<Location>> derefLocationSetMap;
+ private final Map<ValueNumber, Set<Location>> derefLocationSetMap;
boolean resultsFromBackEdge = false;
@@ -60,7 +60,7 @@ public class UnconditionalValueDerefSet {
/**
* Constructor.
- *
+ *
* @param numValueNumbersInMethod
* number of distinct value numbers in method
*/
@@ -73,7 +73,7 @@ public class UnconditionalValueDerefSet {
/**
* Is this the bottom value?
- *
+ *
* @return true if this is the bottom value, false otherwise
*/
public boolean isBottom() {
@@ -90,7 +90,7 @@ public class UnconditionalValueDerefSet {
/**
* Is this the top value?
- *
+ *
* @return true if this is the top value, false otherwise
*/
public boolean isTop() {
@@ -117,7 +117,7 @@ public class UnconditionalValueDerefSet {
/**
* Make this dataflow fact the same as the given one.
- *
+ *
* @param source
* another dataflow fact
*/
@@ -128,16 +128,17 @@ public class UnconditionalValueDerefSet {
lastUpdateTimestamp = source.lastUpdateTimestamp;
// Copy dereference locations for each value number
derefLocationSetMap.clear();
- if (source.derefLocationSetMap.size() > 0)
+ if (source.derefLocationSetMap.size() > 0) {
for (Map.Entry<ValueNumber, Set<Location>> sourceEntry : source.derefLocationSetMap.entrySet()) {
Set<Location> derefLocationSet = Util.makeSmallHashSet(sourceEntry.getValue());
derefLocationSetMap.put(sourceEntry.getKey(), derefLocationSet);
}
+ }
}
/**
* Return whether or not this dataflow fact is identical to the one given.
- *
+ *
* @param otherFact
* another dataflow fact
* @return true if the other dataflow fact is identical to this one, false
@@ -151,7 +152,7 @@ public class UnconditionalValueDerefSet {
/**
* Merge given dataflow fact into this one. We take the intersection of the
* unconditional deref value number set, and union the deref locations.
- *
+ *
* @param fact
* another dataflow fact
* @param skipMe
@@ -178,8 +179,9 @@ public class UnconditionalValueDerefSet {
// For each unconditionally dereferenced value...
for (int i = 0; i < numValueNumbersInMethod; i++) {
ValueNumber vn = valueNumberFactory.forNumber(i);
- if (vn.equals(skipMe))
+ if (vn.equals(skipMe)) {
continue;
+ }
Set<Location> factDerefLocationSet = fact.derefLocationSetMap.get(vn);
if (valueNumbersUnconditionallyDereferenced.get(i)) {
if (factDerefLocationSet != null && !factDerefLocationSet.isEmpty()) {
@@ -197,8 +199,9 @@ public class UnconditionalValueDerefSet {
// The value number is not in the fact:
// remove its location set
if (removed != null) {
- if (UnconditionalValueDerefAnalysis.DEBUG)
+ if (UnconditionalValueDerefAnalysis.DEBUG) {
System.out.println("Goodbye: " + removed);
+ }
}
}
}
@@ -232,7 +235,7 @@ public class UnconditionalValueDerefSet {
/**
* Mark a value as being dereferenced at given Location.
- *
+ *
* @param vn
* the value
* @param location
@@ -251,7 +254,7 @@ public class UnconditionalValueDerefSet {
/**
* Set a value as being unconditionally dereferenced at the given set of
* locations.
- *
+ *
* @param vn
* the value
* @param derefSet
@@ -270,7 +273,7 @@ public class UnconditionalValueDerefSet {
/**
* Clear the set of dereferences for given ValueNumber
- *
+ *
* @param value
* the ValueNumber
*/
@@ -284,7 +287,7 @@ public class UnconditionalValueDerefSet {
/**
* Get the set of dereference Locations for given value number.
- *
+ *
* @param vn
* the value number
* @return the set of dereference Locations
@@ -301,7 +304,7 @@ public class UnconditionalValueDerefSet {
/**
* Return whether or not the given value number is unconditionally
* dereferenced.
- *
+ *
* @param vn
* the value number
* @return true if the value is unconditionally dereferenced, false
@@ -314,8 +317,9 @@ public class UnconditionalValueDerefSet {
public Set<ValueNumber> getValueNumbersThatAreUnconditionallyDereferenced() {
HashSet<ValueNumber> result = new HashSet<ValueNumber>();
for (Map.Entry<ValueNumber, Set<Location>> e : derefLocationSetMap.entrySet()) {
- if (!e.getValue().isEmpty())
+ if (!e.getValue().isEmpty()) {
result.add(e.getKey());
+ }
}
return result;
}
@@ -334,7 +338,7 @@ public class UnconditionalValueDerefSet {
* Get the set of Locations where given value is guaranteed to be
* dereferenced. (I.e., if non-implicit-exception control paths are
* followed, one of these locations will be reached).
- *
+ *
* @param vn
* the value
* @return set of Locations, one of which will definitely be reached if
@@ -350,7 +354,7 @@ public class UnconditionalValueDerefSet {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
@@ -376,10 +380,11 @@ public class UnconditionalValueDerefSet {
}
buf.append('{');
buf.append(i);
- if (valueNumbersUnconditionallyDereferenced.get(i))
+ if (valueNumbersUnconditionallyDereferenced.get(i)) {
buf.append(':');
- else
+ } else {
buf.append('?');
+ }
TreeSet<Location> derefLocationSet = new TreeSet<Location>();
derefLocationSet.addAll(getDerefLocationSet(i));
boolean firstLoc = true;
@@ -417,7 +422,7 @@ public class UnconditionalValueDerefSet {
valueNumbers.addAll(vnaFrame.valueNumbersForLoads());
if (UnconditionalValueDerefAnalysis.DEBUG) {
- for (ValueNumber v : getValueNumbersThatAreUnconditionallyDereferenced())
+ for (ValueNumber v : getValueNumbersThatAreUnconditionallyDereferenced()) {
if (!valueNumbers.contains(v)) {
System.out.println("\nWhy is " + v + " unconditionally dereferenced in #" + System.identityHashCode(this));
System.out.println("VN: " + vnaFrame);
@@ -425,6 +430,7 @@ public class UnconditionalValueDerefSet {
System.out.println("Location: " + location);
System.out.println();
}
+ }
}
retainOnlyTheseValueNumbers(valueNumbers);
diff --git a/src/java/edu/umd/cs/findbugs/ba/generic/GenericObjectType.java b/src/java/edu/umd/cs/findbugs/ba/generic/GenericObjectType.java
index 4a06bbc..dfabd81 100644
--- a/src/java/edu/umd/cs/findbugs/ba/generic/GenericObjectType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/generic/GenericObjectType.java
@@ -72,18 +72,21 @@ public class GenericObjectType extends ObjectType {
@Override
public boolean equals(Object o) {
- if (!(o instanceof GenericObjectType))
+ if (!(o instanceof GenericObjectType)) {
return false;
- if (!super.equals(o))
+ }
+ if (!super.equals(o)) {
return false;
+ }
GenericObjectType that = (GenericObjectType) o;
return Util.nullSafeEquals(this.parameters, that.parameters) && Util.nullSafeEquals(this.variable, that.variable)
&& Util.nullSafeEquals(this.extension, that.extension);
}
public Type getUpperBound() {
- if ("+".equals(variable))
+ if ("+".equals(variable)) {
return extension;
+ }
return this;
}
@@ -111,16 +114,18 @@ public class GenericObjectType extends ObjectType {
return GenericUtilities.TypeCategory.PARAMETERIZED;
} else if (!hasParameters() && variable != null && extension == null) {
- if (variable.equals("*"))
+ if ("*".equals(variable)) {
return GenericUtilities.TypeCategory.WILDCARD;
- else
+ } else {
return GenericUtilities.TypeCategory.TYPE_VARIABLE;
+ }
} else if (!hasParameters() && variable != null && extension != null) {
- if (variable.equals("+"))
+ if ("+".equals(variable)) {
return GenericUtilities.TypeCategory.WILDCARD_EXTENDS;
- else if (variable.equals("-"))
+ } else if ("-".equals(variable)) {
return GenericUtilities.TypeCategory.WILDCARD_SUPER;
+ }
}
// this should never happen
@@ -150,16 +155,18 @@ public class GenericObjectType extends ObjectType {
* @return the type parameter at index
*/
public ReferenceType getParameterAt(int index) {
- if (index < getNumParameters())
+ if (index < getNumParameters()) {
return parameters.get(index);
- else
+ } else {
throw new IndexOutOfBoundsException("The index " + index + " is too large for " + this);
+ }
}
public @CheckForNull
List<? extends ReferenceType> getParameters() {
- if (parameters == null)
+ if (parameters == null) {
return null;
+ }
return Collections.unmodifiableList(parameters);
}
@@ -202,8 +209,9 @@ public class GenericObjectType extends ObjectType {
super(DescriptorFactory.canonicalizeString(class_name));
variable = null;
extension = null;
- if (parameters == null || parameters.size() == 0)
+ if (parameters == null || parameters.size() == 0) {
throw new IllegalStateException("argument 'parameters' must contain at least 1 parameter");
+ }
this.parameters = parameters;
}
@@ -247,8 +255,9 @@ public class GenericObjectType extends ObjectType {
}
public String getGenericParametersAsString() {
- if (getTypeCategory() != GenericUtilities.TypeCategory.PARAMETERIZED)
+ if (getTypeCategory() != GenericUtilities.TypeCategory.PARAMETERIZED) {
throw new IllegalStateException(toString() + " doesn't have generic parameters");
+ }
String baseStringValue = super.toString();
String fullStringValue = toString();
return fullStringValue.substring(baseStringValue.length());
diff --git a/src/java/edu/umd/cs/findbugs/ba/generic/GenericSignatureParser.java b/src/java/edu/umd/cs/findbugs/ba/generic/GenericSignatureParser.java
index 0acc936..7824b79 100644
--- a/src/java/edu/umd/cs/findbugs/ba/generic/GenericSignatureParser.java
+++ b/src/java/edu/umd/cs/findbugs/ba/generic/GenericSignatureParser.java
@@ -36,22 +36,25 @@ import org.apache.bcel.generic.Type;
/**
* A simple class to parse method signatures that include generic information.
* <p>
- *
+ *
* Modified from edu.umd.cs.findbugs.ba.SignatureParser
- *
+ *
* @author Nat Ayewah
*/
public class GenericSignatureParser {
private class ParameterSignatureIterator implements Iterator<String> {
private int index = 1;
+ @Override
public boolean hasNext() {
return index < signature.length() && signature.charAt(index) != ')' && signature.charAt(index) != '^';
}
+ @Override
public String next() {
- if (!hasNext())
+ if (!hasNext()) {
throw new NoSuchElementException();
+ }
StringBuilder result = new StringBuilder();
boolean done;
do {
@@ -81,8 +84,9 @@ public class GenericSignatureParser {
char c = signature.charAt(i);
switch (c) {
case ';':
- if (leftCount == 0)
+ if (leftCount == 0) {
break loop;
+ }
break;
case '<':
leftCount++;
@@ -119,6 +123,7 @@ public class GenericSignatureParser {
return result.toString();
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -129,7 +134,7 @@ public class GenericSignatureParser {
/**
* Parses a generic method signature of the form:
* <code>(argument_signature)return_type_signature</code>
- *
+ *
* @param signature
* the method signature to be parsed
*/
@@ -138,16 +143,17 @@ public class GenericSignatureParser {
// method definitions
int s = signature.indexOf('(');
String sig = signature;
- if (s > 0)
+ if (s > 0) {
sig = sig.substring(s);
- else if (s < 0 || sig.indexOf(':') >= 0 || sig.startsWith("(V)"))
+ } else if (s < 0 || sig.indexOf(':') >= 0 || sig.startsWith("(V)")) {
throw new IllegalArgumentException("Bad method signature: " + signature);
+ }
this.signature = sig;
}
/**
* Get an Iterator over signatures of the method parameters.
- *
+ *
* @return Iterator which returns the parameter type signatures in order
*/
public Iterator<String> parameterSignatureIterator() {
@@ -156,19 +162,20 @@ public class GenericSignatureParser {
/**
* Get the method return type signature.
- *
+ *
* @return the method return type signature
*/
public String getReturnTypeSignature() {
int endOfParams = signature.lastIndexOf(')');
- if (endOfParams < 0)
+ if (endOfParams < 0) {
throw new IllegalArgumentException("Bad method signature: " + signature);
+ }
return signature.substring(endOfParams + 1);
}
/**
* Get the number of parameters in the signature.
- *
+ *
* @return the number of parameters
*/
public int getNumParameters() {
@@ -182,7 +189,7 @@ public class GenericSignatureParser {
/**
* Get the number of parameters passed to method invocation.
- *
+ *
* @param inv
* @param cpg
* @return int number of parameters
@@ -215,14 +222,15 @@ public class GenericSignatureParser {
System.out.println(sig.getSignature());
}
return null; // we've seen two inconsistent
- // signatures
+ // signatures
}
continue;
}
genericSignature = sig.getSignature();
- if (compareSignatures(target.getSignature(), genericSignature))
+ if (compareSignatures(target.getSignature(), genericSignature)) {
parser = new GenericSignatureParser(genericSignature);
+ }
}
}
Iterator<String> iter = parser == null ? null : parser.parameterSignatureIterator();
@@ -240,8 +248,9 @@ public class GenericSignatureParser {
GenericSignatureParser plainParser = new GenericSignatureParser(plainSignature);
GenericSignatureParser genericParser = new GenericSignatureParser(genericSignature);
- if (plainParser.getNumParameters() != genericParser.getNumParameters())
+ if (plainParser.getNumParameters() != genericParser.getNumParameters()) {
return false;
+ }
return true;
}
@@ -257,10 +266,12 @@ public class GenericSignatureParser {
System.out.println(s);
Type t = GenericUtilities.getType(s);
System.out.println("-~- " + t);
- if (t instanceof ObjectType)
+ if (t instanceof ObjectType) {
System.out.println("-~- " + ((ObjectType) t).toString());
- if (t != null)
+ }
+ if (t != null) {
System.out.println("-~- " + t.getClass());
+ }
}
System.out.println(parser.getNumParameters() + " parameter(s)");
diff --git a/src/java/edu/umd/cs/findbugs/ba/generic/GenericUtilities.java b/src/java/edu/umd/cs/findbugs/ba/generic/GenericUtilities.java
index e5a0f66..977ecc5 100644
--- a/src/java/edu/umd/cs/findbugs/ba/generic/GenericUtilities.java
+++ b/src/java/edu/umd/cs/findbugs/ba/generic/GenericUtilities.java
@@ -85,8 +85,9 @@ public class GenericUtilities {
b.append("<");
boolean first = true;
for (Type t : obj.parameters) {
- if (!first)
+ if (!first) {
b.append(",");
+ }
first = false;
b.append(GenericUtilities.getString(t));
}
@@ -184,14 +185,17 @@ public class GenericUtilities {
* @see GenericUtilities.TypeCategory
*/
public static final TypeCategory getTypeCategory(Type type) {
- if (type instanceof GenericObjectType)
+ if (type instanceof GenericObjectType) {
return ((GenericObjectType) type).getTypeCategory();
+ }
- if (type instanceof ObjectType || type instanceof NullType)
+ if (type instanceof ObjectType || type instanceof NullType) {
return TypeCategory.PLAIN_OBJECT_TYPE;
+ }
- if (type instanceof ArrayType)
+ if (type instanceof ArrayType) {
return TypeCategory.ARRAY_TYPE;
+ }
throw new IllegalArgumentException("Not a reference type: " + type);
}
@@ -204,17 +208,19 @@ public class GenericUtilities {
* Get String representation of a Type including Generic information
*/
public static final String getString(Type type) {
- if (type instanceof GenericObjectType)
+ if (type instanceof GenericObjectType) {
return ((GenericObjectType) type).toString(true);
- else if (type instanceof ArrayType)
+ } else if (type instanceof ArrayType) {
return TypeCategory.asString((ArrayType) type);
- else
+ } else {
return type.toString();
+ }
}
static String stripAngleBrackets(String s) {
- if (s.indexOf('<') == -1)
+ if (s.indexOf('<') == -1) {
return s;
+ }
StringBuilder result = new StringBuilder(s.length());
int nesting = 0;
boolean seenLeftBracket = false;
@@ -223,13 +229,14 @@ public class GenericUtilities {
if (c == '<') {
nesting++;
seenLeftBracket = true;
- } else if (c == '>')
+ } else if (c == '>') {
nesting--;
- else if (nesting == 0) {
- if (seenLeftBracket && c == '.')
+ } else if (nesting == 0) {
+ if (seenLeftBracket && c == '.') {
result.append('$');
- else
+ } else {
result.append(c);
+ }
}
}
return result.toString();
@@ -252,48 +259,62 @@ public class GenericUtilities {
public static @CheckForNull
Type getType(String signature) {
try {
- // ensure signature only has one type
- if (new GenericSignatureParser("(" + signature + ")V").getNumParameters() != 1)
- throw new IllegalArgumentException("the following signature does not " + "contain exactly one type: " + signature);
- int index = 0;
-
- if (signature.startsWith("L")) {
- index = lastMatchedLeftAngleBracket(signature);
- if (index < 0)
- return Type.getType(stripAngleBrackets(signature));
-
- String typeParameters = signature.substring(index + 1, nextUnmatchedRightAngleBracket(signature, index + 1));
- List<ReferenceType> parameters = GenericUtilities.getTypeParameters(typeParameters);
- if (parameters == null)
- return null;
- String baseType = removeMatchedAngleBrackets(signature.substring(1, index)).replace('.', '$');
- return new GenericObjectType(baseType, parameters);
+ // ensure signature only has one type
+ if (new GenericSignatureParser("(" + signature + ")V").getNumParameters() != 1) {
+ throw new IllegalArgumentException("the following signature does not " + "contain exactly one type: " + signature);
+ }
+ int index = 0;
- } else if (signature.startsWith("T")) {
- // can't handle type variables
- return null;
+ if (signature.startsWith("L")) {
+ index = lastMatchedLeftAngleBracket(signature);
+ if (index < 0) {
+ return Type.getType(stripAngleBrackets(signature));
+ }
- } else if (signature.startsWith("[")) {
- index++;
- while (signature.charAt(index) == '[')
- index++;
- Type componentType = getType(signature.substring(index));
- if (componentType == null)
+ String typeParameters = signature.substring(index + 1, nextUnmatchedRightAngleBracket(signature, index + 1));
+ List<ReferenceType> parameters = GenericUtilities.getTypeParameters(typeParameters);
+ if (parameters == null) {
+ return null;
+ }
+ String baseType = removeMatchedAngleBrackets(signature.substring(1, index)).replace('.', '$');
+ return new GenericObjectType(baseType, parameters);
+
+ } else if (signature.startsWith("T")) {
+ int i = signature.indexOf(';');
+ if (i > 0) {
+ String var = signature.substring(1, i);
+ if (var.indexOf('<') == -1) {
+ return new GenericObjectType(var);
+ }
+ }
+ // can't handle type variables
return null;
- return new ArrayType(componentType, index);
- } else if (signature.startsWith("*")) {
- return new GenericObjectType("*");
+ } else if (signature.startsWith("[")) {
+ index++;
+ while (signature.charAt(index) == '[') {
+ index++;
+ }
+ Type componentType = getType(signature.substring(index));
+ if (componentType == null) {
+ return null;
+ }
+ return new ArrayType(componentType, index);
+
+ } else if (signature.startsWith("*")) {
+ return new GenericObjectType("*");
- } else if (signature.startsWith("+") || signature.startsWith("-")) {
- Type baseType = getType(signature.substring(1));
- if (baseType == null)
- return null;
- return new GenericObjectType(signature.substring(0, 1), (ReferenceType) baseType);
+ } else if (signature.startsWith("+") || signature.startsWith("-")) {
+ Type baseType = getType(signature.substring(1));
+ if (baseType == null) {
+ return null;
+ }
+ return new GenericObjectType(signature.substring(0, 1), (ReferenceType) baseType);
- } else
- // assert signature contains no generic information
- return Type.getType(signature);
+ } else {
+ // assert signature contains no generic information
+ return Type.getType(signature);
+ }
} catch (IllegalStateException e) {
AnalysisContext.logError("Error parsing signature " + signature, e);
return null;
@@ -301,45 +322,53 @@ public class GenericUtilities {
}
public static ObjectType merge(@CheckForNull Type t1, ObjectType t2) {
- if (t1 instanceof GenericObjectType)
+ if (t1 instanceof GenericObjectType) {
return merge((GenericObjectType) t1, t2);
+ }
return t2;
}
public static Type merge(@CheckForNull GenericObjectType t1, Type t2) {
- if (t1 == null)
+ if (t1 == null) {
return t2;
- if (t2 instanceof ObjectType)
+ }
+ if (t2 instanceof ObjectType) {
return merge(t1,(ObjectType) t2);
- if (t2 instanceof NullType)
+ }
+ if (t2 instanceof NullType) {
return t1;
+ }
return t2;
}
public static ObjectType merge(@CheckForNull GenericObjectType t1, ObjectType t2) {
- if (t1 == null || t2 instanceof GenericObjectType)
+ if (t1 == null || t2 instanceof GenericObjectType) {
return t2;
+ }
List<? extends ReferenceType> parameters = t1.getParameters();
- if (parameters == null)
+ if (parameters == null) {
return t2;
+ }
return new GenericObjectType(t2.getClassName(), parameters);
}
public static String removeMatchedAngleBrackets(String s) {
int first = s.indexOf('<');
- if (first < 0)
+ if (first < 0) {
return s;
+ }
StringBuilder result = new StringBuilder(s.substring(0, first));
int pos = first;
int nesting = 0;
while (pos < s.length()) {
char c = s.charAt(pos++);
- if (c == '<')
+ if (c == '<') {
nesting++;
- else if (c == '>')
+ } else if (c == '>') {
nesting--;
- else if (nesting == 0)
+ } else if (nesting == 0) {
result.append(c);
+ }
}
return result.toString();
@@ -350,15 +379,18 @@ public class GenericUtilities {
int pos = startingAt;
while (true) {
- if (pos < 0)
+ if (pos < 0) {
return -1;
+ }
char c = s.charAt(pos);
if (c == '>') {
- if (nesting == 0)
+ if (nesting == 0) {
return pos;
+ }
nesting--;
- } else if (c == '<')
+ } else if (c == '<') {
nesting++;
+ }
pos++;
}
}
@@ -368,17 +400,20 @@ public class GenericUtilities {
int pos = s.length() - 2;
while (true) {
- if (pos < 0)
+ if (pos < 0) {
return -1;
+ }
char c = s.charAt(pos);
if (c == '<') {
nesting--;
- if (nesting == 0)
+ if (nesting == 0) {
return pos;
- } else if (c == '>')
+ }
+ } else if (c == '>') {
nesting++;
- else if (nesting == 0)
+ } else if (nesting == 0) {
return -1;
+ }
pos--;
}
}
@@ -400,8 +435,9 @@ public class GenericUtilities {
while (iter.hasNext()) {
String parameterString = iter.next();
ReferenceType t = (ReferenceType) getType(parameterString);
- if (t == null)
+ if (t == null) {
return null;
+ }
types.add(t);
}
return types;
@@ -409,11 +445,12 @@ public class GenericUtilities {
public static final List<String> split(String signature, boolean skipInitialAngleBracket) {
List<String> result = new ArrayList<String>();
- if (signature.charAt(0) != '<')
+ if (signature.charAt(0) != '<') {
skipInitialAngleBracket = false;
+ }
int depth = 0;
int start = 0;
- for (int pos = start; pos < signature.length(); pos++)
+ for (int pos = start; pos < signature.length(); pos++) {
switch (signature.charAt(pos)) {
case '<':
depth++;
@@ -426,14 +463,20 @@ public class GenericUtilities {
}
break;
case ';':
- if (depth > 0)
+ if (depth > 0) {
break;
+ }
String substring = signature.substring(start, pos + 1);
result.add(substring);
start = pos + 1;
+ break;
+ default:
+ break;
}
- if (depth != 0)
+ }
+ if (depth != 0) {
throw new IllegalArgumentException("Unbalanced signature: " + signature);
+ }
return result;
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/heap/FieldSet.java b/src/java/edu/umd/cs/findbugs/ba/heap/FieldSet.java
index 59e2bfd..5eee796 100644
--- a/src/java/edu/umd/cs/findbugs/ba/heap/FieldSet.java
+++ b/src/java/edu/umd/cs/findbugs/ba/heap/FieldSet.java
@@ -30,7 +30,7 @@ import edu.umd.cs.findbugs.ba.XField;
public class FieldSet {
private boolean isTop, isBottom;
- private Set<XField> fieldSet;
+ private final Set<XField> fieldSet;
public FieldSet() {
fieldSet = new HashSet<XField>();
@@ -68,8 +68,9 @@ public class FieldSet {
}
public void addField(XField field) {
- if (!isValid())
+ if (!isValid()) {
throw new IllegalStateException();
+ }
fieldSet.add(field);
}
@@ -78,8 +79,9 @@ public class FieldSet {
}
public void mergeWith(FieldSet other) {
- if (other.isTop() || this.isBottom())
+ if (other.isTop() || this.isBottom()) {
return;
+ }
if (other.isBottom() || this.isTop()) {
this.copyFrom(other);
@@ -102,19 +104,21 @@ public class FieldSet {
public boolean isIntersectionNonEmpty(FieldSet other) {
for (XField field : fieldSet) {
- if (other.fieldSet.contains(field))
+ if (other.fieldSet.contains(field)) {
return true;
+ }
}
return false;
}
@Override
public String toString() {
- if (isTop)
+ if (isTop) {
return "TOP";
- else if (isBottom)
+ } else if (isBottom) {
return "BOTTOM";
- else
+ } else {
return fieldSet.toString();
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/heap/FieldSetAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/heap/FieldSetAnalysis.java
index 1529896..58a0387 100644
--- a/src/java/edu/umd/cs/findbugs/ba/heap/FieldSetAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/heap/FieldSetAnalysis.java
@@ -42,9 +42,9 @@ import edu.umd.cs.findbugs.ba.XField;
* @author David Hovemeyer
*/
public abstract class FieldSetAnalysis extends ForwardDataflowAnalysis<FieldSet> {
- private ConstantPoolGen cpg;
+ private final ConstantPoolGen cpg;
- private Map<InstructionHandle, XField> instructionToFieldMap;
+ private final Map<InstructionHandle, XField> instructionToFieldMap;
public FieldSetAnalysis(DepthFirstSearch dfs, ConstantPoolGen cpg) {
super(dfs);
@@ -56,14 +56,17 @@ public abstract class FieldSetAnalysis extends ForwardDataflowAnalysis<FieldSet>
return cpg;
}
+ @Override
public void makeFactTop(FieldSet fact) {
fact.setTop();
}
+ @Override
public boolean isTop(FieldSet fact) {
return fact.isTop();
}
+ @Override
public void initEntryFact(FieldSet result) throws DataflowAnalysisException {
result.clear();
}
@@ -72,14 +75,17 @@ public abstract class FieldSetAnalysis extends ForwardDataflowAnalysis<FieldSet>
// makeFactTop(result);
// }
+ @Override
public void meetInto(FieldSet fact, Edge edge, FieldSet result) throws DataflowAnalysisException {
result.mergeWith(fact);
}
+ @Override
public boolean same(FieldSet fact1, FieldSet fact2) {
return fact1.sameAs(fact2);
}
+ @Override
public FieldSet createFact() {
return new FieldSet();
}
@@ -89,6 +95,7 @@ public abstract class FieldSetAnalysis extends ForwardDataflowAnalysis<FieldSet>
return fact.isValid();
}
+ @Override
public void copy(FieldSet source, FieldSet dest) {
dest.copyFrom(source);
}
@@ -96,15 +103,16 @@ public abstract class FieldSetAnalysis extends ForwardDataflowAnalysis<FieldSet>
@Override
public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, FieldSet fact)
throws DataflowAnalysisException {
- if (!isFactValid(fact))
+ if (!isFactValid(fact)) {
return;
+ }
handleInstruction(handle, basicBlock, fact);
-
+
}
private void handleInstruction(InstructionHandle handle, BasicBlock basicBlock, FieldSet fact)
- {
+ {
Instruction ins = handle.getInstruction();
short opcode = ins.getOpcode();
XField field;
@@ -134,6 +142,8 @@ public abstract class FieldSetAnalysis extends ForwardDataflowAnalysis<FieldSet>
// possible fields
fact.setBottom();
break;
+ default:
+ break;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/heap/StoreAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/heap/StoreAnalysis.java
index d078cef..06ca491 100644
--- a/src/java/edu/umd/cs/findbugs/ba/heap/StoreAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/heap/StoreAnalysis.java
@@ -34,7 +34,7 @@ public class StoreAnalysis extends FieldSetAnalysis {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.heap.FieldSetAnalysis#sawLoad(edu.umd.cs.findbugs
* .ba.heap.FieldSet, edu.umd.cs.findbugs.ba.XField)
@@ -46,7 +46,7 @@ public class StoreAnalysis extends FieldSetAnalysis {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.heap.FieldSetAnalysis#sawStore(edu.umd.cs.findbugs
* .ba.heap.FieldSet, edu.umd.cs.findbugs.ba.XField)
diff --git a/src/java/edu/umd/cs/findbugs/ba/interproc/FieldPropertyDatabase.java b/src/java/edu/umd/cs/findbugs/ba/interproc/FieldPropertyDatabase.java
index 190c806..b927f26 100644
--- a/src/java/edu/umd/cs/findbugs/ba/interproc/FieldPropertyDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/interproc/FieldPropertyDatabase.java
@@ -32,14 +32,14 @@ import edu.umd.cs.findbugs.util.ClassName;
/**
* Interprocedural field property database.
- *
+ *
* @author David Hovemeyer
*/
public abstract class FieldPropertyDatabase<Property> extends PropertyDatabase<FieldDescriptor, Property> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.interproc.PropertyDatabase#parseKey(java.lang.
* String)
@@ -67,7 +67,7 @@ public abstract class FieldPropertyDatabase<Property> extends PropertyDatabase<F
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.interproc.PropertyDatabase#writeKey(java.io.Writer
* , KeyType)
diff --git a/src/java/edu/umd/cs/findbugs/ba/interproc/MethodPropertyDatabase.java b/src/java/edu/umd/cs/findbugs/ba/interproc/MethodPropertyDatabase.java
index c615f56..c86bb75 100644
--- a/src/java/edu/umd/cs/findbugs/ba/interproc/MethodPropertyDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/interproc/MethodPropertyDatabase.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.util.ClassName;
/**
* A MethodPropertyDatabase keeps track of properties of methods. This is useful
* for implementing interprocedural analyses.
- *
+ *
* @author David Hovemeyer
*/
public abstract class MethodPropertyDatabase<Property> extends PropertyDatabase<MethodDescriptor, Property> {
@@ -40,8 +40,9 @@ public abstract class MethodPropertyDatabase<Property> extends PropertyDatabase<
@Override
protected MethodDescriptor parseKey(String methodStr) throws PropertyDatabaseFormatException {
String[] tuple = methodStr.split(",");
- if (tuple.length != 4)
+ if (tuple.length != 4) {
throw new PropertyDatabaseFormatException("Invalid method tuple: " + methodStr);
+ }
try {
int accessFlags = Integer.parseInt(tuple[3]);
diff --git a/src/java/edu/umd/cs/findbugs/ba/interproc/ParameterProperty.java b/src/java/edu/umd/cs/findbugs/ba/interproc/ParameterProperty.java
index 52edc2c..3261035 100644
--- a/src/java/edu/umd/cs/findbugs/ba/interproc/ParameterProperty.java
+++ b/src/java/edu/umd/cs/findbugs/ba/interproc/ParameterProperty.java
@@ -24,7 +24,7 @@ import java.util.Iterator;
/**
* Method property recording which parameters are have some property
* (originally, which were required to be nonnull, now made more generic)
- *
+ *
* @author David Hovemeyer
*/
public class ParameterProperty {
@@ -52,7 +52,7 @@ public class ParameterProperty {
/**
* Get the non-null param bitset.
- *
+ *
* @return the non-null param bitset
*/
public int getParamsWithProperty() {
@@ -62,6 +62,7 @@ public class ParameterProperty {
public Iterable<Integer> iterable() {
return new Iterable<Integer>() {
+ @Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
int nextInt = 0;
@@ -70,16 +71,20 @@ public class ParameterProperty {
}
private void advanceNextInt() {
- while (!hasProperty(nextInt) && nextInt < 32)
+ while (!hasProperty(nextInt) && nextInt < 32) {
nextInt++;
- if (nextInt >= 32)
+ }
+ if (nextInt >= 32) {
nextInt = -1;
+ }
}
+ @Override
public boolean hasNext() {
return nextInt >= 0;
}
+ @Override
public Integer next() {
int result = nextInt;
nextInt++;
@@ -87,6 +92,7 @@ public class ParameterProperty {
return result;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
@@ -99,7 +105,7 @@ public class ParameterProperty {
/**
* Set the non-null param bitset.
- *
+ *
* @param nonNullParamSet
* the non-null param bitset
*/
@@ -109,7 +115,7 @@ public class ParameterProperty {
/**
* Set the non-null param set from given BitSet.
- *
+ *
* @param nonNullSet
* BitSet indicating which parameters are non-null
*/
@@ -121,15 +127,16 @@ public class ParameterProperty {
/**
* Set whether or not a parameter might be non-null.
- *
+ *
* @param param
* the parameter index
* @param hasProperty
* true if the parameter might be non-null, false otherwise
*/
public void setParamWithProperty(int param, boolean hasProperty) {
- if (param < 0 || param > 31)
+ if (param < 0 || param > 31) {
return;
+ }
if (hasProperty) {
bits |= (1 << param);
} else {
@@ -139,23 +146,24 @@ public class ParameterProperty {
/**
* Return whether or not a parameter might be non-null.
- *
+ *
* @param param
* the parameter index
* @return true if the parameter might be non-null, false otherwise
*/
public boolean hasProperty(int param) {
- if (param < 0 || param > 31)
+ if (param < 0 || param > 31) {
return false;
- else
+ } else {
return (bits & (1 << param)) != 0;
+ }
}
/**
* Given a bitset of null arguments passed to the method represented by this
* property, return a bitset indicating which null arguments correspond to
* an non-null param.
- *
+ *
* @param nullArgSet
* bitset of null arguments
* @return bitset intersecting null arguments and non-null params
@@ -170,8 +178,9 @@ public class ParameterProperty {
public BitSet getAsBitSet() {
BitSet result = new BitSet();
- if (isEmpty())
+ if (isEmpty()) {
return result;
+ }
for (int i = 0; i < 32; ++i) {
result.set(i, hasProperty(i));
}
@@ -180,7 +189,7 @@ public class ParameterProperty {
/**
* Return whether or not the set of non-null parameters is empty.
- *
+ *
* @return true if the set is empty, false if it contains at least one
* parameter
*/
@@ -195,8 +204,9 @@ public class ParameterProperty {
buf.append('{');
for (int i = 0; i < 32; ++i) {
if (hasProperty(i)) {
- if (buf.length() > 1)
+ if (buf.length() > 1) {
buf.append(',');
+ }
buf.append(i);
}
}
@@ -208,7 +218,7 @@ public class ParameterProperty {
/**
* Intersect this set with the given set. Useful for summarizing the
* properties of multiple methods.
- *
+ *
* @param targetDerefParamSet
* another set
*/
@@ -218,7 +228,7 @@ public class ParameterProperty {
/**
* Make this object the same as the given one.
- *
+ *
* @param other
* another ParameterNullnessProperty
*/
diff --git a/src/java/edu/umd/cs/findbugs/ba/interproc/PropertyDatabase.java b/src/java/edu/umd/cs/findbugs/ba/interproc/PropertyDatabase.java
index 71a64c9..bdfe77a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/interproc/PropertyDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/interproc/PropertyDatabase.java
@@ -53,7 +53,7 @@ import edu.umd.cs.findbugs.util.Util;
* @author David Hovemeyer
*/
public abstract class PropertyDatabase<KeyType extends FieldOrMethodDescriptor, ValueType> {
- private Map<KeyType, ValueType> propertyMap;
+ private final Map<KeyType, ValueType> propertyMap;
/**
* Constructor. Creates an empty property database.
@@ -144,8 +144,9 @@ public abstract class PropertyDatabase<KeyType extends FieldOrMethodDescriptor,
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
- if (line.equals(""))
+ if ("".equals(line)) {
continue;
+ }
int bar = line.indexOf('|');
if (bar < 0) {
throw new PropertyDatabaseFormatException("Invalid property database: missing separator");
@@ -157,8 +158,9 @@ public abstract class PropertyDatabase<KeyType extends FieldOrMethodDescriptor,
}
} finally {
try {
- if (reader != null)
+ if (reader != null) {
reader.close();
+ }
} catch (IOException e) {
// Ignore
}
@@ -222,8 +224,9 @@ public abstract class PropertyDatabase<KeyType extends FieldOrMethodDescriptor,
AnalysisContext.currentAnalysisContext().setMissingClassWarningsSuppressed(missingClassWarningsSuppressed);
try {
- if (writer != null)
+ if (writer != null) {
writer.close();
+ }
} catch (IOException e) {
// Ignore
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/Analysis.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/Analysis.java
index 73fe1f6..d1c2d4d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/Analysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/Analysis.java
@@ -37,8 +37,8 @@ import edu.umd.cs.findbugs.ba.Location;
import edu.umd.cs.findbugs.ba.SignatureParser;
import edu.umd.cs.findbugs.ba.XFactory;
import edu.umd.cs.findbugs.ba.XMethod;
-import edu.umd.cs.findbugs.ba.ch.InheritanceGraphVisitor;
import edu.umd.cs.findbugs.ba.ch.OverriddenMethodsVisitor;
+import edu.umd.cs.findbugs.ba.ch.SupertypeTraversalVisitor;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.classfile.IAnalysisCache;
@@ -122,7 +122,7 @@ public class Analysis {
// Instance method - must consider type qualifiers inherited
// from superclasses
- InheritanceGraphVisitor visitor = new OverriddenMethodsVisitor(xmethod) {
+ SupertypeTraversalVisitor visitor = new OverriddenMethodsVisitor(xmethod) {
/*
* (non-Javadoc)
*
@@ -139,13 +139,13 @@ public class Analysis {
try {
AnalysisContext.currentAnalysisContext().getSubtypes2()
- .traverseSupertypes(xmethod.getClassDescriptor(), visitor);
+ .traverseSupertypesDepthFirst(xmethod.getClassDescriptor(), visitor);
} catch (ClassNotFoundException e) {
AnalysisContext.currentAnalysisContext().getLookupFailureCallback().reportMissingClass(e);
return Collections.<TypeQualifierValue<?>> emptySet();
} catch (UncheckedAnalysisException e) {
AnalysisContext.currentAnalysisContext().getLookupFailureCallback()
- .logError("Error getting relevant type qualifiers for " + xmethod.toString(), e);
+ .logError("Error getting relevant type qualifiers for " + xmethod.toString(), e);
return Collections.<TypeQualifierValue<?>> emptySet();
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflow.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflow.java
index fb44fc2..91ef98e 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflow.java
@@ -23,14 +23,14 @@ import edu.umd.cs.findbugs.ba.CFG;
/**
* Dataflow class for BackwardTypeQualifierDataflowAnalysis.
- *
+ *
* @author David Hovemeyer
*/
public class BackwardTypeQualifierDataflow extends TypeQualifierDataflow<BackwardTypeQualifierDataflowAnalysis> {
/**
* Constructor.
- *
+ *
* @param cfg
* CFG for analyzed method
* @param analysis
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflowAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflowAnalysis.java
index 65cc80c..6f903e1 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflowAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflowAnalysis.java
@@ -139,10 +139,12 @@ public class BackwardTypeQualifierDataflowAnalysis extends TypeQualifierDataflow
}
}
+ @Override
public BlockOrder getBlockOrder(CFG cfg1) {
return new ReverseDFSOrder(cfg1, rdfs, dfs);
}
+ @Override
public boolean isForwards() {
return false;
}
@@ -213,8 +215,9 @@ public class BackwardTypeQualifierDataflowAnalysis extends TypeQualifierDataflow
XMethod calledMethod = XFactory.createXMethod(inv, cpg);
SignatureParser sigParser = new SignatureParser(calledMethod.getSignature());
- if (sigParser.getNumParameters() == 0)
+ if (sigParser.getNumParameters() == 0) {
return;
+ }
ValueNumberFrame vnaFrame = vnaDataflow.getFactAtLocation(location);
if (!vnaFrame.isValid()) {
@@ -224,8 +227,9 @@ public class BackwardTypeQualifierDataflowAnalysis extends TypeQualifierDataflow
return;
}
- if (TypeQualifierDataflowAnalysis.isIdentifyFunctionForTypeQualifiers(calledMethod))
+ if (TypeQualifierDataflowAnalysis.isIdentifyFunctionForTypeQualifiers(calledMethod)) {
return;
+ }
for (int param = 0; param < calledMethod.getNumParams(); param++) {
TypeQualifierAnnotation tqa = TypeQualifierApplications.getEffectiveTypeQualifierAnnotation(calledMethod, param,
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflowFactory.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflowFactory.java
index ee6d101..8ca7b1f 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/BackwardTypeQualifierDataflowFactory.java
@@ -43,7 +43,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
* @author David Hovemeyer
*/
public class BackwardTypeQualifierDataflowFactory extends
- TypeQualifierDataflowFactory<BackwardTypeQualifierDataflowAnalysis, BackwardTypeQualifierDataflow> {
+TypeQualifierDataflowFactory<BackwardTypeQualifierDataflowAnalysis, BackwardTypeQualifierDataflow> {
/**
* Constructor.
@@ -105,8 +105,9 @@ public class BackwardTypeQualifierDataflowFactory extends
// back to the entry of the method.
// This will contain the effective type qualifier
// annotations on the method parameters.
- if (xmethod.isIdentity())
+ if (xmethod.isIdentity()) {
return;
+ }
BasicBlock entry = dataflow.getCFG().getEntry();
TypeQualifierValueSet entryFact = dataflow.getAnalysis().getResultFact(entry);
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/DirectlyRelevantTypeQualifiersDatabase.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/DirectlyRelevantTypeQualifiersDatabase.java
index 1031dfb..206ae2b 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/DirectlyRelevantTypeQualifiersDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/DirectlyRelevantTypeQualifiersDatabase.java
@@ -57,8 +57,9 @@ public class DirectlyRelevantTypeQualifiersDatabase {
*/
public Collection<TypeQualifierValue<?>> getDirectlyRelevantTypeQualifiers(MethodDescriptor m) {
Collection<TypeQualifierValue<?>> result = methodToDirectlyRelevantQualifiersMap.get(m);
- if (result != null)
+ if (result != null) {
return result;
+ }
return Collections.<TypeQualifierValue<?>> emptyList();
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/FindBugsDefaultAnnotations.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/FindBugsDefaultAnnotations.java
index 4feb327..9549060 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/FindBugsDefaultAnnotations.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/FindBugsDefaultAnnotations.java
@@ -28,14 +28,14 @@ import edu.umd.cs.findbugs.classfile.DescriptorFactory;
/**
* FindBugs-specific default-annotation annotations. I.e.:
- *
+ *
* <pre>
* {@literal @DefaultAnnotationForParameters(Nonnull.class)}
* public class MyClass {
* ...
* }
* </pre>
- *
+ *
* @author David Hovemeyer
*/
@Deprecated
@@ -44,7 +44,7 @@ public abstract class FindBugsDefaultAnnotations {
/** Default annotation for all element types. */
public static final ClassDescriptor DEFAULT_ANNOTATION = DescriptorFactory.instance().getClassDescriptor(
DefaultAnnotation.class);
-
+
/** Default annotation for fields. */
public static final ClassDescriptor DEFAULT_ANNOTATION_FOR_FIELDS = DescriptorFactory.instance()
@@ -57,6 +57,6 @@ public abstract class FindBugsDefaultAnnotations {
/** Default annotation for parameters. */
public static final ClassDescriptor DEFAULT_ANNOTATION_FOR_PARAMETERS = DescriptorFactory.instance()
.getClassDescriptor(DefaultAnnotationForParameters.class);
-
+
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/FlowValue.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/FlowValue.java
index 9f6ad83..c71c5fe 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/FlowValue.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/FlowValue.java
@@ -23,7 +23,7 @@ import javax.annotation.meta.When;
/**
* Flow value type for type qualifier dataflow analysis.
- *
+ *
* @author David Hovemeyer
*/
public enum FlowValue {
@@ -65,11 +65,11 @@ public enum FlowValue {
// Unknown
//
private static final FlowValue[][] mergeMatrix = {
- // TOP ALWAYS NEVER UNKNOWN
- /* TOP */{ TOP, },
- /* ALWAYS */{ ALWAYS, ALWAYS, },
- /* NEVER */{ NEVER, UNKNOWN, NEVER, },
- /* UNKNOWN */{ UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN }, };
+ // TOP ALWAYS NEVER UNKNOWN
+ /* TOP */{ TOP, },
+ /* ALWAYS */{ ALWAYS, ALWAYS, },
+ /* NEVER */{ NEVER, UNKNOWN, NEVER, },
+ /* UNKNOWN */{ UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN }, };
public static final FlowValue meet(FlowValue a, FlowValue b) {
int aIndex = a.ordinal();
@@ -86,28 +86,28 @@ public enum FlowValue {
/**
* Determine whether given flow values conflict.
- * @param typeQualifierValue TODO
* @param forward
* a forwards flow value
* @param backward
* a backwards flow value
- *
+ *
* @return true if values conflict, false otherwise
*/
public static boolean valuesConflict(boolean strictChecking, FlowValue forward, FlowValue backward) {
if (forward == TOP || backward == TOP || backward == UNKNOWN || forward == backward) {
return false;
}
-
- if (strictChecking)
+
+ if (strictChecking) {
return true;
-
+ }
+
return (forward == ALWAYS && backward == NEVER) || (forward == NEVER && backward == ALWAYS);
}
/**
* Convert a When value to a FlowValue value.
- *
+ *
* @param when
* a When value
* @return the corresponding FlowValue
@@ -129,7 +129,7 @@ public enum FlowValue {
/**
* Determine whether given backwards FlowValue conflicts with given source.
- *
+ *
* @param backwardsFlowValue
* a backwards FlowValue
* @param source
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflow.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflow.java
index 7aaa411..6f5c376 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflow.java
@@ -23,14 +23,14 @@ import edu.umd.cs.findbugs.ba.CFG;
/**
* Dataflow object for ForwardTypeQualifierDataflowAnalysis.
- *
+ *
* @author David Hovemeyer
*/
public class ForwardTypeQualifierDataflow extends TypeQualifierDataflow<ForwardTypeQualifierDataflowAnalysis> {
/**
* Constructor.
- *
+ *
* @param cfg
* CFG of analyzed method
* @param analysis
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflowAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflowAnalysis.java
index 334d274..1cc09bd 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflowAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflowAnalysis.java
@@ -82,10 +82,12 @@ public class ForwardTypeQualifierDataflowAnalysis extends TypeQualifierDataflowA
this.dfs = dfs;
}
+ @Override
public BlockOrder getBlockOrder(CFG cfg1) {
return new ReversePostOrder(cfg1, dfs);
}
+ @Override
public boolean isForwards() {
return true;
}
@@ -148,10 +150,11 @@ public class ForwardTypeQualifierDataflowAnalysis extends TypeQualifierDataflowA
When w;
if (typeQualifierValue.canValidate(constantValue)) {
w = typeQualifierValue.validate(constantValue);
- } else if (typeQualifierValue.isStrictQualifier())
+ } else if (typeQualifierValue.isStrictQualifier()) {
return;
- else
+ } else {
w = When.UNKNOWN;
+ }
registerTopOfStackSource(SourceSinkType.CONSTANT_VALUE, location, w, false, constantValue);
}
@@ -175,8 +178,9 @@ public class ForwardTypeQualifierDataflowAnalysis extends TypeQualifierDataflowA
}
XMethod calledXMethod = XFactory.createXMethod(inv, cpg);
- if (TypeQualifierDataflowAnalysis.isIdentifyFunctionForTypeQualifiers(calledXMethod))
+ if (TypeQualifierDataflowAnalysis.isIdentifyFunctionForTypeQualifiers(calledXMethod)) {
return;
+ }
if (calledXMethod.isResolved()) {
TypeQualifierAnnotation tqa = TypeQualifierApplications.getEffectiveTypeQualifierAnnotation(calledXMethod,
@@ -211,8 +215,9 @@ public class ForwardTypeQualifierDataflowAnalysis extends TypeQualifierDataflowA
private void registerTopOfStackSource(SourceSinkType sourceSinkType, Location location, When when, boolean interproc,
@CheckForNull Object constantValue) throws DataflowAnalysisException {
- if (when == When.UNKNOWN && !typeQualifierValue.isStrictQualifier())
+ if (when == When.UNKNOWN && !typeQualifierValue.isStrictQualifier()) {
return;
+ }
ValueNumberFrame vnaFrameAfterInstruction = vnaDataflow.getFactAfterLocation(location);
if (vnaFrameAfterInstruction.isValid()) {
ValueNumber tosValue = vnaFrameAfterInstruction.getTopValue();
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflowFactory.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflowFactory.java
index c102f00..17e598d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/ForwardTypeQualifierDataflowFactory.java
@@ -50,7 +50,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
* @author David Hovemeyer
*/
public class ForwardTypeQualifierDataflowFactory extends
- TypeQualifierDataflowFactory<ForwardTypeQualifierDataflowAnalysis, ForwardTypeQualifierDataflow> {
+TypeQualifierDataflowFactory<ForwardTypeQualifierDataflowAnalysis, ForwardTypeQualifierDataflow> {
/**
* Constructor.
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/JSR305NullnessAnnotations.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/JSR305NullnessAnnotations.java
index d398284..986bdd7 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/JSR305NullnessAnnotations.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/JSR305NullnessAnnotations.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.classfile.DescriptorFactory;
/**
* ClassDescriptors for JSR-305 nullness annotations.
- *
+ *
* @author David Hovemeyer
*/
public abstract class JSR305NullnessAnnotations {
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/ParameterAnnotationLookupResult.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/ParameterAnnotationLookupResult.java
index 7aef67a..0136436 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/ParameterAnnotationLookupResult.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/ParameterAnnotationLookupResult.java
@@ -22,13 +22,13 @@ package edu.umd.cs.findbugs.ba.jsr305;
/**
* TypeQualifierAnnotationLookupResult summarizing TypeQualifierAnnotation(s)
* relevant for a method parameter.
- *
+ *
* @author David Hovemeyer
*/
class ParameterAnnotationLookupResult extends TypeQualifierAnnotationLookupResult {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.jsr305.TypeQualifierAnnotationLookupResult#combine
* (edu.umd.cs.findbugs.ba.jsr305.TypeQualifierAnnotation,
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/ReturnTypeAnnotationAccumulator.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/ReturnTypeAnnotationAccumulator.java
index 5452f4c..71d444b 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/ReturnTypeAnnotationAccumulator.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/ReturnTypeAnnotationAccumulator.java
@@ -24,24 +24,24 @@ import edu.umd.cs.findbugs.ba.XMethod;
/**
* Accumulate relevant return type annotations for a given method by traversing
* its supertypes.
- *
+ *
* @author David Hovemeyer
*/
class ReturnTypeAnnotationAccumulator extends AbstractMethodAnnotationAccumulator {
- private TypeQualifierAnnotationLookupResult result;
+ private final TypeQualifierAnnotationLookupResult result;
private boolean overrides = false;
/**
* Constructor.
- *
+ *
* @param typeQualifierValue
* TypeQualifierValue specifying the kind of annotation we want
* to look up
* @param xmethod
* method whose effective return type annotation we want
*/
- public ReturnTypeAnnotationAccumulator(TypeQualifierValue typeQualifierValue, XMethod xmethod) {
+ public ReturnTypeAnnotationAccumulator(TypeQualifierValue<?> typeQualifierValue, XMethod xmethod) {
super(typeQualifierValue, xmethod);
this.result = new ReturnTypeAnnotationLookupResult();
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/ReturnTypeAnnotationLookupResult.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/ReturnTypeAnnotationLookupResult.java
index 60afac5..e7fe822 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/ReturnTypeAnnotationLookupResult.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/ReturnTypeAnnotationLookupResult.java
@@ -22,13 +22,13 @@ package edu.umd.cs.findbugs.ba.jsr305;
/**
* TypeQualifierAnnotationLookupResult summarizing TypeQualifierAnnotation(s)
* relevant for a method return type.
- *
+ *
* @author David Hovemeyer
*/
class ReturnTypeAnnotationLookupResult extends TypeQualifierAnnotationLookupResult {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.jsr305.TypeQualifierAnnotationLookupResult#combine
* (edu.umd.cs.findbugs.ba.jsr305.TypeQualifierAnnotation,
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/SourceSinkInfo.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/SourceSinkInfo.java
index cd9bfe5..72a7f52 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/SourceSinkInfo.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/SourceSinkInfo.java
@@ -26,7 +26,7 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumber;
/**
* Information about a source or sink in the type qualifier dataflow analysis.
- *
+ *
* @author David Hovemeyer
*/
public class SourceSinkInfo implements Comparable<SourceSinkInfo> {
@@ -48,7 +48,7 @@ public class SourceSinkInfo implements Comparable<SourceSinkInfo> {
/**
* Constructor.
- *
+ *
* @param type
* type of the source or sink
* @param location
@@ -131,7 +131,7 @@ public class SourceSinkInfo implements Comparable<SourceSinkInfo> {
* Set the SourceSinkInfo as having been created based on the results of
* type qualifiers computed for a called method (and not explicitly
* annotating the called method).
- *
+ *
* @param interproc
* true if the SourceSinkInfo results from computed type
* qualifiers for a called method, false otherwise
@@ -144,7 +144,7 @@ public class SourceSinkInfo implements Comparable<SourceSinkInfo> {
* Return whether or not the SourceSinkInfo was created based on the results
* of type qualifiers computed for a called method (and not explicitly
* annotating the called method).
- *
+ *
* @return true if the SourceSinkInfo results from computed type qualifiers
* for a called method, false otherwise
*/
@@ -154,9 +154,10 @@ public class SourceSinkInfo implements Comparable<SourceSinkInfo> {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
+ @Override
public int compareTo(SourceSinkInfo o) {
return this.location.compareTo(o.location);
}
@@ -186,44 +187,58 @@ public class SourceSinkInfo implements Comparable<SourceSinkInfo> {
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
SourceSinkInfo other = (SourceSinkInfo) obj;
if (constantValue == null) {
- if (other.constantValue != null)
+ if (other.constantValue != null) {
return false;
- } else if (!constantValue.equals(other.constantValue))
+ }
+ } else if (!constantValue.equals(other.constantValue)) {
return false;
- if (interproc != other.interproc)
+ }
+ if (interproc != other.interproc) {
return false;
- if (local != other.local)
+ }
+ if (local != other.local) {
return false;
+ }
if (location == null) {
- if (other.location != null)
+ if (other.location != null) {
return false;
- } else if (!location.equals(other.location))
+ }
+ } else if (!location.equals(other.location)) {
return false;
- if (parameter != other.parameter)
+ }
+ if (parameter != other.parameter) {
return false;
- if (type != other.type)
+ }
+ if (type != other.type) {
return false;
+ }
if (vn == null) {
- if (other.vn != null)
+ if (other.vn != null) {
return false;
- } else if (!vn.equals(other.vn))
+ }
+ } else if (!vn.equals(other.vn)) {
return false;
- if (when != other.when)
+ }
+ if (when != other.when) {
return false;
+ }
return true;
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierAnnotation.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierAnnotation.java
index 75f9724..9dcc327 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierAnnotation.java
@@ -93,18 +93,18 @@ public class TypeQualifierAnnotation {
private static final When TOP = null;
private static final When[][] combineReturnValueMatrix = {
- // ALWAYS UNKNOWN MAYBE NEVER
- /* ALWAYS */{ When.ALWAYS, },
- /* UNKNOWN */{ When.ALWAYS, When.UNKNOWN, },
- /* MAYBE */{ When.ALWAYS, When.UNKNOWN, When.MAYBE, },
- /* NEVER */{ TOP, TOP, When.NEVER, When.NEVER }, };
+ // ALWAYS UNKNOWN MAYBE NEVER
+ /* ALWAYS */{ When.ALWAYS, },
+ /* UNKNOWN */{ When.ALWAYS, When.UNKNOWN, },
+ /* MAYBE */{ When.ALWAYS, When.UNKNOWN, When.MAYBE, },
+ /* NEVER */{ TOP, TOP, When.NEVER, When.NEVER }, };
private static final When[][] combineParameterMatrix = {
- // ALWAYS UNKNOWN MAYBE NEVER
- /* ALWAYS */{ When.ALWAYS, },
- /* UNKNOWN */{ When.UNKNOWN, When.UNKNOWN, },
- /* MAYBE */{ When.MAYBE, When.MAYBE, When.MAYBE, },
- /* NEVER */{ When.MAYBE, When.UNKNOWN, When.MAYBE, When.NEVER }, };
+ // ALWAYS UNKNOWN MAYBE NEVER
+ /* ALWAYS */{ When.ALWAYS, },
+ /* UNKNOWN */{ When.UNKNOWN, When.UNKNOWN, },
+ /* MAYBE */{ When.MAYBE, When.MAYBE, When.MAYBE, },
+ /* NEVER */{ When.MAYBE, When.UNKNOWN, When.MAYBE, When.NEVER }, };
/**
* Combine return type annotations.
@@ -169,8 +169,9 @@ public class TypeQualifierAnnotation {
TypeQualifierAnnotation getValue(TypeQualifierValue<?> desc, When when) {
DualKeyHashMap<TypeQualifierValue<?>, When, TypeQualifierAnnotation> map = instance.get();
TypeQualifierAnnotation result = map.get(desc, when);
- if (result != null)
+ if (result != null) {
return result;
+ }
result = new TypeQualifierAnnotation(desc, when);
map.put(desc, when, result);
return result;
@@ -183,8 +184,9 @@ public class TypeQualifierAnnotation {
@Override
public boolean equals(Object o) {
- if (!(o instanceof TypeQualifierAnnotation))
+ if (!(o instanceof TypeQualifierAnnotation)) {
return false;
+ }
TypeQualifierAnnotation other = (TypeQualifierAnnotation) o;
return typeQualifier.equals(other.typeQualifier) && when.equals(other.when);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierAnnotationLookupResult.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierAnnotationLookupResult.java
index 4c05c62..986581d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierAnnotationLookupResult.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierAnnotationLookupResult.java
@@ -34,7 +34,7 @@ import edu.umd.cs.findbugs.classfile.analysis.AnnotatedObject;
* on the annotated entity. This object makes it possible to report such
* conflicts, while still providing a convenient interface for getting the
* "effective" TypeQualifierAnnotation.
- *
+ *
* @author David Hovemeyer
*/
public class TypeQualifierAnnotationLookupResult {
@@ -42,9 +42,9 @@ public class TypeQualifierAnnotationLookupResult {
* Partial result of looking up a TypeQualifierAnnotation.
*/
public static class PartialResult {
- private AnnotatedObject annotatedObject;
+ private final AnnotatedObject annotatedObject;
- private TypeQualifierAnnotation typeQualifierAnnotation;
+ private final TypeQualifierAnnotation typeQualifierAnnotation;
PartialResult(AnnotatedObject annotatedObject, TypeQualifierAnnotation typeQualifierAnnotation) {
this.annotatedObject = annotatedObject;
@@ -67,7 +67,7 @@ public class TypeQualifierAnnotationLookupResult {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
@@ -76,7 +76,7 @@ public class TypeQualifierAnnotationLookupResult {
}
}
- private List<PartialResult> partialResultList;
+ private final List<PartialResult> partialResultList;
TypeQualifierAnnotationLookupResult() {
this.partialResultList = new LinkedList<PartialResult>();
@@ -88,7 +88,7 @@ public class TypeQualifierAnnotationLookupResult {
/**
* Get the effective TypeQualifierAnnotation.
- *
+ *
* @return the effective TypeQualifierAnnotation, or null if no effective
* TypeQualifierAnnotation can be found
*/
@@ -112,7 +112,7 @@ public class TypeQualifierAnnotationLookupResult {
/**
* Subclasses must override this method to combine TypeQualifierAnnotations
* found in multiple superclasses.
- *
+ *
* @param a
* a TypeQualifierAnnotation
* @param b
@@ -127,7 +127,7 @@ public class TypeQualifierAnnotationLookupResult {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierApplications.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierApplications.java
index 5491f0d..1e7a29a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierApplications.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierApplications.java
@@ -147,13 +147,16 @@ public class TypeQualifierApplications {
*/
private static Collection<AnnotationValue> getDirectAnnotation(AnnotatedObject m) {
Collection<AnnotationValue> result = getDirectObjectAnnotations().get(m);
- if (result != null)
+ if (result != null) {
return result;
- if (m.getAnnotationDescriptors().isEmpty())
+ }
+ if (m.getAnnotationDescriptors().isEmpty()) {
return Collections.<AnnotationValue> emptyList();
+ }
result = TypeQualifierResolver.resolveTypeQualifiers(m.getAnnotations());
- if (result.size() == 0)
+ if (result.size() == 0) {
result = Collections.<AnnotationValue> emptyList();
+ }
getDirectObjectAnnotations().put(m, result);
return result;
}
@@ -174,21 +177,26 @@ public class TypeQualifierApplications {
if (map == null) {
int n = m.getNumParams();
if (m.isVarArgs())
+ {
n--; // ignore annotations on varargs parameters
+ }
map = new HashMap<Integer, Collection<AnnotationValue>>(n + 2);
for (int i = 0; i < n; i++) {
Collection<AnnotationValue> a = TypeQualifierResolver.resolveTypeQualifiers(m.getParameterAnnotations(i));
- if (!a.isEmpty())
+ if (!a.isEmpty()) {
map.put(i, a);
+ }
}
- if (map.isEmpty())
+ if (map.isEmpty()) {
map = Collections.emptyMap();
+ }
directParameterAnnotations.put(m, map);
}
Collection<AnnotationValue> result = map.get(parameter);
- if (result != null)
+ if (result != null) {
return result;
+ }
return Collections.emptyList();
}
@@ -205,8 +213,9 @@ public class TypeQualifierApplications {
*/
public static void getDirectApplications(Set<TypeQualifierAnnotation> result, XMethod o, int parameter) {
Collection<AnnotationValue> values = getDirectAnnotation(o, parameter);
- for (AnnotationValue v : values)
+ for (AnnotationValue v : values) {
constructTypeQualifierAnnotation(result, v);
+ }
}
@@ -222,11 +231,13 @@ public class TypeQualifierApplications {
* ElementType representing kind of annotated object
*/
public static void getDirectApplications(Set<TypeQualifierAnnotation> result, AnnotatedObject o, ElementType e) {
- if (!o.getElementType().equals(e))
+ if (!o.getElementType().equals(e)) {
return;
+ }
Collection<AnnotationValue> values = getDirectAnnotation(o);
- for (AnnotationValue v : values)
+ for (AnnotationValue v : values) {
constructTypeQualifierAnnotation(result, v);
+ }
}
@@ -277,8 +288,9 @@ public class TypeQualifierApplications {
private static void getApplicableScopedApplications(Set<TypeQualifierAnnotation> result, AnnotatedObject o, ElementType e) {
if (!o.isSynthetic()) {
AnnotatedObject outer = o.getContainingScope();
- if (outer != null)
+ if (outer != null) {
getApplicableScopedApplications(result, outer, e);
+ }
}
getDirectApplications(result, o, e);
}
@@ -434,6 +446,7 @@ public class TypeQualifierApplications {
break;
default:
// ignore
+ break;
}
// Try out default JDT (Eclipse) annotations
@@ -487,7 +500,7 @@ public class TypeQualifierApplications {
if (!(obj instanceof Type)) {
if (DEBUG_DEFAULT_ANNOTATION) {
System.out
- .println("Found a non-Type value in value array of " + defaultAnnotation.toString() + " annotation");
+ .println("Found a non-Type value in value array of " + defaultAnnotation.toString() + " annotation");
}
continue;
}
@@ -507,8 +520,9 @@ public class TypeQualifierApplications {
AnnotationValue annotation = new AnnotationValue(typeDesc);
Collection<AnnotationValue> resolvedTypeQualifiers = TypeQualifierResolver.resolveTypeQualifiers(annotation);
TypeQualifierAnnotation tqa = extractAnnotation(resolvedTypeQualifiers, typeQualifierValue);
- if (tqa != null)
+ if (tqa != null) {
return tqa;
+ }
}
@@ -564,6 +578,7 @@ public class TypeQualifierApplications {
final AnnotatedObject o2 = o;
if (CHECK_EXCLUSIVE && tqa == null && typeQualifierValue.isExclusiveQualifier()) {
tqa = computeExclusiveQualifier(typeQualifierValue, new ComputeEffectiveTypeQualifierAnnotation() {
+ @Override
public TypeQualifierAnnotation compute(TypeQualifierValue<?> tqv) {
return computeEffectiveTypeQualifierAnnotation(tqv, o2);
}
@@ -605,7 +620,7 @@ public class TypeQualifierApplications {
// If it's an instance method, check for an inherited annotation
if (tqa == null && (o instanceof XMethod) && !((XMethod) o).isStatic() && !((XMethod) o).isPrivate()
- && !((XMethod) o).getName().equals("<init>")) {
+ && !"<init>".equals(((XMethod) o).getName())) {
tqa = getInheritedTypeQualifierAnnotation((XMethod) o, typeQualifierValue);
}
@@ -671,10 +686,11 @@ public class TypeQualifierApplications {
ReturnTypeAnnotationAccumulator accumulator = new ReturnTypeAnnotationAccumulator(typeQualifierValue, o);
try {
- AnalysisContext.currentAnalysisContext().getSubtypes2().traverseSupertypes(o.getClassDescriptor(), accumulator);
+ AnalysisContext.currentAnalysisContext().getSubtypes2().traverseSupertypesDepthFirst(o.getClassDescriptor(), accumulator);
TypeQualifierAnnotation result = accumulator.getResult().getEffectiveTypeQualifierAnnotation();
- if (result == null && accumulator.overrides())
+ if (result == null && accumulator.overrides()) {
return TypeQualifierAnnotation.OVERRIDES_BUT_NO_ANNOTATION;
+ }
return result;
} catch (ClassNotFoundException e) {
AnalysisContext.currentAnalysisContext().getLookupFailureCallback().reportMissingClass(e);
@@ -697,15 +713,19 @@ public class TypeQualifierApplications {
TypeQualifierValue<?> typeQualifierValue, boolean stopAtClassScope) {
if (o.isSynthetic())
+ {
return null; // synthetic objects don't get default annotations
+ }
ElementType elementType = o.getElementType();
while (true) {
o = o.getContainingScope();
- if (o == null)
+ if (o == null) {
return null;
- if (stopAtClassScope && o instanceof XClass)
+ }
+ if (stopAtClassScope && o instanceof XClass) {
return null;
+ }
TypeQualifierAnnotation result;
// Check direct applications of the type qualifier
@@ -715,7 +735,7 @@ public class TypeQualifierApplications {
if (result != null) {
// Great - found an outer scope with a relevant annotation
assert false : "I don't think we should be looking here";
- return result;
+ return result;
}
// Check default annotations
@@ -748,6 +768,7 @@ public class TypeQualifierApplications {
if (CHECK_EXCLUSIVE && tqa == null && typeQualifierValue.isExclusiveQualifier()) {
tqa = computeExclusiveQualifier(typeQualifierValue, new ComputeEffectiveTypeQualifierAnnotation() {
+ @Override
public TypeQualifierAnnotation compute(TypeQualifierValue<?> tqv) {
return computeEffectiveTypeQualifierAnnotation(tqv, xmethod, parameter);
}
@@ -816,64 +837,66 @@ public class TypeQualifierApplications {
}
}
else {
- // Check direct application
- if (DEBUG) {
- System.out.print(" (1) Checking direct application...");
- }
- tqa = getDirectTypeQualifierAnnotation(xmethod, parameter, typeQualifierValue);
- if (DEBUG) {
- System.out.println(tqa != null ? "FOUND" : "none");
- }
-
- // If it's an instance method, check for inherited annotation
- if (tqa == null && !xmethod.isStatic() && !xmethod.isPrivate() && !xmethod.getName().equals("<init>")) {
+ // Check direct application
if (DEBUG) {
- System.out.print(" (2) Checking inherited...");
+ System.out.print(" (1) Checking direct application...");
}
- tqa = getInheritedTypeQualifierAnnotation(xmethod, parameter, typeQualifierValue);
+ tqa = getDirectTypeQualifierAnnotation(xmethod, parameter, typeQualifierValue);
if (DEBUG) {
- if (tqa == TypeQualifierAnnotation.OVERRIDES_BUT_NO_ANNOTATION)
- System.out.println("Overrides, no annotation inherited");
- else if (tqa != null)
- System.out.println("Inherited " + tqa.when);
- else
- System.out.println("Nothing inherited");
+ System.out.println(tqa != null ? "FOUND" : "none");
}
- }
- boolean overriddenMethod = false;
- if (tqa == TypeQualifierAnnotation.OVERRIDES_BUT_NO_ANNOTATION) {
- overriddenMethod = true;
- tqa = null;
- }
- // Check for default (outer scope) annotation
- if (tqa == null) {
- if (xmethod.isVariableSynthetic((xmethod.isStatic() ? 0 : 1) + parameter)) {
+
+ // If it's an instance method, check for inherited annotation
+ if (tqa == null && !xmethod.isStatic() && !xmethod.isPrivate() && !"<init>".equals(xmethod.getName())) {
if (DEBUG) {
- System.out.print(" (3) Skipping default for synthetic parameter");
+ System.out.print(" (2) Checking inherited...");
}
- } else {
+ tqa = getInheritedTypeQualifierAnnotation(xmethod, parameter, typeQualifierValue);
if (DEBUG) {
- System.out.print(" (3) Checking default...");
+ if (tqa == TypeQualifierAnnotation.OVERRIDES_BUT_NO_ANNOTATION) {
+ System.out.println("Overrides, no annotation inherited");
+ } else if (tqa != null) {
+ System.out.println("Inherited " + tqa.when);
+ } else {
+ System.out.println("Nothing inherited");
+ }
}
-
- tqa = getDefaultTypeQualifierAnnotationForParameters(xmethod, typeQualifierValue, overriddenMethod);
-
- if (DEBUG) {
- System.out.println(tqa != null ? "FOUND" : "none");
+ }
+ boolean overriddenMethod = false;
+ if (tqa == TypeQualifierAnnotation.OVERRIDES_BUT_NO_ANNOTATION) {
+ overriddenMethod = true;
+ tqa = null;
+ }
+ // Check for default (outer scope) annotation
+ if (tqa == null) {
+ if (xmethod.isVariableSynthetic((xmethod.isStatic() ? 0 : 1) + parameter)) {
+ if (DEBUG) {
+ System.out.print(" (3) Skipping default for synthetic parameter");
+ }
+ } else {
+ if (DEBUG) {
+ System.out.print(" (3) Checking default...");
+ }
+
+ tqa = getDefaultTypeQualifierAnnotationForParameters(xmethod, typeQualifierValue, overriddenMethod);
+
+ if (DEBUG) {
+ System.out.println(tqa != null ? "FOUND" : "none");
+ }
}
}
}
- }
// Cache answer
result = tqa;
map.put(xmethod, parameter, result);
if (DEBUG) {
- if (result == null)
+ if (result == null) {
System.out.println(" => Answer: no annotation on parameter " + parameter + " of " + xmethod);
- else
+ } else {
System.out.println(" => Answer: " + result.when + " on parameter " + parameter + " of " + xmethod);
+ }
}
}
@@ -901,8 +924,9 @@ public class TypeQualifierApplications {
public static @CheckForNull @CheckReturnValue
TypeQualifierAnnotation getDirectTypeQualifierAnnotation(XMethod xmethod, int parameter, TypeQualifierValue<?> typeQualifierValue) {
XMethod bridge = xmethod.bridgeTo();
- if (bridge != null)
+ if (bridge != null) {
xmethod = bridge;
+ }
Set<TypeQualifierAnnotation> applications = new HashSet<TypeQualifierAnnotation>();
getDirectApplications(applications, xmethod, parameter);
if (DEBUG_METHOD != null && DEBUG_METHOD.equals(xmethod.getName())) {
@@ -932,10 +956,11 @@ public class TypeQualifierApplications {
ParameterAnnotationAccumulator accumulator = new ParameterAnnotationAccumulator(typeQualifierValue, xmethod, parameter);
try {
- AnalysisContext.currentAnalysisContext().getSubtypes2().traverseSupertypes(xmethod.getClassDescriptor(), accumulator);
+ AnalysisContext.currentAnalysisContext().getSubtypes2().traverseSupertypesDepthFirst(xmethod.getClassDescriptor(), accumulator);
TypeQualifierAnnotation result = accumulator.getResult().getEffectiveTypeQualifierAnnotation();
- if (result == null && accumulator.overrides())
+ if (result == null && accumulator.overrides()) {
return TypeQualifierAnnotation.OVERRIDES_BUT_NO_ANNOTATION;
+ }
return result;
} catch (ClassNotFoundException e) {
AnalysisContext.currentAnalysisContext().getLookupFailureCallback().reportMissingClass(e);
@@ -952,7 +977,6 @@ public class TypeQualifierApplications {
* @param typeQualifierValue
* the kind of TypeQualifierValue we are looking for
* @param stopAtMethodScope
- * TODO
* @return the default (outer scope) TypeQualifierAnnotation on the
* parameter, or null if there is no default TypeQualifierAnnotation
*/
@@ -961,20 +985,25 @@ public class TypeQualifierApplications {
TypeQualifierValue<?> typeQualifierValue, boolean stopAtMethodScope) {
if (xmethod.isSynthetic())
+ {
return null; // synthetic methods don't get default annotations
+ }
// System.out.println("Looking for default " + typeQualifierValue +
// " annotation of parameters of " + xmethod);
- if (xmethod.getName().equals("<init>") && xmethod.getClassDescriptor().isAnonymousClass())
+ if ("<init>".equals(xmethod.getName()) && xmethod.getClassDescriptor().isAnonymousClass())
+ {
return null; // constructors for anonymous inner classes don't get
- // default annotations
+ // default annotations
+ }
/** private methods don't inherit from class or package scope */
- if (xmethod.isPrivate())
+ if (xmethod.isPrivate()) {
stopAtMethodScope = true;
+ }
boolean stopAtClassScope = false;
- if (!xmethod.isPublic() && !xmethod.isProtected() && (xmethod.isStatic() || xmethod.getName().equals("<init>"))) {
+ if (!xmethod.isPublic() && !xmethod.isProtected() && (xmethod.isStatic() || "<init>".equals(xmethod.getName()))) {
try {
XClass xclass = Global.getAnalysisCache().getClassAnalysis(XClass.class, xmethod.getClassDescriptor());
stopAtClassScope = xclass.isPrivate();
@@ -985,11 +1014,13 @@ public class TypeQualifierApplications {
AnnotatedObject o = xmethod;
while (true) {
- if (o == null)
+ if (o == null) {
return null;
+ }
- if (stopAtMethodScope && o instanceof XClass)
+ if (stopAtMethodScope && o instanceof XClass) {
return null;
+ }
// Check for direct type qualifier annotation
Set<TypeQualifierAnnotation> applications = new HashSet<TypeQualifierAnnotation>();
getDirectApplications(applications, o, ElementType.PARAMETER);
@@ -997,20 +1028,22 @@ public class TypeQualifierApplications {
if (tqa != null) {
// Found matching annotation in outer scope
assert false : "I think this code is dead; it shouldn't find anything";
- return tqa;
+ return tqa;
}
// Check for default annotation
tqa = getDefaultAnnotation(o, typeQualifierValue, ElementType.PARAMETER);
if (tqa != null) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Found default of " + tqa + " @ " + o);
+ }
return tqa;
}
- if (stopAtClassScope && o instanceof XClass)
+ if (stopAtClassScope && o instanceof XClass) {
return null;
-
+ }
+
o = o.getContainingScope();
-
+
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierDataflow.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierDataflow.java
index 46cc661..434fceb 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierDataflow.java
@@ -24,15 +24,15 @@ import edu.umd.cs.findbugs.ba.Dataflow;
/**
* Dataflow class for TypeQualifierDataflowAnalysis.
- *
+ *
* @author David Hovemeyer
*/
public class TypeQualifierDataflow<AnalysisType extends TypeQualifierDataflowAnalysis> extends
- Dataflow<TypeQualifierValueSet, AnalysisType> {
+Dataflow<TypeQualifierValueSet, AnalysisType> {
/**
* Constructor.
- *
+ *
* @param cfg
* control flow graph (CFG) of analyzed method
* @param analysis
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierDataflowAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierDataflowAnalysis.java
index 6a812bc..0f4bf04 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierDataflowAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierDataflowAnalysis.java
@@ -52,31 +52,37 @@ import edu.umd.cs.findbugs.util.ClassName;
public abstract class TypeQualifierDataflowAnalysis extends AbstractDataflowAnalysis<TypeQualifierValueSet> {
static String primitiveType (String simpleClass) {
- if (simpleClass.equals("Integer"))
+ if ("Integer".equals(simpleClass)) {
return "int";
+ }
return simpleClass.toLowerCase();
}
static boolean isIdentifyFunctionForTypeQualifiers(XMethod m) {
String className = m.getClassName();
- if (!className.startsWith("java.lang"))
+ if (!className.startsWith("java.lang")) {
return false;
+ }
String methodName = m.getName();
if (m.isStatic()) {
- if (!methodName.equals("valueOf"))
+ if (!"valueOf".equals(methodName)) {
return false;
+ }
String signature = m.getSignature();
- if (signature.charAt(2) != ')')
+ if (signature.charAt(2) != ')') {
return false;
+ }
} else {
String simpleClassName = ClassName.extractSimpleName(className);
- if (!methodName.equals(primitiveType(simpleClassName) + "Value"))
+ if (!methodName.equals(primitiveType(simpleClassName) + "Value")) {
return false;
+ }
String signature = m.getSignature();
- if (signature.charAt(1) != ')')
+ if (signature.charAt(1) != ')') {
return false;
+ }
}
return true;
}
@@ -90,7 +96,7 @@ public abstract class TypeQualifierDataflowAnalysis extends AbstractDataflowAnal
protected final ValueNumberDataflow vnaDataflow;
- protected final TypeQualifierValue typeQualifierValue;
+ protected final TypeQualifierValue<?> typeQualifierValue;
protected final ConstantPoolGen cpg;
@@ -112,7 +118,7 @@ public abstract class TypeQualifierDataflowAnalysis extends AbstractDataflowAnal
* the TypeQualifierValue we want the dataflow analysis to check
*/
public TypeQualifierDataflowAnalysis(XMethod xmethod, CFG cfg, ValueNumberDataflow vnaDataflow, ConstantPoolGen cpg,
- TypeQualifierValue typeQualifierValue) {
+ TypeQualifierValue<?> typeQualifierValue) {
this.xmethod = xmethod;
this.cfg = cfg;
this.vnaDataflow = vnaDataflow;
@@ -127,6 +133,7 @@ public abstract class TypeQualifierDataflowAnalysis extends AbstractDataflowAnal
* @see
* edu.umd.cs.findbugs.ba.DataflowAnalysis#initEntryFact(java.lang.Object)
*/
+ @Override
public void initEntryFact(TypeQualifierValueSet result) throws DataflowAnalysisException {
result.makeValid();
}
@@ -149,6 +156,7 @@ public abstract class TypeQualifierDataflowAnalysis extends AbstractDataflowAnal
* @see edu.umd.cs.findbugs.ba.DataflowAnalysis#copy(java.lang.Object,
* java.lang.Object)
*/
+ @Override
public void copy(TypeQualifierValueSet source, TypeQualifierValueSet dest) {
dest.makeSameAs(source);
}
@@ -158,6 +166,7 @@ public abstract class TypeQualifierDataflowAnalysis extends AbstractDataflowAnal
*
* @see edu.umd.cs.findbugs.ba.DataflowAnalysis#createFact()
*/
+ @Override
public TypeQualifierValueSet createFact() {
return new TypeQualifierValueSet(typeQualifierValue);
}
@@ -167,6 +176,7 @@ public abstract class TypeQualifierDataflowAnalysis extends AbstractDataflowAnal
*
* @see edu.umd.cs.findbugs.ba.DataflowAnalysis#isTop(java.lang.Object)
*/
+ @Override
public boolean isTop(TypeQualifierValueSet fact) {
return fact.isTop();
}
@@ -177,6 +187,7 @@ public abstract class TypeQualifierDataflowAnalysis extends AbstractDataflowAnal
* @see
* edu.umd.cs.findbugs.ba.DataflowAnalysis#makeFactTop(java.lang.Object)
*/
+ @Override
public void makeFactTop(TypeQualifierValueSet fact) {
fact.setTop();
}
@@ -187,6 +198,7 @@ public abstract class TypeQualifierDataflowAnalysis extends AbstractDataflowAnal
* @see edu.umd.cs.findbugs.ba.DataflowAnalysis#meetInto(java.lang.Object,
* edu.umd.cs.findbugs.ba.Edge, java.lang.Object)
*/
+ @Override
public void meetInto(TypeQualifierValueSet fact, Edge edge, TypeQualifierValueSet result) throws DataflowAnalysisException {
if (fact.isTop() || result.isBottom()) {
// result does not change
@@ -208,6 +220,7 @@ public abstract class TypeQualifierDataflowAnalysis extends AbstractDataflowAnal
* @see edu.umd.cs.findbugs.ba.DataflowAnalysis#same(java.lang.Object,
* java.lang.Object)
*/
+ @Override
public boolean same(TypeQualifierValueSet fact1, TypeQualifierValueSet fact2) {
return fact1.equals(fact2);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierResolver.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierResolver.java
index 6b6e4a9..9098e9c 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierResolver.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierResolver.java
@@ -90,8 +90,9 @@ public class TypeQualifierResolver {
public static Collection<AnnotationValue> resolveTypeQualifierDefaults(Collection<AnnotationValue> values,
ElementType elementType) {
LinkedList<AnnotationValue> result = new LinkedList<AnnotationValue>();
- for (AnnotationValue value : values)
+ for (AnnotationValue value : values) {
resolveTypeQualifierDefaults(value, elementType, result);
+ }
return result;
}
@@ -134,9 +135,11 @@ public class TypeQualifierResolver {
XClass c = Global.getAnalysisCache().getClassAnalysis(XClass.class, annotationClass);
if (c.getAnnotationDescriptors().contains(typeQualifierNickname)) {
- for (ClassDescriptor d : c.getAnnotationDescriptors())
- if (!d.equals(typeQualifierNickname))
+ for (ClassDescriptor d : c.getAnnotationDescriptors()) {
+ if (!d.equals(typeQualifierNickname)) {
resolveTypeQualifierNicknames(c.getAnnotation(d), result, onStack);
+ }
+ }
} else if (c.getAnnotationDescriptors().contains(typeQualifier)) {
result.add(value);
}
@@ -156,8 +159,9 @@ public class TypeQualifierResolver {
public static void logMissingAnnotationClass(MissingClassException e) {
ClassDescriptor c = e.getClassDescriptor();
- if (c.getClassName().startsWith("javax.annotation"))
+ if (c.getClassName().startsWith("javax.annotation")) {
AnalysisContext.currentAnalysisContext().getLookupFailureCallback().reportMissingClass(c);
+ }
}
/**
@@ -171,12 +175,14 @@ public class TypeQualifierResolver {
* @return Collection of resolved type qualifier AnnotationValues
*/
public static Collection<AnnotationValue> resolveTypeQualifiers(Collection<AnnotationValue> values) {
- if (values.isEmpty())
+ if (values.isEmpty()) {
return Collections.emptyList();
+ }
LinkedList<AnnotationValue> result = new LinkedList<AnnotationValue>();
LinkedList<ClassDescriptor> onStack = new LinkedList<ClassDescriptor>();
- for (AnnotationValue value : values)
+ for (AnnotationValue value : values) {
resolveTypeQualifierNicknames(value, result, onStack);
+ }
return result;
}
@@ -200,18 +206,22 @@ public class TypeQualifierResolver {
try {
XClass c = Global.getAnalysisCache().getClassAnalysis(XClass.class, value.getAnnotationClass());
AnnotationValue defaultAnnotation = c.getAnnotation(typeQualifierDefault);
- if (defaultAnnotation == null)
+ if (defaultAnnotation == null) {
return;
- for (Object o : (Object[]) defaultAnnotation.getValue("value"))
+ }
+ for (Object o : (Object[]) defaultAnnotation.getValue("value")) {
if (o instanceof EnumValue) {
EnumValue e = (EnumValue) o;
if (e.desc.equals(elementTypeDescriptor) && e.value.equals(defaultFor.name())) {
- for (ClassDescriptor d : c.getAnnotationDescriptors())
- if (!d.equals(typeQualifierDefault))
+ for (ClassDescriptor d : c.getAnnotationDescriptors()) {
+ if (!d.equals(typeQualifierDefault)) {
resolveTypeQualifierNicknames(c.getAnnotation(d), result, new LinkedList<ClassDescriptor>());
+ }
+ }
break;
}
}
+ }
} catch (MissingClassException e) {
logMissingAnnotationClass(e);
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierValue.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierValue.java
index 5804034..1a3667f 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierValue.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierValue.java
@@ -113,7 +113,7 @@ public class TypeQualifierValue<A extends Annotation> {
isStrict1 = true;
}
for (XMethod xmethod : xclass.getXMethods()) {
- if (xmethod.getName().equals("value") && xmethod.getSignature().startsWith("()")) {
+ if ("value".equals(xmethod.getName()) && xmethod.getSignature().startsWith("()")) {
isExhaustive1 = xmethod.getAnnotation(EXHAUSTIVE_ANNOTATION) != null;
if (isExhaustive1) {
// exhaustive qualifiers are automatically exclusive
@@ -134,8 +134,8 @@ public class TypeQualifierValue<A extends Annotation> {
this.isStrict = isStrict1;
this.isExclusive = isExclusive1;
this.isExhaustive = isExhaustive1;
-
-
+
+
if (xclass != null) {
ClassDescriptor checkerName = DescriptorFactory.createClassDescriptor(typeQualifier.getClassName() + "$Checker");
@@ -150,7 +150,9 @@ public class TypeQualifierValue<A extends Annotation> {
// found it.
SecurityManager m = System.getSecurityManager();
if (m == null) {
- if (DEBUG_CLASSLOADING) System.out.println("Setting ValidationSecurityManager");
+ if (DEBUG_CLASSLOADING) {
+ System.out.println("Setting ValidationSecurityManager");
+ }
System.setSecurityManager(ValidationSecurityManager.INSTANCE);
}
@@ -165,9 +167,11 @@ public class TypeQualifierValue<A extends Annotation> {
InvocationHandler handler = new InvocationHandler() {
+ @Override
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
- if (arg1.getName() == "value")
+ if ("value".equals(arg1.getName())) {
return TypeQualifierValue.this.value;
+ }
throw new UnsupportedOperationException("Can't handle " + arg1);
}
};
@@ -190,7 +194,9 @@ public class TypeQualifierValue<A extends Annotation> {
else if (DEBUG_CLASSLOADING) {
SecurityManager m = System.getSecurityManager();
if (m == null) {
- if (DEBUG_CLASSLOADING) System.out.println("Setting ValidationSecurityManager");
+ if (DEBUG_CLASSLOADING) {
+ System.out.println("Setting ValidationSecurityManager");
+ }
System.setSecurityManager(ValidationSecurityManager.INSTANCE);
}
}
@@ -202,23 +208,25 @@ public class TypeQualifierValue<A extends Annotation> {
private static <A extends Annotation> TypeQualifierValidator<A> getValidator(
Class<? extends TypeQualifierValidator<A>> checkerClass)
- throws InstantiationException, IllegalAccessException {
+ throws InstantiationException, IllegalAccessException {
return checkerClass.newInstance();
}
@SuppressWarnings("unchecked")
private static <A> Class<A> getQualifierClass(ClassDescriptor typeQualifier) throws ClassNotFoundException {
@DottedClassName String className = typeQualifier.getDottedClassName();
- if (DEBUG_CLASSLOADING)
+ if (DEBUG_CLASSLOADING) {
System.out.println("Getting qualifier class for " + className);
- if (className.startsWith("javax.annotation"))
+ }
+ if (className.startsWith("javax.annotation")) {
return (Class<A>) Class.forName(className);
+ }
try {
Global.getAnalysisCache().getClassAnalysis(ClassData.class, typeQualifier);
} catch (CheckedAnalysisException e) {
throw new ClassNotFoundException("No class data found for " + className);
}
-
+
ValidatorClassLoader validatorLoader = ValidatorClassLoader.INSTANCE;
return (Class<A>) validatorLoader.loadClass(typeQualifier.getDottedClassName());
}
@@ -252,14 +260,16 @@ public class TypeQualifierValue<A extends Annotation> {
}
public boolean canValidate(@CheckForNull Object constantValue) {
- if (validator == null)
+ if (validator == null) {
return false;
+ }
return true;
}
public When validate(@CheckForNull Object constantValue) {
- if (validator == null)
+ if (validator == null) {
throw new IllegalStateException("No validator");
+ }
IAnalysisCache analysisCache = Global.getAnalysisCache();
Profiler profiler = analysisCache.getProfiler();
profiler.start(validator.getClass());
@@ -288,8 +298,9 @@ public class TypeQualifierValue<A extends Annotation> {
TypeQualifierValue<?> getValue(ClassDescriptor desc, @CheckForNull Object value) {
DualKeyHashMap<ClassDescriptor, Object, TypeQualifierValue<?>> map = instance.get().typeQualifierMap;
TypeQualifierValue<?> result = map.get(desc, value);
- if (result != null)
+ if (result != null) {
return result;
+ }
result = new TypeQualifierValue(desc, value);
map.put(desc, value, result);
instance.get().allKnownTypeQualifiers.add(result);
@@ -398,15 +409,17 @@ public class TypeQualifierValue<A extends Annotation> {
@Override
public int hashCode() {
int result = typeQualifier.hashCode();
- if (value != null)
+ if (value != null) {
result += 37 * value.hashCode();
+ }
return result;
}
@Override
public boolean equals(Object o) {
- if (!(o instanceof TypeQualifierValue))
+ if (!(o instanceof TypeQualifierValue)) {
return false;
+ }
TypeQualifierValue<?> other = (TypeQualifierValue<?>) o;
return typeQualifier.equals(other.typeQualifier) && Util.nullSafeEquals(value, other.value);
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierValueSet.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierValueSet.java
index 84f182e..c9652c6 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierValueSet.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/TypeQualifierValueSet.java
@@ -51,7 +51,7 @@ public class TypeQualifierValueSet {
final boolean isStrict;
- public TypeQualifierValueSet(TypeQualifierValue typeQualifierValue) {
+ public TypeQualifierValueSet(TypeQualifierValue<?> typeQualifierValue) {
this.valueMap = new HashMap<ValueNumber, FlowValue>(3);
this.whereAlways = new HashMap<ValueNumber, Set<SourceSinkInfo>>(3);
this.whereNever = new HashMap<ValueNumber, Set<SourceSinkInfo>>(3);
@@ -72,8 +72,11 @@ public class TypeQualifierValueSet {
break;
case NEVER:
addSourceSinkInfo(whereNever, vn, sourceSinkInfo);
+ break;
+ default:
+ break;
}
- } else {
+ }/* else {
if (flowValue.isYes()) {
addSourceSinkInfo(whereAlways, vn, sourceSinkInfo);
@@ -82,25 +85,28 @@ public class TypeQualifierValueSet {
if (flowValue.isNo()) {
addSourceSinkInfo(whereNever, vn, sourceSinkInfo);
}
- }
+ }*/
}
- private void setValue(ValueNumber vn, FlowValue flowValue) {
- if (flowValue == FlowValue.TOP)
- pruneValue(vn);
- else
- valueMap.put(vn, flowValue);
+ private void setValue(ValueNumber vn, FlowValue flowValue) {
+ if (flowValue == FlowValue.TOP) {
+ pruneValue(vn);
+ } else {
+ valueMap.put(vn, flowValue);
+ }
}
static <K, V> void copyMapValue(Map<K, V> map, K from, K to) {
- if (!map.containsKey(from))
+ if (!map.containsKey(from)) {
return;
+ }
map.put(to, map.get(from));
}
void copyInfo(ValueNumber from, ValueNumber to) {
- if (state == State.TOP)
+ if (state == State.TOP) {
return;
+ }
copyMapValue(valueMap, from, to);
copyMapValue(whereAlways, from, to);
copyMapValue(whereNever, from, to);
@@ -109,10 +115,10 @@ public class TypeQualifierValueSet {
private static void addSourceSinkInfo(Map<ValueNumber, Set<SourceSinkInfo>> sourceSinkInfoSetMap, ValueNumber vn,
SourceSinkInfo sourceSinkInfo) {
Set<SourceSinkInfo> sourceSinkInfoSet = sourceSinkInfoSetMap.get(vn);
- if (sourceSinkInfoSet == null) {
- sourceSinkInfoSet = new HashSet<SourceSinkInfo>(3);
- sourceSinkInfoSetMap.put(vn, sourceSinkInfoSet);
- }
+ if (sourceSinkInfoSet == null) {
+ sourceSinkInfoSet = new HashSet<SourceSinkInfo>(3);
+ sourceSinkInfoSetMap.put(vn, sourceSinkInfoSet);
+ }
sourceSinkInfoSet.add(sourceSinkInfo);
}
@@ -143,11 +149,12 @@ public class TypeQualifierValueSet {
private static Set<? extends SourceSinkInfo> getSourceSinkInfoSet(Map<ValueNumber, Set<SourceSinkInfo>> sourceSinkInfoSetMap,
ValueNumber vn) {
Set<SourceSinkInfo> sourceSinkInfoSet = sourceSinkInfoSetMap.get(vn);
- if (sourceSinkInfoSet == null || sourceSinkInfoSet.isEmpty())
+ if (sourceSinkInfoSet == null || sourceSinkInfoSet.isEmpty()) {
return Collections.emptySet();
+ }
return sourceSinkInfoSet;
- }
+ }
private static Set<SourceSinkInfo> getOrCreateSourceSinkInfoSet(Map<ValueNumber, Set<SourceSinkInfo>> sourceSinkInfoSetMap,
ValueNumber vn) {
Set<SourceSinkInfo> sourceSinkInfoSet = sourceSinkInfoSetMap.get(vn);
@@ -321,11 +328,13 @@ public class TypeQualifierValueSet {
StringBuilder buf = new StringBuilder();
buf.append("{");
- boolean first = true;
+ // boolean first = true;
for (ValueNumber vn : interesting) {
FlowValue value = getValue(vn);
- if (value == FlowValue.TOP || /* !isStrict && */ value == FlowValue.UNKNOWN) continue;
+ if (value == FlowValue.TOP || /* !isStrict && */ value == FlowValue.UNKNOWN) {
+ continue;
+ }
if (buf.length() > 1) {
buf.append(", ");
}
@@ -352,12 +361,15 @@ public class TypeQualifierValueSet {
Set<? extends SourceSinkInfo> never = getSourceSinkInfoSet(whereNever, vn);
if (value != FlowValue.UNKNOWN || !always.equals(never)) {
buf.append("[");
- if (!always.isEmpty())
+ if (!always.isEmpty()) {
appendSourceSinkInfos(buf, "YES=", always);
- if (!always.isEmpty() && !never.isEmpty())
+ }
+ if (!always.isEmpty() && !never.isEmpty()) {
buf.append(",");
- if (!never.isEmpty())
+ }
+ if (!never.isEmpty()) {
appendSourceSinkInfos(buf, "NO=", never);
+ }
buf.append("]");
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/ValidationSecurityManager.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/ValidationSecurityManager.java
index 94bff99..ea6b050 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/ValidationSecurityManager.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/ValidationSecurityManager.java
@@ -30,53 +30,61 @@ final class ValidationSecurityManager extends SecurityManager {
static final ValidationSecurityManager INSTANCE = new ValidationSecurityManager();
+ final static ValidatorClassLoader VALIDATOR_LOADER = ValidatorClassLoader.INSTANCE;
+
-
-
static {
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
new RuntimeException("Creating ValidationSecurityManager #").printStackTrace();
+ }
}
public static <A extends Annotation> When sandboxedValidation(A proxy, TypeQualifierValidator<A> v, @CheckForNull
- Object constantValue) {
- if (performingValidation.get())
+ Object constantValue) {
+ if (performingValidation.get()) {
throw new IllegalStateException("recursive validation");
+ }
try {
performingValidation.set(Boolean.TRUE);
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
System.out.println("Performing validation in thread " + Thread.currentThread().getName());
+ }
try {
When result = v.forConstantValue(proxy, constantValue);
- if (!performingValidation.get())
+ if (!performingValidation.get()) {
throw new IllegalStateException("performingValidation not set when validation completes");
+ }
return result;
} catch (ClassCastException e) {
Class<? extends Annotation> c = proxy.getClass();
System.out.println(c.getName() + " extends " + c.getSuperclass().getName());
- for(Class<?> i : c.getInterfaces())
- System.out.println(" " + i.getName());
+ for(Class<?> i : c.getInterfaces()) {
+ System.out.println(" " + i.getName());
+ }
throw e;
}
-
+
} finally {
performingValidation.set(Boolean.FALSE);
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
System.out.println("Validation finished in thread " + Thread.currentThread().getName());
-
+ }
+
}
}
@Override
public void checkPermission(Permission perm) {
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
System.out.println("Checking for " + perm + " permission in thread " + Thread.currentThread().getName());
+ }
if (performingValidation.get() && inValidation()) {
SecurityException e = new SecurityException("No permissions granted while performing JSR-305 validation");
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
e.printStackTrace(System.out);
+ }
throw e;
}
@@ -84,13 +92,15 @@ final class ValidationSecurityManager extends SecurityManager {
@Override
public void checkPermission(Permission perm, Object context) {
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
System.out.println("Checking for " + perm + " permission with content in thread " + Thread.currentThread().getName());
-
+ }
+
if (performingValidation.get() && inValidation()) {
SecurityException e = new SecurityException("No permissions granted while performing JSR-305 validation");
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
e.printStackTrace(System.out);
+ }
throw e;
}
}
@@ -100,8 +110,9 @@ final class ValidationSecurityManager extends SecurityManager {
private boolean inValidation() {
for (Class<?> c : getClassContext()) {
if (TypeQualifierValidator.class.isAssignableFrom(c)
- || c.getClassLoader() == ValidatorClassLoader.INSTANCE)
+ || c.getClassLoader() == VALIDATOR_LOADER) {
return true;
+ }
}
return false;
}
@@ -115,4 +126,4 @@ final class ValidationSecurityManager extends SecurityManager {
};
-}
\ No newline at end of file
+}
diff --git a/src/java/edu/umd/cs/findbugs/ba/jsr305/ValidatorClassLoader.java b/src/java/edu/umd/cs/findbugs/ba/jsr305/ValidatorClassLoader.java
index 1c6f77c..d6fcfba 100644
--- a/src/java/edu/umd/cs/findbugs/ba/jsr305/ValidatorClassLoader.java
+++ b/src/java/edu/umd/cs/findbugs/ba/jsr305/ValidatorClassLoader.java
@@ -28,61 +28,71 @@ import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
class ValidatorClassLoader extends ClassLoader {
static {
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
new RuntimeException("Initialising ValidatorClassLoader").printStackTrace();
+ }
}
final static ValidatorClassLoader INSTANCE = new ValidatorClassLoader();
ValidatorClassLoader() {
super(ClassLoader.getSystemClassLoader().getParent());
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
new RuntimeException("Creating ValidatorClassLoader #").printStackTrace();
+ }
}
-
+
@Override
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
-
+
if (TypeQualifierValue.DEBUG_CLASSLOADING) {
- if (resolve)
+ if (resolve) {
System.out.println("Loading and resolving class for " + name);
- else System.out.println("Loading class for " + name);
+ } else {
+ System.out.println("Loading class for " + name);
+ }
}
-
+
return super.loadClass(name, resolve);
}
@Override
public Class<?> findClass(@DottedClassName String name) throws ClassNotFoundException {
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
System.out.println("Looking for class data for " + name);
-
- if (name.startsWith("javax.annotation"))
- return Class.forName(name);
-
+ }
+
+ if (name.startsWith("javax.annotation")) {
+ return Class.forName(name);
+ }
+
try {
- byte[] b = TypeQualifierValue.loadClassData(name);
+ byte[] b = TypeQualifierValue.loadClassData(name);
return findClass(name, b);
} catch (CheckedAnalysisException e) {
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
e.printStackTrace();
+ }
return super.findClass(name);
} catch (RuntimeException e) {
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
e.printStackTrace();
+ }
throw e;
}
}
-
+
private Class<?> findClass(@DottedClassName String name, byte [] b) {
try {
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
System.out.println("Loading " + b.length + " bytes for class " + name);
+ }
Class<?> result = defineClass(name, b, 0, b.length);
super.resolveClass(result);
- if (TypeQualifierValue.DEBUG_CLASSLOADING)
+ if (TypeQualifierValue.DEBUG_CLASSLOADING) {
System.out.println("defined class " + name);
+ }
return result;
} catch (RuntimeException e) {
e.printStackTrace();
@@ -91,7 +101,7 @@ class ValidatorClassLoader extends ClassLoader {
}
-
-
+
+
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/DerefFinder.java b/src/java/edu/umd/cs/findbugs/ba/npe/DerefFinder.java
index 7c27706..ec1dc89 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/DerefFinder.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/DerefFinder.java
@@ -67,8 +67,9 @@ public class DerefFinder {
public static UsagesRequiringNonNullValues getAnalysis(ClassContext classContext, Method method) {
XMethod thisMethod = classContext.getXClass().findMethod(method.getName(), method.getSignature(), method.isStatic());
- if (DEBUG)
+ if (DEBUG) {
System.out.println(thisMethod);
+ }
UsagesRequiringNonNullValues derefs = new UsagesRequiringNonNullValues();
try {
@@ -97,13 +98,15 @@ public class DerefFinder {
InstructionHandle exceptionThrowerHandle = basicBlock.getExceptionThrower();
Instruction exceptionThrower = exceptionThrowerHandle.getInstruction();
ValueNumberFrame vnaFrame = vna.getStartFact(basicBlock);
- if (!vnaFrame.isValid())
+ if (!vnaFrame.isValid()) {
continue;
+ }
ValueNumber valueNumber = vnaFrame.getInstance(exceptionThrower, cpg);
Location location = new Location(exceptionThrowerHandle, basicBlock);
- if (valueNumberForThis != valueNumber)
+ if (valueNumberForThis != valueNumber) {
derefs.add(location, valueNumber, PointerUsageRequiringNonNullValue.getPointerDereference());
+ }
}
}
@@ -122,14 +125,16 @@ public class DerefFinder {
// Check nonnull annotations
- for (int j = 0; j < numParams; j++)
+ for (int j = 0; j < numParams; j++) {
if (db.parameterMustBeNonNull(m, j)) {
int slot = sigParser.getSlotsFromTopOfStackForParameter(j);
ValueNumber valueNumber = valueNumberFrame.getStackValue(slot);
- if (valueNumberForThis != valueNumber)
+ if (valueNumberForThis != valueNumber) {
derefs.add(location, valueNumber,
PointerUsageRequiringNonNullValue.getPassedAsNonNullParameter(m, j));
+ }
}
+ }
// Check actual targets
try {
@@ -144,24 +149,28 @@ public class DerefFinder {
break;
}
BitSet foo = property.getAsBitSet();
- if (unconditionallyDereferencedNullArgSet == null)
+ if (unconditionallyDereferencedNullArgSet == null) {
unconditionallyDereferencedNullArgSet = foo;
- else
- unconditionallyDereferencedNullArgSet.intersects(foo);
- if (unconditionallyDereferencedNullArgSet.isEmpty())
+ } else {
+ unconditionallyDereferencedNullArgSet.and(foo);
+ }
+ if (unconditionallyDereferencedNullArgSet.isEmpty()) {
break;
+ }
}
if (unconditionallyDereferencedNullArgSet != null && !unconditionallyDereferencedNullArgSet.isEmpty()
- && valueNumberFrame.isValid())
+ && valueNumberFrame.isValid()) {
for (int j = unconditionallyDereferencedNullArgSet.nextSetBit(0); j >= 0; j = unconditionallyDereferencedNullArgSet
.nextSetBit(j + 1)) {
int slot = sigParser.getSlotsFromTopOfStackForParameter(j);
ValueNumber valueNumber = valueNumberFrame.getStackValue(slot);
- if (valueNumberForThis != valueNumber)
+ if (valueNumberForThis != valueNumber) {
derefs.add(location, valueNumber,
PointerUsageRequiringNonNullValue.getPassedAsNonNullParameter(m, j));
+ }
}
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
@@ -172,9 +181,10 @@ public class DerefFinder {
derefs.add(location, valueNumber, PointerUsageRequiringNonNullValue.getPointerNullChecked());
} else if (ins instanceof ARETURN && methodAnnotation == NullnessAnnotation.NONNULL) {
ValueNumber valueNumber = valueNumberFrame.getTopValue();
- if (valueNumberForThis != valueNumber)
+ if (valueNumberForThis != valueNumber) {
derefs.add(location, valueNumber,
PointerUsageRequiringNonNullValue.getReturnFromNonNullMethod(thisMethod));
+ }
} else if (ins instanceof PUTFIELD || ins instanceof PUTSTATIC) {
FieldInstruction inf = (FieldInstruction) ins;
@@ -183,8 +193,9 @@ public class DerefFinder {
.getResolvedAnnotation(field, false);
if (annotation == NullnessAnnotation.NONNULL) {
ValueNumber valueNumber = valueNumberFrame.getTopValue();
- if (valueNumberForThis != valueNumber)
+ if (valueNumberForThis != valueNumber) {
derefs.add(location, valueNumber, PointerUsageRequiringNonNullValue.getStoredIntoNonNullField(field));
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullConditionDecision.java b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullConditionDecision.java
index f769bfb..7dbd310 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullConditionDecision.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullConditionDecision.java
@@ -30,7 +30,7 @@ import edu.umd.cs.findbugs.util.Util;
* A control decision which resulted in information being gained about whether a
* particular value is null or non-null on the IFCMP_EDGE and FALL_THROUGH_EDGE
* branches.
- *
+ *
* @see IsNullValue
* @see IsNullValueFrame
* @see IsNullValueAnalysis
@@ -47,7 +47,7 @@ public class IsNullConditionDecision {
/**
* Constructor.
- *
+ *
* @param value
* the ValueNumber for which we have new information; null if no
* new information
@@ -76,8 +76,9 @@ public class IsNullConditionDecision {
@Override
public boolean equals(Object o) {
- if (!(o instanceof IsNullConditionDecision))
+ if (!(o instanceof IsNullConditionDecision)) {
return false;
+ }
IsNullConditionDecision other = (IsNullConditionDecision) o;
return Util.nullSafeEquals(value, other.value) && Util.nullSafeEquals(ifcmpDecision, other.ifcmpDecision)
&& Util.nullSafeEquals(fallThroughDecision, other.fallThroughDecision);
@@ -101,7 +102,7 @@ public class IsNullConditionDecision {
* Determine whether or not the given edge is feasible. An edge may be
* infeasible if the comparison is redundant (i.e., can only be determined
* one way)
- *
+ *
* @param edgeType
* the type of edge; must be IFCMP_EDGE or FALL_THROUGH_EDGE
* @return true if the edge is feasible, false if infeasible
@@ -113,7 +114,7 @@ public class IsNullConditionDecision {
/**
* Get the decision reached about the value on outgoing edge of given type.
- *
+ *
* @param edgeType
* the type of edge; must be IFCMP_EDGE or FALL_THROUGH_EDGE
* @return the IsNullValue representing the decision, or null if the edge is
@@ -143,4 +144,3 @@ public class IsNullConditionDecision {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValue.java b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValue.java
index 7ee88cd..0fe6120 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValue.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValue.java
@@ -98,34 +98,34 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
private static final int FLAG_MASK = EXCEPTION | PARAM | RETURN_VAL | FIELD_VAL | READLINE_VAL;
private static final int[][] mergeMatrix = {
- // NULL, CHECKED_NULL, NN, CHECKED_NN, NO_KABOOM_NN, NSP,
- // NN_UNKNOWN, NCP2, NCP3
- { NULL }, // NULL
- { NULL, CHECKED_NULL, }, // CHECKED_NULL
- { NSP, NSP, NN }, // NN
- { NSP, NSP, NN, CHECKED_NN, }, // CHECKED_NN
- { NSP, NSP, NN, NN, NO_KABOOM_NN }, // NO_KABOOM_NN
- { NSP, NSP, NSP, NSP, NSP, NSP }, // NSP
- { NSP, NSP, NN_UNKNOWN, NN_UNKNOWN, NN_UNKNOWN, NSP, NN_UNKNOWN, }, // NN_UNKNOWN
- { NSP, NSP, NCP2, NCP2, NCP2, NSP, NCP2, NCP2, }, // NCP2
- { NSP, NSP, NCP3, NCP3, NCP3, NSP, NCP3, NCP3, NCP3 } // NCP3
+ // NULL, CHECKED_NULL, NN, CHECKED_NN, NO_KABOOM_NN, NSP,
+ // NN_UNKNOWN, NCP2, NCP3
+ { NULL }, // NULL
+ { NULL, CHECKED_NULL, }, // CHECKED_NULL
+ { NSP, NSP, NN }, // NN
+ { NSP, NSP, NN, CHECKED_NN, }, // CHECKED_NN
+ { NSP, NSP, NN, NN, NO_KABOOM_NN }, // NO_KABOOM_NN
+ { NSP, NSP, NSP, NSP, NSP, NSP }, // NSP
+ { NSP, NSP, NN_UNKNOWN, NN_UNKNOWN, NN_UNKNOWN, NSP, NN_UNKNOWN, }, // NN_UNKNOWN
+ { NSP, NSP, NCP2, NCP2, NCP2, NSP, NCP2, NCP2, }, // NCP2
+ { NSP, NSP, NCP3, NCP3, NCP3, NSP, NCP3, NCP3, NCP3 } // NCP3
};
private static final IsNullValue[][] instanceByFlagsList = createInstanceByFlagList();
private static IsNullValue[][] createInstanceByFlagList() {
final int max = FLAG_MASK >>> FLAG_SHIFT;
- IsNullValue[][] result = new IsNullValue[max + 1][];
- for (int i = 0; i <= max; ++i) {
- final int flags = i << FLAG_SHIFT;
- result[i] = new IsNullValue[] { new IsNullValue(NULL | flags), new IsNullValue(CHECKED_NULL | flags),
- new IsNullValue(NN | flags), new IsNullValue(CHECKED_NN | flags),
- null, // NO_KABOOM_NN values must be allocated dynamically
- new IsNullValue(NSP | flags), new IsNullValue(NN_UNKNOWN | flags), new IsNullValue(NCP2 | flags),
- new IsNullValue(NCP3 | flags), };
- }
+ IsNullValue[][] result = new IsNullValue[max + 1][];
+ for (int i = 0; i <= max; ++i) {
+ final int flags = i << FLAG_SHIFT;
+ result[i] = new IsNullValue[] { new IsNullValue(NULL | flags), new IsNullValue(CHECKED_NULL | flags),
+ new IsNullValue(NN | flags), new IsNullValue(CHECKED_NN | flags),
+ null, // NO_KABOOM_NN values must be allocated dynamically
+ new IsNullValue(NSP | flags), new IsNullValue(NN_UNKNOWN | flags), new IsNullValue(NCP2 | flags),
+ new IsNullValue(NCP3 | flags), };
+ }
- return result;
+ return result;
}
// Fields
@@ -136,15 +136,17 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
private IsNullValue(int kind) {
this.kind = kind;
locationOfKaBoom = null;
- if (VERIFY_INTEGRITY)
+ if (VERIFY_INTEGRITY) {
checkNoKaboomNNLocation();
+ }
}
private IsNullValue(int kind, Location ins) {
this.kind = kind;
locationOfKaBoom = ins;
- if (VERIFY_INTEGRITY)
+ if (VERIFY_INTEGRITY) {
checkNoKaboomNNLocation();
+ }
}
private void checkNoKaboomNNLocation() {
@@ -155,23 +157,28 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
@Override
public boolean equals(Object o) {
- if (o == null || this.getClass() != o.getClass())
+ if (o == null || this.getClass() != o.getClass()) {
return false;
+ }
IsNullValue other = (IsNullValue) o;
- if (kind != other.kind)
+ if (kind != other.kind) {
return false;
- if (locationOfKaBoom == other.locationOfKaBoom)
+ }
+ if (locationOfKaBoom == other.locationOfKaBoom) {
return true;
- if (locationOfKaBoom == null || other.locationOfKaBoom == null)
+ }
+ if (locationOfKaBoom == null || other.locationOfKaBoom == null) {
return false;
+ }
return locationOfKaBoom.equals(other.locationOfKaBoom);
}
@Override
public int hashCode() {
int hashCode = kind;
- if (locationOfKaBoom != null)
+ if (locationOfKaBoom != null) {
hashCode += locationOfKaBoom.hashCode();
+ }
return hashCode;
}
@@ -231,16 +238,19 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
return getBaseKind() == NO_KABOOM_NN;
}
+ /*
private IsNullValue toBaseValue() {
return instanceByFlagsList[0][getBaseKind()];
}
+ */
/**
* Convert to an exception path value.
*/
public IsNullValue toExceptionValue() {
- if (getBaseKind() == NO_KABOOM_NN)
+ if (getBaseKind() == NO_KABOOM_NN) {
return new IsNullValue(kind | EXCEPTION, locationOfKaBoom);
+ }
return instanceByFlagsList[(getFlags() | EXCEPTION) >> FLAG_SHIFT][getBaseKind()];
}
@@ -259,10 +269,12 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
}
int flag = RETURN_VAL;
- if (methodInvoked.getName().equals("readLine") && methodInvoked.getSignature().equals("()Ljava/lang/String;"))
+ if ("readLine".equals(methodInvoked.getName()) && "()Ljava/lang/String;".equals(methodInvoked.getSignature())) {
flag = READLINE_VAL;
- if (getBaseKind() == NO_KABOOM_NN)
+ }
+ if (getBaseKind() == NO_KABOOM_NN) {
return new IsNullValue(kind | flag, locationOfKaBoom);
+ }
return instanceByFlagsList[(getFlags() | flag) >> FLAG_SHIFT][getBaseKind()];
}
@@ -274,8 +286,9 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
* TODO
*/
public IsNullValue markInformationAsComingFromFieldValue(XField field) {
- if (getBaseKind() == NO_KABOOM_NN)
+ if (getBaseKind() == NO_KABOOM_NN) {
return new IsNullValue(kind | FIELD_VAL, locationOfKaBoom);
+ }
return instanceByFlagsList[(getFlags() | FIELD_VAL) >> FLAG_SHIFT][getBaseKind()];
}
@@ -315,8 +328,9 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
* would have occurred if it were null.
*/
public static IsNullValue noKaboomNonNullValue(@Nonnull Location ins) {
- if (ins == null)
+ if (ins == null) {
throw new NullPointerException("ins cannot be null");
+ }
return new IsNullValue(NO_KABOOM_NN, ins);
}
@@ -384,10 +398,12 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
* Merge two values.
*/
public static IsNullValue merge(IsNullValue a, IsNullValue b) {
- if (a == b)
+ if (a == b) {
return a;
- if (a.equals(b))
+ }
+ if (a.equals(b)) {
return a;
+ }
int aKind = a.kind & 0xff;
int bKind = b.kind & 0xff;
int aFlags = a.getFlags();
@@ -395,10 +411,11 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
int combinedFlags = aFlags & bFlags;
- if (!(a.isNullOnSomePath() || a.isDefinitelyNull()) && b.isException())
+ if (!(a.isNullOnSomePath() || a.isDefinitelyNull()) && b.isException()) {
combinedFlags |= EXCEPTION;
- else if (!(b.isNullOnSomePath() || b.isDefinitelyNull()) && a.isException())
+ } else if (!(b.isNullOnSomePath() || b.isDefinitelyNull()) && a.isException()) {
combinedFlags |= EXCEPTION;
+ }
// Left hand value should be >=, since it is used
// as the first dimension of the matrix to index.
@@ -488,17 +505,21 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
String pfx = "";
if (DEBUG_EXCEPTION) {
int flags = getFlags();
- if (flags == 0)
+ if (flags == 0) {
pfx = "_";
- else {
- if ((flags & EXCEPTION) != 0)
+ } else {
+ if ((flags & EXCEPTION) != 0) {
pfx += "e";
- if ((flags & PARAM) != 0)
+ }
+ if ((flags & PARAM) != 0) {
pfx += "p";
- if ((flags & RETURN_VAL) != 0)
+ }
+ if ((flags & RETURN_VAL) != 0) {
pfx += "r";
- if ((flags & FIELD_VAL) != 0)
+ }
+ if ((flags & FIELD_VAL) != 0) {
pfx += "f";
+ }
}
}
if (DEBUG_KABOOM && locationOfKaBoom == null) {
@@ -542,19 +563,19 @@ public class IsNullValue implements IsNullValueAnalysisFeatures, Debug {
if (NCP_EXTRA_BRANCH) {
// Experimental: track two distinct kinds of "null on complex path"
// values.
- if (value.isNullOnSomePath())
+ if (value.isNullOnSomePath()) {
value = nullOnComplexPathValue();
- else if (value.equals(nullOnComplexPathValue()))
+ } else if (value.equals(nullOnComplexPathValue())) {
value = nullOnComplexPathValue3();
+ }
} else {
// Downgrade "null on simple path" values to
// "null on complex path".
- if (value.isNullOnSomePath())
+ if (value.isNullOnSomePath()) {
value = nullOnComplexPathValue();
+ }
}
return value;
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueAnalysis.java
index 9f6baeb..09ea18c 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueAnalysis.java
@@ -70,12 +70,13 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
* @see IsNullValueFrameModelingVisitor
*/
public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNullValueFrame> implements EdgeTypes,
- IsNullValueAnalysisFeatures {
+IsNullValueAnalysisFeatures {
static final boolean DEBUG = SystemProperties.getBoolean("inva.debug");
static {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("inva.debug enabled");
+ }
}
private final MethodGen methodGen;
@@ -140,24 +141,27 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
state = PointerEqualityCheckState.START;
break;
case START:
- if (ins instanceof org.apache.bcel.generic.ALOAD)
+ if (ins instanceof org.apache.bcel.generic.ALOAD) {
state = PointerEqualityCheckState.SAW1;
- else
+ } else {
return null;
+ }
break;
case SAW1:
- if (ins instanceof org.apache.bcel.generic.ALOAD)
+ if (ins instanceof org.apache.bcel.generic.ALOAD) {
state = PointerEqualityCheckState.SAW2;
- else
+ } else {
return null;
+ }
break;
case SAW2:
if (ins instanceof org.apache.bcel.generic.IF_ACMPNE) {
state = PointerEqualityCheckState.IFEQUAL;
target = ((IF_ACMPNE) ins).getIndex() + loc.getHandle().getPosition();
test = loc;
- } else
+ } else {
return null;
+ }
break;
case IFEQUAL:
if (ins instanceof org.apache.bcel.generic.ReturnInstruction || ins instanceof ATHROW) {
@@ -175,9 +179,9 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
} catch (DataflowAnalysisException e) {
return null;
}
- } else
+ } else {
return null;
-
+ }
}
}
return null;
@@ -185,12 +189,15 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
private @CheckForNull
ValueNumber getKnownNonnullDueToPointerDisequality(ValueNumber knownNull, int pc) {
- if (pointerEqualityCheck == null || pc < pointerEqualityCheck.firstValuePC)
+ if (pointerEqualityCheck == null || pc < pointerEqualityCheck.firstValuePC) {
return null;
- if (pointerEqualityCheck.reg1.equals(knownNull))
+ }
+ if (pointerEqualityCheck.reg1.equals(knownNull)) {
return pointerEqualityCheck.reg2;
- if (pointerEqualityCheck.reg2.equals(knownNull))
+ }
+ if (pointerEqualityCheck.reg2.equals(knownNull)) {
return pointerEqualityCheck.reg1;
+ }
return null;
}
@@ -214,10 +221,12 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
return classAndMethod;
}
+ @Override
public IsNullValueFrame createFact() {
return new IsNullValueFrame(methodGen.getMaxLocals(), trackValueNumbers);
}
+ @Override
public void initEntryFact(IsNullValueFrame result) {
if (cachedEntryFact == null) {
@@ -234,8 +243,9 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
for (int i = 0; i < numLocals; ++i) {
cachedEntryFact.setValue(i, IsNullValue.nonReportingNotNullValue());
}
- if (paramShift == 1)
+ if (paramShift == 1) {
cachedEntryFact.setValue(0, IsNullValue.nonNullValue());
+ }
int slot = paramShift;
for (int paramIndex = 0; paramIndex < argumentTypes.length; paramIndex++) {
@@ -243,17 +253,19 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
XMethodParameter methodParameter = new XMethodParameter(xm, paramIndex);
NullnessAnnotation n = db.getResolvedAnnotation(methodParameter, false);
- if (n == NullnessAnnotation.CHECK_FOR_NULL)
+ if (n == NullnessAnnotation.CHECK_FOR_NULL) {
// Parameter declared @CheckForNull
value = IsNullValue.parameterMarkedAsMightBeNull(methodParameter);
- else if (n == NullnessAnnotation.NONNULL)
+ } else if (n == NullnessAnnotation.NONNULL) {
// Parameter declared @NonNull
// TODO: label this so we don't report defensive programming
- value = false ? IsNullValue.nonNullValue() : IsNullValue.parameterMarkedAsNonnull(methodParameter);
- else
+ // value = false ? IsNullValue.nonNullValue() : IsNullValue.parameterMarkedAsNonnull(methodParameter);
+ value = IsNullValue.parameterMarkedAsNonnull(methodParameter);
+ } else {
// Don't know; use default value, normally non-reporting
// nonnull
value = IsNullValue.nonReportingNotNullValue();
+ }
cachedEntryFact.setValue(slot, value);
@@ -273,8 +285,9 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
if (end == null) {
ValueNumberFrame vnaFrameAfter = vnaDataflow.getFactAfterLocation(Location.getLastLocation(basicBlock));
// purge stale information
- if (!vnaFrameAfter.isTop())
+ if (!vnaFrameAfter.isTop()) {
result.cleanStaleKnowledge(vnaFrameAfter);
+ }
}
}
@@ -288,9 +301,9 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
throws DataflowAnalysisException {
// Determine if this basic block ends in a redundant branch.
if (end == null) {
- if (lastFrame == null)
+ if (lastFrame == null) {
result.setDecision(null);
- else {
+ } else {
IsNullConditionDecision decision = getDecision(basicBlock, lastFrame);
result.setDecision(decision);
}
@@ -303,8 +316,9 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, IsNullValueFrame fact)
throws DataflowAnalysisException {
- if (!fact.isValid())
+ if (!fact.isValid()) {
return;
+ }
// If this is the last instruction in the block,
// save the result immediately before the instruction.
@@ -323,8 +337,9 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
Instruction ins = handle.getInstruction();
visitor.analyzeInstruction(ins);
- if (!fact.isValid())
+ if (!fact.isValid()) {
return;
+ }
// Special case:
// The instruction may have produced previously seen values
@@ -334,15 +349,16 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
// Also, make a note of any newly-produced null values.
int numProduced = ins.produceStack(methodGen.getConstantPool());
- if (numProduced == Constants.UNPREDICTABLE)
+ if (numProduced == Constants.UNPREDICTABLE) {
throw new DataflowAnalysisException("Unpredictable stack production", methodGen, handle);
+ }
int start = fact.getNumSlots() - numProduced;
Location location = new Location(handle, basicBlock);
ValueNumberFrame vnaFrameAfter = vnaDataflow.getFactAfterLocation(location);
if (!vnaFrameAfter.isValid()) {
assert false : "Invalid VNA after location " + location + " in " + SignatureConverter.convertMethodSignature(methodGen);
- return;
+ return;
}
for (int i = start; i < fact.getNumSlots(); ++i) {
ValueNumber value = vnaFrameAfter.getValue(i);
@@ -362,8 +378,8 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
if (visitor.getSlotContainingNewNullValue() >= 0) {
ValueNumber newNullValue = vnaFrameAfter.getValue(visitor.getSlotContainingNewNullValue());
addLocationWhereValueBecomesNull(new LocationWhereValueBecomesNull(location, newNullValue// ,
- // handle
- ));
+ // handle
+ ));
}
}
@@ -372,12 +388,12 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
static {
nullComparisonInstructionSet.set(Constants.IFNULL);
-
nullComparisonInstructionSet.set(Constants.IFNONNULL);
nullComparisonInstructionSet.set(Constants.IF_ACMPEQ);
nullComparisonInstructionSet.set(Constants.IF_ACMPNE);
}
+ @Override
public void meetInto(IsNullValueFrame fact, Edge edge, IsNullValueFrame result) throws DataflowAnalysisException {
meetInto(fact, edge, result, true);
}
@@ -391,7 +407,7 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
if (!NO_SPLIT_DOWNGRADE_NSP) {
// Downgrade NSP to DNR on non-exception control splits
if (!edge.isExceptionEdge() && cfg.getNumNonExceptionSucessors(edge.getSource()) > 1) {
- tmpFact = modifyFrame(fact, tmpFact);
+ tmpFact = modifyFrame(fact, null);
tmpFact.downgradeOnControlSplit();
}
}
@@ -418,12 +434,13 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
ObjectType catchType = handler.getCatchType();
if (catchType != null) {
String catchClass = catchType.getClassName();
- if (catchClass.equals("java.lang.CloneNotSupportedException")
- || catchClass.equals("java.lang.InterruptedException")) {
+ if ("java.lang.CloneNotSupportedException".equals(catchClass)
+ || "java.lang.InterruptedException".equals(catchClass)) {
for (int i = 0; i < tmpFact.getNumSlots(); ++i) {
IsNullValue value = tmpFact.getValue(i);
- if (value.isDefinitelyNull() || value.isNullOnSomePath())
+ if (value.isDefinitelyNull() || value.isNullOnSomePath()) {
tmpFact.setValue(i, IsNullValue.nullOnComplexPathValue());
+ }
}
}
}
@@ -488,24 +505,25 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
addLocationWhereValueBecomesNull(new LocationWhereValueBecomesNull(atIf, valueTested));
ValueNumber knownNonnull = getKnownNonnullDueToPointerDisequality(valueTested, atIf
.getHandle().getPosition());
- if (knownNonnull != null)
+ if (knownNonnull != null) {
tmpFact = replaceValues(fact, tmpFact, knownNonnull, prevVnaFrame, targetVnaFrame,
IsNullValue.checkedNonNullValue());
+ }
}
}
-
}
}
}
} // if (edgeType == IFCMP_EDGE || edgeType ==
- // FALL_THROUGH_EDGE)
+ // FALL_THROUGH_EDGE)
// If this is a fall-through edge from a null check,
// then we know the value checked is not null.
if (sourceBlock.isNullCheck() && edgeType == FALL_THROUGH_EDGE) {
ValueNumberFrame vnaFrame = vnaDataflow.getStartFact(destBlock);
- if (vnaFrame == null)
+ if (vnaFrame == null) {
throw new IllegalStateException("no vna frame at block entry?");
+ }
Instruction firstInDest = edge.getTarget().getFirstInstruction().getInstruction();
@@ -535,11 +553,12 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
tmpFact = replaceValues(fact, tmpFact, replaceMe, vnaFrame, targetVnaFrame, noKaboomNonNullValue);
}
} // if (sourceBlock.isNullCheck() && edgeType ==
- // FALL_THROUGH_EDGE)
+ // FALL_THROUGH_EDGE)
if (propagatePhiNodeInformation && targetVnaFrame.phiNodeForLoads) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Is phi node for loads");
+ }
for (ValueNumber v : fact.getKnownValues()) {
AvailableLoad loadForV = sourceVnaFrame.getLoad(v);
if (DEBUG) {
@@ -547,20 +566,22 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
}
if (loadForV != null) {
ValueNumber[] matchingValueNumbers = targetVnaFrame.getAvailableLoad(loadForV);
- if (matchingValueNumbers != null)
+ if (matchingValueNumbers != null) {
for (ValueNumber v2 : matchingValueNumbers) {
tmpFact = modifyFrame(fact, tmpFact);
tmpFact.useNewValueNumberForLoad(v, v2);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("For " + loadForV + " switch from " + v + " to " + v2);
+ }
}
+ }
}
-
}
}
}
- if (tmpFact != null)
+ if (tmpFact != null) {
fact = tmpFact;
+ }
} // if (fact.isValid())
if (DEBUG) {
@@ -575,17 +596,11 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
}
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.FrameDataflowAnalysis#mergeInto(edu.umd.cs.findbugs
- * .ba.Frame, edu.umd.cs.findbugs.ba.Frame)
- */
@Override
protected void mergeInto(IsNullValueFrame other, IsNullValueFrame result) throws DataflowAnalysisException {
- if (other.isTop())
+ if (other.isTop()) {
return;
+ }
if (result.isTop()) {
result.copyFrom(other);
return;
@@ -598,11 +613,6 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#startIteration()
- */
@Override
public void startIteration() {
// At the beginning of each iteration, clear the set of locations
@@ -646,22 +656,26 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
assert lastFrame != null;
final InstructionHandle lastInSourceHandle = basicBlock.getLastInstruction();
- if (lastInSourceHandle == null)
+ if (lastInSourceHandle == null) {
return null; // doesn't end in null comparison
+ }
final short lastInSourceOpcode = lastInSourceHandle.getInstruction().getOpcode();
if (lastInSourceOpcode == Constants.IFEQ || lastInSourceOpcode == Constants.IFNE) {
// check for instanceof check
InstructionHandle prev = lastInSourceHandle.getPrev();
- if (prev == null)
+ if (prev == null) {
return null;
+ }
short secondToLastOpcode = prev.getInstruction().getOpcode();
// System.out.println("Second last opcode: " +
// Constants.OPCODE_NAMES[secondToLastOpcode]);
- if (secondToLastOpcode != Constants.INSTANCEOF)
+ if (secondToLastOpcode != Constants.INSTANCEOF) {
return null;
- if (instanceOfFrame == null)
+ }
+ if (instanceOfFrame == null) {
return null;
+ }
IsNullValue tos = instanceOfFrame.getTopValue();
boolean isNotInstanceOf = (lastInSourceOpcode != Constants.IFNE);
Location atInstanceOf = new Location(prev, basicBlock);
@@ -673,11 +687,12 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
if (tos.isDefinitelyNull()) {
// Predetermined comparison - one branch is infeasible
- if (isNotInstanceOf)
+ if (isNotInstanceOf) {
ifcmpDecision = tos;
- else
+ } else {
// ifnonnull
fallThroughDecision = tos;
+ }
} else if (tos.isDefinitelyNotNull()) {
return null;
} else {
@@ -685,14 +700,15 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
ifcmpDecision = isNotInstanceOf ? tos : IsNullValue.pathSensitiveNonNullValue();
fallThroughDecision = isNotInstanceOf ? IsNullValue.pathSensitiveNonNullValue() : tos;
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Checking..." + tos + " -> " + ifcmpDecision + " or " + fallThroughDecision);
-
+ }
return new IsNullConditionDecision(instanceOfVnaFrame.getTopValue(), ifcmpDecision, fallThroughDecision);
-
}
- if (!nullComparisonInstructionSet.get(lastInSourceOpcode))
+
+ if (!nullComparisonInstructionSet.get(lastInSourceOpcode)) {
return null; // doesn't end in null comparison
+ }
Location atIf = new Location(lastInSourceHandle, basicBlock);
ValueNumberFrame prevVnaFrame = vnaDataflow.getFactAtLocation(atIf);
@@ -726,15 +742,17 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
// Redundant comparison: both values are null, only one branch
// is feasible
value = null; // no value will be replaced - just want to
- // indicate that one of the branches is infeasible
- if (cmpeq)
+ // indicate that one of the branches is infeasible
+ if (cmpeq) {
ifcmpDecision = IsNullValue.pathSensitiveNullValue();
- else
+ } else {
// cmpne
fallThroughDecision = IsNullValue.pathSensitiveNullValue();
+ }
} else if (tosNull || nextToTosNull) {
- if (tosNull)
+ if (tosNull) {
return handleIfNull(nextToTos, prevVnaFrame.getStackValue(1), cmpeq);
+ }
assert nextToTosNull;
return handleIfNull(tos, prevVnaFrame.getStackValue(0), cmpeq);
@@ -779,18 +797,20 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
if (tos.isDefinitelyNull()) {
// Predetermined comparison - one branch is infeasible
- if (ifnull)
+ if (ifnull) {
ifcmpDecision = IsNullValue.pathSensitiveNullValue();
- else
+ } else {
// ifnonnull
fallThroughDecision = IsNullValue.pathSensitiveNullValue();
+ }
} else if (tos.isDefinitelyNotNull()) {
// Predetermined comparison - one branch is infeasible
- if (ifnull)
+ if (ifnull) {
fallThroughDecision = tos.wouldHaveBeenAKaboom() ? tos : IsNullValue.pathSensitiveNonNullValue();
- else
+ } else {
// ifnonnull
ifcmpDecision = tos.wouldHaveBeenAKaboom() ? tos : IsNullValue.pathSensitiveNonNullValue();
+ }
} else {
// As far as we know, both branches feasible
ifcmpDecision = ifnull ? IsNullValue.pathSensitiveNullValue() : IsNullValue.pathSensitiveNonNullValue();
@@ -822,9 +842,10 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
private IsNullValueFrame replaceValues(IsNullValueFrame origFrame, IsNullValueFrame frame, ValueNumber replaceMe,
ValueNumberFrame prevVnaFrame, ValueNumberFrame targetVnaFrame, IsNullValue replacementValue) {
- if (!targetVnaFrame.isValid())
+ if (!targetVnaFrame.isValid()) {
throw new IllegalArgumentException("Invalid frame in " + methodGen.getClassName() + "." + methodGen.getName() + " : "
+ methodGen.getSignature());
+ }
// If required, make a copy of the frame
frame = modifyFrame(origFrame, frame);
@@ -843,19 +864,24 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
if (DEBUG && loadForV != null) {
System.out.println("For " + replaceMe + " availableLoad is " + loadForV);
ValueNumber[] matchingValueNumbers = targetVnaFrame.getAvailableLoad(loadForV);
- if (matchingValueNumbers != null)
- for (ValueNumber v2 : matchingValueNumbers)
+ if (matchingValueNumbers != null) {
+ for (ValueNumber v2 : matchingValueNumbers) {
System.out.println(" matches " + v2);
+ }
+ }
}
if (loadForV != null) {
ValueNumber[] matchingValueNumbers = targetVnaFrame.getAvailableLoad(loadForV);
- if (matchingValueNumbers != null)
- for (ValueNumber v2 : matchingValueNumbers)
+ if (matchingValueNumbers != null) {
+ for (ValueNumber v2 : matchingValueNumbers) {
if (!replaceMe.equals(v2)) {
frame.setKnownValue(v2, replacementValue);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("For " + loadForV + " switch from " + replaceMe + " to " + v2);
+ }
}
+ }
+ }
}
frame.setKnownValue(replaceMe, replacementValue);
}
@@ -876,8 +902,9 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
if (prevVnaFrame.getValue(i).equals(replaceMe)) {
ValueNumber corresponding = targetVnaFrame.getValue(i);
for (int j = 0; j < targetNumSlots; ++j) {
- if (targetVnaFrame.getValue(j).equals(corresponding))
+ if (targetVnaFrame.getValue(j).equals(corresponding)) {
frame.setValue(j, replacementValue);
+ }
}
}
}
@@ -902,5 +929,3 @@ public class IsNullValueAnalysis extends FrameDataflowAnalysis<IsNullValue, IsNu
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueAnalysisFeatures.java b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueAnalysisFeatures.java
index 7d9e46d..dec2fa8 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueAnalysisFeatures.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueAnalysisFeatures.java
@@ -26,7 +26,7 @@ import edu.umd.cs.findbugs.SystemProperties;
/**
* Knobs for null value analysis.
- *
+ *
* @author David Hovemeyer
*/
public interface IsNullValueAnalysisFeatures {
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueDataflow.java b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueDataflow.java
index f222803..bf6d5e4 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueDataflow.java
@@ -35,4 +35,3 @@ public class IsNullValueDataflow extends AbstractDataflow<IsNullValueFrame, IsNu
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueFrame.java b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueFrame.java
index 9f4be55..865a9b6 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueFrame.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueFrame.java
@@ -60,10 +60,12 @@ public class IsNullValueFrame extends Frame<IsNullValue> {
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (!(obj instanceof PointerEqualityInfo))
+ }
+ if (!(obj instanceof PointerEqualityInfo)) {
return false;
+ }
PointerEqualityInfo other = (PointerEqualityInfo) obj;
return this.addr1.equals(other.addr1) && this.addr2.equals(other.addr2) && this.areEqual == other.areEqual;
}
@@ -89,17 +91,21 @@ public class IsNullValueFrame extends Frame<IsNullValue> {
}
public void cleanStaleKnowledge(ValueNumberFrame vnaFrameAfter) {
- if (vnaFrameAfter.isTop() && !isTop())
+ if (vnaFrameAfter.isTop() && !isTop()) {
throw new IllegalArgumentException("VNA frame is top");
- if (!trackValueNumbers)
+ }
+ if (!trackValueNumbers) {
return;
- if (!ValueNumberAnalysisFeatures.REDUNDANT_LOAD_ELIMINATION)
+ }
+ if (!ValueNumberAnalysisFeatures.REDUNDANT_LOAD_ELIMINATION) {
return;
+ }
for (Iterator<ValueNumber> i = knownValueMap.keySet().iterator(); i.hasNext();) {
ValueNumber v = i.next();
if (vnaFrameAfter.getLoad(v) == null) {
- if (IsNullValueAnalysis.DEBUG)
+ if (IsNullValueAnalysis.DEBUG) {
System.out.println("PURGING " + v);
+ }
i.remove();
}
}
@@ -116,8 +122,9 @@ public class IsNullValueFrame extends Frame<IsNullValue> {
}
public void toExceptionValues() {
- for (int i = 0; i < getNumSlots(); ++i)
+ for (int i = 0; i < getNumSlots(); ++i) {
setValue(i, getValue(i).toExceptionValue());
+ }
if (trackValueNumbers) {
Map<ValueNumber, IsNullValue> replaceMap = new HashMap<ValueNumber, IsNullValue>();
@@ -139,8 +146,9 @@ public class IsNullValueFrame extends Frame<IsNullValue> {
public void setKnownValue(@Nonnull ValueNumber valueNumber, @Nonnull IsNullValue knownValue) {
assert trackValueNumbers;
- if (valueNumber == null || knownValue == null)
+ if (valueNumber == null || knownValue == null) {
throw new NullPointerException();
+ }
knownValueMap.put(valueNumber, knownValue);
if (IsNullValueAnalysis.DEBUG) {
System.out.println("Updated information for " + valueNumber);
@@ -149,10 +157,12 @@ public class IsNullValueFrame extends Frame<IsNullValue> {
}
public void useNewValueNumberForLoad(ValueNumber oldValueNumber, ValueNumber newValueNumber) {
- if (oldValueNumber == null || newValueNumber == null)
+ if (oldValueNumber == null || newValueNumber == null) {
throw new NullPointerException();
- if (newValueNumber.equals(oldValueNumber) || !trackValueNumbers)
+ }
+ if (newValueNumber.equals(oldValueNumber) || !trackValueNumbers) {
return;
+ }
IsNullValue isNullValue = knownValueMap.get(oldValueNumber);
if (isNullValue != null) {
knownValueMap.put(newValueNumber, isNullValue);
@@ -232,15 +242,19 @@ public class IsNullValueFrame extends Frame<IsNullValue> {
@Override
public boolean sameAs(Frame<IsNullValue> other) {
- if (!(other instanceof IsNullValueFrame))
+ if (!(other instanceof IsNullValueFrame)) {
return false;
- if (!super.sameAs(other))
+ }
+ if (!super.sameAs(other)) {
return false;
+ }
IsNullValueFrame o2 = (IsNullValueFrame) other;
- if (!Util.nullSafeEquals(decision, o2.decision))
+ if (!Util.nullSafeEquals(decision, o2.decision)) {
return false;
- if (trackValueNumbers && !Util.nullSafeEquals(knownValueMap, o2.knownValueMap))
+ }
+ if (trackValueNumbers && !Util.nullSafeEquals(knownValueMap, o2.knownValueMap)) {
return false;
+ }
return true;
}
@@ -292,4 +306,3 @@ public class IsNullValueFrame extends Frame<IsNullValue> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueFrameModelingVisitor.java b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueFrameModelingVisitor.java
index 87b662e..f0f8cb3 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueFrameModelingVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/IsNullValueFrameModelingVisitor.java
@@ -98,12 +98,14 @@ public class IsNullValueFrameModelingVisitor extends AbstractFrameModelingVisito
*/
@Override
public void analyzeInstruction(Instruction ins) throws DataflowAnalysisException {
- if (!getFrame().isValid())
+ if (!getFrame().isValid()) {
return;
+ }
slotContainingNewNullValue = -1;
super.analyzeInstruction(ins);
- if (!getFrame().isValid())
+ if (!getFrame().isValid()) {
return;
+ }
if (!NO_ASSERT_HACK) {
if (assertionMethods.isAssertionHandle(getLocation().getHandle(), cpg)) {
@@ -116,8 +118,9 @@ public class IsNullValueFrameModelingVisitor extends AbstractFrameModelingVisito
}
for (Map.Entry<ValueNumber, IsNullValue> e : frame.getKnownValueMapEntrySet()) {
IsNullValue value = e.getValue();
- if (value.isDefinitelyNull() || value.isNullOnSomePath())
+ if (value.isDefinitelyNull() || value.isNullOnSomePath()) {
e.setValue(IsNullValue.nonReportingNotNullValue());
+ }
}
}
@@ -174,7 +177,7 @@ public class IsNullValueFrameModelingVisitor extends AbstractFrameModelingVisito
Location location = getLocation();
- if (trackValueNumbers)
+ if (trackValueNumbers) {
try {
ValueNumberFrame vnaFrame = vnaDataflow.getFactAtLocation(location);
Set<ValueNumber> nonnullParameters = UnconditionalValueDerefAnalysis.checkAllNonNullParams(location, vnaFrame,
@@ -208,7 +211,8 @@ public class IsNullValueFrameModelingVisitor extends AbstractFrameModelingVisito
} catch (DataflowAnalysisException e) {
AnalysisContext.logError("Error looking up nonnull parameters for invoked method", e);
}
- // Determine if we are going to model the return value of this call.
+ }
+ // Determine if we are going to model the return value of this call.
boolean modelCallReturnValue = MODEL_NONNULL_RETURN && returnType instanceof ReferenceType;
if (!modelCallReturnValue) {
@@ -227,12 +231,15 @@ public class IsNullValueFrameModelingVisitor extends AbstractFrameModelingVisito
if (targetSet.isEmpty()) {
XMethod calledMethod = XFactory.createXMethod(obj, getCPG());
result = getReturnValueNullness(calledMethod);
- } else for (XMethod calledMethod : targetSet) {
- IsNullValue pushValue = getReturnValueNullness(calledMethod);
- if (result == null)
- result = pushValue;
- else
- result = IsNullValue.merge(result, pushValue);
+ } else {
+ for (XMethod calledMethod : targetSet) {
+ IsNullValue pushValue = getReturnValueNullness(calledMethod);
+ if (result == null) {
+ result = pushValue;
+ } else {
+ result = IsNullValue.merge(result, pushValue);
+ }
+ }
}
} catch (DataflowAnalysisException e) {
result = IsNullValue.nonReportingNotNullValue();
@@ -247,8 +254,9 @@ public class IsNullValueFrameModelingVisitor extends AbstractFrameModelingVisito
public IsNullValue getReturnValueNullness(XMethod calledMethod) {
IsNullValue pushValue;
- if (IsNullValueAnalysis.DEBUG)
+ if (IsNullValueAnalysis.DEBUG) {
System.out.println("Check " + calledMethod + " for null return...");
+ }
NullnessAnnotation annotation = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase()
.getResolvedAnnotation(calledMethod, false);
Boolean alwaysNonNull = AnalysisContext.currentAnalysisContext().getReturnValueNullnessPropertyDatabase()
@@ -317,19 +325,22 @@ public class IsNullValueFrameModelingVisitor extends AbstractFrameModelingVisito
}
super.visitPUTFIELD(obj);
XField field = XFactory.createXField(obj, cpg);
- if (nullValueStored != null && ValueNumberAnalysisFeatures.REDUNDANT_LOAD_ELIMINATION)
+ if (nullValueStored != null && ValueNumberAnalysisFeatures.REDUNDANT_LOAD_ELIMINATION) {
try {
ValueNumberFrame vnaFrameBefore = vnaDataflow.getFactAtLocation(getLocation());
ValueNumber refValue = vnaFrameBefore.getStackValue(1);
AvailableLoad load = new AvailableLoad(refValue, field);
ValueNumberFrame vnaFrameAfter = vnaDataflow.getFactAfterLocation(getLocation());
ValueNumber[] newValueNumbersForField = vnaFrameAfter.getAvailableLoad(load);
- if (newValueNumbersForField != null && trackValueNumbers)
- for (ValueNumber v : newValueNumbersForField)
+ if (newValueNumbersForField != null && trackValueNumbers) {
+ for (ValueNumber v : newValueNumbersForField) {
getFrame().setKnownValue(v, nullValueStored);
+ }
+ }
} catch (DataflowAnalysisException e) {
AnalysisContext.logError("Oops", e);
}
+ }
}
@Override
@@ -385,10 +396,11 @@ public class IsNullValueFrameModelingVisitor extends AbstractFrameModelingVisito
return;
}
}
- if (field.getClassName().equals("java.util.logging.Level") && field.getName().equals("SEVERE")
- || field.getClassName().equals("org.apache.log4j.Level")
- && (field.getName().equals("ERROR") || field.getName().equals("FATAL")))
+ if ("java.util.logging.Level".equals(field.getClassName()) && "SEVERE".equals(field.getName())
+ || "org.apache.log4j.Level".equals(field.getClassName())
+ && ("ERROR".equals(field.getName()) || "FATAL".equals(field.getName()))) {
getFrame().toExceptionValues();
+ }
if (field.getName().startsWith("class$")) {
produce(IsNullValue.nonNullValue());
@@ -508,4 +520,3 @@ public class IsNullValueFrameModelingVisitor extends AbstractFrameModelingVisito
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/LocationWhereValueBecomesNull.java b/src/java/edu/umd/cs/findbugs/ba/npe/LocationWhereValueBecomesNull.java
index 876d7ed..5857307 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/LocationWhereValueBecomesNull.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/LocationWhereValueBecomesNull.java
@@ -24,17 +24,17 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumber;
/**
* A Location where a particular value number becomes null.
- *
+ *
* @author David Hovemeyer
*/
public class LocationWhereValueBecomesNull implements Comparable<LocationWhereValueBecomesNull> {
- private Location location;
+ private final Location location;
- private ValueNumber valueNumber;
+ private final ValueNumber valueNumber;
/**
* Constructor.
- *
+ *
* @param location
* the Location where a value becomes null
* @param valueNumber
@@ -61,9 +61,10 @@ public class LocationWhereValueBecomesNull implements Comparable<LocationWhereVa
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
+ @Override
public int compareTo(LocationWhereValueBecomesNull o) {
int cmp = this.location.compareTo(o.location);
if (cmp != 0) {
@@ -75,7 +76,7 @@ public class LocationWhereValueBecomesNull implements Comparable<LocationWhereVa
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@@ -89,7 +90,7 @@ public class LocationWhereValueBecomesNull implements Comparable<LocationWhereVa
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/MayReturnNullPropertyDatabase.java b/src/java/edu/umd/cs/findbugs/ba/npe/MayReturnNullPropertyDatabase.java
index be52213..64f4ffd 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/MayReturnNullPropertyDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/MayReturnNullPropertyDatabase.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.ba.interproc.PropertyDatabaseFormatException;
/**
* MethodPropertyDatabase for keeping track of which methods may return null.
- *
+ *
* @author David Hovemeyer
* @deprecated
*/
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/NonNullParamViolation.java b/src/java/edu/umd/cs/findbugs/ba/npe/NonNullParamViolation.java
index d527e09..24bf636 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/NonNullParamViolation.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/NonNullParamViolation.java
@@ -22,9 +22,9 @@ package edu.umd.cs.findbugs.ba.npe;
import edu.umd.cs.findbugs.ba.JavaClassAndMethod;
public class NonNullParamViolation {
- private JavaClassAndMethod classAndMethod;
+ private final JavaClassAndMethod classAndMethod;
- private int param;
+ private final int param;
public NonNullParamViolation(JavaClassAndMethod classAndMethod, int param) {
this.classAndMethod = classAndMethod;
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/NullDerefAndRedundantComparisonFinder.java b/src/java/edu/umd/cs/findbugs/ba/npe/NullDerefAndRedundantComparisonFinder.java
index b3d6977..9cf9f5c 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/NullDerefAndRedundantComparisonFinder.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/NullDerefAndRedundantComparisonFinder.java
@@ -63,7 +63,6 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumber;
import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
import edu.umd.cs.findbugs.ba.vna.ValueNumberSourceInfo;
-import edu.umd.cs.findbugs.bcel.generic.NullnessConversationInstruction;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.log.Profiler;
@@ -109,8 +108,9 @@ public class NullDerefAndRedundantComparisonFinder {
private final AssertionMethods assertionMethods;
static {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("fnd.debug enabled");
+ }
}
/**
@@ -210,6 +210,8 @@ public class NullDerefAndRedundantComparisonFinder {
case Constants.IFNONNULL:
analyzeIfNullBranch(basicBlock, lastHandle);
break;
+ default:
+ break;
}
}
}
@@ -251,10 +253,10 @@ public class NullDerefAndRedundantComparisonFinder {
Map<ValueNumber, SortedSet<Location>> bugEdgeLocationMap = new HashMap<ValueNumber, SortedSet<Location>>();
checkEdges(cfg, nullValueGuaranteedDerefMap, bugEdgeLocationMap);
-
+
Map<ValueNumber, SortedSet<Location>> bugLocationMap = bugEdgeLocationMap;
bugLocationMap.putAll(bugStatementLocationMap);
-
+
// For each value number that is null somewhere in the
// method, collect the set of locations where it becomes null.
// FIXME: we may see some locations that are not guaranteed to be
@@ -264,35 +266,25 @@ public class NullDerefAndRedundantComparisonFinder {
reportBugs(nullValueGuaranteedDerefMap, npeIfStatementCovered, bugLocationMap, nullValueAssignmentMap);
}
- /**
- * @param locationWhereValueBecomesNullSet
- * @return
- */
public Map<ValueNumber, Set<Location>> findNullAssignments(Set<LocationWhereValueBecomesNull> locationWhereValueBecomesNullSet) {
Map<ValueNumber, Set<Location>> nullValueAssignmentMap = new HashMap<ValueNumber, Set<Location>>();
for (LocationWhereValueBecomesNull lwvbn : locationWhereValueBecomesNullSet) {
- if (DEBUG_DEREFS)
+ if (DEBUG_DEREFS) {
System.out.println("OOO " + lwvbn);
+ }
Set<Location> locationSet = nullValueAssignmentMap.get(lwvbn.getValueNumber());
if (locationSet == null) {
locationSet = new HashSet<Location>(4);
nullValueAssignmentMap.put(lwvbn.getValueNumber(), locationSet);
}
locationSet.add(lwvbn.getLocation());
- if (DEBUG_DEREFS)
+ if (DEBUG_DEREFS) {
System.out.println(lwvbn.getValueNumber() + " becomes null at " + lwvbn.getLocation());
+ }
}
return nullValueAssignmentMap;
}
- /**
- * @param nullValueGuaranteedDerefMap
- * @param npeIfStatementCovered
- * @param bugLocationMap
- * @param nullValueAssignmentMap
- * @throws CFGBuilderException
- * @throws DataflowAnalysisException
- */
public void reportBugs(Map<ValueNumber, NullValueUnconditionalDeref> nullValueGuaranteedDerefMap,
HashSet<ValueNumber> npeIfStatementCovered, Map<ValueNumber, SortedSet<Location>> bugLocationMap,
Map<ValueNumber, Set<Location>> nullValueAssignmentMap) throws CFGBuilderException, DataflowAnalysisException {
@@ -312,9 +304,10 @@ public class NullDerefAndRedundantComparisonFinder {
}
}
// TODO: figure out why this is failing
- if (false)
- assert false : "No assigned NullLocationSet for " + valueNumber + " in " + nullValueAssignmentMap.keySet()
- + " while analyzing " + classContext.getJavaClass().getClassName() + "." + method.getName();
+ // if (false) {
+ // assert false : "No assigned NullLocationSet for " + valueNumber + " in " + nullValueAssignmentMap.keySet()
+ // + " while analyzing " + classContext.getJavaClass().getClassName() + "." + method.getName();
+ // }
assignedNullLocationSet = Collections.<Location> emptySet();
}
SortedSet<Location> knownNullAndDoomedAt = bugLocationMap.get(valueNumber);
@@ -324,29 +317,35 @@ public class NullDerefAndRedundantComparisonFinder {
for (Location loc : derefLocationSet) {
variableAnnotation = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, loc, valueNumber,
vnaDataflow.getFactAtLocation(loc), "VALUE_OF");
- if (variableAnnotation != null)
+ if (variableAnnotation != null) {
break;
+ }
}
- if (variableAnnotation == null)
+ if (variableAnnotation == null) {
for (Location loc : knownNullAndDoomedAt) {
variableAnnotation = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, loc, valueNumber,
vnaDataflow.getFactAtLocation(loc), "VALUE_OF");
- if (variableAnnotation != null)
+ if (variableAnnotation != null) {
break;
+ }
}
- if (variableAnnotation == null)
+ }
+ if (variableAnnotation == null) {
for (Location loc : assignedNullLocationSet) {
variableAnnotation = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, loc, valueNumber,
vnaDataflow.getFactAtLocation(loc), "VALUE_OF");
- if (variableAnnotation != null)
+ if (variableAnnotation != null) {
break;
+ }
}
+ }
} catch (DataflowAnalysisException e2) {
}
- if (variableAnnotation == null)
+ if (variableAnnotation == null) {
variableAnnotation = new LocalVariableAnnotation("?", -1, derefLocationSet.iterator().next().getHandle()
.getPosition());
+ }
if (PRUNE_GUARANTEED_DEREFERENCES) {
PostDominatorsAnalysis postDomAnalysis = classContext.getNonExceptionPostDominatorsAnalysis(method);
@@ -364,12 +363,6 @@ public class NullDerefAndRedundantComparisonFinder {
}
}
- /**
- * @param cfg
- * @param nullValueGuaranteedDerefMap
- * @param bugEdgeLocationMap
- * @throws DataflowAnalysisException
- */
public void checkEdges(CFG cfg, Map<ValueNumber, NullValueUnconditionalDeref> nullValueGuaranteedDerefMap,
Map<ValueNumber, SortedSet<Location>> bugEdgeLocationMap) throws DataflowAnalysisException {
// Check every non-exception control edge
@@ -378,9 +371,10 @@ public class NullDerefAndRedundantComparisonFinder {
UnconditionalValueDerefSet uvdFact = uvdDataflow.getFactOnEdge(edge);
- if (uvdFact.isEmpty())
+ if (uvdFact.isEmpty()) {
continue;
-
+ }
+
if (edge.isExceptionEdge()) {
if (DEBUG_DEREFS) {
System.out.println("On exception edge " + edge.formatAsString(false));
@@ -400,16 +394,19 @@ public class NullDerefAndRedundantComparisonFinder {
Location location = null;
if (edge.isExceptionEdge()) {
BasicBlock b = cfg.getSuccessorWithEdgeType(source, EdgeTypes.FALL_THROUGH_EDGE);
- if (b != null)
+ if (b != null) {
location = new Location(source.getExceptionThrower(), b);
- } else
+ }
+ } else {
location = Location.getLastLocation(source);
+ }
if (location != null) {
Instruction in = location.getHandle().getInstruction();
if (assertionMethods.isAssertionInstruction(in, classContext.getConstantPoolGen())) {
- if (DEBUG_DEREFS)
+ if (DEBUG_DEREFS) {
System.out.println("Skipping because it is an assertion method ");
+ }
continue;
}
@@ -476,9 +473,7 @@ public class NullDerefAndRedundantComparisonFinder {
* location in the CFG.
*
* @param thisLocation
- * TODO
* @param knownNullAndDoomedAt
- * TODO
* @param nullValueGuaranteedDerefMap
* map to be populated with null values and where they are
* derefed
@@ -489,7 +484,6 @@ public class NullDerefAndRedundantComparisonFinder {
* @param derefSet
* set of unconditionally derefed values at this location
* @param isEdge
- * TODO
*/
private void checkForUnconditionallyDereferencedNullValues(Location thisLocation,
Map<ValueNumber, SortedSet<Location>> knownNullAndDoomedAt,
@@ -509,11 +503,11 @@ public class NullDerefAndRedundantComparisonFinder {
}
int slots;
- if (vnaFrame.getNumSlots() == invFrame.getNumSlots())
+ if (vnaFrame.getNumSlots() == invFrame.getNumSlots()) {
slots = vnaFrame.getNumSlots();
- else
+ } else {
slots = vnaFrame.getNumLocals();
-
+ /*
if (false) {
InstructionHandle handle = thisLocation.getHandle();
if (handle != null && handle.getInstruction() instanceof NullnessConversationInstruction) {
@@ -539,7 +533,8 @@ public class NullDerefAndRedundantComparisonFinder {
AnalysisContext.logError("huh", e);
}
}
-
+ }
+ */
}
// See if there are any definitely-null values in the frame
@@ -594,9 +589,7 @@ public class NullDerefAndRedundantComparisonFinder {
* dereferenced.
*
* @param thisLocation
- * TODO
* @param bugLocations
- * TODO
* @param nullValueGuaranteedDerefMap
* map of null values to sets of Locations where they are derefed
* @param derefSet
@@ -647,8 +640,9 @@ public class NullDerefAndRedundantComparisonFinder {
*/
private void examineRedundantBranches() {
for (RedundantBranch redundantBranch : redundantBranchList) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Redundant branch: " + redundantBranch);
+ }
int lineNumber = redundantBranch.lineNumber;
// The source to bytecode compiler may sometimes duplicate blocks of
@@ -665,22 +659,23 @@ public class NullDerefAndRedundantComparisonFinder {
boolean reportIt = true;
- if (lineMentionedMultipleTimes.get(lineNumber) && confused)
+ if (lineMentionedMultipleTimes.get(lineNumber) && confused) {
reportIt = false;
- else if (redundantBranch.location.getBasicBlock().isInJSRSubroutine() /*
- * occurs
- * in
- * a
- * JSR
- */
- && confused)
+ } else if (redundantBranch.location.getBasicBlock().isInJSRSubroutine() /*
+ * occurs
+ * in
+ * a
+ * JSR
+ */
+ && confused) {
reportIt = false;
- else {
+ } else {
int pc = redundantBranch.location.getHandle().getPosition();
for (CodeException e : method.getCode().getExceptionTable()) {
if (e.getCatchType() == 0 && e.getStartPC() != e.getHandlerPC() && e.getEndPC() <= pc
- && pc <= e.getEndPC() + 5)
+ && pc <= e.getEndPC() + 5) {
reportIt = false;
+ }
}
}
@@ -699,13 +694,15 @@ public class NullDerefAndRedundantComparisonFinder {
// Probably dead code due to pruning infeasible exception edges.
return;
}
- if (frame.getStackDepth() < 2)
+ if (frame.getStackDepth() < 2) {
throw new DataflowAnalysisException("Stack underflow at " + lastHandle);
+ }
// Find the line number.
int lineNumber = getLineNumber(method, lastHandle);
- if (lineNumber < 0)
+ if (lineNumber < 0) {
return;
+ }
int numSlots = frame.getNumSlots();
IsNullValue top = frame.getValue(numSlots - 1);
@@ -717,13 +714,15 @@ public class NullDerefAndRedundantComparisonFinder {
if (definitelySame || definitelyDifferent) {
if (definitelySame) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Line " + lineNumber + " always same");
+ }
definitelySameBranchSet.set(lineNumber);
}
if (definitelyDifferent) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Line " + lineNumber + " always different");
+ }
definitelyDifferentBranchSet.set(lineNumber);
}
@@ -736,17 +735,19 @@ public class NullDerefAndRedundantComparisonFinder {
Edge infeasibleEdge = invDataflow.getCFG().getOutgoingEdgeWithType(basicBlock, infeasibleEdgeType);
redundantBranch.setInfeasibleEdge(infeasibleEdge);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Adding redundant branch: " + redundantBranch);
+ }
redundantBranchList.add(redundantBranch);
} else {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Line " + lineNumber + " undetermined");
+ }
undeterminedBranchSet.set(lineNumber);
}
}
- // This is called for both IFNULL and IFNONNULL instructions.
+ /** This is called for both IFNULL and IFNONNULL instructions. */
private void analyzeIfNullBranch(BasicBlock basicBlock, InstructionHandle lastHandle) throws DataflowAnalysisException {
Location location = new Location(lastHandle, basicBlock);
@@ -762,12 +763,14 @@ public class NullDerefAndRedundantComparisonFinder {
// Find the line number.
int lineNumber = getLineNumber(method, lastHandle);
- if (lineNumber < 0)
+ if (lineNumber < 0) {
return;
+ }
if (!(top.isDefinitelyNull() || top.isDefinitelyNotNull())) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Line " + lineNumber + " undetermined");
+ }
undeterminedBranchSet.set(lineNumber);
return;
}
@@ -776,16 +779,19 @@ public class NullDerefAndRedundantComparisonFinder {
// or always not taken.
short opcode = lastHandle.getInstruction().getOpcode();
boolean definitelySame = top.isDefinitelyNull();
- if (opcode != Constants.IFNULL)
+ if (opcode != Constants.IFNULL) {
definitelySame = !definitelySame;
+ }
if (definitelySame) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Line " + lineNumber + " always same");
+ }
definitelySameBranchSet.set(lineNumber);
} else {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Line " + lineNumber + " always different");
+ }
definitelyDifferentBranchSet.set(lineNumber);
}
@@ -798,13 +804,14 @@ public class NullDerefAndRedundantComparisonFinder {
Edge infeasibleEdge = invDataflow.getCFG().getOutgoingEdgeWithType(basicBlock, infeasibleEdgeType);
redundantBranch.setInfeasibleEdge(infeasibleEdge);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Adding redundant branch: " + redundantBranch);
+ }
redundantBranchList.add(redundantBranch);
}
private void analyzeNullCheck(IsNullValueDataflow invDataflow, BasicBlock basicBlock) throws DataflowAnalysisException,
- CFGBuilderException {
+ CFGBuilderException {
// Look for null checks where the value checked is definitely
// null or null on some path.
@@ -813,8 +820,9 @@ public class NullDerefAndRedundantComparisonFinder {
// Get the stack values at entry to the null check.
IsNullValueFrame frame = invDataflow.getStartFact(basicBlock);
- if (!frame.isValid())
+ if (!frame.isValid()) {
return;
+ }
// Could the reference be null?
IsNullValue refValue = frame.getInstance(exceptionThrower, classContext.getConstantPoolGen());
@@ -822,20 +830,25 @@ public class NullDerefAndRedundantComparisonFinder {
System.out.println("For basic block " + basicBlock + " value is " + refValue);
}
if (refValue.isDefinitelyNotNull())
+ {
return;
- if (false && !refValue.mightBeNull())
- return;
+ // if (false && !refValue.mightBeNull())
+ // return;
+ }
- if (!refValue.isDefinitelyNull())
+ if (!refValue.isDefinitelyNull()) {
return;
+ }
// Get the value number
ValueNumberFrame vnaFrame = classContext.getValueNumberDataflow(method).getStartFact(basicBlock);
- if (!vnaFrame.isValid())
+ if (!vnaFrame.isValid()) {
return;
+ }
ValueNumber valueNumber = vnaFrame.getInstance(exceptionThrower, classContext.getConstantPoolGen());
Location location = new Location(exceptionThrowerHandle, basicBlock);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Warning: VN " + valueNumber + " invf: " + frame + " @ " + location);
+ }
boolean isConsistent = true;
Iterator<BasicBlock> bbIter = invDataflow.getCFG().blockIterator();
@@ -845,25 +858,30 @@ public class NullDerefAndRedundantComparisonFinder {
while (bbIter.hasNext()) {
BasicBlock bb = bbIter.next();
- if (!bb.isNullCheck())
+ if (!bb.isNullCheck()) {
continue;
+ }
InstructionHandle eth = bb.getExceptionThrower();
- if (eth == exceptionThrowerHandle)
+ if (eth == exceptionThrowerHandle) {
continue;
- if (eth.getInstruction().getOpcode() != exceptionThrower.getOpcode())
+ }
+ if (eth.getInstruction().getOpcode() != exceptionThrower.getOpcode()) {
continue;
+ }
int ePosition = eth.getPosition();
if (ePosition == position || table != null && line == table.getSourceLine(ePosition)) {
IsNullValueFrame frame2 = invDataflow.getStartFact(bb);
- if (!frame2.isValid())
+ if (!frame2.isValid()) {
continue;
+ }
// apparent clone
IsNullValue rv = frame2.getInstance(eth.getInstruction(), classContext.getConstantPoolGen());
- if (!rv.equals(refValue))
+ if (!rv.equals(refValue)) {
isConsistent = false;
+ }
}
}
@@ -905,12 +923,6 @@ public class NullDerefAndRedundantComparisonFinder {
}
/**
- * @param method
- * TODO
- * @param location
- * @param valueNumber
- * @param vnaFrame
- * @return the annotation
* @deprecated Use
* {@link ValueNumberSourceInfo#findRequiredAnnotationFromValueNumber(Method,Location,ValueNumber,ValueNumberFrame, String)}
* instead
@@ -923,8 +935,9 @@ public class NullDerefAndRedundantComparisonFinder {
private static int getLineNumber(Method method, InstructionHandle handle) {
LineNumberTable table = method.getCode().getLineNumberTable();
- if (table == null)
+ if (table == null) {
return -1;
+ }
return table.getSourceLine(handle.getPosition());
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/NullValueUnconditionalDeref.java b/src/java/edu/umd/cs/findbugs/ba/npe/NullValueUnconditionalDeref.java
index d0981a8..f036c6a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/NullValueUnconditionalDeref.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/NullValueUnconditionalDeref.java
@@ -18,7 +18,7 @@ public class NullValueUnconditionalDeref {
private boolean alwaysReadlineValue;
- private Set<Location> derefLocationSet;
+ private final Set<Location> derefLocationSet;
public NullValueUnconditionalDeref() {
this.alwaysOnExceptionPath = true;
@@ -36,8 +36,9 @@ public class NullValueUnconditionalDeref {
if (!isNullValue.isException()) {
alwaysOnExceptionPath = false;
}
- if (!isNullValue.isFieldValue())
+ if (!isNullValue.isFieldValue()) {
alwaysFieldValue = false;
+ }
if (!isNullValue.isReturnValue()) {
alwaysMethodReturnValue = false;
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/ParameterNullnessPropertyDatabase.java b/src/java/edu/umd/cs/findbugs/ba/npe/ParameterNullnessPropertyDatabase.java
index fdef5e2..75df0df 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/ParameterNullnessPropertyDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/ParameterNullnessPropertyDatabase.java
@@ -26,14 +26,14 @@ import edu.umd.cs.findbugs.ba.interproc.PropertyDatabaseFormatException;
/**
* Method property database storing which method parameters might be
* unconditionally dereferenced.
- *
+ *
* @author David Hovemeyer
*/
public class ParameterNullnessPropertyDatabase extends MethodPropertyDatabase<ParameterProperty> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.interproc.MethodPropertyDatabase#decodeProperty
* (java.lang.String)
@@ -52,7 +52,7 @@ public class ParameterNullnessPropertyDatabase extends MethodPropertyDatabase<Pa
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.interproc.MethodPropertyDatabase#encodeProperty
* (Property)
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/RedundantBranch.java b/src/java/edu/umd/cs/findbugs/ba/npe/RedundantBranch.java
index 0c5e0df..1162300 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/RedundantBranch.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/RedundantBranch.java
@@ -38,7 +38,7 @@ public class RedundantBranch {
/**
* Constructor.
- *
+ *
* @param location
* Location of ref comparison
* @param lineNumber
@@ -57,7 +57,7 @@ public class RedundantBranch {
/**
* Constructor.
- *
+ *
* @param location
* Location of ref comparison
* @param lineNumber
@@ -74,7 +74,7 @@ public class RedundantBranch {
/**
* Set the edge which has been determined to be infeasible.
- *
+ *
* @param infeasibleEdge
* The infeasibleEdge to set.
*/
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathType.java b/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathType.java
index 515f6f5..39f70c4 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathType.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
* <li>It is not possible to return normally (i.e., an exception is guaranteed
* to be thrown)</li>
* </ul>
- *
+ *
* @author David Hovemeyer
*/
public class ReturnPathType {
@@ -61,7 +61,7 @@ public class ReturnPathType {
/**
* Make this dataflow fact an exact copy of the other one.
- *
+ *
* @param other
* another dataflow fact
*/
@@ -85,7 +85,7 @@ public class ReturnPathType {
/**
* Set whether or not it is possible to return normally.
- *
+ *
* @param canReturnNormally
* true if the method can return normally at this location, false
* otherwise
@@ -96,7 +96,7 @@ public class ReturnPathType {
/**
* Merge this fact with given fact.
- *
+ *
* @param fact
* another dataflow fact
*/
@@ -119,7 +119,7 @@ public class ReturnPathType {
/**
* Determine whether this dataflow fact is identical to another one.
- *
+ *
* @param other
* another dataflow fact
* @return true if the two dataflow facts are identical, false if they are
@@ -139,7 +139,7 @@ public class ReturnPathType {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeAnalysis.java
index ce3cc01..3086ae9 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeAnalysis.java
@@ -19,8 +19,6 @@
package edu.umd.cs.findbugs.ba.npe;
-import java.util.HashMap;
-
import org.apache.bcel.generic.InstructionHandle;
import edu.umd.cs.findbugs.ba.BasicAbstractDataflowAnalysis;
@@ -36,19 +34,19 @@ import edu.umd.cs.findbugs.ba.ReverseDepthFirstSearch;
/**
* A dataflow analysis to determine, at each location in a method's CFG, whether
* or not it is possible to return normally at that location.
- *
+ *
* @author David Hovemeyer
*/
public class ReturnPathTypeAnalysis extends BasicAbstractDataflowAnalysis<ReturnPathType> {
- private CFG cfg;
+ private final CFG cfg;
- private DepthFirstSearch dfs;
+ private final DepthFirstSearch dfs;
- private ReverseDepthFirstSearch rdfs;
+ private final ReverseDepthFirstSearch rdfs;
/**
* Constructor.
- *
+ *
* @param cfg
* the method's CFG
* @param rdfs
@@ -62,34 +60,18 @@ public class ReturnPathTypeAnalysis extends BasicAbstractDataflowAnalysis<Return
this.rdfs = rdfs;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#copy(java.lang.Object,
- * java.lang.Object)
- */
+ @Override
public void copy(ReturnPathType source, ReturnPathType dest) {
dest.copyFrom(source);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#createFact()
- */
+ @Override
public ReturnPathType createFact() {
ReturnPathType fact = new ReturnPathType();
fact.setTop();
return fact;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#edgeTransfer(edu.umd.cs.findbugs
- * .ba.Edge, java.lang.Object)
- */
@Override
public void edgeTransfer(Edge edge, ReturnPathType fact) {
// The edges leading into the exit block create the "seed" values
@@ -102,49 +84,31 @@ public class ReturnPathTypeAnalysis extends BasicAbstractDataflowAnalysis<Return
}
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#finishIteration()
- */
@Override
public void finishIteration() {
// nothing to do
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#getBlockOrder(edu.umd.cs.findbugs
- * .ba.CFG)
- */
+ @Override
public BlockOrder getBlockOrder(CFG cfg) {
return new ReverseDFSOrder(cfg, rdfs, dfs);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#getLastUpdateTimestamp(java.lang
- * .Object)
- */
@Override
public int getLastUpdateTimestamp(ReturnPathType fact) {
return 0;
}
- /**
+ /*
* Look up a dataflow value in given map, creating a new (top) fact if no
* fact currently exists.
- *
+ *
* @param map
* the map
* @param block
* BasicBlock used as key in map
* @return the dataflow fact for the block
- */
+ *
private ReturnPathType getOrCreateFact(HashMap<BasicBlock, ReturnPathType> map, BasicBlock block) {
ReturnPathType returnPathType = map.get(block);
if (returnPathType == null) {
@@ -153,13 +117,9 @@ public class ReturnPathTypeAnalysis extends BasicAbstractDataflowAnalysis<Return
}
return returnPathType;
}
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#initEntryFact(java.lang.Object)
*/
+
+ @Override
public void initEntryFact(ReturnPathType result) throws DataflowAnalysisException {
// By default, we assume that paths reaching the exit block
// can return normally. If we traverse exception edges which
@@ -169,84 +129,42 @@ public class ReturnPathTypeAnalysis extends BasicAbstractDataflowAnalysis<Return
result.setCanReturnNormally(true);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#isForwards()
- */
+ @Override
public boolean isForwards() {
return false;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#isTop(java.lang.Object)
- */
+ @Override
public boolean isTop(ReturnPathType fact) {
return fact.isTop();
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#makeFactTop(java.lang.Object)
- */
+ @Override
public void makeFactTop(ReturnPathType fact) {
fact.setTop();
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#meetInto(java.lang.Object,
- * edu.umd.cs.findbugs.ba.Edge, java.lang.Object)
- */
+ @Override
public void meetInto(ReturnPathType fact, Edge edge, ReturnPathType result) throws DataflowAnalysisException {
result.mergeWith(fact);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#same(java.lang.Object,
- * java.lang.Object)
- */
+ @Override
public boolean same(ReturnPathType fact1, ReturnPathType fact2) {
return fact1.sameAs(fact2);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#setLastUpdateTimestamp(java.lang
- * .Object, int)
- */
@Override
public void setLastUpdateTimestamp(ReturnPathType fact, int timestamp) {
// ignore
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#startIteration()
- */
@Override
public void startIteration() {
// nothing to do
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#transfer(edu.umd.cs.findbugs.
- * ba.BasicBlock, org.apache.bcel.generic.InstructionHandle,
- * java.lang.Object, java.lang.Object)
- */
+ @Override
public void transfer(BasicBlock basicBlock, InstructionHandle end, ReturnPathType start, ReturnPathType result)
throws DataflowAnalysisException {
// just copy the start fact
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeDataflow.java b/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeDataflow.java
index fd46005..2503188 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeDataflow.java
@@ -24,14 +24,14 @@ import edu.umd.cs.findbugs.ba.Dataflow;
/**
* Dataflow class for ReturnPathTypeAnalysis.
- *
+ *
* @author David Hovemeyer
*/
public class ReturnPathTypeDataflow extends Dataflow<ReturnPathType, ReturnPathTypeAnalysis> {
/**
* Constructor.
- *
+ *
* @param cfg
* CFG of the method being analyzed
* @param analysis
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/ReturnValueNullnessPropertyDatabase.java b/src/java/edu/umd/cs/findbugs/ba/npe/ReturnValueNullnessPropertyDatabase.java
index 1c210de..e027c55 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/ReturnValueNullnessPropertyDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/ReturnValueNullnessPropertyDatabase.java
@@ -24,14 +24,14 @@ import edu.umd.cs.findbugs.ba.interproc.MethodPropertyDatabase;
/**
* Method property database storing which methods return values guaranteed to be
* nonnull
- *
+ *
* @author David Hovemeyer
*/
public class ReturnValueNullnessPropertyDatabase extends MethodPropertyDatabase<Boolean> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.interproc.MethodPropertyDatabase#decodeProperty
* (java.lang.String)
@@ -45,7 +45,7 @@ public class ReturnValueNullnessPropertyDatabase extends MethodPropertyDatabase<
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.interproc.MethodPropertyDatabase#encodeProperty
* (Property)
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/TypeQualifierNullnessAnnotationDatabase.java b/src/java/edu/umd/cs/findbugs/ba/npe/TypeQualifierNullnessAnnotationDatabase.java
index eb234c2..2c9e79a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/TypeQualifierNullnessAnnotationDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/TypeQualifierNullnessAnnotationDatabase.java
@@ -70,13 +70,7 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
this.nonnullTypeQualifierValue = TypeQualifierValue.getValue(javax.annotation.Nonnull.class, null);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#getResolvedAnnotation
- * (java.lang.Object, boolean)
- */
+ @Override
public NullnessAnnotation getResolvedAnnotation(Object o, boolean getMinimal) {
Profiler profiler = Global.getAnalysisCache().getProfiler();
profiler.start(this.getClass());
@@ -100,10 +94,11 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
NullnessAnnotation result = toNullnessAnnotation(tqa);
if (DEBUG) {
- if (result == null)
+ if (result == null) {
System.out.println(" ===> not found");
- else
+ } else {
System.out.println(" ===> " + tqa + "/" + result.toString() );
+ }
}
return result;
} finally {
@@ -117,7 +112,7 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
try {
TypeQualifierAnnotation tqa
= TypeQualifierApplications.getInheritedTypeQualifierAnnotation(m,
- parameter, nonnullTypeQualifierValue);
+ parameter, nonnullTypeQualifierValue);
NullnessAnnotation result = toNullnessAnnotation(tqa);
return result;
} finally {
@@ -158,35 +153,30 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
NullnessAnnotation result = toNullnessAnnotation(tqa);
if (DEBUG) {
- if (result == null)
+ if (result == null) {
System.out.println(" ===> not found");
- else
+ } else {
System.out.println(" ===> " + tqa + "/" + result.toString() );
+ }
}
return result;
} finally {
profiler.end(this.getClass());
}
}
-
+
public static boolean assertsFirstParameterIsNonnull(XMethod m) {
- return (m.getName().equalsIgnoreCase("checkNonNull")
- || m.getName().equalsIgnoreCase("checkNotNull")
+ return ("checkNonNull".equalsIgnoreCase(m.getName())
+ || "checkNotNull".equalsIgnoreCase(m.getName())
// JDK 7 java.util.Objects.requireNonNull(Object)
- || m.getName().equals("requireNonNull")
+ || "requireNonNull".equals(m.getName())
// org.eclipse.core.runtime.Assert(Object)
- || m.getName().equalsIgnoreCase("isNotNull")
- || m.getName().equalsIgnoreCase("assertNotNull"))
- && m.getSignature().startsWith("(Ljava/lang/Object;");
+ || "isNotNull".equalsIgnoreCase(m.getName())
+ || "assertNotNull".equalsIgnoreCase(m.getName()))
+ && m.getSignature().startsWith("(Ljava/lang/Object;");
}
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#parameterMustBeNonNull
- * (edu.umd.cs.findbugs.ba.XMethod, int)
- */
+
+ @Override
public boolean parameterMustBeNonNull(XMethod m, int param) {
if (DEBUG) {
System.out.print("Checking " + m + " param " + param + " for @Nonnull...");
@@ -197,12 +187,13 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
if (tqa == null && param == 0) {
String name = m.getName();
String signature = m.getSignature();
- if (name.equals("main") && signature.equals("([Ljava/lang/String;)V") && m.isStatic() && m.isPublic())
+ if ("main".equals(name) && "([Ljava/lang/String;)V".equals(signature) && m.isStatic() && m.isPublic()) {
return true;
- else if (assertsFirstParameterIsNonnull(m))
+ } else if (assertsFirstParameterIsNonnull(m)) {
return true;
- else if (name.equals("compareTo") && signature.substring(signature.indexOf(";") + 1).equals(")Z") && !m.isStatic())
+ } else if ("compareTo".equals(name) && ")Z".equals(signature.substring(signature.indexOf(';') + 1)) && !m.isStatic()) {
return true;
+ }
}
boolean answer = (tqa != null) && tqa.when == When.ALWAYS;
@@ -248,14 +239,7 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
private static final ClassDescriptor RETURN_VALUES_ARE_NONNULL_BY_DEFAULT = DescriptorFactory
.createClassDescriptor(edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault.class);
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#addDefaultAnnotation
- * (java.lang.String, java.lang.String,
- * edu.umd.cs.findbugs.ba.NullnessAnnotation)
- */
+ @Override
public void addDefaultAnnotation(Target target, String c, NullnessAnnotation n) {
if (DEBUG) {
System.out.println("addDefaultAnnotation: target=" + target + ", c=" + c + ", n=" + n);
@@ -313,23 +297,7 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
xclass.addAnnotation(annotationValue);
}
- // /* (non-Javadoc)
- // * @see
- // edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#addDefaultMethodAnnotation(java.lang.String,
- // edu.umd.cs.findbugs.ba.NullnessAnnotation)
- // */
- // public void addDefaultMethodAnnotation(String name, NullnessAnnotation
- // annotation) {
- // }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#addFieldAnnotation
- * (java.lang.String, java.lang.String, java.lang.String, boolean,
- * edu.umd.cs.findbugs.ba.NullnessAnnotation)
- */
+ @Override
public void addFieldAnnotation(String cName, String mName, String mSig, boolean isStatic, NullnessAnnotation annotation) {
if (DEBUG) {
System.out.println("addFieldAnnotation: annotate " + cName + "." + mName + " with " + annotation);
@@ -377,27 +345,22 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
}
XMethod xmethod = xclass.findMethod(mName, sig, isStatic);
- if (xmethod == null)
+ if (xmethod == null) {
xmethod = XFactory.createXMethod(cName, mName, sig, isStatic);
+ }
return xmethod;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#addMethodAnnotation
- * (java.lang.String, java.lang.String, java.lang.String, boolean,
- * edu.umd.cs.findbugs.ba.NullnessAnnotation)
- */
+ @Override
public void addMethodAnnotation(String cName, String mName, String sig, boolean isStatic, NullnessAnnotation annotation) {
if (DEBUG) {
System.out.println("addMethodAnnotation: annotate " + cName + "." + mName + " with " + annotation);
}
XMethod xmethod = getXMethod(cName, mName, sig, isStatic);
- if (xmethod == null)
+ if (xmethod == null) {
return;
+ }
// Get JSR-305 nullness annotation type
ClassDescriptor nullnessAnnotationType = getNullnessAnnotationClassDescriptor(annotation);
@@ -408,14 +371,7 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
xmethod.addAnnotation(annotationValue);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#
- * addMethodParameterAnnotation(java.lang.String, java.lang.String,
- * java.lang.String, boolean, int,
- * edu.umd.cs.findbugs.ba.NullnessAnnotation)
- */
+ @Override
public void addMethodParameterAnnotation(@DottedClassName String cName, String mName, String sig, boolean isStatic,
int param, NullnessAnnotation annotation) {
if (DEBUG) {
@@ -423,8 +379,9 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
+ annotation);
}
XMethod xmethod = getXMethod(cName, mName, sig, isStatic);
- if (xmethod == null)
+ if (xmethod == null) {
return;
+ }
// Get JSR-305 nullness annotation type
ClassDescriptor nullnessAnnotationType = getNullnessAnnotationClassDescriptor(annotation);
@@ -432,9 +389,10 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
AnnotationValue annotationValue = new AnnotationValue(nullnessAnnotationType);
if (!xmethod.getClassName().equals(cName)) {
- if (SystemProperties.ASSERTIONS_ENABLED)
+ if (SystemProperties.ASSERTIONS_ENABLED) {
AnalysisContext.logError("Could not fully resolve method " + cName + "." + mName + sig + " to apply annotation "
+ annotation);
+ }
return;
}
@@ -449,13 +407,7 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
xmethod.addParameterAnnotation(param, annotationValue);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#loadAuxiliaryAnnotations
- * ()
- */
+ @Override
public void loadAuxiliaryAnnotations() {
DefaultNullnessAnnotations.addDefaultNullnessAnnotations(this);
}
@@ -469,15 +421,16 @@ public class TypeQualifierNullnessAnnotationDatabase implements INullnessAnnotat
* @return corresponding NullnessAnnotation
*/
private @CheckForNull NullnessAnnotation toNullnessAnnotation(@CheckForNull TypeQualifierAnnotation tqa) {
- if (tqa == null || tqa == TypeQualifierAnnotation.OVERRIDES_BUT_NO_ANNOTATION)
+ if (tqa == null || tqa == TypeQualifierAnnotation.OVERRIDES_BUT_NO_ANNOTATION) {
return null;
+ }
if (tqa.when == null) {
new NullPointerException("TGA value with null when field").printStackTrace();
return null;
}
-
-
-
+
+
+
switch (tqa.when) {
case ALWAYS:
return NullnessAnnotation.NONNULL;
diff --git a/src/java/edu/umd/cs/findbugs/ba/npe/UsagesRequiringNonNullValues.java b/src/java/edu/umd/cs/findbugs/ba/npe/UsagesRequiringNonNullValues.java
index a1f0487..f7df780 100644
--- a/src/java/edu/umd/cs/findbugs/ba/npe/UsagesRequiringNonNullValues.java
+++ b/src/java/edu/umd/cs/findbugs/ba/npe/UsagesRequiringNonNullValues.java
@@ -58,15 +58,17 @@ public class UsagesRequiringNonNullValues {
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
- for (Map.Entry<Integer, Collection<Pair>> e : map.asMap().entrySet())
+ for (Map.Entry<Integer, Collection<Pair>> e : map.asMap().entrySet()) {
buf.append(e).append("\n");
+ }
return buf.toString();
}
public void add(Location loc, ValueNumber vn, PointerUsageRequiringNonNullValue usage) {
Pair p = new Pair(vn, usage);
- if (DerefFinder.DEBUG)
+ if (DerefFinder.DEBUG) {
System.out.println("At " + loc + " adding dereference " + p);
+ }
map.add(loc.getHandle().getPosition(), p);
}
@@ -76,13 +78,16 @@ public class UsagesRequiringNonNullValues {
// PointerUsageRequiringNonNullValue secondBest = null;
MergeTree mergeTree = vnaDataflow.getAnalysis().getMergeTree();
for (Pair p : map.get(loc.getHandle().getPosition())) {
- if (p.vn.equals(vn))
+ if (p.vn.equals(vn)) {
return p.pu;
- if (!p.vn.hasFlag(ValueNumber.PHI_NODE))
+ }
+ if (!p.vn.hasFlag(ValueNumber.PHI_NODE)) {
continue;
+ }
BitSet inputs = mergeTree.getTransitiveInputSet(p.vn);
- if (inputs.get(vn.getNumber()))
+ if (inputs.get(vn.getNumber())) {
return p.pu;
+ }
}
return null;
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/InstructionActionCache.java b/src/java/edu/umd/cs/findbugs/ba/obl/InstructionActionCache.java
index dd57bac..495665b 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/InstructionActionCache.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/InstructionActionCache.java
@@ -85,7 +85,7 @@ public class InstructionActionCache {
static final ClassDescriptor WILL_CLOSE = DescriptorFactory.createClassDescriptor(WillClose.class);
public Collection<ObligationPolicyDatabaseAction> getActions(BasicBlock block, InstructionHandle handle) {
- Collection<ObligationPolicyDatabaseAction> actionList = actionCache.get(handle);
+ Collection<ObligationPolicyDatabaseAction> actionList = actionCache.get(handle);
if (actionList == null) {
Instruction ins = handle.getInstruction();
actionList = Collections.emptyList();
@@ -114,31 +114,33 @@ public class InstructionActionCache {
if (actionList.isEmpty()) {
try {
- TypeFrame factAtLocation = null;
- SignatureParser sigParser = new SignatureParser(signature);
-// int startIndex = 0;
-// if (!xmethod.isStatic())
-// startIndex = 1;
- Iterator<String> signatureIterator = sigParser.parameterSignatureIterator();
- int parameters = sigParser.getNumParameters();
- for (int i = 0; i < parameters; i++) {
- String sig = signatureIterator.next();
- Collection<ClassDescriptor> annotations = invokedMethod.getParameterAnnotationDescriptors(i);
- if (annotations.contains(WILL_CLOSE) || sig.equals("Ljava/io/Closeable;") || methodName.startsWith("close")) {
- // closing this value
- if (factAtLocation == null)
- factAtLocation = typeDataflow.getFactAtLocation( new Location(handle, block));
-
- Type argumentType = factAtLocation.getArgument(inv, cpg, i, sigParser);
- if (argumentType instanceof ObjectType) {
- Obligation obligation = database.getFactory().getObligationByType((ObjectType) argumentType);
- if (obligation != null)
- actionList.add(new ObligationPolicyDatabaseAction(ObligationPolicyDatabaseActionType.DEL, obligation));
+ TypeFrame factAtLocation = null;
+ SignatureParser sigParser = new SignatureParser(signature);
+ // int startIndex = 0;
+ // if (!xmethod.isStatic())
+ // startIndex = 1;
+ Iterator<String> signatureIterator = sigParser.parameterSignatureIterator();
+ int parameters = sigParser.getNumParameters();
+ for (int i = 0; i < parameters; i++) {
+ String sig = signatureIterator.next();
+ Collection<ClassDescriptor> annotations = invokedMethod.getParameterAnnotationDescriptors(i);
+ if (annotations.contains(WILL_CLOSE) || "Ljava/io/Closeable;".equals(sig) || methodName.startsWith("close")) {
+ // closing this value
+ if (factAtLocation == null) {
+ factAtLocation = typeDataflow.getFactAtLocation( new Location(handle, block));
+ }
+
+ Type argumentType = factAtLocation.getArgument(inv, cpg, i, sigParser);
+ if (argumentType instanceof ObjectType) {
+ Obligation obligation = database.getFactory().getObligationByType((ObjectType) argumentType);
+ if (obligation != null) {
+ actionList.add(new ObligationPolicyDatabaseAction(ObligationPolicyDatabaseActionType.DEL, obligation));
+ }
+
+ }
}
-
}
- }
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("Error checking " + invokedMethod, e);
@@ -162,15 +164,16 @@ public class InstructionActionCache {
ObligationFactory factory = database.getFactory();
Obligation obligation = factory.getObligationByType((ObjectType) tosType);
if (obligation != null) {
- if (obligation.getClassName().equals("java.sql.ResultSet")) {
+ if ("java.sql.ResultSet".equals(obligation.getClassName())) {
ObjectType sType = ObjectTypeFactory.getInstance(java.sql.Statement.class);
Obligation sObligation = factory.getObligationByType(sType);
actionList = Arrays.asList(
new ObligationPolicyDatabaseAction(ObligationPolicyDatabaseActionType.DEL, obligation),
new ObligationPolicyDatabaseAction(ObligationPolicyDatabaseActionType.DEL, sObligation));
- } else
- actionList = Collections.singleton(new ObligationPolicyDatabaseAction(ObligationPolicyDatabaseActionType.DEL,
- obligation));
+ } else {
+ actionList = Collections.singleton(new ObligationPolicyDatabaseAction(ObligationPolicyDatabaseActionType.DEL,
+ obligation));
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/MatchMethodEntry.java b/src/java/edu/umd/cs/findbugs/ba/obl/MatchMethodEntry.java
index da0099b..a1564e6 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/MatchMethodEntry.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/MatchMethodEntry.java
@@ -33,7 +33,7 @@ import edu.umd.cs.findbugs.util.TypeMatcher;
/**
* An ObligationPolicyDatabaseEntry which creates or deletes an obligation based
* on a call to a specified method.
- *
+ *
* @author David Hovemeyer
*/
public class MatchMethodEntry implements ObligationPolicyDatabaseEntry {
@@ -51,14 +51,15 @@ public class MatchMethodEntry implements ObligationPolicyDatabaseEntry {
private final Obligation[] obligations;
private final ObligationPolicyDatabaseEntryType entryType;
-
+
+ @Override
public Collection<Obligation> getAllObligations() {
return Arrays.asList(obligations);
}
/**
* Constructor. Creates an entry which matches the given XMethod.
- *
+ *
* @param xmethod
* an XMethod
* @param action
@@ -83,7 +84,7 @@ public class MatchMethodEntry implements ObligationPolicyDatabaseEntry {
/**
* Constructor.
- *
+ *
* @param receiverType
* TypeMatcher to match the receiver type (or class containing
* static method)
@@ -112,16 +113,19 @@ public class MatchMethodEntry implements ObligationPolicyDatabaseEntry {
this.entryType = entryType;
}
+ @Override
public ObligationPolicyDatabaseEntryType getEntryType() {
return entryType;
}
+ @Override
public boolean getActions(ReferenceType receiverType, String methodName, String signature, boolean isStatic,
Collection<ObligationPolicyDatabaseAction> actionList) {
if (this.methodName.matches(methodName) && this.signature.matches(signature) && this.isStatic == isStatic
&& this.receiverType.matches(receiverType)) {
- for (Obligation o : obligations)
+ for (Obligation o : obligations) {
actionList.add(new ObligationPolicyDatabaseAction(action, o));
+ }
return true;
}
return false;
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/NonexistentObligationException.java b/src/java/edu/umd/cs/findbugs/ba/obl/NonexistentObligationException.java
index bf35738..e5d81d8 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/NonexistentObligationException.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/NonexistentObligationException.java
@@ -27,4 +27,3 @@ public class NonexistentObligationException extends Exception {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/Obligation.java b/src/java/edu/umd/cs/findbugs/ba/obl/Obligation.java
index db21ff7..fb1755b 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/Obligation.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/Obligation.java
@@ -27,12 +27,12 @@ import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
/**
* An obligation that must be cleaned up by error handling code. Examples
* include open streams and database connections.
- *
+ *
* <p>
* See Weimer and Necula, <a href="http://doi.acm.org/10.1145/1028976.1029011"
* >Finding and preventing run-time error handling mistakes</a>, OOPSLA 2004.
* </p>
- *
+ *
* @author David Hovemeyer
*/
public class Obligation {
@@ -78,4 +78,3 @@ public class Obligation {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationAcquiredOrReleasedInLoopException.java b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationAcquiredOrReleasedInLoopException.java
index 71b1ee0..c18618a 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationAcquiredOrReleasedInLoopException.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationAcquiredOrReleasedInLoopException.java
@@ -24,11 +24,11 @@ import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
/**
* Exception to indicate that ObligationAnalysis has detected a situation in
* which an obligation is either acquired or released inside a loop.
- *
+ *
* @author David Hovemeyer
*/
public class ObligationAcquiredOrReleasedInLoopException extends DataflowAnalysisException {
- private Obligation obligation;
+ private final Obligation obligation;
public ObligationAcquiredOrReleasedInLoopException(Obligation obligation) {
super("Obligation " + obligation + " acquired or released in loop");
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationAnalysis.java
index a42ecb8..b52e818 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationAnalysis.java
@@ -57,12 +57,12 @@ import edu.umd.cs.findbugs.classfile.IErrorLogger;
/**
* Dataflow analysis to track obligations (i/o streams and other resources which
* must be closed).
- *
+ *
* <p>
* See Weimer and Necula, <a href="http://doi.acm.org/10.1145/1028976.1029011"
* >Finding and preventing run-time error handling mistakes</a>, OOPSLA 2004.
* </p>
- *
+ *
* @author David Hovemeyer
*/
public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
@@ -71,19 +71,19 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
private static final boolean DEBUG_NULL_CHECK = SystemProperties.getBoolean("oa.debug.nullcheck");
- private XMethod xmethod;
+ private final XMethod xmethod;
- private ObligationFactory factory;
+ private final ObligationFactory factory;
- private ObligationPolicyDatabase database;
+ private final ObligationPolicyDatabase database;
- private TypeDataflow typeDataflow;
+ private final TypeDataflow typeDataflow;
- private IsNullValueDataflow invDataflow;
+ private final IsNullValueDataflow invDataflow;
- private IErrorLogger errorLogger;
+ private final IErrorLogger errorLogger;
- private InstructionActionCache actionCache;
+ private final InstructionActionCache actionCache;
private StateSet cachedEntryFact;
@@ -91,7 +91,7 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
/**
* Constructor.
- *
+ *
* @param dfs
* a DepthFirstSearch on the method to be analyzed
* @param xmethod
@@ -123,6 +123,7 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
return actionCache;
}
+ @Override
public StateSet createFact() {
return new StateSet(factory);
}
@@ -135,9 +136,10 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
@Override
public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, StateSet fact)
throws DataflowAnalysisException {
- Collection<ObligationPolicyDatabaseAction> actionList = actionCache.getActions(basicBlock, handle);
- if (actionList.isEmpty())
- return;
+ Collection<ObligationPolicyDatabaseAction> actionList = actionCache.getActions(basicBlock, handle);
+ if (actionList.isEmpty()) {
+ return;
+ }
if (DEBUG) {
System.out.println("Applying actions at " + handle + " to " + fact);
}
@@ -152,14 +154,6 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
}
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#transfer(edu.umd.cs.findbugs
- * .ba.BasicBlock, org.apache.bcel.generic.InstructionHandle,
- * java.lang.Object, java.lang.Object)
- */
@Override
public void transfer(BasicBlock basicBlock, @CheckForNull InstructionHandle end, StateSet start, StateSet result)
throws DataflowAnalysisException {
@@ -213,9 +207,9 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
if (isPossibleIfComparison(edge)) {
Obligation comparedObligation = comparesObligationTypeToNull(edge);
if (comparedObligation != null/*
- * && comparedObligation.equals(
- * possiblyLeakedObligation)
- */) {
+ * && comparedObligation.equals(
+ * possiblyLeakedObligation)
+ */) {
if (DEBUG_NULL_CHECK) {
System.out.println("Deleting " + comparedObligation.toString() + " on edge from comparision "
+ edge.getSource().getLastInstruction());
@@ -251,6 +245,8 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
case Constants.IF_ACMPNE:
type = acmpNullCheck(opcode, edge, last, sourceBlock);
break;
+ default:
+ break;
}
if (type == null || !(type instanceof ObjectType)) {
@@ -325,24 +321,12 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
return type;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#copy(edu.umd.cs.findbugs.ba.obl
- * .StateSet, edu.umd.cs.findbugs.ba.obl.StateSet)
- */
+ @Override
public void copy(StateSet src, StateSet dest) {
dest.copyFrom(src);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#initEntryFact(edu.umd.cs.findbugs
- * .ba.obl.StateSet)
- */
+ @Override
public void initEntryFact(StateSet fact) throws DataflowAnalysisException {
if (cachedEntryFact == null) {
cachedEntryFact = new StateSet(factory);
@@ -375,38 +359,27 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.DataflowAnalysis#makeFactTop(edu.umd.cs.findbugs
* .ba.obl.StateSet)
*/
+ @Override
public void makeFactTop(StateSet fact) {
fact.setTop();
}
+ @Override
public boolean isTop(StateSet fact) {
return fact.isTop();
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#same(edu.umd.cs.findbugs.ba.obl
- * .StateSet, edu.umd.cs.findbugs.ba.obl.StateSet)
- */
+ @Override
public boolean same(StateSet a, StateSet b) {
return a.equals(b);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#meetInto(edu.umd.cs.findbugs.
- * ba.obl.StateSet, edu.umd.cs.findbugs.ba.Edge,
- * edu.umd.cs.findbugs.ba.obl.StateSet)
- */
+ @Override
public void meetInto(StateSet fact, Edge edge, StateSet result) throws DataflowAnalysisException {
final StateSet inputFact = fact;
@@ -424,11 +397,11 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
// Handle easy top and bottom cases
if (inputFact.isTop() || result.isBottom() ) {
- // Nothing to do
+ // Nothing to do
} else if (inputFact.isBottom() || result.isTop() || result.isEmpty()) {
copy(inputFact, result);
- } else if (inputFact.isOnExceptionPath()
- && !result.isOnExceptionPath()) {
+ } else if (inputFact.isOnExceptionPath()
+ && !result.isOnExceptionPath()) {
if (DEBUG) {
System.out.println("Ignoring " + inputFact + " in favor of " + result);
BasicBlock from = edge.getSource();
@@ -436,10 +409,11 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
System.out.printf(" edge %s -> %s%n", from, to);
}
// Nothing to do
- } else if(!inputFact.isOnExceptionPath() && !inputFact.isEmpty()
- && result.isOnExceptionPath()) {
- if (DEBUG)
+ } else if(!inputFact.isOnExceptionPath() && !inputFact.isEmpty()
+ && result.isOnExceptionPath()) {
+ if (DEBUG) {
System.out.println("overwriting " + result + " with " + inputFact);
+ }
copy(inputFact, result);
} else {
// We will destructively replace the state map of the result fact
@@ -490,4 +464,3 @@ public class ObligationAnalysis extends ForwardDataflowAnalysis<StateSet> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationDataflow.java b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationDataflow.java
index 1f752de..426b852 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationDataflow.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.ba.Dataflow;
/**
* Dataflow class for ObligationAnalysis.
- *
+ *
* @author David Hovemeyer
*/
public class ObligationDataflow extends Dataflow<StateSet, ObligationAnalysis> {
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationFactory.java b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationFactory.java
index a7329d0..3b1e8ea 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationFactory.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationFactory.java
@@ -43,9 +43,9 @@ import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
* ObligationAnalysis.
*/
public class ObligationFactory {
- private Map<String, Obligation> classNameToObligationMap;
+ private final Map<String, Obligation> classNameToObligationMap;
- private Set<String> slashedClassNames = new HashSet<String>();
+ private final Set<String> slashedClassNames = new HashSet<String>();
// // XXX: this is just for debugging.
// static ObligationFactory lastInstance;
@@ -61,16 +61,19 @@ public class ObligationFactory {
}
public boolean signatureInvolvesObligations(String sig) {
- for (String c : slashedClassNames)
- if (sig.indexOf(c) >= 0)
+ sig = sig.replaceAll("java/io/File", "java/io/");
+ for (String c : slashedClassNames) {
+ if (sig.indexOf(c) >= 0) {
return true;
+ }
+ }
return false;
}
/**
* Determine whether class named by given ClassDescriptor is an Obligation
* type.
- *
+ *
* @param classDescriptor
* a class
* @return true if the class is an Obligation type, false otherwise
@@ -86,7 +89,7 @@ public class ObligationFactory {
/**
* Get an Iterator over known Obligation types.
- *
+ *
* @return Iterator over known Obligation types
*/
public Iterator<Obligation> obligationIterator() {
@@ -97,7 +100,7 @@ public class ObligationFactory {
* Look up an Obligation by type. This returns the first Obligation that is
* a supertype of the type given (meaning that the given type could be an
* instance of the returned Obligation).
- *
+ *
* @param type
* a type
* @return an Obligation that is a supertype of the given type, or null if
@@ -108,8 +111,9 @@ public class ObligationFactory {
Obligation getObligationByType(ObjectType type) throws ClassNotFoundException {
for (Iterator<Obligation> i = obligationIterator(); i.hasNext();) {
Obligation obligation = i.next();
- if (Hierarchy.isSubtype(type, obligation.getType()))
+ if (Hierarchy.isSubtype(type, obligation.getType())) {
return obligation;
+ }
}
return null;
}
@@ -118,7 +122,7 @@ public class ObligationFactory {
* Look up an Obligation by type. This returns the first Obligation that is
* a supertype of the type given (meaning that the given type could be an
* instance of the returned Obligation).
- *
+ *
* @param classDescriptor
* a ClassDescriptor naming a class type
* @return an Obligation that is a supertype of the given type, or null if
@@ -137,7 +141,7 @@ public class ObligationFactory {
/**
* Get array of Obligation types corresponding to the parameters of the
* given method.
- *
+ *
* @param xmethod
* a method
* @return array of Obligation types for each of the method's parameters; a
@@ -172,8 +176,9 @@ public class ObligationFactory {
public Obligation getObligationById(int id) {
for (Obligation obligation : classNameToObligationMap.values()) {
- if (obligation.getId() == id)
+ if (obligation.getId() == id) {
return obligation;
+ }
}
return null;
}
@@ -187,4 +192,3 @@ public class ObligationFactory {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabase.java b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabase.java
index 2297556..ac0023d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabase.java
@@ -33,22 +33,22 @@ import edu.umd.cs.findbugs.ba.XMethod;
/**
* Policy database which defines which methods create and remove obligations.
- *
+ *
* <p>
* See Weimer and Necula, <a href="http://doi.acm.org/10.1145/1028976.1029011"
* >Finding and preventing run-time error handling mistakes</a>, OOPSLA 2004.
* </p>
- *
+ *
* @author David Hovemeyer
*/
public class ObligationPolicyDatabase {
public static final boolean DEBUG = SystemProperties.getBoolean("oa.debug.db");
- private ObligationFactory factory;
+ private final ObligationFactory factory;
+
+ private final LinkedList<ObligationPolicyDatabaseEntry> entryList;
- private LinkedList<ObligationPolicyDatabaseEntry> entryList;
-
- private HashSet<Obligation> allObligations = new HashSet<Obligation>();
+ private final HashSet<Obligation> allObligations = new HashSet<Obligation>();
private boolean strictChecking;
@@ -61,14 +61,15 @@ public class ObligationPolicyDatabase {
public ObligationFactory getFactory() {
return factory;
}
-
+
public Set<Obligation> getAllObligations() {
return allObligations;
}
public void addEntry(ObligationPolicyDatabaseEntry entry) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Adding entry " + entry);
+ }
allObligations.addAll(entry.getAllObligations());
entryList.add(entry);
}
@@ -76,7 +77,7 @@ public class ObligationPolicyDatabase {
/**
* Add an appropriate policy database entry for parameters marked with the
* WillClose annotation.
- *
+ *
* @param xmethod
* a method
* @param obligation
@@ -93,10 +94,11 @@ public class ObligationPolicyDatabase {
addEntry(entry);
return entry;
}
-
+
public void setStrictChecking(boolean strictChecking) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Setting strict checking to " + strictChecking );
+ }
this.strictChecking = strictChecking;
}
@@ -114,10 +116,12 @@ public class ObligationPolicyDatabase {
boolean matched = entry.getActions(receiverType, methodName, signature, isStatic, actionList);
if (DEBUG) {
- if (matched)
+ if (matched)
+ {
System.out.println(" Entry " + entry + " ==> MATCH");
-// else
-// System.out.println(" ==> no match");
+ // else
+ // System.out.println(" ==> no match");
+ }
}
}
if (DEBUG) {
@@ -130,4 +134,3 @@ public class ObligationPolicyDatabase {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseAction.java b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseAction.java
index 554f418..d4d8a84 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseAction.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseAction.java
@@ -24,7 +24,7 @@ import javax.annotation.Nullable;
/**
* An action applied by an entry in the ObligationPolicyDatabase. Adds or
* removes an obligation.
- *
+ *
* @author David Hovemeyer
*/
public class ObligationPolicyDatabaseAction {
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseEntry.java b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseEntry.java
index 8ec3d94..fee75a4 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseEntry.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseEntry.java
@@ -26,7 +26,7 @@ import org.apache.bcel.generic.ReferenceType;
/**
* Interface defining an entry in the ObligationPolicyDatabase. Checks called
* methods to see what actions they apply.
- *
+ *
* @author David Hovemeyer
*/
public interface ObligationPolicyDatabaseEntry {
@@ -38,7 +38,7 @@ public interface ObligationPolicyDatabaseEntry {
/**
* Get the ObligationPolicyDatabaseActions that should be applied when the
* method described by the parameters is called.
- *
+ *
* @param receiverType
* receiver type of called method
* @param methodName
@@ -55,6 +55,6 @@ public interface ObligationPolicyDatabaseEntry {
*/
public boolean getActions(ReferenceType receiverType, String methodName, String signature, boolean isStatic,
Collection<ObligationPolicyDatabaseAction> actionList);
-
+
public Collection<Obligation> getAllObligations();
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseEntryType.java b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseEntryType.java
index 93f579e..09c583c 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseEntryType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationPolicyDatabaseEntryType.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.ba.obl;
/**
* Types of ObligationPolicyDatabaseEntries.
- *
+ *
* @author David Hovemeyer
*/
public enum ObligationPolicyDatabaseEntryType {
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationSet.java b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationSet.java
index 444df25..3c314fa 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/ObligationSet.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/ObligationSet.java
@@ -23,12 +23,12 @@ import java.util.Arrays;
/**
* A multiset of obligations that must be cleaned up by error-handling code.
- *
+ *
* <p>
* See Weimer and Necula, <a href="http://doi.acm.org/10.1145/1028976.1029011"
* >Finding and preventing run-time error handling mistakes</a>, OOPSLA 2004.
* </p>
- *
+ *
* @author David Hovemeyer
*/
public class ObligationSet {
@@ -48,11 +48,13 @@ public class ObligationSet {
invalidate();
}
-
+
public boolean isEmpty() {
- for(short s : countList)
- if (s > 0)
+ for(short s : countList) {
+ if (s > 0) {
return false;
+ }
+ }
return true;
}
public void add(Obligation obligation) {
@@ -64,7 +66,9 @@ public class ObligationSet {
invalidate();
int count = countList[obligation.getId()];
if (count > 0)
+ {
countList[obligation.getId()]--; // = (short)(count - 1);
+ }
}
public int getCount(int id) {
@@ -107,13 +111,14 @@ public class ObligationSet {
@Override
public boolean equals(Object o) {
- if (o == null || o.getClass() != this.getClass())
+ if (o == null || o.getClass() != this.getClass()) {
return false;
+ }
ObligationSet other = (ObligationSet) o;
if (!Arrays.equals(this.countList, other.countList)
- /* || !Arrays.equals(this.whereCreated, other.whereCreated) */) {
+ /* || !Arrays.equals(this.whereCreated, other.whereCreated) */) {
return false;
}
@@ -130,10 +135,12 @@ public class ObligationSet {
buf.append("{");
int count = 0;
for (int i = 0; i < countList.length; ++i) {
- if (countList[i] == 0)
+ if (countList[i] == 0) {
continue;
- if (count > 0)
+ }
+ if (count > 0) {
buf.append(",");
+ }
buf.append(factory.getObligationById(i).toString());
buf.append(" x ");
buf.append(countList[i]);
@@ -174,4 +181,3 @@ public class ObligationSet {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/State.java b/src/java/edu/umd/cs/findbugs/ba/obl/State.java
index 8616eb6..f11f0ac 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/State.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/State.java
@@ -24,12 +24,12 @@ import edu.umd.cs.findbugs.ba.Path;
/**
* Error-handling obligation analysis state. This is a set of obligations and a
* program path on which they are outstanding (not cleaned up).
- *
+ *
* <p>
* See Weimer and Necula, <a href="http://doi.acm.org/10.1145/1028976.1029011"
* >Finding and preventing run-time error handling mistakes</a>, OOPSLA 2004.
* </p>
- *
+ *
* @author David Hovemeyer
*/
public class State {
@@ -93,4 +93,3 @@ public class State {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/obl/StateSet.java b/src/java/edu/umd/cs/findbugs/ba/obl/StateSet.java
index 08324d0..11df401 100644
--- a/src/java/edu/umd/cs/findbugs/ba/obl/StateSet.java
+++ b/src/java/edu/umd/cs/findbugs/ba/obl/StateSet.java
@@ -32,28 +32,28 @@ import edu.umd.cs.findbugs.ba.Path;
/**
* A dataflow fact used in ObligationAnalysis. It is a set of State objects,
* plus the additional capability to represent top and bottom elements.
- *
+ *
* <p>
* Invariant: no StateSet may contain more than one State with the same
* ObligationSet.
* </p>
- *
+ *
* <p>
* See Weimer and Necula, <a href="http://doi.acm.org/10.1145/1028976.1029011"
* >Finding and preventing run-time error handling mistakes</a>, OOPSLA 2004.
* </p>
- *
+ *
* @author David Hovemeyer
*/
public class StateSet {
private boolean isTop;
private boolean isBottom;
-
+
private boolean onExceptionPath;
private Map<ObligationSet, State> stateMap;
-
+
public boolean isEmpty() {
return stateMap.isEmpty();
}
@@ -105,7 +105,7 @@ public class StateSet {
/**
* Return an Iterator over the States in the StateSet.
- *
+ *
* @return an Iterator over the States in the StateSet
*/
public Iterator<State> stateIterator() {
@@ -114,7 +114,7 @@ public class StateSet {
/**
* Get Set of all ObligationsSets in this StateSet.
- *
+ *
* @return Set of all ObligationsSets in this StateSet
*/
public Set<ObligationSet> getAllObligationSets() {
@@ -124,7 +124,7 @@ public class StateSet {
/**
* Get the State which has the given ObligationSet. Returns null if there is
* no such state.
- *
+ *
* @param obligationSet
* we want to get the State with this ObligationSet
* @return the State with the given ObligationSet, or null if there is no
@@ -151,7 +151,7 @@ public class StateSet {
/**
* Make this StateSet an exact copy of the given StateSet.
- *
+ *
* @param other
* a StateSet; this StateSet will be made identical to it
*/
@@ -168,7 +168,7 @@ public class StateSet {
/**
* Return an exact deep copy of this StateSet.
- *
+ *
* @return an exact deep copy of this StateSet
*/
public StateSet duplicate() {
@@ -179,7 +179,7 @@ public class StateSet {
/**
* Add an obligation to every State in the StateSet.
- *
+ *
* @param obligation
* the obligation to add
* @param basicBlockId
@@ -192,18 +192,20 @@ public class StateSet {
State s = new State(factory);
s.getObligationSet().add(obligation);
updatedStateMap.put(s.getObligationSet(), s);
- } else for (State state : stateMap.values()) {
- checkCircularity(state, obligation, basicBlockId);
- state.getObligationSet().add(obligation);
- updatedStateMap.put(state.getObligationSet(), state);
+ } else {
+ for (State state : stateMap.values()) {
+ checkCircularity(state, obligation, basicBlockId);
+ state.getObligationSet().add(obligation);
+ updatedStateMap.put(state.getObligationSet(), state);
+ }
}
replaceMap(updatedStateMap);
}
/**
* Remove an Obligation from every State in the StateSet.
- *
+ *
* @param obligation
* the obligation to remove
* @param basicBlockId
@@ -219,8 +221,9 @@ public class StateSet {
checkCircularity(state, obligation, basicBlockId);
ObligationSet obligationSet = state.getObligationSet();
obligationSet.remove(obligation);
- if (!obligationSet.isEmpty())
- updatedStateMap.put(obligationSet, state);
+ if (!obligationSet.isEmpty()) {
+ updatedStateMap.put(obligationSet, state);
+ }
}
replaceMap(updatedStateMap);
}
@@ -228,7 +231,7 @@ public class StateSet {
/**
* Bail out of the analysis is an obligation is acquired or released in a
* loop.
- *
+ *
* @param state
* a State to which an obligation is being added or removed
* @param obligation
@@ -245,7 +248,7 @@ public class StateSet {
/**
* Replace the map of ObligationSets to States with the given one.
- *
+ *
* @param stateMap
* enw map of ObligationSets to States
*/
@@ -255,7 +258,7 @@ public class StateSet {
/**
* Get all States that have Paths which are prefixes of the given Path.
- *
+ *
* @param path
* a Path
* @return Collection of States that have Paths which are prefixes of the
@@ -273,8 +276,9 @@ public class StateSet {
@Override
public boolean equals(Object o) {
- if (o == null || o.getClass() != this.getClass())
+ if (o == null || o.getClass() != this.getClass()) {
return false;
+ }
StateSet other = (StateSet) o;
return this.isTop == other.isTop && this.isBottom == other.isBottom
&& this.onExceptionPath == other.onExceptionPath && this.stateMap.equals(other.stateMap);
@@ -287,16 +291,17 @@ public class StateSet {
@Override
public String toString() {
- if (isTop)
+ if (isTop) {
return "TOP";
- else if (isBottom)
+ } else if (isBottom) {
return "BOTTOM";
- else {
+ } else {
StringBuilder buf = new StringBuilder();
buf.append(stateMap);
-
- if (onExceptionPath)
+
+ if (onExceptionPath) {
buf.append(" On exception path");
+ }
return buf.toString();
}
}
@@ -310,4 +315,3 @@ public class StateSet {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/BottomType.java b/src/java/edu/umd/cs/findbugs/ba/type/BottomType.java
index c1ae9eb..8f29232 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/BottomType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/BottomType.java
@@ -23,7 +23,7 @@ import org.apache.bcel.generic.Type;
/**
* Special "bottom" type. It is the zero element for the type merge operation.
- *
+ *
* @author David Hovemeyer
* @see TypeAnalysis
* @see TypeFrame
@@ -59,4 +59,3 @@ public class BottomType extends Type implements ExtendedTypes {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/DoubleExtraType.java b/src/java/edu/umd/cs/findbugs/ba/type/DoubleExtraType.java
index 3af7eae..d6d426d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/DoubleExtraType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/DoubleExtraType.java
@@ -25,7 +25,7 @@ import org.apache.bcel.generic.Type;
* Special type used to represent the "extra" part of a double value. We say
* that when a double is stored, local <i>n</i> will have type double, and local
* <i>n+1</i> will have this type.
- *
+ *
* @author David Hovemeyer
* @see TypeAnalysis
* @see TypeFrame
@@ -58,4 +58,3 @@ public class DoubleExtraType extends Type implements ExtendedTypes {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/ExceptionObjectType.java b/src/java/edu/umd/cs/findbugs/ba/type/ExceptionObjectType.java
index 8485d56..224e754 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/ExceptionObjectType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/ExceptionObjectType.java
@@ -34,11 +34,11 @@ public class ExceptionObjectType extends ObjectType implements Constants, Extend
*/
private static final long serialVersionUID = 1L;
- private ExceptionSet exceptionSet;
+ private final ExceptionSet exceptionSet;
/**
* Constructor.
- *
+ *
* @param className
* the class name
* @param exceptionSet
@@ -51,7 +51,7 @@ public class ExceptionObjectType extends ObjectType implements Constants, Extend
/**
* Initialize object from an exception set.
- *
+ *
* @param exceptionSet
* the exception set
* @return a Type that is a supertype of all of the exceptions in the
@@ -59,14 +59,16 @@ public class ExceptionObjectType extends ObjectType implements Constants, Extend
*/
public static Type fromExceptionSet(ExceptionSet exceptionSet) throws ClassNotFoundException {
Type commonSupertype = exceptionSet.getCommonSupertype();
- if (commonSupertype.getType() != T_OBJECT)
+ if (commonSupertype.getType() != T_OBJECT) {
return commonSupertype;
+ }
ObjectType exceptionSupertype = (ObjectType) commonSupertype;
String className = exceptionSupertype.getClassName();
- if (className.equals("java.lang.Throwable"))
+ if ("java.lang.Throwable".equals(className)) {
return exceptionSupertype;
+ }
return new ExceptionObjectType(className, exceptionSet);
}
@@ -82,10 +84,12 @@ public class ExceptionObjectType extends ObjectType implements Constants, Extend
@Override
public boolean equals(Object o) {
- if (o == null)
+ if (o == null) {
return false;
- if (o.getClass() != this.getClass())
+ }
+ if (o.getClass() != this.getClass()) {
return false;
+ }
ExceptionObjectType other = (ExceptionObjectType) o;
return getSignature().equals(other.getSignature()) && exceptionSet.equals(other.exceptionSet);
@@ -93,7 +97,7 @@ public class ExceptionObjectType extends ObjectType implements Constants, Extend
/**
* Return the exception set.
- *
+ *
* @return the ExceptionSet
*/
public ExceptionSet getExceptionSet() {
@@ -106,10 +110,11 @@ public class ExceptionObjectType extends ObjectType implements Constants, Extend
buf.append("<exception:");
boolean first = true;
for (ExceptionSet.ThrownExceptionIterator i = exceptionSet.iterator(); i.hasNext();) {
- if (first)
+ if (first) {
first = false;
- else
+ } else {
buf.append(',');
+ }
buf.append(i.next().toString());
}
buf.append(">");
@@ -117,4 +122,3 @@ public class ExceptionObjectType extends ObjectType implements Constants, Extend
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/ExceptionSet.java b/src/java/edu/umd/cs/findbugs/ba/type/ExceptionSet.java
index de3fbdc..1fe4334 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/ExceptionSet.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/ExceptionSet.java
@@ -67,15 +67,19 @@ public class ExceptionSet implements Serializable {
findNext();
}
+ @Override
public boolean hasNext() {
- if (last == next)
+ if (last == next) {
findNext();
+ }
return next < factory.getNumTypes();
}
+ @Override
public ObjectType next() {
- if (!hasNext())
+ if (!hasNext()) {
throw new NoSuchElementException();
+ }
ObjectType result = factory.getType(next);
last = next;
return result;
@@ -85,6 +89,7 @@ public class ExceptionSet implements Serializable {
return explicitSet.get(last);
}
+ @Override
public void remove() {
exceptionSet.clear(last);
explicitSet.clear(last);
@@ -95,8 +100,9 @@ public class ExceptionSet implements Serializable {
private void findNext() {
++next;
while (next < factory.getNumTypes()) {
- if (exceptionSet.get(next))
+ if (exceptionSet.get(next)) {
break;
+ }
++next;
}
}
@@ -136,10 +142,12 @@ public class ExceptionSet implements Serializable {
@Override
public boolean equals(Object o) {
- if (o == null)
+ if (o == null) {
return false;
- if (o.getClass() != this.getClass())
+ }
+ if (o.getClass() != this.getClass()) {
return false;
+ }
ExceptionSet other = (ExceptionSet) o;
return exceptionSet.equals(other.exceptionSet) && explicitSet.equals(other.explicitSet)
@@ -151,8 +159,9 @@ public class ExceptionSet implements Serializable {
* in the set. Returns the special TOP type if the set is empty.
*/
public Type getCommonSupertype() throws ClassNotFoundException {
- if (commonSupertype != null)
+ if (commonSupertype != null) {
return commonSupertype;
+ }
if (isEmpty()) {
// This probably means that we're looking at an
@@ -205,8 +214,9 @@ public class ExceptionSet implements Serializable {
* @return true if it is
*/
public boolean isSingleton(String exceptionName) {
- if (size != 1)
+ if (size != 1) {
return false;
+ }
ObjectType e = iterator().next();
return e.toString().equals(exceptionName);
@@ -243,11 +253,13 @@ public class ExceptionSet implements Serializable {
*/
public void add(ObjectType type, boolean explicit) {
int index = factory.getIndexOfType(type);
- if (!exceptionSet.get(index))
+ if (!exceptionSet.get(index)) {
++size;
+ }
exceptionSet.set(index);
- if (explicit)
+ if (explicit) {
explicitSet.set(index);
+ }
commonSupertype = null;
}
@@ -269,8 +281,9 @@ public class ExceptionSet implements Serializable {
private int countBits(BitSet bitSet) {
int count = 0;
for (int i = 0; i < factory.getNumTypes(); ++i) {
- if (bitSet.get(i))
+ if (bitSet.get(i)) {
++count;
+ }
}
return count;
}
@@ -308,8 +321,9 @@ public class ExceptionSet implements Serializable {
public boolean containsCheckedExceptions() throws ClassNotFoundException {
for (ThrownExceptionIterator i = iterator(); i.hasNext();) {
ObjectType type = i.next();
- if (!Hierarchy.isUncheckedException(type))
+ if (!Hierarchy.isUncheckedException(type)) {
return true;
+ }
}
return false;
}
@@ -320,8 +334,9 @@ public class ExceptionSet implements Serializable {
public boolean containsExplicitExceptions() {
for (ThrownExceptionIterator i = iterator(); i.hasNext();) {
i.next();
- if (i.isExplicit())
+ if (i.isExplicit()) {
return true;
+ }
}
return false;
}
@@ -333,16 +348,19 @@ public class ExceptionSet implements Serializable {
boolean first = true;
for (ThrownExceptionIterator i = iterator(); i.hasNext();) {
ObjectType type = i.next();
- if (first)
+ if (first) {
first = false;
- else
+ } else {
buf.append(',');
+ }
boolean implicit = !i.isExplicit();
- if (implicit)
+ if (implicit) {
buf.append('[');
+ }
buf.append(type.toString());
- if (implicit)
+ if (implicit) {
buf.append(']');
+ }
}
buf.append('}');
return buf.toString();
@@ -353,4 +371,3 @@ public class ExceptionSet implements Serializable {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/ExceptionSetFactory.java b/src/java/edu/umd/cs/findbugs/ba/type/ExceptionSetFactory.java
index 5ea71e0..c7f553b 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/ExceptionSetFactory.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/ExceptionSetFactory.java
@@ -31,9 +31,9 @@ public class ExceptionSetFactory implements Serializable {
*/
private static final long serialVersionUID = 1L;
- private HashMap<ObjectType, Integer> typeIndexMap;
+ private final HashMap<ObjectType, Integer> typeIndexMap;
- private ArrayList<ObjectType> typeList;
+ private final ArrayList<ObjectType> typeList;
public ExceptionSetFactory() {
this.typeIndexMap = new HashMap<ObjectType, Integer>();
@@ -63,4 +63,3 @@ public class ExceptionSetFactory implements Serializable {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/ExtendedTypes.java b/src/java/edu/umd/cs/findbugs/ba/type/ExtendedTypes.java
index 49fcfd5..260d3ae 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/ExtendedTypes.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/ExtendedTypes.java
@@ -22,7 +22,7 @@ package edu.umd.cs.findbugs.ba.type;
/**
* Extended type codes used by StackAndLocalTypes and StackAndLocalTypeAnalysis
* for typing locals and stack values used in Java bytecode.
- *
+ *
* @author David Hovemeyer
* @see TypeFrame
* @see TypeAnalysis
@@ -79,4 +79,3 @@ public interface ExtendedTypes {
public static final byte T_AVAIL_TYPE = 100;
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/FieldStoreType.java b/src/java/edu/umd/cs/findbugs/ba/type/FieldStoreType.java
index 5f5d2f1..02859cc 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/FieldStoreType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/FieldStoreType.java
@@ -34,11 +34,11 @@ import edu.umd.cs.findbugs.ba.ch.Subtypes2;
* Field property storing the types of values stored in a field. The idea is
* that we may be able to determine a more precise type for values loaded from
* the field than the field type alone would indicate.
- *
+ *
* @author David Hovemeyer
*/
public class FieldStoreType {
- private HashSet<String> typeSignatureSet;
+ private final HashSet<String> typeSignatureSet;
private ReferenceType loadType;
@@ -70,8 +70,9 @@ public class FieldStoreType {
try {
String signature = i.next();
Type type = Type.getType(signature);
- if (!(type instanceof ReferenceType))
+ if (!(type instanceof ReferenceType)) {
continue;
+ }
// FIXME: this will mangle interface types, since
// getFirstCommonSuperclass() ignores interfaces.
@@ -100,13 +101,15 @@ public class FieldStoreType {
}
try {
- if (leastSupertype != null && Hierarchy.isSubtype(leastSupertype, fieldType))
+ if (leastSupertype != null && Hierarchy.isSubtype(leastSupertype, fieldType)) {
loadType = leastSupertype;
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
- if (loadType == null)
+ if (loadType == null) {
loadType = fieldType;
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/FieldStoreTypeDatabase.java b/src/java/edu/umd/cs/findbugs/ba/type/FieldStoreTypeDatabase.java
index 8e1f689..889beab 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/FieldStoreTypeDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/FieldStoreTypeDatabase.java
@@ -49,8 +49,9 @@ public class FieldStoreTypeDatabase extends FieldPropertyDatabase<FieldStoreType
continue;
}
ReferenceType storeType = type.getLoadType((ReferenceType) fieldType);
- if (storeType.equals(fieldType))
+ if (storeType.equals(fieldType)) {
removeProperty(f);
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/LongExtraType.java b/src/java/edu/umd/cs/findbugs/ba/type/LongExtraType.java
index d13238a..4572504 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/LongExtraType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/LongExtraType.java
@@ -25,7 +25,7 @@ import org.apache.bcel.generic.Type;
* Special type used to represent the "extra" part of a long value. We say that
* when a long is stored, local <i>n</i> will have type long, and local
* <i>n+1</i> will have this type.
- *
+ *
* @author David Hovemeyer
* @see TypeAnalysis
* @see TypeFrame
@@ -58,4 +58,3 @@ public class LongExtraType extends Type implements ExtendedTypes {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/NullType.java b/src/java/edu/umd/cs/findbugs/ba/type/NullType.java
index 0117a9d..7434689 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/NullType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/NullType.java
@@ -26,7 +26,7 @@ import org.apache.bcel.generic.ReferenceType;
* the lattice than any object type, but lower than the overall Top type. It
* represents the type of the null value, which may logically be merged with any
* object type without loss of information.
- *
+ *
* @author David Hovemeyer
* @see TypeAnalysis
* @see TypeFrame
@@ -57,4 +57,3 @@ public class NullType extends ReferenceType implements ExtendedTypes {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/StandardTypeMerger.java b/src/java/edu/umd/cs/findbugs/ba/type/StandardTypeMerger.java
index a31d197..83eed3e 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/StandardTypeMerger.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/StandardTypeMerger.java
@@ -63,46 +63,53 @@ public class StandardTypeMerger implements TypeMerger, Constants, ExtendedTypes
this.exceptionSetFactory = exceptionSetFactory;
}
+ @Override
public Type mergeTypes(Type a, Type b) throws DataflowAnalysisException {
- if (a == null) return b;
- if (b == null) return a;
+ if (a == null) {
+ return b;
+ }
+ if (b == null) {
+ return a;
+ }
byte aType = a.getType(), bType = b.getType();
- if (aType == T_TOP) // Top is the identity element
+ if (aType == T_TOP) {
return b;
- else if (bType == T_TOP) // Top is the identity element
+ } else if (bType == T_TOP) {
return a;
- else if (aType == T_BOTTOM || bType == T_BOTTOM) // Bottom meet anything
- // is bottom
+ } else if (aType == T_BOTTOM || bType == T_BOTTOM) {
+ // is bottom
return BottomType.instance();
- else if (isReferenceType(aType) && isReferenceType(bType)) { // Two
- // object
- // types!
+ } else if (isReferenceType(aType) && isReferenceType(bType)) { // Two
+ // object
+ // types!
// Handle the Null type, which serves as a special "top"
// value for reference types.
- if (aType == T_NULL)
+ if (aType == T_NULL) {
return b;
- else if (bType == T_NULL)
+ } else if (bType == T_NULL) {
return a;
+ }
ReferenceType aRef = (ReferenceType) a;
ReferenceType bRef = (ReferenceType) b;
return mergeReferenceTypes(aRef, bRef);
- } else if (isReferenceType(aType) || isReferenceType(bType)) // Object
- // meet
- // non-object
- // is
- // bottom
+ } else if (isReferenceType(aType) || isReferenceType(bType)) {
+ // meet
+ // non-object
+ // is
+ // bottom
return BottomType.instance();
- else if (aType == bType) // Same non-object type?
+ } else if (aType == bType) {
return a;
- else if (isIntegerType(aType) && isIntegerType(bType)) // Two different
- // integer types
- // - use T_INT
+ } else if (isIntegerType(aType) && isIntegerType(bType)) {
+ // integer types
+ // - use T_INT
return Type.INT;
- else
+ } else {
// Default - types are incompatible
return BottomType.instance();
+ }
}
/**
@@ -134,10 +141,11 @@ public class StandardTypeMerger implements TypeMerger, Constants, ExtendedTypes
}
private static void updateExceptionSet(ExceptionSet exceptionSet, ObjectType type) {
- if (type instanceof ExceptionObjectType)
+ if (type instanceof ExceptionObjectType) {
exceptionSet.addAll(((ExceptionObjectType) type).getExceptionSet());
- else
+ } else {
exceptionSet.addExplicit(type);
+ }
}
/**
@@ -152,8 +160,9 @@ public class StandardTypeMerger implements TypeMerger, Constants, ExtendedTypes
* @return the merged Type
*/
protected ReferenceType mergeReferenceTypes(ReferenceType aRef, ReferenceType bRef) throws DataflowAnalysisException {
- if (aRef.equals(bRef))
+ if (aRef.equals(bRef)) {
return aRef;
+ }
byte aType = aRef.getType();
byte bType = bRef.getType();
try {
@@ -163,17 +172,20 @@ public class StandardTypeMerger implements TypeMerger, Constants, ExtendedTypes
if (isObjectType(aType) && isObjectType(bType)
&& ((aType == T_EXCEPTION || isThrowable(aRef)) && (bType == T_EXCEPTION || isThrowable(bRef)))) {
ExceptionSet union = exceptionSetFactory.createExceptionSet();
- if (aType == T_OBJECT && aRef.getSignature().equals("Ljava/lang/Throwable;"))
+ if (aType == T_OBJECT && "Ljava/lang/Throwable;".equals(aRef.getSignature())) {
return aRef;
- if (bType == T_OBJECT && bRef.getSignature().equals("Ljava/lang/Throwable;"))
+ }
+ if (bType == T_OBJECT && "Ljava/lang/Throwable;".equals(bRef.getSignature())) {
return bRef;
+ }
updateExceptionSet(union, (ObjectType) aRef);
updateExceptionSet(union, (ObjectType) bRef);
Type t = ExceptionObjectType.fromExceptionSet(union);
- if (t instanceof ReferenceType)
+ if (t instanceof ReferenceType) {
return (ReferenceType) t;
+ }
}
if (aRef instanceof GenericObjectType && bRef instanceof GenericObjectType
@@ -187,11 +199,13 @@ public class StandardTypeMerger implements TypeMerger, Constants, ExtendedTypes
List<? extends ReferenceType> bP = bG.getParameters();
assert aP != null;
assert bP != null;
- if (aP.size() != bP.size())
+ if (aP.size() != bP.size()) {
break;
+ }
ArrayList<ReferenceType> result = new ArrayList<ReferenceType>(aP.size());
- for (int i = 0; i < aP.size(); i++)
+ for (int i = 0; i < aP.size(); i++) {
result.add(mergeReferenceTypes(aP.get(i), bP.get(i)));
+ }
GenericObjectType rOT = GenericUtilities.getType(aG.getClassName(), result);
return rOT;
@@ -201,10 +215,12 @@ public class StandardTypeMerger implements TypeMerger, Constants, ExtendedTypes
}
}
- if (aRef instanceof GenericObjectType)
+ if (aRef instanceof GenericObjectType) {
aRef = ((GenericObjectType) aRef).getObjectType();
- if (bRef instanceof GenericObjectType)
+ }
+ if (bRef instanceof GenericObjectType) {
bRef = ((GenericObjectType) bRef).getObjectType();
+ }
if (Subtypes2.ENABLE_SUBTYPES2_FOR_COMMON_SUPERCLASS_QUERIES) {
return AnalysisContext.currentAnalysisContext().getSubtypes2().getFirstCommonSuperclass(aRef, bRef);
@@ -218,13 +234,13 @@ public class StandardTypeMerger implements TypeMerger, Constants, ExtendedTypes
}
private boolean isThrowable(ReferenceType ref) /*
- * throws
- * ClassNotFoundException
- */{
+ * throws
+ * ClassNotFoundException
+ */{
try {
- Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
- return subtypes2.isSubtype(ref, Type.THROWABLE);
+ Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
+ return subtypes2.isSubtype(ref, Type.THROWABLE);
} catch (ClassNotFoundException e) {
// We'll just assume that it's not an exception type.
@@ -235,4 +251,3 @@ public class StandardTypeMerger implements TypeMerger, Constants, ExtendedTypes
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/ThrownException.java b/src/java/edu/umd/cs/findbugs/ba/type/ThrownException.java
index 029a1e9..b9648d9 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/ThrownException.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/ThrownException.java
@@ -31,19 +31,19 @@ import org.apache.bcel.generic.ObjectType;
* <li>which exceptions are explicit (declared or explicitly thrown) and which
* are implicit (result of failed runtime checks)
* </ul>
- *
+ *
* @author David Hovemeyer
* @see ExceptionSet
* @see TypeAnalysis
*/
public class ThrownException {
- private ObjectType type;
+ private final ObjectType type;
private boolean explicit;
/**
* Constructor.
- *
+ *
* @param type
* type of exception
* @param explicit
@@ -89,14 +89,15 @@ public class ThrownException {
@Override
public boolean equals(Object o) {
- if (o == null)
+ if (o == null) {
return false;
- if (o.getClass() != this.getClass())
+ }
+ if (o.getClass() != this.getClass()) {
return false;
+ }
ThrownException other = (ThrownException) o;
return this.type.equals(other.type) && this.explicit == other.explicit;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/TopType.java b/src/java/edu/umd/cs/findbugs/ba/type/TopType.java
index 75331d6..7e8a755 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/TopType.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/TopType.java
@@ -23,7 +23,7 @@ import org.apache.bcel.generic.Type;
/**
* Special "top" type. It is the identity element for the type merge operation.
- *
+ *
* @author David Hovemeyer
* @see TypeAnalysis
* @see TypeFrame
@@ -59,4 +59,3 @@ public class TopType extends Type implements ExtendedTypes {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/TypeAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/type/TypeAnalysis.java
index 2a06be9..5c0ed26 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/TypeAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/TypeAnalysis.java
@@ -77,7 +77,7 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
* exception edge in the CFG. This information can be used to prune infeasible
* exception edges, and mark exception edges which propagate only implicit
* exceptions.
- *
+ *
* @author David Hovemeyer
* @see Dataflow
* @see edu.umd.cs.findbugs.ba.DataflowAnalysis
@@ -99,11 +99,11 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
* recomputed for the block.
*/
private class CachedExceptionSet {
- private TypeFrame result;
+ private final TypeFrame result;
- private ExceptionSet exceptionSet;
+ private final ExceptionSet exceptionSet;
- private Map<Edge, ExceptionSet> edgeExceptionMap;
+ private final Map<Edge, ExceptionSet> edgeExceptionMap;
public CachedExceptionSet(TypeFrame result, ExceptionSet exceptionSet) {
this.result = result;
@@ -167,23 +167,23 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
protected CFG cfg;
- private TypeMerger typeMerger;
+ private final TypeMerger typeMerger;
- private TypeFrameModelingVisitor visitor;
+ private final TypeFrameModelingVisitor visitor;
- private Map<BasicBlock, CachedExceptionSet> thrownExceptionSetMap;
+ private final Map<BasicBlock, CachedExceptionSet> thrownExceptionSetMap;
- private RepositoryLookupFailureCallback lookupFailureCallback;
+ private final RepositoryLookupFailureCallback lookupFailureCallback;
- private ExceptionSetFactory exceptionSetFactory;
+ private final ExceptionSetFactory exceptionSetFactory;
private ValueNumberDataflow valueNumberDataflow;
- private Map<BasicBlock, InstanceOfCheck> instanceOfCheckMap;
+ private final Map<BasicBlock, InstanceOfCheck> instanceOfCheckMap;
/**
* Constructor.
- *
+ *
* @param method
* TODO
* @param methodGen
@@ -208,11 +208,13 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
super(dfs);
this.method = method;
Code code = method.getCode();
- if (code == null)
+ if (code == null) {
throw new IllegalArgumentException(method.getName() + " has no code");
+ }
for (Attribute a : code.getAttributes()) {
- if (a instanceof LocalVariableTypeTable)
+ if (a instanceof LocalVariableTypeTable) {
visitor.setLocalTypeTable((LocalVariableTypeTable) a);
+ }
}
this.methodGen = methodGen;
this.cfg = cfg;
@@ -229,7 +231,7 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
/**
* Constructor.
- *
+ *
* @param method
* TODO
* @param methodGen
@@ -249,13 +251,14 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
RepositoryLookupFailureCallback lookupFailureCallback, ExceptionSetFactory exceptionSetFactory) {
this(method, methodGen, cfg, dfs, typeMerger, new TypeFrameModelingVisitor(methodGen.getConstantPool(), typeMerger),
lookupFailureCallback, exceptionSetFactory);
- if (TypeFrameModelingVisitor.DEBUG)
+ if (TypeFrameModelingVisitor.DEBUG) {
System.out.println(methodGen.getClassName() + "." + methodGen.getName() + " " + methodGen.getSignature());
+ }
}
/**
* Constructor which uses StandardTypeMerger.
- *
+ *
* @param method
* TODO
* @param methodGen
@@ -279,7 +282,7 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
* Set the ValueNumberDataflow for the method being analyzed. This is
* optional; if set, it will be used to make instanceof instructions more
* precise.
- *
+ *
* @param valueNumberDataflow
* the ValueNumberDataflow
*/
@@ -291,7 +294,7 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
/**
* Set the FieldStoreTypeDatabase. This can be used to get more accurate
* types for values loaded from fields.
- *
+ *
* @param database
* the FieldStoreTypeDatabase
*/
@@ -302,7 +305,7 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
/**
* Get the set of exceptions that can be thrown on given edge. This should
* only be called after the analysis completes.
- *
+ *
* @param edge
* the Edge
* @return the ExceptionSet
@@ -312,10 +315,12 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
return cachedExceptionSet.getEdgeExceptionSet(edge);
}
+ @Override
public TypeFrame createFact() {
return new TypeFrame(methodGen.getMaxLocals());
}
+ @Override
public void initEntryFact(TypeFrame result) {
// Make the frame valid
result.setValid();
@@ -326,8 +331,9 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
result.clearStack();
// Add local for "this" pointer, if present
- if (!methodGen.isStatic())
+ if (!methodGen.isStatic()) {
result.setValue(slot++, ObjectTypeFactory.getInstance(methodGen.getClassName()));
+ }
// [Added: Support for Generics]
// Get a parser that reads the generic signature of the method and
@@ -355,8 +361,9 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
// replace with a generic version of the type
try {
Type t = GenericUtilities.getType(s);
- if (t != null)
+ if (t != null) {
argType = t;
+ }
} catch (RuntimeException e) {
} // degrade gracefully
}
@@ -367,8 +374,9 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
// Set remaining locals to BOTTOM; this will cause any
// uses of them to be flagged
- while (slot < methodGen.getMaxLocals())
+ while (slot < methodGen.getMaxLocals()) {
result.setValue(slot++, TypeFrame.getBottomType());
+ }
}
@Override
@@ -398,14 +406,6 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
visitor.analyzeInstruction(handle.getInstruction());
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#transfer(edu.umd.cs.findbugs
- * .ba.BasicBlock, org.apache.bcel.generic.InstructionHandle,
- * java.lang.Object, java.lang.Object)
- */
@Override
public void transfer(BasicBlock basicBlock, @CheckForNull InstructionHandle end, TypeFrame start, TypeFrame result)
throws DataflowAnalysisException {
@@ -434,17 +434,20 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
// Do nothing if we're not computing propagated exceptions
if (!(FORCE_ACCURATE_EXCEPTIONS || AnalysisContext.currentAnalysisContext().getBoolProperty(
- AnalysisFeatures.ACCURATE_EXCEPTIONS)))
+ AnalysisFeatures.ACCURATE_EXCEPTIONS))) {
return;
+ }
// Also, nothing to do if the block is not an exception thrower
- if (!basicBlock.isExceptionThrower())
+ if (!basicBlock.isExceptionThrower()) {
return;
+ }
// If cached results are up to date, don't recompute.
CachedExceptionSet cachedExceptionSet = getCachedExceptionSet(basicBlock);
- if (cachedExceptionSet.isUpToDate(result))
+ if (cachedExceptionSet.isUpToDate(result)) {
return;
+ }
// Figure out what exceptions can be thrown out
// of the basic block, and mark each exception edge
@@ -481,15 +484,18 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
// In the process, this will remove exceptions from
// the thrown exception set.
ExceptionSet thrownExceptionSet = cachedExceptionSet.getExceptionSet();
- if (!thrownExceptionSet.isEmpty())
+ if (!thrownExceptionSet.isEmpty()) {
thrownExceptionSet = thrownExceptionSet.duplicate();
+ }
for (Iterator<Edge> i = cfg.outgoingEdgeIterator(basicBlock); i.hasNext();) {
Edge edge = i.next();
- if (edge.isExceptionEdge())
+ if (edge.isExceptionEdge()) {
cachedExceptionSet.setEdgeExceptionSet(edge, computeEdgeExceptionSet(edge, thrownExceptionSet));
+ }
}
}
+ @Override
public void meetInto(TypeFrame fact, Edge edge, TypeFrame result) throws DataflowAnalysisException {
BasicBlock basicBlock = edge.getTarget();
@@ -498,7 +504,7 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
// Handling an exception?
if (basicBlock.isExceptionHandler()) {
- tmpFact = modifyFrame(fact, tmpFact);
+ tmpFact = modifyFrame(fact, null);
// Special case: when merging predecessor facts for entry to
// an exception handler, we clear the stack and push a
@@ -531,8 +537,10 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
// pick a type conservatively using the handler catch type.
catchType = exceptionGen.getCatchType();
if (catchType == null)
+ {
catchType = Type.THROWABLE; // handle catches anything
- // throwable
+ // throwable
+ }
}
tmpFact.pushValue(catchType);
@@ -569,12 +577,14 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
ValueNumber instanceOfValueNumber = check.getValueNumber();
ValueNumberFrame vnaFrame = valueNumberDataflow.getStartFact(edge.getTarget());
- if (!vnaFrame.isValid())
+ if (!vnaFrame.isValid()) {
return tmpFact;
+ }
Type instanceOfType = check.getType();
- if (!(instanceOfType instanceof ReferenceType || instanceOfType instanceof NullType))
+ if (!(instanceOfType instanceof ReferenceType || instanceOfType instanceof NullType)) {
return tmpFact;
+ }
short branchOpcode = edge.getSource().getLastInstruction().getInstruction().getOpcode();
@@ -589,20 +599,23 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
// Successful instanceof check.
for (int i = 0; i < numSlots; ++i) {
- if (!vnaFrame.getValue(i).equals(instanceOfValueNumber))
+ if (!vnaFrame.getValue(i).equals(instanceOfValueNumber)) {
continue;
+ }
Type checkedType = fact.getValue(i);
- if (!(checkedType instanceof ReferenceType))
+ if (!(checkedType instanceof ReferenceType)) {
continue;
+ }
// Only refine the type if the cast is feasible: i.e., a
// downcast.
// Otherwise, just set it to TOP.
try {
boolean guaranteed = Hierarchy.isSubtype((ReferenceType) checkedType, (ReferenceType) instanceOfType);
- if (guaranteed)
+ if (guaranteed) {
continue;
+ }
boolean feasibleCheck = instanceOfType.equals(NullType.instance())
|| Hierarchy.isSubtype((ReferenceType) instanceOfType, (ReferenceType) checkedType);
@@ -610,8 +623,9 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
if (!feasibleCheck && instanceOfType instanceof ObjectType && checkedType instanceof ObjectType) {
double v = Analyze.deepInstanceOf(((ObjectType) instanceOfType).getClassName(),
((ObjectType) checkedType).getClassName());
- if (v > 0.0)
+ if (v > 0.0) {
feasibleCheck = true;
+ }
}
tmpFact = modifyFrame(fact, tmpFact);
if (feasibleCheck) {
@@ -628,16 +642,19 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
} else if (!instanceOfType.equals(NullType.instance())) {
for (int i = 0; i < numSlots; ++i) {
- if (!vnaFrame.getValue(i).equals(instanceOfValueNumber))
+ if (!vnaFrame.getValue(i).equals(instanceOfValueNumber)) {
continue;
+ }
Type checkedType = fact.getValue(i);
- if (!(checkedType instanceof ReferenceType))
+ if (!(checkedType instanceof ReferenceType)) {
continue;
+ }
try {
boolean guaranteed = Hierarchy.isSubtype((ReferenceType) checkedType, (ReferenceType) instanceOfType);
- if (!guaranteed)
+ if (!guaranteed) {
continue;
+ }
tmpFact = modifyFrame(fact, tmpFact);
tmpFact.setTop();
return tmpFact;
@@ -672,7 +689,7 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
* Get the cached set of exceptions that can be thrown from given basic
* block. If this information hasn't been computed yet, then an empty
* exception set is returned.
- *
+ *
* @param basicBlock
* the block to get the cached exception set for
* @return the CachedExceptionSet for the block
@@ -701,7 +718,7 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
* Compute the set of exceptions that can be thrown from the given basic
* block. This should only be called if the existing cached exception set is
* out of date.
- *
+ *
* @param basicBlock
* the basic block
* @param result
@@ -712,7 +729,7 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
private CachedExceptionSet computeBlockExceptionSet(BasicBlock basicBlock, TypeFrame result) throws DataflowAnalysisException {
ExceptionSet exceptionSet = computeThrownExceptionTypes(basicBlock);
-
+
TypeFrame copyOfResult = createFact();
copy(result, copyOfResult);
@@ -729,7 +746,7 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
* exception edge. This method should be called for each outgoing exception
* edge in sequence, so the caught exceptions can be removed from the thrown
* exception set as needed.
- *
+ *
* @param edge
* the exception edge
* @param thrownExceptionSet
@@ -739,8 +756,9 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
*/
private ExceptionSet computeEdgeExceptionSet(Edge edge, ExceptionSet thrownExceptionSet) {
- if (thrownExceptionSet.isEmpty())
+ if (thrownExceptionSet.isEmpty()) {
return thrownExceptionSet;
+ }
ExceptionSet result = exceptionSetFactory.createExceptionSet();
if (edge.getType() == UNHANDLED_EXCEPTION_EDGE) {
@@ -769,8 +787,9 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
ObjectType thrownType = i.next();
boolean explicit = i.isExplicit();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\texception type " + thrownType + ", catch type " + catchType);
+ }
try {
if (Hierarchy.isSubtype(thrownType, catchType)) {
@@ -780,14 +799,16 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
// And it will definitely be caught
i.remove();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\tException is subtype of catch type: " + "will definitely catch");
+ }
} else if (Hierarchy.isSubtype(catchType, thrownType)) {
// Exception possibly thrown along this edge
result.add(thrownType, explicit);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\tException is supertype of catch type: " + "might catch");
+ }
}
} catch (ClassNotFoundException e) {
// As a special case, if a class hierarchy lookup
@@ -806,13 +827,13 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
/**
* Compute the set of exception types that can be thrown by given basic
* block.
- *
+ *
* @param basicBlock
* the basic block
* @return the set of exceptions that can be thrown by the block
*/
private ExceptionSet computeThrownExceptionTypes(BasicBlock basicBlock) throws
- DataflowAnalysisException {
+ DataflowAnalysisException {
ExceptionSet exceptionTypeSet = exceptionSetFactory.createExceptionSet();
InstructionHandle pei = basicBlock.getExceptionThrower();
@@ -894,9 +915,10 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
// Couldn't find declared exceptions,
// so conservatively assume it could thrown any checked
// exception.
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Couldn't find declared exceptions for "
+ SignatureConverter.convertMethodSignature(inv, cpg));
+ }
exceptionTypeSet.addExplicit(Hierarchy.EXCEPTION_TYPE);
} else {
for (ObjectType aDeclaredExceptionList : declaredExceptionList) {
@@ -907,8 +929,9 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
exceptionTypeSet.addImplicit(Hierarchy.RUNTIME_EXCEPTION_TYPE);
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println(pei + " can throw " + exceptionTypeSet);
+ }
return exceptionTypeSet;
}
@@ -943,5 +966,3 @@ public class TypeAnalysis extends FrameDataflowAnalysis<Type, TypeFrame> impleme
// driver.execute(argv[0]);
// }
}
-
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/TypeDataflow.java b/src/java/edu/umd/cs/findbugs/ba/type/TypeDataflow.java
index b5422ae..060a743 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/TypeDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/TypeDataflow.java
@@ -69,4 +69,3 @@ public class TypeDataflow extends Dataflow<TypeFrame, TypeAnalysis> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/TypeFrame.java b/src/java/edu/umd/cs/findbugs/ba/type/TypeFrame.java
index cdd75a1..0491a64 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/TypeFrame.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/TypeFrame.java
@@ -35,7 +35,7 @@ import edu.umd.cs.findbugs.ba.Frame;
* @see TypeAnalysis
*/
public class TypeFrame extends Frame<Type> {
- private BitSet exactTypeSet;
+ private final BitSet exactTypeSet;
/**
* Constructor.
@@ -164,10 +164,12 @@ public class TypeFrame extends Frame<Type> {
@Override
public String toString() {
- if (isTop())
+ if (isTop()) {
return "[TOP]";
- if (isBottom())
+ }
+ if (isBottom()) {
return "[BOTTOM]";
+ }
StringBuilder buf = new StringBuilder();
buf.append('[');
int numSlots = getNumSlots();
@@ -179,16 +181,19 @@ public class TypeFrame extends Frame<Type> {
// the operand stack.
int last = buf.length() - 1;
if (last >= 0) {
- if (buf.charAt(last) == ',')
+ if (buf.charAt(last) == ',') {
buf.deleteCharAt(last);
+ }
}
buf.append(" | ");
}
- if (isExact(i))
+ if (isExact(i)) {
buf.append("!");
+ }
String value = valueToString(getValue(i));
- if (i == numSlots - 1 && value.endsWith(","))
+ if (i == numSlots - 1 && value.endsWith(",")) {
value = value.substring(0, value.length() - 1);
+ }
buf.append(value);
// buf.append(' ');
}
@@ -198,4 +203,3 @@ public class TypeFrame extends Frame<Type> {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/TypeFrameModelingVisitor.java b/src/java/edu/umd/cs/findbugs/ba/type/TypeFrameModelingVisitor.java
index 0bebdee..66498ed 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/TypeFrameModelingVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/TypeFrameModelingVisitor.java
@@ -100,8 +100,6 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
* examining
* @param typeMerger
* TODO
- * @param typesComputerFromGenerics
- * TODO
*/
public TypeFrameModelingVisitor(ConstantPoolGen cpg, TypeMerger typeMerger) {
super(cpg);
@@ -123,13 +121,14 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
public void setLocalTypeTable(LocalVariableTypeTable localTypeTable) {
this.localTypeTable = localTypeTable;
- if (localTypeTable == null)
+ if (localTypeTable == null) {
genericLocalVariables = null;
- else {
+ } else {
genericLocalVariables = new BitSet();
for(LocalVariable lv : localTypeTable.getLocalVariableTypeTable()) {
- if (lv.getSignature().indexOf('<') > 0)
+ if (lv.getSignature().indexOf('<') > 0) {
genericLocalVariables.set(lv.getIndex());
+ }
}
}
@@ -217,8 +216,12 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
TypeFrame frame = getFrame();
int numWordsConsumed = ins.consumeStack(cpg);
- if (numWordsConsumed == Constants.UNPREDICTABLE)
+ if (numWordsConsumed == Constants.UNPREDICTABLE) {
throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins);
+ }
+ if (numWordsConsumed > frame.getStackDepth()) {
+ throw new InvalidBytecodeException("Stack underflow for " + ins + ", " + numWordsConsumed + " needed, " + frame.getStackDepth() + " avail, frame is " + frame);
+ }
try {
while (numWordsConsumed-- > 0) {
frame.popValue();
@@ -234,8 +237,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
* method ensures that we push two types for each double or long value.
*/
protected void pushValue(Type type) {
- if (type.getType() == T_VOID)
+ if (type.getType() == T_VOID) {
throw new IllegalArgumentException("Can't push void");
+ }
TypeFrame frame = getFrame();
if (type.getType() == T_LONG) {
frame.pushValue(Type.LONG);
@@ -243,8 +247,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
} else if (type.getType() == T_DOUBLE) {
frame.pushValue(Type.DOUBLE);
frame.pushValue(TypeFrame.getDoubleExtraType());
- } else
+ } else {
frame.pushValue(type);
+ }
}
/**
@@ -253,8 +258,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
protected void pushReturnType(InvokeInstruction ins) {
ConstantPoolGen cpg = getCPG();
Type type = ins.getType(cpg);
- if (type.getType() != T_VOID)
+ if (type.getType() != T_VOID) {
pushValue(type);
+ }
}
/**
@@ -264,8 +270,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
@Override
public void modelNormalInstruction(Instruction ins, int numWordsConsumed, int numWordsProduced) {
if (VERIFY_INTEGRITY) {
- if (numWordsProduced > 0)
+ if (numWordsProduced > 0) {
throw new InvalidBytecodeException("missing visitor method for " + ins);
+ }
}
super.modelNormalInstruction(ins, numWordsConsumed, numWordsProduced);
}
@@ -350,21 +357,19 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
Type loadType = obj.getFieldType(cpg);
XField xfield = Hierarchy.findXField(obj, getCPG());
- if (xfield != null)
+ if (xfield != null) {
loadType = getType(xfield);
+ }
pushValue(loadType);
}
- /**
- * @param xfield
- * @return
- */
public static Type getType(XField xfield) {
Type t = Type.getType(xfield.getSignature());
- if (!(t instanceof ReferenceType))
+ if (!(t instanceof ReferenceType)) {
return t;
+ }
ReferenceType loadType = (ReferenceType) t;
// Check the field store type database to see if we can
@@ -390,7 +395,7 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
if (xfield.isFinal() && summary.isNull()) {
return TypeFrame.getNullType();
}
- if (!summary.getSignature().equals("Ljava/lang/Object;")) {
+ if (!"Ljava/lang/Object;".equals(summary.getSignature())) {
loadType = (ReferenceType) Type.getType(summary
.getSignature());
}
@@ -413,8 +418,8 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
String methodName = obj.getMethodName(cpg);
String signature = obj.getSignature(cpg);
String className = obj.getClassName(cpg);
- if (methodName.equals("asList") && className.equals("java.util.Arrays")
- && signature.equals("([Ljava/lang/Object;)Ljava/util/List;")) {
+ if ("asList".equals(methodName) && "java.util.Arrays".equals(className)
+ && "([Ljava/lang/Object;)Ljava/util/List;".equals(signature)) {
consumeStack(obj);
Type returnType = Type.getType("Ljava/util/Arrays$ArrayList;");
pushValue(returnType);
@@ -446,8 +451,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
List<? extends ReferenceType> parameters = genericMapType.getParameters();
if (parameters != null && parameters.size() == expectedParameters) {
ReferenceType resultType = parameters.get(index);
- if (resultType instanceof GenericObjectType)
+ if (resultType instanceof GenericObjectType) {
resultType = ((GenericObjectType) resultType).produce();
+ }
typesComputedFromGenerics.add(resultType);
frame.popValue();
frame.pushValue(resultType);
@@ -468,8 +474,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
if (mapType instanceof GenericObjectType) {
GenericObjectType genericMapType = (GenericObjectType) mapType;
List<? extends ReferenceType> parameters = genericMapType.getParameters();
- if (parameters == null)
+ if (parameters == null) {
return false;
+ }
if (parameters.size() == expectedNumberOfTypeParameters) {
ReferenceType keyType = parameters.get(index);
frame.popValue();
@@ -498,13 +505,13 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
String className = obj.getClassName(cpg);
String returnValueSignature = new SignatureParser(signature).getReturnTypeSignature();
- if (returnValueSignature.equals("V")) {
+ if ("V".equals(returnValueSignature)) {
consumeStack(obj);
return;
}
- if (methodName.equals("isInstance")) {
- if (className.equals("java.lang.Class") && valueNumberDataflow != null) {
+ if ("isInstance".equals(methodName)) {
+ if ("java.lang.Class".equals(className) && valueNumberDataflow != null) {
// Record the value number of the value checked by this
// instruction,
// and the type the value was compared to.
@@ -515,8 +522,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
if (stackValue.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
String c = valueNumberDataflow.getClassName(stackValue);
if (c != null) {
- if (c.charAt(0) != '[' && !c.endsWith(";"))
+ if (c.charAt(0) != '[' && !c.endsWith(";")) {
c = "L" + c.replace('.', '/') + ";";
+ }
Type type = Type.getType(c);
if (type instanceof ReferenceType) {
instanceOfValueNumber = vnaFrame.getTopValue();
@@ -540,7 +548,7 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
return;
}
- if (methodName.equals("cast") && className.equals("java.lang.Class")) {
+ if ("cast".equals(methodName) && "java.lang.Class".equals(className)) {
try {
Type resultType = frame.popValue();
frame.popValue();
@@ -552,7 +560,7 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
return;
}
- mapGetCheck: if (methodName.equals("get") && signature.equals("(Ljava/lang/Object;)Ljava/lang/Object;")
+ mapGetCheck: if ("get".equals(methodName) && "(Ljava/lang/Object;)Ljava/lang/Object;".equals(signature)
&& className.endsWith("Map") && Subtypes2.instanceOf(className, "java.util.Map")
&& frame.getStackDepth() >= 2) {
try {
@@ -560,14 +568,17 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
if (mapType instanceof GenericObjectType) {
GenericObjectType genericMapType = (GenericObjectType) mapType;
List<? extends ReferenceType> parameters = genericMapType.getParameters();
- if (parameters == null || parameters.size() != 2)
+ if (parameters == null || parameters.size() != 2) {
break mapGetCheck;
+ }
ClassDescriptor c = DescriptorFactory.getClassDescriptor(genericMapType);
- if (!Subtypes2.instanceOf(c, Map.class))
+ if (!Subtypes2.instanceOf(c, Map.class)) {
break mapGetCheck;
- if (!isStraightGenericMap(c))
+ }
+ if (!isStraightGenericMap(c)) {
break mapGetCheck;
+ }
ReferenceType valueType = parameters.get(1);
consumeStack(obj);
@@ -581,12 +592,14 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
}
- if (className.equals("java.util.Map$Entry"))
- if (methodName.equals("getKey") && getResultTypeFromGenericType(frame, 0, 2) || methodName.equals("getValue")
- && getResultTypeFromGenericType(frame, 1, 2))
+ if ("java.util.Map$Entry".equals(className)) {
+ if ("getKey".equals(methodName) && getResultTypeFromGenericType(frame, 0, 2) || "getValue".equals(methodName)
+ && getResultTypeFromGenericType(frame, 1, 2)) {
return;
+ }
+ }
- if (methodName.equals("entrySet") && signature.equals("()Ljava/util/Set;") && className.startsWith("java.util")
+ if ("entrySet".equals(methodName) && "()Ljava/util/Set;".equals(signature) && className.startsWith("java.util")
&& className.endsWith("Map")) {
Type argType;
try {
@@ -600,30 +613,35 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
if (argType instanceof GenericObjectType) {
GenericObjectType genericArgType = (GenericObjectType) argType;
List<? extends ReferenceType> parameters = genericArgType.getParameters();
- if (parameters != null && parameters.size() == 2)
+ if (parameters != null && parameters.size() == 2) {
mapType = GenericUtilities.getType("java.util.Map$Entry", parameters);
+ }
}
GenericObjectType entrySetType = GenericUtilities.getType("java.util.Set", Collections.singletonList(mapType));
frame.pushValue(entrySetType);
return;
}
- if (className.startsWith("java.util") && className.endsWith("Map"))
- if (methodName.equals("keySet") && signature.equals("()Ljava/util/Set;")
- && handleGetMapView(frame, "java.util.Set", 0, 2) || methodName.equals("values")
- && signature.equals("()Ljava/util/Collection;") && handleGetMapView(frame, "java.util.Collection", 1, 2))
+ if (className.startsWith("java.util") && className.endsWith("Map")) {
+ if ("keySet".equals(methodName) && "()Ljava/util/Set;".equals(signature)
+ && handleGetMapView(frame, "java.util.Set", 0, 2) || "values".equals(methodName)
+ && "()Ljava/util/Collection;".equals(signature) && handleGetMapView(frame, "java.util.Collection", 1, 2)) {
return;
+ }
+ }
- if (methodName.equals("iterator") && signature.equals("()Ljava/util/Iterator;") && className.startsWith("java.util")
- && handleGetMapView(frame, "java.util.Iterator", 0, 1))
+ if ("iterator".equals(methodName) && "()Ljava/util/Iterator;".equals(signature) && className.startsWith("java.util")
+ && handleGetMapView(frame, "java.util.Iterator", 0, 1)) {
return;
- if (className.equals("java.util.Iterator") && methodName.equals("next") && signature.equals("()Ljava/lang/Object;")
- && getResultTypeFromGenericType(frame, 0, 1))
+ }
+ if ("java.util.Iterator".equals(className) && "next".equals(methodName) && "()Ljava/lang/Object;".equals(signature)
+ && getResultTypeFromGenericType(frame, 0, 1)) {
return;
+ }
- if (methodName.equals("initCause") && signature.equals("(Ljava/lang/Throwable;)Ljava/lang/Throwable;")
+ if ("initCause".equals(methodName) && "(Ljava/lang/Throwable;)Ljava/lang/Throwable;".equals(signature)
&& (className.endsWith("Exception")
- || className.endsWith("Error"))) {
+ || className.endsWith("Error"))) {
try {
frame.popValue();
@@ -632,8 +650,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
AnalysisContext.logError("Ooops", e);
}
}
- if (handleToArray(obj))
+ if (handleToArray(obj)) {
return;
+ }
Type result = TopType.instance();
try {
Set<XMethod> targets = Hierarchy2.resolveMethodCallTargets(obj, frame, cpg);
@@ -646,13 +665,15 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
String sourceSignature = m.getSourceSignature();
if (DEBUG) {
System.out.println(" Call target: " + m);
- if (sourceSignature != null)
+ if (sourceSignature != null) {
System.out.println(" source signature: " + sourceSignature);
+ }
}
boolean foundSomething = false;
XMethod m2 = m.bridgeTo();
- if (m2 != null)
+ if (m2 != null) {
m = m2;
+ }
if (sourceSignature != null && !sourceSignature.equals(m.getSignature())) {
GenericSignatureParser p = new GenericSignatureParser(sourceSignature);
String rv = p.getReturnTypeSignature();
@@ -683,8 +704,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
}
if (!foundSomething) {
result = TopType.instance();
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" giving up");
+ }
break;
}
}
@@ -698,16 +720,18 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
}
consumeStack(obj);
- if (result instanceof TopType)
+ if (result instanceof TopType) {
pushReturnType(obj);
- else
+ } else {
pushValue(result);
+ }
}
public static final Pattern mapSignaturePattern = Pattern.compile("<(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*):L[^;]*;(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*):L[^;]*;>.*Ljava/util/(\\p{javaJavaIdentifierStart}(\\p{javaJavaIdentifierPart}|/)*)?Map<T\\1;T\\2;>;.*");
public static boolean isStraightGenericMap(ClassDescriptor c) {
- if (c.matches(Map.class))
+ if (c.matches(Map.class)) {
return true;
+ }
XClass xc;
try {
xc = c.getXClass();
@@ -715,8 +739,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
return false;
}
String sourceSignature = xc.getSourceSignature();
- if (sourceSignature == null)
+ if (sourceSignature == null) {
return false;
+ }
if (sourceSignature.startsWith("<")) {
Matcher matcher = mapSignaturePattern.matcher(sourceSignature);
if (!matcher.matches()) {
@@ -734,8 +759,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
private Type merge(Type prevType, Type newType) throws DataflowAnalysisException {
if (prevType.equals(TopType.instance())) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Got " + newType);
+ }
return newType;
} else if (prevType.equals(newType)) {
return prevType;
@@ -756,10 +782,10 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
return false;
}
Type topValue = frame.getTopValue();
- if (obj.getName(getCPG()).equals("toArray")) {
+ if ("toArray".equals(obj.getName(getCPG()))) {
ReferenceType target = obj.getReferenceType(getCPG());
String signature = obj.getSignature(getCPG());
- if (signature.equals("([Ljava/lang/Object;)[Ljava/lang/Object;") && Subtypes2.isCollection(target)) {
+ if ("([Ljava/lang/Object;)[Ljava/lang/Object;".equals(signature) && Subtypes2.isCollection(target)) {
boolean topIsExact = frame.isExact(frame.getStackLocation(0));
Type resultType = frame.popValue();
@@ -767,8 +793,8 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
frame.pushValue(resultType);
frame.setExact(frame.getStackLocation(0), topIsExact);
return true;
- } else if (signature.equals("()[Ljava/lang/Object;") && Subtypes2.isCollection(target)
- && !topValue.getSignature().equals("Ljava/util/Arrays$ArrayList;")) {
+ } else if ("()[Ljava/lang/Object;".equals(signature) && Subtypes2.isCollection(target)
+ && !"Ljava/util/Arrays$ArrayList;".equals(topValue.getSignature())) {
consumeStack(obj);
pushReturnType(obj);
frame.setExact(frame.getStackLocation(0), true);
@@ -786,18 +812,22 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
@CheckForNull
GenericObjectType getLocalVariable(int index, int pos) {
- if (genericLocalVariables == null || !genericLocalVariables.get(index))
+ if (genericLocalVariables == null || !genericLocalVariables.get(index)) {
return null;
- for (LocalVariable local : localTypeTable.getLocalVariableTypeTable())
+ }
+ for (LocalVariable local : localTypeTable.getLocalVariableTypeTable()) {
if (local.getIndex() == index && local.getStartPC() <= pos
&& pos < +local.getStartPC() + local.getLength()) {
String signature = local.getSignature();
- if (signature.indexOf('<') < 0) continue;
+ if (signature.indexOf('<') < 0) {
+ continue;
+ }
Type t;
try {
t = GenericUtilities.getType(signature);
- if (t instanceof GenericObjectType)
+ if (t instanceof GenericObjectType) {
return (GenericObjectType) t;
+ }
} catch (RuntimeException e) {
AnalysisContext.logError("Bad signature " + signature
+ " for " + local.getName(), e);
@@ -805,6 +835,7 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
}
return null;
}
+ }
return null;
}
@@ -819,14 +850,15 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
Type value = frame.popValue();
int index = obj.getIndex();
if (value instanceof ReferenceType && !(value instanceof GenericObjectType)) {
- GenericObjectType gType = getLocalVariable(index,
+ GenericObjectType gType = getLocalVariable(index,
getLocation().getHandle().getPosition());
value = GenericUtilities.merge(gType, value);
}
frame.setValue(index, value);
frame.setExact(index, isExact);
- } else
+ } else {
super.handleStoreInstruction(obj);
+ }
} catch (DataflowAnalysisException e) {
throw new InvalidBytecodeException(
@@ -842,8 +874,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
@Override
public void handleLoadInstruction(LoadInstruction obj) {
int numProduced = obj.produceStack(cpg);
- if (numProduced == Constants.UNPREDICTABLE)
+ if (numProduced == Constants.UNPREDICTABLE) {
throw new InvalidBytecodeException("Unpredictable stack production");
+ }
if (numProduced != 1) {
super.handleLoadInstruction(obj);
@@ -859,8 +892,9 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
}
boolean isExact = frame.isExact(index);
frame.pushValue(value);
- if (isExact)
+ if (isExact) {
setTopOfStackIsExact();
+ }
}
@Override
@@ -868,10 +902,11 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
try {
Type t = getFrame().popValue();
- if (t instanceof NullType)
+ if (t instanceof NullType) {
pushValue(t);
- else
+ } else {
pushValue(obj.getType(getCPG()));
+ }
} catch (DataflowAnalysisException e) {
throw new InvalidBytecodeException("Stack underflow for " + obj + ": " + e.getMessage());
}
@@ -1172,11 +1207,13 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
boolean isExact = isTopOfStackExact();
Type value = frame.popValue();
frame.pushValue(value);
- if (isExact)
+ if (isExact) {
setTopOfStackIsExact();
+ }
frame.pushValue(value);
- if (isExact)
+ if (isExact) {
setTopOfStackIsExact();
+ }
} catch (DataflowAnalysisException e) {
throw new InvalidBytecodeException(e.toString());
}
@@ -1429,29 +1466,33 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
@Override
public void visitIFEQ(IFEQ obj) {
- if (previousWasEffectiveInstanceOf)
+ if (previousWasEffectiveInstanceOf) {
instanceOfFollowedByBranch = true;
+ }
super.visitIFEQ(obj);
}
@Override
public void visitIFGT(IFGT obj) {
- if (previousWasEffectiveInstanceOf)
+ if (previousWasEffectiveInstanceOf) {
instanceOfFollowedByBranch = true;
+ }
super.visitIFGT(obj);
}
@Override
public void visitIFLE(IFLE obj) {
- if (previousWasEffectiveInstanceOf)
+ if (previousWasEffectiveInstanceOf) {
instanceOfFollowedByBranch = true;
+ }
super.visitIFLE(obj);
}
@Override
public void visitIFNE(IFNE obj) {
- if (previousWasEffectiveInstanceOf)
+ if (previousWasEffectiveInstanceOf) {
instanceOfFollowedByBranch = true;
+ }
super.visitIFNE(obj);
}
@@ -1460,4 +1501,3 @@ public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type,
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/type/TypeMerger.java b/src/java/edu/umd/cs/findbugs/ba/type/TypeMerger.java
index fac5f23..66f7ec2 100644
--- a/src/java/edu/umd/cs/findbugs/ba/type/TypeMerger.java
+++ b/src/java/edu/umd/cs/findbugs/ba/type/TypeMerger.java
@@ -26,14 +26,14 @@ import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
/**
* Interface for object which merges types for TypeAnalysis. By allowing
* multiple implementations, we allow creation of specialized type systems.
- *
+ *
* @author David Hovemeyer
* @see TypeAnalysis
*/
public interface TypeMerger {
/**
* Merge type Types.
- *
+ *
* @param a
* a Type
* @param b
@@ -43,4 +43,3 @@ public interface TypeMerger {
public Type mergeTypes(Type a, Type b) throws DataflowAnalysisException;
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/AvailableLoad.java b/src/java/edu/umd/cs/findbugs/ba/vna/AvailableLoad.java
index 928728e..67d5c9e 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/AvailableLoad.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/AvailableLoad.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.ba.XField;
* <p>
* AvailableLoad objects may be used as keys in both hash and tree sets and
* maps.
- *
+ *
* @author David Hovemeyer
* @see ValueNumberAnalysis
*/
@@ -43,7 +43,7 @@ public class AvailableLoad implements Comparable<AvailableLoad> {
/**
* Constructor from static field.
- *
+ *
* @param staticField
* the StaticField
*/
@@ -54,22 +54,23 @@ public class AvailableLoad implements Comparable<AvailableLoad> {
/**
* Constructor from object reference and instance field.
- *
+ *
* @param reference
* the ValueNumber of the object reference
* @param field
* the InstanceField
*/
public AvailableLoad(ValueNumber reference, XField field) {
- if (reference == null)
+ if (reference == null) {
throw new IllegalArgumentException();
+ }
this.reference = reference;
this.field = field;
}
/**
* Get the ValueNumber of the object reference.
- *
+ *
* @return the ValueNumber, or null if this is a an available static field
* load
*/
@@ -78,35 +79,39 @@ public class AvailableLoad implements Comparable<AvailableLoad> {
}
public boolean matchesReference(ValueNumber v) {
- if (v == reference)
+ if (v == reference) {
return true;
- if (reference == null)
+ }
+ if (reference == null) {
return false;
+ }
return reference.equals(v);
}
/**
* Get the field for which a load is available.
- *
+ *
* @return the XField
*/
public XField getField() {
return field;
}
+ @Override
@SuppressWarnings("unchecked")
public int compareTo(AvailableLoad other) {
int cmp = field.compareTo(other.field);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
- else if (reference == other.reference)
+ } else if (reference == other.reference) {
return 0;
- else if (reference == null)
+ } else if (reference == null) {
return -1;
- else if (other.reference == null)
+ } else if (other.reference == null) {
return 1;
- else
+ } else {
return reference.compareTo(other.reference);
+ }
}
@Override
@@ -116,8 +121,9 @@ public class AvailableLoad implements Comparable<AvailableLoad> {
@Override
public boolean equals(Object o) {
- if (o == null || this.getClass() != o.getClass())
+ if (o == null || this.getClass() != o.getClass()) {
return false;
+ }
AvailableLoad other = (AvailableLoad) o;
return (reference == other.reference || (reference != null && other.reference != null && reference
.equals(other.reference))) && field.equals(other.field);
@@ -129,4 +135,3 @@ public class AvailableLoad implements Comparable<AvailableLoad> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/LoadedFieldSet.java b/src/java/edu/umd/cs/findbugs/ba/vna/LoadedFieldSet.java
index d8a44b5..52ecf18 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/LoadedFieldSet.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/LoadedFieldSet.java
@@ -34,7 +34,7 @@ import edu.umd.cs.findbugs.ba.XField;
* fields are loaded/stored by the overall method. The main purpose is for doing
* redundant load elimination and forward substitution more efficiently, but it
* might be useful in other situations.
- *
+ *
* @author David Hovemeyer
*/
public class LoadedFieldSet {
@@ -57,15 +57,15 @@ public class LoadedFieldSet {
// Fields
// private MethodGen methodGen;
- private Map<XField, LoadStoreCount> loadStoreCountMap;
+ private final Map<XField, LoadStoreCount> loadStoreCountMap;
- private Map<InstructionHandle, XField> handleToFieldMap;
+ private final Map<InstructionHandle, XField> handleToFieldMap;
- private BitSet loadHandleSet;
+ private final BitSet loadHandleSet;
/**
* Constructor. Constructs an empty object.
- *
+ *
* @param methodGen
* the method being analyzed for loads/stores
*/
@@ -79,7 +79,7 @@ public class LoadedFieldSet {
/**
* Get the number of times given field is loaded and stored within the
* method.
- *
+ *
* @param field
* the field
* @return the load/store count object
@@ -95,7 +95,7 @@ public class LoadedFieldSet {
/**
* Add a load of given field at given instruction.
- *
+ *
* @param handle
* the instruction
* @param field
@@ -109,7 +109,7 @@ public class LoadedFieldSet {
/**
* Add a store of given field at given instruction.
- *
+ *
* @param handle
* the instruction
* @param field
@@ -122,7 +122,7 @@ public class LoadedFieldSet {
/**
* Get the field loaded or stored at given instruction, if any.
- *
+ *
* @param handle
* the instruction
* @return the field loaded or stored at the instruction, or null if the
@@ -135,7 +135,7 @@ public class LoadedFieldSet {
/**
* Return whether or not the given field is loaded by any instruction in the
* method.
- *
+ *
* @param field
* the field
* @return true if the field is loaded somewhere in the method, false if it
@@ -147,7 +147,7 @@ public class LoadedFieldSet {
/**
* Return whether or not the given instruction is a load.
- *
+ *
* @param handle
* the instruction
* @return true if the instruction is a load, false if not
@@ -157,4 +157,3 @@ public class LoadedFieldSet {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/MergeTree.java b/src/java/edu/umd/cs/findbugs/ba/vna/MergeTree.java
index d6593d8..9fcadec 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/MergeTree.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/MergeTree.java
@@ -23,25 +23,26 @@ import java.util.BitSet;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
+import java.util.Map.Entry;
import edu.umd.cs.findbugs.SystemProperties;
/**
* Data structure to keep track of which input ValueNumbers were combined to
* produce which other output ValueNumbers.
- *
+ *
* @author David Hovemeyer
*/
public class MergeTree {
public static final boolean DEBUG = SystemProperties.getBoolean("vna.merge.debug");
- private ValueNumberFactory factory;
+ private final ValueNumberFactory factory;
- private Map<ValueNumber, BitSet> outputToInputMap;
+ private final Map<ValueNumber, BitSet> outputToInputMap;
/**
* Constructor.
- *
+ *
* @param factory
* the ValueNumberFactory
*/
@@ -52,7 +53,7 @@ public class MergeTree {
/**
* Map an input ValueNumber to an output ValueNumber.
- *
+ *
* @param input
* the input ValueNumber
* @param output
@@ -70,7 +71,7 @@ public class MergeTree {
/**
* Get the set of input ValueNumbers which directly contributed to the given
* output ValueNumber.
- *
+ *
* @param output
* the output ValueNumber
* @return the set of direct input ValueNumbers
@@ -90,7 +91,7 @@ public class MergeTree {
/**
* Get the transitive set of input ValueNumbers which contributed (directly
* or indirectly) to the given output ValueNumber.
- *
+ *
* @param output
* the output ValueNumber
* @return the transitive set of input ValueNumbers
@@ -116,8 +117,8 @@ public class MergeTree {
System.out.println("\tInput set is " + inputSet);
}
result.or(inputSet);
- for (int i = 0; i < factory.getNumValuesAllocated(); ++i) {
- if (inputSet.get(i) && !visited.get(i)) {
+ for (int i = inputSet.nextSetBit(0); i >= 0; i = inputSet.nextSetBit(i+1)) {
+ if (!visited.get(i)) {
if (DEBUG) {
System.out.println("\tExplore: " + i);
}
@@ -131,4 +132,34 @@ public class MergeTree {
return result;
}
+
+ public BitSet getTransitiveOutputSet(int input) {
+ BitSet visited = new BitSet();
+ BitSet result = new BitSet();
+
+ LinkedList<Integer> workList = new LinkedList<Integer>();
+ workList.addLast(input);
+ while (!workList.isEmpty()) {
+ Integer valueNumber = workList.removeFirst();
+ visited.set(valueNumber);
+ BitSet outputSet = getOutputSet(valueNumber);
+ result.or(outputSet);
+ for (int i = outputSet.nextSetBit(0); i >= 0; i = outputSet.nextSetBit(i+1)) {
+ if (!visited.get(i)) {
+ workList.addLast(i);
+ }
+ }
+ }
+ return result;
+ }
+
+ private BitSet getOutputSet(int valueNumber) {
+ BitSet result = new BitSet();
+ for(Entry<ValueNumber, BitSet> entry : outputToInputMap.entrySet()) {
+ if(entry.getValue().get(valueNumber)) {
+ result.set(entry.getKey().getNumber());
+ }
+ }
+ return result;
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumber.java b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumber.java
index d8abc52..ac77eea 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumber.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumber.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.util.Util;
* ValueNumberFactory} are unique, so reference equality may be used to
* determine whether or not two value numbers are the same. In general,
* ValueNumbers from different factories cannot be compared.
- *
+ *
* @author David Hovemeyer
* @see ValueNumberAnalysis
*/
@@ -42,10 +42,14 @@ public class ValueNumber implements Comparable<ValueNumber> {
static int valueNumbersCreated = 0;
static int valueNumbersReused = 0;
-
+
public static int mergeFlags(int flags1, int flags2) {
- if (flags1 == -1) return flags2;
- if (flags2 == -1) return flags1;
+ if (flags1 == -1) {
+ return flags2;
+ }
+ if (flags2 == -1) {
+ return flags1;
+ }
return flags1 & flags2;
}
@@ -68,6 +72,7 @@ public class ValueNumber implements Comparable<ValueNumber> {
static {
Util.runLogAtShutdown(new Runnable() {
+ @Override
public void run() {
System.out.println("Value number statistics: " + valueNumbersCreated + " created, " + valueNumbersReused
+ " reused");
@@ -82,7 +87,7 @@ public class ValueNumber implements Comparable<ValueNumber> {
final int number;
/**
- * Flags representing meta information about the value. When value numbers are merged,
+ * Flags representing meta information about the value. When value numbers are merged,
* their flags should be the flags common to both.
*/
final int flags;
@@ -102,7 +107,7 @@ public class ValueNumber implements Comparable<ValueNumber> {
/**
* Constructor.
- *
+ *
* @param number
* the value number
*/
@@ -130,8 +135,9 @@ public class ValueNumber implements Comparable<ValueNumber> {
@Override
public String toString() {
- if (flags != 0)
+ if (flags != 0) {
return number + "(" + flags + "),";
+ }
return number + ",";
}
@@ -148,13 +154,14 @@ public class ValueNumber implements Comparable<ValueNumber> {
return false;
}
+ @Override
public int compareTo(ValueNumber other) {
int result = number - other.number;
- if (result != 0)
+ if (result != 0) {
return result;
+ }
return flags - other.flags;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberAnalysis.java b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberAnalysis.java
index 465b05f..a0ecd9d 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberAnalysis.java
@@ -19,14 +19,16 @@
package edu.umd.cs.findbugs.ba.vna;
-import java.util.BitSet;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import javax.annotation.CheckForNull;
+import org.apache.bcel.generic.INVOKEDYNAMIC;
+import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.InvokeInstruction;
import org.apache.bcel.generic.MethodGen;
import edu.umd.cs.findbugs.SystemProperties;
@@ -88,21 +90,24 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
int numLocals = methodGen.getMaxLocals();
this.entryLocalValueList = new ValueNumber[numLocals];
- for (int i = 0; i < numLocals; ++i)
+ for (int i = 0; i < numLocals; ++i) {
this.entryLocalValueList[i] = factory.createFreshValue();
+ }
this.exceptionHandlerValueNumberMap = new IdentityHashMap<BasicBlock, ValueNumber>();
// For non-static methods, keep track of which value represents the
// "this" reference
- if (!methodGen.isStatic())
+ if (!methodGen.isStatic()) {
this.thisValue = entryLocalValueList[0];
+ }
this.factAtLocationMap = new HashMap<Location, ValueNumberFrame>();
this.factAfterLocationMap = new HashMap<Location, ValueNumberFrame>();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("VNA Analysis " + methodGen.getClassName() + "." + methodGen.getName() + " : "
+ methodGen.getSignature());
+ }
}
@@ -155,25 +160,28 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
* @return the ValueNumber assigned to that parameter
*/
public ValueNumber getEntryValueForParameter(int param) {
-
+
SignatureParser sigParser = new SignatureParser(methodGen.getSignature());
int p = 0;
int slotOffset = methodGen.isStatic() ? 0 : 1;
for ( String paramSig : sigParser.parameterSignatures()) {
- if (p == param)
+ if (p == param) {
return getEntryValue(slotOffset);
+ }
param++;
slotOffset += SignatureParser.getNumSlotsForType(paramSig);
}
-
+
throw new IllegalStateException();
}
+ @Override
public ValueNumberFrame createFact() {
return new ValueNumberFrame(methodGen.getMaxLocals());
}
+ @Override
public void initEntryFact(ValueNumberFrame result) {
// Change the frame from TOP to something valid.
result.setValid();
@@ -181,8 +189,30 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
// At entry to the method, each local has (as far as we know) a unique
// value.
int numSlots = result.getNumSlots();
- for (int i = 0; i < numSlots; ++i)
+ for (int i = 0; i < numSlots; ++i) {
result.setValue(i, entryLocalValueList[i]);
+ }
+ }
+
+ @Override
+ public void transfer(BasicBlock basicBlock, InstructionHandle end, ValueNumberFrame start, ValueNumberFrame result)
+ throws DataflowAnalysisException {
+ if(basicBlock.isExceptionThrower() && isFactValid(start)) {
+ /* If exceptionThrower is invoke instruction then it's possible that
+ * it was partially executed before an exception occurred
+ * So we have to kill available loads when control is transferred to the catch block
+ */
+ InstructionHandle handle = basicBlock.getExceptionThrower();
+ Instruction inst = handle.getInstruction();
+ if(inst instanceof InvokeInstruction || inst instanceof INVOKEDYNAMIC) {
+ copy(start, result);
+ visitor.setFrameAndLocation(result, new Location(handle, basicBlock));
+ visitor.setHandle(handle);
+ visitor.visitInvokeOnException(inst);
+ return;
+ }
+ }
+ super.transfer(basicBlock, end, start, result);
}
@Override
@@ -194,7 +224,7 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
ValueNumberFrame atLocation = getFactAtLocation(location);
copy(fact, atLocation);
- visitor.setFrameAndLocation(fact, new Location(handle, basicBlock));
+ visitor.setFrameAndLocation(fact, location);
visitor.setHandle(handle);
visitor.analyzeInstruction(handle.getInstruction());
@@ -202,6 +232,7 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
copy(fact, afterLocation);
}
+ @Override
public void meetInto(ValueNumberFrame fact, Edge edge, ValueNumberFrame result) throws DataflowAnalysisException {
if (edge.getTarget().isExceptionHandler() && fact.isValid()) {
// Special case: when merging predecessor facts for entry to
@@ -237,8 +268,7 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
resultFrame.setValue(slot, value);
}
- private ValueNumber mergeValues(ValueNumberFrame frame, int slot, ValueNumber mine, ValueNumber other)
- {
+ private ValueNumber mergeValues(ValueNumberFrame frame, int slot, ValueNumber mine, ValueNumber other) {
// Merging slot values:
// - Merging identical values results in no change
@@ -254,11 +284,13 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
// I believe (but haven't proved) that this technique is a dumb way
// of computing SSA.
- if (mine != frame.getValue(slot))
+ if (mine != frame.getValue(slot)) {
throw new IllegalStateException();
+ }
- if (mine.equals(other))
+ if (mine.equals(other)) {
return mine;
+ }
ValueNumber mergedValue = frame.getMergedValue(slot);
if (mergedValue == null) {
@@ -289,16 +321,18 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
@Override
public ValueNumberFrame getFactAfterLocation(Location location) {
- if (TRACE)
+ if (TRACE) {
System.out.println("getting fact after " + location);
+ }
ValueNumberFrame fact = factAfterLocationMap.get(location);
if (fact == null) {
- if (TRACE)
+ if (TRACE) {
System.out
- .println("Initialized fact after " + location + " @ "
- + Integer.toHexString(System.identityHashCode(location)) + " in "
- + Integer.toHexString(System.identityHashCode(this)) + " : "
- + factAfterLocationMap.containsKey(location));
+ .println("Initialized fact after " + location + " @ "
+ + Integer.toHexString(System.identityHashCode(location)) + " in "
+ + Integer.toHexString(System.identityHashCode(this)) + " : "
+ + factAfterLocationMap.containsKey(location));
+ }
fact = createFact();
makeFactTop(fact);
@@ -317,6 +351,7 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
}
// These fields are used by the compactValueNumbers() method.
+ /*
private static class ValueCompacter {
public final BitSet valuesUsed;
@@ -333,8 +368,9 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
// specify value numbers which are not actually used (and thus can
// be purged.)
discovered = new int[origNumValuesAllocated];
- for (int i = 0; i < discovered.length; ++i)
+ for (int i = 0; i < discovered.length; ++i) {
discovered[i] = -1;
+ }
}
public boolean isUsed(int number) {
@@ -349,6 +385,7 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
return numValuesUsed++;
}
}
+ */
/**
* Compact the value numbers assigned. This should be done only after the
@@ -367,8 +404,10 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
*/
@Deprecated
public void compactValueNumbers(Dataflow<ValueNumberFrame, ValueNumberAnalysis> dataflow) {
- if (true)
+ if (true) {
throw new UnsupportedOperationException();
+ }
+ /*
ValueCompacter compacter = new ValueCompacter(factory.getNumValuesAllocated());
// We can get all extant Frames by looking at the values in
@@ -389,18 +428,20 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
int after = factory.getNumValuesAllocated();
- if (DEBUG && after < before && before > 0)
+ if (DEBUG && after < before && before > 0) {
System.out.println("Value compaction: " + after + "/" + before + " (" + ((after * 100) / before) + "%)");
-
+ }
+ */
}
/**
* Mark value numbers in a value number frame for compaction.
- */
+ *
private static void markFrameValues(ValueNumberFrame frame, ValueCompacter compacter) {
// We don't need to do anything for top and bottom frames.
- if (!frame.isValid())
+ if (!frame.isValid()) {
return;
+ }
for (int j = 0; j < frame.getNumSlots(); ++j) {
ValueNumber value = frame.getValue(j);
@@ -412,6 +453,7 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
}
}
}
+ */
// /**
// * Test driver.
@@ -451,5 +493,3 @@ public class ValueNumberAnalysis extends FrameDataflowAnalysis<ValueNumber, Valu
return factory.getClassName(v);
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberAnalysisFeatures.java b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberAnalysisFeatures.java
index 52afc7f..a434d63 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberAnalysisFeatures.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberAnalysisFeatures.java
@@ -47,4 +47,3 @@ public interface ValueNumberAnalysisFeatures {
public static final boolean RLE_DEBUG = SystemProperties.getBoolean("vna.rle.debug");
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberCache.java b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberCache.java
index 3168507..232c2a3 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberCache.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberCache.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
* A cache mapping instructions and input values to the output values they
* produce. We must always produce the same output given identical input, or
* else value number analysis will not terminate.
- *
+ *
* @author David Hovemeyer
* @see ValueNumberAnalysis
*/
@@ -58,18 +58,23 @@ public class ValueNumberCache {
@Override
public boolean equals(Object o) {
- if (!(o instanceof Entry))
+ if (!(o instanceof Entry)) {
return false;
+ }
Entry other = (Entry) o;
- if (handle.getPosition() != other.handle.getPosition())
+ if (handle.getPosition() != other.handle.getPosition()) {
return false;
+ }
ValueNumber[] myList = inputValueList;
ValueNumber[] otherList = other.inputValueList;
- if (myList.length != otherList.length)
+ if (myList.length != otherList.length) {
return false;
- for (int i = 0; i < myList.length; ++i)
- if (!myList[i].equals(otherList[i]))
+ }
+ for (int i = 0; i < myList.length; ++i) {
+ if (!myList[i].equals(otherList[i])) {
return false;
+ }
+ }
return true;
}
@@ -102,29 +107,31 @@ public class ValueNumberCache {
/**
* Map of entries to output values.
*/
- private HashMap<Entry, ValueNumber[]> entryToOutputMap = new HashMap<Entry, ValueNumber[]>();
+ private final HashMap<Entry, ValueNumber[]> entryToOutputMap = new HashMap<Entry, ValueNumber[]>();
/**
* Look up cached output values for given entry.
- *
+ *
* @param entry
* the entry
* @return the list of output values, or null if there is no matching entry
* in the cache
*/
public ValueNumber[] lookupOutputValues(Entry entry) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("VN cache lookup: " + entry);
+ }
ValueNumber[] result = entryToOutputMap.get(entry);
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" result ==> " + Arrays.toString(result));
+ }
return result;
}
/**
* Add output values for given entry. Assumes that lookupOutputValues() has
* determined that the entry is not in the cache.
- *
+ *
* @param entry
* the entry
* @param outputValueList
@@ -133,10 +140,10 @@ public class ValueNumberCache {
*/
public void addOutputValues(Entry entry, ValueNumber[] outputValueList) {
ValueNumber[] old = entryToOutputMap.put(entry, outputValueList);
- if (old != null)
+ if (old != null) {
throw new IllegalStateException("overwriting output values for entry!");
+ }
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberDataflow.java b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberDataflow.java
index b8adb10..f9b0c11 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberDataflow.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberDataflow.java
@@ -39,7 +39,7 @@ public class ValueNumberDataflow extends AbstractDataflow<ValueNumberFrame, Valu
/**
* Build map of value numbers to param indices. The first parameter has
* index 0, the second has index 1, etc.
- *
+ *
* @param method
* the method analyzed by the ValueNumberAnalysis
* @return the value number to parameter index map
@@ -51,7 +51,7 @@ public class ValueNumberDataflow extends AbstractDataflow<ValueNumberFrame, Valu
/**
* Build map of value numbers to param indices. The first parameter has
* index 0, the second has index 1, etc.
- *
+ *
* @param methodSignature
* signature of the method analyzed by the ValueNumberAnalysis
* @param isStatic
@@ -80,4 +80,3 @@ public class ValueNumberDataflow extends AbstractDataflow<ValueNumberFrame, Valu
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFactory.java b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFactory.java
index c098cab..c7ad66c 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFactory.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFactory.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
/**
* Factory for ValueNumbers. A single Factory must be used to create all of the
* ValueNumbers for a method.
- *
+ *
* @author David Hovemeyer
* @see ValueNumber
*/
@@ -41,7 +41,7 @@ public class ValueNumberFactory {
*/
private ArrayList<ValueNumber> allocatedValueList = new ArrayList<ValueNumber>();
- private HashMap<String, ValueNumber> classObjectValueMap = new HashMap<String, ValueNumber>();
+ private final HashMap<String, ValueNumber> classObjectValueMap = new HashMap<String, ValueNumber>();
/**
* Create a fresh (unique) value number.
@@ -62,8 +62,9 @@ public class ValueNumberFactory {
* Return a previously allocated value.
*/
public ValueNumber forNumber(int number) {
- if (number >= getNumValuesAllocated())
+ if (number >= getNumValuesAllocated()) {
throw new IllegalArgumentException("Value " + number + " has not been allocated");
+ }
return allocatedValueList.get(number);
}
@@ -76,7 +77,7 @@ public class ValueNumberFactory {
/**
* Compact the value numbers produced by this factory.
- *
+ *
* @param map
* array mapping old numbers to new numbers
* @param numValuesAllocated
@@ -84,8 +85,9 @@ public class ValueNumberFactory {
*/
@Deprecated
public void compact(int[] map, int numValuesAllocated) {
- if (true)
+ if (true) {
throw new UnsupportedOperationException();
+ }
ArrayList<ValueNumber> oldList = this.allocatedValueList;
ArrayList<ValueNumber> newList = new ArrayList<ValueNumber>(Collections.<ValueNumber> nCopies(numValuesAllocated, null));
@@ -104,7 +106,7 @@ public class ValueNumberFactory {
/**
* Get the ValueNumber for given class's Class object.
- *
+ *
* @param className
* the class
*/
@@ -123,15 +125,16 @@ public class ValueNumberFactory {
public @CheckForNull
@DottedClassName
String getClassName(ValueNumber v) {
- if (!v.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))
+ if (!v.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
throw new IllegalArgumentException("Not a value number for a constant class");
+ }
for (Map.Entry<String, ValueNumber> e : classObjectValueMap.entrySet()) {
- if (e.getValue().equals(v))
+ if (e.getValue().equals(v)) {
return e.getKey();
+ }
}
return null;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFrame.java b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFrame.java
index 68fde22..d3a399e 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFrame.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFrame.java
@@ -27,6 +27,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
import java.util.Set;
import javax.annotation.CheckForNull;
@@ -41,7 +43,7 @@ import edu.umd.cs.findbugs.util.Util;
/**
* A dataflow value representing a Java stack frame with value number
* information.
- *
+ *
* @author David Hovemeyer
* @see ValueNumber
* @see ValueNumberAnalysis
@@ -58,6 +60,36 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
public boolean phiNodeForLoads;
+ private static final boolean USE_WRITTEN_OUTSIDE_OF_CONSTRUCTOR = true;
+
+ static int constructedUnmodifiableMap;
+
+ static int reusedMap;
+
+ static int createdEmptyMap;
+
+ static int madeImmutableMutable;
+
+ static int reusedMutableMap;
+
+ static {
+ Util.runLogAtShutdown(new Runnable() {
+
+ @Override
+ public void run() {
+ System.err.println("Getting updatable previously known as:");
+ System.err.println(" " + createdEmptyMap + " created empty map");
+ System.err.println(" " + madeImmutableMutable + " made immutable map mutable");
+ System.err.println(" " + reusedMutableMap + " reused mutable map");
+ System.err.println("Copying map:");
+ System.err.println(" " + constructedUnmodifiableMap + " made mutable map unmodifiable");
+ System.err.println(" " + reusedMap + " reused immutable map");
+ System.err.println();
+
+ }
+ });
+ }
+
public ValueNumberFrame(int numLocals) {
super(numLocals);
if (REDUNDANT_LOAD_ELIMINATION) {
@@ -72,8 +104,9 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
for (Map.Entry<AvailableLoad, ValueNumber[]> e : getAvailableLoadMap().entrySet()) {
buf.append(e.getKey());
buf.append("=");
- for (ValueNumber v : e.getValue())
+ for (ValueNumber v : e.getValue()) {
buf.append(v).append(",");
+ }
buf.append("; ");
}
@@ -83,21 +116,25 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
public @CheckForNull
AvailableLoad getLoad(ValueNumber v) {
- if (!REDUNDANT_LOAD_ELIMINATION)
+ if (!REDUNDANT_LOAD_ELIMINATION) {
return null;
+ }
for (Map.Entry<AvailableLoad, ValueNumber[]> e : getAvailableLoadMap().entrySet()) {
ValueNumber[] values = e.getValue();
- if (values != null)
- for (ValueNumber v2 : values)
- if (v.equals(v2))
+ if (values != null) {
+ for (ValueNumber v2 : values) {
+ if (v.equals(v2)) {
return e.getKey();
+ }
+ }
+ }
}
return null;
}
/**
* Look for an available load.
- *
+ *
* @param availableLoad
* the AvailableLoad (reference and field)
* @return the value(s) available, or null if no matching entry is found
@@ -108,15 +145,14 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
/**
* Add an available load.
- *
+ *
* @param availableLoad
* the AvailableLoad (reference and field)
* @param value
* the value(s) loaded
*/
public void addAvailableLoad(AvailableLoad availableLoad, @Nonnull ValueNumber[] value) {
- if (value == null)
- throw new IllegalStateException();
+ Objects.requireNonNull(value);
getUpdateableAvailableLoadMap().put(availableLoad, value);
for (ValueNumber v : value) {
@@ -129,47 +165,54 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
}
private static <K, V> void removeAllKeys(Map<K, V> map, Iterable<K> removeMe) {
- for (K k : removeMe)
+ for (K k : removeMe) {
map.remove(k);
+ }
}
/**
* Kill all loads of given field.
- *
+ *
* @param field
* the field
*/
public void killLoadsOfField(XField field) {
- if (!REDUNDANT_LOAD_ELIMINATION)
+ if (!REDUNDANT_LOAD_ELIMINATION) {
return;
+ }
HashSet<AvailableLoad> killMe = new HashSet<AvailableLoad>();
for (AvailableLoad availableLoad : getAvailableLoadMap().keySet()) {
if (availableLoad.getField().equals(field)) {
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("KILLING Load of " + availableLoad + " in " + this);
+ }
killMe.add(availableLoad);
}
}
killAvailableLoads(killMe);
}
- private static boolean USE_WRITTEN_OUTSIDE_OF_CONSTRUCTOR = true;
-
/**
* Kill all loads. This conservatively handles method calls where we don't
* really know what fields might be assigned.
*/
public void killAllLoads() {
- if (!REDUNDANT_LOAD_ELIMINATION)
+ killAllLoads(false);
+ }
+
+ public void killAllLoads(boolean primitiveOnly) {
+ if (!REDUNDANT_LOAD_ELIMINATION) {
return;
+ }
FieldSummary fieldSummary = AnalysisContext.currentAnalysisContext().getFieldSummary();
HashSet<AvailableLoad> killMe = new HashSet<AvailableLoad>();
for (AvailableLoad availableLoad : getAvailableLoadMap().keySet()) {
XField field = availableLoad.getField();
- if (field.isVolatile() || !field.isFinal()
- && (!USE_WRITTEN_OUTSIDE_OF_CONSTRUCTOR || fieldSummary.isWrittenOutsideOfConstructor(field))) {
- if (RLE_DEBUG)
+ if ((!primitiveOnly || !field.isReferenceType()) && (field.isVolatile() || !field.isFinal()
+ && (!USE_WRITTEN_OUTSIDE_OF_CONSTRUCTOR || fieldSummary.isWrittenOutsideOfConstructor(field)))) {
+ if (RLE_DEBUG) {
System.out.println("KILLING load of " + availableLoad + " in " + this);
+ }
killMe.add(availableLoad);
}
}
@@ -178,14 +221,16 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
}
public void killAllLoadsExceptFor(@CheckForNull ValueNumber v) {
- if (!REDUNDANT_LOAD_ELIMINATION)
+ if (!REDUNDANT_LOAD_ELIMINATION) {
return;
+ }
AvailableLoad myLoad = getLoad(v);
HashSet<AvailableLoad> killMe = new HashSet<AvailableLoad>();
for (AvailableLoad availableLoad : getAvailableLoadMap().keySet()) {
if (!availableLoad.getField().isFinal() && !availableLoad.equals(myLoad)) {
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("KILLING load of " + availableLoad + " in " + this);
+ }
killMe.add(availableLoad);
}
}
@@ -197,42 +242,46 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
* really know what fields might be assigned.
*/
public void killAllLoadsOf(@CheckForNull ValueNumber v) {
- if (!REDUNDANT_LOAD_ELIMINATION)
+ if (!REDUNDANT_LOAD_ELIMINATION) {
return;
+ }
FieldSummary fieldSummary = AnalysisContext.currentAnalysisContext().getFieldSummary();
HashSet<AvailableLoad> killMe = new HashSet<AvailableLoad>();
for (AvailableLoad availableLoad : getAvailableLoadMap().keySet()) {
- if (availableLoad.getReference() != v)
+ if (availableLoad.getReference() != v) {
continue;
+ }
XField field = availableLoad.getField();
if (!field.isFinal() && (!USE_WRITTEN_OUTSIDE_OF_CONSTRUCTOR || fieldSummary.isWrittenOutsideOfConstructor(field))) {
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("Killing load of " + availableLoad + " in " + this);
+ }
killMe.add(availableLoad);
}
}
killAvailableLoads(killMe);
-
}
public void killLoadsOf(Set<XField> fieldsToKill) {
- if (!REDUNDANT_LOAD_ELIMINATION)
+ if (!REDUNDANT_LOAD_ELIMINATION) {
return;
+ }
HashSet<AvailableLoad> killMe = new HashSet<AvailableLoad>();
for (AvailableLoad availableLoad : getAvailableLoadMap().keySet()) {
- if (fieldsToKill.contains(availableLoad.getField()))
+ if (fieldsToKill.contains(availableLoad.getField())) {
killMe.add(availableLoad);
+ }
}
killAvailableLoads(killMe);
-
}
public void killLoadsWithSimilarName(String className, String methodName) {
- if (!REDUNDANT_LOAD_ELIMINATION)
+ if (!REDUNDANT_LOAD_ELIMINATION) {
return;
+ }
String packageName = extractPackageName(className);
HashSet<AvailableLoad> killMe = new HashSet<AvailableLoad>();
@@ -241,25 +290,20 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
XField field = availableLoad.getField();
String fieldPackageName = extractPackageName(field.getClassName());
if (packageName.equals(fieldPackageName) && field.isStatic()
- && methodName.toLowerCase().indexOf(field.getName().toLowerCase()) >= 0)
+ && methodName.toLowerCase().indexOf(field.getName().toLowerCase()) >= 0) {
killMe.add(availableLoad);
+ }
}
killAvailableLoads(killMe);
}
- /**
- * @param killMe
- */
private void killAvailableLoads(HashSet<AvailableLoad> killMe) {
- if (killMe.size() > 0)
+ if (killMe.size() > 0) {
removeAllKeys(getUpdateableAvailableLoadMap(), killMe);
+ }
}
- /**
- * @param className
- * @return
- */
private String extractPackageName(String className) {
return className.substring(className.lastIndexOf('.') + 1);
}
@@ -282,9 +326,12 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
AvailableLoad load = e.getKey();
ValueNumber[] myVN = e.getValue();
ValueNumber[] otherVN = other.getAvailableLoadMap().get(load);
+ /*
if (false && this.phiNodeForLoads && myVN != null && myVN.length == 1
- && myVN[0].hasFlag(ValueNumber.PHI_NODE))
+ && myVN[0].hasFlag(ValueNumber.PHI_NODE)) {
continue;
+ }
+ */
if (!Arrays.equals(myVN, otherVN)) {
ValueNumber phi = getMergedLoads().get(load);
@@ -293,38 +340,44 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
for (ValueNumber vn : myVN) {
flags = ValueNumber.mergeFlags(flags, vn.getFlags());
}
- if (otherVN != null)
+ if (otherVN != null) {
for (ValueNumber vn : otherVN) {
flags = ValueNumber.mergeFlags(flags, vn.getFlags());
}
- if (flags == -1)
+ }
+ if (flags == -1) {
flags = ValueNumber.PHI_NODE;
- else
+ } else {
flags |= ValueNumber.PHI_NODE;
-
+ }
+
phi = factory.createFreshValue(flags);
getUpdateableMergedLoads().put(load, phi);
for (ValueNumber vn : myVN) {
mergeTree.mapInputToOutput(vn, phi);
}
- if (otherVN != null)
+ if (otherVN != null) {
for (ValueNumber vn : otherVN) {
mergeTree.mapInputToOutput(vn, phi);
}
+ }
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("Creating phi node " + phi + " for " + load + " from " + Arrays.toString(myVN)
+ " x " + Arrays.toString(otherVN) + " in " + System.identityHashCode(this));
+ }
changed = true;
e.setValue(new ValueNumber[] { phi });
} else {
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("Reusing phi node : " + phi + " for " + load + " from "
+ Arrays.toString(myVN) + " x " + Arrays.toString(otherVN) + " in "
+ System.identityHashCode(this));
- if (myVN.length != 1 || !myVN[0].equals(phi))
+ }
+ if (myVN.length != 1 || !myVN[0].equals(phi)) {
e.setValue(new ValueNumber[] { phi });
+ }
}
}
@@ -333,13 +386,15 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
}
Map<ValueNumber, AvailableLoad> previouslyKnownAsOther = other.getPreviouslyKnownAs();
if (getPreviouslyKnownAs() != previouslyKnownAsOther && previouslyKnownAsOther.size() != 0) {
- if (getPreviouslyKnownAs().size() == 0)
+ if (getPreviouslyKnownAs().size() == 0) {
assignPreviouslyKnownAs(other);
- else
+ } else {
getUpdateablePreviouslyKnownAs().putAll(previouslyKnownAsOther);
+ }
}
- if (changed)
+ if (changed) {
this.phiNodeForLoads = true;
+ }
if (changed && RLE_DEBUG) {
System.out.println(s);
System.out.println(" Result is " + this.availableLoadMapAsString());
@@ -358,16 +413,18 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
@Override
public void copyFrom(Frame<ValueNumber> other) {
- if (!(other instanceof ValueNumberFrame))
+ if (!(other instanceof ValueNumberFrame)) {
throw new IllegalArgumentException();
+ }
// If merged value list hasn't been created yet, create it.
if (mergedValueList == null && other.isValid()) {
// This is where this frame gets its size.
// It will have the same size as long as it remains valid.
mergedValueList = new ArrayList<ValueNumber>(other.getNumSlots());
int numSlots = other.getNumSlots();
- for (int i = 0; i < numSlots; ++i)
+ for (int i = 0; i < numSlots; ++i) {
mergedValueList.add(null);
+ }
}
if (REDUNDANT_LOAD_ELIMINATION) {
@@ -404,10 +461,6 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
}
}
- static int constructedUnmodifiableMap;
-
- static int reusedMap;
-
@Override
public String toString() {
String frameValues = super.toString();
@@ -420,17 +473,19 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
while (i.hasNext()) {
AvailableLoad key = i.next();
ValueNumber[] value = getAvailableLoadMap().get(key);
- if (first)
+ if (first) {
first = false;
- else
+ } else {
buf.append(',');
+ }
buf.append(key + "=" + valueToString(value));
}
buf.append(" #");
buf.append(System.identityHashCode(this));
- if (phiNodeForLoads)
+ if (phiNodeForLoads) {
buf.append(" phi");
+ }
return buf.toString();
} else {
return frameValues;
@@ -442,10 +497,11 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
buf.append('[');
boolean first = true;
for (ValueNumber aValueNumberList : valueNumberList) {
- if (first)
+ if (first) {
first = false;
- else
+ } else {
buf.append(',');
+ }
buf.append(aValueNumberList.getNumber());
}
buf.append(']');
@@ -453,60 +509,71 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
}
public boolean fuzzyMatch(ValueNumber v1, ValueNumber v2) {
- if (REDUNDANT_LOAD_ELIMINATION)
+ if (REDUNDANT_LOAD_ELIMINATION) {
return v1.equals(v2) || fromMatchingLoads(v1, v2) || haveMatchingFlags(v1, v2);
- else
+ } else {
return v1.equals(v2);
+ }
}
public boolean veryFuzzyMatch(ValueNumber v1, ValueNumber v2) {
- if (REDUNDANT_LOAD_ELIMINATION)
+ if (REDUNDANT_LOAD_ELIMINATION) {
return v1.equals(v2) || fromMatchingFields(v1, v2) || haveMatchingFlags(v1, v2);
- else
+ } else {
return v1.equals(v2);
+ }
}
public boolean fromMatchingLoads(ValueNumber v1, ValueNumber v2) {
AvailableLoad load1 = getLoad(v1);
- if (load1 == null)
+ if (load1 == null) {
load1 = getPreviouslyKnownAs().get(v1);
- if (load1 == null)
+ }
+ if (load1 == null) {
return false;
+ }
AvailableLoad load2 = getLoad(v2);
- if (load2 == null)
+ if (load2 == null) {
load2 = getPreviouslyKnownAs().get(v2);
- if (load2 == null)
+ }
+ if (load2 == null) {
return false;
+ }
return load1.equals(load2);
}
public boolean fromMatchingFields(ValueNumber v1, ValueNumber v2) {
AvailableLoad load1 = getLoad(v1);
- if (load1 == null)
+ if (load1 == null) {
load1 = getPreviouslyKnownAs().get(v1);
- if (load1 == null)
+ }
+ if (load1 == null) {
return false;
+ }
AvailableLoad load2 = getLoad(v2);
- if (load2 == null)
+ if (load2 == null) {
load2 = getPreviouslyKnownAs().get(v2);
- if (load2 == null)
+ }
+ if (load2 == null) {
return false;
- if (load1.equals(load2))
+ }
+ if (load1.equals(load2)) {
return true;
+ }
if (load1.getField().equals(load2.getField())) {
ValueNumber source1 = load1.getReference();
ValueNumber source2 = load2.getReference();
- if (!this.contains(source1))
+ if (!this.contains(source1)) {
return true;
- if (!this.contains(source2))
+ }
+ if (!this.contains(source2)) {
return true;
+ }
}
return false;
}
/**
- * @param v1
- * @param v2
* @return true if v1 and v2 have a flag in common
*/
public boolean haveMatchingFlags(ValueNumber v1, ValueNumber v2) {
@@ -517,27 +584,23 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
public Collection<ValueNumber> valueNumbersForLoads() {
HashSet<ValueNumber> result = new HashSet<ValueNumber>();
- if (REDUNDANT_LOAD_ELIMINATION)
+ if (REDUNDANT_LOAD_ELIMINATION) {
for (Map.Entry<AvailableLoad, ValueNumber[]> e : getAvailableLoadMap().entrySet()) {
- if (e.getValue() != null)
- for (ValueNumber v2 : e.getValue())
+ if (e.getValue() != null) {
+ for (ValueNumber v2 : e.getValue()) {
result.add(v2);
+ }
+ }
}
+ }
return result;
}
- /**
- * @param availableLoadMap
- * The availableLoadMap to set.
- */
private void setAvailableLoadMap(Map<AvailableLoad, ValueNumber[]> availableLoadMap) {
this.availableLoadMap = availableLoadMap;
}
- /**
- * @return Returns the availableLoadMap.
- */
private Map<AvailableLoad, ValueNumber[]> getAvailableLoadMap() {
return availableLoadMap;
}
@@ -551,65 +614,30 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
return availableLoadMap;
}
- /**
- * @param mergedLoads
- * The mergedLoads to set.
- */
private void setMergedLoads(Map<AvailableLoad, ValueNumber> mergedLoads) {
this.mergedLoads = mergedLoads;
}
- /**
- * @return Returns the mergedLoads.
- */
private Map<AvailableLoad, ValueNumber> getMergedLoads() {
return mergedLoads;
}
private Map<AvailableLoad, ValueNumber> getUpdateableMergedLoads() {
- if (!(mergedLoads instanceof HashMap))
+ if (!(mergedLoads instanceof HashMap)) {
mergedLoads = new HashMap<AvailableLoad, ValueNumber>();
+ }
return mergedLoads;
}
- /**
- * @param previouslyKnownAs
- * The previouslyKnownAs to set.
- */
private void setPreviouslyKnownAs(Map<ValueNumber, AvailableLoad> previouslyKnownAs) {
this.previouslyKnownAs = previouslyKnownAs;
}
- /**
- * @return Returns the previouslyKnownAs.
- */
private Map<ValueNumber, AvailableLoad> getPreviouslyKnownAs() {
return previouslyKnownAs;
}
- static int createdEmptyMap;
-
- static int madeImmutableMutable;
-
- static int reusedMutableMap;
- static {
- Util.runLogAtShutdown(new Runnable() {
-
- public void run() {
- System.err.println("Getting updatable previously known as:");
- System.err.println(" " + createdEmptyMap + " created empty map");
- System.err.println(" " + madeImmutableMutable + " made immutable map mutable");
- System.err.println(" " + reusedMutableMap + " reused mutable map");
- System.err.println("Copying map:");
- System.err.println(" " + constructedUnmodifiableMap + " made mutable map unmodifiable");
- System.err.println(" " + reusedMap + " reused immutable map");
- System.err.println();
-
- }
- });
- }
-
private Map<ValueNumber, AvailableLoad> getUpdateablePreviouslyKnownAs() {
if (previouslyKnownAs.size() == 0) {
previouslyKnownAs = new HashMap<ValueNumber, AvailableLoad>(4);
@@ -619,12 +647,35 @@ public class ValueNumberFrame extends Frame<ValueNumber> implements ValueNumberA
tmp.putAll(previouslyKnownAs);
previouslyKnownAs = tmp;
madeImmutableMutable++;
- } else
+ } else {
reusedMutableMap++;
+ }
return previouslyKnownAs;
}
-}
+ @Override
+ public boolean sameAs(Frame<ValueNumber> other) {
+ if(!super.sameAs(other)) {
+ return false;
+ }
+ if (isTop() && other.isTop() || isBottom() && other.isBottom()) {
+ return true;
+ }
+ ValueNumberFrame o = (ValueNumberFrame)other;
+ if(availableLoadMap.size() != o.availableLoadMap.size()) {
+ return false;
+ }
+ for(Entry<AvailableLoad, ValueNumber[]> entry : availableLoadMap.entrySet()) {
+ ValueNumber[] oValue = o.availableLoadMap.get(entry.getKey());
+ if(!Arrays.equals(entry.getValue(), oValue)) {
+ return false;
+ }
+ }
+ return true;
+ }
-// vim:ts=4
+ public boolean hasAvailableLoads() {
+ return !getAvailableLoadMap().isEmpty();
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFrameModelingVisitor.java b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFrameModelingVisitor.java
index 8b77173..e4ebc3e 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFrameModelingVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberFrameModelingVisitor.java
@@ -32,8 +32,8 @@ import org.apache.bcel.generic.ConstantPushInstruction;
import org.apache.bcel.generic.GETFIELD;
import org.apache.bcel.generic.GETSTATIC;
import org.apache.bcel.generic.IINC;
+import org.apache.bcel.generic.INVOKEDYNAMIC;
import org.apache.bcel.generic.INVOKEINTERFACE;
-import org.apache.bcel.generic.INVOKESPECIAL;
import org.apache.bcel.generic.INVOKESTATIC;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.Instruction;
@@ -42,6 +42,7 @@ import org.apache.bcel.generic.InvokeInstruction;
import org.apache.bcel.generic.LDC;
import org.apache.bcel.generic.MONITORENTER;
import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.PUTFIELD;
import org.apache.bcel.generic.PUTSTATIC;
@@ -56,18 +57,21 @@ import edu.umd.cs.findbugs.ba.InvalidBytecodeException;
import edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback;
import edu.umd.cs.findbugs.ba.XField;
import edu.umd.cs.findbugs.ba.XMethod;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.detect.FindNoSideEffectMethods.MethodSideEffectStatus;
+import edu.umd.cs.findbugs.detect.FindNoSideEffectMethods.NoSideEffectMethodsDatabase;
/**
* Visitor which models the effects of bytecode instructions on value numbers of
* values in the operand stack frames.
- *
+ *
* @see ValueNumber
* @see ValueNumberFrame
* @see ValueNumberAnalysis
* @author David Hovemeyer
*/
public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisitor<ValueNumber, ValueNumberFrame> implements
- Debug, ValueNumberAnalysisFeatures {
+Debug, ValueNumberAnalysisFeatures {
/*
* ----------------------------------------------------------------------
@@ -75,20 +79,22 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
* ----------------------------------------------------------------------
*/
- private MethodGen methodGen;
+ private final MethodGen methodGen;
ValueNumberFactory factory;
- private ValueNumberCache cache;
+ private final ValueNumberCache cache;
- private LoadedFieldSet loadedFieldSet;
+ private final LoadedFieldSet loadedFieldSet;
- private HashMap<Object, ValueNumber> constantValueMap;
+ private final HashMap<Object, ValueNumber> constantValueMap;
- private HashMap<ValueNumber, String> stringConstantMap;
+ private final HashMap<ValueNumber, String> stringConstantMap;
private InstructionHandle handle;
+ private static final ValueNumber[] EMPTY_INPUT_VALUE_LIST = new ValueNumber[0];
+
/*
* ----------------------------------------------------------------------
* Public interface
@@ -97,7 +103,7 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
/**
* Constructor.
- *
+ *
* @param methodGen
* the method being analyzed
* @param factory
@@ -143,51 +149,61 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
/**
* Determine whether redundant load elimination should be performed for the
* heap location referenced by the current instruction.
- *
+ *
* @return true if we should do redundant load elimination for the current
* instruction, false if not
*/
private boolean doRedundantLoadElimination() {
- if (!REDUNDANT_LOAD_ELIMINATION)
+ if (!REDUNDANT_LOAD_ELIMINATION) {
return false;
+ }
XField xfield = loadedFieldSet.getField(handle);
- if (xfield == null)
+ if (xfield == null) {
return false;
+ }
- if (!xfield.isReferenceType())
+ if(xfield.getSignature().equals("D") || xfield.getSignature().equals("J")) {
+ // TODO: support two-slot fields
return false;
+ }
// Don't do redundant load elimination for fields that
// are loaded in only one place.
- if (false && loadedFieldSet.getLoadStoreCount(xfield).getLoadCount() <= 1)
+ /*
+ if (false && loadedFieldSet.getLoadStoreCount(xfield).getLoadCount() <= 1){
return false;
-
+ }
+ */
return true;
}
/**
* Determine whether forward substitution should be performed for the heap
* location referenced by the current instruction.
- *
+ *
* @return true if we should do forward substitution for the current
* instruction, false if not
*/
private boolean doForwardSubstitution() {
- if (!REDUNDANT_LOAD_ELIMINATION)
+ if (!REDUNDANT_LOAD_ELIMINATION) {
return false;
+ }
XField xfield = loadedFieldSet.getField(handle);
- if (xfield == null)
+ if (xfield == null) {
return false;
+ }
- if (!xfield.isReferenceType())
+ if(xfield.getSignature().equals("D") || xfield.getSignature().equals("J")) {
return false;
+ }
// Don't do forward substitution for fields that
// are never read.
- if (!loadedFieldSet.isLoaded(xfield))
+ if (!loadedFieldSet.isLoaded(xfield)) {
return false;
+ }
return true;
}
@@ -196,10 +212,12 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
int numConsumed = ins.consumeStack(getCPG());
int numProduced = ins.produceStack(getCPG());
- if (numConsumed == Constants.UNPREDICTABLE)
+ if (numConsumed == Constants.UNPREDICTABLE) {
throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins);
- if (numProduced == Constants.UNPREDICTABLE)
+ }
+ if (numProduced == Constants.UNPREDICTABLE) {
throw new InvalidBytecodeException("Unpredictable stack production for " + ins);
+ }
if (consumedValueList.length != numConsumed) {
throw new IllegalStateException("Wrong number of values consumed for " + ins + ": expected " + numConsumed + ", got "
@@ -219,12 +237,13 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
public void modelNormalInstruction(Instruction ins, int numWordsConsumed, int numWordsProduced) {
int flags = 0;
- if (ins instanceof InvokeInstruction)
+ if (ins instanceof InvokeInstruction) {
flags = ValueNumber.RETURN_VALUE;
- else if (ins instanceof ArrayInstruction)
+ } else if (ins instanceof ArrayInstruction) {
flags = ValueNumber.ARRAY_VALUE;
- else if (ins instanceof ConstantPushInstruction)
+ } else if (ins instanceof ConstantPushInstruction) {
flags = ValueNumber.CONSTANT_VALUE;
+ }
// Get the input operands to this instruction.
ValueNumber[] inputValueList = popInputValues(numWordsConsumed);
@@ -246,8 +265,9 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
public void visitGETFIELD(GETFIELD obj) {
XField xfield = Hierarchy.findXField(obj, getCPG());
if (xfield != null) {
- if (xfield.isVolatile())
+ if (xfield.isVolatile()) {
getFrame().killAllLoads();
+ }
if (doRedundantLoadElimination()) {
loadInstanceField(xfield, obj);
@@ -261,18 +281,16 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
@Override
public void visitPUTFIELD(PUTFIELD obj) {
if (doForwardSubstitution()) {
- XField xfield = Hierarchy.findXField(obj, getCPG());
- if (xfield != null) {
- storeInstanceField(xfield, obj, false);
- return;
- }
-
+ XField xfield = Hierarchy.findXField(obj, getCPG());
+ if (xfield != null) {
+ storeInstanceField(xfield, obj, false);
+ return;
+ }
+
}
handleNormalInstruction(obj);
}
- private static final ValueNumber[] EMPTY_INPUT_VALUE_LIST = new ValueNumber[0];
-
@Override
public void visitGETSTATIC(GETSTATIC obj) {
ConstantPoolGen cpg = getCPG();
@@ -285,10 +303,11 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
System.out.println("GETSTATIC of " + fieldName + " : " + fieldSig);
}
// Is this an access of a Class object?
- if (fieldName.startsWith("class$") && fieldSig.equals("Ljava/lang/Class;")) {
+ if (fieldName.startsWith("class$") && "Ljava/lang/Class;".equals(fieldSig)) {
String className = fieldName.substring("class$".length()).replace('$', '.');
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("[found load of class object " + className + "]");
+ }
ValueNumber value = factory.getClassObjectValue(className);
frame.pushValue(value);
return;
@@ -296,8 +315,9 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
XField xfield = Hierarchy.findXField(obj, getCPG());
if (xfield != null) {
- if (xfield.isVolatile())
+ if (xfield.isVolatile()) {
getFrame().killAllLoads();
+ }
if (doRedundantLoadElimination()) {
loadStaticField(xfield, obj);
return;
@@ -330,8 +350,8 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
String methodName = obj.getName(cpg);
String methodSig = obj.getSignature(cpg);
- if ((methodName.equals("forName") && targetClassName.equals("java.lang.Class") || methodName.equals("class$"))
- && methodSig.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
+ if (("forName".equals(methodName) && "java.lang.Class".equals(targetClassName) || "class$".equals(methodName))
+ && "(Ljava/lang/String;)Ljava/lang/Class;".equals(methodSig)) {
// Access of a Class object
ValueNumberFrame frame = getFrame();
try {
@@ -339,8 +359,9 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
String className = stringConstantMap.get(arg);
if (className != null) {
frame.popValue();
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("[found access of class object " + className + "]");
+ }
frame.pushValue(factory.getClassObjectValue(className));
return;
}
@@ -354,10 +375,11 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
if (loadedFieldSet.instructionIsLoad(handle)) {
// Load via inner-class accessor
if (doRedundantLoadElimination()) {
- if (xfield.isStatic())
+ if (xfield.isStatic()) {
loadStaticField(xfield, obj);
- else
+ } else {
loadInstanceField(xfield, obj);
+ }
return;
}
} else {
@@ -367,35 +389,46 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
// return the value stored.
boolean pushValue = !methodSig.endsWith(")V");
- if (xfield.isStatic())
+ if (xfield.isStatic()) {
storeStaticField(xfield, obj, pushValue);
- else
+ } else {
storeInstanceField(xfield, obj, pushValue);
+ }
return;
}
}
- } else {
- // Don't know what this method invocation is doing.
- // Kill all loads.
- killLoadsOfObjectsPassed(obj);
- getFrame().killAllLoadsOf(null);
}
- } else {
- // Don't know what this method invocation is doing.
- // Kill all loads.
- killLoadsOfObjectsPassed(obj);
- getFrame().killAllLoadsOf(null);
}
}
-
handleNormalInstruction(obj);
}
+ private void killLoadsOfObjectsPassed(INVOKEDYNAMIC ins) {
+ try {
+
+ int passed = getNumWordsConsumed(ins);
+ ValueNumber[] arguments = allocateValueNumberArray(passed);
+ getFrame().getTopStackWords(arguments);
+ for (ValueNumber v : arguments) {
+ getFrame().killAllLoadsOf(v);
+ }
+
+ } catch (DataflowAnalysisException e) {
+ AnalysisContext.logError("Error in killLoadsOfObjectsPassed", e);
+ }
+ }
+
private void killLoadsOfObjectsPassed(InvokeInstruction ins) {
try {
XMethod called = Hierarchy2.findExactMethod(ins, methodGen.getConstantPool(), Hierarchy.ANY_METHOD);
+ if (called != null ) {
+ NoSideEffectMethodsDatabase nse = Global.getAnalysisCache().getOptionalDatabase(NoSideEffectMethodsDatabase.class);
+ if(nse != null && !nse.is(called.getMethodDescriptor(), MethodSideEffectStatus.SE, MethodSideEffectStatus.OBJ)) {
+ return;
+ }
+ }
FieldSummary fieldSummary = AnalysisContext.currentAnalysisContext().getFieldSummary();
Set<XField> touched = fieldSummary.getFieldsWritten(called);
if (!touched.isEmpty()) {
@@ -407,8 +440,14 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
ValueNumber[] arguments = allocateValueNumberArray(passed);
getFrame().killLoadsWithSimilarName(ins.getClassName(cpg), ins.getMethodName(cpg));
getFrame().getTopStackWords(arguments);
- for (ValueNumber v : arguments)
+ for (ValueNumber v : arguments) {
getFrame().killAllLoadsOf(v);
+ }
+
+ // Too many false-positives for primitives without transitive FieldSummary analysis,
+ // so currently we simply kill any writable primitive on any method call
+ // TODO: implement transitive FieldSummary
+ getFrame().killAllLoads(true);
} catch (DataflowAnalysisException e) {
AnalysisContext.logError("Error in killLoadsOfObjectsPassed", e);
@@ -429,29 +468,45 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
handleNormalInstruction(obj);
}
- @Override
- public void visitINVOKESPECIAL(INVOKESPECIAL obj) {
- // Don't know what this method invocation is doing.
- // Kill all loads.
- killLoadsOfObjectsPassed(obj);
- handleNormalInstruction(obj);
- }
-
- @Override
- public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) {
- // Don't know what this method invocation is doing.
- // Kill all loads.
- if (obj.getMethodName(cpg).equals("lock"))
+ public void visitInvokeOnException(Instruction obj) {
+ if(!REDUNDANT_LOAD_ELIMINATION || !getFrame().hasAvailableLoads()) {
+ return;
+ }
+ if(obj instanceof INVOKEDYNAMIC) {
+ killLoadsOfObjectsPassed((INVOKEDYNAMIC) obj);
+ return;
+ }
+ InvokeInstruction inv = (InvokeInstruction) obj;
+ if ((inv instanceof INVOKEINTERFACE || inv instanceof INVOKEVIRTUAL)
+ && inv.getMethodName(cpg).toLowerCase().indexOf("lock") >= 0) {
+ // Don't know what this method invocation is doing.
+ // Kill all loads.
getFrame().killAllLoads();
- else
- killLoadsOfObjectsPassed(obj);
- handleNormalInstruction(obj);
+ return;
+ }
+ if(inv instanceof INVOKEVIRTUAL && "cast".equals(inv.getMethodName(cpg)) && "java.lang.Class".equals(inv.getClassName(cpg))) {
+ // No-op
+ return;
+ }
+ if(inv instanceof INVOKESTATIC) {
+ String methodName = inv.getName(cpg);
+ if (("forName".equals(methodName) && "java.lang.Class".equals(inv.getClassName(cpg)) || "class$".equals(methodName))
+ && "(Ljava/lang/String;)Ljava/lang/Class;".equals(inv.getSignature(cpg))
+ || (Hierarchy.isInnerClassAccess((INVOKESTATIC) inv, cpg) && loadedFieldSet.getField(handle) != null)) {
+ return;
+ }
+ }
+
+ killLoadsOfObjectsPassed(inv);
+ if(inv instanceof INVOKESTATIC) {
+ getFrame().killAllLoadsOf(null);
+ }
}
@Override
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) {
- if (obj.getMethodName(cpg).equals("cast") && obj.getClassName(cpg).equals("java.lang.Class")) {
+ if ("cast".equals(obj.getMethodName(cpg)) && "java.lang.Class".equals(obj.getClassName(cpg))) {
// treat as no-op
try {
ValueNumberFrame frame = getFrame();
@@ -463,12 +518,6 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
}
return;
}
- // Don't know what this method invocation is doing.
- // Kill all loads.
- if (obj.getMethodName(cpg).toLowerCase().indexOf("lock") >= 0)
- getFrame().killAllLoads();
- else
- killLoadsOfObjectsPassed(obj);
handleNormalInstruction(obj);
}
@@ -498,6 +547,10 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
ConstantClass constantClass = (ConstantClass) constantValue;
String className = constantClass.getBytes(cpg.getConstantPool());
value = factory.getClassObjectValue(className);
+ } else if (constantValue instanceof ObjectType) {
+ ObjectType objectType = (ObjectType) constantValue;
+ String className = objectType.getClassName();
+ value = factory.getClassObjectValue(className);
} else {
value = constantValueMap.get(constantValue);
if (value == null) {
@@ -576,8 +629,9 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
*/
private void pushOutputValues(ValueNumber[] outputValueList) {
ValueNumberFrame frame = getFrame();
- for (ValueNumber aOutputValueList : outputValueList)
+ for (ValueNumber aOutputValueList : outputValueList) {
frame.pushValue(aOutputValueList);
+ }
}
/**
@@ -596,21 +650,23 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
ValueNumber freshValue = factory.createFreshValue(flags);
outputValueList[i] = freshValue;
}
+ /*
if (false && RLE_DEBUG) {
System.out.println("<<cache fill for " + handle.getPosition() + ": " + vlts(inputValueList) + " ==> "
+ vlts(outputValueList) + ">>");
}
+ */
cache.addOutputValues(entry, outputValueList);
- } else if (false && RLE_DEBUG) {
+ } /* else if (false && RLE_DEBUG) {
System.out.println("<<cache hit for " + handle.getPosition() + ": " + vlts(inputValueList) + " ==> "
+ vlts(outputValueList) + ">>");
- }
+ } */
return outputValueList;
}
/**
* Creates a new empty array (if needed) with given size.
- *
+ *
* @param size
* array size
* @return if size is zero, returns {@link #EMPTY_INPUT_VALUE_LIST}
@@ -625,8 +681,9 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
private static String vlts(ValueNumber[] vl) {
StringBuilder buf = new StringBuilder();
for (ValueNumber aVl : vl) {
- if (buf.length() > 0)
+ if (buf.length() > 0) {
buf.append(',');
+ }
buf.append(aVl.getNumber());
}
return buf.toString();
@@ -634,7 +691,7 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
/**
* Load an instance field.
- *
+ *
* @param instanceField
* the field
* @param obj
@@ -651,8 +708,9 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
ValueNumber reference = frame.popValue();
AvailableLoad availableLoad = new AvailableLoad(reference, instanceField);
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("[getfield of " + availableLoad + "]");
+ }
ValueNumber[] loadedValue = frame.getAvailableLoad(availableLoad);
if (loadedValue == null) {
@@ -684,7 +742,7 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
/**
* Load a static field.
- *
+ *
* @param staticField
* the field
* @param obj
@@ -707,11 +765,13 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
frame.addAvailableLoad(availableLoad, loadedValue);
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("[making load of " + staticField + " available]");
+ }
} else {
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("[found available load of " + staticField + "]");
+ }
}
if (VERIFY_INTEGRITY) {
@@ -723,7 +783,7 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
/**
* Store an instance field.
- *
+ *
* @param instanceField
* the field
* @param obj
@@ -749,8 +809,9 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
ValueNumber[] storedValue = allocateValueNumberArray(inputValueList.length - 1);
System.arraycopy(inputValueList, 1, storedValue, 0, inputValueList.length - 1);
- if (pushStoredValue)
+ if (pushStoredValue) {
pushOutputValues(storedValue);
+ }
// Kill all previous loads of the same field,
// in case there is aliasing we don't know about
@@ -759,8 +820,9 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
// Forward substitution
frame.addAvailableLoad(new AvailableLoad(reference, instanceField), storedValue);
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("[making store of " + instanceField + " available]");
+ }
if (VERIFY_INTEGRITY) {
/*
@@ -772,7 +834,7 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
/**
* Store a static field.
- *
+ *
* @param staticField
* the static field
* @param obj
@@ -793,8 +855,9 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
int numWordsConsumed = getNumWordsConsumed(obj);
ValueNumber[] inputValueList = popInputValues(numWordsConsumed);
- if (pushStoredValue)
+ if (pushStoredValue) {
pushOutputValues(inputValueList);
+ }
// Kill loads of this field
frame.killLoadsOfField(staticField);
@@ -802,8 +865,9 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
// Make load available
frame.addAvailableLoad(availableLoad, inputValueList);
- if (RLE_DEBUG)
+ if (RLE_DEBUG) {
System.out.println("[making store of " + staticField + " available]");
+ }
if (VERIFY_INTEGRITY) {
checkConsumedAndProducedValues(obj, inputValueList, pushStoredValue ? inputValueList : EMPTY_INPUT_VALUE_LIST);
@@ -812,4 +876,3 @@ public class ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisito
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberSourceInfo.java b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberSourceInfo.java
index ce38b03..9646813 100644
--- a/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberSourceInfo.java
+++ b/src/java/edu/umd/cs/findbugs/ba/vna/ValueNumberSourceInfo.java
@@ -39,7 +39,7 @@ import edu.umd.cs.findbugs.ba.XField;
/**
* Helper methods to find out information about the source of the value
* represented by a given ValueNumber.
- *
+ *
* @author Bill Pugh
* @author David Hovemeyer
*/
@@ -64,21 +64,24 @@ public abstract class ValueNumberSourceInfo {
}
LocalVariableAnnotation ann = ValueNumberSourceInfo.findLocalAnnotationFromValueNumber(method, location, valueNumber,
vnaFrame);
- if (ann != null && partialRole != null)
+ if (ann != null && partialRole != null) {
ann.setDescription("LOCAL_VARIABLE_" + partialRole);
+ }
if (ann != null && ann.isSignificant()) {
return ann;
}
FieldAnnotation field = ValueNumberSourceInfo.findFieldAnnotationFromValueNumber(method, location, valueNumber, vnaFrame);
if (field != null) {
- if (partialRole != null)
+ if (partialRole != null) {
field.setDescription("FIELD_" + partialRole);
+ }
return field;
}
- if (ann != null)
+ if (ann != null) {
return ann;
+ }
return null;
}
@@ -95,29 +98,33 @@ public abstract class ValueNumberSourceInfo {
BugAnnotation findRequiredAnnotationFromValueNumber(Method method, Location location, ValueNumber valueNumber,
ValueNumberFrame vnaFrame, @CheckForNull String partialRole) {
BugAnnotation result = findAnnotationFromValueNumber(method, location, valueNumber, vnaFrame, partialRole);
- if (result != null)
+ if (result != null) {
return result;
+ }
return new LocalVariableAnnotation("?", -1, location.getHandle().getPosition());
}
public static LocalVariableAnnotation findLocalAnnotationFromValueNumber(Method method, Location location,
ValueNumber valueNumber, ValueNumberFrame vnaFrame) {
- if (vnaFrame == null || vnaFrame.isBottom() || vnaFrame.isTop())
+ if (vnaFrame == null || vnaFrame.isBottom() || vnaFrame.isTop()) {
return null;
+ }
LocalVariableAnnotation localAnnotation = null;
for (int i = 0; i < vnaFrame.getNumLocals(); i++) {
if (valueNumber.equals(vnaFrame.getValue(i))) {
InstructionHandle handle = location.getHandle();
InstructionHandle prev = handle.getPrev();
- if (prev == null)
+ if (prev == null) {
continue;
+ }
int position1 = prev.getPosition();
int position2 = handle.getPosition();
localAnnotation = LocalVariableAnnotation.getLocalVariableAnnotation(method, i, position1, position2);
- if (localAnnotation != null)
+ if (localAnnotation != null) {
return localAnnotation;
+ }
}
}
return null;
@@ -126,15 +133,17 @@ public abstract class ValueNumberSourceInfo {
public static FieldAnnotation findFieldAnnotationFromValueNumber(Method method, Location location, ValueNumber valueNumber,
ValueNumberFrame vnaFrame) {
XField field = ValueNumberSourceInfo.findXFieldFromValueNumber(method, location, valueNumber, vnaFrame);
- if (field == null)
+ if (field == null) {
return null;
+ }
return FieldAnnotation.fromXField(field);
}
public static XField findXFieldFromValueNumber(Method method, Location location, ValueNumber valueNumber,
ValueNumberFrame vnaFrame) {
- if (vnaFrame == null || vnaFrame.isBottom() || vnaFrame.isTop())
+ if (vnaFrame == null || vnaFrame.isBottom() || vnaFrame.isTop()) {
return null;
+ }
AvailableLoad load = vnaFrame.getLoad(valueNumber);
if (load != null) {
@@ -155,11 +164,13 @@ public abstract class ValueNumberSourceInfo {
public BugAnnotation getFromValueNumber(ClassContext classContext, Method method, Location location, int stackPos)
throws DataflowAnalysisException, CFGBuilderException {
ValueNumberFrame vnaFrame = classContext.getValueNumberDataflow(method).getFactAtLocation(location);
- if (!vnaFrame.isValid())
+ if (!vnaFrame.isValid()) {
return null;
+ }
ValueNumber valueNumber = vnaFrame.getStackValue(stackPos);
- if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))
+ if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
return null;
+ }
BugAnnotation variableAnnotation = findAnnotationFromValueNumber(method, location, valueNumber, vnaFrame, "VALUE_OF");
return variableAnnotation;
diff --git a/src/java/edu/umd/cs/findbugs/bcel/AnnotationDetector.java b/src/java/edu/umd/cs/findbugs/bcel/AnnotationDetector.java
index 187bd71..4038f23 100644
--- a/src/java/edu/umd/cs/findbugs/bcel/AnnotationDetector.java
+++ b/src/java/edu/umd/cs/findbugs/bcel/AnnotationDetector.java
@@ -27,12 +27,13 @@ import edu.umd.cs.findbugs.visitclass.AnnotationVisitor;
/**
* Base class for Detectors which want to perform a preorder traversal of the
* classfile including visiting Annotations.
- *
+ *
* @see AnnotationVisitor
*/
abstract public class AnnotationDetector extends AnnotationVisitor implements Detector, UseAnnotationDatabase {
private ClassContext classContext;
+ @Override
public void visitClassContext(ClassContext classContext) {
this.classContext = classContext;
classContext.getJavaClass().accept(this);
@@ -40,15 +41,15 @@ abstract public class AnnotationDetector extends AnnotationVisitor implements De
/**
* Get the ClassContext of the class currently being visited.
- *
+ *
* @return the current ClassContext
*/
public ClassContext getClassContext() {
return classContext;
}
+ @Override
public void report() {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/bcel/BCELUtil.java b/src/java/edu/umd/cs/findbugs/bcel/BCELUtil.java
index a71d6a7..3df1178 100644
--- a/src/java/edu/umd/cs/findbugs/bcel/BCELUtil.java
+++ b/src/java/edu/umd/cs/findbugs/bcel/BCELUtil.java
@@ -40,13 +40,13 @@ import edu.umd.cs.findbugs.util.ClassName;
/**
* Utility methods for detectors and analyses using BCEL.
- *
+ *
* @author David Hovemeyer
*/
public abstract class BCELUtil {
/**
* Construct a MethodDescriptor from JavaClass and method.
- *
+ *
* @param jclass
* a JavaClass
* @param method
@@ -61,7 +61,7 @@ public abstract class BCELUtil {
/**
* Get a MethodDescriptor describing the method called by given
* InvokeInstruction.
- *
+ *
* @param inv
* the InvokeInstruction
* @param cpg
@@ -80,7 +80,7 @@ public abstract class BCELUtil {
/**
* Get FieldDescriptor describing the field accessed by given
* FieldInstruction.
- *
+ *
* @param fins
* a FieldInstruction
* @param cpg
@@ -98,7 +98,7 @@ public abstract class BCELUtil {
/**
* Construct a ClassDescriptor from a JavaClass.
- *
+ *
* @param jclass
* a JavaClass
* @return a ClassDescriptor identifying that JavaClass
@@ -121,7 +121,7 @@ public abstract class BCELUtil {
/**
* Get a ClassDescriptor for the class described by given ObjectType object.
- *
+ *
* @param type
* an ObjectType
* @return a ClassDescriptor for the class described by the ObjectType
@@ -137,7 +137,7 @@ public abstract class BCELUtil {
* Throw a ClassNotFoundException to indicate that class named by given
* ClassDescriptor cannot be found. The exception message is formatted in a
* way that can be decoded by ClassNotFoundExceptionParser.
- *
+ *
* @param classDescriptor
* ClassDescriptor naming a class that cannot be found
* @throws ClassNotFoundException
@@ -154,35 +154,44 @@ public abstract class BCELUtil {
public static ObjectType getObjectTypeInstance(@DottedClassName String className) {
return ObjectType.getInstance(className);
}
-
+
public static ObjectType getObjectTypeInstance(Class<?> clazz) {
return getObjectTypeInstance(clazz.getName());
}
-
+
public static boolean isSynthetic(FieldOrMethod m) {
- if (m.isSynthetic())
+ if (m.isSynthetic()) {
return true;
+ }
- for(Attribute a : m.getAttributes())
- if (a instanceof Synthetic)
+ for(Attribute a : m.getAttributes()) {
+ if (a instanceof Synthetic) {
return true;
+ }
+ }
return false;
}
public static boolean isSynthetic(JavaClass j) {
- if (j.isSynthetic())
+ if (j.isSynthetic()) {
return true;
+ }
- for(Attribute a : j.getAttributes())
- if (a instanceof Synthetic)
+ for(Attribute a : j.getAttributes()) {
+ if (a instanceof Synthetic) {
return true;
+ }
+ }
return false;
}
public static boolean isSynthetic(FieldGenOrMethodGen m) {
- if (m.isSynthetic())
+ if (m.isSynthetic()) {
return true;
- for(Attribute a : m.getAttributes())
- if (a instanceof Synthetic)
+ }
+ for(Attribute a : m.getAttributes()) {
+ if (a instanceof Synthetic) {
return true;
+ }
+ }
return false;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/bcel/CFGDetector.java b/src/java/edu/umd/cs/findbugs/bcel/CFGDetector.java
index 6398412..78a3742 100644
--- a/src/java/edu/umd/cs/findbugs/bcel/CFGDetector.java
+++ b/src/java/edu/umd/cs/findbugs/bcel/CFGDetector.java
@@ -34,24 +34,26 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Base class for detectors that analyze CFG (and/or use CFG-based analyses).
- *
+ *
* @author David Hovemeyer
*/
public abstract class CFGDetector implements Detector2 {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector2#finishPass()
*/
+ @Override
public void finishPass() {
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector2#getDetectorClassName()
*/
+ @Override
public String getDetectorClassName() {
return getClass().getName();
}
@@ -60,11 +62,12 @@ public abstract class CFGDetector implements Detector2 {
protected Method method;
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.Detector2#visitClass(edu.umd.cs.findbugs.classfile
* .ClassDescriptor)
*/
+ @Override
public void visitClass(ClassDescriptor classDescriptor) throws CheckedAnalysisException {
IAnalysisCache analysisCache = Global.getAnalysisCache();
@@ -94,7 +97,7 @@ public abstract class CFGDetector implements Detector2 {
/**
* Visit the CFG (control flow graph) of a method to be analyzed. Should be
* overridded by subclasses.
- *
+ *
* @param methodDescriptor
* @param cfg
* @throws CheckedAnalysisException
diff --git a/src/java/edu/umd/cs/findbugs/bcel/OpcodeStackDetector.java b/src/java/edu/umd/cs/findbugs/bcel/OpcodeStackDetector.java
index 09f9c61..6cc05e9 100644
--- a/src/java/edu/umd/cs/findbugs/bcel/OpcodeStackDetector.java
+++ b/src/java/edu/umd/cs/findbugs/bcel/OpcodeStackDetector.java
@@ -55,8 +55,9 @@ abstract public class OpcodeStackDetector extends BytecodeScanningDetector {
@Override
public final void visitCode(Code obj) {
- if (!shouldVisitCode(obj))
+ if (!shouldVisitCode(obj)) {
return;
+ }
stack = new OpcodeStack();
stack.resetForMethodEntry(this);
super.visitCode(obj);
@@ -69,11 +70,22 @@ abstract public class OpcodeStackDetector extends BytecodeScanningDetector {
return !stack.isTop();
}
+ /**
+ * <p>Note that stack might be TOP when this method is called.</p>
+ * @see #sawOpcode(int)
+ */
@Override
public void afterOpcode(int seen) {
stack.sawOpcode(this, seen);
}
+ /**
+ * <p>By default, this method will not be called when
+ * stack is TOP. To change this behavior, override {@code #beforeOpcode(int)}
+ * and change to return true even if stack is TOP.</p>
+ * <p>see <a href="http://findbugs-tutorials.googlecode.com/files/uffr-talk.pdf">Using FindBugs for Research</a> to learn lattice and what TOP means.</p>
+ * @see #beforeOpcode(int)
+ */
@Override
abstract public void sawOpcode(int seen);
diff --git a/src/java/edu/umd/cs/findbugs/bcel/PreorderDetector.java b/src/java/edu/umd/cs/findbugs/bcel/PreorderDetector.java
index 54c1251..9f66267 100644
--- a/src/java/edu/umd/cs/findbugs/bcel/PreorderDetector.java
+++ b/src/java/edu/umd/cs/findbugs/bcel/PreorderDetector.java
@@ -26,12 +26,13 @@ import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
/**
* Base class for Detectors which want to perform a preorder traversal of the
* classfile.
- *
+ *
* @see PreorderVisitor
*/
abstract public class PreorderDetector extends PreorderVisitor implements Detector {
private ClassContext classContext;
+ @Override
public void visitClassContext(ClassContext classContext) {
this.classContext = classContext;
classContext.getJavaClass().accept(this);
@@ -39,15 +40,15 @@ abstract public class PreorderDetector extends PreorderVisitor implements Detect
/**
* Get the ClassContext of the class currently being visited.
- *
+ *
* @return the current ClassContext
*/
public ClassContext getClassContext() {
return classContext;
}
+ @Override
public void report() {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/bcel/generic/NONNULL2Z.java b/src/java/edu/umd/cs/findbugs/bcel/generic/NONNULL2Z.java
index e4fa569..6616842 100644
--- a/src/java/edu/umd/cs/findbugs/bcel/generic/NONNULL2Z.java
+++ b/src/java/edu/umd/cs/findbugs/bcel/generic/NONNULL2Z.java
@@ -4,7 +4,7 @@ package edu.umd.cs.findbugs.bcel.generic;
/** A synthetic instruction that converts a reference to a boolean value,
* translating any nonnull value to 1 (true), and null value to 0 (false).
- *
+ *
*/
public class NONNULL2Z extends NullnessConversationInstruction {
@@ -12,6 +12,6 @@ public class NONNULL2Z extends NullnessConversationInstruction {
super(org.apache.bcel.Constants.IMPDEP2);
}
-
+
}
diff --git a/src/java/edu/umd/cs/findbugs/bcel/generic/NULL2Z.java b/src/java/edu/umd/cs/findbugs/bcel/generic/NULL2Z.java
index 161002d..35043a2 100644
--- a/src/java/edu/umd/cs/findbugs/bcel/generic/NULL2Z.java
+++ b/src/java/edu/umd/cs/findbugs/bcel/generic/NULL2Z.java
@@ -4,7 +4,7 @@ package edu.umd.cs.findbugs.bcel.generic;
/** A synthetic instruction that converts a reference to a boolean value,
* translating null to 1 (true), and any nonnull value to 0 (false).
- *
+ *
*/
public class NULL2Z extends NullnessConversationInstruction {
@@ -12,7 +12,7 @@ public class NULL2Z extends NullnessConversationInstruction {
public NULL2Z() {
super(org.apache.bcel.Constants.IMPDEP1);
}
-
-
+
+
}
diff --git a/src/java/edu/umd/cs/findbugs/bcel/generic/NullnessConversationInstruction.java b/src/java/edu/umd/cs/findbugs/bcel/generic/NullnessConversationInstruction.java
index dbe68f5..390e6d9 100644
--- a/src/java/edu/umd/cs/findbugs/bcel/generic/NullnessConversationInstruction.java
+++ b/src/java/edu/umd/cs/findbugs/bcel/generic/NullnessConversationInstruction.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -25,7 +25,7 @@ import org.apache.bcel.generic.Type;
import org.apache.bcel.generic.Visitor;
/** A synthetic instruction that converts a the nullness of a reference to a boolean value.
- *
+ *
*/
public abstract class NullnessConversationInstruction extends ConversionInstruction {
@@ -46,7 +46,7 @@ public abstract class NullnessConversationInstruction extends ConversionInstruct
public int produceStack( ConstantPoolGen cpg ) {
return 1;
}
-
+
@Override
public int hashCode() {
return this.getClass().hashCode();
diff --git a/src/java/edu/umd/cs/findbugs/bugReporter/MaxRankDecorator.java b/src/java/edu/umd/cs/findbugs/bugReporter/MaxRankDecorator.java
index df80acf..dfbc555 100644
--- a/src/java/edu/umd/cs/findbugs/bugReporter/MaxRankDecorator.java
+++ b/src/java/edu/umd/cs/findbugs/bugReporter/MaxRankDecorator.java
@@ -40,8 +40,9 @@ public class MaxRankDecorator extends BugReporterDecorator {
@Override
public void reportBug(@Nonnull BugInstance bugInstance) {
int rank = bugInstance.getBugRank();
- if (rank <= maxRank)
+ if (rank <= maxRank) {
getDelegate().reportBug(bugInstance);
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/bugReporter/SuppressionDecorator.java b/src/java/edu/umd/cs/findbugs/bugReporter/SuppressionDecorator.java
index e598b98..3ae37b3 100644
--- a/src/java/edu/umd/cs/findbugs/bugReporter/SuppressionDecorator.java
+++ b/src/java/edu/umd/cs/findbugs/bugReporter/SuppressionDecorator.java
@@ -66,12 +66,13 @@ public class SuppressionDecorator extends BugReporterDecorator {
URL u;
if (adjustmentSource.startsWith("file:") || adjustmentSource.startsWith("http:")
- || adjustmentSource.startsWith("https:"))
+ || adjustmentSource.startsWith("https:")) {
u = new URL(adjustmentSource);
- else {
+ } else {
u = plugin.getPlugin().getResource(adjustmentSource);
- if (u == null)
+ if (u == null) {
u = DetectorFactoryCollection.getCoreResource(adjustmentSource);
+ }
}
if (u != null) {
@@ -90,25 +91,24 @@ public class SuppressionDecorator extends BugReporterDecorator {
* @throws IOException
*/
private void processPackageList(@WillClose Reader rawIn) throws IOException {
- try {
- BufferedReader in = new BufferedReader(rawIn);
- while (true) {
- String s = in.readLine();
- if (s == null)
- break;
- s = s.trim();
- if (s.length() == 0)
- continue;
- String packageName = s.substring(1).trim();
- if (s.charAt(0) == '+') {
- check.add(packageName);
- dontCheck.remove(packageName);
- } else if (s.charAt(0) == '-') {
- dontCheck.add(packageName);
- check.remove(packageName);
- } else
- throw new IllegalArgumentException("Can't parse " + category + " filter line: " + s);
- }
+ try (BufferedReader in = new BufferedReader(rawIn)) {
+ String s;
+ while ((s = in.readLine()) != null) {
+ s = s.trim();
+ if (s.length() == 0) {
+ continue;
+ }
+ String packageName = s.substring(1).trim();
+ if (s.charAt(0) == '+') {
+ check.add(packageName);
+ dontCheck.remove(packageName);
+ } else if (s.charAt(0) == '-') {
+ dontCheck.add(packageName);
+ check.remove(packageName);
+ } else {
+ throw new IllegalArgumentException("Can't parse " + category + " filter line: " + s);
+ }
+ }
} finally {
rawIn.close();
}
@@ -121,8 +121,9 @@ public class SuppressionDecorator extends BugReporterDecorator {
getDelegate().reportBug(bugInstance);
return;
}
- if (check.isEmpty())
+ if (check.isEmpty()) {
return;
+ }
ClassAnnotation c = bugInstance.getPrimaryClass();
@DottedClassName
@@ -136,8 +137,9 @@ public class SuppressionDecorator extends BugReporterDecorator {
return;
}
int i = packageName.lastIndexOf('.');
- if (i < 0)
+ if (i < 0) {
return;
+ }
packageName = packageName.substring(0, i);
}
diff --git a/src/java/edu/umd/cs/findbugs/charsets/UTF8.java b/src/java/edu/umd/cs/findbugs/charsets/UTF8.java
index 3339bbf..80eb9ae 100644
--- a/src/java/edu/umd/cs/findbugs/charsets/UTF8.java
+++ b/src/java/edu/umd/cs/findbugs/charsets/UTF8.java
@@ -44,7 +44,7 @@ import javax.annotation.WillCloseWhenClosed;
public class UTF8 {
/**
- *
+ *
*/
private static final String UTF_8 = "UTF-8";
public static final Charset charset;
@@ -54,13 +54,13 @@ public class UTF8 {
}
public static PrintStream printStream(OutputStream out) {
- return printStream(out, false);
+ return printStream(out, false);
}
public static PrintStream printStream(OutputStream out, boolean autoflush) {
try {
return new PrintStream(out,autoflush, UTF_8);
} catch (UnsupportedEncodingException e) {
- throw new AssertionError("UTF-8 not supported");
+ throw new AssertionError("UTF-8 not supported");
}
}
public static Writer writer(OutputStream out) {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/CheckedAnalysisException.java b/src/java/edu/umd/cs/findbugs/classfile/CheckedAnalysisException.java
index 0c31c31..aed229e 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/CheckedAnalysisException.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/CheckedAnalysisException.java
@@ -22,7 +22,7 @@ package edu.umd.cs.findbugs.classfile;
/**
* Common superclass for all checked exceptions that can be thrown while
* performing some kind of analysis.
- *
+ *
* @author David Hovemeyer
*/
public class CheckedAnalysisException extends Exception {
@@ -38,7 +38,7 @@ public class CheckedAnalysisException extends Exception {
/**
* Constructor.
- *
+ *
* @param msg
* message
*/
@@ -48,7 +48,7 @@ public class CheckedAnalysisException extends Exception {
/**
* Constructor.
- *
+ *
* @param msg
* message
* @param cause
diff --git a/src/java/edu/umd/cs/findbugs/classfile/ClassDescriptor.java b/src/java/edu/umd/cs/findbugs/classfile/ClassDescriptor.java
index 686e4f5..6e59ca7 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/ClassDescriptor.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/ClassDescriptor.java
@@ -75,6 +75,7 @@ public class ClassDescriptor implements Comparable<ClassDescriptor>, Serializabl
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
+ @Override
public int compareTo(ClassDescriptor o) {
return className.compareTo(o.className);
}
@@ -113,7 +114,7 @@ public class ClassDescriptor implements Comparable<ClassDescriptor>, Serializabl
return ClassName.toDottedClassName(className);
}
- public XClass getXClass() throws CheckedAnalysisException {
+ public XClass getXClass() throws CheckedAnalysisException {
return Global.getAnalysisCache().getClassAnalysis(XClass.class, this);
}
/**
@@ -136,8 +137,9 @@ public class ClassDescriptor implements Comparable<ClassDescriptor>, Serializabl
}
public String getSignature() {
- if (isArray())
+ if (isArray()) {
return className;
+ }
return "L" + className + ";";
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/ClassNameMismatchException.java b/src/java/edu/umd/cs/findbugs/classfile/ClassNameMismatchException.java
index 7e0dac4..dd0913d 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/ClassNameMismatchException.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/ClassNameMismatchException.java
@@ -22,15 +22,15 @@ package edu.umd.cs.findbugs.classfile;
/**
* Exception to indicate that the class name defined in a class file does not
* match its expected class name (as indicated by its resource name).
- *
+ *
* @author David Hovemeyer
*/
public class ClassNameMismatchException extends InvalidClassFileFormatException {
- private ClassDescriptor loadedClassDescriptor;
+ private final ClassDescriptor loadedClassDescriptor;
/**
* Constructor.
- *
+ *
* @param expectedClassDescriptor
* class descriptor we were expected based on the resource name
* @param loadedClassDescriptor
diff --git a/src/java/edu/umd/cs/findbugs/classfile/DescriptorFactory.java b/src/java/edu/umd/cs/findbugs/classfile/DescriptorFactory.java
index 9f607e5..cfa15bb 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/DescriptorFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/DescriptorFactory.java
@@ -68,15 +68,17 @@ public class DescriptorFactory {
this.fieldDescriptorMap = new HashMap<FieldDescriptor, FieldDescriptor>();
}
- private MapCache<String, String> stringCache = new MapCache<String, String>(10000);
+ private final MapCache<String, String> stringCache = new MapCache<String, String>(10000);
public static String canonicalizeString(@CheckForNull String s) {
- if (s == null)
+ if (s == null) {
return s;
+ }
DescriptorFactory df = instanceThreadLocal.get();
String cached = df.stringCache.get(s);
- if (cached != null)
+ if (cached != null) {
return cached;
+ }
df.stringCache.put(s, s);
return s;
}
@@ -167,8 +169,9 @@ public class DescriptorFactory {
*/
public MethodDescriptor getMethodDescriptor(@SlashedClassName String className, String name, String signature,
boolean isStatic) {
- if (className == null)
+ if (className == null) {
throw new NullPointerException("className must be nonnull");
+ }
MethodDescriptor methodDescriptor = new MethodDescriptor(className, name, signature, isStatic);
MethodDescriptor existing = methodDescriptorMap.get(methodDescriptor);
if (existing == null) {
@@ -185,10 +188,12 @@ public class DescriptorFactory {
int bad = 0;
for (Map.Entry<MethodDescriptor, MethodDescriptor> e : methodDescriptorMap.entrySet()) {
total++;
- if (e.getKey() instanceof MethodInfo)
+ if (e.getKey() instanceof MethodInfo) {
keys++;
- if (e.getValue() instanceof MethodInfo)
+ }
+ if (e.getValue() instanceof MethodInfo) {
values++;
+ }
}
System.out.printf("Descriptor factory: %d/%d/%d%n", keys, values, total);
@@ -309,16 +314,19 @@ public class DescriptorFactory {
public static ClassDescriptor createClassDescriptorFromSignature(String signature) {
int length = signature.length();
- if (length == 0)
+ if (length == 0) {
throw new IllegalArgumentException("Empty signature");
- if (signature.charAt(0) == 'L' && signature.endsWith(";"))
+ }
+ if (signature.charAt(0) == 'L' && signature.endsWith(";")) {
signature = signature.substring(1, signature.length() - 1);
+ }
return createClassDescriptor(signature);
}
public static ClassDescriptor createClassOrObjectDescriptorFromSignature(String signature) {
- if (signature.charAt(0) == '[')
+ if (signature.charAt(0) == '[') {
return createClassDescriptor("java/lang/Object");
+ }
return createClassDescriptorFromSignature(signature);
}
@@ -331,11 +339,13 @@ public class DescriptorFactory {
}
public static ClassDescriptor[] createClassDescriptor(String[] classNames) {
- if (classNames.length == 0)
+ if (classNames.length == 0) {
return ClassDescriptor.EMPTY_ARRAY;
+ }
ClassDescriptor[] result = new ClassDescriptor[classNames.length];
- for (int i = 0; i < classNames.length; i++)
+ for (int i = 0; i < classNames.length; i++) {
result[i] = createClassDescriptor(classNames[i]);
+ }
return result;
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/FieldDescriptor.java b/src/java/edu/umd/cs/findbugs/classfile/FieldDescriptor.java
index 71de2a8..0dcdb38 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/FieldDescriptor.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/FieldDescriptor.java
@@ -24,14 +24,14 @@ import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
/**
* Descriptor uniquely identifying a field in a class.
- *
+ *
* @author David Hovemeyer
*/
public class FieldDescriptor extends FieldOrMethodDescriptor implements ComparableField {
/**
* Constructor.
- *
+ *
* @param className
* the name of the class the field belongs to
* @param fieldName
@@ -50,6 +50,7 @@ public class FieldDescriptor extends FieldOrMethodDescriptor implements Comparab
return (isStatic() ? "static " : "") + getClassDescriptor().getDottedClassName() + "." + getName() + " " + getSignature();
}
+ @Override
public int compareTo(ComparableField o) {
return FieldOrMethodDescriptor.compareTo(this, (FieldDescriptor)o);
}
@@ -61,5 +62,5 @@ public class FieldDescriptor extends FieldOrMethodDescriptor implements Comparab
}
return false;
}
-
+
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/FieldOrMethodDescriptor.java b/src/java/edu/umd/cs/findbugs/classfile/FieldOrMethodDescriptor.java
index 055f982..fc1fe8d 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/FieldOrMethodDescriptor.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/FieldOrMethodDescriptor.java
@@ -72,6 +72,7 @@ public abstract class FieldOrMethodDescriptor implements FieldOrMethodName {
/**
* @return a ClassDescriptor for the method's class
*/
+ @Override
public ClassDescriptor getClassDescriptor() {
return DescriptorFactory.createClassDescriptor(slashedClassName);
}
@@ -79,6 +80,7 @@ public abstract class FieldOrMethodDescriptor implements FieldOrMethodName {
/**
* @return Returns the method name
*/
+ @Override
public String getName() {
return name;
}
@@ -86,6 +88,7 @@ public abstract class FieldOrMethodDescriptor implements FieldOrMethodName {
/**
* @return Returns the method signature
*/
+ @Override
public String getSignature() {
return signature;
}
@@ -93,6 +96,7 @@ public abstract class FieldOrMethodDescriptor implements FieldOrMethodName {
/**
* @return Returns true if method is static, false if not
*/
+ @Override
public boolean isStatic() {
return isStatic;
}
@@ -116,8 +120,8 @@ public abstract class FieldOrMethodDescriptor implements FieldOrMethodName {
protected boolean haveEqualFields(FieldOrMethodDescriptor other) {
- return this.isStatic == other.isStatic && this.slashedClassName.equals(other.slashedClassName)
- && this.name.equals(other.name) && this.signature.equals(other.signature);
+ return this.isStatic == other.isStatic && this.slashedClassName.equals(other.slashedClassName)
+ && this.name.equals(other.name) && this.signature.equals(other.signature);
}
/*
@@ -144,15 +148,18 @@ public abstract class FieldOrMethodDescriptor implements FieldOrMethodName {
}
public static int compareTo(FieldOrMethodDescriptor thas, FieldOrMethodDescriptor that) {
- int result = thas.slashedClassName.compareTo(that.slashedClassName);
- if (result != 0)
+ int result = thas.slashedClassName.compareTo(that.slashedClassName);
+ if (result != 0) {
return result;
+ }
result = thas.name.compareTo(that.name);
- if (result != 0)
+ if (result != 0) {
return result;
+ }
result = thas.signature.compareTo(that.signature);
- if (result != 0)
+ if (result != 0) {
return result;
+ }
result = (thas.isStatic ? 1 : 0) - (that.isStatic ? 1 : 0);
return result;
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/Global.java b/src/java/edu/umd/cs/findbugs/classfile/Global.java
index e36c030..1674f98 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/Global.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/Global.java
@@ -22,7 +22,7 @@ package edu.umd.cs.findbugs.classfile;
/**
* Static methods for accessing objects that are global to an analysis session.
* Hopefully, this will be limited to the analysis cache.
- *
+ *
* @author David Hovemeyer
*/
public abstract class Global {
@@ -31,7 +31,7 @@ public abstract class Global {
/**
* Remove the analysis cache for the current thread. This should be called
* after all analysis is complete
- *
+ *
*/
public static void removeAnalysisCacheForCurrentThread() {
analysisCacheThreadLocal.remove();
@@ -40,7 +40,7 @@ public abstract class Global {
/**
* Set the analysis cache for the current thread. This should be called
* before any detectors or analyses that need the cache are used.
- *
+ *
* @param analysisCache
* the analysis cache to set for the current thread
*/
@@ -50,7 +50,7 @@ public abstract class Global {
/**
* Get the analysis cache for the current thread.
- *
+ *
* @return the analysis cache for the current thread
*/
public static IAnalysisCache getAnalysisCache() {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IAnalysisCache.java b/src/java/edu/umd/cs/findbugs/classfile/IAnalysisCache.java
index 15e62ea..a537b80 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IAnalysisCache.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IAnalysisCache.java
@@ -28,7 +28,7 @@ import edu.umd.cs.findbugs.log.Profiler;
/**
* The analysis cache performs analyses on classes and methods and caches the
* results.
- *
+ *
* @author David Hovemeyer
*/
public interface IAnalysisCache {
@@ -36,7 +36,7 @@ public interface IAnalysisCache {
/**
* Register the given class analysis engine as producing the analysis result
* type whose Class is given.
- *
+ *
* @param <E>
* analysis result type
* @param analysisResultType
@@ -49,7 +49,7 @@ public interface IAnalysisCache {
/**
* Register the given method analysis engine as producing the analysis
* result type whose Class is given.
- *
+ *
* @param <E>
* analysis result type
* @param analysisResultType
@@ -61,7 +61,7 @@ public interface IAnalysisCache {
/**
* Get an analysis of the given class.
- *
+ *
* @param <E>
* the type of the analysis (e.g., FoobarAnalysis)
* @param analysisClass
@@ -79,7 +79,7 @@ public interface IAnalysisCache {
/**
* See if the cache contains a cached class analysis result for given class
* descriptor.
- *
+ *
* @param analysisClass
* analysis result class
* @param classDescriptor
@@ -91,7 +91,7 @@ public interface IAnalysisCache {
/**
* Get an analysis of the given method.
- *
+ *
* @param <E>
* the type of the analysis (e.g., FoobarAnalysis)
* @param analysisClass
@@ -110,7 +110,7 @@ public interface IAnalysisCache {
* Eagerly put a method analysis object in the cache. This can be necessary
* if an method analysis engine invokes other analysis engines that might
* recursively require the analysis being produced.
- *
+ *
* @param <E>
* the type of the analysis (e.g., FoobarAnalysis)
* @param analysisClass
@@ -126,7 +126,7 @@ public interface IAnalysisCache {
* Purge all analysis results for given method. This can be called when a
* CFG is pruned and we want to compute more accurate analysis results on
* the new CFG.
- *
+ *
* @param methodDescriptor
* method whose analysis results should be purged
*/
@@ -144,7 +144,7 @@ public interface IAnalysisCache {
/**
* Register a database factory.
- *
+ *
* @param <E>
* type of database
* @param databaseClass
@@ -156,14 +156,14 @@ public interface IAnalysisCache {
/**
* Get a database.
- *
+ *
* <em>Note</em>: an unchecked analysis exception will be thrown if the
* database cannot be instantiated. Since instantiation of most kinds of
* databases simply involves creating an object (and not opening a file or
* other failure-prone operation), throwing a CheckedAnalysisException
* creates too great of an exception-handling burden on analyses and
* detectors which use databases.
- *
+ *
* @param <E>
* type of database
* @param databaseClass
@@ -177,7 +177,7 @@ public interface IAnalysisCache {
/**
* Eagerly install a database. This avoids the need to register a database
* factory.
- *
+ *
* @param <E>
* type of database
* @param databaseClass
@@ -189,14 +189,14 @@ public interface IAnalysisCache {
/**
* Get the classpath from which classes are loaded.
- *
+ *
* @return the classpath
*/
public IClassPath getClassPath();
/**
* Get the error logger.
- *
+ *
* @return the error logger
*/
public IErrorLogger getErrorLogger();
@@ -208,8 +208,6 @@ public interface IAnalysisCache {
/**
* Get the analysis profiler instance, never null
- *
- * @return
*/
public Profiler getProfiler();
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/IAnalysisEngine.java
index 495c26d..769312e 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IAnalysisEngine.java
@@ -21,13 +21,13 @@ package edu.umd.cs.findbugs.classfile;
/**
* An engine for analyzing classes or methods.
- *
+ *
* @author David Hovemeyer
*/
public interface IAnalysisEngine<DescriptorType, ResultType> {
/**
* Perform an analysis on class or method named by given descriptor.
- *
+ *
* @param analysisCache
* the analysis cache
* @param descriptor
@@ -38,7 +38,7 @@ public interface IAnalysisEngine<DescriptorType, ResultType> {
/**
* Register the analysis engine with given analysis cache.
- *
+ *
* @param analysisCache
* the analysis cache
*/
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IAnalysisEngineRegistrar.java b/src/java/edu/umd/cs/findbugs/classfile/IAnalysisEngineRegistrar.java
index 3b6ef7d..1487b20 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IAnalysisEngineRegistrar.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IAnalysisEngineRegistrar.java
@@ -22,13 +22,13 @@ package edu.umd.cs.findbugs.classfile;
/**
* Interface for a registrar class that registers analysis engines with an
* analysis cache.
- *
+ *
* @author David Hovemeyer
*/
public interface IAnalysisEngineRegistrar {
/**
* Register analysis engines with given analysis cache.
- *
+ *
* @param analysisCache
* the analysis cache
*/
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IClassAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/IClassAnalysisEngine.java
index 8fa1141..89b774c 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IClassAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IClassAnalysisEngine.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.classfile;
/**
* Engine for performing an analysis on classes.
- *
+ *
* @author David Hovemeyer
*/
public interface IClassAnalysisEngine<ResultType> extends IAnalysisEngine<ClassDescriptor, ResultType> {
@@ -31,7 +31,7 @@ public interface IClassAnalysisEngine<ResultType> extends IAnalysisEngine<ClassD
* recomputed. Unless some correctness criterion prevents analysis results
* from being recomputed, analysis engines should return true (allowing the
* cache to be kept to a manageable size).
- *
+ *
* @return true if analysis results produced by this engine can be
* recomputed, false if for some reason the analysis results must be
* retained indefinitely
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IClassObserver.java b/src/java/edu/umd/cs/findbugs/classfile/IClassObserver.java
index eb06c06..db4a9dd 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IClassObserver.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IClassObserver.java
@@ -23,13 +23,13 @@ package edu.umd.cs.findbugs.classfile;
* Observer for classes being visited in some manner. If the observe wishes to
* load the actual class data (or some analysis of the class) it must explicitly
* load it from the analysis cache.
- *
+ *
* @author David Hovemeyer
*/
public interface IClassObserver {
/**
* Observe a class being visited.
- *
+ *
* @param classDescriptor
* class being visited
*/
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IClassPathBuilder.java b/src/java/edu/umd/cs/findbugs/classfile/IClassPathBuilder.java
index 6b2711c..d01b9f4 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IClassPathBuilder.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IClassPathBuilder.java
@@ -29,13 +29,13 @@ import java.util.List;
* <li>Builds a list of application class descriptors</li>
* <li>Adds system codebases</li>
* </ul>
- *
+ *
* @author David Hovemeyer
*/
public interface IClassPathBuilder {
/**
* Add a project codebase.
- *
+ *
* @param locator
* locator for project codebase
* @param isApplication
@@ -47,7 +47,7 @@ public interface IClassPathBuilder {
/**
* Set whether or not nested archives should be scanned. This should be
* called before the build() method is called.
- *
+ *
* @param scanNestedArchives
* true if nested archives should be scanned, false otherwise
*/
@@ -55,7 +55,7 @@ public interface IClassPathBuilder {
/**
* Build the classpath.
- *
+ *
* @param classPath
* IClassPath object to build
* @param progress
@@ -65,12 +65,12 @@ public interface IClassPathBuilder {
* @throws InterruptedException
*/
public void build(IClassPath classPath, IClassPathBuilderProgress progress) throws CheckedAnalysisException, IOException,
- InterruptedException;
+ InterruptedException;
/**
* Get the list of application classes discovered while scanning the
* classpath.
- *
+ *
* @return list of application classes
*/
public List<ClassDescriptor> getAppClassList();
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IClassPathBuilderProgress.java b/src/java/edu/umd/cs/findbugs/classfile/IClassPathBuilderProgress.java
index c06611f..a20a8db 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IClassPathBuilderProgress.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IClassPathBuilderProgress.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.classfile;
/**
* Progress callback interface for classpath construction.
- *
+ *
* @author David Hovemeyer
*/
public interface IClassPathBuilderProgress {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/ICodeBase.java b/src/java/edu/umd/cs/findbugs/classfile/ICodeBase.java
index c8853cd..22e2922 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/ICodeBase.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/ICodeBase.java
@@ -22,11 +22,11 @@ package edu.umd.cs.findbugs.classfile;
/**
* Interface for a basic code base in which we can look up resources but not
* necessarily scan for the list of all resources.
- *
+ *
* @author David Hovemeyer
*/
public interface ICodeBase {
-
+
enum Discovered {
/** Codebase was explicitly specified. */
@@ -46,14 +46,14 @@ public interface ICodeBase {
}
/**
* Get the codebase locator describing the location of this codebase.
- *
+ *
* @return the ICodeBaseLocator
*/
public ICodeBaseLocator getCodeBaseLocator();
/**
* Look up a resource in this code base.
- *
+ *
* @param resourceName
* name of the resource to look up
* @return ICodeBaseEntry representing the resource or null if the resource
@@ -63,7 +63,7 @@ public interface ICodeBase {
/**
* Designate this code base as an application codebase.
- *
+ *
* @param isAppCodeBase
* true if this is an application codebase, false if not
*/
@@ -71,14 +71,14 @@ public interface ICodeBase {
/**
* Return whether or not this codebase is an application codebase.
- *
+ *
* @return true if this is an application codebase, false if not
*/
public boolean isApplicationCodeBase();
/**
* Set how this codebase was discovered.
- *
+ *
* @param howDiscovered
* one of the constants SPECIFIED, NESTED, IN_JAR_MANIFEST, or
* IN_SYSTEM_CLASSPATH
@@ -87,7 +87,7 @@ public interface ICodeBase {
/**
* Return how this codebase was discovered.
- *
+ *
* @return one of the constants SPECIFIED, NESTED, IN_JAR_MANIFEST, or
* IN_SYSTEM_CLASSPATH
*/
@@ -95,7 +95,7 @@ public interface ICodeBase {
/**
* Return whether or not this code base contains any source files.
- *
+ *
* @return true if the code base contains source file(s), false if it does
* not contain source files
*/
@@ -103,7 +103,7 @@ public interface ICodeBase {
/**
* Get the filesystem pathname of this codebase.
- *
+ *
* @return the filesystem pathname of this codebase, or null if this
* codebase is not accessible via the filesystem
*/
@@ -112,7 +112,7 @@ public interface ICodeBase {
/**
* Set timestamp indicating the most recent time when any of the files in
* the codebase were modified.
- *
+ *
* @param lastModifiedTime
* timestamp when any codebase files were most-recently modified
*/
@@ -123,7 +123,7 @@ public interface ICodeBase {
* the codebase were modified. This information is only likely to be
* accurate if an ICodeBaseIterator has been used to scan the resources in
* the codebase (scannable codebases only, obviously).
- *
+ *
* @return timestamp when any codebase files were most-recently modified, -1
* if unknown
*/
diff --git a/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseEntry.java b/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseEntry.java
index 9fc902a..7e3f0ab 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseEntry.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseEntry.java
@@ -24,13 +24,13 @@ import java.io.InputStream;
/**
* Object representing a resource in a code base.
- *
+ *
* @author David Hovemeyer
*/
public interface ICodeBaseEntry {
/**
* Get the name of the resource.
- *
+ *
* @return the name of the resource
*/
public String getResourceName();
@@ -38,14 +38,14 @@ public interface ICodeBaseEntry {
/**
* Get the number of bytes in the resource. Returns <0 if the number of
* bytes is not known.
- *
+ *
* @return number of bytes in the resource, or <0 if not known.
*/
public int getNumBytes();
/**
* Open an input stream reading from the resource.
- *
+ *
* @return InputStream reading from the resource.
* @throws IOException
* if an error occurs reading from the resource
@@ -54,7 +54,7 @@ public interface ICodeBaseEntry {
/**
* Get the codebase this codebase entry belongs to.
- *
+ *
* @return the codebase this codebase entry belongs to
*/
public ICodeBase getCodeBase();
@@ -64,7 +64,7 @@ public interface ICodeBaseEntry {
* codebase entry. Do not call this method unless
* ClassDescriptor.isClassResource() returns true. This method may require
* the class data to be loaded in order to determine the class.
- *
+ *
* @return ClassDescriptor of this entry
* @throws ResourceNotFoundException, InvalidClassFileFormatException
* if the codebase entry does not reference a valid classfile
@@ -76,7 +76,7 @@ public interface ICodeBaseEntry {
/**
* Override the resource name of this codebase entry.
- *
+ *
* @param resourceName
* the new resource name
*/
diff --git a/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseIterator.java b/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseIterator.java
index 250db6c..593cd35 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseIterator.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseIterator.java
@@ -23,25 +23,25 @@ package edu.umd.cs.findbugs.classfile;
* Iterator over the resources in an IScannableCodeBase. Note that some of the
* methods can throw InterruptedException. This occurs when the analysis is
* canceled by interrupting the analysis thread.
- *
+ *
* <p>
* Note that the close() method must be called when done with an
* ICodeBaseIterator object.
* </p>
- *
+ *
* @author David Hovemeyer
*/
public interface ICodeBaseIterator {
/**
* Return true if there is another resource to be scanned, false otherwise.
- *
+ *
* @return true if there is another resource to be scanned, false otherwise
*/
public boolean hasNext() throws InterruptedException;
/**
* Get the ICodeBaseEntry representing the next resource in the code base.
- *
+ *
* @return the ICodeBaseEntry representing the next resource in the code
* base
* @throws InterruptedException
diff --git a/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseLocator.java b/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseLocator.java
index d503c14..cb615eb 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseLocator.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/ICodeBaseLocator.java
@@ -23,13 +23,13 @@ import java.io.IOException;
/**
* Specify the location of a codebase.
- *
+ *
* @author David Hovemeyer
*/
public interface ICodeBaseLocator {
/**
* Get the codebase object.
- *
+ *
* @return the codebase object
*/
public ICodeBase openCodeBase() throws IOException, ResourceNotFoundException;
@@ -38,7 +38,7 @@ public interface ICodeBaseLocator {
* Get the codebase locator describing the location of a relative codebase.
* This method is useful for getting the location of a codebase referred to
* in the Class-Path attribute of a Jar manifest.
- *
+ *
* @param relativePath
* the path of a relative codebase
* @return codebase locator of the relative codebase whose path is given
@@ -50,8 +50,9 @@ public interface ICodeBaseLocator {
* codebase locators that refer to the same codebase should produce the same
* string representation. So, this string can serve as a key identifying the
* codebase in a map.
- *
+ *
* @return a string representation of the codebase
*/
+ @Override
public String toString();
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IDatabaseFactory.java b/src/java/edu/umd/cs/findbugs/classfile/IDatabaseFactory.java
index ebaed15..2b50b66 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IDatabaseFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IDatabaseFactory.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.classfile;
/**
* Interface for a database factory.
- *
+ *
* @author David Hovemeyer
*/
public interface IDatabaseFactory<T> {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IErrorLogger.java b/src/java/edu/umd/cs/findbugs/classfile/IErrorLogger.java
index 65c3d18..ec1095f 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IErrorLogger.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IErrorLogger.java
@@ -21,13 +21,13 @@ package edu.umd.cs.findbugs.classfile;
/**
* Interface for objects that log various kinds of analysis errors.
- *
+ *
* @author David Hovemeyer
*/
public interface IErrorLogger {
/**
* Called to report a class lookup failure.
- *
+ *
* @param ex
* a ClassNotFoundException resulting from the class lookup
* failure
@@ -36,7 +36,7 @@ public interface IErrorLogger {
/**
* Called to report a class lookup failure.
- *
+ *
* @param classDescriptor
* ClassDescriptor of a missing class
*/
@@ -44,7 +44,7 @@ public interface IErrorLogger {
/**
* Log an error that occurs while performing analysis.
- *
+ *
* @param message
* the error message
*/
@@ -52,7 +52,7 @@ public interface IErrorLogger {
/**
* Log an error that occurs while performing analysis.
- *
+ *
* @param message
* the error message
* @param e
@@ -62,7 +62,7 @@ public interface IErrorLogger {
/**
* Report that we skipped some analysis of a method
- *
+ *
* @param method
* the method we skipped
*/
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IMethodAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/IMethodAnalysisEngine.java
index a0d49c7..db7cff8 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IMethodAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IMethodAnalysisEngine.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.classfile;
/**
* Engine for performing an analysis on methods.
- *
+ *
* @author David Hovemeyer
*/
public interface IMethodAnalysisEngine<ResultType> extends IAnalysisEngine<MethodDescriptor, ResultType> {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/IScannableCodeBase.java b/src/java/edu/umd/cs/findbugs/classfile/IScannableCodeBase.java
index c1006de..52ae358 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/IScannableCodeBase.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/IScannableCodeBase.java
@@ -22,7 +22,7 @@ package edu.umd.cs.findbugs.classfile;
/**
* A scannable code base: in addition to looking up a named resource, scannable
* code bases can also enumerate the names of the resources they contain.
- *
+ *
* @author David Hovemeyer
*/
public interface IScannableCodeBase extends ICodeBase {
@@ -32,7 +32,7 @@ public interface IScannableCodeBase extends ICodeBase {
/**
* Get an iterator over the resources in the this code base.
- *
+ *
* @return ICodeBaseIterator over the resources in the code base
*/
public ICodeBaseIterator iterator() throws InterruptedException;
diff --git a/src/java/edu/umd/cs/findbugs/classfile/InvalidClassFileFormatException.java b/src/java/edu/umd/cs/findbugs/classfile/InvalidClassFileFormatException.java
index 242c52e..a6471e2 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/InvalidClassFileFormatException.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/InvalidClassFileFormatException.java
@@ -23,9 +23,9 @@ package edu.umd.cs.findbugs.classfile;
* @author David Hovemeyer
*/
public class InvalidClassFileFormatException extends CheckedAnalysisException {
- private ClassDescriptor classDescriptor;
+ private final ClassDescriptor classDescriptor;
- private ICodeBaseEntry codeBaseEntry;
+ private final ICodeBaseEntry codeBaseEntry;
public InvalidClassFileFormatException(ClassDescriptor classDescriptor, ICodeBaseEntry codeBaseEntry) {
super("Invalid classfile format");
@@ -62,7 +62,7 @@ public class InvalidClassFileFormatException extends CheckedAnalysisException {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Throwable#getMessage()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/classfile/MethodDescriptor.java b/src/java/edu/umd/cs/findbugs/classfile/MethodDescriptor.java
index d060dc0..4328928 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/MethodDescriptor.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/MethodDescriptor.java
@@ -19,19 +19,24 @@
package edu.umd.cs.findbugs.classfile;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.INVOKESTATIC;
+import org.apache.bcel.generic.InvokeInstruction;
+
import edu.umd.cs.findbugs.ba.ComparableMethod;
import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
+import edu.umd.cs.findbugs.util.ClassName;
/**
* Descriptor uniquely identifying a method in a class.
- *
+ *
* @author David Hovemeyer
*/
public class MethodDescriptor extends FieldOrMethodDescriptor implements ComparableMethod {
/**
* Constructor.
- *
+ *
* @param className
* name of the class containing the method, in VM format (e.g.,
* "java/lang/String")
@@ -46,10 +51,19 @@ public class MethodDescriptor extends FieldOrMethodDescriptor implements Compara
super(className, methodName, methodSignature, isStatic);
}
+ public MethodDescriptor(@SlashedClassName String className, String methodName, String methodSignature) {
+ super(className, methodName, methodSignature, false);
+ }
+
+ public MethodDescriptor(InvokeInstruction iins, ConstantPoolGen cpg) {
+ super(ClassName.toSlashedClassName(iins.getClassName(cpg)), iins.getMethodName(cpg), iins.getSignature(cpg), iins instanceof INVOKESTATIC);
+ }
+
+ @Override
public int compareTo(ComparableMethod o) {
return FieldOrMethodDescriptor.compareTo(this, (MethodDescriptor)o);
}
-
+
@Override
public final boolean equals(Object obj) {
if (obj instanceof MethodDescriptor) {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/MissingClassException.java b/src/java/edu/umd/cs/findbugs/classfile/MissingClassException.java
index d55cb85..4b87ae5 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/MissingClassException.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/MissingClassException.java
@@ -22,15 +22,15 @@ package edu.umd.cs.findbugs.classfile;
/**
* CheckedAnalysisException subtype to indicate that a required class was
* missing.
- *
+ *
* @author David Hovemeyer
*/
public class MissingClassException extends ResourceNotFoundException {
- private ClassDescriptor classDescriptor;
+ private final ClassDescriptor classDescriptor;
/**
* Constructor.
- *
+ *
* @param classDescriptor
* missing class
*/
@@ -41,7 +41,7 @@ public class MissingClassException extends ResourceNotFoundException {
/**
* Constructor.
- *
+ *
* @param classDescriptor
* missing class
* @param cause
diff --git a/src/java/edu/umd/cs/findbugs/classfile/RecomputableClassAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/RecomputableClassAnalysisEngine.java
index 967ad78..d894b22 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/RecomputableClassAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/RecomputableClassAnalysisEngine.java
@@ -24,6 +24,7 @@ package edu.umd.cs.findbugs.classfile;
*/
public abstract class RecomputableClassAnalysisEngine<ResultType> implements IClassAnalysisEngine<ResultType> {
+ @Override
public boolean canRecompute() {
// can be recomputed
return true;
diff --git a/src/java/edu/umd/cs/findbugs/classfile/ReflectionDatabaseFactory.java b/src/java/edu/umd/cs/findbugs/classfile/ReflectionDatabaseFactory.java
index 38655aa..0bfa6a5 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/ReflectionDatabaseFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/ReflectionDatabaseFactory.java
@@ -27,16 +27,16 @@ import java.lang.reflect.Modifier;
/**
* A generic database factory that tries to create the database by (in order of
* preference)
- *
+ *
* <ol>
* <li>Invoking a static <b>create</b> method</li>
* <li>Invoking a no-arg constructor
* </ol>
- *
+ *
* @author David Hovemeyer
*/
public class ReflectionDatabaseFactory<E> implements IDatabaseFactory<E> {
- private Class<E> databaseClass;
+ private final Class<E> databaseClass;
public ReflectionDatabaseFactory(Class<E> databaseClass) {
this.databaseClass = databaseClass;
@@ -44,9 +44,10 @@ public class ReflectionDatabaseFactory<E> implements IDatabaseFactory<E> {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.IDatabaseFactory#createDatabase()
*/
+ @Override
public E createDatabase() throws CheckedAnalysisException {
E database;
@@ -65,7 +66,7 @@ public class ReflectionDatabaseFactory<E> implements IDatabaseFactory<E> {
/**
* Try to create the database using a static create() method.
- *
+ *
* @return the database, or null if there is no static create() method
* @throws CheckedAnalysisException
*/
@@ -96,7 +97,7 @@ public class ReflectionDatabaseFactory<E> implements IDatabaseFactory<E> {
/**
* Try to create the database using a no-arg constructor.
- *
+ *
* @return the database, or null if there is no no-arg constructor
* @throws CheckedAnalysisException
*/
@@ -121,11 +122,12 @@ public class ReflectionDatabaseFactory<E> implements IDatabaseFactory<E> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IDatabaseFactory#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerDatabaseFactory(databaseClass, this);
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/ResourceNotFoundException.java b/src/java/edu/umd/cs/findbugs/classfile/ResourceNotFoundException.java
index 64bdc1a..7e81110 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/ResourceNotFoundException.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/ResourceNotFoundException.java
@@ -21,17 +21,17 @@ package edu.umd.cs.findbugs.classfile;
/**
* Exception to indicate that a resource was not found.
- *
+ *
* @author David Hovemeyer
*/
public class ResourceNotFoundException extends CheckedAnalysisException {
- private String resourceName;
+ private final String resourceName;
public static final String MESSAGE_PREFIX = "Resource not found: ";
/**
* Constructor.
- *
+ *
* @param resourceName
* name of the missing resource
*/
@@ -42,7 +42,7 @@ public class ResourceNotFoundException extends CheckedAnalysisException {
/**
* Constructor.
- *
+ *
* @param resourceName
* name of the missing resource
* @param cause
@@ -55,7 +55,7 @@ public class ResourceNotFoundException extends CheckedAnalysisException {
/**
* Get the name of the resource that was not found.
- *
+ *
* @return the name of the resource that was not found
*/
public String getResourceName() {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/UncheckedAnalysisException.java b/src/java/edu/umd/cs/findbugs/classfile/UncheckedAnalysisException.java
index 0f6e6a8..674ad95 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/UncheckedAnalysisException.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/UncheckedAnalysisException.java
@@ -21,13 +21,13 @@ package edu.umd.cs.findbugs.classfile;
/**
* Common base class for unchecked analysis exceptions.
- *
+ *
* @author David Hovemeyer
*/
public class UncheckedAnalysisException extends RuntimeException {
/**
* Constructor.
- *
+ *
* @param message
* message describing the exception
*/
@@ -37,7 +37,7 @@ public class UncheckedAnalysisException extends RuntimeException {
/**
* Constructor.
- *
+ *
* @param message
* message describing the exception
* @param cause
diff --git a/src/java/edu/umd/cs/findbugs/classfile/analysis/AnnotationValue.java b/src/java/edu/umd/cs/findbugs/classfile/analysis/AnnotationValue.java
index 2914348..f5ed221 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/analysis/AnnotationValue.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/analysis/AnnotationValue.java
@@ -28,22 +28,23 @@ import org.objectweb.asm.AnnotationVisitor;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.DescriptorFactory;
+import edu.umd.cs.findbugs.classfile.engine.asm.FindBugsASM;
/**
* The "raw" version of an annotation appearing in a class file.
- *
+ *
* @author William Pugh
*/
public class AnnotationValue {
private final ClassDescriptor annotationClass;
- private Map<String, Object> valueMap = new HashMap<String, Object>(4);
+ private final Map<String, Object> valueMap = new HashMap<String, Object>(4);
- private Map<String, Object> typeMap = new HashMap<String, Object>(4);
+ private final Map<String, Object> typeMap = new HashMap<String, Object>(4);
/**
* Constructor.
- *
+ *
* @param annotationClass
* the annotation class
*/
@@ -53,7 +54,7 @@ public class AnnotationValue {
/**
* Constructor.
- *
+ *
* @param annotationClass
* JVM signature of the annotation class
*/
@@ -73,7 +74,7 @@ public class AnnotationValue {
* "http://asm.objectweb.org/current/doc/javadoc/user/org/objectweb/asm/AnnotationVisitor.html"
* >AnnotationVisitor Javadoc</a> for information on what the object
* returned could be.
- *
+ *
* @param name
* name of annotation element
* @return the element value (primitive value, String value, enum value,
@@ -85,7 +86,7 @@ public class AnnotationValue {
/**
* Get a descriptor specifying the type of an annotation element.
- *
+ *
* @param name
* name of annotation element
* @return descriptor specifying the type of the annotation element
@@ -100,8 +101,9 @@ public class AnnotationValue {
}
private static String canonicalString(String s) {
- if (s.equals("value"))
+ if ("value".equals(s)) {
return "value";
+ }
return s;
}
@@ -109,7 +111,8 @@ public class AnnotationValue {
* Get an AnnotationVisitor which can populate this AnnotationValue object.
*/
public AnnotationVisitor getAnnotationVisitor() {
- return new AnnotationVisitor() {
+ return new AnnotationVisitor(FindBugsASM.ASM_VERSION) {
+ @Override
public void visit(String name, Object value) {
name = canonicalString(name);
valueMap.put(name, value);
@@ -117,11 +120,12 @@ public class AnnotationValue {
/*
* (non-Javadoc)
- *
+ *
* @see
* org.objectweb.asm.AnnotationVisitor#visitAnnotation(java.lang
* .String, java.lang.String)
*/
+ @Override
public AnnotationVisitor visitAnnotation(String name, String desc) {
name = canonicalString(name);
AnnotationValue newValue = new AnnotationValue(desc);
@@ -132,10 +136,11 @@ public class AnnotationValue {
/*
* (non-Javadoc)
- *
+ *
* @see
* org.objectweb.asm.AnnotationVisitor#visitArray(java.lang.String)
*/
+ @Override
public AnnotationVisitor visitArray(String name) {
name = canonicalString(name);
return new AnnotationArrayVisitor(name);
@@ -143,20 +148,22 @@ public class AnnotationValue {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.AnnotationVisitor#visitEnd()
*/
+ @Override
public void visitEnd() {
}
/*
* (non-Javadoc)
- *
+ *
* @see
* org.objectweb.asm.AnnotationVisitor#visitEnum(java.lang.String,
* java.lang.String, java.lang.String)
*/
+ @Override
public void visitEnum(String name, String desc, String value) {
name = canonicalString(name);
valueMap.put(name, new EnumValue(desc, value));
@@ -166,7 +173,7 @@ public class AnnotationValue {
};
}
- private final class AnnotationArrayVisitor implements AnnotationVisitor {
+ private final class AnnotationArrayVisitor extends AnnotationVisitor {
/**
*
*/
@@ -184,37 +191,45 @@ public class AnnotationValue {
* @param result
*/
private AnnotationArrayVisitor(String name) {
+ super(FindBugsASM.ASM_VERSION);
name = canonicalString(name);
this.name = name;
this.outerList = null;
}
private AnnotationArrayVisitor(List<Object> outerList) {
+ super(FindBugsASM.ASM_VERSION);
this.name = null;
this.outerList = outerList;
}
+ @Override
public void visit(String name, Object value) {
result.add(value);
}
+ @Override
public AnnotationVisitor visitAnnotation(String name, String desc) {
AnnotationValue newValue = new AnnotationValue(desc);
result.add(newValue);
return newValue.getAnnotationVisitor();
}
+ @Override
public AnnotationVisitor visitArray(String name) {
return new AnnotationArrayVisitor(result);
}
+ @Override
public void visitEnd() {
- if (name != null)
+ if (name != null) {
valueMap.put(name, result.toArray());
- else
+ } else {
outerList.add(result.toArray());
+ }
}
+ @Override
public void visitEnum(String name, String desc, String value) {
result.add(new EnumValue(desc, value));
diff --git a/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassData.java b/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassData.java
index b74948e..4f61ef0 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassData.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassData.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.classfile.ICodeBaseEntry;
/**
* The data (bytes) of a class.
- *
+ *
* @author David Hovemeyer
*/
public class ClassData {
@@ -39,7 +39,7 @@ public class ClassData {
/**
* Constructor.
- *
+ *
* @param classDescriptor
* descriptor for the class
* @param data
@@ -74,14 +74,14 @@ public class ClassData {
/**
* Open an InputStream on the class data.
- *
+ *
* @return InputStream reading from the class data
*/
public InputStream getInputStream() {
return new ByteArrayInputStream(data);
}
-
+
@Override
public String toString() {
return codeBaseEntry + ":" + classDescriptor;
diff --git a/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassInfo.java b/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassInfo.java
index 3d35091..ccf78ed 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassInfo.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassInfo.java
@@ -31,6 +31,7 @@ import java.util.Set;
import javax.annotation.CheckForNull;
+import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.XClass;
import edu.umd.cs.findbugs.ba.XField;
@@ -54,7 +55,9 @@ import edu.umd.cs.findbugs.util.Util;
*
* @author David Hovemeyer
*/
-public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, AnnotatedObject {
+public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass {
+
+ private final static boolean DEBUG = SystemProperties.getBoolean("ci.debug");
private final FieldInfo[] xFields;
private final MethodInfo[] xMethods;
@@ -73,6 +76,11 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
private final boolean hasStubs;
+ @CheckForNull
+ AnnotatedObject containingScope;
+
+ private boolean containingScopeCached;
+
public static class Builder extends ClassNameAndSuperclassInfo.Builder {
private List<FieldInfo> fieldInfoList = new LinkedList<FieldInfo>();
@@ -95,31 +103,78 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
boolean hasStubs;
+ private static String arguments(String signature) {
+ int i = signature.indexOf('(');
+ if (i == -1) {
+ return signature;
+ }
+ return signature.substring(0,i+1);
+ }
+
@Override
public ClassInfo build() {
AnalysisContext context = AnalysisContext.currentAnalysisContext();
FieldInfo fields[];
MethodInfo methods[];
- if (fieldInfoList.size() == 0)
+ if (fieldInfoList.size() == 0) {
fields = FieldInfo.EMPTY_ARRAY;
- else
+ } else {
fields = fieldInfoList.toArray(new FieldInfo[fieldInfoList.size()]);
+ }
+
+
+ for(MethodInfo m : methodInfoList) {
+ if (m.isBridge() && !bridgedSignatures.containsKey(m)) {
+
+ if (DEBUG) {
+ System.out.println("Have bridge method:" + m);
+ }
+ for(MethodInfo to : methodInfoList) {
+ if (m != to) {
+ if (!to.isBridge()
+ && m.getName().equals(to.getName())
+ && arguments( m.getSignature()).equals(arguments(to.getSignature()))) {
+ if (DEBUG) {
+ System.out.println(" to method:" + to);
+ }
+ bridgedSignatures.put(m, to.getSignature());
+ }
+
+ }
+ } // end for(MethodInfo to
+ } // end if (m.isBridge()
+ } // end for(MethodInfo m : methodInfoList)
+
+
for (Map.Entry<MethodInfo, String> e : bridgedSignatures.entrySet()) {
MethodInfo method = e.getKey();
String signature = e.getValue();
- for (MethodInfo m : methodInfoList)
+ for (MethodInfo m : methodInfoList) {
if (m.getName().equals(method.getName()) && m.getSignature().equals(signature)) {
+ if (DEBUG) {
+ System.out.println("Found bridge method:");
+ System.out.println(" " + method);
+ if (!method.getAnnotations().isEmpty()) {
+ System.out.println(" " + method.getAnnotations());
+ }
+ System.out.println(" " + m);
+ if (!m.getAnnotations().isEmpty()) {
+ System.out.println(" " + m.getAnnotations());
+ }
+ }
context.setBridgeMethod(method, m);
}
+ }
- }
+ } // end for
- if (methodInfoList.size() == 0)
+ if (methodInfoList.size() == 0) {
methods = MethodInfo.EMPTY_ARRAY;
- else
+ } else {
methods = methodInfoList.toArray(new MethodInfo[methodInfoList.size()]);
+ }
return new ClassInfo(classDescriptor, classSourceSignature, superclassDescriptor, interfaceDescriptorList,
codeBaseEntry, accessFlags, source, majorVersion, minorVersion, referencedClassDescriptorList,
@@ -131,9 +186,6 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
this.source = source;
}
- /**
- * @return Returns the classDescriptor.
- */
public ClassDescriptor getClassDescriptor() {
return classDescriptor;
}
@@ -147,10 +199,6 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
classAnnotations.put(annotationClass, value);
}
- /**
- * @param fieldDescriptorList
- * The fieldDescriptorList to set.
- */
public void setFieldDescriptorList(FieldInfo[] fieldDescriptorList) {
this.fieldInfoList = Arrays.asList(fieldDescriptorList);
}
@@ -159,10 +207,6 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
fieldInfoList.add(field);
}
- /**
- * @param methodDescriptorList
- * The methodDescriptorList to set.
- */
public void setMethodDescriptorList(MethodInfo[] methodDescriptorList) {
this.methodInfoList = Arrays.asList(methodDescriptorList);
}
@@ -171,17 +215,13 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
methodInfoList.add(method);
}
- public void addBridgeMethodDescriptor(MethodInfo method, String bridgedSignature) {
+ public void addBridgeMethodDescriptor(MethodInfo from, String bridgedSignature) {
if (bridgedSignature != null) {
- bridgedSignatures.put(method, bridgedSignature);
+ bridgedSignatures.put(from, bridgedSignature);
}
- addMethodDescriptor(method);
+ addMethodDescriptor(from);
}
- /**
- * @param immediateEnclosingClass
- * The immediateEnclosingClass to set.
- */
public void setImmediateEnclosingClass(ClassDescriptor immediateEnclosingClass) {
this.immediateEnclosingClass = immediateEnclosingClass;
}
@@ -205,10 +245,12 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
final MultiMap<MethodInfo, MethodInfo> multiMap = SelfMethodCalls.getSelfCalls(getClassDescriptor(), map);
OutEdges2<MethodInfo> edges1 = new OutEdges2<MethodInfo>() {
+ @Override
public Collection<MethodInfo> getOutEdges(MethodInfo method) {
return multiMap.get(method);
}
+ @Override
public int score(MethodInfo e) {
return e.getMethodCallCount();
}
@@ -233,16 +275,10 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
* @param referencedClassDescriptorList
* ClassDescriptors of all classes/interfaces referenced by the
* class
- * @param calledClassDescriptors
- * TODO
* @param fieldDescriptorList
* FieldDescriptors of fields defined in the class
* @param methodInfoList
* MethodDescriptors of methods defined in the class
- * @param usesConcurrency
- * TODO
- * @param hasStubs
- * TODO
*/
private ClassInfo(ClassDescriptor classDescriptor, String classSourceSignature, ClassDescriptor superclassDescriptor,
ClassDescriptor[] interfaceDescriptorList, ICodeBaseEntry codeBaseEntry, int accessFlags, String source,
@@ -254,8 +290,9 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
referencedClassDescriptorList, calledClassDescriptors, majorVersion, minorVersion);
this.source = source;
this.classSourceSignature = classSourceSignature;
- if (fieldDescriptorList.length == 0)
+ if (fieldDescriptorList.length == 0) {
fieldDescriptorList = FieldInfo.EMPTY_ARRAY;
+ }
this.xFields = fieldDescriptorList;
this.xMethods = methodInfoList;
this.immediateEnclosingClass = immediateEnclosingClass;
@@ -263,6 +300,7 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
this.usesConcurrency = usesConcurrency;
this.hasStubs = hasStubs;
this.methodsInCallOrder = computeMethodsInCallOrder();
+ /*
if (false) {
System.out.println("Methods in call order for " + classDescriptor);
for (MethodInfo m : methodsInCallOrder) {
@@ -270,51 +308,36 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
}
System.out.println();
}
+ */
}
- /**
- * @return Returns the fieldDescriptorList.
- */
+ @Override
public List<? extends XField> getXFields() {
return Arrays.asList(xFields);
}
- /**
- * @return Returns the methodDescriptorList.
- */
+ @Override
public List<? extends XMethod> getXMethods() {
return Arrays.asList(xMethods);
}
- /**
- * @return Returns the methodDescriptorList.
- */
public List<? extends XMethod> getXMethodsInCallOrder() {
return Arrays.asList(methodsInCallOrder);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.XClass#findMethod(java.lang.String,
- * java.lang.String, boolean)
- */
+ @Override
public XMethod findMethod(String methodName, String methodSig, boolean isStatic) {
int hash = FieldOrMethodDescriptor.getNameSigHashCode(methodName, methodSig);
- for (MethodInfo mInfo : xMethods)
+ for (MethodInfo mInfo : xMethods) {
if (mInfo.getNameSigHashCode() == hash && mInfo.getName().equals(methodName)
- && mInfo.getSignature().equals(methodSig) && mInfo.isStatic() == isStatic)
+ && mInfo.getSignature().equals(methodSig) && mInfo.isStatic() == isStatic) {
return mInfo;
+ }
+ }
return null;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.XClass#findMethod(edu.umd.cs.findbugs.classfile
- * .MethodDescriptor)
- */
+ @Override
public XMethod findMethod(MethodDescriptor descriptor) {
if (!descriptor.getClassDescriptor().equals(this)) {
throw new IllegalArgumentException();
@@ -322,37 +345,39 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
return findMatchingMethod(descriptor);
}
+ @Override
public XMethod findMatchingMethod(MethodDescriptor descriptor) {
return findMethod(descriptor.getName(), descriptor.getSignature(), descriptor.isStatic());
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.XClass#findField(java.lang.String,
- * java.lang.String, boolean)
- */
+ @Override
public XField findField(String name, String signature, boolean isStatic) {
int hash = FieldOrMethodDescriptor.getNameSigHashCode(name, signature);
- for (FieldInfo fInfo : xFields)
+ for (FieldInfo fInfo : xFields) {
if (fInfo.getNameSigHashCode() == hash && fInfo.getName().equals(name) && fInfo.getSignature().equals(signature)
- && fInfo.isStatic() == isStatic)
+ && fInfo.isStatic() == isStatic) {
return fInfo;
+ }
+ }
try {
- if (getSuperclassDescriptor() == null)
+ if (getSuperclassDescriptor() == null) {
return null;
+ }
XClass superClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, getSuperclassDescriptor());
XField result = superClass.findField(name, signature, isStatic);
- if (result != null)
+ if (result != null) {
return result;
- if (!isStatic)
+ }
+ if (!isStatic) {
return null;
+ }
ClassDescriptor[] interfaces = getInterfaceDescriptorList();
for (ClassDescriptor implementedInterface : interfaces) {
superClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, implementedInterface);
result = superClass.findField(name, signature, isStatic);
- if (result != null)
+ if (result != null) {
return result;
+ }
}
return null;
} catch (CheckedAnalysisException e) {
@@ -360,18 +385,11 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
}
}
- /**
- * @return Returns the immediateEnclosingClass.
- */
+ @Override
public ClassDescriptor getImmediateEnclosingClass() {
return immediateEnclosingClass;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.AccessibleEntity#getPackageName()
- */
@Override
public String getPackageName() {
String dottedClassName = getClassDescriptor().toDottedClassName();
@@ -383,12 +401,6 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
}
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.AccessibleEntity#getPackageName()
- */
-
public String getSlashedPackageName() {
String slashedClassName = getClassDescriptor().getClassName();
int lastSlash = slashedClassName.lastIndexOf('/');
@@ -399,14 +411,17 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
}
}
+ @Override
public Collection<ClassDescriptor> getAnnotationDescriptors() {
return classAnnotations.keySet();
}
+ @Override
public Collection<AnnotationValue> getAnnotations() {
return classAnnotations.values();
}
+ @Override
public AnnotationValue getAnnotation(ClassDescriptor desc) {
return classAnnotations.get(desc);
}
@@ -428,25 +443,24 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
classAnnotations = Util.immutableMap(updatedMap);
}
+ @Override
public ElementType getElementType() {
- if (getClassName().endsWith("package-info"))
+ if (getClassName().endsWith("package-info")) {
return ElementType.PACKAGE;
- else if (isAnnotation())
+ } else if (isAnnotation()) {
return ElementType.ANNOTATION_TYPE;
+ }
return ElementType.TYPE;
}
+ @Override
public @CheckForNull
String getSource() {
return source;
}
- @CheckForNull
- AnnotatedObject containingScope;
-
- private boolean containingScopeCached = false;
-
+ @Override
public @CheckForNull
AnnotatedObject getContainingScope() {
if (!containingScopeCached) {
@@ -472,19 +486,17 @@ public class ClassInfo extends ClassNameAndSuperclassInfo implements XClass, Ann
}
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.XClass#getSourceSignature()
- */
+ @Override
public String getSourceSignature() {
return classSourceSignature;
}
+ @Override
public boolean usesConcurrency() {
return usesConcurrency;
}
+ @Override
public boolean hasStubs() {
return hasStubs;
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassNameAndSuperclassInfo.java b/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassNameAndSuperclassInfo.java
index 566b95c..094506e 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassNameAndSuperclassInfo.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/analysis/ClassNameAndSuperclassInfo.java
@@ -123,17 +123,19 @@ public class ClassNameAndSuperclassInfo extends ClassDescriptor {
* The referencedClassDescriptorList to set.
*/
public void setReferencedClassDescriptors(Collection<ClassDescriptor> referencedClassDescriptorList) {
- if (referencedClassDescriptorList.size() == 0)
+ if (referencedClassDescriptorList.size() == 0) {
this.referencedClassDescriptorList = Collections.emptyList();
- else
+ } else {
this.referencedClassDescriptorList = new ArrayList<ClassDescriptor>(referencedClassDescriptorList);
+ }
}
public void setCalledClassDescriptors(Collection<ClassDescriptor> calledClassDescriptorList) {
- if (calledClassDescriptorList.size() == 0)
+ if (calledClassDescriptorList.size() == 0) {
this.calledClassDescriptors = Collections.emptySet();
- else
+ } else {
this.calledClassDescriptors = new HashSet<ClassDescriptor>(calledClassDescriptorList);
+ }
}
}
@@ -148,8 +150,9 @@ public class ClassNameAndSuperclassInfo extends ClassDescriptor {
this.interfaceDescriptorList = interfaceDescriptorList;
this.codeBaseEntry = codeBaseEntry;
this.accessFlags = accessFlags;
- if (calledClassDescriptors == null)
+ if (calledClassDescriptors == null) {
throw new NullPointerException("calledClassDescriptors must not be null");
+ }
this.calledClassDescriptors = calledClassDescriptors;
this.majorVersion = majorVersion;
this.minorVersion = minorVersion;
diff --git a/src/java/edu/umd/cs/findbugs/classfile/analysis/EnumValue.java b/src/java/edu/umd/cs/findbugs/classfile/analysis/EnumValue.java
index cb39a11..08e9ea0 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/analysis/EnumValue.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/analysis/EnumValue.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.classfile.DescriptorFactory;
/**
* Represents an enumeration value used with an application of an annotation.
- *
+ *
* @author William Pugh
* @author David Hovemeyer
*/
diff --git a/src/java/edu/umd/cs/findbugs/classfile/analysis/FieldInfo.java b/src/java/edu/umd/cs/findbugs/classfile/analysis/FieldInfo.java
index 3772f55..b975f57 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/analysis/FieldInfo.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/analysis/FieldInfo.java
@@ -119,27 +119,31 @@ public class FieldInfo extends FieldDescriptor implements XField {
return checkFlag(Constants.ACC_SYNCHRONIZED);
}
+ @Override
public boolean isDeprecated() {
return checkFlag(Opcodes.ACC_DEPRECATED);
}
+ @Override
public @DottedClassName
String getClassName() {
return getClassDescriptor().toDottedClassName();
}
+ @Override
public @DottedClassName
String getPackageName() {
return getClassDescriptor().getPackageName();
}
+ @Override
public String getSourceSignature() {
return fieldSourceSignature;
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
@@ -157,88 +161,100 @@ public class FieldInfo extends FieldDescriptor implements XField {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#getAccessFlags()
*/
+ @Override
public int getAccessFlags() {
return accessFlags;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isFinal()
*/
+ @Override
public boolean isFinal() {
return checkFlag(Constants.ACC_FINAL);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isPrivate()
*/
+ @Override
public boolean isPrivate() {
return checkFlag(Constants.ACC_PRIVATE);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isProtected()
*/
+ @Override
public boolean isProtected() {
return checkFlag(Constants.ACC_PROTECTED);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isPublic()
*/
+ @Override
public boolean isPublic() {
return checkFlag(Constants.ACC_PUBLIC);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isResolved()
*/
+ @Override
public boolean isResolved() {
return this.isResolved;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.XField#isReferenceType()
*/
+ @Override
public boolean isReferenceType() {
return getSignature().startsWith("L") || getSignature().startsWith("[");
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.XField#isVolatile()
*/
+ @Override
public boolean isVolatile() {
return checkFlag(Constants.ACC_VOLATILE);
}
+ @Override
public boolean isSynthetic() {
return checkFlag(Constants.ACC_SYNTHETIC);
}
+ @Override
public Collection<ClassDescriptor> getAnnotationDescriptors() {
return fieldAnnotations.keySet();
}
+ @Override
public AnnotationValue getAnnotation(ClassDescriptor desc) {
return fieldAnnotations.get(desc);
}
+ @Override
public Collection<AnnotationValue> getAnnotations() {
return fieldAnnotations.values();
}
@@ -248,7 +264,7 @@ public class FieldInfo extends FieldDescriptor implements XField {
* that might not be directly evident in the code. It's not a great idea in
* general, but we can get away with it as long as it's done early enough
* (i.e., before anyone asks what annotations this field has.)
- *
+ *
* @param annotationValue
* an AnnotationValue representing a field annotation
*/
@@ -262,9 +278,10 @@ public class FieldInfo extends FieldDescriptor implements XField {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.ba.XField#getFieldDescriptor()
*/
+ @Override
public FieldDescriptor getFieldDescriptor() {
return this;
}
@@ -272,7 +289,7 @@ public class FieldInfo extends FieldDescriptor implements XField {
/**
* Create a FieldInfo object to represent an unresolved field.
* <em>Don't call this directly - use XFactory instead.</em>
- *
+ *
* @param className
* name of class containing the field
* @param name
@@ -286,17 +303,19 @@ public class FieldInfo extends FieldDescriptor implements XField {
public static FieldInfo createUnresolvedFieldInfo(String className, String name, String signature, boolean isStatic) {
className = ClassName.toSlashedClassName(className);
return new FieldInfo(className, name, signature, null, // without seeing
- // the definition
- // we don't know
- // if it has a
- // generic type
+ // the definition
+ // we don't know
+ // if it has a
+ // generic type
isStatic ? Constants.ACC_STATIC : 0, new HashMap<ClassDescriptor, AnnotationValue>(), false);
}
+ @Override
public ElementType getElementType() {
return ElementType.FIELD;
}
+ @Override
public @CheckForNull
AnnotatedObject getContainingScope() {
try {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/analysis/MethodInfo.java b/src/java/edu/umd/cs/findbugs/classfile/analysis/MethodInfo.java
index 616867d..d9626c2 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/analysis/MethodInfo.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/analysis/MethodInfo.java
@@ -58,8 +58,9 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
public static final MethodInfo[] EMPTY_ARRAY = new MethodInfo[0];
public static MethodInfo[] newArray(int sz) {
- if (sz == 0)
+ if (sz == 0) {
return EMPTY_ARRAY;
+ }
return new MethodInfo[sz];
}
@@ -90,6 +91,8 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
boolean isIdentity;
+ boolean usesInvokeDynamic;
+
int methodCallCount;
MethodDescriptor accessMethodForMethod;
@@ -100,6 +103,10 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
final Map<Integer, Map<ClassDescriptor, AnnotationValue>> methodParameterAnnotations = new HashMap<Integer, Map<ClassDescriptor, AnnotationValue>>(
4);
+ @Override
+ public String toString() {
+ return "builder for " + className + "." + methodName + methodSignature;
+ }
public Builder(@SlashedClassName String className, String methodName, String methodSignature, int accessFlags) {
this.className = className;
this.methodName = methodName;
@@ -119,13 +126,15 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
}
public void setVariableHasName(int p) {
- if (p < 64)
+ if (p < 64) {
variableHasName |= 1 << p;
+ }
}
public void setVariableIsSynthetic(int p) {
- if (p < 64)
+ if (p < 64) {
variableIsSynthetic |= 1 << p;
+ }
}
public void setUsesConcurrency() {
@@ -177,12 +186,13 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
}
public MethodInfo build() {
- if (variableHasName != 0)
+ if (variableHasName != 0) {
variableIsSynthetic |= (~variableHasName);
+ }
return new MethodInfo(className, methodName, methodSignature, methodSourceSignature, accessFlags,
isUnconditionalThrower, isUnsupported, usesConcurrency, hasBackBranch, isStub, isIdentity,
- methodCallCount, exceptions, accessMethodForMethod, accessMethodForField,
- methodAnnotations, methodParameterAnnotations, variableIsSynthetic);
+ usesInvokeDynamic, methodCallCount, exceptions, accessMethodForMethod,
+ accessMethodForField, methodAnnotations, methodParameterAnnotations, variableIsSynthetic);
}
public void setIsUnconditionalThrower() {
@@ -202,6 +212,13 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
this.methodCallCount = methodCallCount;
}
+
+ /**
+ *
+ */
+ public void setUsesInvokeDynamic() {
+ usesInvokeDynamic = true;
+ }
}
final int accessFlags;
@@ -226,15 +243,16 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
Map<Integer, Map<ClassDescriptor, AnnotationValue>> methodParameterAnnotations;
public static class MethodInfoDatabase {
- final IdentityHashMap<MethodInfo, Void> unconditionalThrowers = new IdentityHashMap<MethodInfo, Void>();
- final IdentityHashMap<MethodInfo, Void> unsupportedMethods = new IdentityHashMap<MethodInfo, Void>();
- final IdentityHashMap<MethodInfo, MethodDescriptor> accessMethodForMethod = new IdentityHashMap<MethodInfo, MethodDescriptor>();
- final IdentityHashMap<MethodInfo, FieldDescriptor> accessMethodForField = new IdentityHashMap<MethodInfo, FieldDescriptor>();
- final IdentityHashMap<MethodInfo, Void> identityMethods = new IdentityHashMap<MethodInfo, Void>();
+ final IdentityHashMap<MethodInfo, Void> unconditionalThrowers = new IdentityHashMap<MethodInfo, Void>();
+ final IdentityHashMap<MethodInfo, Void> unsupportedMethods = new IdentityHashMap<MethodInfo, Void>();
+ final IdentityHashMap<MethodInfo, MethodDescriptor> accessMethodForMethod = new IdentityHashMap<MethodInfo, MethodDescriptor>();
+ final IdentityHashMap<MethodInfo, FieldDescriptor> accessMethodForField = new IdentityHashMap<MethodInfo, FieldDescriptor>();
+ final IdentityHashMap<MethodInfo, Void> identityMethods = new IdentityHashMap<MethodInfo, Void>();
+ final IdentityHashMap<MethodInfo, Void> invokeDynamicMethods = new IdentityHashMap<MethodInfo, Void>();
}
- /**
+ /**
* @return Returns the database.
*/
static MethodInfoDatabase getDatabase() {
@@ -259,34 +277,46 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
static IdentityHashMap<MethodInfo, Void> getIdentitymethods() {
return getDatabase().identityMethods;
}
+ static public IdentityHashMap<MethodInfo, Void> getInvokeDynamicMethods() {
+ return getDatabase().invokeDynamicMethods;
+ }
MethodInfo(@SlashedClassName String className, String methodName, String methodSignature, String methodSourceSignature,
int accessFlags, boolean isUnconditionalThrower, boolean isUnsupported, boolean usesConcurrency,
boolean hasBackBranch, boolean isStub, boolean isIdentity,
- int methodCallCount, @CheckForNull String[] exceptions, @CheckForNull MethodDescriptor accessMethodForMethod,
+ boolean usesInvokeDynamic, int methodCallCount, @CheckForNull String[] exceptions,
+ @CheckForNull MethodDescriptor accessMethodForMethod,
@CheckForNull FieldDescriptor accessMethodForField,
- Map<ClassDescriptor, AnnotationValue> methodAnnotations,
- Map<Integer, Map<ClassDescriptor, AnnotationValue>> methodParameterAnnotations, long variableIsSynthetic) {
+ Map<ClassDescriptor, AnnotationValue> methodAnnotations, Map<Integer, Map<ClassDescriptor, AnnotationValue>> methodParameterAnnotations, long variableIsSynthetic) {
super(className, methodName, methodSignature, (accessFlags & Constants.ACC_STATIC) != 0);
this.accessFlags = accessFlags;
this.exceptions = exceptions;
- if (exceptions != null)
- for (int i = 0; i < exceptions.length; i++)
+ if (exceptions != null) {
+ for (int i = 0; i < exceptions.length; i++) {
exceptions[i] = DescriptorFactory.canonicalizeString(exceptions[i]);
+ }
+ }
this.methodSourceSignature = DescriptorFactory.canonicalizeString(methodSourceSignature);
this.methodAnnotations = Util.immutableMap(methodAnnotations);
this.methodParameterAnnotations = Util.immutableMap(methodParameterAnnotations);
- if (isUnconditionalThrower)
+ if (isUnconditionalThrower) {
getUnconditionalthrowers().put(this, null);
- if (isUnsupported)
+ }
+ if (isUnsupported) {
getUnconditionalthrowers().put(this, null);
- if (accessMethodForMethod != null)
+ }
+ if (accessMethodForMethod != null) {
getAccessmethodformethod().put(this, accessMethodForMethod);
- if (accessMethodForField!= null)
+ }
+ if (accessMethodForField!= null) {
getAccessmethodforfield().put(this, accessMethodForField);
+ }
if (isIdentity) {
getIdentitymethods().put(this, null);
}
+ if (usesInvokeDynamic) {
+ getInvokeDynamicMethods().put(this, null);
+ }
this.usesConcurrency = usesConcurrency;
this.hasBackBranch = hasBackBranch;
@@ -295,6 +325,7 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
this.variableIsSynthetic = variableIsSynthetic;
}
+ @Override
public @CheckForNull
String[] getThrownExceptions() {
return exceptions;
@@ -302,24 +333,37 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
+ @Override
public boolean isUnconditionalThrower() {
return getUnconditionalthrowers().containsKey(this);
}
+ @Override
public boolean isIdentity() {
return getIdentitymethods().containsKey(this);
}
+ @Override
+ public boolean usesInvokeDynamic() {
+ return getInvokeDynamicMethods().containsKey(this);
+ }
+
+
+ @Override
public boolean isUnsupported() {
return getUnsupportedmethods().containsKey(this);
}
+ @Override
public int getNumParams() {
return new SignatureParser(getSignature()).getNumParameters();
}
+ @Override
public boolean isVariableSynthetic(int param) {
- if (param >= 64) return false;
+ if (param >= 64) {
+ return false;
+ }
return (variableIsSynthetic & (1 << param)) != 0;
}
@@ -331,39 +375,51 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
return (accessFlags & flag) != 0;
}
+ @Override
public boolean isNative() {
return checkFlag(Constants.ACC_NATIVE);
}
+ @Override
public boolean isAbstract() {
return checkFlag(Constants.ACC_ABSTRACT);
}
+ @Override
public boolean isSynchronized() {
return checkFlag(Constants.ACC_SYNCHRONIZED);
}
+ @Override
+ public boolean isBridge() {
+ return checkFlag(Constants.ACC_BRIDGE);
+ }
+
/*
* (non-Javadoc)
*
* @see edu.umd.cs.findbugs.ba.XMethod#isReturnTypeReferenceType()
*/
+ @Override
public boolean isReturnTypeReferenceType() {
SignatureParser parser = new SignatureParser(getSignature());
String returnTypeSig = parser.getReturnTypeSignature();
return SignatureParser.isReferenceType(returnTypeSig);
}
+ @Override
public @DottedClassName
String getClassName() {
return getClassDescriptor().toDottedClassName();
}
+ @Override
public @DottedClassName
String getPackageName() {
return getClassDescriptor().getPackageName();
}
+ @Override
public String getSourceSignature() {
return methodSourceSignature;
}
@@ -379,7 +435,7 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
return FieldOrMethodDescriptor.compareTo(this, (MethodDescriptor) rhs);
}
- if (rhs instanceof XMethod) {
+ if (rhs instanceof XMethod) {
return XFactory.compare((XMethod) this, (XMethod) rhs);
}
@@ -391,6 +447,7 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#getAccessFlags()
*/
+ @Override
public int getAccessFlags() {
return accessFlags;
}
@@ -400,6 +457,7 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isFinal()
*/
+ @Override
public boolean isFinal() {
return checkFlag(Constants.ACC_FINAL);
}
@@ -409,10 +467,12 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isPrivate()
*/
+ @Override
public boolean isPrivate() {
return checkFlag(Constants.ACC_PRIVATE);
}
+ @Override
public boolean isDeprecated() {
return checkFlag(Opcodes.ACC_DEPRECATED);
}
@@ -422,6 +482,7 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isProtected()
*/
+ @Override
public boolean isProtected() {
return checkFlag(Constants.ACC_PROTECTED);
}
@@ -431,10 +492,12 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isPublic()
*/
+ @Override
public boolean isPublic() {
return checkFlag(Constants.ACC_PUBLIC);
}
+ @Override
public boolean isSynthetic() {
return checkFlag(Constants.ACC_SYNTHETIC);
}
@@ -444,46 +507,65 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.AccessibleEntity#isResolved()
*/
+ @Override
public boolean isResolved() {
return true;
}
+ @Override
public Collection<ClassDescriptor> getParameterAnnotationDescriptors(int param) {
Map<ClassDescriptor, AnnotationValue> map = methodParameterAnnotations.get(param);
- if (map == null)
+ if (map == null) {
return Collections.<ClassDescriptor> emptySet();
+ }
return map.keySet();
}
+ @Override
public boolean hasParameterAnnotations() {
return !methodParameterAnnotations.isEmpty();
}
-
+
+ @Override
public @Nullable
AnnotationValue getParameterAnnotation(int param, ClassDescriptor desc) {
Map<ClassDescriptor, AnnotationValue> map = methodParameterAnnotations.get(param);
- if (map == null)
+ if (map == null) {
return null;
+ }
return map.get(desc);
}
+ @Override
public Collection<AnnotationValue> getParameterAnnotations(int param) {
Map<ClassDescriptor, AnnotationValue> map = methodParameterAnnotations.get(param);
- if (map == null)
+ if (map == null) {
return Collections.<AnnotationValue> emptySet();
+ }
return map.values();
}
+ @Override
public Collection<ClassDescriptor> getAnnotationDescriptors() {
return methodAnnotations.keySet();
}
+ @Override
public AnnotationValue getAnnotation(ClassDescriptor desc) {
return methodAnnotations.get(desc);
}
+ @Override
public Collection<AnnotationValue> getAnnotations() {
- return methodAnnotations.values();
+
+ Collection<AnnotationValue> result = methodAnnotations.values();
+ if (result.isEmpty() && isBridge()) {
+ XMethod to = bridgeTo();
+ if (to != null) {
+ result = to.getAnnotations();
+ }
+ }
+ return result;
}
/**
@@ -495,6 +577,7 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
* @param annotationValue
* an AnnotationValue representing a method annotation
*/
+ @Override
public void addAnnotation(AnnotationValue annotationValue) {
HashMap<ClassDescriptor, AnnotationValue> updatedAnnotations = new HashMap<ClassDescriptor, AnnotationValue>(
methodAnnotations);
@@ -511,6 +594,7 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
* @param annotationValue
* an AnnotationValue representing a parameter annotation
*/
+ @Override
public void addParameterAnnotation(int param, AnnotationValue annotationValue) {
HashMap<Integer, Map<ClassDescriptor, AnnotationValue>> updatedAnnotations = new HashMap<Integer, Map<ClassDescriptor, AnnotationValue>>(
methodParameterAnnotations);
@@ -530,16 +614,20 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#getMethodDescriptor()
*/
+ @Override
public MethodDescriptor getMethodDescriptor() {
return this;
}
+ @Override
public ElementType getElementType() {
- if (getName().equals("<init>"))
+ if ("<init>".equals(getName())) {
return ElementType.CONSTRUCTOR;
+ }
return ElementType.METHOD;
}
+ @Override
public @CheckForNull
AnnotatedObject getContainingScope() {
try {
@@ -554,6 +642,7 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#isVarArgs()
*/
+ @Override
public boolean isVarArgs() {
return checkFlag(Constants.ACC_VARARGS);
}
@@ -563,6 +652,7 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#usesConcurrency()
*/
+ @Override
public boolean usesConcurrency() {
return usesConcurrency;
}
@@ -571,14 +661,17 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
public boolean hasBackBranch() {
return hasBackBranch;
}
+ @Override
public boolean isStub() {
return isStub;
}
+ @Override
public @CheckForNull
MethodDescriptor getAccessMethodForMethod() {
return getAccessmethodformethod().get(this);
}
+ @Override
public @CheckForNull
FieldDescriptor getAccessMethodForField() {
return getAccessmethodforfield().get(this);
@@ -589,6 +682,7 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#bridgeFrom()
*/
+ @Override
public XMethod bridgeFrom() {
return AnalysisContext.currentAnalysisContext().getBridgeFrom(this);
}
@@ -598,15 +692,18 @@ public class MethodInfo extends MethodDescriptor implements XMethod {
*
* @see edu.umd.cs.findbugs.ba.XMethod#bridgeTo()
*/
+ @Override
public XMethod bridgeTo() {
return AnalysisContext.currentAnalysisContext().getBridgeTo(this);
}
+ @Override
public XMethod resolveAccessMethodForMethod() {
MethodDescriptor access = getAccessMethodForMethod();
- if (access != null)
+ if (access != null) {
return XFactory.createXMethod(access);
+ }
return this;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/AbstractFieldAnnotationVisitor.java b/src/java/edu/umd/cs/findbugs/classfile/engine/AbstractFieldAnnotationVisitor.java
index da0e5e2..7a9955e 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/AbstractFieldAnnotationVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/AbstractFieldAnnotationVisitor.java
@@ -22,18 +22,25 @@ package edu.umd.cs.findbugs.classfile.engine;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.FieldVisitor;
+import edu.umd.cs.findbugs.classfile.engine.asm.FindBugsASM;
+
/**
* @author pwilliam
*/
-public abstract class AbstractFieldAnnotationVisitor implements FieldVisitor {
+public abstract class AbstractFieldAnnotationVisitor extends FieldVisitor {
+
+ public AbstractFieldAnnotationVisitor() {
+ super(FindBugsASM.ASM_VERSION);
+ }
/*
* (non-Javadoc)
- *
+ *
* @see
* org.objectweb.asm.FieldVisitor#visitAttribute(org.objectweb.asm.Attribute
* )
*/
+ @Override
public void visitAttribute(Attribute attr) {
// TODO Auto-generated method stub
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/AbstractMethodVisitor.java b/src/java/edu/umd/cs/findbugs/classfile/engine/AbstractMethodVisitor.java
index 7ab9640..88cc5e8 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/AbstractMethodVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/AbstractMethodVisitor.java
@@ -24,19 +24,27 @@ import org.objectweb.asm.Attribute;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
+import edu.umd.cs.findbugs.classfile.engine.asm.FindBugsASM;
+
/**
* @author pwilliam
*/
-public abstract class AbstractMethodVisitor implements MethodVisitor {
+public abstract class AbstractMethodVisitor extends MethodVisitor {
+
+
+ public AbstractMethodVisitor() {
+ super(FindBugsASM.ASM_VERSION);
+ }
public void visitSomeInsn() {
}
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitAnnotationDefault()
*/
+ @Override
public AnnotationVisitor visitAnnotationDefault() {
// TODO Auto-generated method stub
return null;
@@ -44,20 +52,22 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see
* org.objectweb.asm.MethodVisitor#visitAttribute(org.objectweb.asm.Attribute
* )
*/
+ @Override
public void visitAttribute(Attribute attr) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitCode()
*/
+ @Override
public void visitCode() {
// TODO Auto-generated method stub
@@ -65,10 +75,11 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitFieldInsn(int,
* java.lang.String, java.lang.String, java.lang.String)
*/
+ @Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
visitSomeInsn();
@@ -76,10 +87,11 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitFrame(int, int,
* java.lang.Object[], int, java.lang.Object[])
*/
+ @Override
public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) {
// TODO Auto-generated method stub
@@ -87,9 +99,10 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitIincInsn(int, int)
*/
+ @Override
public void visitIincInsn(int var, int increment) {
visitSomeInsn();
@@ -97,9 +110,10 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitInsn(int)
*/
+ @Override
public void visitInsn(int opcode) {
visitSomeInsn();
@@ -107,9 +121,10 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitIntInsn(int, int)
*/
+ @Override
public void visitIntInsn(int opcode, int operand) {
visitSomeInsn();
@@ -117,10 +132,11 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitJumpInsn(int,
* org.objectweb.asm.Label)
*/
+ @Override
public void visitJumpInsn(int opcode, Label label) {
visitSomeInsn();
@@ -128,9 +144,10 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitLabel(org.objectweb.asm.Label)
*/
+ @Override
public void visitLabel(Label label) {
// TODO Auto-generated method stub
@@ -138,9 +155,10 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitLdcInsn(java.lang.Object)
*/
+ @Override
public void visitLdcInsn(Object cst) {
visitSomeInsn();
@@ -148,10 +166,11 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitLineNumber(int,
* org.objectweb.asm.Label)
*/
+ @Override
public void visitLineNumber(int line, Label start) {
// TODO Auto-generated method stub
@@ -159,11 +178,12 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitLocalVariable(java.lang.String,
* java.lang.String, java.lang.String, org.objectweb.asm.Label,
* org.objectweb.asm.Label, int)
*/
+ @Override
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
// TODO Auto-generated method stub
@@ -171,11 +191,12 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see
* org.objectweb.asm.MethodVisitor#visitLookupSwitchInsn(org.objectweb.asm
* .Label, int[], org.objectweb.asm.Label[])
*/
+ @Override
public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
visitSomeInsn();
@@ -183,9 +204,10 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitMaxs(int, int)
*/
+ @Override
public void visitMaxs(int maxStack, int maxLocals) {
// TODO Auto-generated method stub
@@ -193,22 +215,24 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitMethodInsn(int,
* java.lang.String, java.lang.String, java.lang.String)
*/
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
visitSomeInsn();
}
/*
* (non-Javadoc)
- *
+ *
* @see
* org.objectweb.asm.MethodVisitor#visitMultiANewArrayInsn(java.lang.String,
* int)
*/
+ @Override
public void visitMultiANewArrayInsn(String desc, int dims) {
visitSomeInsn();
@@ -216,23 +240,25 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitTableSwitchInsn(int, int,
* org.objectweb.asm.Label, org.objectweb.asm.Label[])
*/
- public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
+ @Override
+ public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
- *
+ *
* @see
* org.objectweb.asm.MethodVisitor#visitTryCatchBlock(org.objectweb.asm.
* Label, org.objectweb.asm.Label, org.objectweb.asm.Label,
* java.lang.String)
*/
+ @Override
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
// TODO Auto-generated method stub
@@ -240,9 +266,10 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitTypeInsn(int, java.lang.String)
*/
+ @Override
public void visitTypeInsn(int opcode, String type) {
visitSomeInsn();
@@ -250,9 +277,10 @@ public abstract class AbstractMethodVisitor implements MethodVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see org.objectweb.asm.MethodVisitor#visitVarInsn(int, int)
*/
+ @Override
public void visitVarInsn(int opcode, int var) {
visitSomeInsn();
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassDataAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassDataAnalysisEngine.java
index 043b22a..9d6a84f 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassDataAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassDataAnalysisEngine.java
@@ -41,6 +41,7 @@ import edu.umd.cs.findbugs.io.IO;
*/
public class ClassDataAnalysisEngine extends RecomputableClassAnalysisEngine<ClassData> {
+ @Override
public ClassData analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor) throws CheckedAnalysisException {
// Compute the resource name
@@ -81,6 +82,7 @@ public class ClassDataAnalysisEngine extends RecomputableClassAnalysisEngine<Cla
return new ClassData(descriptor, codeBaseEntry, data);
}
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerClassAnalysisEngine(ClassData.class, this);
}
@@ -93,14 +95,17 @@ public class ClassDataAnalysisEngine extends RecomputableClassAnalysisEngine<Cla
this.descriptor = descriptor;
}
+ @Override
public String getResourceName() {
return descriptor.toResourceName();
}
+ @Override
public int getNumBytes() {
return -1;
}
+ @Override
public InputStream openResource() throws IOException {
InputStream stream = getClass().getClassLoader().getResourceAsStream(descriptor.toResourceName());
if(stream == null){
@@ -109,14 +114,17 @@ public class ClassDataAnalysisEngine extends RecomputableClassAnalysisEngine<Cla
return stream;
}
+ @Override
public ICodeBase getCodeBase() {
return null;
}
+ @Override
public ClassDescriptor getClassDescriptor() {
return descriptor;
}
+ @Override
public void overrideResourceName(String resourceName) {
//
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassInfoAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassInfoAnalysisEngine.java
index a6e3777..f695310 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassInfoAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassInfoAnalysisEngine.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.classfile.analysis.ClassInfo;
/**
* Analysis engine to produce the ClassInfo for a loaded class. We parse just
* enough information from the classfile to get the needed information.
- *
+ *
* @author David Hovemeyer
*/
public class ClassInfoAnalysisEngine implements IClassAnalysisEngine<XClass> {
@@ -45,21 +45,24 @@ public class ClassInfoAnalysisEngine implements IClassAnalysisEngine<XClass> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ClassInfo analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor) throws CheckedAnalysisException {
- if (descriptor instanceof ClassInfo)
+ if (descriptor instanceof ClassInfo) {
return (ClassInfo) descriptor;
+ }
ClassData classData;
try {
classData = analysisCache.getClassAnalysis(ClassData.class, descriptor);
} catch (edu.umd.cs.findbugs.classfile.MissingClassException e) {
- if (!descriptor.getSimpleName().equals("package-info"))
+ if (!"package-info".equals(descriptor.getSimpleName())) {
throw e;
+ }
ClassInfo.Builder builder = new ClassInfo.Builder();
builder.setClassDescriptor(descriptor);
@@ -84,20 +87,22 @@ public class ClassInfoAnalysisEngine implements IClassAnalysisEngine<XClass> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerClassAnalysisEngine(XClass.class, this);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.IAnalysisEngine#canRecompute()
*/
+ @Override
public boolean canRecompute() {
// ClassInfo objects serve as XClass objects,
// which we want interned. So, they are never purged from the cache.
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassNameAndSuperclassInfoAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassNameAndSuperclassInfoAnalysisEngine.java
index a33e92e..121eb22 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassNameAndSuperclassInfoAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassNameAndSuperclassInfoAnalysisEngine.java
@@ -33,18 +33,19 @@ import edu.umd.cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo;
/**
* Analysis engine to produce the ClassInfo for a loaded class. We parse just
* enough information from the classfile to get the needed information.
- *
+ *
* @author David Hovemeyer
*/
public class ClassNameAndSuperclassInfoAnalysisEngine implements IClassAnalysisEngine<ClassNameAndSuperclassInfo> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ClassNameAndSuperclassInfo analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor)
throws CheckedAnalysisException {
// Get InputStream reading from class data
@@ -65,20 +66,22 @@ public class ClassNameAndSuperclassInfoAnalysisEngine implements IClassAnalysisE
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerClassAnalysisEngine(ClassNameAndSuperclassInfo.class, this);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.IAnalysisEngine#canRecompute()
*/
+ @Override
public boolean canRecompute() {
// ClassInfo objects serve as XClass objects,
// which we want interned. So, they are never purged from the cache.
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParser.java b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParser.java
index 8b91f54..e37f344 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParser.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParser.java
@@ -29,15 +29,12 @@ import javax.annotation.CheckForNull;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.DescriptorFactory;
-import edu.umd.cs.findbugs.classfile.FieldDescriptor;
import edu.umd.cs.findbugs.classfile.IClassConstants;
import edu.umd.cs.findbugs.classfile.ICodeBaseEntry;
import edu.umd.cs.findbugs.classfile.InvalidClassFileFormatException;
-import edu.umd.cs.findbugs.classfile.MethodDescriptor;
import edu.umd.cs.findbugs.classfile.analysis.ClassInfo;
import edu.umd.cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo;
import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
-import edu.umd.cs.findbugs.io.IO;
import edu.umd.cs.findbugs.util.ClassName;
/**
@@ -70,7 +67,7 @@ public class ClassParser implements ClassParserInterface {
private Constant[] constantPool;
- private ClassDescriptor immediateEnclosingClass;
+ // private ClassDescriptor immediateEnclosingClass;
/**
* Constructor.
@@ -88,19 +85,14 @@ public class ClassParser implements ClassParserInterface {
this.codeBaseEntry = codeBaseEntry;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.engine.ClassParserInterface#parse(edu.umd
- * .cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo.Builder)
- */
+ @Override
public void parse(ClassNameAndSuperclassInfo.Builder builder) throws InvalidClassFileFormatException {
try {
int magic = in.readInt();
- if (magic != 0xcafebabe)
+ if (magic != 0xcafebabe) {
throw new InvalidClassFileFormatException("Classfile header isn't 0xCAFEBABE", expectedClassDescriptor,
codeBaseEntry);
+ }
int major_version = in.readUnsignedShort();
int minor_version = in.readUnsignedShort();
int constant_pool_count = in.readUnsignedShort();
@@ -129,12 +121,13 @@ public class ClassParser implements ClassParserInterface {
throw new InvalidClassFileFormatException(expectedClassDescriptor, codeBaseEntry);
}
ClassDescriptor[] interfaceDescriptorList;
- if (interfaces_count == 0)
+ if (interfaces_count == 0) {
interfaceDescriptorList = ClassDescriptor.EMPTY_ARRAY;
- else {
+ } else {
interfaceDescriptorList = new ClassDescriptor[interfaces_count];
- for (int i = 0; i < interfaceDescriptorList.length; i++)
+ for (int i = 0; i < interfaceDescriptorList.length; i++) {
interfaceDescriptorList[i] = getClassDescriptor(in.readUnsignedShort());
+ }
}
// Extract all references to other classes,
// both CONSTANT_Class entries and also referenced method
@@ -153,13 +146,7 @@ public class ClassParser implements ClassParserInterface {
}
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.engine.ClassParserInterface#parse(edu.umd
- * .cs.findbugs.classfile.analysis.ClassInfo.Builder)
- */
+ @Override
public void parse(ClassInfo.Builder builder) throws InvalidClassFileFormatException {
throw new UnsupportedOperationException("Need to use a ClassParserUsingASM to build ClassInfo");
}
@@ -198,10 +185,6 @@ public class ClassParser implements ClassParserInterface {
return referencedClassSet;
}
- /**
- * @param referencedClassSet
- * @param signature
- */
public static void extractReferencedClassesFromSignature(Set<ClassDescriptor> referencedClassSet, String signature) {
while (signature.length() > 0) {
int start = signature.indexOf('L');
@@ -228,24 +211,24 @@ public class ClassParser implements ClassParserInterface {
// D: double
// i: 2-byte constant pool index
private static final String[] CONSTANT_FORMAT_MAP = { null,
- "8", // 1:CONSTANT_Utf8
- null, // 2:
- "I", // 3: CONSTANT_Integer
- "F", // 4: CONSTANT_Float
- "L", // 5: CONSTANT_Long
- "D", // 6: CONSTANT_Double
- "i", // 7: CONSTANT_Class
- "i", // 8: CONSTANT_String
- "ii", // 9: CONSTANT_Fieldref
- "ii", // 10: CONSTANT_Methodref
- "ii", // 11: CONSTANT_InterfaceMethodref
- "ii", // 12: CONSTANT_NameAndType
- null, // 13:
- null, // 14:
- "bi", // 15: CONSTANT_MethodHandle
- "i", // 16: CONSTANT_MethodType
- null, // 17:
- "ii", // 18: CONSTANT_InvokeDynamic
+ "8", // 1:CONSTANT_Utf8
+ null, // 2:
+ "I", // 3: CONSTANT_Integer
+ "F", // 4: CONSTANT_Float
+ "L", // 5: CONSTANT_Long
+ "D", // 6: CONSTANT_Double
+ "i", // 7: CONSTANT_Class
+ "i", // 8: CONSTANT_String
+ "ii", // 9: CONSTANT_Fieldref
+ "ii", // 10: CONSTANT_Methodref
+ "ii", // 11: CONSTANT_InterfaceMethodref
+ "ii", // 12: CONSTANT_NameAndType
+ null, // 13:
+ null, // 14:
+ "bi", // 15: CONSTANT_MethodHandle
+ "i", // 16: CONSTANT_MethodType
+ null, // 17:
+ "ii", // 18: CONSTANT_InvokeDynamic
};
@@ -277,13 +260,13 @@ public class ClassParser implements ClassParserInterface {
data[i] = in.readInt();
break;
case 'F':
- data[i] = new Float(in.readFloat());
+ data[i] = Float.valueOf(in.readFloat());
break;
case 'L':
data[i] = in.readLong();
break;
case 'D':
- data[i] = new Double(in.readDouble());
+ data[i] = Double.valueOf(in.readDouble());
break;
case 'i':
data[i] = in.readUnsignedShort();
@@ -356,10 +339,6 @@ public class ClassParser implements ClassParserInterface {
/**
* Check that a constant pool index is valid.
*
- * @param expectedClassDescriptor
- * class descriptor
- * @param constantPool
- * the constant pool
* @param index
* the index to check
* @throws InvalidClassFileFormatException
@@ -399,46 +378,30 @@ public class ClassParser implements ClassParserInterface {
* @return the FieldDescriptor
* @throws IOException
* @throws InvalidClassFileFormatException
- */
+ *
private FieldDescriptor readField(ClassDescriptor thisClassDescriptor) throws IOException, InvalidClassFileFormatException {
return readFieldOrMethod(thisClassDescriptor, new FieldOrMethodDescriptorCreator<FieldDescriptor>() {
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.classfile.engine.ClassParser.
- * FieldOrMethodDescriptorCreator#create(java.lang.String,
- * java.lang.String, java.lang.String, int)
- */
+ @Override
public FieldDescriptor create(String className, String name, String signature, int accessFlags) {
return DescriptorFactory.instance().getFieldDescriptor(className, name, signature,
(accessFlags & IClassConstants.ACC_STATIC) != 0);
}
});
- }
+ }*/
/**
* Read method_info, read method descriptor.
*
- * @param thisClassDescriptor
- * @return
- * @throws IOException
- * @throws InvalidClassFileFormatException
- */
private MethodDescriptor readMethod(ClassDescriptor thisClassDescriptor) throws InvalidClassFileFormatException, IOException {
return readFieldOrMethod(thisClassDescriptor, new FieldOrMethodDescriptorCreator<MethodDescriptor>() {
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.classfile.engine.ClassParser.
- * FieldOrMethodDescriptorCreator#create(java.lang.String,
- * java.lang.String, java.lang.String, int)
- */
+
+ @Override
public MethodDescriptor create(String className, String name, String signature, int accessFlags) {
return DescriptorFactory.instance().getMethodDescriptor(className, name, signature,
(accessFlags & IClassConstants.ACC_STATIC) != 0);
}
});
- }
+ }*/
/**
* Read field_info or method_info. They have the same format.
@@ -452,7 +415,7 @@ public class ClassParser implements ClassParserInterface {
* @return the parsed descriptor
* @throws IOException
* @throws InvalidClassFileFormatException
- */
+ *
private <E> E readFieldOrMethod(ClassDescriptor thisClassDescriptor, FieldOrMethodDescriptorCreator<E> creator)
throws IOException, InvalidClassFileFormatException {
int access_flags = in.readUnsignedShort();
@@ -470,14 +433,14 @@ public class ClassParser implements ClassParserInterface {
}
return creator.create(thisClassDescriptor.getClassName(), name, signature, access_flags);
- }
+ }*/
/**
* Read an attribute.
*
* @throws IOException
* @throws InvalidClassFileFormatException
- */
+ *
private void readAttribute() throws IOException, InvalidClassFileFormatException {
int attribute_name_index = in.readUnsignedShort();
String attrName = getUtf8String(attribute_name_index);
@@ -492,7 +455,7 @@ public class ClassParser implements ClassParserInterface {
} else {
IO.skipFully(in, attribute_length);
}
- }
+ }*/
/**
* Read an InnerClasses attribute.
@@ -501,7 +464,7 @@ public class ClassParser implements ClassParserInterface {
* length of attribute (excluding first 6 bytes)
* @throws InvalidClassFileFormatException
* @throws IOException
- */
+ *
private void readInnerClassesAttribute(int attribute_length) throws InvalidClassFileFormatException, IOException {
int number_of_classes = in.readUnsignedShort();
if (attribute_length != number_of_classes * 8) {
@@ -514,12 +477,12 @@ public class ClassParser implements ClassParserInterface {
int inner_name_index = in.readUnsignedShort();
int inner_class_access_flags = in.readUnsignedShort();
- if (outer_class_info_index != 0) {
- // Record which class this class is a member of.
- this.immediateEnclosingClass = getClassDescriptor(outer_class_info_index);
- }
+ // if (outer_class_info_index != 0) {
+ // // Record which class this class is a member of.
+ // this.immediateEnclosingClass = getClassDescriptor(outer_class_info_index);
+ // }
}
- }
+ }*/
/**
* Get the signature from a CONSTANT_NameAndType.
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserInterface.java b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserInterface.java
index 5474636..b551e3e 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserInterface.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserInterface.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo;
* Interface implemented by ClassParsers - objects that take the raw bytes of a
* classfile and parse the important symbolic information to produce
* ClassNameAndSuperclassInfo and ClassInfo objects.
- *
+ *
* @author Bill Pugh
* @author David Hovemeyer
*/
@@ -36,7 +36,7 @@ public interface ClassParserInterface {
/**
* Parse the class data into a ClassNameAndSuperclassInfo object containing
* (some of) the class's symbolic information.
- *
+ *
* @param classInfo
* a ClassNameAndSuperclassInfo object to be filled in with (some
* of) the class's symbolic information
@@ -47,7 +47,7 @@ public interface ClassParserInterface {
/**
* Parse the class data into a ClassInfo object containing (some of) the
* class's symbolic information.
- *
+ *
* @param classInfo
* a ClassInfo object to be filled in with (some of) the class's
* symbolic information
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserUsingASM.java b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserUsingASM.java
index e37ac4e..68e3148 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserUsingASM.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserUsingASM.java
@@ -30,6 +30,7 @@ import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -45,6 +46,7 @@ import edu.umd.cs.findbugs.classfile.analysis.ClassInfo.Builder;
import edu.umd.cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo;
import edu.umd.cs.findbugs.classfile.analysis.FieldInfo;
import edu.umd.cs.findbugs.classfile.analysis.MethodInfo;
+import edu.umd.cs.findbugs.classfile.engine.asm.FindBugsASM;
import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
import edu.umd.cs.findbugs.util.ClassName;
@@ -71,12 +73,425 @@ public class ClassParserUsingASM implements ClassParserInterface {
private @SlashedClassName
String slashedClassName;
- private final ClassDescriptor expectedClassDescriptor;
+ // private final ClassDescriptor expectedClassDescriptor;
private final ICodeBaseEntry codeBaseEntry;
+ /**
+ * @author pugh
+ */
+ private final class ClassParserMethodVisitor extends AbstractMethodVisitor {
+ /**
+ *
+ */
+ private final TreeSet<ClassDescriptor> calledClassSet;
+
+ /**
+ *
+ */
+ private final edu.umd.cs.findbugs.classfile.analysis.MethodInfo.Builder mBuilder;
+
+ /**
+ *
+ */
+ private final String methodName;
+
+ /**
+ *
+ */
+ private final int access;
+
+ /**
+ *
+ */
+ private final String methodDesc;
+
+ /**
+ *
+ */
+ private final edu.umd.cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo.Builder cBuilder;
+
+ boolean sawReturn;
+
+ boolean sawNormalThrow = false;
+
+ boolean sawUnsupportedThrow = false;
+
+ boolean sawSystemExit = false;
+
+ boolean sawBranch = false;
+
+ boolean sawBackBranch = false;
+
+ int methodCallCount = 0;
+
+ int fieldInstructionCount = 0;
+
+ boolean sawStubThrow = false;
+
+ boolean justSawInitializationOfUnsupportedOperationException;
+
+ boolean isBridge;
+
+ String bridgedMethodSignature;
+
+ IdentityMethodState identityState =
+ IdentityMethodState.INITIAL;
+
+ ParameterLoadState parameterLoadState = ParameterLoadState.OTHER;
+
+ int parameterForLoadState;
+
+ StubState stubState = StubState.INITIAL;
+
+ boolean isAccessMethod;
+
+ String accessOwner, accessName, accessDesc;
+
+ boolean accessForField;
+
+ boolean accessIsStatic;
+
+ HashSet<Label> labelsSeen = new HashSet<Label>();
+
+ /**
+ * @param calledClassSet
+ * @param mBuilder
+ * @param methodName
+ * @param access
+ * @param methodDesc
+ * @param cBuilder
+ */
+ private ClassParserMethodVisitor(TreeSet<ClassDescriptor> calledClassSet,
+ edu.umd.cs.findbugs.classfile.analysis.MethodInfo.Builder mBuilder, String methodName, int access,
+ String methodDesc, edu.umd.cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo.Builder cBuilder) {
+ this.calledClassSet = calledClassSet;
+ this.mBuilder = mBuilder;
+ this.methodName = methodName;
+ this.access = access;
+ this.methodDesc = methodDesc;
+ this.cBuilder = cBuilder;
+ sawReturn = (access & Opcodes.ACC_NATIVE) != 0;
+ isBridge = (access & Opcodes.ACC_SYNTHETIC) != 0 && (access & Opcodes.ACC_BRIDGE) != 0;
+ isAccessMethod = methodName.startsWith("access$");
+ }
+
+ boolean isStatic() {
+ return (access & Opcodes.ACC_STATIC) != 0;
+ }
+
+ @Override
+ public
+ void visitLocalVariable(String name,
+ String desc,
+ String signature,
+ Label start,
+ Label end,
+ int index) {
+ mBuilder.setVariableHasName(index);
+
+ }
+
+ @Override
+ public void visitLdcInsn(Object cst) {
+ if (cst.equals("Stub!")) {
+ stubState = StubState.LOADED_STUB;
+ } else {
+ stubState = StubState.INITIAL;
+ }
+ identityState = IdentityMethodState.NOT;
+ }
+
+ @Override
+ public void visitInsn(int opcode) {
+ switch (opcode) {
+ case Constants.MONITORENTER:
+ mBuilder.setUsesConcurrency();
+ break;
+ case Constants.ARETURN:
+ case Constants.IRETURN:
+ case Constants.LRETURN:
+ case Constants.DRETURN:
+ case Constants.FRETURN:
+ if (identityState == IdentityMethodState.LOADED_PARAMETER) {
+ mBuilder.setIsIdentity();
+ }
+ sawReturn = true;
+ break;
+ case Constants.RETURN:
+ sawReturn = true;
+ break;
+ case Constants.ATHROW:
+ if (stubState == StubState.INITIALIZE_RUNTIME) {
+ sawStubThrow = true;
+ } else if (justSawInitializationOfUnsupportedOperationException) {
+ sawUnsupportedThrow = true;
+ } else {
+ sawNormalThrow = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ resetState();
+ }
+
+ public void resetState() {
+ stubState = StubState.INITIAL;
+ }
+
+ @Override
+ public void visitSomeInsn() {
+ identityState = IdentityMethodState.NOT;
+ parameterLoadState = ParameterLoadState.OTHER;
+ resetState();
+ }
+
+ @Override
+ public void visitVarInsn(int opcode, int var) {
+
+ boolean match = false;
+ if (parameterLoadState == ParameterLoadState.OTHER && !isStatic() && var == 0) {
+ parameterLoadState = ParameterLoadState.LOADED_THIS;
+
+ match = true;
+ }
+ else if (parameterLoadState == ParameterLoadState.LOADED_THIS && var > 0){
+ parameterLoadState = ParameterLoadState.LOADED_THIS_AND_PARAMETER;
+ parameterForLoadState = var;
+ match = true;
+ }
+
+ if (identityState == IdentityMethodState.INITIAL) {
+ match = true;
+ if (var > 0 || isStatic()) {
+ identityState = IdentityMethodState.LOADED_PARAMETER;
+ } else {
+ identityState = IdentityMethodState.NOT;
+ }
+
+ }
+ if (!match) {
+ visitSomeInsn();
+ }
+ }
+
+ @Override
+ public void visitFieldInsn(int opcode,
+ String owner,
+ String name,
+ String desc) {
+ if (opcode == Opcodes.PUTFIELD && parameterLoadState == ParameterLoadState.LOADED_THIS_AND_PARAMETER
+ && owner.equals(slashedClassName) && name.startsWith("this$")) {
+ mBuilder.setVariableIsSynthetic(parameterForLoadState);
+ }
+ fieldInstructionCount++;
+
+ if (isAccessMethod && this.accessOwner == null) {
+ this.accessOwner = owner;
+ this.accessName = name;
+ this.accessDesc = desc;
+ this.accessIsStatic = opcode == Opcodes.GETSTATIC || opcode == Opcodes.PUTSTATIC;
+ this.accessForField = true;
+ }
+ visitSomeInsn();
+ }
+
+ @Override
+ public org.objectweb.asm.AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
+ AnnotationValue value = new AnnotationValue(desc);
+ mBuilder.addAnnotation(desc, value);
+ return value.getAnnotationVisitor();
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ mBuilder.setUsesInvokeDynamic();
+ }
+
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
+ identityState = IdentityMethodState.NOT;
+ methodCallCount++;
+ if (isAccessMethod && this.accessOwner == null) {
+ this.accessOwner = owner;
+ this.accessName = name;
+ this.accessDesc = desc;
+ this.accessIsStatic = opcode == Opcodes.INVOKESTATIC;
+ this.accessForField = false;
+ }
+ if (stubState == StubState.LOADED_STUB && opcode == Opcodes.INVOKESPECIAL
+ && "java/lang/RuntimeException".equals(owner) && "<init>".equals(name)) {
+ stubState = StubState.INITIALIZE_RUNTIME;
+ } else {
+ stubState = StubState.INITIAL;
+ }
+ if (owner.startsWith("java/util/concurrent")) {
+ mBuilder.setUsesConcurrency();
+ }
+ if (opcode == Opcodes.INVOKEINTERFACE) {
+ return;
+ }
+
+ if (owner.charAt(0) == '[' && owner.charAt(owner.length() - 1) != ';') {
+ // primitive array
+ return;
+ }
+ if (opcode == Opcodes.INVOKESTATIC && "java/lang/System".equals(owner) && "exit".equals(name)
+ && !sawReturn) {
+ sawSystemExit = true;
+ }
+ justSawInitializationOfUnsupportedOperationException = opcode == Opcodes.INVOKESPECIAL
+ && "java/lang/UnsupportedOperationException".equals(owner) && "<init>".equals(name);
+
+ if (isBridge && bridgedMethodSignature == null) {
+ switch (opcode) {
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE:
+ if (desc != null && name.equals(methodName)) {
+ bridgedMethodSignature = desc;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // System.out.println("Call from " +
+ // ClassParserUsingASM.this.slashedClassName +
+ // " to " + owner + " : " + desc);
+ if (desc == null || desc.indexOf('[') == -1 && desc.indexOf('L') == -1) {
+ return;
+ }
+ if (ClassParserUsingASM.this.slashedClassName.equals(owner)) {
+ return;
+ }
+ ClassDescriptor classDescriptor = DescriptorFactory.instance().getClassDescriptor(owner);
+ calledClassSet.add(classDescriptor);
+
+ }
+
+ private void sawBranchTo(Label label) {
+ sawBranch = true;
+ if (labelsSeen.contains(label)) {
+ sawBackBranch = true;
+ }
+ }
+
+ @Override
+ public void visitJumpInsn(int opcode, Label label) {
+ sawBranchTo(label);
+ identityState = IdentityMethodState.NOT;
+ super.visitJumpInsn(opcode, label);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
+ sawBranchTo(dflt);
+ for (Label lbl : labels) {
+ sawBranchTo(lbl);
+ }
+ identityState = IdentityMethodState.NOT;
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
+ sawBranchTo(dflt);
+ for (Label lbl : labels) {
+ sawBranchTo(lbl);
+ }
+ identityState = IdentityMethodState.NOT;
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ @Override
+ public void visitLabel(Label label) {
+ labelsSeen.add(label);
+ super.visitLabel(label);
+
+ }
+
+ @Override
+ public void visitEnd() {
+ labelsSeen.clear();
+ if (isAccessMethod && accessOwner != null) {
+ if (!accessForField && methodCallCount == 1) {
+ mBuilder.setAccessMethodForMethod(accessOwner, accessName, accessDesc, accessIsStatic);
+ } else if(accessForField && fieldInstructionCount == 1) {
+ boolean isSetter = methodDesc.endsWith(")V");
+ int numArg = new SignatureParser(methodDesc).getNumParameters();
+ int expected = 0;
+ if (!accessIsStatic) {
+ expected++;
+ }
+ if (isSetter) {
+ expected++;
+ }
+ boolean OK;
+ if (isSetter) {
+ OK = methodDesc.substring(1).startsWith(ClassName.toSignature(accessOwner) + accessDesc);
+ } else {
+ OK = methodDesc.substring(1).startsWith(ClassName.toSignature(accessOwner));
+ }
+ if (numArg == expected && OK) {
+ mBuilder.setAccessMethodForField(accessOwner, accessName, accessDesc, accessIsStatic);
+ }
+ }
+ }
+ if (sawBackBranch) {
+ mBuilder.setHasBackBranch();
+ }
+ boolean sawThrow = sawNormalThrow | sawUnsupportedThrow | sawStubThrow;
+ if (sawThrow && !sawReturn || sawSystemExit && !sawBranch) {
+
+ mBuilder.setIsUnconditionalThrower();
+ if (!sawReturn && !sawNormalThrow) {
+ if (sawUnsupportedThrow) {
+ mBuilder.setUnsupported();
+ }
+ if (sawStubThrow) {
+ mBuilder.addAccessFlags(Constants.ACC_SYNTHETIC);
+ mBuilder.setIsStub();
+
+ }
+ }
+ // else
+ // System.out.println(slashedClassName+"."+methodName+methodDesc
+ // + " is thrower");
+ }
+ mBuilder.setNumberMethodCalls(methodCallCount);
+ MethodInfo methodInfo = mBuilder.build();
+ Builder classBuilder = (ClassInfo.Builder) cBuilder;
+ if (isBridge && bridgedMethodSignature != null && !bridgedMethodSignature.equals(methodDesc)) {
+ classBuilder.addBridgeMethodDescriptor(methodInfo, bridgedMethodSignature);
+ } else {
+ classBuilder.addMethodDescriptor(methodInfo);
+ }
+
+ if (methodInfo.usesConcurrency()) {
+ classBuilder.setUsesConcurrency();
+ }
+ if (methodInfo.isStub()) {
+ classBuilder.setHasStubs();
+ }
+ }
+
+ @Override
+ public org.objectweb.asm.AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
+ boolean visible) {
+ AnnotationValue value = new AnnotationValue(desc);
+ mBuilder.addParameterAnnotation(parameter, desc, value);
+ return value.getAnnotationVisitor();
+ }
+ }
+
enum StubState {
INITIAL, LOADED_STUB, INITIALIZE_RUNTIME
}
@@ -90,40 +505,37 @@ public class ClassParserUsingASM implements ClassParserInterface {
public ClassParserUsingASM(ClassReader classReader, @CheckForNull ClassDescriptor expectedClassDescriptor,
ICodeBaseEntry codeBaseEntry) {
this.classReader = classReader;
- this.expectedClassDescriptor = expectedClassDescriptor;
+ // this.expectedClassDescriptor = expectedClassDescriptor;
this.codeBaseEntry = codeBaseEntry;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.engine.ClassParserInterface#parse(edu.umd
- * .cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo.Builder)
- */
+ @Override
public void parse(final ClassNameAndSuperclassInfo.Builder cBuilder) throws InvalidClassFileFormatException {
cBuilder.setCodeBaseEntry(codeBaseEntry);
final TreeSet<ClassDescriptor> calledClassSet = new TreeSet<ClassDescriptor>();
- classReader.accept(new ClassVisitor() {
+ classReader.accept(new ClassVisitor(FindBugsASM.ASM_VERSION) {
- boolean isInnerClass = false;
+ // boolean isInnerClass = false;
+ @Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
ClassParserUsingASM.this.slashedClassName = name;
cBuilder.setClassfileVersion(version >>> 16, version & 0xffff);
cBuilder.setAccessFlags(access);
cBuilder.setClassDescriptor(DescriptorFactory.createClassDescriptor(name));
cBuilder.setInterfaceDescriptorList(DescriptorFactory.createClassDescriptor(interfaces));
- if (superName != null)
+ if (superName != null) {
cBuilder.setSuperclassDescriptor(DescriptorFactory.createClassDescriptor(superName));
+ }
if (cBuilder instanceof ClassInfo.Builder) {
((ClassInfo.Builder) cBuilder).setSourceSignature(signature);
}
}
+ @Override
public org.objectweb.asm.AnnotationVisitor visitAnnotation(String desc, boolean isVisible) {
if (cBuilder instanceof ClassInfo.Builder) {
AnnotationValue value = new AnnotationValue(desc);
@@ -133,36 +545,41 @@ public class ClassParserUsingASM implements ClassParserInterface {
return null;
}
+ @Override
public void visitAttribute(Attribute arg0) {
- // TODO Auto-generated method stub
-
+ //
}
+ @Override
public void visitEnd() {
- // TODO Auto-generated method stub
-
+ //
}
+ @Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
- if (name.equals("this$0"))
- isInnerClass = true;
+ // if (name.equals("this$0"))
+ // isInnerClass = true;
- if (desc == null)
+ if (desc == null) {
throw new NullPointerException("Description cannot be null");
+ }
if (cBuilder instanceof ClassInfo.Builder) {
final ClassInfo.Builder cBuilder2 = (ClassInfo.Builder) cBuilder;
- if ((access & Opcodes.ACC_VOLATILE) != 0 || desc.contains("util/concurrent"))
+ if ((access & Opcodes.ACC_VOLATILE) != 0 || desc.contains("util/concurrent")) {
cBuilder2.setUsesConcurrency();
+ }
final FieldInfo.Builder fBuilder = new FieldInfo.Builder(slashedClassName, name, desc, access);
fBuilder.setSourceSignature(signature);
return new AbstractFieldAnnotationVisitor() {
+ @Override
public org.objectweb.asm.AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
AnnotationValue value = new AnnotationValue(desc);
fBuilder.addAnnotation(desc, value);
return value.getAnnotationVisitor();
}
+ @Override
public void visitEnd() {
cBuilder2.addFieldDescriptor(fBuilder.build());
@@ -174,6 +591,7 @@ public class ClassParserUsingASM implements ClassParserInterface {
return null;
}
+ @Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
if (name.equals(slashedClassName) && outerName != null) {
if (cBuilder instanceof ClassInfo.Builder) {
@@ -186,339 +604,29 @@ public class ClassParserUsingASM implements ClassParserInterface {
}
+ @Override
public MethodVisitor visitMethod(final int access, final String methodName, final String methodDesc,
String signature, String[] exceptions) {
if (cBuilder instanceof ClassInfo.Builder) {
final MethodInfo.Builder mBuilder = new MethodInfo.Builder(slashedClassName, methodName, methodDesc, access);
mBuilder.setSourceSignature(signature);
mBuilder.setThrownExceptions(exceptions);
- if ((access & Opcodes.ACC_SYNCHRONIZED) != 0)
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
mBuilder.setUsesConcurrency();
+ }
- return new AbstractMethodVisitor() {
-
- boolean sawReturn = (access & Opcodes.ACC_NATIVE) != 0;
-
- boolean sawNormalThrow = false;
-
- boolean sawUnsupportedThrow = false;
-
- boolean sawSystemExit = false;
-
- boolean sawBranch = false;
-
- boolean sawBackBranch = false;
-
- int methodCallCount = 0;
- int fieldInstructionCount = 0;
-
- boolean sawStubThrow = false;
-
- boolean justSawInitializationOfUnsupportedOperationException;
-
- boolean isBridge = (access & Opcodes.ACC_SYNTHETIC) != 0 && (access & Opcodes.ACC_BRIDGE) != 0;
-
- String bridgedMethodSignature;
-
- IdentityMethodState identityState =
- IdentityMethodState.INITIAL;
-
- ParameterLoadState parameterLoadState = ParameterLoadState.OTHER;
-
- int parameterForLoadState;
-
- StubState stubState = StubState.INITIAL;
-
- boolean isAccessMethod = methodName.startsWith("access$");
-
- String accessOwner, accessName, accessDesc;
-
- boolean accessForField;
- boolean accessIsStatic;
-
- HashSet<Label> labelsSeen = new HashSet<Label>();
-
- boolean isStatic() {
- return (access & Opcodes.ACC_STATIC) != 0;
- }
-
- @Override
- public
- void visitLocalVariable(String name,
- String desc,
- String signature,
- Label start,
- Label end,
- int index) {
- mBuilder.setVariableHasName(index);
-
- }
-
- @Override
- public void visitLdcInsn(Object cst) {
- if (cst.equals("Stub!"))
- stubState = StubState.LOADED_STUB;
- else
- stubState = StubState.INITIAL;
- identityState = IdentityMethodState.NOT;
- }
-
- @Override
- public void visitInsn(int opcode) {
- switch (opcode) {
- case Constants.MONITORENTER:
- mBuilder.setUsesConcurrency();
- break;
- case Constants.ARETURN:
- case Constants.IRETURN:
- case Constants.LRETURN:
- case Constants.DRETURN:
- case Constants.FRETURN:
- if (identityState == IdentityMethodState.LOADED_PARAMETER)
- mBuilder.setIsIdentity();
- sawReturn = true;
- break;
- case Constants.RETURN:
- sawReturn = true;
- break;
- case Constants.ATHROW:
- if (stubState == StubState.INITIALIZE_RUNTIME)
- sawStubThrow = true;
- else if (justSawInitializationOfUnsupportedOperationException)
- sawUnsupportedThrow = true;
- else
- sawNormalThrow = true;
- break;
- }
-
- resetState();
- }
-
- public void resetState() {
- stubState = StubState.INITIAL;
- }
-
- @Override
- public void visitSomeInsn() {
- identityState = IdentityMethodState.NOT;
- parameterLoadState = ParameterLoadState.OTHER;
- resetState();
- }
-
- @Override
- public void visitVarInsn(int opcode, int var) {
-
- boolean match = false;
- if (parameterLoadState == ParameterLoadState.OTHER && !isStatic() && var == 0) {
- parameterLoadState = ParameterLoadState.LOADED_THIS;
-
- match = true;
- }
- else if (parameterLoadState == ParameterLoadState.LOADED_THIS && var > 0){
- parameterLoadState = ParameterLoadState.LOADED_THIS_AND_PARAMETER;
- parameterForLoadState = var;
- match = true;
- }
-
- if (identityState == IdentityMethodState.INITIAL) {
- match = true;
- if (var > 0 || isStatic())
- identityState = IdentityMethodState.LOADED_PARAMETER;
- else
- identityState = IdentityMethodState.NOT;
-
- }
- if (!match)
- visitSomeInsn();
- }
-
- @Override
- public void visitFieldInsn(int opcode,
- String owner,
- String name,
- String desc) {
- if (opcode == Opcodes.PUTFIELD && parameterLoadState == ParameterLoadState.LOADED_THIS_AND_PARAMETER
- && owner.equals(slashedClassName) && name.startsWith("this$")) {
- mBuilder.setVariableIsSynthetic(parameterForLoadState);
- }
- fieldInstructionCount++;
-
- if (isAccessMethod && this.accessOwner == null) {
- this.accessOwner = owner;
- this.accessName = name;
- this.accessDesc = desc;
- this.accessIsStatic = opcode == Opcodes.GETSTATIC || opcode == Opcodes.PUTSTATIC;
- this.accessForField = true;
- }
- visitSomeInsn();
- }
-
- public org.objectweb.asm.AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
- AnnotationValue value = new AnnotationValue(desc);
- mBuilder.addAnnotation(desc, value);
- return value.getAnnotationVisitor();
- }
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
- identityState = IdentityMethodState.NOT;
- methodCallCount++;
- if (isAccessMethod && this.accessOwner == null) {
- this.accessOwner = owner;
- this.accessName = name;
- this.accessDesc = desc;
- this.accessIsStatic = opcode == Opcodes.INVOKESTATIC;
- this.accessForField = false;
- }
- if (stubState == StubState.LOADED_STUB && opcode == Opcodes.INVOKESPECIAL
- && owner.equals("java/lang/RuntimeException") && name.equals("<init>"))
- stubState = StubState.INITIALIZE_RUNTIME;
- else
- stubState = StubState.INITIAL;
- if (owner.startsWith("java/util/concurrent"))
- mBuilder.setUsesConcurrency();
- if (opcode == Opcodes.INVOKEINTERFACE)
- return;
-
- if (owner.charAt(0) == '[' && owner.charAt(owner.length() - 1) != ';') {
- // primitive array
- return;
- }
- if (opcode == Opcodes.INVOKESTATIC && owner.equals("java/lang/System") && name.equals("exit")
- && !sawReturn)
- sawSystemExit = true;
- justSawInitializationOfUnsupportedOperationException = opcode == Opcodes.INVOKESPECIAL
- && owner.equals("java/lang/UnsupportedOperationException") && name.equals("<init>");
-
- if (isBridge && bridgedMethodSignature == null)
- switch (opcode) {
- case Opcodes.INVOKEVIRTUAL:
- case Opcodes.INVOKESPECIAL:
- case Opcodes.INVOKESTATIC:
- case Opcodes.INVOKEINTERFACE:
- if (desc != null && name.equals(methodName))
- bridgedMethodSignature = desc;
- }
-
- // System.out.println("Call from " +
- // ClassParserUsingASM.this.slashedClassName +
- // " to " + owner + " : " + desc);
- if (desc == null || desc.indexOf('[') == -1 && desc.indexOf('L') == -1)
- return;
- if (ClassParserUsingASM.this.slashedClassName.equals(owner))
- return;
- ClassDescriptor classDescriptor = DescriptorFactory.instance().getClassDescriptor(owner);
- calledClassSet.add(classDescriptor);
-
- }
-
- private void sawBranchTo(Label label) {
- sawBranch = true;
- if (labelsSeen.contains(label))
- sawBackBranch = true;
- }
-
- @Override
- public void visitJumpInsn(int opcode, Label label) {
- sawBranchTo(label);
- identityState = IdentityMethodState.NOT;
- super.visitJumpInsn(opcode, label);
- }
-
- @Override
- public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
- sawBranchTo(dflt);
- for (Label lbl : labels)
- sawBranchTo(lbl);
- identityState = IdentityMethodState.NOT;
- super.visitLookupSwitchInsn(dflt, keys, labels);
- }
-
- @Override
- public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
- sawBranchTo(dflt);
- for (Label lbl : labels)
- sawBranchTo(lbl);
- identityState = IdentityMethodState.NOT;
- super.visitTableSwitchInsn(min, max, dflt, labels);
- }
-
- @Override
- public void visitLabel(Label label) {
- labelsSeen.add(label);
- super.visitLabel(label);
-
- }
-
- public void visitEnd() {
- labelsSeen.clear();
- if (isAccessMethod && accessOwner != null) {
- if (!accessForField && methodCallCount == 1) {
- mBuilder.setAccessMethodForMethod(accessOwner, accessName, accessDesc, accessIsStatic);
- } else if(accessForField && fieldInstructionCount == 1) {
- boolean isSetter = methodDesc.endsWith(")V");
- int numArg = new SignatureParser(methodDesc).getNumParameters();
- int expected = 0;
- if (!accessIsStatic) expected++;
- if (isSetter) expected++;
- boolean OK;
- if (isSetter)
- OK = methodDesc.substring(1).startsWith(ClassName.toSignature(accessOwner) + accessDesc);
- else
- OK = methodDesc.substring(1).startsWith(ClassName.toSignature(accessOwner));
- if (numArg == expected && OK)
- mBuilder.setAccessMethodForField(accessOwner, accessName, accessDesc, accessIsStatic);
- }
- }
- if (sawBackBranch)
- mBuilder.setHasBackBranch();
- boolean sawThrow = sawNormalThrow | sawUnsupportedThrow | sawStubThrow;
- if (sawThrow && !sawReturn || sawSystemExit && !sawBranch) {
-
- mBuilder.setIsUnconditionalThrower();
- if (!sawReturn && !sawNormalThrow) {
- if (sawUnsupportedThrow)
- mBuilder.setUnsupported();
- if (sawStubThrow) {
- mBuilder.addAccessFlags(Constants.ACC_SYNTHETIC);
- mBuilder.setIsStub();
-
- }
- }
- // else
- // System.out.println(slashedClassName+"."+methodName+methodDesc
- // + " is thrower");
- }
- mBuilder.setNumberMethodCalls(methodCallCount);
- MethodInfo methodInfo = mBuilder.build();
- Builder classBuilder = (ClassInfo.Builder) cBuilder;
- if (isBridge && bridgedMethodSignature != null && !bridgedMethodSignature.equals(methodDesc))
- classBuilder.addBridgeMethodDescriptor(methodInfo, bridgedMethodSignature);
- else
- classBuilder.addMethodDescriptor(methodInfo);
-
- if (methodInfo.usesConcurrency())
- classBuilder.setUsesConcurrency();
- if (methodInfo.isStub())
- classBuilder.setHasStubs();
- }
-
- public org.objectweb.asm.AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
- boolean visible) {
- AnnotationValue value = new AnnotationValue(desc);
- mBuilder.addParameterAnnotation(parameter, desc, value);
- return value.getAnnotationVisitor();
- }
- };
+ return new ClassParserMethodVisitor(calledClassSet, mBuilder, methodName, access, methodDesc, cBuilder);
}
return null;
}
+ @Override
public void visitOuterClass(String owner, String name, String desc) {
}
+ @Override
public void visitSource(String arg0, String arg1) {
if (cBuilder instanceof ClassInfo.Builder) {
((ClassInfo.Builder) cBuilder).setSource(arg0);
@@ -545,6 +653,7 @@ public class ClassParserUsingASM implements ClassParserInterface {
case Constants.CONSTANT_Integer:
case Constants.CONSTANT_Float:
case Constants.CONSTANT_NameAndType:
+ case Constants.CONSTANT_InvokeDynamic:
size = 5;
break;
case Constants.CONSTANT_Long:
@@ -566,11 +675,13 @@ public class ClassParserUsingASM implements ClassParserInterface {
}
size = 3;
break;
- // case ClassWriter.CLASS:
- // case ClassWriter.STR:
case Constants.CONSTANT_String:
+ case Constants.CONSTANT_MethodType:
size = 3;
break;
+ case Constants.CONSTANT_MethodHandle:
+ size = 4;
+ break;
default:
throw new IllegalStateException("Unexpected tag of " + tag + " at offset " + offset + " while parsing "
+ slashedClassName + " from " + codeBaseEntry);
@@ -583,6 +694,7 @@ public class ClassParserUsingASM implements ClassParserInterface {
cBuilder.setReferencedClassDescriptors(referencedClassSet);
}
+ @Override
public void parse(ClassInfo.Builder builder) throws InvalidClassFileFormatException {
parse((ClassNameAndSuperclassInfo.Builder) builder);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserUsingBCEL.java b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserUsingBCEL.java
index 10fb39f..7adbd53 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserUsingBCEL.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/ClassParserUsingBCEL.java
@@ -68,40 +68,44 @@ public class ClassParserUsingBCEL implements ClassParserInterface {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.engine.ClassParserInterface#parse(edu.umd
* .cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo.Builder)
*/
+ @Override
public void parse(final ClassNameAndSuperclassInfo.Builder builder) throws InvalidClassFileFormatException {
builder.setCodeBaseEntry(codeBaseEntry);
builder.setAccessFlags(javaClass.getAccessFlags());
ClassDescriptor classDescriptor = DescriptorFactory.createClassDescriptorFromDottedClassName(javaClass.getClassName());
- if (expectedClassDescriptor != null && expectedClassDescriptor.equals(classDescriptor))
+ if (expectedClassDescriptor != null && expectedClassDescriptor.equals(classDescriptor)) {
throw new InvalidClassFileFormatException("Expected " + expectedClassDescriptor, classDescriptor, codeBaseEntry);
+ }
builder.setClassDescriptor(classDescriptor);
builder.setSuperclassDescriptor(DescriptorFactory.createClassDescriptorFromDottedClassName(javaClass.getSuperclassName()));
String[] allInterfaces = javaClass.getInterfaceNames();
ClassDescriptor[] allInterfaceDescriptiors;
- if (allInterfaces.length == 0)
+ if (allInterfaces.length == 0) {
allInterfaceDescriptiors = ClassDescriptor.EMPTY_ARRAY;
- else {
+ } else {
allInterfaceDescriptiors = new ClassDescriptor[allInterfaces.length];
- for (int i = 0; i < allInterfaces.length; i++)
+ for (int i = 0; i < allInterfaces.length; i++) {
allInterfaceDescriptiors[i] = DescriptorFactory.createClassDescriptorFromDottedClassName(allInterfaces[i]);
+ }
}
builder.setInterfaceDescriptorList(allInterfaceDescriptiors);
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.engine.ClassParserInterface#parse(edu.umd
* .cs.findbugs.classfile.analysis.ClassInfo.Builder)
*/
+ @Override
public void parse(ClassInfo.Builder builder) throws InvalidClassFileFormatException {
parse((ClassNameAndSuperclassInfo.Builder) builder);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/EngineRegistrar.java b/src/java/edu/umd/cs/findbugs/classfile/engine/EngineRegistrar.java
index 575d50f..9b47740 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/EngineRegistrar.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/EngineRegistrar.java
@@ -27,12 +27,12 @@ import edu.umd.cs.findbugs.classfile.engine.asm.ClassReaderAnalysisEngine;
/**
* Register analysis engines with an analysis cache.
- *
+ *
* @author David Hovemeyer
*/
public class EngineRegistrar implements IAnalysisEngineRegistrar {
private static IClassAnalysisEngine<?>[] classAnalysisEngineList = { new ClassDataAnalysisEngine(),
- new ClassInfoAnalysisEngine(), new ClassNameAndSuperclassInfoAnalysisEngine(), new ClassReaderAnalysisEngine() };
+ new ClassInfoAnalysisEngine(), new ClassNameAndSuperclassInfoAnalysisEngine(), new ClassReaderAnalysisEngine() };
private static IMethodAnalysisEngine<?>[] methodAnalysisEngineList = {};
@@ -44,11 +44,12 @@ public class EngineRegistrar implements IAnalysisEngineRegistrar {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngineRegistrar#registerWith(edu
* .umd.cs.findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerAnalysisEngines(IAnalysisCache analysisCache) {
for (IClassAnalysisEngine<?> engine : classAnalysisEngineList) {
engine.registerWith(analysisCache);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/SelfMethodCalls.java b/src/java/edu/umd/cs/findbugs/classfile/engine/SelfMethodCalls.java
index 09bb746..ee1752b 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/SelfMethodCalls.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/SelfMethodCalls.java
@@ -23,15 +23,16 @@ import java.util.HashSet;
import java.util.Map;
import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.commons.EmptyVisitor;
import edu.umd.cs.findbugs.asm.FBClassReader;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.classfile.engine.asm.FindBugsASM;
import edu.umd.cs.findbugs.util.MultiMap;
/**
@@ -40,7 +41,7 @@ import edu.umd.cs.findbugs.util.MultiMap;
public class SelfMethodCalls {
static private boolean interestingSignature(String signature) {
- return !signature.equals("()V");
+ return !"()V".equals(signature);
}
public static <T> MultiMap<T, T> getSelfCalls(final ClassDescriptor classDescriptor, final Map<String, T> methods) {
@@ -53,14 +54,14 @@ public class SelfMethodCalls {
AnalysisContext.logError("Error finding self method calls for " + classDescriptor, e);
return map;
}
- reader.accept(new EmptyVisitor() {
+ reader.accept(new ClassVisitor(FindBugsASM.ASM_VERSION) {
@Override
public MethodVisitor visitMethod(final int access, final String name, final String desc, String signature,
String[] exceptions) {
- return new EmptyVisitor() {
+ return new MethodVisitor(FindBugsASM.ASM_VERSION) {
@Override
- public void visitMethodInsn(int opcode, String owner, String name2, String desc2) {
+ public void visitMethodInsn(int opcode, String owner, String name2, String desc2, boolean itf) {
if (owner.equals(classDescriptor.getClassName()) && interestingSignature(desc2)) {
T from = methods.get(name + desc + ((access & Opcodes.ACC_STATIC) != 0));
T to = methods.get(name2 + desc2 + (opcode == Opcodes.INVOKESTATIC));
@@ -76,9 +77,9 @@ public class SelfMethodCalls {
return map;
}
- private final ClassReader classReader;
+ // private final ClassReader classReader;
public SelfMethodCalls(ClassReader classReader) {
- this.classReader = classReader;
+ // this.classReader = classReader;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/asm/ClassNodeAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/engine/asm/ClassNodeAnalysisEngine.java
index a1ae516..96e2a0d 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/asm/ClassNodeAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/asm/ClassNodeAnalysisEngine.java
@@ -31,18 +31,19 @@ import edu.umd.cs.findbugs.classfile.RecomputableClassAnalysisEngine;
/**
* Analysis engine to produce the ClassNode (ASM tree format) for a class.
- *
+ *
* @author David Hovemeyer
*/
public class ClassNodeAnalysisEngine extends RecomputableClassAnalysisEngine<ClassNode> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ClassNode analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor) throws CheckedAnalysisException {
ClassReader classReader = analysisCache.getClassAnalysis(ClassReader.class, descriptor);
@@ -63,11 +64,12 @@ public class ClassNodeAnalysisEngine extends RecomputableClassAnalysisEngine<Cla
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerClassAnalysisEngine(ClassNode.class, this);
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/asm/ClassReaderAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/engine/asm/ClassReaderAnalysisEngine.java
index 475f437..1267061 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/asm/ClassReaderAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/asm/ClassReaderAnalysisEngine.java
@@ -28,18 +28,19 @@ import edu.umd.cs.findbugs.classfile.analysis.ClassData;
/**
* Analysis engine to produce an ASM ClassReader for a class.
- *
+ *
* @author David Hovemeyer
*/
public class ClassReaderAnalysisEngine extends RecomputableClassAnalysisEngine<FBClassReader> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public FBClassReader analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor) throws CheckedAnalysisException {
ClassData classData = analysisCache.getClassAnalysis(ClassData.class, descriptor);
@@ -51,11 +52,12 @@ public class ClassReaderAnalysisEngine extends RecomputableClassAnalysisEngine<F
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerClassAnalysisEngine(FBClassReader.class, this);
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/asm/EngineRegistrar.java b/src/java/edu/umd/cs/findbugs/classfile/engine/asm/EngineRegistrar.java
index 968f0cf..1ba9d2e 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/asm/EngineRegistrar.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/asm/EngineRegistrar.java
@@ -26,12 +26,12 @@ import edu.umd.cs.findbugs.classfile.IMethodAnalysisEngine;
/**
* Analysis engine registrar for ASM-based analyses.
- *
+ *
* @author David Hovemeyer
*/
public class EngineRegistrar implements IAnalysisEngineRegistrar {
private static final IClassAnalysisEngine<?>[] classAnalysisEngineList = { new ClassNodeAnalysisEngine(),
- new ClassReaderAnalysisEngine(), };
+ new ClassReaderAnalysisEngine(), };
private static IMethodAnalysisEngine<?>[] methodAnalysisEngineList = {};
@@ -43,10 +43,11 @@ public class EngineRegistrar implements IAnalysisEngineRegistrar {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.IAnalysisEngineRegistrar#
* registerAnalysisEngines(edu.umd.cs.findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerAnalysisEngines(IAnalysisCache analysisCache) {
for (IClassAnalysisEngine<?> engine : classAnalysisEngineList) {
engine.registerWith(analysisCache);
diff --git a/src/java/edu/umd/cs/findbugs/ba/ComparableMethod.java b/src/java/edu/umd/cs/findbugs/classfile/engine/asm/FindBugsASM.java
similarity index 82%
copy from src/java/edu/umd/cs/findbugs/ba/ComparableMethod.java
copy to src/java/edu/umd/cs/findbugs/classfile/engine/asm/FindBugsASM.java
index e8ed264..7f46704 100644
--- a/src/java/edu/umd/cs/findbugs/ba/ComparableMethod.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/asm/FindBugsASM.java
@@ -1,27 +1,31 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package edu.umd.cs.findbugs.ba;
+package edu.umd.cs.findbugs.classfile.engine.asm;
+
+import org.objectweb.asm.Opcodes;
/**
* @author pugh
*/
-public interface ComparableMethod extends Comparable<ComparableMethod> {
+public class FindBugsASM {
+
+ public static final int ASM_VERSION = Opcodes.ASM5;
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AnalysisFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AnalysisFactory.java
index 8be5398..b489d97 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AnalysisFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AnalysisFactory.java
@@ -43,13 +43,13 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
* Abstract factory class for creating analysis objects.
*/
public abstract class AnalysisFactory<Analysis> implements IMethodAnalysisEngine<Analysis> {
- private String analysisName;
+ private final String analysisName;
- private Class<Analysis> analysisClass;
+ private final Class<Analysis> analysisClass;
/**
* Constructor.
- *
+ *
* @param analysisName
* name of the analysis factory: for diagnostics/debugging
*/
@@ -71,11 +71,12 @@ public abstract class AnalysisFactory<Analysis> implements IMethodAnalysisEngine
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerMethodAnalysisEngine(analysisClass, this);
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AssertionMethodsFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AssertionMethodsFactory.java
index 8808f50..732d695 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AssertionMethodsFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AssertionMethodsFactory.java
@@ -29,11 +29,12 @@ import edu.umd.cs.findbugs.classfile.RecomputableClassAnalysisEngine;
/**
* Class analysis engine for creating AssertionMethods objects.
- *
+ *
* @author David Hovemeyer
*/
public class AssertionMethodsFactory extends RecomputableClassAnalysisEngine<AssertionMethods> {
+ @Override
public AssertionMethods analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor) throws CheckedAnalysisException {
JavaClass jclass = analysisCache.getClassAnalysis(JavaClass.class, descriptor);
return new AssertionMethods(jclass);
@@ -41,11 +42,12 @@ public class AssertionMethodsFactory extends RecomputableClassAnalysisEngine<Ass
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerClassAnalysisEngine(AssertionMethods.class, this);
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AssignedFieldMapFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AssignedFieldMapFactory.java
index 8490b40..6e326bb 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AssignedFieldMapFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/AssignedFieldMapFactory.java
@@ -27,18 +27,19 @@ import edu.umd.cs.findbugs.classfile.RecomputableClassAnalysisEngine;
/**
* Analysis engine for producing an AssignedFieldMap for a class.
- *
+ *
* @author David Hovemeyer
*/
public class AssignedFieldMapFactory extends RecomputableClassAnalysisEngine<AssignedFieldMap> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public AssignedFieldMap analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor) throws CheckedAnalysisException {
/*
* JavaClass jclass = analysisCache.getClassAnalysis(JavaClass.class,
@@ -49,11 +50,12 @@ public class AssignedFieldMapFactory extends RecomputableClassAnalysisEngine<Ass
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
/*
* analysisCache.registerClassAnalysisEngine(AssignedFieldMap.class,
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/BackwardTypeQualifierDataflowFactoryFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/BackwardTypeQualifierDataflowFactoryFactory.java
index 28286ea..e617143 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/BackwardTypeQualifierDataflowFactoryFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/BackwardTypeQualifierDataflowFactoryFactory.java
@@ -26,7 +26,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Factory to create BackwardTypeQualifierDataflowFactory objects.
- *
+ *
* @author David Hovemeyer
*/
public class BackwardTypeQualifierDataflowFactoryFactory extends AnalysisFactory<BackwardTypeQualifierDataflowFactory> {
@@ -36,11 +36,12 @@ public class BackwardTypeQualifierDataflowFactoryFactory extends AnalysisFactory
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public BackwardTypeQualifierDataflowFactory analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
throws CheckedAnalysisException {
return new BackwardTypeQualifierDataflowFactory(descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/BlockTypeAnalysisFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/BlockTypeAnalysisFactory.java
index d32d578..2396b87 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/BlockTypeAnalysisFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/BlockTypeAnalysisFactory.java
@@ -10,7 +10,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine for producing BlockTypeDataflow for an analyzed method.
- *
+ *
* @author David Hovemeyer
*/
public class BlockTypeAnalysisFactory extends AnalysisFactory<BlockTypeDataflow> {
@@ -20,11 +20,12 @@ public class BlockTypeAnalysisFactory extends AnalysisFactory<BlockTypeDataflow>
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public BlockTypeDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
CFG cfg = getCFG(analysisCache, descriptor);
DepthFirstSearch dfs = getDepthFirstSearch(analysisCache, descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CFGFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CFGFactory.java
index 860b949..68629eb 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CFGFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CFGFactory.java
@@ -59,7 +59,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce CFG (control flow graph) objects for an analyzed
* method.
- *
+ *
* @author David Hovemeyer
*/
public class CFGFactory extends AnalysisFactory<CFG> {
@@ -74,11 +74,12 @@ public class CFGFactory extends AnalysisFactory<CFG> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public CFG analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
// Construct the CFG in its raw form
MethodGen methodGen = analysisCache.getMethodAnalysis(MethodGen.class, descriptor);
@@ -132,9 +133,10 @@ public class CFGFactory extends AnalysisFactory<CFG> {
if (prevInstruction instanceof GETSTATIC && lastInstruction instanceof IFNE) {
GETSTATIC getStatic = (GETSTATIC) prevInstruction;
- if (getStatic.getFieldName(methodGen.getConstantPool()).equals("$assertionsDisabled")
- && getStatic.getSignature(methodGen.getConstantPool()).equals("Z"))
+ if ("$assertionsDisabled".equals(getStatic.getFieldName(methodGen.getConstantPool()))
+ && "Z".equals(getStatic.getSignature(methodGen.getConstantPool()))) {
edgesToRemove.add(e);
+ }
}
} catch (RuntimeException exception) {
assert true; // ignore it
@@ -163,10 +165,10 @@ public class CFGFactory extends AnalysisFactory<CFG> {
changed = changed || pruner.wasCFGModified();
} catch (MissingClassException e) {
AnalysisContext.currentAnalysisContext().getLookupFailureCallback()
- .reportMissingClass(e.getClassNotFoundException());
+ .reportMissingClass(e.getClassNotFoundException());
} catch (DataflowAnalysisException e) {
AnalysisContext.currentAnalysisContext().getLookupFailureCallback()
- .logError("unable to extract type analysis", e);
+ .logError("unable to extract type analysis", e);
} catch (ClassNotFoundException e) {
AnalysisContext.currentAnalysisContext().getLookupFailureCallback().reportMissingClass(e);
}
@@ -209,11 +211,13 @@ public class CFGFactory extends AnalysisFactory<CFG> {
dfs.search();
Collection<BasicBlock> unreachable = dfs.unvisitedVertices();
if (!unreachable.isEmpty()) {
- if (DEBUG_CFG)
+ if (DEBUG_CFG) {
System.out.println("Unreachable blocks");
+ }
for (BasicBlock b : unreachable) {
- if (DEBUG_CFG)
+ if (DEBUG_CFG) {
System.out.println(" removing " + b);
+ }
cfg.removeVertex(b);
}
}
@@ -225,7 +229,7 @@ public class CFGFactory extends AnalysisFactory<CFG> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CallListDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CallListDataflowFactory.java
index a4cbbe9..6225587 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CallListDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CallListDataflowFactory.java
@@ -8,7 +8,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce CallListDataflow objects for a method.
- *
+ *
* @author David Hovemeyer
*/
public class CallListDataflowFactory extends AnalysisFactory<CallListDataflow> {
@@ -18,11 +18,12 @@ public class CallListDataflowFactory extends AnalysisFactory<CallListDataflow> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public CallListDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
CallListAnalysis analysis = new CallListAnalysis(getCFG(analysisCache, descriptor), getDepthFirstSearch(analysisCache,
descriptor), getConstantPoolGen(analysisCache, descriptor.getClassDescriptor()));
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ClassContextClassAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ClassContextClassAnalysisEngine.java
index 3ca2411..bc811d5 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ClassContextClassAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ClassContextClassAnalysisEngine.java
@@ -31,18 +31,19 @@ import edu.umd.cs.findbugs.classfile.RecomputableClassAnalysisEngine;
/**
* Adapter to produce the ClassContext for a given class. This is
* backwards-compatibility for the BCEL-based analysis framework.
- *
+ *
* @author David Hovemeyer
*/
public class ClassContextClassAnalysisEngine extends RecomputableClassAnalysisEngine<ClassContext> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ClassContext analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor) throws CheckedAnalysisException {
JavaClass javaClass = analysisCache.getClassAnalysis(JavaClass.class, descriptor);
@@ -52,11 +53,12 @@ public class ClassContextClassAnalysisEngine extends RecomputableClassAnalysisEn
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerClassAnalysisEngine(ClassContext.class, this);
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CompactLocationNumberingFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CompactLocationNumberingFactory.java
index eccc9d8..39c1279 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CompactLocationNumberingFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/CompactLocationNumberingFactory.java
@@ -28,7 +28,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce CompactLocationNumbering objects for methods.
- *
+ *
* @author David Hovemeyer
*/
public class CompactLocationNumberingFactory extends AnalysisFactory<CompactLocationNumbering> {
@@ -41,11 +41,12 @@ public class CompactLocationNumberingFactory extends AnalysisFactory<CompactLoca
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public CompactLocationNumbering analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
throws CheckedAnalysisException {
Method method = analysisCache.getMethodAnalysis(Method.class, descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ConstantDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ConstantDataflowFactory.java
index 60239ea..d1b1cc1 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ConstantDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ConstantDataflowFactory.java
@@ -10,7 +10,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce ConstantDataflow objects for an analyzed method.
- *
+ *
* @author David Hovemeyer
*/
public class ConstantDataflowFactory extends AnalysisFactory<ConstantDataflow> {
@@ -20,15 +20,17 @@ public class ConstantDataflowFactory extends AnalysisFactory<ConstantDataflow> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ConstantDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
MethodGen methodGen = getMethodGen(analysisCache, descriptor);
- if (methodGen == null)
+ if (methodGen == null) {
return null;
+ }
ConstantAnalysis analysis = new ConstantAnalysis(methodGen, getDepthFirstSearch(analysisCache, descriptor));
ConstantDataflow dataflow = new ConstantDataflow(getCFG(analysisCache, descriptor), analysis);
dataflow.execute();
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ConstantPoolGenFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ConstantPoolGenFactory.java
index 29c8e66..0bc87bb 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ConstantPoolGenFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ConstantPoolGenFactory.java
@@ -30,18 +30,19 @@ import edu.umd.cs.findbugs.classfile.RecomputableClassAnalysisEngine;
/**
* Analysis engine to produce ConstantPoolGen objects for an analyzed class.
- *
+ *
* @author David Hovemeyer
*/
public class ConstantPoolGenFactory extends RecomputableClassAnalysisEngine<ConstantPoolGen> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ConstantPoolGen analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor) throws CheckedAnalysisException {
ClassGen classGen = new ClassGen(analysisCache.getClassAnalysis(JavaClass.class, descriptor));
return classGen.getConstantPool();
@@ -49,11 +50,12 @@ public class ConstantPoolGenFactory extends RecomputableClassAnalysisEngine<Cons
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerClassAnalysisEngine(ConstantPoolGen.class, this);
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/DepthFirstSearchFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/DepthFirstSearchFactory.java
index 5d804ca..f069426 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/DepthFirstSearchFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/DepthFirstSearchFactory.java
@@ -26,7 +26,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce DepthFirstSearch objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class DepthFirstSearchFactory extends AnalysisFactory<DepthFirstSearch> {
@@ -39,11 +39,12 @@ public class DepthFirstSearchFactory extends AnalysisFactory<DepthFirstSearch> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public DepthFirstSearch analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
CFG cfg = getCFG(analysisCache, descriptor);
DepthFirstSearch dfs = new DepthFirstSearch(cfg);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/DominatorsAnalysisFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/DominatorsAnalysisFactory.java
index 4cc2c88..df9e32b 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/DominatorsAnalysisFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/DominatorsAnalysisFactory.java
@@ -10,7 +10,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce DominatorsAnalysis objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class DominatorsAnalysisFactory extends AnalysisFactory<DominatorsAnalysis> {
@@ -23,11 +23,12 @@ public class DominatorsAnalysisFactory extends AnalysisFactory<DominatorsAnalysi
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public DominatorsAnalysis analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
CFG cfg = getCFG(analysisCache, descriptor);
DepthFirstSearch dfs = getDepthFirstSearch(analysisCache, descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/EngineRegistrar.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/EngineRegistrar.java
index ecc538c..3ca9143 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/EngineRegistrar.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/EngineRegistrar.java
@@ -54,38 +54,39 @@ import edu.umd.cs.findbugs.classfile.analysis.MethodInfo.MethodInfoDatabase;
*/
public class EngineRegistrar implements IAnalysisEngineRegistrar {
private static final IClassAnalysisEngine<?>[] classAnalysisEngineList = { new ClassContextClassAnalysisEngine(),
- new JavaClassAnalysisEngine(), new ConstantPoolGenFactory(),
- // new AssignedFieldMapFactory(),
- new AssertionMethodsFactory(), };
+ new JavaClassAnalysisEngine(), new ConstantPoolGenFactory(),
+ // new AssignedFieldMapFactory(),
+ new AssertionMethodsFactory(), };
private static final IMethodAnalysisEngine<?>[] methodAnalysisEngineList = { new MethodFactory(), new MethodGenFactory(),
- new CFGFactory(), new UsagesRequiringNonNullValuesFactory(), new ValueNumberDataflowFactory(),
- new IsNullValueDataflowFactory(), new TypeDataflowFactory(), new DepthFirstSearchFactory(),
- new ReverseDepthFirstSearchFactory(), new UnpackedCodeFactory(), new LockDataflowFactory(), new LockCheckerFactory(),
- new ReturnPathDataflowFactory(), new DominatorsAnalysisFactory(), new NonExceptionPostdominatorsAnalysisFactory(),
- new NonImplicitExceptionPostDominatorsAnalysisFactory(), new ExceptionSetFactoryFactory(),
- new ParameterSignatureListFactory(), new ConstantDataflowFactory(), new LoadDataflowFactory(),
- new StoreDataflowFactory(), new LoadedFieldSetFactory(), new LiveLocalStoreDataflowFactory(),
- new BlockTypeAnalysisFactory(), new CallListDataflowFactory(), new UnconditionalValueDerefDataflowFactory(),
- new CompactLocationNumberingFactory(), new ReturnPathTypeDataflowFactory(),
- new ForwardTypeQualifierDataflowFactoryFactory(), new BackwardTypeQualifierDataflowFactoryFactory(),
- new OpcodeStack.JumpInfoFactory(), new StackMapAnalysisFactory(), new ObligationDataflowFactory(), };
+ new CFGFactory(), new UsagesRequiringNonNullValuesFactory(), new ValueNumberDataflowFactory(),
+ new IsNullValueDataflowFactory(), new TypeDataflowFactory(), new DepthFirstSearchFactory(),
+ new ReverseDepthFirstSearchFactory(), new UnpackedCodeFactory(), new LockDataflowFactory(), new LockCheckerFactory(),
+ new ReturnPathDataflowFactory(), new DominatorsAnalysisFactory(), new NonExceptionPostdominatorsAnalysisFactory(),
+ new NonImplicitExceptionPostDominatorsAnalysisFactory(), new ExceptionSetFactoryFactory(),
+ new ParameterSignatureListFactory(), new ConstantDataflowFactory(), new LoadDataflowFactory(),
+ new StoreDataflowFactory(), new LoadedFieldSetFactory(), new LiveLocalStoreDataflowFactory(),
+ new BlockTypeAnalysisFactory(), new CallListDataflowFactory(), new UnconditionalValueDerefDataflowFactory(),
+ new CompactLocationNumberingFactory(), new ReturnPathTypeDataflowFactory(),
+ new ForwardTypeQualifierDataflowFactoryFactory(), new BackwardTypeQualifierDataflowFactoryFactory(),
+ new OpcodeStack.JumpInfoFactory(), new StackMapAnalysisFactory(), new ObligationDataflowFactory(),
+ new ValueRangeAnalysisFactory(), new FinallyDuplicatesInfoFactory()};
private static final IDatabaseFactory<?>[] databaseFactoryList = {
- // new ReflectionDatabaseFactory<Subtypes>(Subtypes.class),
- new ReflectionDatabaseFactory<Subtypes2>(Subtypes2.class),
- new ReflectionDatabaseFactory<InnerClassAccessMap>(InnerClassAccessMap.class),
- new ReflectionDatabaseFactory<CheckReturnAnnotationDatabase>(CheckReturnAnnotationDatabase.class),
- new ReflectionDatabaseFactory<AnnotationRetentionDatabase>(AnnotationRetentionDatabase.class),
- new ReflectionDatabaseFactory<JCIPAnnotationDatabase>(JCIPAnnotationDatabase.class),
- new ReflectionDatabaseFactory<SourceInfoMap>(SourceInfoMap.class),
- new ReflectionDatabaseFactory<FieldStoreTypeDatabase>(FieldStoreTypeDatabase.class),
- new ReflectionDatabaseFactory<ParameterNullnessPropertyDatabase>(ParameterNullnessPropertyDatabase.class),
- new ReflectionDatabaseFactory<ReturnValueNullnessPropertyDatabase>(ReturnValueNullnessPropertyDatabase.class),
- new ReflectionDatabaseFactory<DirectlyRelevantTypeQualifiersDatabase>(DirectlyRelevantTypeQualifiersDatabase.class),
- new ReflectionDatabaseFactory<TypeQualifierDatabase>(TypeQualifierDatabase.class),
- new ReflectionDatabaseFactory<MethodInfoDatabase>(MethodInfoDatabase.class),
- };
+ // new ReflectionDatabaseFactory<Subtypes>(Subtypes.class),
+ new ReflectionDatabaseFactory<Subtypes2>(Subtypes2.class),
+ new ReflectionDatabaseFactory<InnerClassAccessMap>(InnerClassAccessMap.class),
+ new ReflectionDatabaseFactory<CheckReturnAnnotationDatabase>(CheckReturnAnnotationDatabase.class),
+ new ReflectionDatabaseFactory<AnnotationRetentionDatabase>(AnnotationRetentionDatabase.class),
+ new ReflectionDatabaseFactory<JCIPAnnotationDatabase>(JCIPAnnotationDatabase.class),
+ new ReflectionDatabaseFactory<SourceInfoMap>(SourceInfoMap.class),
+ new ReflectionDatabaseFactory<FieldStoreTypeDatabase>(FieldStoreTypeDatabase.class),
+ new ReflectionDatabaseFactory<ParameterNullnessPropertyDatabase>(ParameterNullnessPropertyDatabase.class),
+ new ReflectionDatabaseFactory<ReturnValueNullnessPropertyDatabase>(ReturnValueNullnessPropertyDatabase.class),
+ new ReflectionDatabaseFactory<DirectlyRelevantTypeQualifiersDatabase>(DirectlyRelevantTypeQualifiersDatabase.class),
+ new ReflectionDatabaseFactory<TypeQualifierDatabase>(TypeQualifierDatabase.class),
+ new ReflectionDatabaseFactory<MethodInfoDatabase>(MethodInfoDatabase.class),
+ };
/*
* (non-Javadoc)
@@ -93,6 +94,7 @@ public class EngineRegistrar implements IAnalysisEngineRegistrar {
* @see edu.umd.cs.findbugs.classfile.IAnalysisEngineRegistrar#
* registerAnalysisEngines(edu.umd.cs.findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerAnalysisEngines(IAnalysisCache analysisCache) {
for (IClassAnalysisEngine<?> engine : classAnalysisEngineList) {
engine.registerWith(analysisCache);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ExceptionSetFactoryFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ExceptionSetFactoryFactory.java
index a47fad8..fd1fc6f 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ExceptionSetFactoryFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ExceptionSetFactoryFactory.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce ExceptionSetFactory objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class ExceptionSetFactoryFactory extends AnalysisFactory<ExceptionSetFactory> {
@@ -38,11 +38,12 @@ public class ExceptionSetFactoryFactory extends AnalysisFactory<ExceptionSetFact
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ExceptionSetFactory analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
return new ExceptionSetFactory();
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/FinallyDuplicatesInfoFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/FinallyDuplicatesInfoFactory.java
new file mode 100644
index 0000000..4ec93a8
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/FinallyDuplicatesInfoFactory.java
@@ -0,0 +1,360 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.classfile.engine.bcel;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.bcel.classfile.CodeException;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.ALOAD;
+import org.apache.bcel.generic.ASTORE;
+import org.apache.bcel.generic.ATHROW;
+import org.apache.bcel.generic.BranchInstruction;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.InstructionList;
+import org.apache.bcel.generic.JSR;
+import org.apache.bcel.generic.LocalVariableInstruction;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.StoreInstruction;
+
+import edu.umd.cs.findbugs.ba.CFG;
+import edu.umd.cs.findbugs.ba.Edge;
+import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
+import edu.umd.cs.findbugs.classfile.IAnalysisCache;
+import edu.umd.cs.findbugs.classfile.IMethodAnalysisEngine;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+
+/**
+ * @author Tagir Valeev
+ */
+public class FinallyDuplicatesInfoFactory implements IMethodAnalysisEngine<FinallyDuplicatesInfoFactory.FinallyDuplicatesInfo> {
+ private static final FinallyDuplicatesInfo NONE_FINALLY_INFO = new FinallyDuplicatesInfo();
+
+ public static class FinallyDuplicatesInfo {
+ private final List<SortedMap<Integer, Integer>> duplicateBlocks;
+ private final int[] positions;
+
+ public FinallyDuplicatesInfo(int[] positions, List<SortedMap<Integer, Integer>> duplicateBlocks) {
+ this.positions = positions;
+ this.duplicateBlocks = duplicateBlocks;
+ }
+
+ public FinallyDuplicatesInfo() {
+ this.duplicateBlocks = null;
+ this.positions = null;
+ }
+
+ public BitSet getDuplicates(int pos) {
+ if(duplicateBlocks == null) {
+ return new BitSet();
+ }
+ BitSet current = new BitSet();
+ current.set(pos);
+ boolean changed;
+ do {
+ changed = false;
+ for(SortedMap<Integer, Integer> duplicates : duplicateBlocks) {
+ for (int i = current.nextSetBit(0); i >= 0; i = current.nextSetBit(i+1)) {
+ int offset = getOffset(duplicates, i);
+ if(offset >= 0) {
+ for(Integer key : duplicates.keySet()) {
+ int dupPosition = positions[getInstructionNumber(positions, key)+offset];
+ if(!current.get(dupPosition)) {
+ changed = true;
+ current.set(dupPosition);
+ }
+ }
+ }
+ }
+ }
+ } while(changed && duplicateBlocks.size() > 1);
+ current.clear(pos);
+ return current;
+ }
+
+ public List<Edge> getDuplicates(CFG cfg, Edge edge) {
+ InstructionHandle ih = edge.getSource().getLastInstruction();
+ if(ih == null) {
+ return Collections.emptyList();
+ }
+ BitSet duplicates = getDuplicates(ih.getPosition());
+ if(duplicates.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List<Edge> result = new ArrayList<>();
+ for(Iterator<Edge> edgeIterator = cfg.edgeIterator(); edgeIterator.hasNext(); ) {
+ Edge next = edgeIterator.next();
+ if(next.getType() != edge.getType()) {
+ continue;
+ }
+ InstructionHandle lastInst = next.getSource().getLastInstruction();
+ if(lastInst != null && lastInst.getPosition() >= 0 && duplicates.get(lastInst.getPosition())) {
+ result.add(next);
+ }
+ }
+ return result;
+ }
+
+ private int getOffset(SortedMap<Integer, Integer> duplicates, int i) {
+ SortedMap<Integer, Integer> headMap = duplicates.headMap(i+1);
+ if(headMap.isEmpty()) {
+ return -1;
+ }
+ int end = headMap.get(headMap.lastKey());
+ if(end <= i) {
+ return -1;
+ }
+ return getInstructionNumber(positions, i)-getInstructionNumber(positions, headMap.lastKey());
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(duplicateBlocks);
+ }
+ }
+
+ private static class TryBlock {
+ boolean incorrect = false;
+ final int catchAnyAddress;
+ InstructionHandle firstInstruction;
+ SortedMap<Integer, Integer> normalBlocks = new TreeMap<>();
+ SortedMap<Integer, Integer> duplicates = new TreeMap<>();
+
+ public TryBlock(int catchAnyAddress) {
+ this.catchAnyAddress = catchAnyAddress;
+ }
+
+ public void update(BitSet exceptionTargets, BitSet branchTargets, InstructionList il, Set<Integer> finallyTargets, BitSet usedTargets) {
+ int lastEnd = -1;
+ InstructionHandle ih = il.findHandle(catchAnyAddress);
+ if(ih == null || !(ih.getInstruction() instanceof ASTORE)) {
+ incorrect = true;
+ return;
+ }
+ int varIndex = ((ASTORE)ih.getInstruction()).getIndex();
+ firstInstruction = ih.getNext();
+ if(firstInstruction == null) {
+ incorrect = true;
+ return;
+ }
+ int start = firstInstruction.getPosition();
+ int end = start;
+ while(true) {
+ ih = ih.getNext();
+ if(ih == null) {
+ incorrect = true;
+ return;
+ }
+ end = ih.getPosition();
+ Instruction inst = ih.getInstruction();
+ if((inst instanceof ALOAD) && ((ALOAD)inst).getIndex() == varIndex) {
+ ih = ih.getNext();
+ if(ih == null || !(ih.getInstruction() instanceof ATHROW)) {
+ incorrect = true;
+ return;
+ }
+ break;
+ }
+ if(inst instanceof JSR) {
+ // We are not interested in JSR finally blocks as they are not duplicated
+ incorrect = true;
+ return;
+ }
+ }
+ duplicates.put(start, end);
+ normalBlocks.put(catchAnyAddress, catchAnyAddress);
+ for(Entry<Integer, Integer> entry : normalBlocks.entrySet()) {
+ if(lastEnd > -1) {
+ if(entry.getKey() > lastEnd) {
+ int candidateStart = lastEnd;
+ int block2end = equalBlocks(firstInstruction, il.findHandle(candidateStart), end-start, il.getInstructionPositions());
+ if(block2end > 0 && block2end <= entry.getKey()) {
+ duplicates.put(candidateStart, block2end);
+ while(true) {
+ int newKey = Math.min(exceptionTargets.nextSetBit(block2end+1), branchTargets.nextSetBit(block2end+1));
+ if(newKey < 0 || newKey > entry.getKey()) {
+ break;
+ }
+ InstructionHandle ih2 = il.findHandle(newKey);
+ if(exceptionTargets.get(newKey)) {
+ ih2 = ih2.getNext(); // Skip astore
+ }
+ candidateStart = ih2.getPosition();
+ block2end = equalBlocks(firstInstruction, ih2, end-start, il.getInstructionPositions());
+ if(block2end > 0 && block2end <= entry.getKey()) {
+ duplicates.put(candidateStart, block2end);
+ } else {
+ block2end = newKey;
+ }
+ }
+ }
+ }
+ }
+ lastEnd = entry.getValue();
+ }
+ ih = ih.getNext();
+ int block2end = equalBlocks(firstInstruction, ih, end-start, il.getInstructionPositions());
+ if(block2end > 0) {
+ duplicates.put(ih.getPosition(), block2end);
+ }
+ }
+
+ private int equalBlocks(InstructionHandle ih1, InstructionHandle ih2, int length, int[] positions) {
+ if(length == 0) {
+ return -1;
+ }
+ if(ih1 == null || ih2 == null) {
+ return -1;
+ }
+ int start1 = ih1.getPosition();
+ int start2 = ih2.getPosition();
+ int startNum1 = getInstructionNumber(positions, start1);
+ int startNum2 = getInstructionNumber(positions, start2);
+ Map<Integer, Integer> lvMap = new HashMap<>();
+ while(true) {
+ if(ih1 == null || ih2 == null) {
+ return -1;
+ }
+ Instruction inst1 = ih1.getInstruction();
+ Instruction inst2 = ih2.getInstruction();
+ if(!inst1.equals(inst2)) {
+ if(inst1 instanceof LocalVariableInstruction && inst2 instanceof LocalVariableInstruction) {
+ if(inst1.getClass() != inst2.getClass()) {
+ return -1;
+ }
+ LocalVariableInstruction lvi1 = (LocalVariableInstruction)inst1;
+ LocalVariableInstruction lvi2 = (LocalVariableInstruction)inst2;
+ int lv1 = lvi1.getIndex();
+ int lv2 = lvi2.getIndex();
+ Integer targetLV = lvMap.get(lv1);
+ if(targetLV == null) {
+ if(!(lvi1 instanceof StoreInstruction)) {
+ return -1;
+ }
+ lvMap.put(lv1, lv2);
+ } else if(targetLV != lv2) {
+ return -1;
+ }
+ } else {
+ if(inst1.getOpcode() != inst2.getOpcode()) {
+ return -1;
+ }
+ if(!(inst1 instanceof BranchInstruction)) {
+ return -1;
+ }
+ int target1 = ((BranchInstruction)inst1).getTarget().getPosition();
+ int target2 = ((BranchInstruction)inst2).getTarget().getPosition();
+ if(!(getInstructionNumber(positions, target1)-startNum1 == getInstructionNumber(positions, target2)-startNum2 || (target1 == start1+length))) {
+ return -1;
+ }
+ }
+ }
+ if(ih1.getPosition()-start1+inst1.getLength() >= length) {
+ return ih2.getPosition()+inst2.getLength();
+ }
+ ih1 = ih1.getNext();
+ ih2 = ih2.getNext();
+ }
+ }
+
+ @Override
+ public String toString() {
+ if(incorrect) {
+ return "INCORRECT";
+ }
+ return duplicates.toString();
+ }
+ }
+
+ private static int getInstructionNumber(int[] positions, int position) {
+ return Math.abs(Arrays.binarySearch(positions, position));
+ }
+
+ @Override
+ public FinallyDuplicatesInfo analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
+ Method method = analysisCache.getMethodAnalysis(Method.class, descriptor);
+ if(method == null) {
+ return NONE_FINALLY_INFO;
+ }
+ BitSet exceptionTargets = new BitSet();
+ Map<Integer, TryBlock> finallyTargets = new LinkedHashMap<>();
+ for(CodeException codeException : method.getCode().getExceptionTable()) {
+ if(codeException.getCatchType() == 0) {
+ TryBlock block = finallyTargets.get(codeException.getHandlerPC());
+ if(block == null) {
+ block = new TryBlock(codeException.getHandlerPC());
+ finallyTargets.put(codeException.getHandlerPC(), block);
+ }
+ if(codeException.getStartPC() != codeException.getHandlerPC()) {
+ block.normalBlocks.put(codeException.getStartPC(), codeException.getEndPC());
+ }
+ }
+ exceptionTargets.set(codeException.getHandlerPC());
+ }
+ if(finallyTargets.isEmpty()) {
+ return NONE_FINALLY_INFO;
+ }
+ MethodGen methodGen = analysisCache.getMethodAnalysis(MethodGen.class, descriptor);
+ if(methodGen == null) {
+ return NONE_FINALLY_INFO;
+ }
+ InstructionList il = methodGen.getInstructionList();
+ BitSet branchTargets = new BitSet();
+ for(InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) {
+ Instruction inst = ih.getInstruction();
+ if(inst instanceof BranchInstruction) {
+ branchTargets.set(((BranchInstruction) inst).getTarget().getPosition());
+ }
+ }
+ BitSet usedTargets = new BitSet();
+ List<SortedMap<Integer, Integer>> duplicates = new ArrayList<>();
+ for(TryBlock block : finallyTargets.values()) {
+ if(usedTargets.get(block.catchAnyAddress)) {
+ continue;
+ }
+ block.update(exceptionTargets, branchTargets, il, finallyTargets.keySet(), usedTargets);
+ if(!block.incorrect && block.duplicates.size() > 1) {
+ duplicates.add(block.duplicates);
+ }
+ }
+ if(duplicates.isEmpty()) {
+ return NONE_FINALLY_INFO;
+ }
+ return new FinallyDuplicatesInfo(il.getInstructionPositions(), duplicates);
+ }
+
+ @Override
+ public void registerWith(IAnalysisCache analysisCache) {
+ analysisCache.registerMethodAnalysisEngine(FinallyDuplicatesInfo.class, this);
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ForwardTypeQualifierDataflowFactoryFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ForwardTypeQualifierDataflowFactoryFactory.java
index f43ec0e..0bff7dc 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ForwardTypeQualifierDataflowFactoryFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ForwardTypeQualifierDataflowFactoryFactory.java
@@ -26,7 +26,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Factory for ForwardTypeQualifierDataflowFactory objects.
- *
+ *
* @author David Hovemeyer
*/
public class ForwardTypeQualifierDataflowFactoryFactory extends AnalysisFactory<ForwardTypeQualifierDataflowFactory> {
@@ -36,11 +36,12 @@ public class ForwardTypeQualifierDataflowFactoryFactory extends AnalysisFactory<
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ForwardTypeQualifierDataflowFactory analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
throws CheckedAnalysisException {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/IsNullValueDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/IsNullValueDataflowFactory.java
index 3653633..a6a8e04 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/IsNullValueDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/IsNullValueDataflowFactory.java
@@ -38,7 +38,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce IsNullValueDataflow objects for an analyzed
* method.
- *
+ *
* @author David Hovemeyer
*/
public class IsNullValueDataflowFactory extends AnalysisFactory<IsNullValueDataflow> {
@@ -51,11 +51,12 @@ public class IsNullValueDataflowFactory extends AnalysisFactory<IsNullValueDataf
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public IsNullValueDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
MethodGen methodGen = getMethodGen(analysisCache, descriptor);
if (methodGen == null) {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/JavaClassAnalysisEngine.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/JavaClassAnalysisEngine.java
index 11e0984..86b9b31 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/JavaClassAnalysisEngine.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/JavaClassAnalysisEngine.java
@@ -51,6 +51,7 @@ public class JavaClassAnalysisEngine implements IClassAnalysisEngine<JavaClass>
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public JavaClass analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor) throws CheckedAnalysisException {
try {
ClassData classData = analysisCache.getClassAnalysis(ClassData.class, descriptor);
@@ -79,6 +80,7 @@ public class JavaClassAnalysisEngine implements IClassAnalysisEngine<JavaClass>
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
*/
+ @Override
public void registerWith(IAnalysisCache analysisCache) {
analysisCache.registerClassAnalysisEngine(JavaClass.class, this);
}
@@ -88,6 +90,7 @@ public class JavaClassAnalysisEngine implements IClassAnalysisEngine<JavaClass>
*
* @see edu.umd.cs.findbugs.classfile.IAnalysisEngine#canRecompute()
*/
+ @Override
public boolean canRecompute() {
// Currently, JavaClass objects are compared by reference equality in
// some places,
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LiveLocalStoreDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LiveLocalStoreDataflowFactory.java
index b86254f..fa76c50 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LiveLocalStoreDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LiveLocalStoreDataflowFactory.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce LiveLocalStoreDataflow objects for analyzed
* methods.
- *
+ *
* @author David Hovemeyer
*/
public class LiveLocalStoreDataflowFactory extends AnalysisFactory<LiveLocalStoreDataflow> {
@@ -45,11 +45,12 @@ public class LiveLocalStoreDataflowFactory extends AnalysisFactory<LiveLocalStor
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public LiveLocalStoreDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
throws CheckedAnalysisException {
MethodGen methodGen = getMethodGen(analysisCache, descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LoadDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LoadDataflowFactory.java
index 05812dc..977bd00 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LoadDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LoadDataflowFactory.java
@@ -28,7 +28,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce LoadDataflow objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class LoadDataflowFactory extends AnalysisFactory<LoadDataflow> {
@@ -41,15 +41,17 @@ public class LoadDataflowFactory extends AnalysisFactory<LoadDataflow> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public LoadDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
MethodGen methodGen = getMethodGen(analysisCache, descriptor);
- if (methodGen == null)
+ if (methodGen == null) {
return null;
+ }
LoadAnalysis analysis = new LoadAnalysis(getDepthFirstSearch(analysisCache, descriptor), getConstantPoolGen(
analysisCache, descriptor.getClassDescriptor()));
LoadDataflow dataflow = new LoadDataflow(getCFG(analysisCache, descriptor), analysis);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LoadedFieldSetFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LoadedFieldSetFactory.java
index 21b7aa5..bc64387 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LoadedFieldSetFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LoadedFieldSetFactory.java
@@ -45,7 +45,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
* (there is no need to remember stores of fields that are never read, or loads
* of fields that are only loaded in one location). However, it might be useful
* for other kinds of analysis.
- *
+ *
* <p>
* The tricky part is that in addition to fields loaded and stored with
* get/putfield and get/putstatic, we also try to figure out field accessed
@@ -70,15 +70,17 @@ public class LoadedFieldSetFactory extends AnalysisFactory<LoadedFieldSet> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public LoadedFieldSet analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
MethodGen methodGen = getMethodGen(analysisCache, descriptor);
- if (methodGen == null)
+ if (methodGen == null) {
return null;
+ }
InstructionList il = methodGen.getInstructionList();
LoadedFieldSet loadedFieldSet = new LoadedFieldSet(methodGen);
@@ -99,20 +101,22 @@ public class LoadedFieldSetFactory extends AnalysisFactory<LoadedFieldSet> {
* + " at " + inv); }
*/
if (access != null) {
- if (access.isLoad())
+ if (access.isLoad()) {
loadedFieldSet.addLoad(handle, access.getField());
- else
+ } else {
loadedFieldSet.addStore(handle, access.getField());
+ }
}
}
} else if (fieldInstructionOpcodeSet.get(opcode)) {
boolean isLoad = (opcode == Constants.GETFIELD || opcode == Constants.GETSTATIC);
XField field = Hierarchy.findXField((FieldInstruction) ins, cpg);
if (field != null) {
- if (isLoad)
+ if (isLoad) {
loadedFieldSet.addLoad(handle, field);
- else
+ } else {
loadedFieldSet.addStore(handle, field);
+ }
}
}
} catch (ClassNotFoundException e) {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LockCheckerFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LockCheckerFactory.java
index 12961c9..1a7fdf6 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LockCheckerFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LockCheckerFactory.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce LockChecker objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class LockCheckerFactory extends AnalysisFactory<LockChecker> {
@@ -38,11 +38,12 @@ public class LockCheckerFactory extends AnalysisFactory<LockChecker> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public LockChecker analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
LockChecker lockChecker = new LockChecker(descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LockDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LockDataflowFactory.java
index 56fd210..bee9dc7 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LockDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/LockDataflowFactory.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce LockDataflow objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class LockDataflowFactory extends AnalysisFactory<LockDataflow> {
@@ -45,11 +45,12 @@ public class LockDataflowFactory extends AnalysisFactory<LockDataflow> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public LockDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
MethodGen methodGen = getMethodGen(analysisCache, descriptor);
if (methodGen == null) {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodBytecodeSetFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodBytecodeSetFactory.java
index 8e1d099..ebe03ad 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodBytecodeSetFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodBytecodeSetFactory.java
@@ -43,11 +43,12 @@ public class MethodBytecodeSetFactory extends AnalysisFactory<MethodBytecodeSet>
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public MethodBytecodeSet analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
Method method = analysisCache.getMethodAnalysis(Method.class, descriptor);
Code code = method.getCode();
@@ -75,7 +76,7 @@ public class MethodBytecodeSetFactory extends AnalysisFactory<MethodBytecodeSet>
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodFactory.java
index 8110df3..c70b6e2 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodFactory.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Method analysis engine to produce BCEL Method objects.
- *
+ *
* @author David Hovemeyer
*/
public class MethodFactory extends AnalysisFactory<Method> {
@@ -40,11 +40,12 @@ public class MethodFactory extends AnalysisFactory<Method> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public Method analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
JavaClass jclass = analysisCache.getClassAnalysis(JavaClass.class, descriptor.getClassDescriptor());
Method[] methodList = jclass.getMethods();
@@ -69,7 +70,7 @@ public class MethodFactory extends AnalysisFactory<Method> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#registerWith(edu.umd.cs
* .findbugs.classfile.IAnalysisCache)
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodGenFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodGenFactory.java
index df1e656..9e05169 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodGenFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/MethodGenFactory.java
@@ -26,13 +26,15 @@ import org.apache.bcel.generic.MethodGen;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.AnalysisFeatures;
import edu.umd.cs.findbugs.ba.JavaClassAndMethod;
+import edu.umd.cs.findbugs.ba.XFactory;
+import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.IAnalysisCache;
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce MethodGen objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
* @author Bill Pugh
*/
@@ -46,31 +48,39 @@ public class MethodGenFactory extends AnalysisFactory<MethodGen> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public MethodGen analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
Method method = getMethod(analysisCache, descriptor);
- if (method.getCode() == null)
+ if (method.getCode() == null) {
+ return null;
+ }
+ XMethod xmethod = XFactory.createXMethod(descriptor);
+ if (xmethod.usesInvokeDynamic() && false) {
+ AnalysisContext.currentAnalysisContext().analysisSkippedDueToInvokeDynamic(xmethod);
return null;
+ }
+
try {
AnalysisContext analysisContext = AnalysisContext.currentAnalysisContext();
JavaClass jclass = getJavaClass(analysisCache, descriptor.getClassDescriptor());
ConstantPoolGen cpg = getConstantPoolGen(analysisCache, descriptor.getClassDescriptor());
String methodName = method.getName();
- int codeLength = method.getCode().getLength();
+ int codeLength = method.getCode().getCode().length;
String superclassName = jclass.getSuperclassName();
- if (codeLength > 6000 && methodName.equals("<clinit>") && superclassName.equals("java.lang.Enum")) {
+ if (codeLength > 6000 && "<clinit>".equals(methodName) && "java.lang.Enum".equals(superclassName)) {
analysisContext.getLookupFailureCallback().reportSkippedAnalysis(
new JavaClassAndMethod(jclass, method).toMethodDescriptor());
return null;
}
if (analysisContext.getBoolProperty(AnalysisFeatures.SKIP_HUGE_METHODS)) {
- if (codeLength > 6000 || (methodName.equals("<clinit>") || methodName.equals("getContents")) && codeLength > 2000) {
+ if (codeLength > 6000 || ("<clinit>".equals(methodName) || "getContents".equals(methodName)) && codeLength > 2000) {
analysisContext.getLookupFailureCallback().reportSkippedAnalysis(
new JavaClassAndMethod(jclass, method).toMethodDescriptor());
return null;
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonExceptionPostdominatorsAnalysis.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonExceptionPostdominatorsAnalysis.java
index 2b0cfa9..9ba89b0 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonExceptionPostdominatorsAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonExceptionPostdominatorsAnalysis.java
@@ -26,13 +26,13 @@ import edu.umd.cs.findbugs.ba.ReverseDepthFirstSearch;
/**
* PostDominatorsAnalysis variant in which all exception edges are ignored.
- *
+ *
* @author David Hovemeyer
*/
public class NonExceptionPostdominatorsAnalysis extends PostDominatorsAnalysis {
/**
* Constructor.
- *
+ *
* @param cfg
* the CFG to compute dominator relationships for
* @param rdfs
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonExceptionPostdominatorsAnalysisFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonExceptionPostdominatorsAnalysisFactory.java
index a25c5e8..a982315 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonExceptionPostdominatorsAnalysisFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonExceptionPostdominatorsAnalysisFactory.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce NonExceptionPostDominatorsAnalysis objects for
* analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class NonExceptionPostdominatorsAnalysisFactory extends AnalysisFactory<NonExceptionPostdominatorsAnalysis> {
@@ -39,11 +39,12 @@ public class NonExceptionPostdominatorsAnalysisFactory extends AnalysisFactory<N
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public NonExceptionPostdominatorsAnalysis analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
throws CheckedAnalysisException {
CFG cfg = getCFG(analysisCache, descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonImplicitExceptionPostDominatorsAnalysis.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonImplicitExceptionPostDominatorsAnalysis.java
index 54819a4..ef4dabc 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonImplicitExceptionPostDominatorsAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonImplicitExceptionPostDominatorsAnalysis.java
@@ -32,12 +32,13 @@ import edu.umd.cs.findbugs.ba.ReverseDepthFirstSearch;
* Implicit exception edges correspond to undeclared runtime exceptions; thus,
* this analysis considers only normal control edges and declared exception
* edges.
- *
+ *
* @author David Hovemeyer
*/
public class NonImplicitExceptionPostDominatorsAnalysis extends PostDominatorsAnalysis {
public NonImplicitExceptionPostDominatorsAnalysis(CFG cfg, ReverseDepthFirstSearch rdfs, DepthFirstSearch dfs) {
super(cfg, rdfs, dfs, new EdgeChooser() {
+ @Override
public boolean choose(Edge edge) {
return !edge.isExceptionEdge() || edge.isFlagSet(EdgeTypes.EXPLICIT_EXCEPTIONS_FLAG);
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonImplicitExceptionPostDominatorsAnalysisFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonImplicitExceptionPostDominatorsAnalysisFactory.java
index 3dce236..3183b55 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonImplicitExceptionPostDominatorsAnalysisFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/NonImplicitExceptionPostDominatorsAnalysisFactory.java
@@ -30,11 +30,11 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce NonImplicitExceptionPostDominatorsAnalysis objects
* for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class NonImplicitExceptionPostDominatorsAnalysisFactory extends
- AnalysisFactory<NonImplicitExceptionPostDominatorsAnalysis> {
+AnalysisFactory<NonImplicitExceptionPostDominatorsAnalysis> {
/**
* Constructor.
*/
@@ -44,11 +44,12 @@ public class NonImplicitExceptionPostDominatorsAnalysisFactory extends
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public NonImplicitExceptionPostDominatorsAnalysis analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
throws CheckedAnalysisException {
CFG cfg = getCFG(analysisCache, descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ObligationDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ObligationDataflowFactory.java
index f7c4a1c..bed64d0 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ObligationDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ObligationDataflowFactory.java
@@ -39,7 +39,7 @@ import edu.umd.cs.findbugs.log.Profiler;
/**
* Analysis factory which creates instances of ObligationDataflow.
- *
+ *
* @author David Hovemeyer
*/
public class ObligationDataflowFactory extends AnalysisFactory<ObligationDataflow> {
@@ -50,6 +50,7 @@ public class ObligationDataflowFactory extends AnalysisFactory<ObligationDataflo
super("Obligation dataflow", ObligationDataflow.class);
}
+ @Override
public ObligationDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor methodDescriptor)
throws CheckedAnalysisException {
CFG cfg = analysisCache.getMethodAnalysis(CFG.class, methodDescriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ParameterSignatureListFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ParameterSignatureListFactory.java
index bdc9801..5a47f9b 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ParameterSignatureListFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ParameterSignatureListFactory.java
@@ -28,7 +28,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce parameter signature lists for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class ParameterSignatureListFactory extends AnalysisFactory<String[]> {
@@ -42,11 +42,12 @@ public class ParameterSignatureListFactory extends AnalysisFactory<String[]> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public String[] analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
SignatureParser parser = new SignatureParser(descriptor.getSignature());
ArrayList<String> resultList = new ArrayList<String>();
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReturnPathDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReturnPathDataflowFactory.java
index 70f72e4..d3167a6 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReturnPathDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReturnPathDataflowFactory.java
@@ -28,7 +28,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce ReturnPathDataflow objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class ReturnPathDataflowFactory extends AnalysisFactory<ReturnPathDataflow> {
@@ -41,11 +41,12 @@ public class ReturnPathDataflowFactory extends AnalysisFactory<ReturnPathDataflo
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ReturnPathDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
CFG cfg = getCFG(analysisCache, descriptor);
DepthFirstSearch dfs = getDepthFirstSearch(analysisCache, descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReturnPathTypeDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReturnPathTypeDataflowFactory.java
index a5775fd..1de5629 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReturnPathTypeDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReturnPathTypeDataflowFactory.java
@@ -30,7 +30,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce ReturnPathTypeDataflow objects for analyzed
* methods.
- *
+ *
* @author David Hovemeyer
*/
public class ReturnPathTypeDataflowFactory extends AnalysisFactory<ReturnPathTypeDataflow> {
@@ -43,11 +43,12 @@ public class ReturnPathTypeDataflowFactory extends AnalysisFactory<ReturnPathTyp
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ReturnPathTypeDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
throws CheckedAnalysisException {
CFG cfg = getCFG(analysisCache, descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReverseDepthFirstSearchFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReverseDepthFirstSearchFactory.java
index 7eee0e9..00709c8 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReverseDepthFirstSearchFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ReverseDepthFirstSearchFactory.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce ReverseDepthFirstSearch objects for analyzed
* methods.
- *
+ *
* @author David Hovemeyer
*/
public class ReverseDepthFirstSearchFactory extends AnalysisFactory<ReverseDepthFirstSearch> {
@@ -40,11 +40,12 @@ public class ReverseDepthFirstSearchFactory extends AnalysisFactory<ReverseDepth
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ReverseDepthFirstSearch analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
throws CheckedAnalysisException {
CFG cfg = getCFG(analysisCache, descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/StoreDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/StoreDataflowFactory.java
index 436fa1b..c544d7e 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/StoreDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/StoreDataflowFactory.java
@@ -28,7 +28,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce StoreDataflow objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class StoreDataflowFactory extends AnalysisFactory<StoreDataflow> {
@@ -41,15 +41,17 @@ public class StoreDataflowFactory extends AnalysisFactory<StoreDataflow> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public StoreDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
MethodGen methodGen = getMethodGen(analysisCache, descriptor);
- if (methodGen == null)
+ if (methodGen == null) {
return null;
+ }
StoreAnalysis analysis = new StoreAnalysis(getDepthFirstSearch(analysisCache, descriptor), getConstantPoolGen(
analysisCache, descriptor.getClassDescriptor()));
StoreDataflow dataflow = new StoreDataflow(getCFG(analysisCache, descriptor), analysis);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/TypeDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/TypeDataflowFactory.java
index a9bd165..f9a74b9 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/TypeDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/TypeDataflowFactory.java
@@ -37,7 +37,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce TypeDataflow objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class TypeDataflowFactory extends AnalysisFactory<TypeDataflow> {
@@ -50,11 +50,12 @@ public class TypeDataflowFactory extends AnalysisFactory<TypeDataflow> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public TypeDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
MethodGen methodGen = getMethodGen(analysisCache, descriptor);
if (methodGen == null) {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnconditionalValueDerefDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnconditionalValueDerefDataflowFactory.java
index 1f73555..2fcb807 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnconditionalValueDerefDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnconditionalValueDerefDataflowFactory.java
@@ -35,7 +35,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce UnconditionalValueDerefDataflow objects for
* analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class UnconditionalValueDerefDataflowFactory extends AnalysisFactory<UnconditionalValueDerefDataflow> {
@@ -48,11 +48,12 @@ public class UnconditionalValueDerefDataflowFactory extends AnalysisFactory<Unco
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public UnconditionalValueDerefDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
throws CheckedAnalysisException {
MethodGen methodGen = getMethodGen(analysisCache, descriptor);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedBytecodeCallback.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedBytecodeCallback.java
index 01f86bd..ec9dfc5 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedBytecodeCallback.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedBytecodeCallback.java
@@ -23,9 +23,9 @@ import edu.umd.cs.findbugs.ba.BytecodeScanner;
import edu.umd.cs.findbugs.ba.MethodBytecodeSet;
public class UnpackedBytecodeCallback implements BytecodeScanner.Callback {
- private MethodBytecodeSet bytecodeSet;
+ private final MethodBytecodeSet bytecodeSet;
- private short[] offsetToOpcodeMap;
+ private final short[] offsetToOpcodeMap;
public UnpackedBytecodeCallback(int codeSize) {
this.bytecodeSet = new MethodBytecodeSet();
@@ -34,11 +34,12 @@ public class UnpackedBytecodeCallback implements BytecodeScanner.Callback {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.BytecodeScanner.Callback#handleInstruction(int,
* int)
*/
+ @Override
public void handleInstruction(int opcode, int index) {
bytecodeSet.set(opcode);
offsetToOpcodeMap[index] = (short) opcode;
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedCode.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedCode.java
index 90f273c..2b1e05c 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedCode.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedCode.java
@@ -7,9 +7,9 @@ import edu.umd.cs.findbugs.ba.MethodBytecodeSet;
* well as a map of bytecode offsets to opcodes.
*/
public class UnpackedCode {
- private MethodBytecodeSet bytecodeSet;
+ private final MethodBytecodeSet bytecodeSet;
- private short[] offsetToBytecodeMap;
+ private final short[] offsetToBytecodeMap;
public UnpackedCode(MethodBytecodeSet bytecodeSet, short[] offsetToBytecodeMap) {
this.bytecodeSet = bytecodeSet;
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedCodeFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedCodeFactory.java
index a43bed3..82ef4bf 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedCodeFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UnpackedCodeFactory.java
@@ -28,7 +28,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce UnpackedCode objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class UnpackedCodeFactory extends AnalysisFactory<UnpackedCode> {
@@ -41,16 +41,18 @@ public class UnpackedCodeFactory extends AnalysisFactory<UnpackedCode> {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public UnpackedCode analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
Method method = getMethod(analysisCache, descriptor);
Code code = method.getCode();
- if (code == null)
+ if (code == null) {
return null;
+ }
byte[] instructionList = code.getCode();
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UsagesRequiringNonNullValuesFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UsagesRequiringNonNullValuesFactory.java
index 815bd1f..b3aa3bd 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UsagesRequiringNonNullValuesFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/UsagesRequiringNonNullValuesFactory.java
@@ -36,11 +36,12 @@ public class UsagesRequiringNonNullValuesFactory extends AnalysisFactory<UsagesR
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public UsagesRequiringNonNullValues analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
throws CheckedAnalysisException {
// ClassContext classContext = getClassContext(jclass);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ValueNumberDataflowFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ValueNumberDataflowFactory.java
index 5a68de0..a36b6e2 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ValueNumberDataflowFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ValueNumberDataflowFactory.java
@@ -40,7 +40,7 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Analysis engine to produce ValueNumberDataflow objects for analyzed methods.
- *
+ *
* @author David Hovemeyer
*/
public class ValueNumberDataflowFactory extends AnalysisFactory<ValueNumberDataflow> {
@@ -53,11 +53,12 @@ public class ValueNumberDataflowFactory extends AnalysisFactory<ValueNumberDataf
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
* .classfile.IAnalysisCache, java.lang.Object)
*/
+ @Override
public ValueNumberDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
MethodGen methodGen = getMethodGen(analysisCache, descriptor);
if (methodGen == null) {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ValueRangeAnalysisFactory.java b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ValueRangeAnalysisFactory.java
new file mode 100644
index 0000000..898f4d2
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/classfile/engine/bcel/ValueRangeAnalysisFactory.java
@@ -0,0 +1,972 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.classfile.engine.bcel;
+
+import static org.apache.bcel.Constants.*;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.annotation.Nullable;
+
+import org.apache.bcel.classfile.Constant;
+import org.apache.bcel.classfile.ConstantCP;
+import org.apache.bcel.classfile.ConstantNameAndType;
+import org.apache.bcel.classfile.ConstantObject;
+import org.apache.bcel.classfile.ConstantPool;
+import org.apache.bcel.classfile.ConstantUtf8;
+import org.apache.bcel.classfile.LocalVariable;
+import org.apache.bcel.classfile.LocalVariableTable;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.ARRAYLENGTH;
+import org.apache.bcel.generic.CPInstruction;
+import org.apache.bcel.generic.ConstantPushInstruction;
+import org.apache.bcel.generic.GETFIELD;
+import org.apache.bcel.generic.GETSTATIC;
+import org.apache.bcel.generic.IFNE;
+import org.apache.bcel.generic.INVOKEVIRTUAL;
+import org.apache.bcel.generic.IfInstruction;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.LCMP;
+import org.apache.bcel.generic.LoadInstruction;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.PushInstruction;
+import org.apache.bcel.generic.Type;
+
+import edu.umd.cs.findbugs.ba.BasicBlock;
+import edu.umd.cs.findbugs.ba.CFG;
+import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
+import edu.umd.cs.findbugs.ba.Edge;
+import edu.umd.cs.findbugs.ba.EdgeTypes;
+import edu.umd.cs.findbugs.ba.Location;
+import edu.umd.cs.findbugs.ba.MethodUnprofitableException;
+import edu.umd.cs.findbugs.ba.XFactory;
+import edu.umd.cs.findbugs.ba.XMethod;
+import edu.umd.cs.findbugs.ba.vna.ValueNumber;
+import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
+import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
+import edu.umd.cs.findbugs.classfile.IAnalysisCache;
+import edu.umd.cs.findbugs.classfile.IMethodAnalysisEngine;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+import edu.umd.cs.findbugs.classfile.engine.bcel.FinallyDuplicatesInfoFactory.FinallyDuplicatesInfo;
+
+/**
+ * @author Tagir Valeev
+ */
+public class ValueRangeAnalysisFactory implements IMethodAnalysisEngine<ValueRangeAnalysisFactory.ValueRangeAnalysis> {
+ private static class TypeLongRange {
+ long min, max;
+ String signature;
+
+ public TypeLongRange(long min, long max, String signature) {
+ this.min = min;
+ this.max = max;
+ this.signature = signature;
+ }
+
+ public void addBordersTo(Set<Long> borders) {
+ borders.add(min);
+ if(min > Long.MIN_VALUE) {
+ borders.add(min-1);
+ }
+ borders.add(max);
+ if(max < Long.MAX_VALUE) {
+ borders.add(max+1);
+ }
+ }
+ }
+
+ private static final Map<String, TypeLongRange> typeRanges;
+
+ static {
+ typeRanges = new HashMap<>();
+ typeRanges.put("Z", new TypeLongRange(0, 1, "Z"));
+ typeRanges.put("B", new TypeLongRange(Byte.MIN_VALUE, Byte.MAX_VALUE, "B"));
+ typeRanges.put("S", new TypeLongRange(Short.MIN_VALUE, Short.MAX_VALUE, "S"));
+ typeRanges.put("I", new TypeLongRange(Integer.MIN_VALUE, Integer.MAX_VALUE, "I"));
+ typeRanges.put("J", new TypeLongRange(Long.MIN_VALUE, Long.MAX_VALUE, "J"));
+ typeRanges.put("C", new TypeLongRange(Character.MIN_VALUE, Character.MAX_VALUE, "C"));
+ }
+
+ public static class LongRangeSet implements Iterable<LongRangeSet> {
+ private final SortedMap<Long, Long> map = new TreeMap<>();
+ private final TypeLongRange range;
+
+ public LongRangeSet(String type) {
+ TypeLongRange range = typeRanges.get(type);
+ if(range == null) {
+ throw new IllegalArgumentException("Type is not supported: " + type);
+ }
+ map.put(range.min, range.max);
+ this.range = range;
+ }
+
+ private LongRangeSet(TypeLongRange range, long from, long to) {
+ this.range = range;
+ if(from < range.min) {
+ from = range.min;
+ }
+ if(to > range.max) {
+ to = range.max;
+ }
+ if (from <= to) {
+ map.put(from, to);
+ }
+ }
+
+ private LongRangeSet(TypeLongRange range) {
+ this.range = range;
+ }
+
+ public LongRangeSet gt(long value) {
+ splitGreater(value);
+ if(value == Long.MAX_VALUE) {
+ return new LongRangeSet(range);
+ }
+ return new LongRangeSet(range, value + 1, range.max);
+ }
+
+ public LongRangeSet ge(long value) {
+ splitGreater(value-1);
+ return new LongRangeSet(range, value, range.max);
+ }
+
+ public LongRangeSet lt(long value) {
+ splitGreater(value-1);
+ if(value == Long.MIN_VALUE) {
+ return new LongRangeSet(range);
+ }
+ return new LongRangeSet(range, range.min, value - 1);
+ }
+
+ public LongRangeSet le(long value) {
+ splitGreater(value);
+ return new LongRangeSet(range, range.min, value);
+ }
+
+ public LongRangeSet eq(long value) {
+ splitGreater(value);
+ splitGreater(value-1);
+ return new LongRangeSet(range, value, value);
+ }
+
+ public LongRangeSet ne(long value) {
+ splitGreater(value);
+ splitGreater(value-1);
+ LongRangeSet rangeSet = lt(value);
+ if (value < range.max) {
+ rangeSet.map.put(value + 1, range.max);
+ }
+ return rangeSet;
+ }
+
+ public void addBordersTo(Set<Long> borders) {
+ range.addBordersTo(borders);
+ }
+
+ public LongRangeSet empty() {
+ return new LongRangeSet(range);
+ }
+
+ public boolean intersects(LongRangeSet other) {
+ for (Entry<Long, Long> entry : map.entrySet()) {
+ SortedMap<Long, Long> subMap = entry.getValue() == Long.MAX_VALUE ? other.map.tailMap(entry.getKey()) : other.map
+ .subMap(entry.getKey(), entry.getValue() + 1);
+ if (!subMap.isEmpty()) {
+ return true;
+ }
+ SortedMap<Long, Long> headMap = other.map.headMap(entry.getKey());
+ if (!headMap.isEmpty() && headMap.get(headMap.lastKey()) >= entry.getKey()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void splitGreater(long number) {
+ Long lNumber = number;
+ if(number == Long.MAX_VALUE) {
+ return;
+ }
+ Long nextNumber = number + 1;
+ SortedMap<Long, Long> headMap = map.headMap(nextNumber);
+ if (headMap.isEmpty()) {
+ return;
+ }
+ Long lastKey = headMap.lastKey();
+ Long lastValue = headMap.get(lastKey);
+ if (number >= lastValue) {
+ return;
+ }
+ map.put(lastKey, lNumber);
+ map.put(nextNumber, lastValue);
+ }
+
+ public String getSignature() {
+ return range.signature;
+ }
+
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ public boolean isFull() {
+ if(map.size() != 1) {
+ return false;
+ }
+ Long min = map.firstKey();
+ Long max = map.get(min);
+ return min <= range.min && max >= range.max;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ for (Entry<Long, Long> entry : map.entrySet()) {
+ if (sb.length() > 0) {
+ sb.append("+");
+ }
+ if (entry.getKey().equals(entry.getValue())) {
+ sb.append("{").append(entry.getKey()).append("}");
+ } else {
+ sb.append("[").append(entry.getKey()).append(", ").append(entry.getValue()).append("]");
+ }
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public Iterator<LongRangeSet> iterator() {
+ final Iterator<Entry<Long, Long>> iterator = map.entrySet().iterator();
+ return new Iterator<ValueRangeAnalysisFactory.LongRangeSet>() {
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public LongRangeSet next() {
+ Entry<Long, Long> entry = iterator.next();
+ return new LongRangeSet(range, entry.getKey(), entry.getValue());
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ private void add(Long start, Long end) {
+ SortedMap<Long, Long> headMap;
+ if (end < Long.MAX_VALUE) {
+ headMap = map.headMap(end + 1);
+ Long tailEnd = map.remove(end + 1);
+ if (tailEnd != null) {
+ end = tailEnd;
+ }
+ if (!headMap.isEmpty()) {
+ tailEnd = headMap.get(headMap.lastKey());
+ if (tailEnd > end) {
+ end = tailEnd;
+ }
+ }
+ }
+ headMap = map.headMap(start);
+ if (!headMap.isEmpty()) {
+ Long headStart = headMap.lastKey();
+ Long headEnd = map.get(headStart);
+ if (headEnd >= start - 1) {
+ map.remove(headStart);
+ start = headStart;
+ }
+ }
+ map.subMap(start, end).clear();
+ map.remove(end);
+ map.put(start, end);
+ }
+
+ public LongRangeSet add(LongRangeSet rangeSet) {
+ for(Entry<Long, Long> entry : rangeSet.map.entrySet()) {
+ add(entry.getKey(), entry.getValue());
+ }
+ return this;
+ }
+
+ public boolean same(LongRangeSet rangeSet) {
+ return map.equals(rangeSet.map);
+ }
+ }
+
+ private static class Branch {
+ final LongRangeSet trueSet;
+ final LongRangeSet trueReachedSet, falseReachedSet;
+ final String trueCondition, falseCondition;
+ final Number number;
+ final Set<Long> numbers = new HashSet<>();
+ final String varName;
+
+ public Branch(String varName, String trueCondition, String falseCondition, LongRangeSet trueSet, Number number) {
+ this.trueSet = trueSet;
+ this.trueCondition = fixCondition(trueCondition);
+ this.falseCondition = fixCondition(falseCondition);
+ this.trueReachedSet = trueSet.empty();
+ this.falseReachedSet = trueSet.empty();
+ trueSet.addBordersTo(numbers);
+ this.number = number;
+ this.varName = varName;
+ }
+
+ private String fixCondition(String condition) {
+ if (condition.equals("!= true")) {
+ return "== false";
+ }
+ if (condition.equals("!= false")) {
+ return "== true";
+ }
+ return condition;
+ }
+ }
+
+ private static class Value {
+ final String name;
+ final ValueNumber vn;
+ final String signature;
+
+ public Value(String name, @Nullable ValueNumber vn, String signature) {
+ this.name = name;
+ this.vn = vn;
+ this.signature = signature;
+ }
+ }
+
+ private static class Condition {
+ short opcode;
+ Value value;
+ Number number;
+
+ public Condition(short opcode, Value value, Number number) {
+ super();
+ this.opcode = opcode;
+ this.value = value;
+ this.number = number;
+ }
+ }
+
+ private static class Context {
+ final ConstantPool cp;
+ final LocalVariableTable lvTable;
+ final Map<Integer, Value> types;
+ final ValueNumberDataflow vnaDataflow;
+
+ public Context(ConstantPool cp, LocalVariableTable lvTable, Map<Integer, Value> types, ValueNumberDataflow vnaDataflow) {
+ this.cp = cp;
+ this.lvTable = lvTable;
+ this.types = types;
+ this.vnaDataflow = vnaDataflow;
+ }
+
+ public Condition extractCondition(BackIterator iterator) throws DataflowAnalysisException {
+ Instruction comparisonInstruction = iterator.next().getInstruction();
+ if (!(comparisonInstruction instanceof IfInstruction)) {
+ return null;
+ }
+ short cmpOpcode = comparisonInstruction.getOpcode();
+ int nargs = ((IfInstruction) comparisonInstruction).consumeStack(null);
+ if (nargs == 2) {
+ return extractTwoArgCondition(iterator, cmpOpcode, "I");
+ } else if (nargs == 1) {
+ Object val = extractValue(iterator, "I");
+ if(val instanceof Value) {
+ return new Condition(cmpOpcode, (Value) val, 0);
+ } else if(val instanceof LCMP) {
+ return extractTwoArgCondition(iterator, cmpOpcode, "J");
+ }
+ }
+ return null;
+ }
+
+ private Object extractValue(BackIterator iterator, String defSignature) throws DataflowAnalysisException {
+ if(!iterator.hasNext()) {
+ return null;
+ }
+ BasicBlock block = iterator.block;
+ InstructionHandle ih = iterator.next();
+ Instruction inst = ih.getInstruction();
+ if (inst instanceof ConstantPushInstruction) {
+ return ((ConstantPushInstruction) inst).getValue();
+ }
+ if (inst instanceof CPInstruction && inst instanceof PushInstruction) {
+ Constant constant = cp.getConstant(((CPInstruction) inst).getIndex());
+ if (constant instanceof ConstantObject) {
+ Object value = ((ConstantObject) constant).getConstantValue(cp);
+ if (value instanceof Number) {
+ return value;
+ }
+ }
+ return inst;
+ }
+ if(inst instanceof ARRAYLENGTH) {
+ Object valueObj = extractValue(iterator, defSignature);
+ if(valueObj instanceof Value) {
+ Value value = (Value)valueObj;
+ return new Value(value.name+".length", value.vn, "I");
+ }
+ return null;
+ }
+ if(inst instanceof GETFIELD) {
+ Object valueObj = extractValue(iterator, defSignature);
+ if(valueObj instanceof Value) {
+ Value value = (Value)valueObj;
+ ConstantCP desc = (ConstantCP)cp.getConstant(((GETFIELD)inst).getIndex());
+ ConstantNameAndType nameAndType = (ConstantNameAndType) cp.getConstant(desc.getNameAndTypeIndex());
+ String name = ((ConstantUtf8)cp.getConstant(nameAndType.getNameIndex())).getBytes();
+ String signature = ((ConstantUtf8)cp.getConstant(nameAndType.getSignatureIndex())).getBytes();
+ return new Value(value.name+"."+name, vnaDataflow.getFactAfterLocation(new Location(ih, block)).getStackValue(0), signature);
+ }
+ return null;
+ }
+ if(inst instanceof INVOKEVIRTUAL) {
+ ConstantCP desc = (ConstantCP)cp.getConstant(((INVOKEVIRTUAL)inst).getIndex());
+ ConstantNameAndType nameAndType = (ConstantNameAndType) cp.getConstant(desc.getNameAndTypeIndex());
+ String className = cp.getConstantString(desc.getClassIndex(), CONSTANT_Class);
+ String name = ((ConstantUtf8)cp.getConstant(nameAndType.getNameIndex())).getBytes();
+ String signature = ((ConstantUtf8)cp.getConstant(nameAndType.getSignatureIndex())).getBytes();
+ if(className.equals("java/lang/Integer") && name.equals("intValue") && signature.equals("()I") ||
+ className.equals("java/lang/Long") && name.equals("longValue") && signature.equals("()J") ||
+ className.equals("java/lang/Short") && name.equals("shortValue") && signature.equals("()S") ||
+ className.equals("java/lang/Byte") && name.equals("byteValue") && signature.equals("()B") ||
+ className.equals("java/lang/Boolean") && name.equals("booleanValue") && signature.equals("()Z") ||
+ className.equals("java/lang/Character") && name.equals("charValue") && signature.equals("()C")) {
+ Object valueObj = extractValue(iterator, defSignature);
+ if(valueObj instanceof Value) {
+ Value value = (Value)valueObj;
+ return new Value(value.name, value.vn, String.valueOf(signature.charAt(signature.length()-1)));
+ }
+ }
+ if(className.equals("java/lang/String") && name.equals("length") && signature.equals("()I")) {
+ Object valueObj = extractValue(iterator, defSignature);
+ if(valueObj instanceof Value) {
+ Value value = (Value)valueObj;
+ return new Value(value.name+".length()", value.vn, "I");
+ }
+ }
+ return null;
+ }
+ if(inst instanceof LoadInstruction) {
+ int index = ((LoadInstruction)inst).getIndex();
+ LocalVariable lv = lvTable == null ? null : lvTable.getLocalVariable(index, ih.getPosition());
+ String name, signature;
+ if(lv == null) {
+ name = "local$"+index;
+ if(types.containsKey(index)) {
+ signature = types.get(index).signature;
+ name = types.get(index).name;
+ } else {
+ signature = defSignature;
+ }
+ } else {
+ name = lv.getName();
+ signature = lv.getSignature();
+ }
+ return new Value(name, vnaDataflow.getFactAfterLocation(new Location(ih, block)).getStackValue(0), signature);
+ }
+ return inst;
+ }
+
+ /**
+ * @param opcode
+ * @return opcode which returns the same result when arguments are placed in opposite order
+ */
+ private static short revertOpcode(short opcode) {
+ switch (opcode) {
+ case IF_ICMPGE:
+ return IF_ICMPLE;
+ case IF_ICMPGT:
+ return IF_ICMPLT;
+ case IF_ICMPLE:
+ return IF_ICMPGE;
+ case IF_ICMPLT:
+ return IF_ICMPGT;
+ case IFLE:
+ return IFGE;
+ case IFGE:
+ return IFLE;
+ case IFGT:
+ return IFLT;
+ case IFLT:
+ return IFGT;
+ default:
+ return opcode;
+ }
+ }
+
+ private Condition extractTwoArgCondition(BackIterator iterator, short cmpOpcode, String signature) throws DataflowAnalysisException {
+ Object val2 = extractValue(iterator, signature);
+ if(val2 instanceof Instruction) {
+ return null;
+ }
+ Object val1 = extractValue(iterator, signature);
+ if(val1 instanceof Instruction) {
+ return null;
+ }
+ if (!(val1 instanceof Value) && !(val2 instanceof Value)) {
+ return null;
+ }
+ if (!(val1 instanceof Value)) {
+ Object tmp = val1;
+ val1 = val2;
+ val2 = tmp;
+ cmpOpcode = revertOpcode(cmpOpcode);
+ }
+ if(!(val2 instanceof Number)) {
+ return null;
+ }
+ return new Condition(cmpOpcode, (Value)val1, (Number)val2);
+ }
+ }
+
+ private static class VariableData {
+ final LongRangeSet splitSet;
+ final Map<Edge, Branch> edges = new IdentityHashMap<>();
+ final BitSet reachableBlocks = new BitSet();
+
+ public VariableData(String type) {
+ splitSet = new LongRangeSet(type);
+ }
+
+ public void addBranch(Edge edge, Branch branch) {
+ edges.put(edge, branch);
+ }
+ }
+
+ public static class RedundantCondition {
+ private final Location location;
+ private final String trueCondition;
+ private final String signature;
+ private final boolean byType;
+ private final boolean hasDeadCode;
+ private final boolean border;
+ private final Location deadCodeLocation;
+ private final Location liveCodeLocation;
+ private final Number number;
+
+ public RedundantCondition(Location location, String trueCondition, boolean hasDeadCode, Location deadCodeLocation,
+ Location liveCodeLocation, String signature, boolean byType, Number number, boolean border) {
+ this.location = location;
+ this.trueCondition = trueCondition;
+ this.hasDeadCode = hasDeadCode;
+ this.deadCodeLocation = deadCodeLocation;
+ this.liveCodeLocation = liveCodeLocation;
+ this.signature = signature;
+ this.byType = byType;
+ this.number = number;
+ this.border = border;
+ }
+
+ public boolean isBorder() {
+ return border;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public String getTrueCondition() {
+ return trueCondition;
+ }
+
+ public boolean isDeadCodeUnreachable() {
+ return hasDeadCode;
+ }
+
+ public String getSignature() {
+ return signature;
+ }
+
+ public boolean isByType() {
+ return byType;
+ }
+
+ public Location getLiveCodeLocation() {
+ return liveCodeLocation;
+ }
+
+ public Location getDeadCodeLocation() {
+ return deadCodeLocation;
+ }
+
+ public Number getNumber() {
+ return number;
+ }
+ }
+
+ public static class ValueRangeAnalysis {
+ private List<RedundantCondition> redundantConditions = new ArrayList<>();
+
+ public ValueRangeAnalysis(List<RedundantCondition> redundantConditions) {
+ this.redundantConditions = redundantConditions;
+ }
+
+ public RedundantCondition[] getRedundantConditions() {
+ return redundantConditions.toArray(new RedundantCondition[redundantConditions.size()]);
+ }
+ }
+
+ @Override
+ public ValueRangeAnalysis analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
+ XMethod xMethod = XFactory.createXMethod(descriptor);
+ if (xMethod.isNative() || xMethod.isSynthetic() || xMethod.isAbstract()) {
+ return null;
+ }
+ CFG cfg;
+ try {
+ cfg = analysisCache.getMethodAnalysis(CFG.class, descriptor);
+ } catch (MethodUnprofitableException e) {
+ return null;
+ }
+ if (cfg == null) {
+ return null;
+ }
+ ClassContext classContext = analysisCache.getClassAnalysis(ClassContext.class, descriptor.getClassDescriptor());
+ Method method = analysisCache.getMethodAnalysis(Method.class, descriptor);
+ Context context = new Context(cfg.getMethodGen().getConstantPool().getConstantPool(), method.getCode().getLocalVariableTable(),
+ getParameterTypes(descriptor), classContext.getValueNumberDataflow(method));
+ Map<ValueNumber, VariableData> analyzedArguments = new HashMap<>();
+ Map<Edge, Branch> allEdges = new IdentityHashMap<>();
+ for (Iterator<Edge> edgeIterator = cfg.edgeIterator(); edgeIterator.hasNext();) {
+ Edge edge = edgeIterator.next();
+ if (edge.getType() == EdgeTypes.IFCMP_EDGE) {
+ BasicBlock source = edge.getSource();
+ Condition condition = context.extractCondition(new BackIterator(cfg, source));
+ if(condition == null) {
+ continue;
+ }
+ ValueNumber valueNumber = condition.value.vn;
+ String varName = condition.value.name;
+ VariableData data = analyzedArguments.get(valueNumber);
+ if (data == null) {
+ try {
+ data = new VariableData(condition.value.signature);
+ } catch (IllegalArgumentException e) {
+ continue;
+ }
+ analyzedArguments.put(valueNumber, data);
+ }
+ Number number = condition.number;
+ String numberStr = convertNumber(data.splitSet.getSignature(), number);
+ Branch branch = null;
+ switch (condition.opcode) {
+ case IF_ICMPGT:
+ case IFGT:
+ branch = new Branch(varName, "> " + numberStr, "<= " + numberStr, data.splitSet.gt(number.longValue()), number);
+ break;
+ case IF_ICMPLE:
+ case IFLE:
+ branch = new Branch(varName, "<= " + numberStr, "> " + numberStr, data.splitSet.le(number.longValue()), number);
+ break;
+ case IF_ICMPGE:
+ case IFGE:
+ branch = new Branch(varName, ">= " + numberStr, "< " + numberStr, data.splitSet.ge(number.longValue()), number);
+ break;
+ case IF_ICMPLT:
+ case IFLT:
+ branch = new Branch(varName, "< " + numberStr, ">= " + numberStr, data.splitSet.lt(number.longValue()), number);
+ break;
+ case IF_ICMPEQ:
+ case IFEQ:
+ branch = new Branch(varName, "== " + numberStr, "!= " + numberStr, data.splitSet.eq(number.longValue()), number);
+ break;
+ case IF_ICMPNE:
+ case IFNE:
+ branch = new Branch(varName, "!= " + numberStr, "== " + numberStr, data.splitSet.ne(number.longValue()), number);
+ break;
+ default:
+ break;
+ }
+ if(branch != null) {
+ data.addBranch(edge, branch);
+ allEdges.put(edge, branch);
+ }
+ }
+ }
+ FinallyDuplicatesInfo fi = null;
+ List<RedundantCondition> redundantConditions = new ArrayList<>();
+ for (VariableData data : analyzedArguments.values()) {
+ for (LongRangeSet subRange : data.splitSet) {
+ BitSet reachedBlocks = new BitSet();
+ walkCFG(cfg, cfg.getEntry(), subRange, data.edges, reachedBlocks, new HashSet<Long>());
+ data.reachableBlocks.or(reachedBlocks);
+ }
+ }
+ for (VariableData data : analyzedArguments.values()) {
+ for (Entry<Edge, Branch> entry : data.edges.entrySet()) {
+ Branch branch = entry.getValue();
+ Edge edge = entry.getKey();
+ if (branch.trueReachedSet.isEmpty() ^ branch.falseReachedSet.isEmpty()) {
+ if(fi == null) {
+ fi = analysisCache.getMethodAnalysis(FinallyDuplicatesInfo.class, descriptor);
+ }
+ List<Edge> duplicates = fi.getDuplicates(cfg, edge);
+ if(!duplicates.isEmpty()) {
+ boolean trueValue = !branch.trueReachedSet.isEmpty();
+ boolean falseValue = !branch.falseReachedSet.isEmpty();
+ for(Edge dup : duplicates) {
+ Branch dupBranch = allEdges.get(dup);
+ if(dupBranch != null) {
+ trueValue |= !dupBranch.trueReachedSet.isEmpty();
+ falseValue |= !dupBranch.falseReachedSet.isEmpty();
+ }
+ }
+ if(trueValue && falseValue) {
+ continue;
+ }
+ }
+ BasicBlock trueTarget = edge.getTarget();
+ BasicBlock falseTarget = cfg.getSuccessorWithEdgeType(edge.getSource(), EdgeTypes.FALL_THROUGH_EDGE);
+ String condition;
+ BasicBlock deadTarget, aliveTarget;
+ if(branch.trueReachedSet.isEmpty()) {
+ condition = branch.varName + " " + branch.falseCondition;
+ deadTarget = trueTarget;
+ aliveTarget = falseTarget;
+ } else {
+ condition = branch.varName + " " + branch.trueCondition;
+ deadTarget = falseTarget;
+ aliveTarget = trueTarget;
+ }
+ redundantConditions.add(new RedundantCondition(Location.getLastLocation(edge.getSource()), condition,
+ !data.reachableBlocks.get(deadTarget.getLabel()), getLocation(deadTarget), getLocation(aliveTarget),
+ branch.trueSet.getSignature(), branch.trueSet.isEmpty() || branch.trueSet.isFull(),
+ branch.number, branch.numbers.contains(branch.number.longValue())));
+ }
+ }
+ }
+ if (!redundantConditions.isEmpty()) {
+ BitSet assertionBlocks = new BitSet();
+ MethodGen methodGen = cfg.getMethodGen();
+ Iterator<InstructionHandle> iterator = methodGen.getInstructionList().iterator();
+ while(iterator.hasNext()) {
+ InstructionHandle ih = iterator.next();
+ if(ih.getInstruction() instanceof GETSTATIC) {
+ Instruction next = ih.getNext().getInstruction();
+ if(next instanceof IFNE) {
+ GETSTATIC getStatic = (GETSTATIC)ih.getInstruction();
+ if ("$assertionsDisabled".equals(getStatic.getFieldName(methodGen.getConstantPool()))
+ && "Z".equals(getStatic.getSignature(methodGen.getConstantPool()))) {
+ int end = ((IFNE)next).getTarget().getPosition();
+ assertionBlocks.set(ih.getNext().getPosition(), end);
+ }
+ }
+ }
+ }
+ if(!assertionBlocks.isEmpty()) {
+ List<RedundantCondition> filtered = new ArrayList<>();
+ for(RedundantCondition condition : redundantConditions) {
+ if(!(assertionBlocks.get(condition.getLocation().getHandle().getPosition()))) {
+ // TODO: do not filter out failed asserts
+ filtered.add(condition);
+ }
+ }
+ redundantConditions = filtered;
+ }
+ Collections.sort(redundantConditions, new Comparator<RedundantCondition>() {
+ @Override
+ public int compare(RedundantCondition o1, RedundantCondition o2) {
+ return o1.location.compareTo(o2.location);
+ }
+ });
+ return new ValueRangeAnalysis(redundantConditions);
+ }
+ return null;
+ }
+
+ private static Location getLocation(BasicBlock block) {
+ InstructionHandle handle = block.getFirstInstruction();
+ if(handle == null) {
+ handle = block.getExceptionThrower();
+ }
+ return handle == null ? null : new Location(handle, block);
+ }
+
+ private static String convertNumber(String signature, Number number) {
+ long val = number.longValue();
+ switch (signature) {
+ case "Z":
+ if (val == 0) {
+ return "false";
+ }
+ return "true";
+ case "C":
+ if (val == '\n') {
+ return "'\\n'";
+ }
+ if (val == '\r') {
+ return "'\\r'";
+ }
+ if (val == '\b') {
+ return "'\\b'";
+ }
+ if (val == '\t') {
+ return "'\\t'";
+ }
+ if (val == '\'') {
+ return "'\\''";
+ }
+ if (val == '\\') {
+ return "'\\\\'";
+ }
+ if (val >= 32 && val < 128) {
+ return "'" + ((char) val) + "'";
+ }
+ return convertNumber(val);
+ case "I":
+ if(val >= 32 && val < 128) {
+ return val+" ('" + ((char) val) + "')";
+ }
+ return convertNumber(val);
+ default:
+ return convertNumber(val);
+ }
+ }
+
+ private static String convertNumber(long val) {
+ if(val == Long.MIN_VALUE) {
+ return "Long.MIN_VALUE";
+ }
+ if(val == Long.MAX_VALUE) {
+ return "Long.MAX_VALUE";
+ }
+ String suffix = "";
+ if (val > Integer.MAX_VALUE || val < Integer.MIN_VALUE) {
+ suffix = "L";
+ }
+ if (val > 128) {
+ return val + suffix + " (0x" + Long.toHexString(val) + suffix + ")";
+ }
+ return val + suffix;
+ }
+
+ private static Map<Integer, Value> getParameterTypes(MethodDescriptor descriptor) {
+ Type[] argumentTypes = Type.getArgumentTypes(descriptor.getSignature());
+ int j = 0;
+ Map<Integer, Value> result = new HashMap<>();
+ if(!descriptor.isStatic()) {
+ result.put(j++, new Value("this", null, "L"+descriptor.getSlashedClassName()+";"));
+ }
+ for (int i = 0; i < argumentTypes.length; i++) {
+ result.put(j, new Value("arg"+i, null, argumentTypes[i].getSignature()));
+ j += argumentTypes[i].getSize();
+ }
+ return result;
+ }
+
+ private static void walkCFG(CFG cfg, BasicBlock basicBlock, LongRangeSet subRange, Map<Edge, Branch> edges, BitSet reachedBlocks, Set<Long> numbers) {
+ reachedBlocks.set(basicBlock.getLabel());
+ for (Iterator<Edge> iterator = cfg.outgoingEdgeIterator(basicBlock); iterator.hasNext();) {
+ Edge edge = iterator.next();
+ Branch branch = edges.get(edge);
+ if (branch != null) {
+ branch.numbers.addAll(numbers);
+ numbers = new HashSet<>(numbers);
+ numbers.add(branch.number.longValue());
+ if (branch.trueSet.intersects(subRange)) {
+ branch.trueReachedSet.add(subRange);
+ } else {
+ branch.falseReachedSet.add(subRange);
+ continue;
+ }
+ }
+ BasicBlock target = edge.getTarget();
+ if (!reachedBlocks.get(target.getLabel())) {
+ walkCFG(cfg, target, subRange, edges, reachedBlocks, numbers);
+ }
+ if (branch != null) {
+ break;
+ }
+ }
+ }
+
+ private static class BackIterator implements Iterator<InstructionHandle> {
+ private BasicBlock block;
+ private InstructionHandle next;
+ private final CFG cfg;
+
+ public BackIterator(CFG cfg, BasicBlock block) {
+ this.block = block;
+ this.cfg = cfg;
+ this.next = block.getLastInstruction();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ @Override
+ public InstructionHandle next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ InstructionHandle result = next;
+ if(result == block.getFirstInstruction()) {
+ do {
+ Iterator<Edge> edgeIterator = cfg.incomingEdgeIterator(block);
+ if(!edgeIterator.hasNext()) {
+ break;
+ }
+ Edge edge = edgeIterator.next();
+ if(!edgeIterator.hasNext() && edge.getType() == EdgeTypes.FALL_THROUGH_EDGE) {
+ block = edge.getSource();
+ } else {
+ break;
+ }
+ } while(block.isExceptionThrower());
+ }
+ next = (block.isExceptionThrower() || result == block.getFirstInstruction()) ? null : next.getPrev();
+ return result;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ @Override
+ public void registerWith(IAnalysisCache analysisCache) {
+ analysisCache.registerMethodAnalysisEngine(ValueRangeAnalysis.class, this);
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/AbstractScannableCodeBase.java b/src/java/edu/umd/cs/findbugs/classfile/impl/AbstractScannableCodeBase.java
index d82a4d8..dfca728 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/AbstractScannableCodeBase.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/AbstractScannableCodeBase.java
@@ -31,11 +31,11 @@ import edu.umd.cs.findbugs.classfile.IScannableCodeBase;
* Abstract base class for implementations of IScannableCodeBase. Provides an
* implementation of the getCodeBaseLocator(), containsSourceFiles(),
* setApplicationCodeBase(), and isApplicationCodeBase() methods.
- *
+ *
* @author David Hovemeyer
*/
public abstract class AbstractScannableCodeBase implements IScannableCodeBase {
- private ICodeBaseLocator codeBaseLocator;
+ private final ICodeBaseLocator codeBaseLocator;
private boolean isAppCodeBase;
@@ -43,7 +43,7 @@ public abstract class AbstractScannableCodeBase implements IScannableCodeBase {
private long lastModifiedTime;
- private Map<String, String> resourceNameTranslationMap;
+ private final Map<String, String> resourceNameTranslationMap;
public AbstractScannableCodeBase(ICodeBaseLocator codeBaseLocator) {
this.codeBaseLocator = codeBaseLocator;
@@ -53,19 +53,21 @@ public abstract class AbstractScannableCodeBase implements IScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#getCodeBaseLocator()
*/
+ @Override
public ICodeBaseLocator getCodeBaseLocator() {
return codeBaseLocator;
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IScannableCodeBase#containsSourceFiles()
*/
+ @Override
public boolean containsSourceFiles() {
return false;
@@ -73,46 +75,51 @@ public abstract class AbstractScannableCodeBase implements IScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBase#setApplicationCodeBase(boolean)
*/
+ @Override
public void setApplicationCodeBase(boolean isAppCodeBase) {
this.isAppCodeBase = isAppCodeBase;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#isApplicationCodeBase()
*/
+ @Override
public boolean isApplicationCodeBase() {
return isAppCodeBase;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#setHowDiscovered(int)
*/
+ @Override
public void setHowDiscovered(ICodeBase.Discovered howDiscovered) {
this.howDiscovered = howDiscovered;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#getHowDiscovered()
*/
+ @Override
public ICodeBase.Discovered getHowDiscovered() {
return howDiscovered;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#setLastModifiedTime(long)
*/
+ @Override
public void setLastModifiedTime(long lastModifiedTime) {
if (lastModifiedTime > 0 && FindBugs.validTimestamp(lastModifiedTime)) {
this.lastModifiedTime = lastModifiedTime;
@@ -126,16 +133,18 @@ public abstract class AbstractScannableCodeBase implements IScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#getLastModifiedTime()
*/
+ @Override
public long getLastModifiedTime() {
return lastModifiedTime;
}
public void addResourceNameTranslation(String origResourceName, String newResourceName) {
- if (!origResourceName.equals(newResourceName))
+ if (!origResourceName.equals(newResourceName)) {
resourceNameTranslationMap.put(origResourceName, newResourceName);
+ }
}
public String translateResourceName(String resourceName) {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/AbstractScannableCodeBaseEntry.java b/src/java/edu/umd/cs/findbugs/classfile/impl/AbstractScannableCodeBaseEntry.java
index 5f28164..0dc0c59 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/AbstractScannableCodeBaseEntry.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/AbstractScannableCodeBaseEntry.java
@@ -25,26 +25,29 @@ import edu.umd.cs.findbugs.classfile.ICodeBaseEntry;
* @author David Hovemeyer
*/
public abstract class AbstractScannableCodeBaseEntry implements ICodeBaseEntry {
+ @Override
public abstract AbstractScannableCodeBase getCodeBase();
public abstract String getRealResourceName();
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBaseEntry#overrideResourceName(java
* .lang.String)
*/
+ @Override
public void overrideResourceName(String resourceName) {
getCodeBase().addResourceNameTranslation(getRealResourceName(), resourceName);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getResourceName()
*/
+ @Override
public String getResourceName() {
return getCodeBase().translateResourceName(getRealResourceName());
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/AnalysisCache.java b/src/java/edu/umd/cs/findbugs/classfile/impl/AnalysisCache.java
index 3a9c505..32c480a 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/AnalysisCache.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/AnalysisCache.java
@@ -19,6 +19,8 @@
package edu.umd.cs.findbugs.classfile.impl;
+import static java.util.Objects.requireNonNull;
+
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -70,7 +72,7 @@ public class AnalysisCache implements IAnalysisCache {
*/
private static final int MAX_CLASS_RESULTS_TO_CACHE = 5000;
- private static final boolean ASSERTIONS_ENABLED = SystemProperties.ASSERTIONS_ENABLED;
+ // private static final boolean ASSERTIONS_ENABLED = SystemProperties.ASSERTIONS_ENABLED;
// Fields
private final IClassPath classPath;
@@ -89,6 +91,7 @@ public class AnalysisCache implements IAnalysisCache {
private final Map<?, ?> analysisLocals = Collections.synchronizedMap(new HashMap<Object, Object>());
+ @Override
public final Map<?, ?> getAnalysisLocals() {
return analysisLocals;
}
@@ -137,8 +140,9 @@ public class AnalysisCache implements IAnalysisCache {
@SuppressWarnings("unchecked")
static <E> E checkedCast(Class<E> analysisClass, Object o) {
- if (SystemProperties.ASSERTIONS_ENABLED)
+ if (SystemProperties.ASSERTIONS_ENABLED) {
return analysisClass.cast(o);
+ }
return (E) o;
}
@@ -160,15 +164,12 @@ public class AnalysisCache implements IAnalysisCache {
this.databaseMap = new HashMap<Class<?>, Object>();
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.classfile.IAnalysisCache#getClassPath()
- */
+ @Override
public IClassPath getClassPath() {
return classPath;
}
+ @Override
public void purgeAllMethodAnalysis() {
// System.out.println("ZZZ : purging all method analyses");
@@ -193,6 +194,7 @@ public class AnalysisCache implements IAnalysisCache {
return (Map<ClassDescriptor, E>) descriptorMap;
}
+ @Override
public void purgeClassAnalysis(Class<?> analysisClass) {
classAnalysisMap.remove(analysisClass);
}
@@ -233,18 +235,10 @@ public class AnalysisCache implements IAnalysisCache {
}
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisCache#getClassAnalysis(java.lang
- * .Class, edu.umd.cs.findbugs.classfile.ClassDescriptor)
- */
+ @Override
@SuppressWarnings("unchecked")
public <E> E getClassAnalysis(Class<E> analysisClass, @Nonnull ClassDescriptor classDescriptor) throws CheckedAnalysisException {
- if (classDescriptor == null) {
- throw new NullPointerException("classDescriptor is null");
- }
+ requireNonNull(classDescriptor, "classDescriptor is null");
// Get the descriptor->result map for this analysis class,
// creating if necessary
Map<ClassDescriptor, Object> descriptorMap = findOrCreateDescriptorMap(classAnalysisMap,
@@ -304,13 +298,7 @@ public class AnalysisCache implements IAnalysisCache {
return checkedCast(analysisClass, analysisResult);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisCache#probeClassAnalysis(java.
- * lang.Class, edu.umd.cs.findbugs.classfile.ClassDescriptor)
- */
+ @Override
public <E> E probeClassAnalysis(Class<E> analysisClass, @Nonnull ClassDescriptor classDescriptor) {
Map<ClassDescriptor, Object> descriptorMap = classAnalysisMap.get(analysisClass);
if (descriptorMap == null) {
@@ -323,17 +311,9 @@ public class AnalysisCache implements IAnalysisCache {
return Integer.toHexString(System.identityHashCode(o));
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisCache#getMethodAnalysis(java.lang
- * .Class, edu.umd.cs.findbugs.classfile.MethodDescriptor)
- */
+ @Override
public <E> E getMethodAnalysis(Class<E> analysisClass, @Nonnull MethodDescriptor methodDescriptor) throws CheckedAnalysisException {
- if (methodDescriptor == null) {
- throw new NullPointerException("methodDescriptor is null");
- }
+ requireNonNull(methodDescriptor, "methodDescriptor is null");
ClassContext classContext = getClassAnalysis(ClassContext.class, methodDescriptor.getClassDescriptor());
Object object = classContext.getMethodAnalysis(analysisClass, methodDescriptor);
@@ -392,14 +372,7 @@ public class AnalysisCache implements IAnalysisCache {
}
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisCache#eagerlyPutMethodAnalysis
- * (java.lang.Class, edu.umd.cs.findbugs.classfile.MethodDescriptor,
- * java.lang.Object)
- */
+ @Override
public <E> void eagerlyPutMethodAnalysis(Class<E> analysisClass, @Nonnull MethodDescriptor methodDescriptor, E analysisObject) {
try {
ClassContext classContext = getClassAnalysis(ClassContext.class, methodDescriptor.getClassDescriptor());
@@ -413,13 +386,7 @@ public class AnalysisCache implements IAnalysisCache {
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisCache#purgeMethodAnalyses(edu.
- * umd.cs.findbugs.classfile.MethodDescriptor)
- */
+ @Override
public void purgeMethodAnalyses(@Nonnull MethodDescriptor methodDescriptor) {
try {
@@ -481,48 +448,26 @@ public class AnalysisCache implements IAnalysisCache {
return descriptorMap;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisCache#registerClassAnalysisEngine
- * (java.lang.Class, edu.umd.cs.findbugs.classfile.IClassAnalysisEngine)
- */
+ @Override
public <E> void registerClassAnalysisEngine(Class<E> analysisResultType, IClassAnalysisEngine<E> classAnalysisEngine) {
classAnalysisEngineMap.put(analysisResultType, classAnalysisEngine);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisCache#registerMethodAnalysisEngine
- * (java.lang.Class, edu.umd.cs.findbugs.classfile.IMethodAnalysisEngine)
- */
+ @Override
public <E> void registerMethodAnalysisEngine(Class<E> analysisResultType, IMethodAnalysisEngine<E> methodAnalysisEngine) {
methodAnalysisEngineMap.put(analysisResultType, methodAnalysisEngine);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisCache#registerDatabaseFactory(
- * java.lang.Class, edu.umd.cs.findbugs.classfile.IDatabaseFactory)
- */
+ @Override
public <E> void registerDatabaseFactory(Class<E> databaseClass, IDatabaseFactory<E> databaseFactory) {
databaseFactoryMap.put(databaseClass, databaseFactory);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisCache#getDatabase(java.lang.Class)
- */
+ @Override
public <E> E getDatabase(Class<E> databaseClass) {
return getDatabase(databaseClass, false);
}
+ @Override
public @CheckForNull <E> E getOptionalDatabase(Class<E> databaseClass) {
return getDatabase(databaseClass, true);
}
@@ -534,7 +479,9 @@ public class AnalysisCache implements IAnalysisCache {
// Find the database factory
IDatabaseFactory<?> databaseFactory = databaseFactoryMap.get(databaseClass);
if (databaseFactory == null) {
- if (optional) return null;
+ if (optional) {
+ return null;
+ }
throw new IllegalArgumentException("No database factory registered for " + databaseClass.getName());
}
@@ -545,7 +492,6 @@ public class AnalysisCache implements IAnalysisCache {
database = new AbnormalAnalysisResult(e);
}
// FIXME: should catch and re-throw RuntimeExceptions?
-
databaseMap.put(databaseClass, database);
}
@@ -553,35 +499,20 @@ public class AnalysisCache implements IAnalysisCache {
throw new UncheckedAnalysisException("Error instantiating " + databaseClass.getName() + " database",
((AbnormalAnalysisResult) database).checkedAnalysisException);
}
-
return databaseClass.cast(database);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisCache#eagerlyPutDatabase(java.
- * lang.Class, java.lang.Object)
- */
+ @Override
public <E> void eagerlyPutDatabase(Class<E> databaseClass, E database) {
databaseMap.put(databaseClass, database);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.classfile.IAnalysisCache#getErrorLogger()
- */
+ @Override
public IErrorLogger getErrorLogger() {
return bugReporter;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.classfile.IAnalysisCache#getProfiler()
- */
+ @Override
public Profiler getProfiler() {
return bugReporter.getProjectStats().getProfiler();
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/ClassFactory.java b/src/java/edu/umd/cs/findbugs/classfile/impl/ClassFactory.java
index 32438bd..4e38c82 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/ClassFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/ClassFactory.java
@@ -36,7 +36,7 @@ import edu.umd.cs.findbugs.classfile.ResourceNotFoundException;
/**
* Factory to create codebase/classpath/classfile objects.
- *
+ *
* @author David Hovemeyer
*/
public class ClassFactory implements IClassFactory {
@@ -51,30 +51,33 @@ public class ClassFactory implements IClassFactory {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.impl.IClassFactory#createClassPath()
*/
+ @Override
public IClassPath createClassPath() {
return new ClassPathImpl();
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IClassFactory#createClassPathBuilder(edu
* .umd.cs.findbugs.classfile.IErrorLogger)
*/
+ @Override
public IClassPathBuilder createClassPathBuilder(IErrorLogger errorLogger) {
return new ClassPathBuilder(this, errorLogger);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.impl.IClassFactory#
* createFilesystemCodeBaseLocator(java.lang.String)
*/
+ @Override
public ICodeBaseLocator createFilesystemCodeBaseLocator(String pathName) {
// Attempt to canonicalize the pathname.
// It's not fatal if we can't.
@@ -89,11 +92,12 @@ public class ClassFactory implements IClassFactory {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.IClassFactory#
* createNestedArchiveCodeBaseLocator
* (edu.umd.cs.findbugs.classfile.ICodeBase, java.lang.String)
*/
+ @Override
public ICodeBaseLocator createNestedArchiveCodeBaseLocator(ICodeBase parentCodeBase, String path) {
return new NestedZipFileCodeBaseLocator(parentCodeBase, path);
}
@@ -125,11 +129,12 @@ public class ClassFactory implements IClassFactory {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IClassFactory#createAnalysisCache(edu.umd
* .cs.findbugs.classfile.IClassPath)
*/
+ @Override
public IAnalysisCache createAnalysisCache(IClassPath classPath, BugReporter errorLogger) {
IAnalysisCache analysisCache = new AnalysisCache(classPath, errorLogger);
return analysisCache;
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/ClassPathBuilder.java b/src/java/edu/umd/cs/findbugs/classfile/impl/ClassPathBuilder.java
index a95c371..edabb67 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/ClassPathBuilder.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/ClassPathBuilder.java
@@ -141,10 +141,12 @@ public class ClassPathBuilder implements IClassPathBuilder {
return ((IScannableCodeBase) codeBase).iterator();
} else {
return new ICodeBaseIterator() {
+ @Override
public boolean hasNext() throws InterruptedException {
return false;
}
+ @Override
public ICodeBaseEntry next() throws InterruptedException {
throw new UnsupportedOperationException();
}
@@ -192,6 +194,7 @@ public class ClassPathBuilder implements IClassPathBuilder {
* edu.umd.cs.findbugs.classfile.IClassPathBuilder#addCodeBase(edu.umd.cs
* .findbugs.classfile.ICodeBaseLocator, boolean)
*/
+ @Override
public void addCodeBase(ICodeBaseLocator locator, boolean isApplication) {
addToWorkList(projectWorkList, new WorkListItem(locator, isApplication, ICodeBase.Discovered.SPECIFIED));
}
@@ -203,6 +206,7 @@ public class ClassPathBuilder implements IClassPathBuilder {
* edu.umd.cs.findbugs.classfile.IClassPathBuilder#scanNestedArchives(boolean
* )
*/
+ @Override
public void scanNestedArchives(boolean scanNestedArchives) {
this.scanNestedArchives = scanNestedArchives;
}
@@ -215,8 +219,9 @@ public class ClassPathBuilder implements IClassPathBuilder {
* .classfile.IClassPath,
* edu.umd.cs.findbugs.classfile.IClassPathBuilderProgress)
*/
+ @Override
public void build(IClassPath classPath, IClassPathBuilderProgress progress) throws CheckedAnalysisException, IOException,
- InterruptedException {
+ InterruptedException {
// Discover all directly and indirectly referenced codebases
processWorkList(classPath, projectWorkList, progress);
@@ -522,6 +527,7 @@ public class ClassPathBuilder implements IClassPathBuilder {
*
* @see java.io.FileFilter#accept(java.io.File)
*/
+ @Override
public boolean accept(File pathname) {
String path = pathname.getPath();
boolean isArchive = Archive.isArchiveFileName(path);
@@ -621,9 +627,11 @@ public class ClassPathBuilder implements IClassPathBuilder {
scanJarManifestForClassPathEntries(workList, discoveredCodeBase.getCodeBase());
} catch (IOException e) {
if (item.isAppCodeBase() || item.getHowDiscovered() == ICodeBase.Discovered.SPECIFIED) {
- if (e instanceof FileNotFoundException)
+ if (e instanceof FileNotFoundException) {
errorLogger.logError("File not found: " + item.getCodeBaseLocator());
- else errorLogger.logError("Cannot open codebase " + item.getCodeBaseLocator(), e);
+ } else {
+ errorLogger.logError("Cannot open codebase " + item.getCodeBaseLocator(), e);
+ }
}
} catch (ResourceNotFoundException e) {
if (item.getHowDiscovered() == ICodeBase.Discovered.SPECIFIED) {
@@ -808,6 +816,7 @@ public class ClassPathBuilder implements IClassPathBuilder {
*
* @see edu.umd.cs.findbugs.classfile.IClassPathBuilder#getAppClassList()
*/
+ @Override
public List<ClassDescriptor> getAppClassList() {
return appClassList;
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/ClassPathImpl.java b/src/java/edu/umd/cs/findbugs/classfile/impl/ClassPathImpl.java
index 77cfb6d..ccf5b45 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/ClassPathImpl.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/ClassPathImpl.java
@@ -38,11 +38,11 @@ import edu.umd.cs.findbugs.classfile.ResourceNotFoundException;
* @author David Hovemeyer
*/
public class ClassPathImpl implements IClassPath {
- private List<IScannableCodeBase> appCodeBaseList;
+ private final List<IScannableCodeBase> appCodeBaseList;
- private List<ICodeBase> auxCodeBaseList;
+ private final List<ICodeBase> auxCodeBaseList;
- private Map<String, ICodeBaseEntry> codeBaseEntryMap;
+ private final Map<String, ICodeBaseEntry> codeBaseEntryMap;
public ClassPathImpl() {
this.appCodeBaseList = new LinkedList<IScannableCodeBase>();
@@ -72,6 +72,7 @@ public class ClassPathImpl implements IClassPath {
* edu.umd.cs.findbugs.classfile.IClassPath#addCodeBase(edu.umd.cs.findbugs
* .classfile.ICodeBase)
*/
+ @Override
public void addCodeBase(ICodeBase codeBase) {
if (codeBase.isApplicationCodeBase()) {
if (!(codeBase instanceof IScannableCodeBase)) {
@@ -88,6 +89,7 @@ public class ClassPathImpl implements IClassPath {
*
* @see edu.umd.cs.findbugs.classfile.IClassPath#appCodeBaseIterator()
*/
+ @Override
public Iterator<? extends ICodeBase> appCodeBaseIterator() {
return appCodeBaseList.iterator();
}
@@ -97,6 +99,7 @@ public class ClassPathImpl implements IClassPath {
*
* @see edu.umd.cs.findbugs.classfile.IClassPath#auxCodeBaseIterator()
*/
+ @Override
public Iterator<? extends ICodeBase> auxCodeBaseIterator() {
return auxCodeBaseList.iterator();
}
@@ -106,6 +109,7 @@ public class ClassPathImpl implements IClassPath {
*
* @see edu.umd.cs.findbugs.classfile.IClassPath#close()
*/
+ @Override
public void close() {
for (ICodeBase codeBase : appCodeBaseList) {
codeBase.close();
@@ -118,6 +122,7 @@ public class ClassPathImpl implements IClassPath {
codeBaseEntryMap.clear();
}
+ @Override
public Map<String, ICodeBaseEntry> getApplicationCodebaseEntries() {
Map<String, ICodeBaseEntry> appEntries = new HashMap<String, ICodeBaseEntry>();
Iterator<Entry<String, ICodeBaseEntry>> iterator = codeBaseEntryMap.entrySet().iterator();
@@ -137,6 +142,7 @@ public class ClassPathImpl implements IClassPath {
* @see
* edu.umd.cs.findbugs.classfile.IClassPath#lookupResource(java.lang.String)
*/
+ @Override
public ICodeBaseEntry lookupResource(String resourceName) throws ResourceNotFoundException {
// See if we have cached the codebase entry for this resource
ICodeBaseEntry result = codeBaseEntryMap.get(resourceName);
@@ -193,6 +199,7 @@ public class ClassPathImpl implements IClassPath {
* edu.umd.cs.findbugs.classfile.IClassPath#mapResourceNameToCodeBaseEntry
* (java.lang.String, edu.umd.cs.findbugs.classfile.ICodeBaseEntry)
*/
+ @Override
public void mapResourceNameToCodeBaseEntry(String resourceName, ICodeBaseEntry codeBaseEntry) {
codeBaseEntryMap.put(resourceName, codeBaseEntry);
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/DelegatingCodeBaseEntry.java b/src/java/edu/umd/cs/findbugs/classfile/impl/DelegatingCodeBaseEntry.java
index b9e1fda..f01d3fc 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/DelegatingCodeBaseEntry.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/DelegatingCodeBaseEntry.java
@@ -32,13 +32,13 @@ import edu.umd.cs.findbugs.classfile.ResourceNotFoundException;
* Implementation of ICodeBaseEntry that delegates to another codebase entry.
* This is needed for codebase entries in nested zipfiles, which are implemented
* using a private zipfile codebase.
- *
+ *
* @author David Hovemeyer
*/
public class DelegatingCodeBaseEntry implements ICodeBaseEntry {
- private ICodeBase frontEndCodeBase;
+ private final ICodeBase frontEndCodeBase;
- private ICodeBaseEntry delegateCodeBaseEntry;
+ private final ICodeBaseEntry delegateCodeBaseEntry;
public DelegatingCodeBaseEntry(ICodeBase frontEndCodeBase, ICodeBaseEntry delegateCodeBaseEntry) {
this.frontEndCodeBase = frontEndCodeBase;
@@ -47,63 +47,69 @@ public class DelegatingCodeBaseEntry implements ICodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getNumBytes()
*/
+ @Override
public int getNumBytes() {
return delegateCodeBaseEntry.getNumBytes();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getResourceName()
*/
+ @Override
public String getResourceName() {
return delegateCodeBaseEntry.getResourceName();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#openResource()
*/
+ @Override
public InputStream openResource() throws IOException {
return delegateCodeBaseEntry.openResource();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getCodeBase()
*/
+ @Override
public ICodeBase getCodeBase() {
return frontEndCodeBase;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getClassDescriptor()
*/
+ @Override
public ClassDescriptor getClassDescriptor() throws ResourceNotFoundException, InvalidClassFileFormatException {
return delegateCodeBaseEntry.getClassDescriptor();
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBaseEntry#overrideResourceName(java
* .lang.String)
*/
+ @Override
public void overrideResourceName(String resourceName) {
delegateCodeBaseEntry.overrideResourceName(resourceName);
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@@ -118,7 +124,7 @@ public class DelegatingCodeBaseEntry implements ICodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
@@ -128,7 +134,7 @@ public class DelegatingCodeBaseEntry implements ICodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/DelegatingCodeBaseIterator.java b/src/java/edu/umd/cs/findbugs/classfile/impl/DelegatingCodeBaseIterator.java
index b8721f7..4b773f0 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/DelegatingCodeBaseIterator.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/DelegatingCodeBaseIterator.java
@@ -28,13 +28,13 @@ import edu.umd.cs.findbugs.classfile.IScannableCodeBase;
* An implementation of ICodeBaseIterator that delegates to another codebase. In
* particular, the codebase entries it creates are DelegatingCodeBaseEntry
* objects.
- *
+ *
* @author David Hovemeyer
*/
public class DelegatingCodeBaseIterator implements ICodeBaseIterator {
- private ICodeBase frontEndCodeBase;
+ private final ICodeBase frontEndCodeBase;
- private ICodeBaseIterator delegateCodeBaseIterator;
+ private final ICodeBaseIterator delegateCodeBaseIterator;
public DelegatingCodeBaseIterator(ICodeBase frontEndCodeBase, IScannableCodeBase delegateCodeBase)
throws InterruptedException {
@@ -44,18 +44,20 @@ public class DelegatingCodeBaseIterator implements ICodeBaseIterator {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseIterator#hasNext()
*/
+ @Override
public boolean hasNext() throws InterruptedException {
return delegateCodeBaseIterator.hasNext();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseIterator#next()
*/
+ @Override
public ICodeBaseEntry next() throws InterruptedException {
ICodeBaseEntry delegateCodeBaseEntry = delegateCodeBaseIterator.next();
return new DelegatingCodeBaseEntry(frontEndCodeBase, delegateCodeBaseEntry);
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/DirectoryCodeBase.java b/src/java/edu/umd/cs/findbugs/classfile/impl/DirectoryCodeBase.java
index a921500..c43d3c9 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/DirectoryCodeBase.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/DirectoryCodeBase.java
@@ -37,7 +37,7 @@ import edu.umd.cs.findbugs.classfile.ICodeBaseLocator;
/**
* IScannableCodeBase implementation to read resources from a filesystem
* directory.
- *
+ *
* @author David Hovemeyer
*/
public class DirectoryCodeBase extends AbstractScannableCodeBase {
@@ -47,18 +47,20 @@ public class DirectoryCodeBase extends AbstractScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseIterator#hasNext()
*/
+ @Override
public boolean hasNext() throws InterruptedException {
return fileNameIterator.hasNext();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseIterator#next()
*/
+ @Override
public ICodeBaseEntry next() throws InterruptedException {
final String fileName = fileNameIterator.next();
@@ -67,8 +69,8 @@ public class DirectoryCodeBase extends AbstractScannableCodeBase {
// Update last modified time
File file = new File(fileName);
- long modTime = file.lastModified();
- addLastModifiedTime(modTime);
+ long modTime = file.lastModified();
+ addLastModifiedTime(modTime);
return new DirectoryCodeBaseEntry(DirectoryCodeBase.this, resourceName);
}
@@ -82,7 +84,7 @@ public class DirectoryCodeBase extends AbstractScannableCodeBase {
/**
* Constructor.
- *
+ *
* @param codeBaseLocator
* the codebase locator for this codebase
* @param directory
@@ -97,9 +99,10 @@ public class DirectoryCodeBase extends AbstractScannableCodeBase {
this.rfs = new RecursiveFileSearch(directory.getPath(), new FileFilter() {
/*
* (non-Javadoc)
- *
+ *
* @see java.io.FileFilter#accept(java.io.File)
*/
+ @Override
public boolean accept(File pathname) {
return true;
}
@@ -109,9 +112,10 @@ public class DirectoryCodeBase extends AbstractScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.IScannableCodeBase#iterator()
*/
+ @Override
public ICodeBaseIterator iterator() throws InterruptedException {
if (!searchPerformed) {
rfs.search();
@@ -123,28 +127,31 @@ public class DirectoryCodeBase extends AbstractScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#getPathName()
*/
+ @Override
public String getPathName() {
return directory.getPath();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#close()
*/
+ @Override
public void close() {
// Nothing to do
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBase#lookupResource(java.lang.String)
*/
+ @Override
public ICodeBaseEntry lookupResource(String resourceName) {
// Translate resource name, in case a resource name
// has been overridden and the resource is being accessed
@@ -165,9 +172,6 @@ public class DirectoryCodeBase extends AbstractScannableCodeBase {
/**
* Get the full path of given resource.
- *
- * @param resourceName
- * @return
*/
File getFullPathOfResource(String resourceName) {
return new File(directory, resourceName);
@@ -175,7 +179,7 @@ public class DirectoryCodeBase extends AbstractScannableCodeBase {
/**
* Get the resource name given a full filename.
- *
+ *
* @param fileName
* the full filename (which must be inside the directory)
* @return the resource name (i.e., the filename with the directory stripped
@@ -217,7 +221,7 @@ public class DirectoryCodeBase extends AbstractScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/DirectoryCodeBaseEntry.java b/src/java/edu/umd/cs/findbugs/classfile/impl/DirectoryCodeBaseEntry.java
index ff19323..b4ad978 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/DirectoryCodeBaseEntry.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/DirectoryCodeBaseEntry.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.classfile.InvalidClassFileFormatException;
/**
* Codebase entry class for directory codebases.
- *
+ *
* @author David Hovemeyer
*/
public class DirectoryCodeBaseEntry extends AbstractScannableCodeBaseEntry {
@@ -44,9 +44,10 @@ public class DirectoryCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getNumBytes()
*/
+ @Override
public int getNumBytes() {
File fullPath = codeBase.getFullPathOfResource(realResourceName);
// this is not needed but causes slowdown on a slow file system IO
@@ -60,16 +61,17 @@ public class DirectoryCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#openResource()
*/
+ @Override
public InputStream openResource() throws IOException {
return codeBase.openFile(realResourceName);
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.impl.AbstractScannableCodeBaseEntry#getCodeBase
* ()
@@ -81,7 +83,7 @@ public class DirectoryCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.impl.AbstractScannableCodeBaseEntry#
* getRealResourceName()
*/
@@ -92,16 +94,17 @@ public class DirectoryCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getClassDescriptor()
*/
+ @Override
public ClassDescriptor getClassDescriptor() throws InvalidClassFileFormatException {
return DescriptorFactory.createClassDescriptorFromResourceName(getResourceName());
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@@ -115,7 +118,7 @@ public class DirectoryCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
@@ -125,7 +128,7 @@ public class DirectoryCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/FilesystemCodeBaseLocator.java b/src/java/edu/umd/cs/findbugs/classfile/impl/FilesystemCodeBaseLocator.java
index fb922b3..0672678 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/FilesystemCodeBaseLocator.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/FilesystemCodeBaseLocator.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.classfile.ICodeBaseLocator;
/**
* Codebase locator for files and directories in the filesystem.
- *
+ *
* @author David Hovemeyer
*/
public class FilesystemCodeBaseLocator implements ICodeBaseLocator {
@@ -52,11 +52,12 @@ public class FilesystemCodeBaseLocator implements ICodeBaseLocator {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBaseLocator#createRelativeCodeBaseLocator
* (java.lang.String)
*/
+ @Override
public ICodeBaseLocator createRelativeCodeBaseLocator(String relativePath) {
File path = new File(pathName);
if (!path.isDirectory()) {
@@ -68,16 +69,17 @@ public class FilesystemCodeBaseLocator implements ICodeBaseLocator {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseLocator#openCodeBase()
*/
+ @Override
public ICodeBase openCodeBase() throws IOException {
return ClassFactory.createFilesystemCodeBase(this);
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
@@ -87,7 +89,7 @@ public class FilesystemCodeBaseLocator implements ICodeBaseLocator {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@@ -101,7 +103,7 @@ public class FilesystemCodeBaseLocator implements ICodeBaseLocator {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/NestedZipFileCodeBase.java b/src/java/edu/umd/cs/findbugs/classfile/impl/NestedZipFileCodeBase.java
index 31950cd..6d41221 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/NestedZipFileCodeBase.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/NestedZipFileCodeBase.java
@@ -38,13 +38,13 @@ import edu.umd.cs.findbugs.io.IO;
* codebase. These are handled by extracting the nested zip/jar file to a
* temporary file, and delegating to an internal ZipFileCodeBase that reads from
* the temporary file.
- *
+ *
* @author David Hovemeyer
*/
public class NestedZipFileCodeBase extends AbstractScannableCodeBase {
- private ICodeBase parentCodeBase;
+ private final ICodeBase parentCodeBase;
- private String resourceName;
+ private final String resourceName;
private File tempFile;
@@ -52,7 +52,7 @@ public class NestedZipFileCodeBase extends AbstractScannableCodeBase {
/**
* Constructor.
- *
+ *
* @param codeBaseLocator
* the codebase locator for this codebase
*/
@@ -67,7 +67,7 @@ public class NestedZipFileCodeBase extends AbstractScannableCodeBase {
// Create a temp file
this.tempFile = File.createTempFile("findbugs", ".zip");
tempFile.deleteOnExit(); // just in case we crash before the
- // codebase is closed
+ // codebase is closed
// Copy nested zipfile to the temporary file
// FIXME: potentially long blocking operation - should be
@@ -96,19 +96,21 @@ public class NestedZipFileCodeBase extends AbstractScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.IScannableCodeBase#iterator()
*/
+ @Override
public ICodeBaseIterator iterator() throws InterruptedException {
return new DelegatingCodeBaseIterator(this, delegateCodeBase);
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBase#lookupResource(java.lang.String)
*/
+ @Override
public ICodeBaseEntry lookupResource(String resourceName) {
ICodeBaseEntry delegateCodeBaseEntry = delegateCodeBase.lookupResource(resourceName);
if (delegateCodeBaseEntry == null) {
@@ -119,18 +121,20 @@ public class NestedZipFileCodeBase extends AbstractScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#getPathName()
*/
+ @Override
public String getPathName() {
return null;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#close()
*/
+ @Override
public void close() {
delegateCodeBase.close();
if (!tempFile.delete()) {
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/NestedZipFileCodeBaseLocator.java b/src/java/edu/umd/cs/findbugs/classfile/impl/NestedZipFileCodeBaseLocator.java
index 5dd8141..b95199b 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/NestedZipFileCodeBaseLocator.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/NestedZipFileCodeBaseLocator.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.classfile.ResourceNotFoundException;
/**
* Codebase locator for a zip/jar archive nested inside a parent codebase.
- *
+ *
* @author David Hovemeyer
*/
public class NestedZipFileCodeBaseLocator implements ICodeBaseLocator {
@@ -56,11 +56,12 @@ public class NestedZipFileCodeBaseLocator implements ICodeBaseLocator {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBaseLocator#createRelativeCodeBaseLocator
* (java.lang.String)
*/
+ @Override
public ICodeBaseLocator createRelativeCodeBaseLocator(String relativePath) {
// The relative path indicates another codebase (archive) in the same
// parent codebase
@@ -69,16 +70,17 @@ public class NestedZipFileCodeBaseLocator implements ICodeBaseLocator {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseLocator#openCodeBase()
*/
+ @Override
public ICodeBase openCodeBase() throws ResourceNotFoundException, IOException {
return ClassFactory.createNestedZipFileCodeBase(this);
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
@@ -88,7 +90,7 @@ public class NestedZipFileCodeBaseLocator implements ICodeBaseLocator {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@@ -102,7 +104,7 @@ public class NestedZipFileCodeBaseLocator implements ICodeBaseLocator {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/SingleFileCodeBase.java b/src/java/edu/umd/cs/findbugs/classfile/impl/SingleFileCodeBase.java
index fe291be..e3a69e5 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/SingleFileCodeBase.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/SingleFileCodeBase.java
@@ -43,14 +43,14 @@ import edu.umd.cs.findbugs.io.IO;
/**
* Implementation of ICodeBase for a single classfile.
- *
+ *
* @author David Hovemeyer
*/
public class SingleFileCodeBase implements IScannableCodeBase {
- private ICodeBaseLocator codeBaseLocator;
+ private final ICodeBaseLocator codeBaseLocator;
- private String fileName;
+ private final String fileName;
private boolean isAppCodeBase;
@@ -75,46 +75,51 @@ public class SingleFileCodeBase implements IScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#getCodeBaseLocator()
*/
+ @Override
public ICodeBaseLocator getCodeBaseLocator() {
return codeBaseLocator;
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.IScannableCodeBase#containsSourceFiles()
*/
+ @Override
public boolean containsSourceFiles() throws InterruptedException {
return false;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.IScannableCodeBase#iterator()
*/
+ @Override
public ICodeBaseIterator iterator() throws InterruptedException {
return new ICodeBaseIterator() {
boolean done = false;
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseIterator#hasNext()
*/
+ @Override
public boolean hasNext() throws InterruptedException {
return !done;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseIterator#next()
*/
+ @Override
public ICodeBaseEntry next() throws InterruptedException {
if (done) {
throw new NoSuchElementException();
@@ -127,10 +132,11 @@ public class SingleFileCodeBase implements IScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBase#lookupResource(java.lang.String)
*/
+ @Override
public ICodeBaseEntry lookupResource(String resourceName) {
if (!resourceName.equals(getResourceName())) {
return null;
@@ -141,46 +147,51 @@ public class SingleFileCodeBase implements IScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBase#setApplicationCodeBase(boolean)
*/
+ @Override
public void setApplicationCodeBase(boolean isAppCodeBase) {
this.isAppCodeBase = isAppCodeBase;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#isApplicationCodeBase()
*/
+ @Override
public boolean isApplicationCodeBase() {
return isAppCodeBase;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#setHowDiscovered(int)
*/
+ @Override
public void setHowDiscovered(ICodeBase.Discovered howDiscovered) {
this.howDiscovered = howDiscovered;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#getHowDiscovered()
*/
+ @Override
public ICodeBase.Discovered getHowDiscovered() {
return howDiscovered;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#setLastModifiedTime(long)
*/
+ @Override
public void setLastModifiedTime(long lastModifiedTime) {
if (lastModifiedTime > 0 && FindBugs.validTimestamp(lastModifiedTime)) {
this.lastModifiedTime = lastModifiedTime;
@@ -189,18 +200,20 @@ public class SingleFileCodeBase implements IScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#getLastModifiedTime()
*/
+ @Override
public long getLastModifiedTime() {
return lastModifiedTime;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#getPathName()
*/
+ @Override
public String getPathName() {
return fileName;
}
@@ -211,9 +224,10 @@ public class SingleFileCodeBase implements IScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#close()
*/
+ @Override
public void close() {
// Nothing to do
}
@@ -221,7 +235,7 @@ public class SingleFileCodeBase implements IScannableCodeBase {
/**
* Get the resource name of the single file. We have to open the file and
* parse the constant pool in order to find this out.
- *
+ *
* @return the resource name (e.g., "java/lang/String.class" if the class is
* java.lang.String)
*/
@@ -268,7 +282,7 @@ public class SingleFileCodeBase implements IScannableCodeBase {
/**
* Return the number of bytes in the file.
- *
+ *
* @return the number of bytes in the file, or -1 if the file's length can't
* be determined
*/
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/SingleFileCodeBaseEntry.java b/src/java/edu/umd/cs/findbugs/classfile/impl/SingleFileCodeBaseEntry.java
index 67b0611..fd6f59b 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/SingleFileCodeBaseEntry.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/SingleFileCodeBaseEntry.java
@@ -11,7 +11,7 @@ import edu.umd.cs.findbugs.classfile.ResourceNotFoundException;
/**
* Codebase entry for a single-file codebase.
- *
+ *
* @author David Hovemeyer
*/
public class SingleFileCodeBaseEntry implements ICodeBaseEntry {
@@ -21,7 +21,7 @@ public class SingleFileCodeBaseEntry implements ICodeBaseEntry {
/**
* Constructor.
- *
+ *
* @param codeBase
* parent codebase
*/
@@ -31,65 +31,72 @@ public class SingleFileCodeBaseEntry implements ICodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getNumBytes()
*/
+ @Override
public int getNumBytes() {
return codeBase.getNumBytes();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getResourceName()
*/
+ @Override
public String getResourceName() {
- if (overriddenResourceName != null)
+ if (overriddenResourceName != null) {
return overriddenResourceName;
+ }
return codeBase.getResourceName();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#openResource()
*/
+ @Override
public InputStream openResource() throws IOException {
return codeBase.openFile();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getCodeBase()
*/
+ @Override
public ICodeBase getCodeBase() {
return codeBase;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getClassDescriptor()
*/
+ @Override
public ClassDescriptor getClassDescriptor() throws ResourceNotFoundException, InvalidClassFileFormatException {
return codeBase.getClassDescriptor();
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBaseEntry#overrideResourceName(java
* .lang.String)
*/
+ @Override
public void overrideResourceName(String resourceName) {
overriddenResourceName = resourceName;
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@@ -103,7 +110,7 @@ public class SingleFileCodeBaseEntry implements ICodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
@@ -113,7 +120,7 @@ public class SingleFileCodeBaseEntry implements ICodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/ZipCodeBaseFactory.java b/src/java/edu/umd/cs/findbugs/classfile/impl/ZipCodeBaseFactory.java
index 9d7d6ee..cd8c7a6 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/ZipCodeBaseFactory.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/ZipCodeBaseFactory.java
@@ -38,14 +38,14 @@ public class ZipCodeBaseFactory {
try {
return new ZipFileCodeBase(codeBaseLocator, file);
} catch (ZipException e) {
- // May be too many zip entries
- return new ZipInputStreamCodeBase(codeBaseLocator, file);
+ // May be too many zip entries
+ return new ZipInputStreamCodeBase(codeBaseLocator, file);
} finally {
profiler.end(ZipCodeBaseFactory.class);
}
}
-
+
}
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/ZipFileCodeBase.java b/src/java/edu/umd/cs/findbugs/classfile/impl/ZipFileCodeBase.java
index a2981e5..e4bf6f1 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/ZipFileCodeBase.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/ZipFileCodeBase.java
@@ -58,44 +58,42 @@ public class ZipFileCodeBase extends AbstractScannableCodeBase {
} catch (IOException e) {
if (!file.exists()) {
File parent = file.getParentFile();
- if (!(parent.exists() && parent.isDirectory() && parent.canRead()))
+ if (!(parent.exists() && parent.isDirectory() && parent.canRead())) {
throw new IOException("Can't read directory containing zip file: " + file);
+ }
throw new IOException("Zip file doesn't exist: " + file);
}
- if (!file.canRead())
+ if (!file.canRead()) {
throw new IOException("Can't read file zip file: " + file);
- if (!file.isFile())
+ }
+ if (!file.isFile()) {
throw new IOException("Zip file isn't a normal file: " + file);
- if (file.length() == 0)
+ }
+ if (file.length() == 0) {
throw new IOException("Zip file is empty: " + file);
+ }
if (!(e instanceof ZipException)) {
IOException ioException = new IOException("Error opening zip file " + file + " of " + file.length() + " bytes");
ioException.initCause(e);
throw ioException;
}
- DataInputStream in = new DataInputStream(new FileInputStream(file));
int magicBytes;
- try {
+ try (DataInputStream in = new DataInputStream(new FileInputStream(file))){
magicBytes = in.readInt();
- in.close();
} catch (IOException e3) {
throw new IOException(String.format("Unable read first 4 bytes of zip file %s of %d bytes", file, file.length()));
}
- if (magicBytes != 0x504b0304)
+ if (magicBytes != 0x504b0304) {
throw new IOException(String.format("Wrong magic bytes of %x for zip file %s of %d bytes", magicBytes, file,
file.length()));
+ }
ZipException e2 = new ZipException("Error opening zip file " + file + " of " + file.length() + " bytes");
e2.initCause(e);
throw e2;
}
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.ICodeBase#lookupResource(java.lang.String)
- */
+ @Override
public ICodeBaseEntry lookupResource(String resourceName) {
// Translate resource name, in case a resource name
// has been overridden and the resource is being accessed
@@ -115,22 +113,20 @@ public class ZipFileCodeBase extends AbstractScannableCodeBase {
}
}
+ @Override
public ICodeBaseIterator iterator() {
final Enumeration<? extends ZipEntry> zipEntryEnumerator = zipFile.entries();
return new ICodeBaseIterator() {
ZipFileCodeBaseEntry nextEntry;
+ @Override
public boolean hasNext() {
scanForNextEntry();
return nextEntry != null;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.classfile.ICodeBaseIterator#next()
- */
+ @Override
public ICodeBaseEntry next() throws InterruptedException {
scanForNextEntry();
if (nextEntry == null) {
@@ -156,24 +152,15 @@ public class ZipFileCodeBase extends AbstractScannableCodeBase {
}
}
}
-
};
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.classfile.ICodeBase#getPathName()
- */
+ @Override
public String getPathName() {
return zipFile.getName();
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.classfile.ICodeBase#close()
- */
+ @Override
public void close() {
try {
zipFile.close();
@@ -182,11 +169,6 @@ public class ZipFileCodeBase extends AbstractScannableCodeBase {
}
}
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#toString()
- */
@Override
public String toString() {
return zipFile.getName();
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/ZipFileCodeBaseEntry.java b/src/java/edu/umd/cs/findbugs/classfile/impl/ZipFileCodeBaseEntry.java
index 50d6bf1..fa64003 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/ZipFileCodeBaseEntry.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/ZipFileCodeBaseEntry.java
@@ -28,7 +28,7 @@ import edu.umd.cs.findbugs.classfile.DescriptorFactory;
/**
* Implementation of ICodeBaseEntry for resources in zipfile codebases.
- *
+ *
* @author David Hovemeyer
*/
public class ZipFileCodeBaseEntry extends AbstractScannableCodeBaseEntry {
@@ -43,25 +43,27 @@ public class ZipFileCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getNumBytes()
*/
+ @Override
public int getNumBytes() {
return (int) zipEntry.getSize();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#openResource()
*/
+ @Override
public InputStream openResource() throws IOException {
return codeBase.zipFile.getInputStream(zipEntry);
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.impl.AbstractScannableCodeBaseEntry#getCodeBase
* ()
@@ -73,7 +75,7 @@ public class ZipFileCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.impl.AbstractScannableCodeBaseEntry#
* getRealResourceName()
*/
@@ -84,16 +86,17 @@ public class ZipFileCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getClassDescriptor()
*/
+ @Override
public ClassDescriptor getClassDescriptor() {
return DescriptorFactory.createClassDescriptorFromResourceName(getResourceName());
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@@ -107,7 +110,7 @@ public class ZipFileCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
@@ -117,7 +120,7 @@ public class ZipFileCodeBaseEntry extends AbstractScannableCodeBaseEntry {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/ZipInputStreamCodeBase.java b/src/java/edu/umd/cs/findbugs/classfile/impl/ZipInputStreamCodeBase.java
index 8f9e4e4..5292a00 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/ZipInputStreamCodeBase.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/ZipInputStreamCodeBase.java
@@ -36,7 +36,7 @@ import edu.umd.cs.findbugs.util.MapCache;
/**
* Implementation of ICodeBase to read from a zip file or jar file.
- *
+ *
* @author David Hovemeyer
*/
public class ZipInputStreamCodeBase extends AbstractScannableCodeBase {
@@ -50,7 +50,7 @@ public class ZipInputStreamCodeBase extends AbstractScannableCodeBase {
/**
* Constructor.
- *
+ *
* @param codeBaseLocator
* the codebase locator for this codebase
* @param file
@@ -73,9 +73,9 @@ public class ZipInputStreamCodeBase extends AbstractScannableCodeBase {
while ((ze = zis.getNextEntry()) != null) {
String name = ze.getName();
if (!ze.isDirectory()
- && (name.equals("META-INF/MANIFEST.MF") || name.endsWith(".class") || Archive.isArchiveFileName(name))) {
+ && ("META-INF/MANIFEST.MF".equals(name) || name.endsWith(".class") || Archive.isArchiveFileName(name))) {
entries.add(name);
- if (name.equals("META-INF/MANIFEST.MF")) {
+ if ("META-INF/MANIFEST.MF".equals(name)) {
map.put(name, build(zis, ze));
}
}
@@ -93,10 +93,11 @@ public class ZipInputStreamCodeBase extends AbstractScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.ICodeBase#lookupResource(java.lang.String)
*/
+ @Override
public ICodeBaseEntry lookupResource(String resourceName) {
// Translate resource name, in case a resource name
@@ -182,9 +183,10 @@ public class ZipInputStreamCodeBase extends AbstractScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseIterator#hasNext()
*/
+ @Override
public boolean hasNext() throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
@@ -195,9 +197,10 @@ public class ZipInputStreamCodeBase extends AbstractScannableCodeBase {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseIterator#next()
*/
+ @Override
public ICodeBaseEntry next() throws InterruptedException {
try {
if (Thread.interrupted()) {
@@ -214,31 +217,34 @@ public class ZipInputStreamCodeBase extends AbstractScannableCodeBase {
}
+ @Override
public ICodeBaseIterator iterator() {
return new MyIterator();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#getPathName()
*/
+ @Override
public String getPathName() {
return file.getName();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBase#close()
*/
+ @Override
public void close() {
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/classfile/impl/ZipInputStreamCodeBaseEntry.java b/src/java/edu/umd/cs/findbugs/classfile/impl/ZipInputStreamCodeBaseEntry.java
index c070671..9ab3c47 100644
--- a/src/java/edu/umd/cs/findbugs/classfile/impl/ZipInputStreamCodeBaseEntry.java
+++ b/src/java/edu/umd/cs/findbugs/classfile/impl/ZipInputStreamCodeBaseEntry.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.classfile.DescriptorFactory;
/**
* Implementation of ICodeBaseEntry for resources in zipfile codebases.
- *
+ *
* @author David Hovemeyer
*/
public class ZipInputStreamCodeBaseEntry extends AbstractScannableCodeBaseEntry {
@@ -47,18 +47,20 @@ public class ZipInputStreamCodeBaseEntry extends AbstractScannableCodeBaseEntry
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getNumBytes()
*/
+ @Override
public int getNumBytes() {
return (int) zipEntry.getSize();
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#openResource()
*/
+ @Override
public InputStream openResource() throws IOException {
return new ByteArrayInputStream(bytes);
}
@@ -69,7 +71,7 @@ public class ZipInputStreamCodeBaseEntry extends AbstractScannableCodeBaseEntry
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.classfile.impl.AbstractScannableCodeBaseEntry#getCodeBase
* ()
@@ -81,7 +83,7 @@ public class ZipInputStreamCodeBaseEntry extends AbstractScannableCodeBaseEntry
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.impl.AbstractScannableCodeBaseEntry#
* getRealResourceName()
*/
@@ -92,16 +94,17 @@ public class ZipInputStreamCodeBaseEntry extends AbstractScannableCodeBaseEntry
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.classfile.ICodeBaseEntry#getClassDescriptor()
*/
+ @Override
public ClassDescriptor getClassDescriptor() {
return DescriptorFactory.createClassDescriptorFromResourceName(getResourceName());
}
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@@ -115,7 +118,7 @@ public class ZipInputStreamCodeBaseEntry extends AbstractScannableCodeBaseEntry
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#hashCode()
*/
@Override
@@ -125,7 +128,7 @@ public class ZipInputStreamCodeBaseEntry extends AbstractScannableCodeBaseEntry
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/cloud/AbstractCloud.java b/src/java/edu/umd/cs/findbugs/cloud/AbstractCloud.java
index 4c2fe5f..a05c30c 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/AbstractCloud.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/AbstractCloud.java
@@ -83,7 +83,7 @@ public abstract class AbstractCloud implements Cloud {
}
}
LEADERBOARD_BLACKLIST_PATTERN = p;
-
+
}
protected final CloudPlugin plugin;
@@ -122,9 +122,11 @@ public abstract class AbstractCloud implements Cloud {
}
boolean abstractCloudInitialized = false;
+ @Override
public boolean isInitialized() {
return abstractCloudInitialized;
}
+ @Override
@OverridingMethodsMustInvokeSuper
public boolean initialize() throws IOException {
abstractCloudInitialized = true;
@@ -152,69 +154,85 @@ public abstract class AbstractCloud implements Cloud {
this.sourceFileLinkFormatWithLine = sfwl;
} catch (RuntimeException e) {
LOGGER.log(Level.WARNING, "Could not compile pattern " + sp, e);
- if (THROW_EXCEPTION_IF_CANT_CONNECT)
+ if (THROW_EXCEPTION_IF_CANT_CONNECT) {
throw e;
+ }
}
}
return true;
}
+ @Override
public Mode getMode() {
return mode;
}
+ @Override
public void setMode(Mode mode) {
this.mode = mode;
}
+ @Override
public CloudPlugin getPlugin() {
return plugin;
}
+ @Override
public BugCollection getBugCollection() {
return bugCollection;
}
+ @Override
public boolean supportsBugLinks() {
return false;
}
+ @Override
public void setBugLinkOnCloudAndStoreIssueDetails(BugInstance b, String viewUrl, String linkType)
throws IOException, SignInCancelledException {
throw new UnsupportedOperationException();
}
+ @Override
public void updateBugStatusCache(BugInstance b, String status) {
throw new UnsupportedOperationException();
}
+ @Override
public boolean supportsClaims() {
return false;
}
+ @Override
public boolean supportsCloudReports() {
return true;
}
+ @Override
public String claimedBy(BugInstance b) {
throw new UnsupportedOperationException();
}
+ @Override
public boolean claim(BugInstance b) {
throw new UnsupportedOperationException();
}
+ @Override
public URL getBugLink(BugInstance b) {
throw new UnsupportedOperationException();
}
+ @Override
public String getBugLinkType(BugInstance instance) {
return null;
}
+ @Override
public URL fileBug(BugInstance bug) {
throw new UnsupportedOperationException();
}
+ @Override
public BugFilingStatus getBugLinkStatus(BugInstance b) {
throw new UnsupportedOperationException();
}
@@ -232,33 +250,41 @@ public abstract class AbstractCloud implements Cloud {
}
public boolean hasVoted(BugInstance bug) {
- for (BugDesignation bd : getLatestDesignationFromEachUser(bug))
- if (getUser().equals(bd.getUser()))
+ for (BugDesignation bd : getLatestDesignationFromEachUser(bug)) {
+ if (getUser().equals(bd.getUser())) {
return true;
+ }
+ }
return false;
}
public String notInCloudMsg(BugInstance b) {
-
- if (!!isOnlineCloud())
+
+ if (!!isOnlineCloud()) {
return "off line cloud";
- if (getSigninState().canDownload())
+ }
+ if (getSigninState().canDownload()) {
return "disconnected from cloud";
- if (!issueDataDownloaded)
+ }
+ if (!issueDataDownloaded) {
return "Waiting for issue data...";
+ }
return "Issue not recorded in cloud";
-
+
}
+ @Override
public String getCloudReport(BugInstance b) {
return getSelectiveCloudReport(b, Collections.<String>emptySet());
}
+ @Override
public String getCloudReportWithoutMe(BugInstance b) {
String user = getUser();
Set<String> usersToExclude = user == null ? Collections.<String>emptySet() : Collections.singleton(user);
return getSelectiveCloudReport(b, usersToExclude);
}
+ @Override
public void bugsPopulated() {
issueDataDownloaded = false;
}
@@ -281,8 +307,9 @@ public abstract class AbstractCloud implements Cloud {
if (bugLinkStatus != null && bugLinkStatus.bugIsFiled()) {
builder.append("\nBug status is ").append(getBugStatus(b));
- if (getBugIsUnassigned(b))
+ if (getBugIsUnassigned(b)) {
builder.append("\nBug is unassigned");
+ }
builder.append("\n\n");
}
@@ -308,53 +335,68 @@ public abstract class AbstractCloud implements Cloud {
return false;
}
+ @Override
public String getBugStatus(BugInstance b) {
return null;
}
protected abstract Iterable<BugDesignation> getLatestDesignationFromEachUser(BugInstance bd);
+ @Override
public Date getUserDate(BugInstance b) {
return new Date(getUserTimestamp(b));
}
+ @Override
public void addListener(CloudListener listener) {
- if (listener == null)
+ if (listener == null) {
throw new NullPointerException();
- if (!listeners.contains(listener))
+ }
+ if (!listeners.contains(listener)) {
listeners.add(listener);
+ }
}
+ @Override
public void removeListener(CloudListener listener) {
listeners.remove(listener);
}
+ @Override
public void addStatusListener(CloudStatusListener listener) {
- if (listener == null)
+ if (listener == null) {
throw new NullPointerException();
- if (!statusListeners.contains(listener))
+ }
+ if (!statusListeners.contains(listener)) {
statusListeners.add(listener);
+ }
}
+ @Override
public void removeStatusListener(CloudStatusListener listener) {
statusListeners.remove(listener);
}
+ @Override
public String getStatusMsg() {
return statusMsg;
}
+ @Override
public void shutdown() {
}
+ @Override
public boolean getIWillFix(BugInstance b) {
return getUserDesignation(b) == UserDesignation.I_WILL_FIX;
}
+ @Override
public UserDesignation getConsensusDesignation(BugInstance b) {
- if (b == null)
+ if (b == null) {
throw new NullPointerException("null bug instance");
+ }
Multiset<UserDesignation> designations = new Multiset<UserDesignation>();
int count = 0;
int totalCount = 0;
@@ -363,10 +405,11 @@ public abstract class AbstractCloud implements Cloud {
int notAProblem = 0;
for (BugDesignation designation : getLatestDesignationFromEachUser(b)) {
UserDesignation d = UserDesignation.valueOf(designation.getDesignationKey());
- if (d == UserDesignation.I_WILL_FIX)
+ if (d == UserDesignation.I_WILL_FIX) {
d = UserDesignation.MUST_FIX;
- else if (d == UserDesignation.UNCLASSIFIED)
+ } else if (d == UserDesignation.UNCLASSIFIED) {
continue;
+ }
switch (d) {
case I_WILL_FIX:
case MUST_FIX:
@@ -379,16 +422,20 @@ public abstract class AbstractCloud implements Cloud {
case OBSOLETE_CODE:
notAProblem++;
break;
+ default:
+ break;
}
designations.add(d);
totalCount++;
- if (d.nonVoting())
+ if (d.nonVoting()) {
continue;
+ }
count++;
total += d.score();
}
- if (totalCount == 0)
+ if (totalCount == 0) {
return UserDesignation.UNCLASSIFIED;
+ }
UserDesignation mostCommonVotingDesignation = null;
UserDesignation mostCommonDesignation = null;
@@ -396,40 +443,48 @@ public abstract class AbstractCloud implements Cloud {
UserDesignation d = e.getKey();
if (mostCommonVotingDesignation == null && !d.nonVoting()) {
mostCommonVotingDesignation = d;
- if (e.getValue() > count / 2)
+ if (e.getValue() > count / 2) {
return d;
+ }
}
if (mostCommonDesignation == null && d != UserDesignation.UNCLASSIFIED) {
mostCommonDesignation = d;
- if (e.getValue() > count / 2)
+ if (e.getValue() > count / 2) {
return d;
+ }
}
}
double score = total / count;
- if (score >= UserDesignation.SHOULD_FIX.score() || isAProblem > notAProblem)
+ if (score >= UserDesignation.SHOULD_FIX.score() || isAProblem > notAProblem) {
return UserDesignation.SHOULD_FIX;
- if (score <= UserDesignation.NOT_A_BUG.score())
+ }
+ if (score <= UserDesignation.NOT_A_BUG.score()) {
return UserDesignation.NOT_A_BUG;
- if (score <= UserDesignation.MOSTLY_HARMLESS.score() || notAProblem > isAProblem)
+ }
+ if (score <= UserDesignation.MOSTLY_HARMLESS.score() || notAProblem > isAProblem) {
return UserDesignation.MOSTLY_HARMLESS;
+ }
return UserDesignation.NEEDS_STUDY;
}
+ @Override
public boolean overallClassificationIsNotAProblem(BugInstance b) {
UserDesignation consensusDesignation = getConsensusDesignation(b);
return consensusDesignation.notAProblem();
}
+ @Override
public double getClassificationScore(BugInstance b) {
int count = 0;
double total = 0.0;
for (BugDesignation designation : getLatestDesignationFromEachUser(b)) {
UserDesignation d = UserDesignation.valueOf(designation.getDesignationKey());
- if (d.nonVoting())
+ if (d.nonVoting()) {
continue;
+ }
count++;
total += d.score();
}
@@ -437,6 +492,7 @@ public abstract class AbstractCloud implements Cloud {
}
+ @Override
public double getClassificationVariance(BugInstance b) {
int count = 0;
@@ -444,8 +500,9 @@ public abstract class AbstractCloud implements Cloud {
double totalSquares = 0.0;
for (BugDesignation designation : getLatestDesignationFromEachUser(b)) {
UserDesignation d = UserDesignation.valueOf(designation.getDesignationKey());
- if (d.nonVoting())
+ if (d.nonVoting()) {
continue;
+ }
count++;
total += d.score();
totalSquares += d.score() * d.score();
@@ -455,18 +512,21 @@ public abstract class AbstractCloud implements Cloud {
}
+ @Override
public double getPortionObsoleteClassifications(BugInstance b) {
int count = 0;
double total = 0.0;
for (BugDesignation designation : getLatestDesignationFromEachUser(b)) {
count++;
UserDesignation d = UserDesignation.valueOf(designation.getDesignationKey());
- if (d == UserDesignation.OBSOLETE_CODE)
+ if (d == UserDesignation.OBSOLETE_CODE) {
total++;
+ }
}
return total / count;
}
+ @Override
public int getNumberReviewers(BugInstance b) {
int count = 0;
Iterable<BugDesignation> designations = getLatestDesignationFromEachUser(b);
@@ -477,6 +537,7 @@ public abstract class AbstractCloud implements Cloud {
return count;
}
+ @Override
@SuppressWarnings("boxing")
public void printCloudSummary(PrintWriter w, Iterable<BugInstance> bugs, String[] packagePrefixes) {
@@ -511,8 +572,9 @@ public abstract class AbstractCloud implements Cloud {
w.println("Code analyzed");
}
w.printf("%,7d packages%n%,7d classes%n", packageCount, classCount);
- if (ncss > 0)
+ if (ncss > 0) {
w.printf("%,7d thousands of lines of non-commenting source statements%n", (ncss + 999) / 1000);
+ }
w.println();
int count = 0;
for (BugInstance bd : bugs) {
@@ -520,23 +582,26 @@ public abstract class AbstractCloud implements Cloud {
count++;
HashSet<String> reviewers = new HashSet<String>();
String status = supportsBugLinks() && getBugLinkStatus(bd).bugIsFiled() ? getBugStatus(bd) : null;
- if (status != null)
+ if (status != null) {
bugStatus.add(status);
+ }
- for (BugDesignation d : getLatestDesignationFromEachUser(bd))
+ for (BugDesignation d : getLatestDesignationFromEachUser(bd)) {
if (reviewers.add(d.getUser())) {
evaluations.add(d.getUser());
designations.add(i18n.getUserDesignation(d.getDesignationKey()));
}
+ }
int numReviews = Math.min(reviewers.size(), issuesWithThisManyReviews.length - 1);
issuesWithThisManyReviews[numReviews]++;
}
- if (count == getBugCollection().getCollection().size())
+ if (count == getBugCollection().getCollection().size()) {
w.printf("Summary for %d issues%n%n", count);
- else
+ } else {
w.printf("Summary for %d issues that are in the current view%n%n", count);
+ }
if (evaluations.numKeys() == 0) {
w.println("No reviews found");
} else {
@@ -559,14 +624,16 @@ public abstract class AbstractCloud implements Cloud {
}
w.println();
w.println("Distribution of number of reviews");
- for (int i = 0; i < issuesWithThisManyReviews.length; i++)
+ for (int i = 0; i < issuesWithThisManyReviews.length; i++) {
if (issuesWithThisManyReviews[i] > 0) {
w.printf("%4d with %3d review", issuesWithThisManyReviews[i], i);
- if (i != 1)
+ if (i != 1) {
w.print("s");
+ }
w.println();
}
+ }
}
@SuppressWarnings("boxing")
@@ -584,19 +651,23 @@ public abstract class AbstractCloud implements Cloud {
previousScore = num;
}
String key = e.getKey();
- if (LEADERBOARD_BLACKLIST_PATTERN != null && LEADERBOARD_BLACKLIST_PATTERN.matcher(key).matches())
+ if (LEADERBOARD_BLACKLIST_PATTERN != null && LEADERBOARD_BLACKLIST_PATTERN.matcher(key).matches()) {
continue;
+ }
boolean shouldAlwaysPrint = key.equals(alwaysPrint);
- if (row <= maxRows || shouldAlwaysPrint)
+ if (row <= maxRows || shouldAlwaysPrint) {
w.printf(format, position, num, key);
+ }
- if (shouldAlwaysPrint)
+ if (shouldAlwaysPrint) {
foundAlwaysPrint = true;
+ }
row++;
if (row >= maxRows) {
- if (alwaysPrint == null)
+ if (alwaysPrint == null) {
break;
+ }
if (foundAlwaysPrint) {
w.printf("Total of %d %ss%n", evaluations.numKeys(), title);
break;
@@ -606,47 +677,59 @@ public abstract class AbstractCloud implements Cloud {
}
}
+ @Override
public boolean supportsCloudSummaries() {
return true;
}
+ @Override
public boolean canStoreUserAnnotation(BugInstance bugInstance) {
return true;
}
+ @Override
public double getClassificationDisagreement(BugInstance b) {
return 0;
}
+ @Override
public UserDesignation getUserDesignation(BugInstance b) {
BugDesignation bd = getPrimaryDesignation(b);
- if (bd == null)
+ if (bd == null) {
return UserDesignation.UNCLASSIFIED;
+ }
return UserDesignation.valueOf(bd.getDesignationKey());
}
+ @Override
public String getUserEvaluation(BugInstance b) {
BugDesignation bd = getPrimaryDesignation(b);
- if (bd == null)
+ if (bd == null) {
return "";
+ }
String result = bd.getAnnotationText();
- if (result == null)
+ if (result == null) {
return "";
+ }
return result;
}
+ @Override
public long getUserTimestamp(BugInstance b) {
BugDesignation bd = getPrimaryDesignation(b);
- if (bd == null)
+ if (bd == null) {
return Long.MAX_VALUE;
+ }
return bd.getTimestamp();
}
+ @Override
public long getFirstSeen(BugInstance b) {
return getLocalFirstSeen(b);
}
+ @Override
public void addDateSeen(BugInstance b, long when) {
throw new UnsupportedOperationException();
}
@@ -676,23 +759,26 @@ public abstract class AbstractCloud implements Cloud {
protected void fireIssueDataDownloadedEvent() {
issueDataDownloaded = true;
- for (CloudStatusListener statusListener : statusListeners)
+ for (CloudStatusListener statusListener : statusListeners) {
statusListener.handleIssueDataDownloadedEvent();
+ }
}
+ @Override
public SigninState getSigninState() {
return signinState;
}
- @SuppressWarnings({ "ThrowableInstanceNeverThrown" })
public void setSigninState(SigninState state) {
SigninState oldState = this.signinState;
- if (oldState == state)
+ if (oldState == state) {
return;
+ }
LOGGER.log(Level.FINER, "State " + oldState + " -> " + state, new Throwable("Change in login state at:"));
this.signinState = state;
- for (CloudStatusListener statusListener : statusListeners)
+ for (CloudStatusListener statusListener : statusListeners) {
statusListener.handleStateChange(oldState, state);
+ }
}
public BugInstance getBugByHash(String hash) {
@@ -724,14 +810,17 @@ public abstract class AbstractCloud implements Cloud {
listener.taskStarted(task);
}
task.setDefaultListener(new CloudTaskListener() {
+ @Override
public void taskStatusUpdated(String statusLine, double percentCompleted) {
setStatusMsg(name + "... " + statusLine);
}
+ @Override
public void taskFinished() {
setStatusMsg("");
}
+ @Override
public void taskFailed(String message) {
setStatusMsg(name + "... FAILED - " + message);
}
@@ -749,10 +838,11 @@ public abstract class AbstractCloud implements Cloud {
private static void printLeaderBoard(PrintWriter w, Multiset<String> evaluations, int maxRows, String alwaysPrint,
boolean listRank, String title) {
- if (listRank)
+ if (listRank) {
w.printf("%3s %4s %s%n", "rnk", "num", title);
- else
+ } else {
w.printf("%4s %s%n", "num", title);
+ }
printLeaderBoard2(w, evaluations, maxRows, alwaysPrint, listRank ? "%3d %4d %s%n" : "%2$4d %3$s%n", title);
}
@@ -760,14 +850,17 @@ public abstract class AbstractCloud implements Cloud {
return properties.getProperty("findbugs.cloud." + propertyName);
}
+ @Override
public boolean supportsSourceLinks() {
return sourceFileLinkPattern != null;
}
+ @Override
@SuppressWarnings("boxing")
public @CheckForNull URL getSourceLink(BugInstance b) {
- if (sourceFileLinkPattern == null)
+ if (sourceFileLinkPattern == null) {
return null;
+ }
SourceLineAnnotation src = b.getPrimarySourceLineAnnotation();
String fileName = src.getSourcePath();
@@ -775,23 +868,26 @@ public abstract class AbstractCloud implements Cloud {
int endLine = src.getEndLine();
java.util.regex.Matcher m = sourceFileLinkPattern.matcher(fileName);
boolean isMatch = m.matches();
- if (isMatch)
+ if (isMatch) {
try {
URL link;
- if (startLine > 0)
+ if (startLine > 0) {
link = new URL(String.format(sourceFileLinkFormatWithLine, m.group(1),
startLine, startLine - 10, endLine));
- else
+ } else {
link = new URL(String.format(sourceFileLinkFormat, m.group(1)));
+ }
return link;
} catch (Exception e) {
AnalysisContext.logError("Error generating source link for " + src, e);
}
+ }
return null;
}
+ @Override
public String getSourceLinkToolTip(BugInstance b) {
return sourceFileLinkToolTip;
}
@@ -803,6 +899,7 @@ public abstract class AbstractCloud implements Cloud {
* edu.umd.cs.findbugs.cloud.Cloud#getBugIsUnassigned(edu.umd.cs.findbugs
* .BugInstance)
*/
+ @Override
public boolean getBugIsUnassigned(BugInstance b) {
return true;
}
@@ -814,25 +911,31 @@ public abstract class AbstractCloud implements Cloud {
* edu.umd.cs.findbugs.cloud.Cloud#getWillNotBeFixed(edu.umd.cs.findbugs
* .BugInstance)
*/
+ @Override
public boolean getWillNotBeFixed(BugInstance b) {
return false;
}
+ @Override
public Set<String> getReviewers(BugInstance b) {
HashSet<String> result = new HashSet<String>();
- for (BugDesignation d : getLatestDesignationFromEachUser(b))
+ for (BugDesignation d : getLatestDesignationFromEachUser(b)) {
result.add(d.getUser());
+ }
return result;
}
+ @Override
public IGuiCallback getGuiCallback() {
return getBugCollection().getProject().getGuiCallback();
}
+ @Override
public String getCloudName() {
return getPlugin().getDescription();
}
-
+
+ @Override
public boolean communicationInitiated() {
return !isOnlineCloud();
}
@@ -840,14 +943,16 @@ public abstract class AbstractCloud implements Cloud {
public long getLocalFirstSeen(BugInstance b) {
long firstVersion = b.getFirstVersion();
AppVersion v = getBugCollection().getAppVersionFromSequenceNumber(firstVersion);
- if (v == null)
+ if (v == null) {
return getBugCollection().getTimestamp();
+ }
long firstSeen = v.getTimestamp();
if (b.hasXmlProps()) {
XmlProps props = b.getXmlProps();
Date propsFirstSeen = props.getFirstSeen();
- if (propsFirstSeen != null && firstSeen > propsFirstSeen.getTime())
+ if (propsFirstSeen != null && firstSeen > propsFirstSeen.getTime()) {
firstSeen = propsFirstSeen.getTime();
+ }
}
return firstSeen;
}
diff --git a/src/java/edu/umd/cs/findbugs/cloud/BugCollectionStorageCloud.java b/src/java/edu/umd/cs/findbugs/cloud/BugCollectionStorageCloud.java
index 635a455..0385a4a 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/BugCollectionStorageCloud.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/BugCollectionStorageCloud.java
@@ -57,25 +57,30 @@ public class BugCollectionStorageCloud extends AbstractCloud {
}
}
+ @Override
public void waitUntilIssueDataDownloaded() {
}
+ @Override
public void initiateCommunication() {
}
+ @Override
public boolean waitUntilNewIssuesUploaded(long timeout, TimeUnit unit) throws InterruptedException {
return true;
}
+ @Override
public boolean waitUntilIssueDataDownloaded(long timeout, TimeUnit unit) throws InterruptedException {
return true;
}
-
+
@Override
public Mode getMode() {
return Mode.COMMUNAL;
}
+ @Override
public String getUser() {
return null;
}
@@ -84,8 +89,9 @@ public class BugCollectionStorageCloud extends AbstractCloud {
@Override
public UserDesignation getUserDesignation(BugInstance b) {
BugDesignation bd = b.getUserDesignation();
- if (bd == null)
+ if (bd == null) {
return UserDesignation.UNCLASSIFIED;
+ }
return UserDesignation.valueOf(bd.getDesignationKey());
}
@@ -93,8 +99,9 @@ public class BugCollectionStorageCloud extends AbstractCloud {
@Override
public String getUserEvaluation(BugInstance b) {
BugDesignation bd = b.getUserDesignation();
- if (bd == null)
+ if (bd == null) {
return "";
+ }
return bd.getAnnotationText();
}
@@ -102,8 +109,9 @@ public class BugCollectionStorageCloud extends AbstractCloud {
@Override
public long getUserTimestamp(BugInstance b) {
BugDesignation bd = b.getUserDesignation();
- if (bd == null)
+ if (bd == null) {
return Long.MAX_VALUE;
+ }
return bd.getTimestamp();
}
@@ -117,31 +125,39 @@ public class BugCollectionStorageCloud extends AbstractCloud {
}
+ @Override
public void setSaveSignInInformation(boolean save) {
}
+ @Override
public boolean isSavingSignInInformationEnabled() {
return false;
}
+ @Override
public void signIn() {
}
+ @Override
public void signOut() {
}
+ @Override
public boolean availableForInitialization() {
return true;
}
+ @Override
public void storeUserAnnotation(BugInstance bugInstance) {
}
+ @Override
public void bugFiled(BugInstance b, Object bugLink) {
throw new UnsupportedOperationException();
}
+ @Override
@SuppressWarnings({"deprecation"})
public BugDesignation getPrimaryDesignation(BugInstance b) {
return b.getUserDesignation();
@@ -150,30 +166,36 @@ public class BugCollectionStorageCloud extends AbstractCloud {
@Override
protected Iterable<BugDesignation> getLatestDesignationFromEachUser(BugInstance bd) {
BugDesignation designation = getPrimaryDesignation(bd);
- if (designation == null)
+ if (designation == null) {
return Collections.emptySet();
+ }
return Collections.singleton(designation);
}
+ @Override
public Collection<String> getProjects(String className) {
return Collections.emptyList();
}
+ @Override
public boolean isInCloud(BugInstance b) {
return true;
}
+ @Override
public boolean isOnlineCloud() {
return false;
}
+ @Override
public void waitUntilNewIssuesUploaded() {
}
@Override
public void addDateSeen(BugInstance b, long when) {
- if (when > 0)
- b.getXmlProps().setFirstSeen(new Date(when));
+ if (when > 0) {
+ b.getXmlProps().setFirstSeen(new Date(when));
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/cloud/BugFilingCommentHelper.java b/src/java/edu/umd/cs/findbugs/cloud/BugFilingCommentHelper.java
index c26ffcd..630649d 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/BugFilingCommentHelper.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/BugFilingCommentHelper.java
@@ -77,7 +77,7 @@ public class BugFilingCommentHelper {
int firstLine = Integer.MAX_VALUE;
int lastLine = Integer.MIN_VALUE;
- for (BugAnnotation a : b.getAnnotations())
+ for (BugAnnotation a : b.getAnnotations()) {
if (a instanceof SourceLineAnnotation) {
SourceLineAnnotation s = (SourceLineAnnotation) a;
if (s.getClassName().equals(primaryClass.getClassName()) && s.getStartLine() > 0) {
@@ -87,6 +87,7 @@ public class BugFilingCommentHelper {
}
}
+ }
SourceLineAnnotation primarySource = primaryClass.getSourceLines();
if (primarySource.isSourceFileKnown() && firstLine >= 1 && firstLine <= lastLine && lastLine - firstLine < 50) {
@@ -100,13 +101,15 @@ public class BugFilingCommentHelper {
List<SourceLine> source = new ArrayList<SourceLine>();
while (lineNumber <= lastLine + 4) {
String txt = in.readLine();
- if (txt == null)
+ if (txt == null) {
break;
+ }
if (lineNumber >= firstLine - 4) {
String trimmed = txt.trim();
if (trimmed.length() == 0) {
- if (lineNumber > lastLine)
+ if (lineNumber > lastLine) {
break;
+ }
txt = trimmed;
}
@@ -115,14 +118,16 @@ public class BugFilingCommentHelper {
}
lineNumber++;
}
- if (commonWhiteSpace == null)
+ if (commonWhiteSpace == null) {
commonWhiteSpace = "";
+ }
out.println("\nRelevant source code:");
for (SourceLine s : source) {
- if (s.text.length() == 0)
+ if (s.text.length() == 0) {
out.printf("%5d: %n", s.line);
- else
+ } else {
out.printf("%5d: %s%n", s.line, s.text.substring(commonWhiteSpace.length()));
+ }
}
out.println();
@@ -147,10 +152,11 @@ public class BugFilingCommentHelper {
ClassAnnotation primaryClass = b.getPrimaryClass();
for (BugAnnotation a : b.getAnnotations()) {
- if (a == primaryClass)
+ if (a == primaryClass) {
out.println(a);
- else
+ } else {
out.println(" " + a.toString(primaryClass));
+ }
}
if (cloud.supportsSourceLinks()) {
URL link = cloud.getSourceLink(b);
@@ -192,13 +198,15 @@ public class BugFilingCommentHelper {
UserDesignation designation = cloud.getUserDesignation(b);
String result;
- if (designation != UserDesignation.UNCLASSIFIED)
+ if (designation != UserDesignation.UNCLASSIFIED) {
result = "Classified as: " + designation.toString() + "\n";
- else
+ } else {
result = "";
+ }
String eval = cloud.getUserEvaluation(b).trim();
- if (eval.length() > 0)
+ if (eval.length() > 0) {
result = result + eval + "\n";
+ }
return result;
}
@@ -210,14 +218,17 @@ public class BugFilingCommentHelper {
// ====================================
private String commonLeadingWhitespace(String soFar, String txt) {
- if (txt.length() == 0)
+ if (txt.length() == 0) {
return soFar;
- if (soFar == null)
+ }
+ if (soFar == null) {
return txt;
+ }
soFar = Util.commonPrefix(soFar, txt);
for (int i = 0; i < soFar.length(); i++) {
- if (!Character.isWhitespace(soFar.charAt(i)))
+ if (!Character.isWhitespace(soFar.charAt(i))) {
return soFar.substring(0, i);
+ }
}
return soFar;
}
diff --git a/src/java/edu/umd/cs/findbugs/cloud/Cloud.java b/src/java/edu/umd/cs/findbugs/cloud/Cloud.java
index d326a2b..3ad9780 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/Cloud.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/Cloud.java
@@ -95,7 +95,7 @@ public interface Cloud {
* Waits until all new issues have been uploaded
*/
public void waitUntilNewIssuesUploaded();
-
+
public boolean waitUntilNewIssuesUploaded(long timeout, TimeUnit unit)
throws InterruptedException;
@@ -221,7 +221,7 @@ public interface Cloud {
URL fileBug(BugInstance b);
void setBugLinkOnCloudAndStoreIssueDetails(BugInstance b, String viewUrl, String linkType) throws IOException,
- SignInCancelledException;
+ SignInCancelledException;
/** Updates the local cache of bug reporting status. Does not modify server code. */
void updateBugStatusCache(BugInstance b, String status);
@@ -436,9 +436,6 @@ public interface Cloud {
}
}
- /**
- * @return
- */
public boolean nonVoting() {
return this == UserDesignation.OBSOLETE_CODE || this == UserDesignation.NEEDS_STUDY
|| this == UserDesignation.UNCLASSIFIED;
diff --git a/src/java/edu/umd/cs/findbugs/cloud/CloudFactory.java b/src/java/edu/umd/cs/findbugs/cloud/CloudFactory.java
index e892434..2106030 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/CloudFactory.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/CloudFactory.java
@@ -67,25 +67,23 @@ public class CloudFactory {
Constructor<? extends Cloud> constructor = cloudClass.getConstructor(CloudPlugin.class, BugCollection.class,
Properties.class);
Cloud cloud = constructor.newInstance(plugin, bc, properties);
- if (DEBUG)
+ if (DEBUG) {
bc.getProject().getGuiCallback().showMessageDialog("constructed " + cloud.getClass().getName());
+ }
LOGGER.log(Level.FINE, "constructed cloud plugin " + plugin.getId());
- if (!cloud.availableForInitialization())
- handleInitializationException(bc, plugin,
+ if (!cloud.availableForInitialization()) {
+ handleInitializationException(bc, plugin,
new IllegalStateException(cloud.getClass().getName() + " cloud " + plugin.getId()+ " doesn't have information needed for initialization"));
+ }
return cloud;
} catch (InvocationTargetException e) {
- return handleInitializationException(bc, plugin, e.getCause());
+ return handleInitializationException(bc, plugin, e.getCause());
} catch (Exception e) {
return handleInitializationException(bc, plugin, e);
}
}
- /**
- * @param bc
- * @return
- */
public static CloudPlugin getCloudPlugin(BugCollection bc) {
CloudPlugin plugin = null;
Project project = bc.getProject();
@@ -93,8 +91,9 @@ public class CloudFactory {
String cloudId = project.getCloudId();
if (cloudId != null) {
plugin = DetectorFactoryCollection.instance().getRegisteredClouds().get(cloudId);
- if (plugin == null && FAIL_ON_CLOUD_ERROR)
+ if (plugin == null && FAIL_ON_CLOUD_ERROR) {
throw new IllegalArgumentException("Cannot find registered cloud for " + cloudId);
+ }
}
// is the desired plugin disabled for this project (and/or globally)? if so, skip it.
if (plugin != null) {
@@ -105,11 +104,12 @@ public class CloudFactory {
}
}
if (plugin == null) {
- if (DEFAULT_CLOUD != null)
+ if (DEFAULT_CLOUD != null) {
LOGGER.log(Level.FINE, "Trying default cloud " + DEFAULT_CLOUD);
+ }
cloudId = DEFAULT_CLOUD;
plugin = DetectorFactoryCollection.instance().getRegisteredClouds().get(cloudId);
- }
+ }
return plugin;
}
@@ -118,32 +118,38 @@ public class CloudFactory {
bc.getProject().getGuiCallback().showMessageDialog("failed " + e.getMessage() + e.getClass().getName());
}
LOGGER.log(Level.WARNING, "Could not load cloud plugin " + plugin, e);
- if (SystemProperties.getBoolean("findbugs.failIfUnableToConnectToCloud"))
+ if (SystemProperties.getBoolean("findbugs.failIfUnableToConnectToCloud")) {
System.exit(1);
+ }
return getPlainCloud(bc);
}
public static void initializeCloud(BugCollection bc, Cloud cloud) throws IOException {
IGuiCallback callback = bc.getProject().getGuiCallback();
- if (!cloud.availableForInitialization())
+ if (!cloud.availableForInitialization()) {
return;
+ }
- if (DEBUG)
+ if (DEBUG) {
callback.showMessageDialog("attempting to initialize " + cloud.getClass().getName());
+ }
- if (!cloud.initialize())
+ if (!cloud.initialize()) {
throw new IOException("Unable to connect to " + cloud.getCloudName());
+ }
- if (DEBUG)
+ if (DEBUG) {
callback.showMessageDialog("initialized " + cloud.getClass().getName());
+ }
}
public static @Nonnull Cloud getPlainCloud(BugCollection bc) {
DoNothingCloud cloud = new DoNothingCloud(bc);
- if (cloud.initialize())
+ if (cloud.initialize()) {
return cloud;
+ }
throw new IllegalStateException("Unable to initialize DoNothingCloud");
}
diff --git a/src/java/edu/umd/cs/findbugs/cloud/CloudPlugin.java b/src/java/edu/umd/cs/findbugs/cloud/CloudPlugin.java
index 707bb87..834043c 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/CloudPlugin.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/CloudPlugin.java
@@ -46,8 +46,8 @@ public class CloudPlugin {
final boolean hidden;
public CloudPlugin(String findbugsPluginId, String cloudid, ClassLoader classLoader, Class<? extends Cloud> cloudClass,
- Class<? extends NameLookup> usernameClass, boolean hidden, PropertyBundle properties, String description,
- String details) {
+ Class<? extends NameLookup> usernameClass, boolean hidden, PropertyBundle properties, String description,
+ String details) {
this.findbugsPluginId = findbugsPluginId;
this.cloudid = cloudid;
this.classLoader = classLoader;
@@ -99,7 +99,7 @@ public class CloudPlugin {
public String toString() {
return getDescription();
}
-
+
public boolean isOnline() {
return OnlineCloud.class.isAssignableFrom(cloudClass);
}
diff --git a/src/java/edu/umd/cs/findbugs/cloud/DoNothingCloud.java b/src/java/edu/umd/cs/findbugs/cloud/DoNothingCloud.java
index 76876e2..0a65658 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/DoNothingCloud.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/DoNothingCloud.java
@@ -1,351 +1,427 @@
-package edu.umd.cs.findbugs.cloud;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.URL;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Properties;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.CheckForNull;
-
-import edu.umd.cs.findbugs.AppVersion;
-import edu.umd.cs.findbugs.BugCollection;
-import edu.umd.cs.findbugs.BugDesignation;
-import edu.umd.cs.findbugs.BugInstance;
-import edu.umd.cs.findbugs.IGuiCallback;
-import edu.umd.cs.findbugs.PropertyBundle;
-import edu.umd.cs.findbugs.cloud.username.NoNameLookup;
-
-/**
- * Doesn't do much. Relies on the {@link edu.umd.cs.findbugs.BugInstance.XmlProps}
- * read from the analysis XML file, if present.
- */
-public class DoNothingCloud implements Cloud {
- private CloudPlugin plugin;
- private BugCollection bugCollection;
-
- private static CloudPlugin getFallbackPlugin() {
- return new CloudPluginBuilder().setCloudid("edu.umd.cs.findbugs.cloud.doNothingCloud").setDescription("Do Nothing Cloud")
- .setDetails("No reviews will be stored.")
- .setClassLoader(BugCollectionStorageCloud.class.getClassLoader())
- .setCloudClass(BugCollectionStorageCloud.class)
- .setUsernameClass(NoNameLookup.class)
- .setProperties(new PropertyBundle())
- .setOnlineStorage(false)
- .createCloudPlugin();
- }
-
- /** Invoked via reflection */
- @SuppressWarnings({"UnusedDeclaration"})
- public DoNothingCloud(CloudPlugin plugin, BugCollection bc, Properties props) {
- this.plugin = plugin;
- this.bugCollection = bc;
- }
-
- public DoNothingCloud(BugCollection bc) {
- this(getFallbackPlugin(), bc, new Properties());
- }
-
- public CloudPlugin getPlugin() {
- return plugin;
- }
-
- public String getCloudName() {
- return "(no cloud selected)";
- }
-
- public BugCollection getBugCollection() {
- return bugCollection;
- }
-
- public IGuiCallback getGuiCallback() {
- return null;
- }
-
- public String getStatusMsg() {
- return null;
- }
-
- public void printCloudSummary(PrintWriter w, Iterable<BugInstance> bugs, String[] packagePrefixes) {
- }
-
- public void addListener(CloudListener listener) {
- }
-
- public void removeListener(CloudListener listener) {
- }
-
- public void addStatusListener(CloudStatusListener cloudStatusListener) {
- }
-
- public void removeStatusListener(CloudStatusListener cloudStatusListener) {
- }
-
- public boolean availableForInitialization() {
- return true;
- }
-
- public boolean initialize() {
- return true;
- }
-
- public void waitUntilNewIssuesUploaded() {
- }
-
- public void waitUntilIssueDataDownloaded() {
- }
-
- public boolean waitUntilNewIssuesUploaded(long timeout, TimeUnit unit) throws InterruptedException {
- return true;
- }
-
- public boolean waitUntilIssueDataDownloaded(long timeout, TimeUnit unit) throws InterruptedException {
- return true;
- }
- public void bugsPopulated() {
- }
-
- public void initiateCommunication() {
- }
-
- public void shutdown() {
- }
-
- public String getUser() {
- return null;
- }
-
- public SigninState getSigninState() {
- return SigninState.NO_SIGNIN_REQUIRED;
- }
-
- public void setSaveSignInInformation(boolean save) {
- }
-
- public boolean isSavingSignInInformationEnabled() {
- return false;
- }
-
- public void signIn() throws IOException {
- }
-
- public void signOut() {
- }
-
- public Mode getMode() {
- return null;
- }
-
- public void setMode(Mode m) {
- }
-
- public boolean supportsSourceLinks() {
- return false;
- }
-
- public boolean supportsBugLinks() {
- return false;
- }
-
- public boolean supportsCloudReports() {
- return false;
- }
-
- public boolean supportsClaims() {
- return false;
- }
-
- public boolean supportsCloudSummaries() {
- return false;
- }
-
- public Collection<String> getProjects(String className) {
- return null;
- }
-
- public boolean isInCloud(BugInstance b) {
- return b.getXmlProps().isInCloud();
- }
-
- public boolean isOnlineCloud() {
- return "true".equals(bugCollection.getXmlCloudDetails().get("online"));
- }
-
- public boolean getIWillFix(BugInstance b) {
- return false;
- }
-
- public String getSourceLinkToolTip(@CheckForNull BugInstance b) {
- return null;
- }
-
- public URL getSourceLink(BugInstance b) {
- return null;
- }
-
- public BugFilingStatus getBugLinkStatus(BugInstance b) {
- return null;
- }
-
- public String getBugStatus(BugInstance b) {
- return null;
- }
-
- public boolean getWillNotBeFixed(BugInstance b) {
- return false;
- }
-
- public boolean getBugIsUnassigned(BugInstance b) {
- return false;
- }
-
- public URL getBugLink(BugInstance b) {
- return null;
- }
-
- public String getBugLinkType(BugInstance instance) {
- return null;
- }
-
- public URL fileBug(BugInstance b) {
- throw new UnsupportedOperationException();
- }
-
- public void setBugLinkOnCloudAndStoreIssueDetails(BugInstance b, String viewUrl, String linkType)
- throws IOException, SignInCancelledException {
- throw new UnsupportedOperationException();
- }
-
- public void updateBugStatusCache(BugInstance b, String status) {
- }
-
- public void bugFiled(BugInstance b, @CheckForNull Object bugLink) {
- throw new UnsupportedOperationException();
- }
-
- public String getCloudReport(BugInstance b) {
- return "";
- }
-
- public String getCloudReportWithoutMe(BugInstance b) {
- return getCloudReport(b);
- }
-
- public String claimedBy(BugInstance b) {
- return null;
- }
-
- public boolean claim(BugInstance b) {
- throw new UnsupportedOperationException();
- }
-
- public long getUserTimestamp(BugInstance b) {
- return 0;
- }
-
- public Date getUserDate(BugInstance b) {
- return null;
- }
-
- public BugDesignation getPrimaryDesignation(BugInstance b) {
- return null;
- }
-
- public UserDesignation getUserDesignation(BugInstance b) {
- return null;
- }
-
- public String getUserEvaluation(BugInstance b) {
- return null;
- }
-
- public double getClassificationScore(BugInstance b) {
- return 0;
- }
-
- public double getClassificationVariance(BugInstance b) {
- return 0;
- }
-
- public double getClassificationDisagreement(BugInstance b) {
- return 0;
- }
-
- public double getPortionObsoleteClassifications(BugInstance b) {
- return 0;
- }
-
- public int getNumberReviewers(BugInstance b) {
- return b.getXmlProps().getReviewCount();
- }
-
- public Set<String> getReviewers(BugInstance b) {
- return Collections.emptySet();
- }
-
- public long getFirstSeen(BugInstance b) {
- long computed = getFirstSeenFromVersion(b);
- Date fromXml = b.getXmlProps().getFirstSeen();
- if (fromXml == null)
- return computed;
-
- long fromXmlTime = fromXml.getTime();
- if (computed == 0 && fromXmlTime > 0)
- return fromXmlTime;
- else if (fromXmlTime == 0 && computed > 0)
- return computed;
-
- return Math.min(fromXmlTime, computed);
- }
-
- public void addDateSeen(BugInstance b, long when) {
- if (when > 0)
- b.getXmlProps().setFirstSeen(new Date(when));
- }
-
- public long getFirstSeenFromVersion(BugInstance b) {
- long firstVersion = b.getFirstVersion();
- AppVersion v = getBugCollection().getAppVersionFromSequenceNumber(firstVersion);
- if (v == null)
- return getBugCollection().getTimestamp();
- return v.getTimestamp();
- }
-
- public UserDesignation getConsensusDesignation(BugInstance b) {
- String consensus = b.getXmlProps().getConsensus();
- if (consensus == null)
- return UserDesignation.UNCLASSIFIED;
- try {
- return UserDesignation.valueOf(consensus);
- } catch (IllegalArgumentException e) {
- return UserDesignation.UNCLASSIFIED;
- }
- }
-
- public boolean overallClassificationIsNotAProblem(BugInstance b) {
- UserDesignation consensusDesignation = getConsensusDesignation(b);
- return consensusDesignation != UserDesignation.UNCLASSIFIED && consensusDesignation.score() < 0;
- }
-
- public boolean canStoreUserAnnotation(BugInstance bugInstance) {
- return false;
- }
-
- public void storeUserAnnotation(BugInstance bugInstance) {
- throw new UnsupportedOperationException();
- }
-
- public boolean communicationInitiated() {
- return false;
- }
-
- public boolean isInitialized() {
- return true;
- }
-
-
-}
+package edu.umd.cs.findbugs.cloud;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.CheckForNull;
+
+import edu.umd.cs.findbugs.AppVersion;
+import edu.umd.cs.findbugs.BugCollection;
+import edu.umd.cs.findbugs.BugDesignation;
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.IGuiCallback;
+import edu.umd.cs.findbugs.PropertyBundle;
+import edu.umd.cs.findbugs.cloud.username.NoNameLookup;
+
+/**
+ * Doesn't do much. Relies on the {@link edu.umd.cs.findbugs.BugInstance.XmlProps}
+ * read from the analysis XML file, if present.
+ */
+public class DoNothingCloud implements Cloud {
+ private final CloudPlugin plugin;
+ private final BugCollection bugCollection;
+
+ private static CloudPlugin getFallbackPlugin() {
+ return new CloudPluginBuilder().setCloudid("edu.umd.cs.findbugs.cloud.doNothingCloud").setDescription("Do Nothing Cloud")
+ .setDetails("No reviews will be stored.")
+ .setClassLoader(BugCollectionStorageCloud.class.getClassLoader())
+ .setCloudClass(BugCollectionStorageCloud.class)
+ .setUsernameClass(NoNameLookup.class)
+ .setProperties(new PropertyBundle())
+ .setOnlineStorage(false)
+ .createCloudPlugin();
+ }
+
+ /** Invoked via reflection */
+ @SuppressWarnings({"UnusedDeclaration"})
+ public DoNothingCloud(CloudPlugin plugin, BugCollection bc, Properties props) {
+ this.plugin = plugin;
+ this.bugCollection = bc;
+ }
+
+ public DoNothingCloud(BugCollection bc) {
+ this(getFallbackPlugin(), bc, new Properties());
+ }
+
+ @Override
+ public CloudPlugin getPlugin() {
+ return plugin;
+ }
+
+ @Override
+ public String getCloudName() {
+ return "(no cloud selected)";
+ }
+
+ @Override
+ public BugCollection getBugCollection() {
+ return bugCollection;
+ }
+
+ @Override
+ public IGuiCallback getGuiCallback() {
+ return null;
+ }
+
+ @Override
+ public String getStatusMsg() {
+ return null;
+ }
+
+ @Override
+ public void printCloudSummary(PrintWriter w, Iterable<BugInstance> bugs, String[] packagePrefixes) {
+ }
+
+ @Override
+ public void addListener(CloudListener listener) {
+ }
+
+ @Override
+ public void removeListener(CloudListener listener) {
+ }
+
+ @Override
+ public void addStatusListener(CloudStatusListener cloudStatusListener) {
+ }
+
+ @Override
+ public void removeStatusListener(CloudStatusListener cloudStatusListener) {
+ }
+
+ @Override
+ public boolean availableForInitialization() {
+ return true;
+ }
+
+ @Override
+ public boolean initialize() {
+ return true;
+ }
+
+ @Override
+ public void waitUntilNewIssuesUploaded() {
+ }
+
+ @Override
+ public void waitUntilIssueDataDownloaded() {
+ }
+
+ @Override
+ public boolean waitUntilNewIssuesUploaded(long timeout, TimeUnit unit) throws InterruptedException {
+ return true;
+ }
+
+ @Override
+ public boolean waitUntilIssueDataDownloaded(long timeout, TimeUnit unit) throws InterruptedException {
+ return true;
+ }
+ @Override
+ public void bugsPopulated() {
+ }
+
+ @Override
+ public void initiateCommunication() {
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public String getUser() {
+ return null;
+ }
+
+ @Override
+ public SigninState getSigninState() {
+ return SigninState.NO_SIGNIN_REQUIRED;
+ }
+
+ @Override
+ public void setSaveSignInInformation(boolean save) {
+ }
+
+ @Override
+ public boolean isSavingSignInInformationEnabled() {
+ return false;
+ }
+
+ @Override
+ public void signIn() throws IOException {
+ }
+
+ @Override
+ public void signOut() {
+ }
+
+ @Override
+ public Mode getMode() {
+ return null;
+ }
+
+ @Override
+ public void setMode(Mode m) {
+ }
+
+ @Override
+ public boolean supportsSourceLinks() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsBugLinks() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsCloudReports() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsClaims() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsCloudSummaries() {
+ return false;
+ }
+
+ @Override
+ public Collection<String> getProjects(String className) {
+ return null;
+ }
+
+ @Override
+ public boolean isInCloud(BugInstance b) {
+ return b.getXmlProps().isInCloud();
+ }
+
+ @Override
+ public boolean isOnlineCloud() {
+ return "true".equals(bugCollection.getXmlCloudDetails().get("online"));
+ }
+
+ @Override
+ public boolean getIWillFix(BugInstance b) {
+ return false;
+ }
+
+ @Override
+ public String getSourceLinkToolTip(@CheckForNull BugInstance b) {
+ return null;
+ }
+
+ @Override
+ public URL getSourceLink(BugInstance b) {
+ return null;
+ }
+
+ @Override
+ public BugFilingStatus getBugLinkStatus(BugInstance b) {
+ return null;
+ }
+
+ @Override
+ public String getBugStatus(BugInstance b) {
+ return null;
+ }
+
+ @Override
+ public boolean getWillNotBeFixed(BugInstance b) {
+ return false;
+ }
+
+ @Override
+ public boolean getBugIsUnassigned(BugInstance b) {
+ return false;
+ }
+
+ @Override
+ public URL getBugLink(BugInstance b) {
+ return null;
+ }
+
+ @Override
+ public String getBugLinkType(BugInstance instance) {
+ return null;
+ }
+
+ @Override
+ public URL fileBug(BugInstance b) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setBugLinkOnCloudAndStoreIssueDetails(BugInstance b, String viewUrl, String linkType)
+ throws IOException, SignInCancelledException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void updateBugStatusCache(BugInstance b, String status) {
+ }
+
+ @Override
+ public void bugFiled(BugInstance b, @CheckForNull Object bugLink) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getCloudReport(BugInstance b) {
+ return "";
+ }
+
+ @Override
+ public String getCloudReportWithoutMe(BugInstance b) {
+ return getCloudReport(b);
+ }
+
+ @Override
+ public String claimedBy(BugInstance b) {
+ return null;
+ }
+
+ @Override
+ public boolean claim(BugInstance b) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getUserTimestamp(BugInstance b) {
+ return 0;
+ }
+
+ @Override
+ public Date getUserDate(BugInstance b) {
+ return null;
+ }
+
+ @Override
+ public BugDesignation getPrimaryDesignation(BugInstance b) {
+ return null;
+ }
+
+ @Override
+ public UserDesignation getUserDesignation(BugInstance b) {
+ return null;
+ }
+
+ @Override
+ public String getUserEvaluation(BugInstance b) {
+ return null;
+ }
+
+ @Override
+ public double getClassificationScore(BugInstance b) {
+ return 0;
+ }
+
+ @Override
+ public double getClassificationVariance(BugInstance b) {
+ return 0;
+ }
+
+ @Override
+ public double getClassificationDisagreement(BugInstance b) {
+ return 0;
+ }
+
+ @Override
+ public double getPortionObsoleteClassifications(BugInstance b) {
+ return 0;
+ }
+
+ @Override
+ public int getNumberReviewers(BugInstance b) {
+ return b.getXmlProps().getReviewCount();
+ }
+
+ @Override
+ public Set<String> getReviewers(BugInstance b) {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public long getFirstSeen(BugInstance b) {
+ long computed = getFirstSeenFromVersion(b);
+ Date fromXml = b.getXmlProps().getFirstSeen();
+ if (fromXml == null) {
+ return computed;
+ }
+
+ long fromXmlTime = fromXml.getTime();
+ if (computed == 0 && fromXmlTime > 0) {
+ return fromXmlTime;
+ } else if (fromXmlTime == 0 && computed > 0) {
+ return computed;
+ }
+
+ return Math.min(fromXmlTime, computed);
+ }
+
+ @Override
+ public void addDateSeen(BugInstance b, long when) {
+ if (when > 0) {
+ b.getXmlProps().setFirstSeen(new Date(when));
+ }
+ }
+
+ public long getFirstSeenFromVersion(BugInstance b) {
+ long firstVersion = b.getFirstVersion();
+ AppVersion v = getBugCollection().getAppVersionFromSequenceNumber(firstVersion);
+ if (v == null) {
+ return getBugCollection().getTimestamp();
+ }
+ return v.getTimestamp();
+ }
+
+ @Override
+ public UserDesignation getConsensusDesignation(BugInstance b) {
+ String consensus = b.getXmlProps().getConsensus();
+ if (consensus == null) {
+ return UserDesignation.UNCLASSIFIED;
+ }
+ try {
+ return UserDesignation.valueOf(consensus);
+ } catch (IllegalArgumentException e) {
+ return UserDesignation.UNCLASSIFIED;
+ }
+ }
+
+ @Override
+ public boolean overallClassificationIsNotAProblem(BugInstance b) {
+ UserDesignation consensusDesignation = getConsensusDesignation(b);
+ return consensusDesignation != UserDesignation.UNCLASSIFIED && consensusDesignation.score() < 0;
+ }
+
+ @Override
+ public boolean canStoreUserAnnotation(BugInstance bugInstance) {
+ return false;
+ }
+
+ @Override
+ public void storeUserAnnotation(BugInstance bugInstance) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean communicationInitiated() {
+ return false;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return true;
+ }
+
+
+}
diff --git a/src/java/edu/umd/cs/findbugs/cloud/MutableCloudTask.java b/src/java/edu/umd/cs/findbugs/cloud/MutableCloudTask.java
index ad5c48a..0af9c20 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/MutableCloudTask.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/MutableCloudTask.java
@@ -1,101 +1,108 @@
-package edu.umd.cs.findbugs.cloud;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-public class MutableCloudTask implements Cloud.CloudTask {
- private String name;
-
- private CopyOnWriteArrayList<Cloud.CloudTaskListener> listeners = new CopyOnWriteArrayList<Cloud.CloudTaskListener>();
-
- private String substatus = "";
-
- private double percentDone = 0;
-
- /** A listener used only if no other listeners are present. */
- private Cloud.CloudTaskListener defaultListener;
-
- private boolean finished = false;
-
- private boolean useDefaultListener = true;
-
- public MutableCloudTask(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public String getStatusLine() {
- return substatus;
- }
-
- public double getPercentCompleted() {
- return percentDone;
- }
-
- public void addListener(Cloud.CloudTaskListener listener) {
- listeners.addIfAbsent(listener);
- }
-
- public void removeListener(Cloud.CloudTaskListener listener) {
- listeners.remove(listener);
- }
-
- public boolean isFinished() {
- return finished;
- }
-
- public void setUseDefaultListener(boolean enabled) {
- this.useDefaultListener = enabled;
- }
-
- public void update(String substatus, double percentDone) {
- this.substatus = substatus;
- this.percentDone = percentDone;
- for (Cloud.CloudTaskListener listener : getListeners()) {
- listener.taskStatusUpdated(substatus, percentDone);
- }
- }
-
- public void finished() {
- finished = true;
- for (Cloud.CloudTaskListener listener : getListeners()) {
- listener.taskFinished();
- }
- clearListeners();
- }
-
- public void failed(String message) {
- finished = true;
- for (Cloud.CloudTaskListener listener : getListeners()) {
- listener.taskFailed(message);
- }
- clearListeners();
- }
-
- /** A listener used only if no other listeners are present. */
- public void setDefaultListener(Cloud.CloudTaskListener defaultListener) {
- this.defaultListener = defaultListener;
- }
-
- private List<Cloud.CloudTaskListener> getListeners() {
- List<Cloud.CloudTaskListener> myListeners = new ArrayList<Cloud.CloudTaskListener>(listeners);
- if (useDefaultListener && myListeners.isEmpty() && defaultListener != null) {
- myListeners.add(defaultListener);
- }
- return myListeners;
- }
-
- /** I think this is a good idea for garbage collection purposes -Keith */
- private void clearListeners() {
- listeners.clear();
- defaultListener = null;
- }
-
- public boolean isUsingDefaultListener() {
- return listeners.isEmpty();
- }
-}
+package edu.umd.cs.findbugs.cloud;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class MutableCloudTask implements Cloud.CloudTask {
+ private final String name;
+
+ private final CopyOnWriteArrayList<Cloud.CloudTaskListener> listeners = new CopyOnWriteArrayList<Cloud.CloudTaskListener>();
+
+ private String substatus = "";
+
+ private double percentDone = 0;
+
+ /** A listener used only if no other listeners are present. */
+ private Cloud.CloudTaskListener defaultListener;
+
+ private boolean finished = false;
+
+ private boolean useDefaultListener = true;
+
+ public MutableCloudTask(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getStatusLine() {
+ return substatus;
+ }
+
+ @Override
+ public double getPercentCompleted() {
+ return percentDone;
+ }
+
+ @Override
+ public void addListener(Cloud.CloudTaskListener listener) {
+ listeners.addIfAbsent(listener);
+ }
+
+ @Override
+ public void removeListener(Cloud.CloudTaskListener listener) {
+ listeners.remove(listener);
+ }
+
+ @Override
+ public boolean isFinished() {
+ return finished;
+ }
+
+ @Override
+ public void setUseDefaultListener(boolean enabled) {
+ this.useDefaultListener = enabled;
+ }
+
+ public void update(String substatus, double percentDone) {
+ this.substatus = substatus;
+ this.percentDone = percentDone;
+ for (Cloud.CloudTaskListener listener : getListeners()) {
+ listener.taskStatusUpdated(substatus, percentDone);
+ }
+ }
+
+ public void finished() {
+ finished = true;
+ for (Cloud.CloudTaskListener listener : getListeners()) {
+ listener.taskFinished();
+ }
+ clearListeners();
+ }
+
+ public void failed(String message) {
+ finished = true;
+ for (Cloud.CloudTaskListener listener : getListeners()) {
+ listener.taskFailed(message);
+ }
+ clearListeners();
+ }
+
+ /** A listener used only if no other listeners are present. */
+ public void setDefaultListener(Cloud.CloudTaskListener defaultListener) {
+ this.defaultListener = defaultListener;
+ }
+
+ private List<Cloud.CloudTaskListener> getListeners() {
+ List<Cloud.CloudTaskListener> myListeners = new ArrayList<Cloud.CloudTaskListener>(listeners);
+ if (useDefaultListener && myListeners.isEmpty() && defaultListener != null) {
+ myListeners.add(defaultListener);
+ }
+ return myListeners;
+ }
+
+ /** I think this is a good idea for garbage collection purposes -Keith */
+ private void clearListeners() {
+ listeners.clear();
+ defaultListener = null;
+ }
+
+ public boolean isUsingDefaultListener() {
+ return listeners.isEmpty();
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/cloud/OnlineCloud.java b/src/java/edu/umd/cs/findbugs/cloud/OnlineCloud.java
index c11d9ac..27b97c1 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/OnlineCloud.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/OnlineCloud.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
diff --git a/src/java/edu/umd/cs/findbugs/cloud/username/ClearCloudPreferences.java b/src/java/edu/umd/cs/findbugs/cloud/username/ClearCloudPreferences.java
index b2d3801..e3ae480 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/username/ClearCloudPreferences.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/username/ClearCloudPreferences.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -26,16 +26,16 @@ import java.util.prefs.Preferences;
* @author pugh
*/
public class ClearCloudPreferences {
-
+
public static void main(String args[]) throws BackingStoreException {
Preferences prefs = Preferences.userNodeForPackage(WebCloudNameLookup.class);
-
- System.out.println(prefs.getLong(WebCloudNameLookup.KEY_APPENGINECLOUD_SESSION_ID, 0));
- WebCloudNameLookup.clearSavedSessionInformation();
-
- prefs.flush();
- prefs.clear();
- prefs.flush();
+
+ System.out.println(prefs.getLong(WebCloudNameLookup.KEY_APPENGINECLOUD_SESSION_ID, 0));
+ WebCloudNameLookup.clearSavedSessionInformation();
+
+ prefs.flush();
+ prefs.clear();
+ prefs.flush();
}
}
diff --git a/src/java/edu/umd/cs/findbugs/cloud/username/LocalNameLookup.java b/src/java/edu/umd/cs/findbugs/cloud/username/LocalNameLookup.java
index 10f54ed..5b17231 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/username/LocalNameLookup.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/username/LocalNameLookup.java
@@ -29,6 +29,7 @@ public class LocalNameLookup implements NameLookup {
String username;
+ @Override
public boolean signIn(CloudPlugin plugin, BugCollection bugCollection) {
try {
@@ -39,6 +40,7 @@ public class LocalNameLookup implements NameLookup {
}
}
+ @Override
public String getUsername() {
return username;
}
diff --git a/src/java/edu/umd/cs/findbugs/cloud/username/NameLookup.java b/src/java/edu/umd/cs/findbugs/cloud/username/NameLookup.java
index 9af6538..c91659d 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/username/NameLookup.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/username/NameLookup.java
@@ -37,11 +37,11 @@ public interface NameLookup {
/**
* tries to obtain a user name. May prompt the user and/or perform network
* activity.
- *
+ *
* @param plugin
* TODO
* @param bugCollection
- *
+ *
* @return true if successful
*/
boolean signIn(CloudPlugin plugin, BugCollection bugCollection) throws IOException;
diff --git a/src/java/edu/umd/cs/findbugs/cloud/username/NoNameLookup.java b/src/java/edu/umd/cs/findbugs/cloud/username/NoNameLookup.java
index 87becce..1ba2f35 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/username/NoNameLookup.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/username/NoNameLookup.java
@@ -27,10 +27,12 @@ import edu.umd.cs.findbugs.cloud.CloudPlugin;
*/
public class NoNameLookup implements NameLookup {
+ @Override
public String getUsername() {
return "no name";
}
+ @Override
public boolean signIn(CloudPlugin plugin, BugCollection bugCollection) {
return true;
}
diff --git a/src/java/edu/umd/cs/findbugs/cloud/username/PromptForNameLookup.java b/src/java/edu/umd/cs/findbugs/cloud/username/PromptForNameLookup.java
index c20b66d..1c00e0e 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/username/PromptForNameLookup.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/username/PromptForNameLookup.java
@@ -47,7 +47,7 @@ public class PromptForNameLookup implements NameLookup {
.showQuestionDialog(
"Name/handle/email for recording your reviews?\n"
+ "(sorry, no authentication or confidentiality currently provided)",
- "Name for recording your reviews", findbugsUser == null ? "" : findbugsUser);
+ "Name for recording your reviews", findbugsUser == null ? "" : findbugsUser);
if (findbugsUser != null) {
prefs.put(USER_NAME, findbugsUser);
username = findbugsUser;
@@ -56,10 +56,12 @@ public class PromptForNameLookup implements NameLookup {
return false;
}
+ @Override
public String getUsername() {
return username;
}
+ @Override
public boolean signIn(CloudPlugin plugin, BugCollection bugCollection) {
this.bugCollection = bugCollection;
return true;
diff --git a/src/java/edu/umd/cs/findbugs/cloud/username/WebCloudNameLookup.java b/src/java/edu/umd/cs/findbugs/cloud/username/WebCloudNameLookup.java
index eaad920..1e82053 100644
--- a/src/java/edu/umd/cs/findbugs/cloud/username/WebCloudNameLookup.java
+++ b/src/java/edu/umd/cs/findbugs/cloud/username/WebCloudNameLookup.java
@@ -59,14 +59,17 @@ public class WebCloudNameLookup implements NameLookup {
private String username;
private String url;
+ @Override
public boolean signIn(CloudPlugin plugin, BugCollection bugCollection) throws IOException {
loadProperties(plugin);
- if (softSignin())
+ if (softSignin()) {
return true;
+ }
- if (sessionId == null)
+ if (sessionId == null) {
sessionId = loadOrCreateSessionId();
+ }
LOGGER.info("Opening browser for session " + sessionId);
URL u = new URL(url + "/browser-auth/" + sessionId);
@@ -90,8 +93,9 @@ public class WebCloudNameLookup implements NameLookup {
public void loadProperties(CloudPlugin plugin) {
PropertyBundle pluginProps = plugin.getProperties();
url = pluginProps.getProperty(APPENGINE_HOST_PROPERTY_NAME);
- if (url == null)
+ if (url == null) {
throw new IllegalStateException("Host not specified for " + plugin.getId());
+ }
}
/**
@@ -101,9 +105,10 @@ public class WebCloudNameLookup implements NameLookup {
* @throws IOException
*/
public boolean softSignin() throws IOException {
- if (url == null)
+ if (url == null) {
throw new IllegalStateException("Null host");
-
+ }
+
checkResolveHost();
if (sessionId != null) {
@@ -116,8 +121,9 @@ public class WebCloudNameLookup implements NameLookup {
}
// check the previously used session ID
long id = loadSessionId();
- if (id == 0)
+ if (id == 0) {
return false;
+ }
boolean authorized = checkAuthorized(getAuthCheckUrl(id));
if (authorized) {
LOGGER.info("Authorized with session ID: " + id);
@@ -134,7 +140,7 @@ public class WebCloudNameLookup implements NameLookup {
} catch (MalformedURLException e) {
assert true;
/* this will come out later */
- }
+ }
}
private URL getAuthCheckUrl(long sessionId) throws MalformedURLException {
@@ -168,6 +174,7 @@ public class WebCloudNameLookup implements NameLookup {
return sessionId;
}
+ @Override
public String getUsername() {
return username;
}
@@ -179,18 +186,20 @@ public class WebCloudNameLookup implements NameLookup {
// ======================= end of public methods =======================
private static SecureRandom secureRandom = new SecureRandom();
-
+
private long loadOrCreateSessionId() {
long id = loadSessionId();
if (id != 0) {
LOGGER.info("Using saved session ID: " + id);
return id;
}
- while (id == 0)
+ while (id == 0) {
id = secureRandom.nextLong();
+ }
- if (isSavingSessionInfoEnabled())
+ if (isSavingSessionInfoEnabled()) {
saveSessionInformation(id);
+ }
return id;
}
diff --git a/src/java/edu/umd/cs/findbugs/config/AnalysisFeatureSetting.java b/src/java/edu/umd/cs/findbugs/config/AnalysisFeatureSetting.java
index 5000534..5a7ec88 100644
--- a/src/java/edu/umd/cs/findbugs/config/AnalysisFeatureSetting.java
+++ b/src/java/edu/umd/cs/findbugs/config/AnalysisFeatureSetting.java
@@ -24,18 +24,19 @@ import edu.umd.cs.findbugs.ba.AnalysisFeatures.AnalysisFeature;
/**
* Configure a specific boolean analysis property.
- *
+ *
* @author David Hovemeyer
*/
public class AnalysisFeatureSetting {
private @AnalysisFeature
+ final
int property;
- private boolean enabled;
+ private final boolean enabled;
/**
* Constructor.
- *
+ *
* @param property
* the analysis property to configure
* @param enabled
@@ -49,7 +50,7 @@ public class AnalysisFeatureSetting {
/**
* Set the configured value of the analysis property in the given
* AnalysisContext.
- *
+ *
* @param analysisContext
* the AnalysisContext
*/
diff --git a/src/java/edu/umd/cs/findbugs/config/CommandLine.java b/src/java/edu/umd/cs/findbugs/config/CommandLine.java
index c12e163..ce04cf0 100644
--- a/src/java/edu/umd/cs/findbugs/config/CommandLine.java
+++ b/src/java/edu/umd/cs/findbugs/config/CommandLine.java
@@ -46,19 +46,19 @@ public abstract class CommandLine {
private static final String SPACES = " ";
- private List<String> optionList;
+ private final List<String> optionList;
- private Set<String> unlistedOptions;
+ private final Set<String> unlistedOptions;
- private Map<Integer, String> optionGroups;
+ private final Map<Integer, String> optionGroups;
- private Set<String> requiresArgumentSet;
+ private final Set<String> requiresArgumentSet;
- private Map<String, String> optionDescriptionMap;
+ private final Map<String, String> optionDescriptionMap;
- private Map<String, String> optionExtraPartSynopsisMap;
+ private final Map<String, String> optionExtraPartSynopsisMap;
- private Map<String, String> argumentDescriptionMap;
+ private final Map<String, String> argumentDescriptionMap;
int maxWidth;
@@ -96,8 +96,9 @@ public abstract class CommandLine {
optionList.add(option);
optionDescriptionMap.put(option, description);
- if (option.length() > maxWidth)
+ if (option.length() > maxWidth) {
maxWidth = option.length();
+ }
}
/**
@@ -118,8 +119,9 @@ public abstract class CommandLine {
// Option will display as -foo[:extraPartSynopsis]
int length = option.length() + optionExtraPartSynopsis.length() + 3;
- if (length > maxWidth)
+ if (length > maxWidth) {
maxWidth = length;
+ }
}
/**
@@ -139,8 +141,9 @@ public abstract class CommandLine {
argumentDescriptionMap.put(option, argumentDesc);
int width = option.length() + 3 + argumentDesc.length();
- if (width > maxWidth)
+ if (width > maxWidth) {
maxWidth = width;
+ }
}
/**
@@ -167,7 +170,7 @@ public abstract class CommandLine {
*/
public String[] expandOptionFiles(String[] argv, boolean ignoreComments, boolean ignoreBlankLines) throws IOException,
- HelpRequestedException {
+ HelpRequestedException {
// Add all expanded options at the end of the options list, before the
// list of
// jar/zip/class files and directories.
@@ -223,16 +226,20 @@ public abstract class CommandLine {
while ((line = reader.readLine()) != null) {
line = line.trim();
- if (ignoreComments && line.startsWith("#"))
+ if (ignoreComments && line.startsWith("#")) {
continue;
+ }
- if (ignoreBlankLines && line.equals(""))
+ if (ignoreBlankLines && "".equals(line)) {
continue;
- if (line.length() >= 2 && line.charAt(0) == '"' && line.charAt(line.length() - 1) == '"')
+ }
+ if (line.length() >= 2 && line.charAt(0) == '"' && line.charAt(line.length() - 1) == '"') {
resultList.add(line.substring(0, line.length() - 1));
- else
- for (String segment : line.split(" "))
+ } else {
+ for (String segment : line.split(" ")) {
resultList.add(segment);
+ }
+ }
}
}
@@ -305,10 +312,12 @@ public abstract class CommandLine {
while (arg < argv.length) {
String option = argv[arg];
- if (option.equals("-help") || option.equals("-h"))
+ if ("-help".equals(option) || "-h".equals(option)) {
throw new HelpRequestedException();
- if (!option.startsWith("-"))
+ }
+ if (!option.startsWith("-")) {
break;
+ }
String optionExtraPart = "";
int colon = option.indexOf(':');
@@ -317,20 +326,24 @@ public abstract class CommandLine {
option = option.substring(0, colon);
}
- if (optionDescriptionMap.get(option) == null)
+ if (optionDescriptionMap.get(option) == null) {
throw new IllegalArgumentException("Unknown option: " + option);
+ }
if (requiresArgumentSet.contains(option)) {
++arg;
- if (arg >= argv.length)
+ if (arg >= argv.length) {
throw new IllegalArgumentException("Option " + option + " requires an argument");
+ }
String argument = argv[arg];
- if (!dryRun)
+ if (!dryRun) {
handleOptionWithArgument(option, argument);
+ }
++arg;
} else {
- if (!dryRun)
+ if (!dryRun) {
handleOption(option, optionExtraPart);
+ }
++arg;
}
}
@@ -376,8 +389,9 @@ public abstract class CommandLine {
}
count++;
- if (unlistedOptions.contains(option))
+ if (unlistedOptions.contains(option)) {
continue;
+ }
out.print(" ");
StringBuilder buf = new StringBuilder();
@@ -401,8 +415,9 @@ public abstract class CommandLine {
}
private static void printField(PrintStream out, String s, int width) {
- if (s.length() > width)
+ if (s.length() > width) {
throw new IllegalArgumentException();
+ }
int nSpaces = width - s.length();
out.print(s);
while (nSpaces > 0) {
diff --git a/src/java/edu/umd/cs/findbugs/config/ProjectFilterSettings.java b/src/java/edu/umd/cs/findbugs/config/ProjectFilterSettings.java
index f3dc5b0..2355fdd 100644
--- a/src/java/edu/umd/cs/findbugs/config/ProjectFilterSettings.java
+++ b/src/java/edu/umd/cs/findbugs/config/ProjectFilterSettings.java
@@ -74,20 +74,20 @@ public class ProjectFilterSettings implements Cloneable {
* The character used for delimiting whole fields in filter settings encoded
* as strings
*/
- private static String FIELD_DELIMITER = "|";
+ private static final char FIELD_DELIMITER = '|';
/**
* The character used for delimiting list items in filter settings encoded
* as strings
*/
- private static String LISTITEM_DELIMITER = ",";
+ private static final String LISTITEM_DELIMITER = ",";
- private static int DEFAULT_MIN_RANK = 15;
+ private static final int DEFAULT_MIN_RANK = 15;
// Fields
private Set<String> activeBugCategorySet; // not used for much:
- // hiddenBugCategorySet has
- // priority.
+ // hiddenBugCategorySet has
+ // priority.
private Set<String> hiddenBugCategorySet;
@@ -205,18 +205,18 @@ public class ProjectFilterSettings implements Cloneable {
String minRankStr;
if (bar >= 0) {
minRankStr = s.substring(0, bar);
- s = s.substring(bar + 1);
+ // s = s.substring(bar + 1);
} else {
minRankStr = s;
- s = "";
+ // s = "";
}
result.setMinRank(Integer.parseInt(minRankStr));
}
- if (s.length() > 0) {
- // Can add other fields here...
- assert true;
- }
+ // if (s.length() > 0) {
+ // // Can add other fields here...
+ // assert true;
+ // }
return result;
@@ -277,7 +277,7 @@ public class ProjectFilterSettings implements Cloneable {
// HACK: it is conceivable that the detector plugin which generated
// this warning is not available any more, in which case we can't
// find out the category. Let the warning be visible in this case.
- if (bugPattern != null && !containsCategory(bugPattern.getCategory())) {
+ if (!containsCategory(bugPattern.getCategory())) {
return false;
}
@@ -561,4 +561,3 @@ public class ProjectFilterSettings implements Cloneable {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/config/SortedProperties.java b/src/java/edu/umd/cs/findbugs/config/SortedProperties.java
index 6f77a73..5313e0e 100644
--- a/src/java/edu/umd/cs/findbugs/config/SortedProperties.java
+++ b/src/java/edu/umd/cs/findbugs/config/SortedProperties.java
@@ -13,15 +13,15 @@ import java.util.Set;
public final class SortedProperties extends Properties {
/**
* Overriden to be able to write properties sorted by keys to the disk
- *
+ *
* @see java.util.Hashtable#keys()
*/
@SuppressWarnings("unchecked")
@Override
public synchronized Enumeration<Object> keys() {
// sort elements based on detector (prop key) names
- Set set = keySet();
- return (Enumeration<Object>) sortKeys(set);
+ Set<?> set = keySet();
+ return (Enumeration<Object>) sortKeys((Set<String>) set);
}
/**
@@ -29,7 +29,7 @@ public final class SortedProperties extends Properties {
* before storing them to disk. Otherwise each change may lead to problems
* by diff against previous version - because Property entries are randomly
* distributed (it's a map).
- *
+ *
* @param keySet
* non null set instance to sort
* @return non null list wich contains all given keys, sorted
diff --git a/src/java/edu/umd/cs/findbugs/config/UserPreferences.java b/src/java/edu/umd/cs/findbugs/config/UserPreferences.java
index 9153fc0..947380b 100644
--- a/src/java/edu/umd/cs/findbugs/config/UserPreferences.java
+++ b/src/java/edu/umd/cs/findbugs/config/UserPreferences.java
@@ -63,12 +63,10 @@ import edu.umd.cs.findbugs.util.Util;
*/
public class UserPreferences implements Cloneable {
- // Public constants
-
/**
* Separator string for values composed from a string and boolean
*/
- private static final String BOOL_SEPARATOR = "|";
+ private static final char BOOL_SEPARATOR = '|';
public static final String EFFORT_MIN = "min";
@@ -99,11 +97,20 @@ public class UserPreferences implements Cloneable {
private static final String EFFORT_KEY = "effort";
- private static final String KEY_INCLUDE_FILTER = "includefilter";
+ /**
+ * Key prefix for custom filters, full key consists of a prefix + filter index starting with 0
+ */
+ public static final String KEY_INCLUDE_FILTER = "includefilter";
- private static final String KEY_EXCLUDE_FILTER = "excludefilter";
+ /**
+ * Key prefix for custom filters, full key consists of a prefix + filter index starting with 0
+ */
+ public static final String KEY_EXCLUDE_FILTER = "excludefilter";
- private static final String KEY_EXCLUDE_BUGS = "excludebugs";
+ /**
+ * Key prefix for custom filters, full key consists of a prefix + filter index starting with 0
+ */
+ public static final String KEY_EXCLUDE_BUGS = "excludebugs";
// Fields
@@ -295,8 +302,9 @@ public class UserPreferences implements Cloneable {
props.put(DETECTOR_THRESHOLD_KEY, String.valueOf(filterSettings.getMinPriorityAsInt()));
props.put(RUN_AT_FULL_BUILD, String.valueOf(runAtFullBuild));
props.setProperty(EFFORT_KEY, effort);
- if (cloudId != null)
+ if (cloudId != null) {
props.setProperty(CLOUD_ID_KEY, cloudId);
+ }
writeProperties(props, KEY_INCLUDE_FILTER, includeFilterFiles);
writeProperties(props, KEY_EXCLUDE_FILTER, excludeFilterFiles);
writeProperties(props, KEY_EXCLUDE_BUGS, excludeBugsFiles);
@@ -721,9 +729,9 @@ public class UserPreferences implements Cloneable {
* setting.
*/
public AnalysisFeatureSetting[] getAnalysisFeatureSettings() {
- if (effort.equals(EFFORT_DEFAULT)) {
+ if (EFFORT_DEFAULT.equals(effort)) {
return FindBugs.DEFAULT_EFFORT;
- } else if (effort.equals(EFFORT_MIN)) {
+ } else if (EFFORT_MIN.equals(effort)) {
return FindBugs.MIN_EFFORT;
}
return FindBugs.MAX_EFFORT;
diff --git a/src/java/edu/umd/cs/findbugs/detect/AnyMethodReturnValueStreamFactory.java b/src/java/edu/umd/cs/findbugs/detect/AnyMethodReturnValueStreamFactory.java
index 8bf4bce..1f68da8 100644
--- a/src/java/edu/umd/cs/findbugs/detect/AnyMethodReturnValueStreamFactory.java
+++ b/src/java/edu/umd/cs/findbugs/detect/AnyMethodReturnValueStreamFactory.java
@@ -37,7 +37,7 @@ import edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback;
* class.
*/
public class AnyMethodReturnValueStreamFactory implements StreamFactory {
- private ObjectType baseClassType;
+ private final ObjectType baseClassType;
private String bugType;
@@ -51,6 +51,7 @@ public class AnyMethodReturnValueStreamFactory implements StreamFactory {
return this;
}
+ @Override
public Stream createStream(Location location, ObjectType type, ConstantPoolGen cpg,
RepositoryLookupFailureCallback lookupFailureCallback) {
@@ -58,13 +59,15 @@ public class AnyMethodReturnValueStreamFactory implements StreamFactory {
try {
if (ins instanceof InvokeInstruction) {
- if (!Hierarchy.isSubtype(type, baseClassType))
+ if (!Hierarchy.isSubtype(type, baseClassType)) {
return null;
+ }
Stream stream = new Stream(location, type.getClassName(), baseClassType.getClassName()).setIsOpenOnCreation(true)
.setIgnoreImplicitExceptions(true);
- if (bugType != null)
+ if (bugType != null) {
stream.setInteresting(bugType);
+ }
return stream;
}
@@ -76,4 +79,3 @@ public class AnyMethodReturnValueStreamFactory implements StreamFactory {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/AppendingToAnObjectOutputStream.java b/src/java/edu/umd/cs/findbugs/detect/AppendingToAnObjectOutputStream.java
index 7fe2075..44ad42a 100644
--- a/src/java/edu/umd/cs/findbugs/detect/AppendingToAnObjectOutputStream.java
+++ b/src/java/edu/umd/cs/findbugs/detect/AppendingToAnObjectOutputStream.java
@@ -19,12 +19,15 @@
package edu.umd.cs.findbugs.detect;
+import java.util.Collections;
+
import org.apache.bcel.classfile.Method;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.OpcodeStack;
import edu.umd.cs.findbugs.Priorities;
+import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
public class AppendingToAnObjectOutputStream extends OpcodeStackDetector {
@@ -35,6 +38,13 @@ public class AppendingToAnObjectOutputStream extends OpcodeStackDetector {
this.bugReporter = bugReporter;
}
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ if(hasInterestingClass(classContext.getJavaClass().getConstantPool(), Collections.singleton("java/io/ObjectOutputStream"))) {
+ super.visitClassContext(classContext);
+ }
+ }
+
boolean sawOpenInAppendMode;
@Override
@@ -44,7 +54,7 @@ public class AppendingToAnObjectOutputStream extends OpcodeStackDetector {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.bcel.OpcodeStackDetector#sawOpcode(int)
*/
@Override
@@ -57,31 +67,33 @@ public class AppendingToAnObjectOutputStream extends OpcodeStackDetector {
String calledMethodName = getNameConstantOperand();
String calledMethodSig = getSigConstantOperand();
if (!sawOpenInAppendMode) {
- if (calledClassName.equals("java/io/ObjectOutputStream") && calledMethodName.equals("<init>")
- && calledMethodSig.equals("(Ljava/io/OutputStream;)V")
- && stack.getStackItem(0).getSpecialKind() == OpcodeStack.Item.FILE_OPENED_IN_APPEND_MODE)
+ if ("java/io/ObjectOutputStream".equals(calledClassName) && "<init>".equals(calledMethodName)
+ && "(Ljava/io/OutputStream;)V".equals(calledMethodSig)
+ && stack.getStackItem(0).getSpecialKind() == OpcodeStack.Item.FILE_OPENED_IN_APPEND_MODE) {
bugReporter.reportBug(new BugInstance(this, "IO_APPENDING_TO_OBJECT_OUTPUT_STREAM", Priorities.HIGH_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
+ }
return;
}
- if (calledClassName.equals("java/io/FileOutputStream") && calledMethodName.equals("<init>")
- && (calledMethodSig.equals("(Ljava/io/File;Z)V") || calledMethodSig.equals("(Ljava/lang/String;Z)V"))) {
+ if ("java/io/FileOutputStream".equals(calledClassName) && "<init>".equals(calledMethodName)
+ && ("(Ljava/io/File;Z)V".equals(calledMethodSig) || "(Ljava/lang/String;Z)V".equals(calledMethodSig))) {
OpcodeStack.Item item = stack.getStackItem(0);
Object value = item.getConstant();
sawOpenInAppendMode = value instanceof Integer && ((Integer) value).intValue() == 1;
} else if (!sawOpenInAppendMode) {
return;
- } else if (calledClassName.equals("java/io/BufferedOutputStream") && calledMethodName.equals("<init>")
- && calledMethodSig.equals("(Ljava/io/OutputStream;)V")) {
+ } else if ("java/io/BufferedOutputStream".equals(calledClassName) && "<init>".equals(calledMethodName)
+ && "(Ljava/io/OutputStream;)V".equals(calledMethodSig)) {
// do nothing
- } else if (calledClassName.equals("java/io/ObjectOutputStream") && calledMethodName.equals("<init>")
- && calledMethodSig.equals("(Ljava/io/OutputStream;)V")) {
+ } else if ("java/io/ObjectOutputStream".equals(calledClassName) && "<init>".equals(calledMethodName)
+ && "(Ljava/io/OutputStream;)V".equals(calledMethodSig)) {
bugReporter.reportBug(new BugInstance(this, "IO_APPENDING_TO_OBJECT_OUTPUT_STREAM", Priorities.HIGH_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
sawOpenInAppendMode = false;
- } else
+ } else {
sawOpenInAppendMode = false;
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/AtomicityProblem.java b/src/java/edu/umd/cs/findbugs/detect/AtomicityProblem.java
index 83fd42c..5ac8915 100644
--- a/src/java/edu/umd/cs/findbugs/detect/AtomicityProblem.java
+++ b/src/java/edu/umd/cs/findbugs/detect/AtomicityProblem.java
@@ -19,11 +19,14 @@
package edu.umd.cs.findbugs.detect;
+import java.util.Collections;
+
import org.apache.bcel.classfile.Code;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.OpcodeStack;
+import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.ba.XClass;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
@@ -32,7 +35,7 @@ import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
* if we get from a ConcurrentHashMap and assign to a variable... and don't do
* anything else and perform a null check on it... and then do a set on it...
* (or anything else inside the if that modifies it?) then we have a bug.
- *
+ *
* @author Michael Midgley-Biggs
*/
public class AtomicityProblem extends OpcodeStackDetector {
@@ -41,7 +44,7 @@ public class AtomicityProblem extends OpcodeStackDetector {
int lastQuestionableCheckTarget = -1;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
final static boolean DEBUG = false;
@@ -50,6 +53,13 @@ public class AtomicityProblem extends OpcodeStackDetector {
}
@Override
+ public void visitClassContext(ClassContext classContext) {
+ if(hasInterestingClass(classContext.getJavaClass().getConstantPool(), Collections.singleton("java/util/concurrent/ConcurrentHashMap"))) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
public void visit(Code obj) {
if (DEBUG) {
System.out.println("Checking " + obj);
@@ -61,7 +71,7 @@ public class AtomicityProblem extends OpcodeStackDetector {
/**
* This is the "dumb" version of the detector. It may generate false
* positives, and/or not detect all instances of the bug.
- *
+ *
* @see edu.umd.cs.findbugs.visitclass.DismantleBytecode#sawOpcode(int)
*/
@Override
@@ -77,8 +87,8 @@ public class AtomicityProblem extends OpcodeStackDetector {
System.out.println("Stack top: " + top);
}
XMethod m = top.getReturnValueOf();
- if (m != null && m.getClassName().equals("java.util.concurrent.ConcurrentHashMap")
- && m.getName().equals("containsKey")) {
+ if (m != null && "java.util.concurrent.ConcurrentHashMap".equals(m.getClassName())
+ && "containsKey".equals(m.getName())) {
lastQuestionableCheckTarget = getBranchTarget();
if (seen == IFEQ) {
priority = LOW_PRIORITY;
@@ -98,7 +108,7 @@ public class AtomicityProblem extends OpcodeStackDetector {
if (DEBUG) {
System.out.println("Found null check");
}
- if (m != null && m.getClassName().equals("java.util.concurrent.ConcurrentHashMap") && m.getName().equals("get")) {
+ if (m != null && "java.util.concurrent.ConcurrentHashMap".equals(m.getClassName()) && "get".equals(m.getName())) {
lastQuestionableCheckTarget = getBranchTarget();
if (seen == IFNULL) {
priority = LOW_PRIORITY;
@@ -110,19 +120,21 @@ public class AtomicityProblem extends OpcodeStackDetector {
}
case INVOKEVIRTUAL:
case INVOKEINTERFACE: {
- if (getDottedClassConstantOperand().equals("java.util.concurrent.ConcurrentHashMap")) {
+ if ("java.util.concurrent.ConcurrentHashMap".equals(getDottedClassConstantOperand())) {
String methodName = getNameConstantOperand();
XClass xClass = getXClassOperand();
- if (xClass != null && methodName.equals("put")) {
+ if (xClass != null && "put".equals(methodName)) {
if ((getPC() < lastQuestionableCheckTarget) && (lastQuestionableCheckTarget != -1)) {
bugReporter.reportBug(new BugInstance(this, "AT_OPERATION_SEQUENCE_ON_CONCURRENT_ABSTRACTION", priority)
- .addClassAndMethod(this).addType(xClass.getClassDescriptor()).addCalledMethod(this)
- .addSourceLine(this));
+ .addClassAndMethod(this).addType(xClass.getClassDescriptor()).addCalledMethod(this)
+ .addSourceLine(this));
}
}
}
break;
}
+ default:
+ break;
}
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/BadAppletConstructor.java b/src/java/edu/umd/cs/findbugs/detect/BadAppletConstructor.java
index 27783f8..d5edfe5 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BadAppletConstructor.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BadAppletConstructor.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.ba.ClassContext;
public class BadAppletConstructor extends BytecodeScanningDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private final JavaClass appletClass;
@@ -50,13 +50,15 @@ public class BadAppletConstructor extends BytecodeScanningDetector {
@Override
public void visitClassContext(ClassContext classContext) {
- if (appletClass == null)
+ if (appletClass == null) {
return;
+ }
JavaClass cls = classContext.getJavaClass();
try {
- if (cls.instanceOf(appletClass))
+ if (cls.instanceOf(appletClass)) {
cls.accept(this);
+ }
} catch (ClassNotFoundException cnfe) {
bugReporter.reportMissingClass(cnfe);
}
@@ -64,13 +66,14 @@ public class BadAppletConstructor extends BytecodeScanningDetector {
@Override
public void visit(Method obj) {
- inConstructor = obj.getName().equals("<init>");
+ inConstructor = "<init>".equals(obj.getName());
}
@Override
public void visit(Code obj) {
- if (inConstructor)
+ if (inConstructor) {
super.visit(obj);
+ }
}
@Override
@@ -78,13 +81,13 @@ public class BadAppletConstructor extends BytecodeScanningDetector {
if (seen == INVOKEVIRTUAL) {
String method = getNameConstantOperand();
String signature = getSigConstantOperand();
- if (((method.equals("getDocumentBase") || method.equals("getCodeBase")) && signature.equals("()Ljava/net/URL;"))
- || (method.equals("getAppletContext") && signature.equals("()Ljava/applet/AppletContext;"))
- || (method.equals("getParameter") && signature.equals("(Ljava/lang/String;)Ljava/lang/String;")))
+ if ((("getDocumentBase".equals(method) || "getCodeBase".equals(method)) && "()Ljava/net/URL;".equals(signature))
+ || ("getAppletContext".equals(method) && "()Ljava/applet/AppletContext;".equals(signature))
+ || ("getParameter".equals(method) && "(Ljava/lang/String;)Ljava/lang/String;".equals(signature))) {
bugReporter.reportBug(new BugInstance(this, "BAC_BAD_APPLET_CONSTRUCTOR", NORMAL_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
+ }
}
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/BadResultSetAccess.java b/src/java/edu/umd/cs/findbugs/detect/BadResultSetAccess.java
index 8279ecb..2244690 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BadResultSetAccess.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BadResultSetAccess.java
@@ -20,12 +20,14 @@
package edu.umd.cs.findbugs.detect;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.OpcodeStack;
+import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
import edu.umd.cs.findbugs.internalAnnotations.StaticConstant;
import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
@@ -70,16 +72,23 @@ public class BadResultSetAccess extends OpcodeStackDetector {
}
@Override
+ public void visitClassContext(ClassContext classContext) {
+ if(hasInterestingClass(classContext.getJavaClass().getConstantPool(), Collections.singleton("java/sql/ResultSet"))) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
public void sawOpcode(int seen) {
if (seen == INVOKEINTERFACE) {
String methodName = getNameConstantOperand();
String clsConstant = getClassConstantOperand();
- if ((clsConstant.equals("java/sql/ResultSet") && ((methodName.startsWith("get") && dbFieldTypesSet
+ if (("java/sql/ResultSet".equals(clsConstant) && ((methodName.startsWith("get") && dbFieldTypesSet
.contains(methodName.substring(3))) || (methodName.startsWith("update") && dbFieldTypesSet
- .contains(methodName.substring(6)))))
- || ((clsConstant.equals("java/sql/PreparedStatement") && ((methodName.startsWith("set") && dbFieldTypesSet
- .contains(methodName.substring(3))))))) {
+ .contains(methodName.substring(6)))))
+ || (("java/sql/PreparedStatement".equals(clsConstant) && ((methodName.startsWith("set") && dbFieldTypesSet
+ .contains(methodName.substring(3))))))) {
String signature = getSigConstantOperand();
int numParms = PreorderVisitor.getNumberArguments(signature);
if (stack.getStackDepth() >= numParms) {
@@ -87,9 +96,9 @@ public class BadResultSetAccess extends OpcodeStackDetector {
if ("I".equals(item.getSignature()) && item.couldBeZero()) {
bugReporter.reportBug(new BugInstance(this,
- clsConstant.equals("java/sql/PreparedStatement") ? "SQL_BAD_PREPARED_STATEMENT_ACCESS"
+ "java/sql/PreparedStatement".equals(clsConstant) ? "SQL_BAD_PREPARED_STATEMENT_ACCESS"
: "SQL_BAD_RESULTSET_ACCESS", item.mustBeZero() ? HIGH_PRIORITY : NORMAL_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
}
}
}
@@ -98,4 +107,3 @@ public class BadResultSetAccess extends OpcodeStackDetector {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/BadSyntaxForRegularExpression.java b/src/java/edu/umd/cs/findbugs/detect/BadSyntaxForRegularExpression.java
index 5ead423..40bba4f 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BadSyntaxForRegularExpression.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BadSyntaxForRegularExpression.java
@@ -38,18 +38,22 @@ public class BadSyntaxForRegularExpression extends OpcodeStackDetector {
}
private void singleDotPatternWouldBeSilly(int stackDepth, boolean ignorePasswordMasking) {
- if (ignorePasswordMasking && stackDepth != 1)
+ if (ignorePasswordMasking && stackDepth != 1) {
throw new IllegalArgumentException("Password masking requires stack depth 1, but is " + stackDepth);
- if (stack.getStackDepth() < stackDepth)
+ }
+ if (stack.getStackDepth() < stackDepth) {
return;
+ }
OpcodeStack.Item it = stack.getStackItem(stackDepth);
Object value = it.getConstant();
- if (value == null || !(value instanceof String))
+ if (value == null || !(value instanceof String)) {
return;
+ }
String regex = (String) value;
- boolean dotIsUsed = regex.equals(".");
- if (!dotIsUsed && !regex.equals("|"))
+ boolean dotIsUsed = ".".equals(regex);
+ if (!dotIsUsed && !"|".equals(regex)) {
return;
+ }
int priority = HIGH_PRIORITY;
if (ignorePasswordMasking && dotIsUsed) {
priority = NORMAL_PRIORITY;
@@ -57,11 +61,13 @@ public class BadSyntaxForRegularExpression extends OpcodeStackDetector {
Object topValue = top.getConstant();
if (topValue instanceof String) {
String replacementString = (String) topValue;
- if (replacementString.toLowerCase().equals("x") || replacementString.equals("-") || replacementString.equals("*")
- || replacementString.equals(" ") || replacementString.equals("\\*"))
+ if ("x".equals(replacementString.toLowerCase()) || "-".equals(replacementString) || "*".equals(replacementString)
+ || " ".equals(replacementString) || "\\*".equals(replacementString)) {
return;
- if (replacementString.length() == 1 && getMethodName().toLowerCase().indexOf("pass") >= 0)
+ }
+ if (replacementString.length() == 1 && getMethodName().toLowerCase().indexOf("pass") >= 0) {
priority = LOW_PRIORITY;
+ }
}
}
@@ -74,31 +80,35 @@ public class BadSyntaxForRegularExpression extends OpcodeStackDetector {
}
private void sawRegExPattern(int stackDepth, int flags) {
- if (stack.getStackDepth() < stackDepth)
+ if (stack.getStackDepth() < stackDepth) {
return;
+ }
OpcodeStack.Item it = stack.getStackItem(stackDepth);
if (it.getSpecialKind() == OpcodeStack.Item.FILE_SEPARATOR_STRING && (flags & Pattern.LITERAL) == 0) {
bugReporter.reportBug(new BugInstance(this, "RE_CANT_USE_FILE_SEPARATOR_AS_REGULAR_EXPRESSION", HIGH_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addCalledMethod(this).addSourceLine(this));
return;
}
Object value = it.getConstant();
- if (value == null || !(value instanceof String))
+ if (value == null || !(value instanceof String)) {
return;
+ }
String regex = (String) value;
try {
Pattern.compile(regex, flags);
} catch (PatternSyntaxException e) {
String message = e.getMessage();
int eol = message.indexOf('\n');
- if (eol > 0)
+ if (eol > 0) {
message = message.substring(0, eol);
+ }
BugInstance bug = new BugInstance(this, "RE_BAD_SYNTAX_FOR_REGULAR_EXPRESSION", HIGH_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this).addString(message).describe(StringAnnotation.ERROR_MSG_ROLE)
- .addString(regex).describe(StringAnnotation.REGEX_ROLE);
+ .addClassAndMethod(this).addCalledMethod(this).addString(message).describe(StringAnnotation.ERROR_MSG_ROLE)
+ .addString(regex).describe(StringAnnotation.REGEX_ROLE);
String options = getOptions(flags);
- if (options.length() > 0)
+ if (options.length() > 0) {
bug.addString("Regex flags: " + options).describe(StringAnnotation.STRING_MESSAGE);
+ }
bug.addSourceLine(this);
bugReporter.reportBug(bug);
}
@@ -106,40 +116,42 @@ public class BadSyntaxForRegularExpression extends OpcodeStackDetector {
/** return an int on the stack, or 'defaultValue' if can't determine */
private int getIntValue(int stackDepth, int defaultValue) {
- if (stack.getStackDepth() < stackDepth)
+ if (stack.getStackDepth() < stackDepth) {
return defaultValue;
+ }
OpcodeStack.Item it = stack.getStackItem(stackDepth);
Object value = it.getConstant();
- if (value == null || !(value instanceof Integer))
+ if (value == null || !(value instanceof Integer)) {
return defaultValue;
+ }
return ((Number) value).intValue();
}
@Override
public void sawOpcode(int seen) {
- if (seen == INVOKESTATIC && getClassConstantOperand().equals("java/util/regex/Pattern")
- && getNameConstantOperand().equals("compile") && getSigConstantOperand().startsWith("(Ljava/lang/String;I)"))
+ if (seen == INVOKESTATIC && "java/util/regex/Pattern".equals(getClassConstantOperand())
+ && "compile".equals(getNameConstantOperand()) && getSigConstantOperand().startsWith("(Ljava/lang/String;I)")) {
sawRegExPattern(1, getIntValue(0, 0));
- else if (seen == INVOKESTATIC && getClassConstantOperand().equals("java/util/regex/Pattern")
- && getNameConstantOperand().equals("compile") && getSigConstantOperand().startsWith("(Ljava/lang/String;)"))
+ } else if (seen == INVOKESTATIC && "java/util/regex/Pattern".equals(getClassConstantOperand())
+ && "compile".equals(getNameConstantOperand()) && getSigConstantOperand().startsWith("(Ljava/lang/String;)")) {
sawRegExPattern(0);
- else if (seen == INVOKESTATIC && getClassConstantOperand().equals("java/util/regex/Pattern")
- && getNameConstantOperand().equals("matches"))
+ } else if (seen == INVOKESTATIC && "java/util/regex/Pattern".equals(getClassConstantOperand())
+ && "matches".equals(getNameConstantOperand())) {
sawRegExPattern(1);
- else if (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/lang/String")
- && getNameConstantOperand().equals("replaceAll")) {
+ } else if (seen == INVOKEVIRTUAL && "java/lang/String".equals(getClassConstantOperand())
+ && "replaceAll".equals(getNameConstantOperand())) {
sawRegExPattern(1);
singleDotPatternWouldBeSilly(1, true);
- } else if (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/lang/String")
- && getNameConstantOperand().equals("replaceFirst")) {
+ } else if (seen == INVOKEVIRTUAL && "java/lang/String".equals(getClassConstantOperand())
+ && "replaceFirst".equals(getNameConstantOperand())) {
sawRegExPattern(1);
singleDotPatternWouldBeSilly(1, false);
- } else if (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/lang/String")
- && getNameConstantOperand().equals("matches")) {
+ } else if (seen == INVOKEVIRTUAL && "java/lang/String".equals(getClassConstantOperand())
+ && "matches".equals(getNameConstantOperand())) {
sawRegExPattern(0);
singleDotPatternWouldBeSilly(0, false);
- } else if (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/lang/String")
- && getNameConstantOperand().equals("split")) {
+ } else if (seen == INVOKEVIRTUAL && "java/lang/String".equals(getClassConstantOperand())
+ && "split".equals(getNameConstantOperand())) {
sawRegExPattern(0);
singleDotPatternWouldBeSilly(0, false);
}
@@ -147,10 +159,12 @@ public class BadSyntaxForRegularExpression extends OpcodeStackDetector {
}
static void appendOption(StringBuilder b, int flags, int mask, String name) {
- if ((flags & mask) == 0)
+ if ((flags & mask) == 0) {
return;
- if (b.length() > 0)
+ }
+ if (b.length() > 0) {
b.append(" | ");
+ }
b.append("Pattern." + name);
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/BadUseOfReturnValue.java b/src/java/edu/umd/cs/findbugs/detect/BadUseOfReturnValue.java
index 65e804f..8581cce 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BadUseOfReturnValue.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BadUseOfReturnValue.java
@@ -48,25 +48,27 @@ public class BadUseOfReturnValue extends BytecodeScanningDetector {
@Override
public void sawOpcode(int seen) {
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("indexOf")
- && getClassConstantOperand().equals("java/lang/String")
- && getSigConstantOperand().equals("(Ljava/lang/String;)I"))
+ if (seen == INVOKEVIRTUAL && "indexOf".equals(getNameConstantOperand())
+ && "java/lang/String".equals(getClassConstantOperand())
+ && "(Ljava/lang/String;)I".equals(getSigConstantOperand())) {
stringIndexOfOnTOS = true;
- else if (stringIndexOfOnTOS) {
- if (seen == IFLE || seen == IFGT)
+ } else if (stringIndexOfOnTOS) {
+ if (seen == IFLE || seen == IFGT) {
bugAccumulator.accumulateBug(
new BugInstance(this, "RV_CHECK_FOR_POSITIVE_INDEXOF", LOW_PRIORITY).addClassAndMethod(this), this);
+ }
stringIndexOfOnTOS = false;
}
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("readLine")
- && getSigConstantOperand().equals("()Ljava/lang/String;") && getClassConstantOperand().startsWith("java/io")
- && !getClassConstantOperand().equals("java/io/LineNumberReader"))
+ if (seen == INVOKEVIRTUAL && "readLine".equals(getNameConstantOperand())
+ && "()Ljava/lang/String;".equals(getSigConstantOperand()) && getClassConstantOperand().startsWith("java/io")
+ && !"java/io/LineNumberReader".equals(getClassConstantOperand())) {
readLineOnTOS = true;
- else if (readLineOnTOS) {
- if (seen == IFNULL || seen == IFNONNULL)
+ } else if (readLineOnTOS) {
+ if (seen == IFNULL || seen == IFNONNULL) {
bugAccumulator.accumulateBug(
new BugInstance(this, "RV_DONT_JUST_NULL_CHECK_READLINE", NORMAL_PRIORITY).addClassAndMethod(this), this);
+ }
readLineOnTOS = false;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/BadlyOverriddenAdapter.java b/src/java/edu/umd/cs/findbugs/detect/BadlyOverriddenAdapter.java
index dd58a26..afaa7f6 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BadlyOverriddenAdapter.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BadlyOverriddenAdapter.java
@@ -31,13 +31,13 @@ import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.BytecodeScanningDetector;
public class BadlyOverriddenAdapter extends BytecodeScanningDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private boolean isAdapter;
- private Map<String, String> methodMap;
+ private final Map<String, String> methodMap;
- private Map<String, BugInstance> badOverrideMap;
+ private final Map<String, BugInstance> badOverrideMap;
public BadlyOverriddenAdapter(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -51,15 +51,15 @@ public class BadlyOverriddenAdapter extends BytecodeScanningDetector {
methodMap.clear();
badOverrideMap.clear();
JavaClass superClass = obj.getSuperClass();
- if (superClass == null)
+ if (superClass == null) {
return;
+ }
String packageName = superClass.getPackageName();
String className = superClass.getClassName();
// A more generic way to add Adapters would be nice here
- isAdapter = ((className.endsWith("Adapter")) && (packageName.equals("java.awt.event") || packageName
- .equals("javax.swing.event")))
- || ((className.equals("DefaultHandler") && (packageName.equals("org.xml.sax.helpers"))));
+ isAdapter = ((className.endsWith("Adapter")) && ("java.awt.event".equals(packageName) || "javax.swing.event".equals(packageName)))
+ || (("DefaultHandler".equals(className) && ("org.xml.sax.helpers".equals(packageName))));
if (isAdapter) {
Method[] methods = superClass.getMethods();
for (Method method1 : methods) {
@@ -74,8 +74,9 @@ public class BadlyOverriddenAdapter extends BytecodeScanningDetector {
@Override
public void visitAfter(JavaClass obj) {
for (BugInstance bi : badOverrideMap.values()) {
- if (bi != null)
+ if (bi != null) {
bugReporter.reportBug(bi);
+ }
}
}
@@ -84,11 +85,11 @@ public class BadlyOverriddenAdapter extends BytecodeScanningDetector {
if (isAdapter) {
String methodName = obj.getName();
String signature = methodMap.get(methodName);
- if (!methodName.equals("<init>") && signature != null) {
+ if (!"<init>".equals(methodName) && signature != null) {
if (!signature.equals(obj.getSignature())) {
if (!badOverrideMap.keySet().contains(methodName)) {
badOverrideMap.put(methodName, new BugInstance(this, "BOA_BADLY_OVERRIDDEN_ADAPTER", NORMAL_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
}
} else {
badOverrideMap.put(methodName, null);
@@ -98,4 +99,3 @@ public class BadlyOverriddenAdapter extends BytecodeScanningDetector {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/BooleanReturnNull.java b/src/java/edu/umd/cs/findbugs/detect/BooleanReturnNull.java
index 85debac..48e9cd7 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BooleanReturnNull.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BooleanReturnNull.java
@@ -19,62 +19,27 @@
package edu.umd.cs.findbugs.detect;
-import org.apache.bcel.classfile.Code;
-
-import edu.umd.cs.findbugs.BugAccumulator;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
-import edu.umd.cs.findbugs.ba.AnalysisContext;
-import edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase;
-import edu.umd.cs.findbugs.ba.NullnessAnnotation;
-import edu.umd.cs.findbugs.ba.SignatureParser;
-import edu.umd.cs.findbugs.ba.XMethod;
-import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
/**
* @author alison
*/
-public class BooleanReturnNull extends OpcodeStackDetector {
-
- BugAccumulator bugAccumulator;
+public class BooleanReturnNull extends TypeReturnNull {
public BooleanReturnNull(BugReporter bugReporter) {
- this.bugAccumulator = new BugAccumulator(bugReporter);
+ super(bugReporter);
}
@Override
- public void visit(Code code) {
- String s = getMethodSig();
- SignatureParser sp = new SignatureParser(s);
- // Check to see if the method has Boolean return type
- if (!"Ljava/lang/Boolean;".equals(sp.getReturnTypeSignature()))
- return;
-
- if (isExplicitlyNullable())
- return;
-
- super.visit(code); // make callbacks to sawOpcode for all opcodes
- bugAccumulator.reportAccumulatedBugs();
-
- }
- private boolean isExplicitlyNullable() {
- AnalysisContext analysisContext = AnalysisContext.currentAnalysisContext();
- INullnessAnnotationDatabase nullnessAnnotationDatabase = analysisContext.getNullnessAnnotationDatabase();
- XMethod xMethod = getXMethod();
- NullnessAnnotation na = nullnessAnnotationDatabase.getResolvedAnnotation(xMethod, true);
- return na != null && na != NullnessAnnotation.NONNULL;
+ protected boolean matchesReturnSignature(String returnSignature) {
+ return "Ljava/lang/Boolean;".equals(returnSignature);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.bcel.OpcodeStackDetector#sawOpcode(int)
- */
- @Override
- public void sawOpcode(int seen) {
- if (seen == ARETURN && getPrevOpcode(1) == ACONST_NULL)
- bugAccumulator.accumulateBug(new BugInstance(this, "NP_BOOLEAN_RETURN_NULL",
- getMethodName().startsWith("is") ? HIGH_PRIORITY : NORMAL_PRIORITY).addClassAndMethod(this), this);
+ @Override
+ protected void accumulateBug() {
+ bugAccumulator.accumulateBug(new BugInstance(this, "NP_BOOLEAN_RETURN_NULL",
+ getMethodName().startsWith("is") ? HIGH_PRIORITY : NORMAL_PRIORITY).addClassAndMethod(this), this);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/BuildCheckReturnAnnotationDatabase.java b/src/java/edu/umd/cs/findbugs/detect/BuildCheckReturnAnnotationDatabase.java
index 94d9e5c..826b014 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BuildCheckReturnAnnotationDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BuildCheckReturnAnnotationDatabase.java
@@ -54,7 +54,6 @@ public class BuildCheckReturnAnnotationDatabase extends AnnotationVisitor {
defaultKind.put("ForParameters", AnnotationDatabase.Target.PARAMETER);
defaultKind.put("ForMethods", AnnotationDatabase.Target.METHOD);
defaultKind.put("ForFields", AnnotationDatabase.Target.FIELD);
-
}
public BuildCheckReturnAnnotationDatabase() {
@@ -62,9 +61,10 @@ public class BuildCheckReturnAnnotationDatabase extends AnnotationVisitor {
}
static String simpleClassName(@DottedClassName String className) {
- int i = className.lastIndexOf(".");
- if (i < 0)
+ int i = className.lastIndexOf('.');
+ if (i < 0) {
return className;
+ }
return className.substring(i + 1);
}
@@ -77,16 +77,18 @@ public class BuildCheckReturnAnnotationDatabase extends AnnotationVisitor {
annotationClassSimpleName = annotationClassSimpleName.substring(DEFAULT_ANNOTATION_ANNOTATION_CLASS.length());
Target annotationTarget = defaultKind.get(annotationClassSimpleName);
- if (annotationTarget != Target.METHOD)
+ if (annotationTarget != Target.METHOD) {
return;
+ }
ElementValue v = map.get("value");
if (v instanceof ClassElementValue) {
handleClassElementValue((ClassElementValue) v, map, annotationTarget);
} else if (v instanceof ArrayElementValue) {
for (ElementValue v2 : ((ArrayElementValue) v).getElementValuesArray()) {
- if (v2 instanceof ClassElementValue)
+ if (v2 instanceof ClassElementValue) {
handleClassElementValue((ClassElementValue) v2, map, annotationTarget);
+ }
}
}
@@ -100,45 +102,46 @@ public class BuildCheckReturnAnnotationDatabase extends AnnotationVisitor {
if (v instanceof EnumElementValue) {
EnumElementValue when = (EnumElementValue) v;
String w = simpleClassName(when.getEnumValueString());
- if (w.equals("NEVER") || w.equals("UNKNOWN"))
+ if ("NEVER".equals(w) || "UNKNOWN".equals(w)) {
n = CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE;
- else if (w.equals("MAYBE"))
+ } else if ("MAYBE".equals(w)) {
n = CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE;
- else if (w.equals("ALWAYS"))
+ } else if ("ALWAYS".equals(w)) {
n = CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH;
- else
+ } else {
return;
- } else
+ }
+ } else {
n = CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM;
+ }
} else if (annotationClassName.equals(edu.umd.cs.findbugs.annotations.CheckReturnValue.class.getName())) {
n = CheckReturnValueAnnotation.parse(getAnnotationParameterAsString(map, "priority"));
- } else if (annotationClassSimpleName.equals("CheckReturnValue")) {
+ } else if ("CheckReturnValue".equals(annotationClassSimpleName)) {
n = CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM;
- } else
+ } else {
return;
- if (n == null)
+ }
+ if (n == null) {
return;
- if (visitingMethod())
+ }
+ if (visitingMethod()) {
AnalysisContext.currentAnalysisContext().getCheckReturnAnnotationDatabase()
- .addDirectAnnotation(XFactory.createXMethod(this), n);
- else
+ .addDirectAnnotation(XFactory.createXMethod(this), n);
+ } else {
AnalysisContext.currentAnalysisContext().getCheckReturnAnnotationDatabase()
- .addDefaultAnnotation(Target.METHOD, getDottedClassName(), n);
+ .addDefaultAnnotation(Target.METHOD, getDottedClassName(), n);
+ }
}
- /**
- * @param value
- * @param map
- * @param annotationTarget
- */
private void handleClassElementValue(ClassElementValue value, Map<String, ElementValue> map, Target annotationTarget) {
- if (simpleClassName(value.getClassString()).equals("CheckReturnValue")) {
+ if ("CheckReturnValue".equals(simpleClassName(value.getClassString()))) {
CheckReturnValueAnnotation n = CheckReturnValueAnnotation.parse(getAnnotationParameterAsString(map, "priority"));
- if (n != null)
+ if (n != null) {
AnalysisContext.currentAnalysisContext().getCheckReturnAnnotationDatabase()
- .addDefaultAnnotation(annotationTarget, getDottedClassName(), n);
+ .addDefaultAnnotation(annotationTarget, getDottedClassName(), n);
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/BuildInterproceduralCallGraph.java b/src/java/edu/umd/cs/findbugs/detect/BuildInterproceduralCallGraph.java
index b89e97a..936779b 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BuildInterproceduralCallGraph.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BuildInterproceduralCallGraph.java
@@ -35,11 +35,11 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Build the interprocedural call graph.
- *
+ *
* NOTE: at the present time, this facility is only used to find relevant type
* qualifiers. It could become a more general-purpose facility if there were a
* need.
- *
+ *
* @author David Hovemeyer
*/
public class BuildInterproceduralCallGraph extends BytecodeScanningDetector implements NonReportingDetector {
@@ -50,7 +50,7 @@ public class BuildInterproceduralCallGraph extends BytecodeScanningDetector impl
/**
* Constructor.
- *
+ *
* @param bugReporter
* the BugReporter to use
*/
@@ -61,13 +61,6 @@ public class BuildInterproceduralCallGraph extends BytecodeScanningDetector impl
callGraph = new InterproceduralCallGraph();
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.BytecodeScanningDetector#visitClassContext(edu.umd
- * .cs.findbugs.ba.ClassContext)
- */
@Override
public void visitClassContext(ClassContext classContext) {
if (!Analysis.FIND_EFFECTIVE_RELEVANT_QUALIFIERS) {
@@ -76,24 +69,12 @@ public class BuildInterproceduralCallGraph extends BytecodeScanningDetector impl
super.visitClassContext(classContext);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.visitclass.BetterVisitor#visitMethod(org.apache.bcel
- * .classfile.Method)
- */
@Override
public void visitMethod(Method obj) {
currentVertex = findVertex(getXMethod());
super.visitMethod(obj);
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.visitclass.DismantleBytecode#sawOpcode(int)
- */
@Override
public void sawOpcode(int seen) {
switch (seen) {
@@ -105,12 +86,15 @@ public class BuildInterproceduralCallGraph extends BytecodeScanningDetector impl
XMethod calledXMethod = XFactory.createXMethod(called);
InterproceduralCallGraphVertex calledVertex = findVertex(calledXMethod);
callGraph.createEdge(currentVertex, calledVertex);
+ break;
+ default:
+ break;
}
}
/**
* Find the InterproceduralCallGraphVertex for given XMethod.
- *
+ *
* @param xmethod
* an XMethod
* @return the XMethod's InterproceduralCallGraphVertex
@@ -126,11 +110,6 @@ public class BuildInterproceduralCallGraph extends BytecodeScanningDetector impl
return vertex;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.BytecodeScanningDetector#report()
- */
@Override
public void report() {
if (!Analysis.FIND_EFFECTIVE_RELEVANT_QUALIFIERS) {
diff --git a/src/java/edu/umd/cs/findbugs/detect/BuildNonNullAnnotationDatabase.java b/src/java/edu/umd/cs/findbugs/detect/BuildNonNullAnnotationDatabase.java
index d919bc1..e829322 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BuildNonNullAnnotationDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BuildNonNullAnnotationDatabase.java
@@ -54,7 +54,7 @@ import edu.umd.cs.findbugs.visitclass.AnnotationVisitor;
public class BuildNonNullAnnotationDatabase extends AnnotationVisitor {
private static final boolean DEBUG = SystemProperties.getBoolean("fnd.debug.annotation");
- private static final String DEFAULT_ANNOTATION_ANNOTATION_CLASS = "DefaultAnnotation";
+ // private static final String DEFAULT_ANNOTATION_ANNOTATION_CLASS = "DefaultAnnotation";
@StaticConstant
private static final Map<String, AnnotationDatabase.Target> defaultKind = new HashMap<String, AnnotationDatabase.Target>();
@@ -73,23 +73,18 @@ public class BuildNonNullAnnotationDatabase extends AnnotationVisitor {
}
static String lastPortion(String className) {
- int i = className.lastIndexOf(".");
- if (i < 0)
+ int i = className.lastIndexOf('.');
+ if (i < 0) {
return className;
+ }
return className.substring(i + 1);
}
- /*
- * * @param value
- *
- * @param map
- *
- * @param annotationTarget
- */
private void handleClassElementValue(ClassElementValue value, Target annotationTarget) {
NullnessAnnotation n = NullnessAnnotation.Parser.parse(value.getClassString());
- if (n != null)
+ if (n != null) {
database.addDefaultAnnotation(annotationTarget, getDottedClassName(), n);
+ }
}
@@ -107,26 +102,29 @@ public class BuildNonNullAnnotationDatabase extends AnnotationVisitor {
annotationClass = annotationClass.substring("DefaultAnnotation".length());
Target annotationTarget = defaultKind.get(annotationClass);
- if (annotationTarget != Target.METHOD)
+ if (annotationTarget != Target.METHOD) {
return;
+ }
ElementValue v = map.get("value");
if (v instanceof ClassElementValue) {
handleClassElementValue((ClassElementValue) v, annotationTarget);
} else if (v instanceof ArrayElementValue) {
for (ElementValue v2 : ((ArrayElementValue) v).getElementValuesArray()) {
- if (v2 instanceof ClassElementValue)
+ if (v2 instanceof ClassElementValue) {
handleClassElementValue((ClassElementValue) v2, annotationTarget);
+ }
}
}
return;
}
- } else if (visitingMethod())
+ } else if (visitingMethod()) {
database.addDirectAnnotation(XFactory.createXMethod(this), n);
- else if (visitingField())
+ } else if (visitingField()) {
database.addDirectAnnotation(XFactory.createXField(this), n);
+ }
}
@@ -152,8 +150,9 @@ public class BuildNonNullAnnotationDatabase extends AnnotationVisitor {
NullnessAnnotation n = NullnessAnnotation.Parser.parse(annotationClass);
annotationClass = lastPortion(annotationClass);
- if (n == null)
+ if (n == null) {
return;
+ }
XMethod xmethod = XFactory.createXMethod(this);
if (DEBUG) {
diff --git a/src/java/edu/umd/cs/findbugs/detect/BuildNonnullReturnDatabase.java b/src/java/edu/umd/cs/findbugs/detect/BuildNonnullReturnDatabase.java
index dcfb1ee..43752b0 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BuildNonnullReturnDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BuildNonnullReturnDatabase.java
@@ -43,7 +43,7 @@ import edu.umd.cs.findbugs.ba.npe.IsNullValueFrame;
/**
* Build database of methods that return values guaranteed to be nonnull
- *
+ *
*/
public class BuildNonnullReturnDatabase {
public static final boolean VERBOSE_DEBUG = SystemProperties.getBoolean("fnd.debug.nullarg.verbose");
@@ -54,21 +54,25 @@ public class BuildNonnullReturnDatabase {
boolean fullAnalysis = AnalysisContext.currentAnalysisContext().getBoolProperty(
FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES);
if (!fullAnalysis && !AnalysisContext.currentAnalysisContext()./*
- * getSubtypes
- * ().
- */isApplicationClass(classContext.getJavaClass()))
+ * getSubtypes
+ * ().
+ */isApplicationClass(classContext.getJavaClass())) {
return;
- if (VERBOSE_DEBUG)
+ }
+ if (VERBOSE_DEBUG) {
System.out.println("Visiting class " + classContext.getJavaClass().getClassName());
+ }
- for (Method m : classContext.getMethodsInCallOrder())
+ for (Method m : classContext.getMethodsInCallOrder()) {
considerMethod(classContext, m);
+ }
}
private void considerMethod(ClassContext classContext, Method method) {
if ((method.getReturnType() instanceof ReferenceType) && classContext.getMethodGen(method) != null) {
- if (VERBOSE_DEBUG)
+ if (VERBOSE_DEBUG) {
System.out.println("Check " + method);
+ }
analyzeMethod(classContext, method);
}
}
@@ -89,11 +93,13 @@ public class BuildNonnullReturnDatabase {
InstructionHandle handle = location.getHandle();
Instruction ins = handle.getInstruction();
- if (!(ins instanceof ARETURN))
+ if (!(ins instanceof ARETURN)) {
continue;
+ }
IsNullValueFrame frame = inv.getFactAtLocation(location);
- if (!frame.isValid())
+ if (!frame.isValid()) {
continue;
+ }
IsNullValue value = frame.getTopValue();
if (!value.isDefinitelyNotNull()) {
guaranteedNonNull = false;
@@ -106,9 +112,10 @@ public class BuildNonnullReturnDatabase {
if (guaranteedNonNull) {
returnsNonNull++;
AnalysisContext.currentAnalysisContext().getReturnValueNullnessPropertyDatabase()
- .setProperty(xmethod.getMethodDescriptor(), guaranteedNonNull);
- if (DEBUG)
+ .setProperty(xmethod.getMethodDescriptor(), guaranteedNonNull);
+ if (DEBUG) {
System.out.println("Unconditional deref: " + xmethod + "=" + guaranteedNonNull);
+ }
}
@@ -116,11 +123,11 @@ public class BuildNonnullReturnDatabase {
XMethod xmethod = XFactory.createXMethod(classContext.getJavaClass(), method);
AnalysisContext.currentAnalysisContext().getLookupFailureCallback()
- .logError("Error analyzing " + xmethod + " for unconditional deref training", e);
+ .logError("Error analyzing " + xmethod + " for unconditional deref training", e);
} catch (DataflowAnalysisException e) {
XMethod xmethod = XFactory.createXMethod(classContext.getJavaClass(), method);
AnalysisContext.currentAnalysisContext().getLookupFailureCallback()
- .logError("Error analyzing " + xmethod + " for unconditional deref training", e);
+ .logError("Error analyzing " + xmethod + " for unconditional deref training", e);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/BuildObligationPolicyDatabase.java b/src/java/edu/umd/cs/findbugs/detect/BuildObligationPolicyDatabase.java
index b3d24a8..3a840ec 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BuildObligationPolicyDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BuildObligationPolicyDatabase.java
@@ -148,8 +148,9 @@ public class BuildObligationPolicyDatabase implements Detector2, NonReportingDet
for (Map.Entry<MethodDescriptor, String> e : db.entrySet()) {
String[] v = e.getValue().split(",");
Obligation obligation = database.getFactory().getObligationByName(v[2]);
- if (obligation == null)
+ if (obligation == null) {
obligation = database.getFactory().addObligation(v[2]);
+ }
database.addEntry(new MatchMethodEntry(e.getKey(), ObligationPolicyDatabaseActionType.valueOf(v[0]),
ObligationPolicyDatabaseEntryType.valueOf(v[1]), obligation));
}
@@ -163,6 +164,7 @@ public class BuildObligationPolicyDatabase implements Detector2, NonReportingDet
Global.getAnalysisCache().eagerlyPutDatabase(ObligationPolicyDatabase.class, database);
}
+ @Override
public void visitClass(ClassDescriptor classDescriptor) throws CheckedAnalysisException {
XClass xclass = Global.getAnalysisCache().getClassAnalysis(XClass.class, classDescriptor);
@@ -241,11 +243,12 @@ public class BuildObligationPolicyDatabase implements Detector2, NonReportingDet
* obligation. If strict checking is performed, // weak
* entries are ignored.
*/
- if (xmethod.getName().equals("<init>") || xmethod.isStatic()
+ if ("<init>".equals(xmethod.getName()) || xmethod.isStatic()
|| xmethod.getName().toLowerCase().indexOf("close") >= 0
- || xmethod.getSignature().toLowerCase().indexOf("Closeable") >= 0)
+ || xmethod.getSignature().toLowerCase().indexOf("Closeable") >= 0) {
addParameterDeletesObligationDatabaseEntry(xmethod, obligationType,
ObligationPolicyDatabaseEntryType.WEAK);
+ }
}
}
}
@@ -253,6 +256,7 @@ public class BuildObligationPolicyDatabase implements Detector2, NonReportingDet
}
+ @Override
public void finishPass() {
//
// If we saw any obligation-related annotations in the application
@@ -271,6 +275,7 @@ public class BuildObligationPolicyDatabase implements Detector2, NonReportingDet
}
}
+ @Override
public String getDetectorClassName() {
return this.getClass().getName();
}
@@ -383,7 +388,7 @@ public class BuildObligationPolicyDatabase implements Detector2, NonReportingDet
// See what type of obligation is being created.
Obligation createdObligation = null;
- if (xmethod.getName().equals("<init>")) {
+ if ("<init>".equals(xmethod.getName())) {
// Constructor - obligation type is the type of object being created
// (or some supertype)
createdObligation = database.getFactory().getObligationByType(xmethod.getClassDescriptor());
diff --git a/src/java/edu/umd/cs/findbugs/detect/BuildStringPassthruGraph.java b/src/java/edu/umd/cs/findbugs/detect/BuildStringPassthruGraph.java
new file mode 100644
index 0000000..5c67f38
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/detect/BuildStringPassthruGraph.java
@@ -0,0 +1,293 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.detect;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+import org.apache.bcel.classfile.Code;
+import org.apache.bcel.classfile.Method;
+
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.NonReportingDetector;
+import edu.umd.cs.findbugs.OpcodeStack.Item;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+
+/**
+ * Builds the database of string parameters passed from method to method unchanged.
+ * @author Tagir Valeev
+ */
+public class BuildStringPassthruGraph extends OpcodeStackDetector implements NonReportingDetector {
+
+ public static class MethodParameter {
+ final MethodDescriptor md;
+
+ final int parameterNumber;
+
+ public MethodParameter(MethodDescriptor md, int parameterNumber) {
+ super();
+ this.md = md;
+ this.parameterNumber = parameterNumber;
+ }
+
+ public MethodDescriptor getMethodDescriptor() {
+ return md;
+ }
+
+ public int getParameterNumber() {
+ return parameterNumber;
+ }
+
+ @Override
+ public String toString() {
+ return this.md + "[" + this.parameterNumber + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((md == null) ? 0 : md.hashCode());
+ result = prime * result + parameterNumber;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ MethodParameter other = (MethodParameter) obj;
+ if (md == null) {
+ if (other.md != null) {
+ return false;
+ }
+ } else if (!md.equals(other.md)) {
+ return false;
+ }
+ if (parameterNumber != other.parameterNumber) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public static class StringPassthruDatabase {
+ private static final List<MethodDescriptor> FILENAME_STRING_METHODS = Arrays.asList(
+ new MethodDescriptor("java/io/File", "<init>", "(Ljava/lang/String;)V"),
+ new MethodDescriptor("java/io/File", "<init>", "(Ljava/lang/String;Ljava/lang/String;)V"),
+ new MethodDescriptor("java/io/RandomAccessFile", "<init>", "(Ljava/lang/String;Ljava/lang/String;)V"),
+ new MethodDescriptor("java/nio/file/Paths", "get", "(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path;", true),
+ new MethodDescriptor("java/io/FileReader", "<init>", "(Ljava/lang/String;)V"),
+ new MethodDescriptor("java/io/FileWriter", "<init>", "(Ljava/lang/String;)V"),
+ new MethodDescriptor("java/io/FileWriter", "<init>", "(Ljava/lang/String;Z)V"),
+ new MethodDescriptor("java/io/FileInputStream", "<init>", "(Ljava/lang/String;)V"),
+ new MethodDescriptor("java/io/FileOutputStream", "<init>", "(Ljava/lang/String;)V"),
+ new MethodDescriptor("java/io/FileOutputStream", "<init>", "(Ljava/lang/String;Z)V"),
+ new MethodDescriptor("java/util/Formatter", "<init>", "(Ljava/lang/String;)V"),
+ new MethodDescriptor("java/util/Formatter", "<init>", "(Ljava/lang/String;Ljava/lang/String;)V"),
+ new MethodDescriptor("java/util/Formatter", "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/util/Locale;)V"),
+ new MethodDescriptor("java/util/jar/JarFile", "<init>", "(Ljava/lang/String;)V"),
+ new MethodDescriptor("java/util/jar/JarFile", "<init>", "(Ljava/lang/String;Z)V"),
+ new MethodDescriptor("java/util/zip/ZipFile", "<init>", "(Ljava/lang/String;)V"),
+ new MethodDescriptor("java/util/zip/ZipFile", "<init>", "(Ljava/lang/String;Ljava/nio/charset/Charset;)V"),
+ new MethodDescriptor("java/io/PrintStream", "<init>", "(Ljava/lang/String;)V"),
+ new MethodDescriptor("java/io/PrintStream", "<init>", "(Ljava/lang/String;Ljava/lang/String;)V"),
+ new MethodDescriptor("java/io/PrintWriter", "<init>", "(Ljava/lang/String;)V"),
+ new MethodDescriptor("java/io/PrintWriter", "<init>", "(Ljava/lang/String;Ljava/lang/String;)V")
+ );
+
+ private final Map<MethodParameter, Set<MethodParameter>> graph = new HashMap<>();
+
+ /**
+ * Adds edge to the string passthru graph
+ * @param in callee
+ * @param out caller
+ */
+ void addEdge(MethodParameter in, MethodParameter out) {
+ Set<MethodParameter> outs = graph.get(in);
+ if (outs == null) {
+ outs = new HashSet<>();
+ graph.put(in, outs);
+ }
+ outs.add(out);
+ }
+
+ Set<MethodParameter> findLinked(Set<MethodParameter> inputs) {
+ Set<MethodParameter> result = new HashSet<>(inputs);
+ Queue<MethodParameter> toCheck = new ArrayDeque<>(inputs);
+ while (!toCheck.isEmpty()) {
+ MethodParameter in = toCheck.poll();
+ Set<MethodParameter> outs = graph.get(in);
+ if (outs != null) {
+ for (MethodParameter out : outs) {
+ if (!result.contains(out)) {
+ result.add(out);
+ toCheck.add(out);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns methods which call directly or indirectly methods from inputs
+ * passing the parameter unchanged
+ *
+ * @param inputs
+ * input methods with parameter
+ * @return Map where keys are methods and values are parameter indexes which can be passed to requested methods unchanged
+ */
+ public Map<MethodDescriptor, int[]> findLinkedMethods(Set<MethodParameter> inputs) {
+ Map<MethodDescriptor, int[]> result = new HashMap<>();
+ for (MethodParameter found : findLinked(inputs)) {
+ int[] params = result.get(found.getMethodDescriptor());
+ if(params == null) {
+ params = new int[] {found.getParameterNumber()};
+ result.put(found.getMethodDescriptor(), params);
+ } else {
+ int[] newParams = new int[params.length+1];
+ System.arraycopy(params, 0, newParams, 0, params.length);
+ newParams[params.length] = found.getParameterNumber();
+ result.put(found.getMethodDescriptor(), newParams);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns methods which parameter is the file name
+ * @return Map where keys are methods and values are parameter indexes which are used as file names
+ */
+ public Map<MethodDescriptor, int[]> getFileNameStringMethods() {
+ Set<MethodParameter> fileNameStringMethods = new HashSet<>();
+ for(MethodDescriptor md : FILENAME_STRING_METHODS) {
+ fileNameStringMethods.add(new MethodParameter(md, 0));
+ }
+ return findLinkedMethods(fileNameStringMethods);
+ }
+ }
+
+ private final StringPassthruDatabase cache = new StringPassthruDatabase();
+
+ private int nArgs;
+
+ private int shift;
+
+ private boolean[] argEnabled;
+
+ private List<MethodParameter>[] passedParameters;
+
+ public BuildStringPassthruGraph(BugReporter bugReporter) {
+ Global.getAnalysisCache().eagerlyPutDatabase(StringPassthruDatabase.class, cache);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void visitMethod(Method obj) {
+ argEnabled = null;
+ org.apache.bcel.generic.Type[] argumentTypes = obj.getArgumentTypes();
+ if(argumentTypes.length == 0) {
+ return;
+ }
+ nArgs = argumentTypes.length;
+ for(int i=0; i<nArgs; i++) {
+ if(argumentTypes[i].getSignature().equals("Ljava/lang/String;")) {
+ if(argEnabled == null) {
+ argEnabled = new boolean[nArgs];
+ }
+ argEnabled[i] = true;
+ }
+ }
+ if(argEnabled != null) {
+ shift = obj.isStatic() ? 0 : -1;
+ passedParameters = new List[nArgs];
+ }
+ super.visitMethod(obj);
+ }
+
+ @Override
+ public boolean shouldVisitCode(Code obj) {
+ return argEnabled != null;
+ }
+
+ @Override
+ public void visitAfter(Code obj) {
+ super.visitAfter(obj);
+ for (int i = 0; i < nArgs; i++) {
+ List<MethodParameter> list = passedParameters[i];
+ if (list != null) {
+ MethodParameter cur = new MethodParameter(getMethodDescriptor(), i);
+ for (MethodParameter mp : list) {
+ cache.addEdge(mp, cur);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if (isRegisterStore()) {
+ int param = getRegisterOperand() + shift;
+ if (param >= 0 && param < nArgs) {
+ argEnabled[param] = false;
+ passedParameters[param] = null;
+ }
+ }
+ switch (seen) {
+ case INVOKESPECIAL:
+ case INVOKESTATIC:
+ case INVOKEINTERFACE:
+ case INVOKEVIRTUAL:
+ MethodDescriptor md = getMethodDescriptorOperand();
+ int callArgs = getNumberArguments(md.getSignature());
+ for (int i = 0; i < callArgs; i++) {
+ Item item = getStack().getStackItem(callArgs - 1 - i);
+ int param = item.getRegisterNumber() + shift;
+ if (param >= 0 && param < nArgs && argEnabled[param]) {
+ List<MethodParameter> list = passedParameters[param];
+ if (list == null) {
+ passedParameters[param] = list = new ArrayList<>();
+ }
+ list.add(new MethodParameter(md, i));
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/detect/BuildUnconditionalParamDerefDatabase.java b/src/java/edu/umd/cs/findbugs/detect/BuildUnconditionalParamDerefDatabase.java
index 53806f5..b5bc35e 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BuildUnconditionalParamDerefDatabase.java
+++ b/src/java/edu/umd/cs/findbugs/detect/BuildUnconditionalParamDerefDatabase.java
@@ -57,8 +57,6 @@ import edu.umd.cs.findbugs.ba.jsr305.TypeQualifierValue;
import edu.umd.cs.findbugs.ba.vna.ValueNumber;
import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
-import edu.umd.cs.findbugs.classfile.ClassDescriptor;
-import edu.umd.cs.findbugs.classfile.DescriptorFactory;
/**
* Build database of unconditionally dereferenced parameters.
@@ -70,37 +68,42 @@ public abstract class BuildUnconditionalParamDerefDatabase implements Detector {
private static final boolean DEBUG = SystemProperties.getBoolean("fnd.debug.nullarg") || VERBOSE_DEBUG;
- public final TypeQualifierValue nonnullTypeQualifierValue;
+ public final TypeQualifierValue<javax.annotation.Nonnull> nonnullTypeQualifierValue;
abstract protected void reportBug(BugInstance bug);
public BuildUnconditionalParamDerefDatabase() {
- ClassDescriptor nonnullClassDesc = DescriptorFactory.createClassDescriptor(javax.annotation.Nonnull.class);
- this.nonnullTypeQualifierValue = TypeQualifierValue.getValue(nonnullClassDesc, null);
+ this.nonnullTypeQualifierValue = TypeQualifierValue.getValue(javax.annotation.Nonnull.class, null);
}
+ @Override
public void visitClassContext(ClassContext classContext) {
boolean fullAnalysis = AnalysisContext.currentAnalysisContext().getBoolProperty(
FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES);
- if (!fullAnalysis && !AnalysisContext.currentAnalysisContext().isApplicationClass(classContext.getJavaClass()))
+ if (!fullAnalysis && !AnalysisContext.currentAnalysisContext().isApplicationClass(classContext.getJavaClass())) {
return;
- if (VERBOSE_DEBUG)
+ }
+ if (VERBOSE_DEBUG) {
System.out.println("Visiting class " + classContext.getJavaClass().getClassName());
+ }
- for (Method m : classContext.getMethodsInCallOrder())
+ for (Method m : classContext.getMethodsInCallOrder()) {
considerMethod(classContext, m);
+ }
}
private void considerMethod(ClassContext classContext, Method method) {
boolean hasReferenceParameters = false;
- for (Type argument : method.getArgumentTypes())
+ for (Type argument : method.getArgumentTypes()) {
if (argument instanceof ReferenceType) {
hasReferenceParameters = true;
}
+ }
if (hasReferenceParameters && classContext.getMethodGen(method) != null) {
- if (VERBOSE_DEBUG)
+ if (VERBOSE_DEBUG) {
System.out.println("Check " + method);
+ }
analyzeMethod(classContext, method);
}
}
@@ -133,8 +136,8 @@ public abstract class BuildUnconditionalParamDerefDatabase implements Detector {
TypeQualifierAnnotation typeQualifierAnnotation = TypeQualifierApplications
.getEffectiveTypeQualifierAnnotation(xmethod, i, nonnullTypeQualifierValue);
boolean implicitNullCheckForEquals = false;
- if (directTypeQualifierAnnotation == null && method.getName().equals("equals")
- && method.getSignature().equals("(Ljava/lang/Object;)Z") && !method.isStatic()) {
+ if (directTypeQualifierAnnotation == null && "equals".equals(method.getName())
+ && "(Ljava/lang/Object;)Z".equals(method.getSignature()) && !method.isStatic()) {
implicitNullCheckForEquals = true;
Code code = method.getCode();
ConstantPool cp = jclass.getConstantPool();
@@ -155,22 +158,25 @@ public abstract class BuildUnconditionalParamDerefDatabase implements Detector {
typeQualifierAnnotation = TypeQualifierAnnotation.getValue(nonnullTypeQualifierValue, When.MAYBE);
}
- if (typeQualifierAnnotation != null && typeQualifierAnnotation.when == When.ALWAYS)
+ if (typeQualifierAnnotation != null && typeQualifierAnnotation.when == When.ALWAYS) {
unconditionalDerefSet.set(i);
- else if (isCaught(classContext, method, entryFact, paramVN)) {
+ } else if (isCaught(classContext, method, entryFact, paramVN)) {
// ignore
- } else if (typeQualifierAnnotation == null)
+ } else if (typeQualifierAnnotation == null) {
unconditionalDerefSet.set(i);
- else {
+ } else {
int paramLocal = xmethod.isStatic() ? i : i + 1;
int priority = Priorities.NORMAL_PRIORITY;
- if (typeQualifierAnnotation.when != When.UNKNOWN)
+ if (typeQualifierAnnotation.when != When.UNKNOWN) {
priority--;
- if (xmethod.isStatic() || xmethod.isFinal() || xmethod.isPrivate() || xmethod.getName().equals("<init>")
- || jclass.isFinal())
+ }
+ if (xmethod.isStatic() || xmethod.isFinal() || xmethod.isPrivate() || "<init>".equals(xmethod.getName())
+ || jclass.isFinal()) {
priority--;
- if (directTypeQualifierAnnotation == null)
+ }
+ if (directTypeQualifierAnnotation == null) {
priority++;
+ }
String bugPattern = implicitNullCheckForEquals ? "NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT"
: "NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE";
reportBug(new BugInstance(this, bugPattern, priority).addClassAndMethod(jclass, method).add(
@@ -178,10 +184,11 @@ public abstract class BuildUnconditionalParamDerefDatabase implements Detector {
}
}
i++;
- if (paramSig.equals("D") || paramSig.equals("J"))
+ if ("D".equals(paramSig) || "J".equals(paramSig)) {
paramLocalOffset += 2;
- else
+ } else {
paramLocalOffset += 1;
+ }
}
// No need to add properties if there are no unconditionally
@@ -201,34 +208,28 @@ public abstract class BuildUnconditionalParamDerefDatabase implements Detector {
property.setParamsWithProperty(unconditionalDerefSet);
AnalysisContext.currentAnalysisContext().getUnconditionalDerefParamDatabase()
- .setProperty(xmethod.getMethodDescriptor(), property);
+ .setProperty(xmethod.getMethodDescriptor(), property);
if (DEBUG) {
System.out.println("Unconditional deref: " + xmethod + "=" + property);
}
} catch (CheckedAnalysisException e) {
AnalysisContext.currentAnalysisContext().getLookupFailureCallback()
- .logError("Error analyzing " + xmethod + " for unconditional deref training", e);
+ .logError("Error analyzing " + xmethod + " for unconditional deref training", e);
}
}
- /**
- * @param classContext
- * @param method
- * @param entryFact
- * @param paramVN
- * @return
- */
public boolean isCaught(ClassContext classContext, Method method, UnconditionalValueDerefSet entryFact, ValueNumber paramVN) {
boolean caught = true;
Set<Location> dereferenceSites
- = entryFact.getDerefLocationSet(paramVN);
+ = entryFact.getDerefLocationSet(paramVN);
if (dereferenceSites != null && !dereferenceSites.isEmpty()) {
ConstantPool cp = classContext.getJavaClass().getConstantPool();
for(Location loc : dereferenceSites) {
- if (!FindNullDeref.catchesNull(cp, method.getCode(), loc))
+ if (!FindNullDeref.catchesNull(cp, method.getCode(), loc)) {
caught = false;
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/CallToUnconditionalThrower.java b/src/java/edu/umd/cs/findbugs/detect/CallToUnconditionalThrower.java
index b5c7ebf..845a24a 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CallToUnconditionalThrower.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CallToUnconditionalThrower.java
@@ -35,6 +35,7 @@ import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.Detector;
import edu.umd.cs.findbugs.MethodAnnotation;
import edu.umd.cs.findbugs.Priorities;
+import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.BasicBlock;
import edu.umd.cs.findbugs.ba.CFG;
@@ -59,23 +60,22 @@ public class CallToUnconditionalThrower extends PreorderVisitor implements Detec
AnalysisContext analysisContext;
+ private final boolean testingEnabled;
+
public CallToUnconditionalThrower(BugReporter bugReporter) {
this.bugReporter = bugReporter;
+ testingEnabled = SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors");
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.Detector#report()
- */
+ @Override
public void report() {
- // TODO Auto-generated method stub
-
+ //
}
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {
- if (BCELUtil.isSynthetic(method) || (method.getAccessFlags() & Constants.ACC_BRIDGE) == Constants.ACC_BRIDGE)
+ if (BCELUtil.isSynthetic(method) || (method.getAccessFlags() & Constants.ACC_BRIDGE) == Constants.ACC_BRIDGE) {
return;
+ }
CFG cfg = classContext.getCFG(method);
ConstantPoolGen cpg = classContext.getConstantPoolGen();
@@ -85,19 +85,22 @@ public class CallToUnconditionalThrower extends PreorderVisitor implements Detec
BasicBlock basicBlock = i.next();
// Check if it's a method invocation.
- if (!basicBlock.isExceptionThrower())
+ if (!basicBlock.isExceptionThrower()) {
continue;
+ }
InstructionHandle thrower = basicBlock.getExceptionThrower();
Instruction ins = thrower.getInstruction();
- if (!(ins instanceof InvokeInstruction))
+ if (!(ins instanceof InvokeInstruction)) {
continue;
+ }
InvokeInstruction inv = (InvokeInstruction) ins;
boolean foundThrower = false;
boolean foundNonThrower = false;
- if (inv instanceof INVOKEINTERFACE)
+ if (inv instanceof INVOKEINTERFACE) {
continue;
+ }
String className = inv.getClassName(cpg);
@@ -108,28 +111,33 @@ public class CallToUnconditionalThrower extends PreorderVisitor implements Detec
Set<XMethod> targetSet = null;
try {
- if (className.startsWith("["))
+ if (className.startsWith("[")) {
continue;
+ }
String methodSig = inv.getSignature(cpg);
- if (!methodSig.endsWith("V"))
+ if (!methodSig.endsWith("V")) {
continue;
+ }
targetSet = Hierarchy2.resolveMethodCallTargets(inv, typeFrame, cpg);
for (XMethod xMethod : targetSet) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\tFound " + xMethod);
+ }
boolean isUnconditionalThrower = xMethod.isUnconditionalThrower() && !xMethod.isUnsupported()
&& !xMethod.isSynthetic();
if (isUnconditionalThrower) {
foundThrower = true;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Found thrower");
+ }
} else {
foundNonThrower = true;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Found non thrower");
+ }
}
}
@@ -137,22 +145,28 @@ public class CallToUnconditionalThrower extends PreorderVisitor implements Detec
analysisContext.getLookupFailureCallback().reportMissingClass(e);
}
boolean newResult = foundThrower && !foundNonThrower;
- if (newResult)
+ if (newResult) {
bugReporter.reportBug(new BugInstance(this, "TESTING", Priorities.NORMAL_PRIORITY)
- .addClassAndMethod(classContext.getJavaClass(), method)
- .addString("Call to method that always throws Exception").addMethod(primaryXMethod)
- .describe(MethodAnnotation.METHOD_CALLED).addSourceLine(classContext, method, loc));
+ .addClassAndMethod(classContext.getJavaClass(), method)
+ .addString("Call to method that always throws Exception").addMethod(primaryXMethod)
+ .describe(MethodAnnotation.METHOD_CALLED).addSourceLine(classContext, method, loc));
+ }
}
}
+ @Override
public void visitClassContext(ClassContext classContext) {
+ if(!testingEnabled){
+ return;
+ }
analysisContext = AnalysisContext.currentAnalysisContext();
Method[] methodList = classContext.getJavaClass().getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
diff --git a/src/java/edu/umd/cs/findbugs/detect/CallToUnsupportedMethod.java b/src/java/edu/umd/cs/findbugs/detect/CallToUnsupportedMethod.java
index 1269e66..cdb1653 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CallToUnsupportedMethod.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CallToUnsupportedMethod.java
@@ -59,13 +59,15 @@ public class CallToUnsupportedMethod implements Detector {
this.bugReporter = bugReporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
Method[] methodList = javaClass.getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -88,9 +90,10 @@ public class CallToUnsupportedMethod implements Detector {
* @param method
*/
private void analyzeMethod(ClassContext classContext, Method method) throws MethodUnprofitableException, CFGBuilderException,
- DataflowAnalysisException {
- if (BCELUtil.isSynthetic(method)|| (method.getAccessFlags() & Constants.ACC_BRIDGE) == Constants.ACC_BRIDGE)
+ DataflowAnalysisException {
+ if (BCELUtil.isSynthetic(method)|| (method.getAccessFlags() & Constants.ACC_BRIDGE) == Constants.ACC_BRIDGE) {
return;
+ }
CFG cfg = classContext.getCFG(method);
TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
ConstantPoolGen constantPoolGen = classContext.getConstantPoolGen();
@@ -101,20 +104,24 @@ public class CallToUnsupportedMethod implements Detector {
Instruction ins = handle.getInstruction();
// Only consider invoke instructions
- if (!(ins instanceof InvokeInstruction))
+ if (!(ins instanceof InvokeInstruction)) {
continue;
- if (ins instanceof INVOKEINTERFACE)
+ }
+ if (ins instanceof INVOKEINTERFACE) {
continue;
+ }
InvokeInstruction inv = (InvokeInstruction) ins;
TypeFrame frame = typeDataflow.getFactAtLocation(location);
String methodName = inv.getMethodName(constantPoolGen);
- if (methodName.toLowerCase().indexOf("unsupported") >= 0)
+ if (methodName.toLowerCase().indexOf("unsupported") >= 0) {
continue;
+ }
String methodSig = inv.getSignature(constantPoolGen);
- if (methodSig.equals("()Ljava/lang/UnsupportedOperationException;"))
+ if ("()Ljava/lang/UnsupportedOperationException;".equals(methodSig)) {
continue;
+ }
Set<XMethod> targets;
try {
@@ -124,19 +131,23 @@ public class CallToUnsupportedMethod implements Detector {
AnalysisContext.reportMissingClass(e);
continue locationLoop;
}
- if (targets.isEmpty())
+ if (targets.isEmpty()) {
continue locationLoop;
+ }
int priority = targets.size() == 1 ? Priorities.HIGH_PRIORITY : Priorities.NORMAL_PRIORITY;
for (XMethod m : targets) {
- if (!m.isUnsupported())
+ if (!m.isUnsupported()) {
continue locationLoop;
+ }
XClass xc = AnalysisContext.currentXFactory().getXClass(m.getClassDescriptor());
- if (!(inv instanceof INVOKESTATIC) && !(m.isFinal() || xc.isFinal()))
+ if (!(inv instanceof INVOKESTATIC) && !(m.isFinal() || xc.isFinal())) {
priority = Priorities.NORMAL_PRIORITY;
+ }
if (xc == null || xc.isAbstract()) {
try {
- if (!AnalysisContext.currentAnalysisContext().getSubtypes2().hasSubtypes(m.getClassDescriptor()))
+ if (!AnalysisContext.currentAnalysisContext().getSubtypes2().hasSubtypes(m.getClassDescriptor())) {
continue locationLoop;
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
continue locationLoop;
@@ -144,8 +155,8 @@ public class CallToUnsupportedMethod implements Detector {
}
}
BugInstance bug = new BugInstance(this, "DMI_UNSUPPORTED_METHOD", priority)
- .addClassAndMethod(classContext.getJavaClass(), method).addCalledMethod(constantPoolGen, inv)
- .addSourceLine(classContext, method, location);
+ .addClassAndMethod(classContext.getJavaClass(), method).addCalledMethod(constantPoolGen, inv)
+ .addSourceLine(classContext, method, location);
bugReporter.reportBug(bug);
}
@@ -154,9 +165,10 @@ public class CallToUnsupportedMethod implements Detector {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector#report()
*/
+ @Override
public void report() {
// TODO Auto-generated method stub
diff --git a/src/java/edu/umd/cs/findbugs/detect/CalledMethods.java b/src/java/edu/umd/cs/findbugs/detect/CalledMethods.java
index 44dc52e..da2b14e 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CalledMethods.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CalledMethods.java
@@ -52,11 +52,13 @@ public class CalledMethods extends BytecodeScanningDetector implements NonReport
if ((seen == PUTFIELD || seen == PUTSTATIC)) {
XField f = getXFieldOperand();
if (f != null) {
- if (f.isFinal() || !f.isProtected() && !f.isPublic())
- if (emptyArrayOnTOS)
+ if (f.isFinal() || !f.isProtected() && !f.isPublic()) {
+ if (emptyArrayOnTOS) {
emptyArray.add(f);
- else
+ } else {
nonEmptyArray.add(f);
+ }
+ }
}
}
@@ -65,8 +67,9 @@ public class CalledMethods extends BytecodeScanningDetector implements NonReport
if (seen == GETSTATIC || seen == GETFIELD) {
XField f = getXFieldOperand();
- if (emptyArray.contains(f) && !nonEmptyArray.contains(f) && f.isFinal())
+ if (emptyArray.contains(f) && !nonEmptyArray.contains(f) && f.isFinal()) {
emptyArrayOnTOS = true;
+ }
}
switch (seen) {
case INVOKEVIRTUAL:
@@ -75,8 +78,9 @@ public class CalledMethods extends BytecodeScanningDetector implements NonReport
case INVOKEINTERFACE:
ClassDescriptor c = getClassDescriptorOperand();
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
- if (subtypes2.isApplicationClass(c))
+ if (subtypes2.isApplicationClass(c)) {
xFactory.addCalledMethod(getMethodDescriptorOperand());
+ }
break;
default:
@@ -87,11 +91,11 @@ public class CalledMethods extends BytecodeScanningDetector implements NonReport
@Override
public void report() {
emptyArray.removeAll(nonEmptyArray);
- for (XField f : emptyArray)
+ for (XField f : emptyArray) {
xFactory.addEmptyArrayField(f);
+ }
emptyArray.clear();
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/CbeckMustOverrideSuperAnnotation.java b/src/java/edu/umd/cs/findbugs/detect/CbeckMustOverrideSuperAnnotation.java
index c00be83..a003ac0 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CbeckMustOverrideSuperAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CbeckMustOverrideSuperAnnotation.java
@@ -26,6 +26,7 @@ import org.apache.bcel.classfile.Code;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.Lookup;
+import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
@@ -38,39 +39,50 @@ public class CbeckMustOverrideSuperAnnotation extends OpcodeStackDetector {
ClassDescriptor mustOverrideAnnotation = DescriptorFactory.createClassDescriptor(OverridingMethodsMustInvokeSuper.class);
+ private final boolean testingEnabled;
+
public CbeckMustOverrideSuperAnnotation(BugReporter bugReporter) {
this.bugReporter = bugReporter;
+ testingEnabled = SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors");
}
private boolean sawCallToSuper;
@Override
public void visit(Code code) {
- if (getMethod().isStatic() || getMethod().isPrivate())
+ if(!testingEnabled){
+ return;
+ }
+ if (getMethod().isStatic() || getMethod().isPrivate()) {
return;
+ }
XMethod overrides = Lookup.findSuperImplementorAsXMethod(getThisClass(), getMethodName(), getMethodSig(), bugReporter);
- if (overrides == null)
+ if (overrides == null) {
return;
+ }
AnnotationValue annotation = overrides.getAnnotation(mustOverrideAnnotation);
- if (annotation == null)
+ if (annotation == null) {
return;
+ }
sawCallToSuper = false;
super.visit(code);
- if (!sawCallToSuper)
+ if (!sawCallToSuper) {
bugReporter.reportBug(new BugInstance(this, "TESTING", NORMAL_PRIORITY).addClassAndMethod(this).addString(
"Method must invoke override method in superclass"));
+ }
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.bcel.OpcodeStackDetector#sawOpcode(int)
*/
@Override
public void sawOpcode(int seen) {
- if (seen != INVOKESPECIAL)
+ if (seen != INVOKESPECIAL) {
return;
+ }
String calledClassName = getClassConstantOperand();
String calledMethodName = getNameConstantOperand();
diff --git a/src/java/edu/umd/cs/findbugs/detect/CheckAnalysisContextContainedAnnotation.java b/src/java/edu/umd/cs/findbugs/detect/CheckAnalysisContextContainedAnnotation.java
index 10169ba..1f8aa57 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CheckAnalysisContextContainedAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CheckAnalysisContextContainedAnnotation.java
@@ -29,6 +29,7 @@ import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.OpcodeStack;
import edu.umd.cs.findbugs.OpcodeStack.Item;
import edu.umd.cs.findbugs.OpcodeStack.JumpInfo;
+import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.ba.XClass;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
@@ -44,9 +45,12 @@ public class CheckAnalysisContextContainedAnnotation extends OpcodeStackDetector
final BugAccumulator accumulator;
+ private final boolean testingEnabled;
+
public CheckAnalysisContextContainedAnnotation(BugReporter bugReporter) {
this.bugReporter = bugReporter;
this.accumulator = new BugAccumulator(bugReporter);
+ testingEnabled = SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors");
}
final static ClassDescriptor ConstantAnnotation = DescriptorFactory.createClassDescriptor(StaticConstant.class);
@@ -56,8 +60,9 @@ public class CheckAnalysisContextContainedAnnotation extends OpcodeStackDetector
private boolean analysisContextContained(XClass xclass) {
AnnotatedObject ao = xclass;
do {
- if (ao.getAnnotation(AnalysisContextContainedAnnotation) != null)
+ if (ao.getAnnotation(AnalysisContextContainedAnnotation) != null) {
return true;
+ }
ao = ao.getContainingScope();
} while (ao != null);
@@ -66,23 +71,24 @@ public class CheckAnalysisContextContainedAnnotation extends OpcodeStackDetector
}
@Override
public void visit(Field field) {
- if (!field.isStatic())
- return;
- String signature = field.getSignature();
- if (signature.startsWith("Ljava/util/") && !signature.equals("Ljava/util/regex/Pattern;")
- && !signature.equals("Ljava/util/logging/Logger;") && !signature.equals("Ljava/util/BitSet;")
- && !signature.equals("Ljava/util/ResourceBundle;")
- && !signature.equals("Ljava/util/Comparator;")
- && getXField().getAnnotation(ConstantAnnotation) == null) {
- boolean flagged = analysisContextContained(getXClass());
-
- bugReporter.reportBug(new BugInstance(this, "TESTING", flagged ? NORMAL_PRIORITY : LOW_PRIORITY).addClass(this).addField(this).addType(signature));
-
- }
+ if (!field.isStatic()) {
+ return;
+ }
+ String signature = field.getSignature();
+ if (signature.startsWith("Ljava/util/") && !"Ljava/util/regex/Pattern;".equals(signature)
+ && !"Ljava/util/logging/Logger;".equals(signature) && !"Ljava/util/BitSet;".equals(signature)
+ && !"Ljava/util/ResourceBundle;".equals(signature)
+ && !"Ljava/util/Comparator;".equals(signature)
+ && getXField().getAnnotation(ConstantAnnotation) == null) {
+ boolean flagged = analysisContextContained(getXClass());
+
+ bugReporter.reportBug(new BugInstance(this, "TESTING", flagged ? NORMAL_PRIORITY : LOW_PRIORITY).addClass(this).addField(this).addType(signature));
+
+ }
}
@Override
public void visit(Code code) {
- boolean interesting = false;
+ boolean interesting = testingEnabled;
if (interesting) {
// initialize any variables we want to initialize for the method
super.visit(code); // make callbacks to sawOpcode for all opcodes
@@ -99,10 +105,11 @@ public class CheckAnalysisContextContainedAnnotation extends OpcodeStackDetector
case Constants.IF_ICMPNE:
OpcodeStack.Item left = stack.getStackItem(1);
OpcodeStack.Item right = stack.getStackItem(0);
- if (bad(left, right) || bad(right, left))
+ if (bad(left, right) || bad(right, left)) {
accumulator.accumulateBug(new BugInstance(this, "TESTING", NORMAL_PRIORITY).addClassAndMethod(this)
.addValueSource(left, this).addValueSource(right, this)
.addString("Just check the sign of the result of compare or compareTo, not specific values such as 1 or -1"), this);
+ }
break;
}
@@ -111,18 +118,23 @@ public class CheckAnalysisContextContainedAnnotation extends OpcodeStackDetector
private boolean bad(Item left, Item right) {
XMethod m = left.getReturnValueOf();
- if (m == null)
+ if (m == null) {
return false;
+ }
Object value = right.getConstant();
- if (!(value instanceof Integer) || ((Integer) value).intValue() == 0)
+ if (!(value instanceof Integer) || ((Integer) value).intValue() == 0) {
return false;
- if (m.isStatic() || !m.isPublic())
+ }
+ if (m.isStatic() || !m.isPublic()) {
return false;
+ }
- if (m.getName().equals("compareTo") && m.getSignature().equals("(Ljava/lang/Object;)I"))
+ if ("compareTo".equals(m.getName()) && "(Ljava/lang/Object;)I".equals(m.getSignature())) {
return true;
- if (m.getName().equals("compare") && m.getSignature().equals("(Ljava/lang/Object;Ljava/lang/Object;)I"))
+ }
+ if ("compare".equals(m.getName()) && "(Ljava/lang/Object;Ljava/lang/Object;)I".equals(m.getSignature())) {
return true;
+ }
return false;
diff --git a/src/java/edu/umd/cs/findbugs/detect/CheckCalls.java b/src/java/edu/umd/cs/findbugs/detect/CheckCalls.java
index b9f5000..aa1e0af 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CheckCalls.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CheckCalls.java
@@ -41,7 +41,7 @@ import edu.umd.cs.findbugs.ba.SignatureConverter;
/**
* This is just for debugging method call resolution.
- *
+ *
* @author David Hovemeyer
*/
public class CheckCalls implements Detector, NonReportingDetector {
@@ -58,20 +58,23 @@ public class CheckCalls implements Detector, NonReportingDetector {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.Detector#visitClassContext(edu.umd.cs.findbugs.ba
* .ClassContext)
*/
+ @Override
public void visitClassContext(ClassContext classContext) {
Method[] methodList = classContext.getJavaClass().getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
// System.out.println("--> " + method.getName());
- if (METHOD != null && !method.getName().equals(METHOD))
+ if (METHOD != null && !method.getName().equals(METHOD)) {
continue;
+ }
try {
System.out.println("Analyzing " + SignatureConverter.convertMethodSignature(classContext.getJavaClass(), method));
@@ -87,7 +90,7 @@ public class CheckCalls implements Detector, NonReportingDetector {
}
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, ClassNotFoundException,
- DataflowAnalysisException {
+ DataflowAnalysisException {
CFG cfg = classContext.getCFG(method);
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
@@ -95,8 +98,9 @@ public class CheckCalls implements Detector, NonReportingDetector {
if (ins instanceof InvokeInstruction) {
if (TARGET_METHOD != null
- && !((InvokeInstruction) ins).getMethodName(classContext.getConstantPoolGen()).equals(TARGET_METHOD))
+ && !((InvokeInstruction) ins).getMethodName(classContext.getConstantPoolGen()).equals(TARGET_METHOD)) {
continue;
+ }
System.out.println("\n*******************************************************\n");
@@ -121,9 +125,10 @@ public class CheckCalls implements Detector, NonReportingDetector {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector#report()
*/
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/CheckExpectedWarnings.java b/src/java/edu/umd/cs/findbugs/detect/CheckExpectedWarnings.java
index d2c2d93..d701611 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CheckExpectedWarnings.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CheckExpectedWarnings.java
@@ -26,7 +26,6 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.StringTokenizer;
import javax.annotation.CheckForNull;
@@ -64,8 +63,6 @@ import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
import edu.umd.cs.findbugs.classfile.analysis.AnnotationValue;
import edu.umd.cs.findbugs.classfile.analysis.EnumValue;
-import edu.umd.cs.findbugs.plan.AnalysisPass;
-import edu.umd.cs.findbugs.plan.ExecutionPlan;
/**
* Check uses of the ExpectWarning and NoWarning annotations. This is for
@@ -80,8 +77,6 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
private final BugCollection bugCollection;
- private Set<String> possibleBugCodes;
-
private boolean initialized = false;
private Map<ClassDescriptor, Collection<BugInstance>> warningsByClass;
private Map<MethodDescriptor, Collection<BugInstance>> warningsByMethod;
@@ -108,11 +103,12 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
}
}
+ @Override
public void visitClass(ClassDescriptor classDescriptor) throws CheckedAnalysisException {
if (reporter == null) {
if (!warned) {
System.err
- .println("*** NOTE ***: CheckExpectedWarnings disabled because bug reporter doesn't use a BugCollection");
+ .println("*** NOTE ***: CheckExpectedWarnings disabled because bug reporter doesn't use a BugCollection");
warned = true;
}
return;
@@ -146,8 +142,9 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
}
FieldAnnotation field = warning.getPrimaryField();
if (field != null) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("primary field of " + field + " for " + warning);
+ }
FieldDescriptor fieldDescriptor = field.toFieldDescriptor();
Collection<BugInstance> warnings = warningsByField.get(fieldDescriptor);
@@ -157,46 +154,26 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
}
warnings.add(warning);
}
- if(field == null && method == null){
- ClassAnnotation clazz = warning.getPrimaryClass();
- if (clazz != null) {
- ClassDescriptor classDesc = clazz.getClassDescriptor();
- Collection<BugInstance> warnings = warningsByClass.get(classDesc);
- if (warnings == null) {
- warnings = new LinkedList<BugInstance>();
- warningsByClass.put(classDesc, warnings);
- }
- warnings.add(warning);
- }
- }
- }
-
- //
- // Based on enabled detectors, figure out which bug codes
- // could possibly be reported. Don't complain about
- // expected warnings that would be produced by detectors
- // that aren't enabled.
- //
- possibleBugCodes = new HashSet<String>();
- ExecutionPlan executionPlan = Global.getAnalysisCache().getDatabase(ExecutionPlan.class);
- Iterator<AnalysisPass> i = executionPlan.passIterator();
- while (i.hasNext()) {
- AnalysisPass pass = i.next();
- Iterator<DetectorFactory> j = pass.iterator();
- while (j.hasNext()) {
- DetectorFactory factory = j.next();
-
- Collection<BugPattern> reportedPatterns = factory.getReportedBugPatterns();
- for (BugPattern pattern : reportedPatterns) {
- possibleBugCodes.add(pattern.getType());
- possibleBugCodes.add(pattern.getAbbrev());
+ ClassAnnotation clazz = warning.getPrimaryClass();
+ if (clazz != null) {
+ ClassDescriptor classDesc = clazz.getClassDescriptor();
+ if(field != null && classDesc.equals(field.getClassDescriptor())) {
+ continue;
}
+ if (method != null && classDesc.equals(method.getClassDescriptor())) {
+ continue;
+ }
+ Collection<BugInstance> warnings = warningsByClass.get(classDesc);
+ if (warnings == null) {
+ warnings = new LinkedList<BugInstance>();
+ warningsByClass.put(classDesc, warnings);
+ }
+ warnings.add(warning);
}
+
}
- if (DEBUG) {
- System.out.println("CEW: possible warnings are " + possibleBugCodes);
- }
+
}
XClass xclass = Global.getAnalysisCache().getClassAnalysis(XClass.class, classDescriptor);
@@ -204,6 +181,12 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
if (DEBUG) {
System.out.println("CEW: checking " + xclass.toString());
}
+ if (xclass.isSynthetic()) {
+ if (DEBUG) {
+ System.out.println("Skipping synthetic classxclass " + xclass.toString());
+ }
+ return;
+ }
check(xclass, expectWarning, true, HIGH_PRIORITY);
check(xclass, desireWarning, true, NORMAL_PRIORITY);
check(xclass, noWarning, false, HIGH_PRIORITY);
@@ -213,6 +196,12 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
if (DEBUG) {
System.out.println("CEW: checking " + xmethod.toString());
}
+ if (xmethod.isSynthetic()) {
+ if (DEBUG) {
+ System.out.println("Skipping synthetic method " + xmethod.toString());
+ }
+ continue;
+ }
check(xmethod, expectWarning, true, HIGH_PRIORITY);
check(xmethod, desireWarning, true, NORMAL_PRIORITY);
check(xmethod, noWarning, false, HIGH_PRIORITY);
@@ -222,6 +211,12 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
if (DEBUG) {
System.out.println("CEW: checking " + xfield.toString());
}
+ if (xfield.isSynthetic()) {
+ if (DEBUG) {
+ System.out.println("Skipping synthetic field " + xfield.toString());
+ }
+ continue;
+ }
check(xfield, expectWarning, true, HIGH_PRIORITY);
check(xfield, desireWarning, true, NORMAL_PRIORITY);
check(xfield, noWarning, false, HIGH_PRIORITY);
@@ -232,8 +227,9 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
private void check(XClass xclass, ClassDescriptor annotation, boolean expectWarnings, int priority) {
AnnotationValue expect = xclass.getAnnotation(annotation);
- if (expect == null)
+ if (expect == null) {
return;
+ }
if (DEBUG) {
System.out.println("*** Found " + annotation + " annotation on " + xclass);
}
@@ -244,8 +240,9 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
private void check(XMethod xmethod, ClassDescriptor annotation, boolean expectWarnings, int priority) {
AnnotationValue expect = xmethod.getAnnotation(annotation);
- if (expect == null)
+ if (expect == null) {
return;
+ }
if (DEBUG) {
System.out.println("*** Found " + annotation + " annotation on " + xmethod);
}
@@ -256,8 +253,9 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
private void check(XField xfield, ClassDescriptor annotation, boolean expectWarnings, int priority) {
AnnotationValue expect = xfield.getAnnotation(annotation);
- if (expect == null)
+ if (expect == null) {
return;
+ }
if (DEBUG) {
System.out.println("*** Found " + annotation + " annotation on " + xfield);
@@ -276,22 +274,25 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
EnumValue wantedConfidence = (EnumValue) expect.getValue("confidence");
EnumValue wantedPriority = (EnumValue) expect.getValue("priority");
Integer num = (Integer) expect.getValue("num");
- if (num == null)
+ if (num == null) {
num = (expectWarnings ? 1 : 0);
+ }
Integer rank = (Integer) expect.getValue("rank");
- if (rank == null)
+ if (rank == null) {
rank = BugRanker.VISIBLE_RANK_MAX;
+ }
int minPriority = Confidence.LOW.getConfidenceValue();
- if (wantedConfidence != null)
+ if (wantedConfidence != null) {
minPriority = Confidence.valueOf(wantedConfidence.value).getConfidenceValue();
- else if (wantedPriority != null)
+ } else if (wantedPriority != null) {
minPriority = Priority.valueOf(wantedPriority.value).getPriorityValue();
+ }
if (DEBUG) {
- if (warnings == null)
+ if (warnings == null) {
System.out.println("Checking " + expectedBugCodes + " against no bugs");
- else {
+ } else {
System.out.println("Checking " + expectedBugCodes + " against " + warnings.size() + " bugs");
for (BugInstance b : warnings) {
System.out.println(" " + b.getType());
@@ -304,8 +305,6 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
StringTokenizer tok = new StringTokenizer(expectedBugCodes, ",");
while (tok.hasMoreTokens()) {
String bugCode = tok.nextToken().trim();
- if (!possibleBugCodes.contains(bugCode))
- continue;
checkAnnotation(bugCode, warnings, expectWarnings, priority, rank, num, descriptor, minPriority, cd);
}
}
@@ -319,18 +318,24 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
Collection<SourceLineAnnotation> bugs = countWarnings(warnings, bugCode, minPriority,
rank);
if (expectWarnings && bugs.size() < num) {
+ if (DetectorFactoryCollection.instance().isDisabledByDefault(bugCode)) {
+ return;
+ }
BugInstance bug = makeWarning("FB_MISSING_EXPECTED_WARNING", methodDescriptor, priority, cd).addString(bugCodeMessage);
if (!bugs.isEmpty()) {
bug.addString(String.format("Expected %d bugs, saw %d", num, bugs.size()));
}
reporter.reportBug(bug);
} else if (bugs.size() > num) {
+ // More bugs than expected
BugInstance bug = makeWarning("FB_UNEXPECTED_WARNING", methodDescriptor, priority, cd).addString(bugCodeMessage);
if (!expectWarnings) {
+ // Wanted no more than this many warnings
for (SourceLineAnnotation s : bugs) {
reporter.reportBug(bug.add(s));
}
} else if(num > 1){
+ // For example, we told it that we expected 3 warnings, and saw 4 warnings
// num == 1 is default value. So if we set a non default value, and see more warnings
// as expected, it's a problem
bug.addString(String.format("Expected %d bugs, saw %d", num, bugs.size()));
@@ -339,22 +344,18 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
}
}
- /**
- * @param bugPattern
- * @param methodDescriptor
- * @param priority
- * @return
- */
public BugInstance makeWarning(String bugPattern, Object descriptor, int priority, ClassDescriptor cd) {
BugInstance bug = new BugInstance(this, bugPattern, priority).addClass(cd);
- if (descriptor instanceof FieldDescriptor)
+ if (descriptor instanceof FieldDescriptor) {
bug.addField((FieldDescriptor)descriptor);
- else if (descriptor instanceof MethodDescriptor)
+ } else if (descriptor instanceof MethodDescriptor) {
bug.addMethod((MethodDescriptor)descriptor);
- else if (descriptor instanceof ClassDescriptor)
+ } else if (descriptor instanceof ClassDescriptor) {
bug.addClass((ClassDescriptor)descriptor);
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("Reporting " + bug);
+ }
return bug;
}
@@ -362,6 +363,7 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
private static Collection<SourceLineAnnotation> countWarnings( Collection<BugInstance> warnings,
@CheckForNull String bugCode,
int desiredPriority, int rank) {
+
Collection<SourceLineAnnotation> matching = new HashSet<SourceLineAnnotation>();
DetectorFactoryCollection i18n = DetectorFactoryCollection.instance();
boolean matchPattern = false;
@@ -373,40 +375,50 @@ public class CheckExpectedWarnings implements Detector2, NonReportingDetector {
if (warnings != null) {
for (BugInstance warning : warnings) {
- if (warning.getPriority() > desiredPriority)
+ if (warning.getPriority() > desiredPriority) {
continue;
- if (warning.getBugRank() > rank)
+ }
+ if (warning.getBugRank() > rank) {
continue;
+ }
if (bugCode == null) {
matching.add(warning.getPrimarySourceLineAnnotation());
+ matching.addAll(warning.getAnotherInstanceSourceLineAnnotations());
continue;
}
BugPattern pattern = warning.getBugPattern();
String match;
- if (matchPattern)
+ if (matchPattern) {
match = pattern.getType();
- else
+ } else {
match = pattern.getAbbrev();
+ }
if (match.equals(bugCode)) {
matching.add(warning.getPrimarySourceLineAnnotation());
+ matching.addAll(warning.getAnotherInstanceSourceLineAnnotations());
+
}
}
}
return matching;
}
+ @Override
public void finishPass() {
HashSet<BugPattern> claimedReported = new HashSet<BugPattern>();
- for (DetectorFactory d : DetectorFactoryCollection.instance().getFactories())
+ for (DetectorFactory d : DetectorFactoryCollection.instance().getFactories()) {
claimedReported.addAll(d.getReportedBugPatterns());
+ }
for (BugPattern b : DetectorFactoryCollection.instance().getBugPatterns()) {
String category = b.getCategory();
- if (!b.isDeprecated() && !category.equals("EXPERIMENTAL") && !claimedReported.contains(b))
+ if (!b.isDeprecated() && !"EXPERIMENTAL".equals(category) && !claimedReported.contains(b)) {
AnalysisContext.logError("No detector claims " + b.getType());
+ }
}
}
+ @Override
public String getDetectorClassName() {
return CheckExpectedWarnings.class.getName();
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/CheckImmutableAnnotation.java b/src/java/edu/umd/cs/findbugs/detect/CheckImmutableAnnotation.java
index cc86f83..65645e4 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CheckImmutableAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CheckImmutableAnnotation.java
@@ -41,21 +41,25 @@ public class CheckImmutableAnnotation extends PreorderVisitor implements Detecto
@Override
public void visitJavaClass(JavaClass obj) {
JCIPAnnotationDatabase jcipAnotationDatabase = AnalysisContext.currentAnalysisContext().getJCIPAnnotationDatabase();
- if (jcipAnotationDatabase.hasClassAnnotation(obj.getClassName().replace('/', '.'), "Immutable"))
+ if (jcipAnotationDatabase.hasClassAnnotation(obj.getClassName().replace('/', '.'), "Immutable")) {
super.visitJavaClass(obj);
+ }
}
@Override
public void visit(Field obj) {
- if (!obj.isFinal() && !obj.isTransient() && !obj.isVolatile())
+ if (!obj.isFinal() && !obj.isTransient() && !obj.isVolatile()) {
bugReporter.reportBug(new BugInstance(this, "JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS", NORMAL_PRIORITY).addClass(
this).addVisitedField(this));
+ }
}
+ @Override
public void report() {
}
+ @Override
public void visitClassContext(ClassContext classContext) {
classContext.getJavaClass().accept(this);
diff --git a/src/java/edu/umd/cs/findbugs/detect/CheckRelaxingNullnessAnnotation.java b/src/java/edu/umd/cs/findbugs/detect/CheckRelaxingNullnessAnnotation.java
index 361747e..3e72f2f 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CheckRelaxingNullnessAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CheckRelaxingNullnessAnnotation.java
@@ -19,8 +19,7 @@
package edu.umd.cs.findbugs.detect;
-import static edu.umd.cs.findbugs.ba.NullnessAnnotation.CHECK_FOR_NULL;
-import static edu.umd.cs.findbugs.ba.NullnessAnnotation.NONNULL;
+import static edu.umd.cs.findbugs.ba.NullnessAnnotation.*;
import static org.objectweb.asm.Opcodes.ACC_STATIC;
import java.util.Arrays;
@@ -58,6 +57,7 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
import edu.umd.cs.findbugs.classfile.analysis.AnnotationValue;
+import edu.umd.cs.findbugs.classfile.engine.asm.FindBugsASM;
import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
import edu.umd.cs.findbugs.util.ClassName;
@@ -123,23 +123,22 @@ public class CheckRelaxingNullnessAnnotation extends ClassNodeDetector {
private Map<Integer, NullnessAnnotation> nonNullParameter;
- private boolean checkForNullReturn;
+ private boolean relaxedNullReturn;
DetectorNode(int access, String name, String desc, String signature, String[] exceptions, XMethod xmethod) {
- super(access, name, desc, signature, exceptions);
+ super(FindBugsASM.ASM_VERSION, access, name, desc, signature, exceptions);
this.xmethod = xmethod;
}
- @SuppressWarnings("unchecked")
@Override
public void visitEnd() {
super.visitEnd();
// 1 test if we have suspicious annotations on method or parameters
- checkForNullReturn = containsCheckForNull(visibleAnnotations);
- if(!checkForNullReturn){
- checkForNullReturn = containsCheckForNull(invisibleAnnotations);
+ relaxedNullReturn = containsRelaxedNonNull(visibleAnnotations);
+ if(!relaxedNullReturn){
+ relaxedNullReturn = containsRelaxedNonNull(invisibleAnnotations);
}
- boolean needsCheck = checkForNullReturn;
+ boolean needsCheck = relaxedNullReturn;
if (invisibleParameterAnnotations != null || visibleParameterAnnotations != null) {
nonNullParameter = getNonnullOrNullableParams(visibleParameterAnnotations);
Map<Integer, NullnessAnnotation> nnp = getNonnullOrNullableParams(invisibleParameterAnnotations);
@@ -186,7 +185,7 @@ public class CheckRelaxingNullnessAnnotation extends ClassNodeDetector {
private final boolean checkMethod(@Nonnull XMethod method) {
boolean foundAny = false;
- if (checkForNullReturn && containsNullness(method.getAnnotations(), NONNULL)) {
+ if (relaxedNullReturn && containsNullness(method.getAnnotations(), NONNULL)) {
BugInstance bug = new BugInstance(CheckRelaxingNullnessAnnotation.this, "NP_METHOD_RETURN_RELAXING_ANNOTATION",
HIGH_PRIORITY);
bug.addClassAndMethod(xmethod);
@@ -199,11 +198,11 @@ public class CheckRelaxingNullnessAnnotation extends ClassNodeDetector {
if (containsNullness(method.getParameterAnnotations(i), CHECK_FOR_NULL)) {
NullnessAnnotation a = e.getValue();
BugInstance bug = new BugInstance(CheckRelaxingNullnessAnnotation.this,
- "NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION", a.equals(NONNULL) ? HIGH_PRIORITY : NORMAL_PRIORITY);
- bug.addClassAndMethod(xmethod);
+ "NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION", a.equals(NONNULL) ? HIGH_PRIORITY : NORMAL_PRIORITY);
+ bug.addClassAndMethod(xmethod);
LocalVariableAnnotation lva = null;
if (localVariables != null) {
- for(LocalVariableNode lvn : (List<LocalVariableNode>)localVariables) {
+ for(LocalVariableNode lvn : localVariables) {
if (lvn.index == i+1) {
lva = new LocalVariableAnnotation(lvn.name, i+1, 0);
lva.setDescription(LocalVariableAnnotation.PARAMETER_NAMED_ROLE);
@@ -262,13 +261,13 @@ public class CheckRelaxingNullnessAnnotation extends ClassNodeDetector {
}
}
- static boolean containsCheckForNull(@CheckForNull List<AnnotationNode> methodAnnotations) {
+ static boolean containsRelaxedNonNull(@CheckForNull List<AnnotationNode> methodAnnotations) {
if (methodAnnotations == null) {
return false;
}
for (AnnotationNode annotation : methodAnnotations) {
NullnessAnnotation nullness = getNullness(annotation.desc);
- if (nullness == CHECK_FOR_NULL) {
+ if (nullness == CHECK_FOR_NULL || nullness == NULLABLE) {
return true;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/CheckTypeQualifiers.java b/src/java/edu/umd/cs/findbugs/detect/CheckTypeQualifiers.java
index 532e1f6..7c9d574 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CheckTypeQualifiers.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CheckTypeQualifiers.java
@@ -124,15 +124,18 @@ public class CheckTypeQualifiers extends CFGDetector {
int size = allKnownTypeQualifiers.size();
if (size == 1) {
TypeQualifierValue<?> value = Util.first(allKnownTypeQualifiers);
- if (!value.typeQualifier.getClassName().equals(NONNULL_ANNOTATION))
+ if (!value.typeQualifier.getClassName().equals(NONNULL_ANNOTATION)) {
shouldRunAnalysis = true;
+ }
- } else if (size > 1)
+ } else if (size > 1) {
shouldRunAnalysis = true;
+ }
}
- if (shouldRunAnalysis)
+ if (shouldRunAnalysis) {
super.visitClass(classDescriptor);
+ }
}
/*
@@ -148,8 +151,9 @@ public class CheckTypeQualifiers extends CFGDetector {
return;
}
- if (methodDescriptor.getName().startsWith("access$"))
+ if (methodDescriptor.getName().startsWith("access$")) {
return;
+ }
XMethod xMethod = XFactory.createXMethod(methodDescriptor);
if (DEBUG) {
@@ -158,11 +162,13 @@ public class CheckTypeQualifiers extends CFGDetector {
Collection<TypeQualifierValue<?>> relevantQualifiers = Analysis.getRelevantTypeQualifiers(methodDescriptor, cfg);
for(Iterator<TypeQualifierValue<?>> i = relevantQualifiers.iterator(); i.hasNext(); ) {
- if (i.next().getTypeQualifierClassDescriptor().getClassName().equals(NONNULL_ANNOTATION))
+ if (i.next().getTypeQualifierClassDescriptor().getClassName().equals(NONNULL_ANNOTATION)) {
i.remove();
+ }
}
- if (relevantQualifiers.isEmpty())
+ if (relevantQualifiers.isEmpty()) {
return;
+ }
if (DEBUG) {
System.out.println(" Relevant type qualifiers are " + relevantQualifiers);
}
@@ -173,7 +179,7 @@ public class CheckTypeQualifiers extends CFGDetector {
BackwardTypeQualifierDataflowFactory.class, methodDescriptor);
ValueNumberDataflow vnaDataflow = analysisCache.getMethodAnalysis(ValueNumberDataflow.class, methodDescriptor);
- for (TypeQualifierValue typeQualifierValue : relevantQualifiers) {
+ for (TypeQualifierValue<?> typeQualifierValue : relevantQualifiers) {
try {
checkQualifier(xMethod, cfg, typeQualifierValue, forwardDataflowFactory, backwardDataflowFactory,
@@ -207,10 +213,10 @@ public class CheckTypeQualifiers extends CFGDetector {
* @param vnaDataflow
* ValueNumberDataflow for the method
*/
- private void checkQualifier(XMethod xmethod, CFG cfg, TypeQualifierValue typeQualifierValue,
+ private void checkQualifier(XMethod xmethod, CFG cfg, TypeQualifierValue<?> typeQualifierValue,
ForwardTypeQualifierDataflowFactory forwardDataflowFactory,
BackwardTypeQualifierDataflowFactory backwardDataflowFactory, ValueNumberDataflow vnaDataflow)
- throws CheckedAnalysisException {
+ throws CheckedAnalysisException {
if (DEBUG) {
System.out.println("----------------------------------------------------------------------");
@@ -227,10 +233,10 @@ public class CheckTypeQualifiers extends CFGDetector {
DataflowCFGPrinter<ValueNumberFrame, ValueNumberAnalysis> p = new DataflowCFGPrinter<ValueNumberFrame, ValueNumberAnalysis>(vnaDataflow);
p.print(System.out);
}
-
+
ForwardTypeQualifierDataflow forwardDataflow = forwardDataflowFactory.getDataflow(typeQualifierValue);
- if (DEBUG_DATAFLOW && (DEBUG_DATAFLOW_MODE.startsWith("forward") || DEBUG_DATAFLOW_MODE.equals("both"))) {
+ if (DEBUG_DATAFLOW && (DEBUG_DATAFLOW_MODE.startsWith("forward") || "both".equals(DEBUG_DATAFLOW_MODE))) {
System.out.println("********* Forwards analysis *********");
DataflowCFGPrinter<TypeQualifierValueSet, ForwardTypeQualifierDataflowAnalysis> p = new DataflowCFGPrinter<TypeQualifierValueSet, ForwardTypeQualifierDataflowAnalysis>(
forwardDataflow);
@@ -239,7 +245,7 @@ public class CheckTypeQualifiers extends CFGDetector {
BackwardTypeQualifierDataflow backwardDataflow = backwardDataflowFactory.getDataflow(typeQualifierValue);
- if (DEBUG_DATAFLOW && (DEBUG_DATAFLOW_MODE.startsWith("backward") || DEBUG_DATAFLOW_MODE.equals("both"))) {
+ if (DEBUG_DATAFLOW && (DEBUG_DATAFLOW_MODE.startsWith("backward") || "both".equals(DEBUG_DATAFLOW_MODE))) {
System.out.println("********* Backwards analysis *********");
DataflowCFGPrinter<TypeQualifierValueSet, BackwardTypeQualifierDataflowAnalysis> p = new DataflowCFGPrinter<TypeQualifierValueSet, BackwardTypeQualifierDataflowAnalysis>(
backwardDataflow);
@@ -250,7 +256,7 @@ public class CheckTypeQualifiers extends CFGDetector {
checkValueSources(xmethod, cfg, typeQualifierValue, vnaDataflow, forwardDataflow, backwardDataflow);
}
- private void checkDataflow(XMethod xmethod, CFG cfg, TypeQualifierValue typeQualifierValue,
+ private void checkDataflow(XMethod xmethod, CFG cfg, TypeQualifierValue<?> typeQualifierValue,
ValueNumberDataflow vnaDataflow, ForwardTypeQualifierDataflow forwardDataflow,
BackwardTypeQualifierDataflow backwardDataflow) throws DataflowAnalysisException, CheckedAnalysisException {
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
@@ -311,7 +317,7 @@ public class CheckTypeQualifiers extends CFGDetector {
}
- private void checkForEqualityTest(XMethod xmethod, CFG cfg, TypeQualifierValue typeQualifierValue,
+ private void checkForEqualityTest(XMethod xmethod, CFG cfg, TypeQualifierValue<?> typeQualifierValue,
TypeQualifierValueSet forwardsFact, Location loc, ValueNumberFrame factAtLocation) throws DataflowAnalysisException {
InstructionHandle handle = loc.getHandle();
Instruction ins = handle.getInstruction();
@@ -322,29 +328,35 @@ public class CheckTypeQualifiers extends CFGDetector {
isTest = true;
} else if (ins instanceof InvokeInstruction && ins.consumeStack(cpg) == 2) {
InvokeInstruction invoke = (InvokeInstruction) ins;
- isTest = invoke.getMethodName(cpg).equals("equals") &&invoke.getSignature(cpg).equals("(Ljava/lang/Object;)Z") ;
+ isTest = "equals".equals(invoke.getMethodName(cpg)) &&"(Ljava/lang/Object;)Z".equals(invoke.getSignature(cpg)) ;
}
if (isTest) {
ValueNumber top = factAtLocation.getStackValue(0);
- if (top.hasFlag(ValueNumber.CONSTANT_VALUE))
+ if (top.hasFlag(ValueNumber.CONSTANT_VALUE)) {
return;
+ }
ValueNumber next = factAtLocation.getStackValue(1);
- if (next.hasFlag(ValueNumber.CONSTANT_VALUE))
+ if (next.hasFlag(ValueNumber.CONSTANT_VALUE)) {
return;
+ }
FlowValue topTQ = forwardsFact.getValue(top);
FlowValue nextTQ = forwardsFact.getValue(next);
if (DEBUG) {
System.out.println("Comparing values at " + loc.toCompactString());
System.out.println(" Comparing " + topTQ + " and " + nextTQ);
}
- if (topTQ.equals(nextTQ)) return;
+ if (topTQ.equals(nextTQ)) {
+ return;
+ }
if (FlowValue.valuesConflict(typeQualifierValue.isStrictQualifier() && !xmethod.isIdentity(), topTQ, nextTQ)) {
BugInstance warning = new BugInstance(this,"TQ_COMPARING_VALUES_WITH_INCOMPATIBLE_TYPE_QUALIFIERS", HIGH_PRIORITY).addClassAndMethod(xmethod);
annotateWarningWithTypeQualifier(warning, typeQualifierValue);
- for(SourceSinkInfo s : forwardsFact.getWhere(top))
- annotateWarningWithSourceSinkInfo(warning, xmethod, top, s);
- for(SourceSinkInfo s : forwardsFact.getWhere(next))
+ for(SourceSinkInfo s : forwardsFact.getWhere(top)) {
+ annotateWarningWithSourceSinkInfo(warning, xmethod, top, s);
+ }
+ for(SourceSinkInfo s : forwardsFact.getWhere(next)) {
annotateWarningWithSourceSinkInfo(warning, xmethod, next, s);
+ }
SourceLineAnnotation observedLocation = SourceLineAnnotation.fromVisitedInstruction(xmethod.getMethodDescriptor(),
loc);
warning.add(observedLocation);
@@ -358,7 +370,7 @@ public class CheckTypeQualifiers extends CFGDetector {
}
- private void checkValueSources(XMethod xMethod, CFG cfg, TypeQualifierValue typeQualifierValue,
+ private void checkValueSources(XMethod xMethod, CFG cfg, TypeQualifierValue<?> typeQualifierValue,
ValueNumberDataflow vnaDataflow, ForwardTypeQualifierDataflow forwardDataflow,
BackwardTypeQualifierDataflow backwardDataflow) throws DataflowAnalysisException, CheckedAnalysisException {
@@ -401,7 +413,7 @@ public class CheckTypeQualifiers extends CFGDetector {
vn, location);
} else if (source.getWhen() == When.UNKNOWN && source.getType() == SourceSinkType.PARAMETER) {
- int p = source.getParameter();
+ int p = source.getParameter();
TypeQualifierAnnotation directTypeQualifierAnnotation = TypeQualifierApplications
.getDirectTypeQualifierAnnotation(xMethod, p, typeQualifierValue);
if (directTypeQualifierAnnotation != null && directTypeQualifierAnnotation.when == When.UNKNOWN) {
@@ -457,7 +469,7 @@ public class CheckTypeQualifiers extends CFGDetector {
}
private void checkForConflictingValues(XMethod xMethod, CFG cfg,
- TypeQualifierValue typeQualifierValue, TypeQualifierValueSet forwardsFact, TypeQualifierValueSet backwardsFact,
+ TypeQualifierValue<?> typeQualifierValue, TypeQualifierValueSet forwardsFact, TypeQualifierValueSet backwardsFact,
Location locationToReport, Location locationWhereDoomedValueIsObserved, ValueNumberFrame vnaFrame) throws CheckedAnalysisException {
Set<ValueNumber> valueNumberSet = new HashSet<ValueNumber>();
valueNumberSet.addAll(forwardsFact.getValueNumbers());
@@ -466,13 +478,12 @@ public class CheckTypeQualifiers extends CFGDetector {
for (ValueNumber vn : valueNumberSet) {
FlowValue forward = forwardsFact.getValue(vn);
FlowValue backward = backwardsFact.getValue(vn);
- if (!FlowValue.valuesConflict(typeQualifierValue.isStrictQualifier() && !xMethod.isIdentity(), forward, backward))
+ if (!FlowValue.valuesConflict(typeQualifierValue.isStrictQualifier() && !xMethod.isIdentity(), forward, backward)) {
continue;
+ }
if (DEBUG) {
System.out.println("Check " + vn + ": forward=" + forward + ", backward=" + backward + " at " + checkLocation);
- forwardsFact.getValue(vn);
- backwardsFact.getValue(vn);
}
emitDataflowWarning(xMethod, typeQualifierValue, forwardsFact, backwardsFact, vn, forward, backward,
@@ -481,17 +492,18 @@ public class CheckTypeQualifiers extends CFGDetector {
}
}
- private void emitDataflowWarning(XMethod xMethod, TypeQualifierValue typeQualifierValue,
+ private void emitDataflowWarning(XMethod xMethod, TypeQualifierValue<?> typeQualifierValue,
TypeQualifierValueSet forwardsFact, TypeQualifierValueSet backwardsFact, ValueNumber vn, FlowValue forward,
FlowValue backward, Location locationToReport, @CheckForNull Location locationWhereDoomedValueIsObserved, ValueNumberFrame vnaFrame)
- throws CheckedAnalysisException {
+ throws CheckedAnalysisException {
String bugType;
- if (typeQualifierValue.isStrictQualifier() && forward == FlowValue.UNKNOWN)
+ if (typeQualifierValue.isStrictQualifier() && forward == FlowValue.UNKNOWN) {
bugType = "TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED";
- else if (backward == FlowValue.NEVER)
+ } else if (backward == FlowValue.NEVER) {
bugType = "TQ_ALWAYS_VALUE_USED_WHERE_NEVER_REQUIRED";
- else
+ } else {
bugType = "TQ_NEVER_VALUE_USED_WHERE_ALWAYS_REQUIRED";
+ }
// Issue warning
BugInstance warning = new BugInstance(this, bugType, Priorities.NORMAL_PRIORITY).addClassAndMethod(xMethod);
@@ -547,7 +559,7 @@ public class CheckTypeQualifiers extends CFGDetector {
bugReporter.reportBug(warning);
}
- private void emitSourceWarning(String bugType, XMethod xMethod, TypeQualifierValue typeQualifierValue,
+ private void emitSourceWarning(String bugType, XMethod xMethod, TypeQualifierValue<?> typeQualifierValue,
FlowValue backwardsFlowValue, TypeQualifierValueSet backwardsFact, SourceSinkInfo source, ValueNumber vn,
Location location) {
@@ -565,11 +577,11 @@ public class CheckTypeQualifiers extends CFGDetector {
bugReporter.reportBug(warning);
}
- private void annotateWarningWithTypeQualifier(BugInstance warning, TypeQualifierValue typeQualifierValue) {
- if (TypeQualifierValue.hasMultipleVariants(typeQualifierValue)) {
- StringBuilder buf = new StringBuilder();
- buf.append("@");
- buf.append(typeQualifierValue.typeQualifier.getDottedClassName());
+ private void annotateWarningWithTypeQualifier(BugInstance warning, TypeQualifierValue<?> typeQualifierValue) {
+ if (TypeQualifierValue.hasMultipleVariants(typeQualifierValue)) {
+ StringBuilder buf = new StringBuilder();
+ buf.append("@");
+ buf.append(typeQualifierValue.typeQualifier.getDottedClassName());
// When there are multiple variants, qualify the type
// qualifier with the value indicating which variant.
@@ -594,7 +606,7 @@ public class CheckTypeQualifiers extends CFGDetector {
sourceSinkInfo.getLocal());
lva.setDescription(lva.isSignificant() ? LocalVariableAnnotation.PARAMETER_VALUE_SOURCE_NAMED_ROLE
: LocalVariableAnnotation.PARAMETER_VALUE_SOURCE_ROLE);
-
+
warning.add(lva);
} catch (CheckedAnalysisException e) {
warning.addSourceLine(methodDescriptor, sourceSinkInfo.getLocation()).describe("SOURCE_LINE_VALUE_SOURCE");
@@ -607,10 +619,11 @@ public class CheckTypeQualifiers extends CFGDetector {
warning.addString((String) constantValue).describe(StringAnnotation.STRING_CONSTANT_ROLE);
} else if (constantValue instanceof Integer) {
warning.addInt((Integer) constantValue).describe(IntAnnotation.INT_VALUE);
- } else if (constantValue == null)
+ } else if (constantValue == null) {
warning.addString("null").describe(StringAnnotation.STRING_NONSTRING_CONSTANT_ROLE);
- else
+ } else {
warning.addString(constantValue.toString()).describe(StringAnnotation.STRING_NONSTRING_CONSTANT_ROLE);
+ }
break;
case RETURN_VALUE_OF_CALLED_METHOD:
@@ -647,8 +660,9 @@ public class CheckTypeQualifiers extends CFGDetector {
Location getSinkLocation(Iterable<? extends SourceSinkInfo> info) {
for (SourceSinkInfo s : info) {
Location l = getSinkLocation(s);
- if (l != null)
+ if (l != null) {
return l;
+ }
}
return null;
diff --git a/src/java/edu/umd/cs/findbugs/detect/CloneIdiom.java b/src/java/edu/umd/cs/findbugs/detect/CloneIdiom.java
index f054e3d..3452cbb 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CloneIdiom.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CloneIdiom.java
@@ -45,7 +45,7 @@ import edu.umd.cs.findbugs.visitclass.DismantleBytecode;
public class CloneIdiom extends DismantleBytecode implements Detector, StatelessDetector {
- private ClassDescriptor cloneDescriptor = DescriptorFactory.createClassDescriptor(java.lang.Cloneable.class);
+ private final ClassDescriptor cloneDescriptor = DescriptorFactory.createClassDescriptor(java.lang.Cloneable.class);
boolean isCloneable, hasCloneMethod;
@@ -66,25 +66,27 @@ public class CloneIdiom extends DismantleBytecode implements Detector, Stateless
// boolean throwsExceptions;
boolean implementsCloneableDirectly;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public CloneIdiom(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
classContext.getJavaClass().accept(this);
}
@Override
public void visit(Code obj) {
- if (getMethodName().equals("clone") && getMethodSig().startsWith("()"))
+ if ("clone".equals(getMethodName()) && getMethodSig().startsWith("()")) {
super.visit(obj);
+ }
}
@Override
public void sawOpcode(int seen) {
- if (seen == INVOKESPECIAL && getNameConstantOperand().equals("clone") && getSigConstantOperand().startsWith("()")) {
+ if (seen == INVOKESPECIAL && "clone".equals(getNameConstantOperand()) && getSigConstantOperand().startsWith("()")) {
/*
* System.out.println("Saw call to " + nameConstant + ":" +
* sigConstant + " in " + betterMethodName);
@@ -101,14 +103,16 @@ public class CloneIdiom extends DismantleBytecode implements Detector, Stateless
isCloneable = false;
check = false;
isFinal = obj.isFinal();
- if (obj.isInterface())
+ if (obj.isInterface()) {
return;
- if (obj.isAbstract())
+ }
+ if (obj.isAbstract()) {
return;
+ }
// Does this class directly implement Cloneable?
String[] interface_names = obj.getInterfaceNames();
for (String interface_name : interface_names) {
- if (interface_name.equals("java.lang.Cloneable")) {
+ if ("java.lang.Cloneable".equals(interface_name)) {
implementsCloneableDirectly = true;
isCloneable = true;
break;
@@ -117,11 +121,13 @@ public class CloneIdiom extends DismantleBytecode implements Detector, Stateless
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
try {
- if (subtypes2.isSubtype(getClassDescriptor(), cloneDescriptor))
+ if (subtypes2.isSubtype(getClassDescriptor(), cloneDescriptor)) {
isCloneable = true;
+ }
if (subtypes2.isSubtype(DescriptorFactory.createClassDescriptorFromDottedClassName(obj.getSuperclassName()),
- cloneDescriptor))
+ cloneDescriptor)) {
implementsCloneableDirectly = false;
+ }
} catch (ClassNotFoundException e) {
bugReporter.reportMissingClass(e);
@@ -135,28 +141,34 @@ public class CloneIdiom extends DismantleBytecode implements Detector, Stateless
@Override
public void visitAfter(JavaClass obj) {
- if (!check)
+ if (!check) {
return;
- if (cloneOnlyThrowsException)
+ }
+ if (cloneOnlyThrowsException) {
return;
+ }
if (implementsCloneableDirectly && !hasCloneMethod) {
- if (!referencesCloneMethod)
+ if (!referencesCloneMethod) {
bugReporter.reportBug(new BugInstance(this, "CN_IDIOM", NORMAL_PRIORITY).addClass(this));
+ }
}
if (hasCloneMethod && isCloneable && !invokesSuperClone && !isFinal && obj.isPublic()) {
int priority = LOW_PRIORITY;
- if (obj.isPublic() || obj.isProtected())
+ if (obj.isPublic() || obj.isProtected()) {
priority = NORMAL_PRIORITY;
+ }
try {
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
Set<ClassDescriptor> directSubtypes = subtypes2.getDirectSubtypes(getClassDescriptor());
- if (!directSubtypes.isEmpty())
+ if (!directSubtypes.isEmpty()) {
priority--;
+ }
BugInstance bug = new BugInstance(this, "CN_IDIOM_NO_SUPER_CALL", priority).addClass(this).addMethod(
cloneMethodAnnotation);
- for (ClassDescriptor d : directSubtypes)
+ for (ClassDescriptor d : directSubtypes) {
bug.addClass(d).describe(ClassAnnotation.SUBCLASS_ROLE);
+ }
bugReporter.reportBug(bug);
} catch (ClassNotFoundException e) {
bugReporter.reportMissingClass(e);
@@ -164,8 +176,9 @@ public class CloneIdiom extends DismantleBytecode implements Detector, Stateless
} else if (hasCloneMethod && !isCloneable && !cloneOnlyThrowsException && !cloneIsDeprecated && !obj.isAbstract()) {
int priority = Priorities.NORMAL_PRIORITY;
- if (referencesCloneMethod)
+ if (referencesCloneMethod) {
priority--;
+ }
bugReporter.reportBug(new BugInstance(this, "CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE", priority).addClass(this)
.addMethod(cloneMethodAnnotation));
@@ -177,23 +190,29 @@ public class CloneIdiom extends DismantleBytecode implements Detector, Stateless
public void visit(ConstantNameAndType obj) {
String methodName = obj.getName(getConstantPool());
String methodSig = obj.getSignature(getConstantPool());
- if (!methodName.equals("clone"))
+ if (!"clone".equals(methodName)) {
return;
- if (!methodSig.startsWith("()"))
+ }
+ if (!methodSig.startsWith("()")) {
return;
+ }
referencesCloneMethod = true;
}
@Override
public void visit(Method obj) {
- if (obj.isAbstract() || BCELUtil.isSynthetic(obj))
+ if (obj.isAbstract() || BCELUtil.isSynthetic(obj)) {
return;
- if (!obj.isPublic())
+ }
+ if (!obj.isPublic()) {
return;
- if (!getMethodName().equals("clone"))
+ }
+ if (!"clone".equals(getMethodName())) {
return;
- if (!getMethodSig().startsWith("()"))
+ }
+ if (!getMethodSig().startsWith("()")) {
return;
+ }
hasCloneMethod = true;
cloneIsDeprecated = getXMethod().isDeprecated();
cloneMethodAnnotation = MethodAnnotation.fromVisitedMethod(this);
@@ -205,9 +224,10 @@ public class CloneIdiom extends DismantleBytecode implements Detector, Stateless
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector#report()
*/
+ @Override
public void report() {
// do nothing
diff --git a/src/java/edu/umd/cs/findbugs/detect/ComparatorIdiom.java b/src/java/edu/umd/cs/findbugs/detect/ComparatorIdiom.java
index e46b4d8..3844107 100644
--- a/src/java/edu/umd/cs/findbugs/detect/ComparatorIdiom.java
+++ b/src/java/edu/umd/cs/findbugs/detect/ComparatorIdiom.java
@@ -39,6 +39,7 @@ public class ComparatorIdiom extends PreorderVisitor implements Detector {
this.bugReporter = bugReporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
classContext.getJavaClass().accept(this);
}
@@ -49,26 +50,30 @@ public class ComparatorIdiom extends PreorderVisitor implements Detector {
if (Subtypes2.instanceOf(obj, "java.util.Comparator") && !ClassName.isAnonymous(getClassName())
&& !Subtypes2.instanceOf(obj, "java.io.Serializable")) {
int priority = NORMAL_PRIORITY;
- if (obj.isInterface() || obj.isAbstract())
+ if (obj.isInterface() || obj.isAbstract()) {
return;
+ }
double easilySerializable = 1.0;
for (Field f : obj.getFields()) {
try {
- if (f.getName().startsWith("this$"))
+ if (f.getName().startsWith("this$")) {
return;
+ }
String signature = f.getSignature();
char firstChar = signature.charAt(0);
- if (firstChar == 'L' || firstChar == '[')
+ if (firstChar == 'L' || firstChar == '[') {
easilySerializable *= DeepSubtypeAnalysis.isDeepSerializable(signature);
+ }
} catch (ClassNotFoundException e) {
easilySerializable = 0.0;
break;
}
}
- if (easilySerializable < 0.9)
+ if (easilySerializable < 0.9) {
priority = LOW_PRIORITY;
+ }
bugReporter.reportBug(new BugInstance(this, "SE_COMPARATOR_SHOULD_BE_SERIALIZABLE", priority).addClass(this));
@@ -76,6 +81,7 @@ public class ComparatorIdiom extends PreorderVisitor implements Detector {
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/ConfusedInheritance.java b/src/java/edu/umd/cs/findbugs/detect/ConfusedInheritance.java
index e7096cd..a91e691 100644
--- a/src/java/edu/umd/cs/findbugs/detect/ConfusedInheritance.java
+++ b/src/java/edu/umd/cs/findbugs/detect/ConfusedInheritance.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
public class ConfusedInheritance extends PreorderVisitor implements Detector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private JavaClass cls;
@@ -39,6 +39,7 @@ public class ConfusedInheritance extends PreorderVisitor implements Detector {
this.bugReporter = bugReporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
cls = classContext.getJavaClass();
if (cls.isFinal()) {
@@ -54,6 +55,7 @@ public class ConfusedInheritance extends PreorderVisitor implements Detector {
}
}
+ @Override
public void report() {
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/ConfusionBetweenInheritedAndOuterMethod.java b/src/java/edu/umd/cs/findbugs/detect/ConfusionBetweenInheritedAndOuterMethod.java
index 5048cf9..73d3ef8 100644
--- a/src/java/edu/umd/cs/findbugs/detect/ConfusionBetweenInheritedAndOuterMethod.java
+++ b/src/java/edu/umd/cs/findbugs/detect/ConfusionBetweenInheritedAndOuterMethod.java
@@ -22,19 +22,24 @@ package edu.umd.cs.findbugs.detect;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.classfile.LocalVariable;
+import org.apache.bcel.classfile.LocalVariableTable;
import edu.umd.cs.findbugs.BugAccumulator;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
-import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.ba.XFactory;
import edu.umd.cs.findbugs.ba.XMethod;
+import edu.umd.cs.findbugs.ba.ch.Subtypes2;
import edu.umd.cs.findbugs.bcel.BCELUtil;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
-public class ConfusionBetweenInheritedAndOuterMethod extends BytecodeScanningDetector {
+public class ConfusionBetweenInheritedAndOuterMethod extends OpcodeStackDetector {
BugAccumulator bugAccumulator;
+ BugInstance iteratorBug;
+
public ConfusionBetweenInheritedAndOuterMethod(BugReporter bugReporter) {
this.bugAccumulator = new BugAccumulator(bugReporter);
}
@@ -62,14 +67,31 @@ public class ConfusionBetweenInheritedAndOuterMethod extends BytecodeScanningDet
@Override
public void visit(Code obj) {
if (isInnerClass && !BCELUtil.isSynthetic(getMethod())) {
-// System.out.println(getFullyQualifiedMethodName());
super.visit(obj);
+ iteratorBug = null;
}
}
@Override
public void sawOpcode(int seen) {
-// System.out.printf("%3d : %s%n", getPC(), OPCODE_NAMES[seen]);
+ if (iteratorBug != null) {
+ if (isRegisterStore()) {
+ LocalVariableTable lvt = getMethod().getLocalVariableTable();
+ if (lvt != null) {
+ LocalVariable localVariable = lvt.getLocalVariable(getRegisterOperand(), getNextPC());
+ if(localVariable == null || localVariable.getName().endsWith("$")) {
+ // iterator() result is stored to the synthetic variable which has no name in LVT or name is suffixed with '$'
+ // Looks like it's for-each cycle like for(Object obj : this)
+ // Do not report such case
+ iteratorBug = null;
+ }
+ }
+ }
+ if(iteratorBug != null) {
+ bugAccumulator.accumulateBug(iteratorBug, this);
+ }
+ iteratorBug = null;
+ }
if (seen != INVOKEVIRTUAL) {
return;
}
@@ -82,6 +104,10 @@ public class ConfusionBetweenInheritedAndOuterMethod extends BytecodeScanningDet
|| invokedMethod.isSynthetic()) {
return;
}
+ if(getStack().getStackItem(getNumberArguments(getSigConstantOperand())).getRegisterNumber() != 0) {
+ // called not for this object
+ return;
+ }
// method is inherited
String possibleTargetClass = getDottedClassName();
String superClassName = getDottedSuperclassName();
@@ -110,15 +136,17 @@ public class ConfusionBetweenInheritedAndOuterMethod extends BytecodeScanningDet
priority++;
}
-// System.out.println("Found it");
- bugAccumulator.accumulateBug(
- new BugInstance(this, "IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD", priority)
- .addClassAndMethod(this).addMethod(invokedMethod).describe("METHOD_INHERITED")
- .addMethod(alternativeMethod).describe("METHOD_ALTERNATIVE_TARGET"), this);
+ BugInstance bug = new BugInstance(this, "IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD", priority)
+ .addClassAndMethod(this).addMethod(invokedMethod).describe("METHOD_INHERITED")
+ .addMethod(alternativeMethod).describe("METHOD_ALTERNATIVE_TARGET");
+ if(invokedMethod.getName().equals("iterator") && invokedMethod.getSignature().equals("()Ljava/util/Iterator;")
+ && Subtypes2.instanceOf(getDottedClassName(), "java.lang.Iterable")) {
+ iteratorBug = bug;
+ } else {
+ bugAccumulator.accumulateBug(bug, this);
+ }
break;
}
}
-
}
-
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/CovariantArrayAssignment.java b/src/java/edu/umd/cs/findbugs/detect/CovariantArrayAssignment.java
new file mode 100644
index 0000000..0a23836
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/detect/CovariantArrayAssignment.java
@@ -0,0 +1,190 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.detect;
+
+import org.apache.bcel.classfile.Code;
+import org.apache.bcel.classfile.LocalVariable;
+import org.apache.bcel.classfile.LocalVariableTable;
+
+import edu.umd.cs.findbugs.BugAccumulator;
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.OpcodeStack.Item;
+import edu.umd.cs.findbugs.ba.AnalysisContext;
+import edu.umd.cs.findbugs.ba.SignatureParser;
+import edu.umd.cs.findbugs.ba.XClass;
+import edu.umd.cs.findbugs.ba.XField;
+import edu.umd.cs.findbugs.ba.ch.Subtypes2;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.ClassDescriptor;
+import edu.umd.cs.findbugs.classfile.DescriptorFactory;
+import edu.umd.cs.findbugs.classfile.FieldDescriptor;
+import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
+
+/**
+ * @author Tagir Valeev
+ */
+public class CovariantArrayAssignment extends OpcodeStackDetector {
+ private final BugAccumulator accumulator;
+
+ public CovariantArrayAssignment(BugReporter bugReporter) {
+ accumulator = new BugAccumulator(bugReporter);
+ }
+
+ @Override
+ public void visit(Code obj) {
+ super.visit(obj);
+ accumulator.reportAccumulatedBugs();
+ }
+
+ /**
+ * @param superClass
+ * @param subClass
+ * @return true if superClass is abstract or interface and all known non-abstract implementations
+ * are derived from given subClass
+ */
+ private static boolean allImplementationsDerivedFromSubclass(@SlashedClassName String superClass, @SlashedClassName String subClass) {
+ ClassDescriptor superDescriptor = DescriptorFactory.createClassDescriptor(superClass);
+ XClass xClass = AnalysisContext.currentXFactory().getXClass(superDescriptor);
+ if(xClass == null || (!xClass.isInterface() && !xClass.isAbstract())) {
+ return false;
+ }
+ try {
+ ClassDescriptor wantedDescriptor = DescriptorFactory.createClassDescriptor(subClass);
+ Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
+ for (ClassDescriptor subDescriptor : subtypes2.getSubtypes(superDescriptor)) {
+ if (subDescriptor.equals(superDescriptor) || subDescriptor.equals(wantedDescriptor)) {
+ continue;
+ }
+ XClass xSubClass = AnalysisContext.currentXFactory().getXClass(subDescriptor);
+ if (xSubClass == null
+ || (!xSubClass.isAbstract() && !xSubClass.isInterface() && !subtypes2.isSubtype(subDescriptor,
+ wantedDescriptor))) {
+ return false;
+ }
+ }
+ return true;
+ } catch (ClassNotFoundException e) {
+ // unresolved class
+ }
+ return false;
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if ((isRegisterStore() && !isRegisterLoad()) || seen == PUTFIELD || seen == PUTSTATIC || seen == ARETURN) {
+ Item valueItem = getStack().getStackItem(0);
+ if(!valueItem.isNull() && valueItem.isNewlyAllocated() && valueItem.getSignature().startsWith("[L")
+ && !((Integer)0).equals(valueItem.getConstant())) {
+ String valueClass = valueItem.getSignature().substring(2, valueItem.getSignature().length()-1);
+ String arraySignature = null;
+ int priority = LOW_PRIORITY;
+ String pattern = null;
+ FieldDescriptor field = null;
+ if(seen == PUTFIELD || seen == PUTSTATIC) {
+ arraySignature = getSigConstantOperand();
+ pattern = "CAA_COVARIANT_ARRAY_FIELD";
+ field = getFieldDescriptorOperand();
+ if(field instanceof XField) {
+ XField xField = (XField)field;
+ if((xField.isPublic() || xField.isProtected())) {
+ XClass xClass = AnalysisContext.currentXFactory().getXClass(xField.getClassDescriptor());
+ if(xClass != null && xClass.isPublic()) {
+ priority = NORMAL_PRIORITY;
+ }
+ }
+ }
+ } else if(seen == ARETURN) {
+ if(getXMethod().bridgeFrom() == null) {
+ pattern = "CAA_COVARIANT_ARRAY_RETURN";
+ arraySignature = new SignatureParser(getMethodSig()).getReturnTypeSignature();
+ if (!arraySignature.equals("[Ljava/lang/Object;")
+ && (getXMethod().isPublic() || getXMethod().isProtected()) && getXClass().isPublic()) {
+ priority = NORMAL_PRIORITY;
+ }
+ }
+ } else {
+ LocalVariableTable lvt = getMethod().getLocalVariableTable();
+ if(lvt != null) {
+ LocalVariable localVariable = lvt.getLocalVariable(getRegisterOperand(), getNextPC());
+ if(localVariable != null) {
+ pattern = "CAA_COVARIANT_ARRAY_LOCAL";
+ arraySignature = localVariable.getSignature();
+ }
+ }
+ }
+ if(arraySignature != null && arraySignature.startsWith("[L")) {
+ String arrayClass = arraySignature.substring(2, arraySignature.length()-1);
+ if(!valueClass.equals(arrayClass)) {
+ if(priority == NORMAL_PRIORITY && allImplementationsDerivedFromSubclass(arrayClass, valueClass)) {
+ priority = LOW_PRIORITY;
+ }
+ BugInstance bug = new BugInstance(this, pattern, priority).addClassAndMethod(this)
+ .addFoundAndExpectedType(valueItem.getSignature(), arraySignature)
+ .addSourceLine(this).addValueSource(valueItem, this);
+ if(field != null) {
+ bug.addField(field);
+ }
+ accumulator.accumulateBug(bug, this);
+ }
+ }
+ }
+ }
+
+ if (seen == AASTORE) {
+ Item valueItem = getStack().getStackItem(0);
+ if(!valueItem.isNull()) {
+ Item arrayItem = getStack().getStackItem(2);
+ String arraySignature = arrayItem.getSignature();
+ String valueSignature = valueItem.getSignature();
+ // if valueSignature is "Ljava/lang/Object;" then OpcodeStack probably could not define actual type at all: skip this case
+ if(arraySignature.startsWith("[L") && valueSignature.startsWith("L") && !valueSignature.equals("Ljava/lang/Object;")) {
+ String arrayClass = arraySignature.substring(2, arraySignature.length()-1);
+ String valueClass = valueSignature.substring(1, valueSignature.length()-1);
+ try {
+ ClassDescriptor valueClassDescriptor = DescriptorFactory.createClassDescriptor(valueClass);
+ ClassDescriptor arrayClassDescriptor = DescriptorFactory.createClassDescriptor(arrayClass);
+ if (!AnalysisContext.currentAnalysisContext().getSubtypes2()
+ .isSubtype(valueClassDescriptor, arrayClassDescriptor)) {
+ int priority = HIGH_PRIORITY; // in this case we may be pretty sure that if this line is executed ArrayStoreException will happen
+ if(AnalysisContext.currentAnalysisContext().getSubtypes2().isSubtype(arrayClassDescriptor, valueClassDescriptor)) {
+ priority = NORMAL_PRIORITY;
+ if(allImplementationsDerivedFromSubclass(valueClass, arrayClass)) {
+ // Every implementation of valueClass also extends arrayClass
+ // In this case ArrayStoreException will never occur in current project
+ // So it's enough that we reported a bug when this array was created
+ priority = IGNORE_PRIORITY;
+ }
+ }
+ BugInstance bug = new BugInstance(this, "CAA_COVARIANT_ARRAY_ELEMENT_STORE", priority).addClassAndMethod(this)
+ .addFoundAndExpectedType(valueSignature, 'L'+arrayClass+';')
+ .addSourceLine(this)
+ .addValueSource(valueItem, this)
+ .addValueSource(arrayItem, this);
+ accumulator.accumulateBug(bug, this);
+ }
+ } catch (ClassNotFoundException e) {
+ // Probably class was not supplied to the analysis: assume that everything is correct
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/detect/CrossSiteScripting.java b/src/java/edu/umd/cs/findbugs/detect/CrossSiteScripting.java
index 86d5019..4932ce3 100644
--- a/src/java/edu/umd/cs/findbugs/detect/CrossSiteScripting.java
+++ b/src/java/edu/umd/cs/findbugs/detect/CrossSiteScripting.java
@@ -34,6 +34,9 @@ import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.StringAnnotation;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+import edu.umd.cs.findbugs.detect.BuildStringPassthruGraph.StringPassthruDatabase;
public class CrossSiteScripting extends OpcodeStackDetector {
@@ -41,9 +44,13 @@ public class CrossSiteScripting extends OpcodeStackDetector {
final BugAccumulator accumulator;
+ private final Map<MethodDescriptor, int[]> allFileNameStringMethods;
+
public CrossSiteScripting(BugReporter bugReporter) {
this.bugReporter = bugReporter;
this.accumulator = new BugAccumulator(bugReporter);
+ StringPassthruDatabase database = Global.getAnalysisCache().getDatabase(StringPassthruDatabase.class);
+ allFileNameStringMethods = database.getFileNameStringMethods();
}
Map<String, OpcodeStack.Item> map = new HashMap<String, OpcodeStack.Item>();
@@ -64,13 +71,15 @@ public class CrossSiteScripting extends OpcodeStackDetector {
assert item.isServletParameterTainted();
String s = item.getHttpParameterName();
int pc = item.getInjectionPC();
- if (s != null && xmlSafe.matcher(s).matches())
+ if (s != null && xmlSafe.matcher(s).matches()) {
bug.addString(s).describe(StringAnnotation.PARAMETER_NAME_ROLE);
+ }
SourceLineAnnotation thisLine = SourceLineAnnotation.fromVisitedInstruction(this);
if (pc >= 0) {
SourceLineAnnotation source = SourceLineAnnotation.fromVisitedInstruction(this, pc);
- if (thisLine.getStartLine() != source.getStartLine())
+ if (thisLine.getStartLine() != source.getStartLine()) {
bug.add(source).describe(SourceLineAnnotation.ROLE_GENERATED_AT);
+ }
}
bug.addOptionalLocalVariable(this, item);
@@ -90,25 +99,28 @@ public class CrossSiteScripting extends OpcodeStackDetector {
OpcodeStack.Item oldTop = top;
top = null;
+ if (seen == INVOKESPECIAL || seen == INVOKESTATIC || seen == INVOKEINTERFACE || seen == INVOKEVIRTUAL) {
+ int[] params = allFileNameStringMethods.get(getMethodDescriptorOperand());
+ if(params != null) {
+ int numArgs = getNumberArguments(getSigConstantOperand());
+ for(int param : params) {
+ OpcodeStack.Item path = stack.getStackItem(numArgs-1-param);
+ if (isTainted(path)) {
+ String bugPattern = taintPriority(path) == Priorities.HIGH_PRIORITY ? "PT_ABSOLUTE_PATH_TRAVERSAL"
+ : "PT_RELATIVE_PATH_TRAVERSAL";
+ annotateAndReport(new BugInstance(this, bugPattern, Priorities.NORMAL_PRIORITY).addClassAndMethod(this)
+ .addCalledMethod(this), path);
+ }
+ }
+ }
+ }
if (seen == INVOKESPECIAL) {
String calledClassName = getClassConstantOperand();
String calledMethodName = getNameConstantOperand();
String calledMethodSig = getSigConstantOperand();
- if (calledClassName.startsWith("java/io/File") && calledMethodSig.equals("(Ljava/lang/String;)V")) {
- OpcodeStack.Item path = stack.getStackItem(0);
- if (isTainted(path)) {
- String bugPattern = taintPriority(path) == Priorities.HIGH_PRIORITY ? "PT_ABSOLUTE_PATH_TRAVERSAL"
- : "PT_RELATIVE_PATH_TRAVERSAL";
- annotateAndReport(new BugInstance(this, bugPattern, Priorities.NORMAL_PRIORITY).addClassAndMethod(this)
- .addCalledMethod(this), path);
- }
-
- }
-
-
- if (calledClassName.equals("javax/servlet/http/Cookie") && calledMethodName.equals("<init>")
- && calledMethodSig.equals("(Ljava/lang/String;Ljava/lang/String;)V")) {
+ if ("javax/servlet/http/Cookie".equals(calledClassName) && "<init>".equals(calledMethodName)
+ && "(Ljava/lang/String;Ljava/lang/String;)V".equals(calledMethodSig)) {
OpcodeStack.Item value = stack.getStackItem(0);
OpcodeStack.Item name = stack.getStackItem(1);
if (value.isServletParameterTainted() || name.isServletParameterTainted()) {
@@ -123,19 +135,20 @@ public class CrossSiteScripting extends OpcodeStackDetector {
String calledClassName = getClassConstantOperand();
String calledMethodName = getNameConstantOperand();
String calledMethodSig = getSigConstantOperand();
- if (calledClassName.equals("javax/servlet/http/HttpServletResponse") && calledMethodName.equals("setContentType")) {
+ if ("javax/servlet/http/HttpServletResponse".equals(calledClassName) && "setContentType".equals(calledMethodName)) {
OpcodeStack.Item writing = stack.getStackItem(0);
if ("text/plain".equals(writing.getConstant())) {
isPlainText = true;
}
- } else if (calledClassName.equals("javax/servlet/http/HttpSession") && calledMethodName.equals("setAttribute")) {
+ } else if ("javax/servlet/http/HttpSession".equals(calledClassName) && "setAttribute".equals(calledMethodName)) {
OpcodeStack.Item value = stack.getStackItem(0);
OpcodeStack.Item name = stack.getStackItem(1);
Object nameConstant = name.getConstant();
- if (nameConstant instanceof String)
+ if (nameConstant instanceof String) {
map.put((String) nameConstant, value);
- } else if (calledClassName.equals("javax/servlet/http/HttpSession") && calledMethodName.equals("getAttribute")) {
+ }
+ } else if ("javax/servlet/http/HttpSession".equals(calledClassName) && "getAttribute".equals(calledMethodName)) {
OpcodeStack.Item name = stack.getStackItem(0);
Object nameConstant = name.getConstant();
if (nameConstant instanceof String) {
@@ -145,22 +158,23 @@ public class CrossSiteScripting extends OpcodeStackDetector {
replaceTop = top;
}
}
- } else if (calledClassName.equals("javax/servlet/http/HttpServletResponse")
+ } else if ("javax/servlet/http/HttpServletResponse".equals(calledClassName)
&& (calledMethodName.startsWith("send") || calledMethodName.endsWith("Header"))
&& calledMethodSig.endsWith("Ljava/lang/String;)V")) {
OpcodeStack.Item writing = stack.getStackItem(0);
if (isTainted(writing)) {
- if (calledMethodName.equals("sendError"))
+ if ("sendError".equals(calledMethodName)) {
annotateAndReport(
new BugInstance(this, "XSS_REQUEST_PARAMETER_TO_SEND_ERROR", taintPriority(writing))
- .addClassAndMethod(this),
+ .addClassAndMethod(this),
writing);
- else
+ } else {
annotateAndReport(
new BugInstance(this, "HRS_REQUEST_PARAMETER_TO_HTTP_HEADER", taintPriority(writing))
- .addClassAndMethod(this),
+ .addClassAndMethod(this),
writing);
+ }
}
}
@@ -169,48 +183,52 @@ public class CrossSiteScripting extends OpcodeStackDetector {
String calledMethodName = getNameConstantOperand();
String calledMethodSig = getSigConstantOperand();
- if ((calledMethodName.startsWith("print") || calledMethodName.equals("write"))
- && calledClassName.equals("javax/servlet/jsp/JspWriter")
- && (calledMethodSig.equals("(Ljava/lang/Object;)V") || calledMethodSig.equals("(Ljava/lang/String;)V"))) {
+ if ((calledMethodName.startsWith("print") || "write".equals(calledMethodName))
+ && "javax/servlet/jsp/JspWriter".equals(calledClassName)
+ && ("(Ljava/lang/Object;)V".equals(calledMethodSig) || "(Ljava/lang/String;)V".equals(calledMethodSig))) {
OpcodeStack.Item writing = stack.getStackItem(0);
// System.out.println(SourceLineAnnotation.fromVisitedInstruction(this)
// + " writing " + writing);
- if (isTainted(writing))
+ if (isTainted(writing)) {
annotateAndReport(
new BugInstance(this, "XSS_REQUEST_PARAMETER_TO_JSP_WRITER", taintPriority(writing))
- .addClassAndMethod(this),
+ .addClassAndMethod(this),
writing);
- else if (isTainted(oldTop))
+ } else if (isTainted(oldTop)) {
annotateAndReport(
new BugInstance(this, "XSS_REQUEST_PARAMETER_TO_JSP_WRITER", Priorities.NORMAL_PRIORITY)
- .addClassAndMethod(this),
+ .addClassAndMethod(this),
oldTop);
+ }
} else if (calledClassName.startsWith("java/io/") && calledClassName.endsWith("Writer")
&& (calledMethodName.startsWith("print") || calledMethodName.startsWith("write"))
- && (calledMethodSig.equals("(Ljava/lang/Object;)V") || calledMethodSig.equals("(Ljava/lang/String;)V"))) {
+ && ("(Ljava/lang/Object;)V".equals(calledMethodSig) || "(Ljava/lang/String;)V".equals(calledMethodSig))) {
OpcodeStack.Item writing = stack.getStackItem(0);
OpcodeStack.Item writingTo = stack.getStackItem(1);
- if (isTainted(writing) && writingTo.isServletWriter())
+ if (isTainted(writing) && writingTo.isServletWriter()) {
annotateAndReport(
new BugInstance(this, "XSS_REQUEST_PARAMETER_TO_SERVLET_WRITER", taintPriority(writing))
- .addClassAndMethod(this),
+ .addClassAndMethod(this),
writing);
- else if (isTainted(oldTop) && writingTo.isServletWriter())
+ } else if (isTainted(oldTop) && writingTo.isServletWriter()) {
annotateAndReport(
new BugInstance(this, "XSS_REQUEST_PARAMETER_TO_SERVLET_WRITER", Priorities.NORMAL_PRIORITY)
- .addClassAndMethod(this),
+ .addClassAndMethod(this),
writing);
+ }
}
}
}
private boolean isTainted(OpcodeStack.Item writing) {
- if (writing == null)
+ if (writing == null) {
return false;
+ }
return writing.isServletParameterTainted();
}
+ /*
private boolean isDirectTaint(OpcodeStack.Item writing) {
if (writing == null)
return false;
@@ -224,17 +242,18 @@ public class CrossSiteScripting extends OpcodeStackDetector {
String clsName = m.getClassName();
return clsName.equals("javax/servlet/http/HttpServletRequest") || clsName.equals("javax/servlet/http/ServletRequest");
}
+ */
+
private int taintPriority(OpcodeStack.Item writing) {
- if (writing == null)
+ if (writing == null) {
return Priorities.NORMAL_PRIORITY;
+ }
XMethod method = writing.getReturnValueOf();
- if (method != null && method.getName().equals("getParameter")
- && method.getClassName().equals("javax.servlet.http.HttpServletRequest"))
+ if (method != null && "getParameter".equals(method.getName())
+ && "javax.servlet.http.HttpServletRequest".equals(method.getClassName())) {
return Priorities.HIGH_PRIORITY;
+ }
return Priorities.NORMAL_PRIORITY;
-
}
-
-
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/DeadLocalStoreProperty.java b/src/java/edu/umd/cs/findbugs/detect/DeadLocalStoreProperty.java
index 3b151ea..7293dad 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DeadLocalStoreProperty.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DeadLocalStoreProperty.java
@@ -5,7 +5,7 @@ import edu.umd.cs.findbugs.props.PriorityAdjustment;
/**
* Warning property for FindDeadLocalStores.
- *
+ *
* @author David Hovemeyer
*/
public class DeadLocalStoreProperty extends AbstractWarningProperty {
diff --git a/src/java/edu/umd/cs/findbugs/detect/DefaultEncodingDetector.java b/src/java/edu/umd/cs/findbugs/detect/DefaultEncodingDetector.java
index 9d70658..b4f158c 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DefaultEncodingDetector.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DefaultEncodingDetector.java
@@ -77,7 +77,7 @@ public class DefaultEncodingDetector extends OpcodeStackDetector {
protected void addMethodAnnotation(@DottedClassName String cName, String mName, String mSig, boolean isStatic,
DefaultEncodingAnnotation annotation) {
super.addMethodAnnotation(cName, mName, mSig, isStatic, annotation);
- classes.add(DescriptorFactory.createClassDescriptorFromDottedClassName(cName));
+ classes.add(DescriptorFactory.createClassDescriptorFromDottedClassName(cName));
}
@@ -174,6 +174,9 @@ public class DefaultEncodingDetector extends OpcodeStackDetector {
bugAccumulator.accumulateBug(new BugInstance(this, "DM_DEFAULT_ENCODING", HIGH_PRIORITY).addClassAndMethod(this)
.addCalledMethod(this), this);
}
+ break;
+ default:
+ break;
}
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/DoInsideDoPrivileged.java b/src/java/edu/umd/cs/findbugs/detect/DoInsideDoPrivileged.java
index a13c60d..95e42ec 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DoInsideDoPrivileged.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DoInsideDoPrivileged.java
@@ -50,35 +50,40 @@ public class DoInsideDoPrivileged extends BytecodeScanningDetector {
@Override
public void visit(Code obj) {
- if (isDoPrivileged && getMethodName().equals("run"))
+ if (isDoPrivileged && "run".equals(getMethodName())) {
return;
- if (getMethod().isPrivate())
+ }
+ if (getMethod().isPrivate()) {
return;
- if (DumbMethods.isTestMethod(getMethod()))
+ }
+ if (DumbMethods.isTestMethod(getMethod())) {
return;
+ }
super.visit(obj);
bugAccumulator.reportAccumulatedBugs();
}
@Override
public void sawOpcode(int seen) {
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("setAccessible")) {
+ if (seen == INVOKEVIRTUAL && "setAccessible".equals(getNameConstantOperand())) {
@DottedClassName
String className = getDottedClassConstantOperand();
- if (className.equals("java.lang.reflect.Field") || className.equals("java.lang.reflect.Method"))
+ if ("java.lang.reflect.Field".equals(className) || "java.lang.reflect.Method".equals(className)) {
bugAccumulator.accumulateBug(
new BugInstance(this, "DP_DO_INSIDE_DO_PRIVILEGED", LOW_PRIORITY).addClassAndMethod(this)
- .addCalledMethod(this), this);
+ .addCalledMethod(this), this);
+ }
}
if (seen == NEW) {
@DottedClassName
String classOfConstructedClass = getDottedClassConstantOperand();
if (Subtypes2.instanceOf(classOfConstructedClass, "java.lang.ClassLoader")
- && !(getMethodName().equals("main") && getMethodSig().equals("([Ljava/lang/String;)V") && getMethod()
- .isStatic()))
+ && !("main".equals(getMethodName()) && "([Ljava/lang/String;)V".equals(getMethodSig()) && getMethod()
+ .isStatic())) {
bugAccumulator.accumulateBug(new BugInstance(this, "DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED", NORMAL_PRIORITY)
- .addClassAndMethod(this).addClass(classOfConstructedClass), this);
+ .addClassAndMethod(this).addClass(classOfConstructedClass), this);
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/DontCatchIllegalMonitorStateException.java b/src/java/edu/umd/cs/findbugs/detect/DontCatchIllegalMonitorStateException.java
index 137adbe..93bcbb7 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DontCatchIllegalMonitorStateException.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DontCatchIllegalMonitorStateException.java
@@ -44,42 +44,50 @@ public class DontCatchIllegalMonitorStateException extends PreorderVisitor imple
public DontCatchIllegalMonitorStateException(BugReporter bugReporter) {
this.bugReporter = bugReporter;
- if (DEBUG)
+ if (DEBUG) {
msgs = new HashSet<String>();
+ }
}
@Override
public void visit(ExceptionTable obj) {
if (DEBUG) {
String names[] = obj.getExceptionNames();
- for (String name : names)
- if (name.equals("java.lang.Exception") || name.equals("java.lang.Throwable"))
+ for (String name : names) {
+ if ("java.lang.Exception".equals(name) || "java.lang.Throwable".equals(name)) {
System.out.println(name + " thrown by " + getFullyQualifiedMethodName());
+ }
+ }
}
}
@Override
public void visit(CodeException obj) {
int type = obj.getCatchType();
- if (type == 0)
+ if (type == 0) {
return;
+ }
String name = getConstantPool().constantToString(getConstantPool().getConstant(type));
if (DEBUG) {
String msg = "Catching " + name + " in " + getFullyQualifiedMethodName();
- if (msgs.add(msg))
+ if (msgs.add(msg)) {
System.out.println(msg);
+ }
}
- if (name.equals("java.lang.IllegalMonitorStateException"))
+ if ("java.lang.IllegalMonitorStateException".equals(name)) {
bugReporter.reportBug(new BugInstance(this, "IMSE_DONT_CATCH_IMSE", HIGH_PRIORITY).addClassAndMethod(this)
.addSourceLine(this.classContext, this, obj.getHandlerPC()));
+ }
}
+ @Override
public void visitClassContext(ClassContext classContext) {
this.classContext = classContext;
classContext.getJavaClass().accept(this);
}
+ @Override
public void report() {
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/DontIgnoreResultOfPutIfAbsent.java b/src/java/edu/umd/cs/findbugs/detect/DontIgnoreResultOfPutIfAbsent.java
index b5d016b..9d1d3c8 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DontIgnoreResultOfPutIfAbsent.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DontIgnoreResultOfPutIfAbsent.java
@@ -32,8 +32,6 @@ import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ArrayType;
import org.apache.bcel.generic.ConstantPoolGen;
-import org.apache.bcel.generic.IFNONNULL;
-import org.apache.bcel.generic.IFNULL;
import org.apache.bcel.generic.INVOKESTATIC;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionHandle;
@@ -50,7 +48,6 @@ import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.Detector;
import edu.umd.cs.findbugs.Priorities;
import edu.umd.cs.findbugs.SourceLineAnnotation;
-import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.TypeAnnotation;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.CFG;
@@ -64,6 +61,7 @@ import edu.umd.cs.findbugs.ba.XClass;
import edu.umd.cs.findbugs.ba.XField;
import edu.umd.cs.findbugs.ba.ch.Subtypes2;
import edu.umd.cs.findbugs.ba.type.TypeDataflow;
+import edu.umd.cs.findbugs.ba.type.TypeFrame;
import edu.umd.cs.findbugs.ba.vna.ValueNumber;
import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
@@ -73,6 +71,7 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.DescriptorFactory;
import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
+import edu.umd.cs.findbugs.util.ClassName;
public class DontIgnoreResultOfPutIfAbsent implements Detector {
@@ -84,43 +83,45 @@ public class DontIgnoreResultOfPutIfAbsent implements Detector {
final ClassDescriptor concurrentMapDescriptor = DescriptorFactory.createClassDescriptor(ConcurrentMap.class);
+ // private final boolean testingEnabled;
+
public DontIgnoreResultOfPutIfAbsent(BugReporter bugReporter) {
this.bugReporter = bugReporter;
this.accumulator = new BugAccumulator(bugReporter);
+ // testingEnabled = SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors");
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.Detector#report()
- */
+ @Override
public void report() {
- // TODO Auto-generated method stub
-
+ //
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
ConstantPool pool = javaClass.getConstantPool();
boolean found = false;
- for (Constant constantEntry : pool.getConstantPool())
+ for (Constant constantEntry : pool.getConstantPool()) {
if (constantEntry instanceof ConstantNameAndType) {
ConstantNameAndType nt = (ConstantNameAndType) constantEntry;
- if (nt.getName(pool).equals("putIfAbsent")) {
+ if ("putIfAbsent".equals(nt.getName(pool))) {
found = true;
break;
}
}
- if (!found)
+ }
+ if (!found) {
return;
+ }
Method[] methodList = javaClass.getMethods();
for (Method method : methodList) {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -152,50 +153,60 @@ public class DontIgnoreResultOfPutIfAbsent implements Detector {
ClassDescriptor cd = DescriptorFactory.getClassDescriptor((ObjectType) type);
@SlashedClassName
String className = cd.getClassName();
- if (immutableClassNames.contains(className))
+ if (immutableClassNames.contains(className)) {
return Priorities.LOW_PRIORITY;
+ }
XClass xClass = AnalysisContext.currentXFactory().getXClass(cd);
- if (xClass == null)
+ if (xClass == null) {
return Priorities.IGNORE_PRIORITY;
+ }
ClassDescriptor superclassDescriptor = xClass.getSuperclassDescriptor();
if (superclassDescriptor != null) {
@SlashedClassName
String superClassName = superclassDescriptor.getClassName();
- if (superClassName.equals("java/lang/Enum"))
+ if ("java/lang/Enum".equals(superClassName)) {
return Priorities.LOW_PRIORITY;
+ }
}
boolean hasMutableField = false;
boolean hasUpdates = false;
- for (XField f : xClass.getXFields())
+ for (XField f : xClass.getXFields()) {
if (!f.isStatic()) {
if (!f.isFinal() && !f.isSynthetic()) {
hasMutableField = true;
- if (unreadFields.isWrittenOutsideOfInitialization(f))
+ if (unreadFields.isWrittenOutsideOfInitialization(f)) {
hasUpdates = true;
+ }
}
String signature = f.getSignature();
if (signature.startsWith("Ljava/util/concurrent") || signature.startsWith("Ljava/lang/StringB")
|| signature.charAt(0) == '[' || signature.indexOf("Map") >= 0 || signature.indexOf("List") >= 0
- || signature.indexOf("Set") >= 0)
+ || signature.indexOf("Set") >= 0) {
hasMutableField = hasUpdates = true;
+ }
}
+ }
- if (!hasMutableField && !xClass.isInterface() && !xClass.isAbstract())
+ if (!hasMutableField && !xClass.isInterface() && !xClass.isAbstract()) {
return Priorities.LOW_PRIORITY;
+ }
if (hasUpdates || className.startsWith("java/util") || className.indexOf("Map") >= 0
- || className.indexOf("List") >= 0)
+ || className.indexOf("List") >= 0) {
return Priorities.HIGH_PRIORITY;
+ }
return Priorities.NORMAL_PRIORITY;
- } else
+ } else {
return Priorities.IGNORE_PRIORITY;
+ }
}
private void analyzeMethod(ClassContext classContext, Method method) throws DataflowAnalysisException, CFGBuilderException {
- if (BCELUtil.isSynthetic(method) || (method.getAccessFlags() & Constants.ACC_BRIDGE) == Constants.ACC_BRIDGE)
+ if (BCELUtil.isSynthetic(method) || (method.getAccessFlags() & Constants.ACC_BRIDGE) == Constants.ACC_BRIDGE) {
return;
+ }
if (DEBUG) {
System.out.println(" Analyzing method " + classContext.getJavaClass().getClassName() + "." + method.getName());
@@ -220,68 +231,76 @@ public class DontIgnoreResultOfPutIfAbsent implements Detector {
if (ins instanceof InvokeInstruction) {
InvokeInstruction invoke = (InvokeInstruction) ins;
- String className = invoke.getClassName(cpg);
-
- if (invoke.getMethodName(cpg).equals("putIfAbsent")) {
+ if ("putIfAbsent".equals(invoke.getMethodName(cpg))) {
String signature = invoke.getSignature(cpg);
- if (signature.equals("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
- && !(invoke instanceof INVOKESTATIC) && extendsConcurrentMap(className)) {
- InstructionHandle next = handle.getNext();
- boolean isIgnored = next != null && next.getInstruction() instanceof POP;
- boolean isImmediateNullTest = next != null
- && (next.getInstruction() instanceof IFNULL || next.getInstruction() instanceof IFNONNULL);
- if (countOtherCalls || isIgnored) {
- BitSet live = llsaDataflow.getAnalysis().getFactAtLocation(location);
- ValueNumberFrame vna = vnaDataflow.getAnalysis().getFactAtLocation(location);
- ValueNumber vn = vna.getTopValue();
-
- int locals = vna.getNumLocals();
- boolean isRetained = false;
- for (int pos = 0; pos < locals; pos++)
- if (vna.getValue(pos).equals(vn) && live.get(pos)) {
- BugAnnotation ba = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, location, vn,
- vnaDataflow.getFactAtLocation(location), "VALUE_OF");
- if (ba == null)
- continue;
- String pattern = "RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED";
- if (!isIgnored)
- pattern = "UNKNOWN";
- Type type = typeDataflow.getAnalysis().getFactAtLocation(location).getTopValue();
- int priority = getPriorityForBeingMutable(type);
- BugInstance bugInstance = new BugInstance(this, pattern, priority)
- .addClassAndMethod(methodGen, sourceFileName).addCalledMethod(methodGen, invoke)
- .add(new TypeAnnotation(type)).add(ba);
- SourceLineAnnotation where = SourceLineAnnotation.fromVisitedInstruction(classContext,
- method, location);
- accumulator.accumulateBug(bugInstance, where);
- isRetained = true;
- break;
+ if ("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;".equals(signature)
+ && !(invoke instanceof INVOKESTATIC)) {
+ TypeFrame typeFrame = typeDataflow.getFactAtLocation(location);
+ Type objType = typeFrame.getStackValue(2);
+ if(extendsConcurrentMap(ClassName.toDottedClassName(ClassName.fromFieldSignature(objType.getSignature())))) {
+ InstructionHandle next = handle.getNext();
+ boolean isIgnored = next != null && next.getInstruction() instanceof POP;
+ // boolean isImmediateNullTest = next != null
+ // && (next.getInstruction() instanceof IFNULL || next.getInstruction() instanceof IFNONNULL);
+ if (countOtherCalls || isIgnored) {
+ BitSet live = llsaDataflow.getAnalysis().getFactAtLocation(location);
+ ValueNumberFrame vna = vnaDataflow.getAnalysis().getFactAtLocation(location);
+ ValueNumber vn = vna.getTopValue();
+
+ int locals = vna.getNumLocals();
+ // boolean isRetained = false;
+ for (int pos = 0; pos < locals; pos++) {
+ if (vna.getValue(pos).equals(vn) && live.get(pos)) {
+ BugAnnotation ba = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, location, vn,
+ vnaDataflow.getFactAtLocation(location), "VALUE_OF");
+ if (ba == null) {
+ continue;
+ }
+ String pattern = "RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED";
+ if (!isIgnored) {
+ pattern = "UNKNOWN";
+ }
+ Type type = typeFrame.getTopValue();
+ int priority = getPriorityForBeingMutable(type);
+ BugInstance bugInstance = new BugInstance(this, pattern, priority)
+ .addClassAndMethod(methodGen, sourceFileName).addCalledMethod(methodGen, invoke)
+ .add(new TypeAnnotation(type)).add(ba);
+ SourceLineAnnotation where = SourceLineAnnotation.fromVisitedInstruction(classContext,
+ method, location);
+ accumulator.accumulateBug(bugInstance, where);
+ // isRetained = true;
+ break;
+ }
}
- if (countOtherCalls && !isRetained && SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors")) {
+ }
+ /*
+ if (testingEnabled && (countOtherCalls && !isRetained)) {
int priority = LOW_PRIORITY;
if (!isImmediateNullTest && !isIgnored) {
TypeDataflow typeAnalysis = classContext.getTypeDataflow(method);
Type type = typeAnalysis.getFactAtLocation(location).getTopValue();
String valueSignature = type.getSignature();
- if (!valueSignature.startsWith("Ljava/util/concurrent/atomic/Atomic"))
+ if (!valueSignature.startsWith("Ljava/util/concurrent/atomic/Atomic")) {
priority = Priorities.HIGH_PRIORITY;
+ }
}
BugInstance bugInstance = new BugInstance(this, "TESTING", priority)
- .addClassAndMethod(methodGen, sourceFileName).addString("Counting putIfAbsentCalls")
- .addCalledMethod(methodGen, invoke);
+ .addClassAndMethod(methodGen, sourceFileName).addString("Counting putIfAbsentCalls")
+ .addCalledMethod(methodGen, invoke);
SourceLineAnnotation where = SourceLineAnnotation.fromVisitedInstruction(classContext, method,
location);
accumulator.accumulateBug(bugInstance, where);
}
-
+ */
}
- } else if (countOtherCalls) {
+ } /* else if (testingEnabled && countOtherCalls) {
BugInstance bugInstance = new BugInstance(this, "TESTING2", Priorities.NORMAL_PRIORITY)
- .addClassAndMethod(methodGen, sourceFileName).addCalledMethod(methodGen, invoke);
+ .addClassAndMethod(methodGen, sourceFileName).addCalledMethod(methodGen, invoke);
SourceLineAnnotation where = SourceLineAnnotation.fromVisitedInstruction(classContext, method, location);
accumulator.accumulateBug(bugInstance, where);
}
+ */
}
}
@@ -290,15 +309,17 @@ public class DontIgnoreResultOfPutIfAbsent implements Detector {
}
private boolean extendsConcurrentMap(@DottedClassName String className) {
- if (className.equals("java.util.concurrent.ConcurrentHashMap")
- || className.equals(concurrentMapDescriptor.getDottedClassName()))
+ if ("java.util.concurrent.ConcurrentHashMap".equals(className)
+ || className.equals(concurrentMapDescriptor.getDottedClassName())) {
return true;
+ }
ClassDescriptor c = DescriptorFactory.createClassDescriptorFromDottedClassName(className);
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
try {
- if (subtypes2.isSubtype(c, concurrentMapDescriptor))
+ if (subtypes2.isSubtype(c, concurrentMapDescriptor)) {
return true;
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/DontUseEnum.java b/src/java/edu/umd/cs/findbugs/detect/DontUseEnum.java
index 451a844..45b3914 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DontUseEnum.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DontUseEnum.java
@@ -52,7 +52,7 @@ public class DontUseEnum extends PreorderDetector {
}
private boolean isReservedName(String name) {
- return name.equals("enum") || name.equals("assert");
+ return "enum".equals(name) || "assert".equals(name);
}
@Override
@@ -70,7 +70,7 @@ public class DontUseEnum extends PreorderDetector {
LocalVariableAnnotation var = new LocalVariableAnnotation(obj.getName(), obj.getIndex(), obj.getStartPC());
SourceLineAnnotation source = SourceLineAnnotation.fromVisitedInstruction(getClassContext(), this, obj.getStartPC());
BugInstance bug = new BugInstance(this, "NM_FUTURE_KEYWORD_USED_AS_IDENTIFIER", NORMAL_PRIORITY)
- .addClassAndMethod(this).add(var).add(source);
+ .addClassAndMethod(this).add(var).add(source);
bugReporter.reportBug(bug);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/DoomedCodeWarningProperty.java b/src/java/edu/umd/cs/findbugs/detect/DoomedCodeWarningProperty.java
index 290277e..4c1d379 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DoomedCodeWarningProperty.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DoomedCodeWarningProperty.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.props.PriorityAdjustment;
/**
* A WarningProperty for warnings that are reported at a "doomed" Location; one
* that cannot return normally.
- *
+ *
* @author David Hovemeyer
*/
public class DoomedCodeWarningProperty extends AbstractWarningProperty {
diff --git a/src/java/edu/umd/cs/findbugs/detect/DroppedException.java b/src/java/edu/umd/cs/findbugs/detect/DroppedException.java
index 087facd..1d44dea 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DroppedException.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DroppedException.java
@@ -67,23 +67,27 @@ public class DroppedException extends PreorderVisitor implements Detector {
public DroppedException(BugReporter bugReporter) {
this.bugReporter = bugReporter;
this.bugAccumulator = new BugAccumulator(bugReporter);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Dropped Exception debugging turned on");
+ }
}
+ @Override
public void visitClassContext(ClassContext classContext) {
this.classContext = classContext;
classContext.getJavaClass().accept(this);
bugAccumulator.reportAccumulatedBugs();
-
+
}
+ @Override
public void report() {
}
boolean isChecked(String c) {
- if (!causes.add(c))
+ if (!causes.add(c)) {
return checkedCauses.contains(c);
+ }
try {
if (Hierarchy.isSubtype(c, "java.lang.Exception") && !Hierarchy.isSubtype(c, "java.lang.RuntimeException")) {
checkedCauses.add(c);
@@ -104,8 +108,9 @@ public class DroppedException extends PreorderVisitor implements Detector {
CodeException[] exp = obj.getExceptionTable();
LineNumberTable lineNumbers = obj.getLineNumberTable();
- if (exp == null)
+ if (exp == null) {
return;
+ }
byte[] code = obj.getCode();
for (CodeException aExp : exp) {
@@ -128,66 +133,77 @@ public class DroppedException extends PreorderVisitor implements Detector {
j += 1 + NO_OF_OPERANDS[opcode];
if (opcode >= IRETURN && opcode <= RETURN || opcode >= IFEQ && opcode <= GOTO && (opcode != GOTO || j < end)) {
exitInTryBlock = true;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\texit: " + opcode + " in " + getFullyQualifiedMethodName());
+ }
break;
}
}
if (exitInTryBlock) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Exit in try block");
+ }
continue;
}
- if (handled < 5)
+ if (handled < 5) {
continue;
+ }
@DottedClassName String causeName;
- if (cause == 0)
+ if (cause == 0) {
causeName = "java.lang.Throwable";
- else {
+ } else {
causeName = Utility.compactClassName(getConstantPool().getConstantString(cause, CONSTANT_Class), false);
- if (!isChecked(causeName))
+ if (!isChecked(causeName)) {
continue;
+ }
}
int jumpAtEnd = 0;
if (end < code.length && asUnsignedByte(code[end]) == GOTO) {
jumpAtEnd = getUnsignedShort(code, end + 1);
- if (jumpAtEnd < handled)
+ if (jumpAtEnd < handled) {
jumpAtEnd = 0;
+ }
}
int opcode = asUnsignedByte(code[handled]);
int afterHandler = 0;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("DE:\topcode is " + OPCODE_NAMES[opcode] + ", " + asUnsignedByte(code[handled + 1]));
+ }
boolean drops = false;
boolean startsWithASTORE03 = opcode >= ASTORE_0 && opcode <= ASTORE_3;
- if (startsWithASTORE03 && asUnsignedByte(code[handled + 1]) == RETURN) {
- if (DEBUG)
+ if (startsWithASTORE03 && asUnsignedByte(code[handled + 1]) == RETURN) {
+ if (DEBUG) {
System.out.println("Drop 1");
+ }
drops = true;
afterHandler = handled + 1;
}
if (handled + 2 < code.length && opcode == ASTORE && asUnsignedByte(code[handled + 2]) == RETURN) {
drops = true;
afterHandler = handled + 2;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Drop 2");
+ }
}
if (handled + 3 < code.length && !exitInTryBlock) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("DE: checking for jumps");
+ }
if (startsWithASTORE03 && asUnsignedByte(code[handled - 3]) == GOTO) {
int offsetBefore = getUnsignedShort(code, handled - 2);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("offset before = " + offsetBefore);
+ }
if (offsetBefore == 4) {
drops = true;
afterHandler = handled + 1;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Drop 3");
+ }
}
}
if (opcode == ASTORE && asUnsignedByte(code[handled - 3]) == GOTO) {
@@ -195,8 +211,9 @@ public class DroppedException extends PreorderVisitor implements Detector {
if (offsetBefore == 5) {
drops = true;
afterHandler = handled + 2;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Drop 4");
+ }
}
}
if (startsWithASTORE03 && asUnsignedByte(code[handled + 1]) == GOTO && asUnsignedByte(code[handled - 3]) == GOTO) {
@@ -206,8 +223,9 @@ public class DroppedException extends PreorderVisitor implements Detector {
if (offsetAfter > 0 && offsetAfter + 4 == offsetBefore) {
drops = true;
afterHandler = handled + 4;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Drop 5");
+ }
}
}
@@ -218,52 +236,61 @@ public class DroppedException extends PreorderVisitor implements Detector {
if (offsetAfter > 0 && offsetAfter + 5 == offsetBefore) {
drops = true;
afterHandler = handled + 5;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Drop 6");
+ }
}
}
}
boolean multiLineHandler = false;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("afterHandler = " + afterHandler + ", handled = " + handled);
+ }
if (afterHandler > handled && lineNumbers != null) {
int startHandlerLinenumber = lineNumbers.getSourceLine(handled);
int endHandlerLinenumber = getNextExecutableLineNumber(lineNumbers, afterHandler) - 1;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Handler in lines " + startHandlerLinenumber + "-" + endHandlerLinenumber);
+ }
if (endHandlerLinenumber > startHandlerLinenumber) {
multiLineHandler = true;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Multiline handler");
+ }
}
}
- if (end - start >= 4 && drops && !causeName.equals("java.lang.InterruptedException")
- && !causeName.equals("java.lang.CloneNotSupportedException")) {
+ if (end - start >= 4 && drops && !"java.lang.InterruptedException".equals(causeName)
+ && !"java.lang.CloneNotSupportedException".equals(causeName)) {
int priority = NORMAL_PRIORITY;
- if (exitInTryBlock)
+ if (exitInTryBlock) {
priority++;
- if (end - start == 4)
+ }
+ if (end - start == 4) {
priority++;
+ }
SourceLineAnnotation srcLine = SourceLineAnnotation.fromVisitedInstruction(this.classContext, this, handled);
if (srcLine != null && LOOK_IN_SOURCE_TO_FIND_COMMENTED_CATCH_BLOCKS) {
- if (catchBlockHasComment(srcLine))
+ if (catchBlockHasComment(srcLine)) {
return;
- else
+ } else {
priority++;
+ }
} else {
// can't look at source
- if (lineNumbers == null || multiLineHandler)
+ if (lineNumbers == null || multiLineHandler) {
priority += 2;
+ }
}
- if (causeName.equals("java.lang.Error") || causeName.equals("java.lang.Exception") || causeName.equals("java.lang.Throwable")
- || causeName.equals("java.lang.RuntimeException")) {
+ if ("java.lang.Error".equals(causeName) || "java.lang.Exception".equals(causeName) || "java.lang.Throwable".equals(causeName)
+ || "java.lang.RuntimeException".equals(causeName)) {
priority--;
- if (end - start > 30)
+ if (end - start > 30) {
priority--;
+ }
}
int register = -1;
@@ -278,24 +305,27 @@ public class DroppedException extends PreorderVisitor implements Detector {
if (DEBUG) {
System.out.println("Name: " + name);
}
- if (name.startsWith("ignore") || name.startsWith("cant"))
+ if (name.startsWith("ignore") || name.startsWith("cant")) {
continue;
+ }
}
if (DEBUG) {
System.out.println("Priority is " + priority);
}
- if (priority > LOW_PRIORITY)
+ if (priority > LOW_PRIORITY) {
return;
- if (priority < HIGH_PRIORITY)
+ }
+ if (priority < HIGH_PRIORITY) {
priority = HIGH_PRIORITY;
+ }
if (DEBUG) {
System.out.println("reporting warning");
}
BugInstance bugInstance = new BugInstance(this, exitInTryBlock ? "DE_MIGHT_DROP" : "DE_MIGHT_IGNORE", priority)
- .addClassAndMethod(this);
+ .addClassAndMethod(this);
bugInstance.addClass(causeName).describe("CLASS_EXCEPTION");
bugInstance.addSourceLine(srcLine);
bugAccumulator.accumulateBug(bugInstance, srcLine);
@@ -310,20 +340,23 @@ public class DroppedException extends PreorderVisitor implements Detector {
int i = 0;
for (; i < entries.length && entries[i].getStartPC() < PC; i++) {
int line = entries[i].getLineNumber();
- if (line > beforePC)
+ if (line > beforePC) {
beforePC = line;
+ }
}
if (i < entries.length) {
int secondChoice = entries[i].getLineNumber();
for (; i < entries.length; i++) {
int line = entries[i].getLineNumber();
- if (line > beforePC)
+ if (line > beforePC) {
return line;
+ }
}
return secondChoice;
- } else
+ } else {
return entries[entries.length - 1].getLineNumber();
+ }
}
private static final int START = 0;
@@ -352,13 +385,14 @@ public class DroppedException extends PreorderVisitor implements Detector {
/**
* Analyze a class's source code to see if there is a comment (or other
* text) in a catch block we have marked as dropping an exception.
- *
+ *
* @return true if there is a comment in the catch block, false if not (or
* if we can't tell)
*/
private boolean catchBlockHasComment(SourceLineAnnotation srcLine) {
- if (!LOOK_IN_SOURCE_TO_FIND_COMMENTED_CATCH_BLOCKS)
+ if (!LOOK_IN_SOURCE_TO_FIND_COMMENTED_CATCH_BLOCKS) {
return false;
+ }
SourceFinder sourceFinder = AnalysisContext.currentAnalysisContext().getSourceFinder();
try {
@@ -366,12 +400,15 @@ public class DroppedException extends PreorderVisitor implements Detector {
int startLine = srcLine.getStartLine();
int scanStartLine = startLine - NUM_CONTEXT_LINES;
- if (scanStartLine < 1)
+ if (scanStartLine < 1) {
scanStartLine = 1;
+ }
int offset = sourceFile.getLineOffset(scanStartLine - 1);
if (offset < 0)
+ {
return false; // Source file has changed?
+ }
Tokenizer tokenizer = new Tokenizer(UTF8.reader(sourceFile.getInputStreamFromOffset(offset)));
// Read the tokens into an ArrayList,
@@ -382,12 +419,14 @@ public class DroppedException extends PreorderVisitor implements Detector {
for (int line = scanStartLine; line < scanStartLine + MAX_LINES;) {
Token token = tokenizer.next();
int kind = token.getKind();
- if (kind == Token.EOF)
+ if (kind == Token.EOF) {
break;
+ }
if (kind == Token.EOL) {
- if (line == startLine)
+ if (line == startLine) {
eolOfCatchBlockStart = tokenList.size();
+ }
++line;
}
@@ -395,8 +434,10 @@ public class DroppedException extends PreorderVisitor implements Detector {
}
if (eolOfCatchBlockStart < 0)
+ {
return false; // Couldn't scan line reported as start of catch
- // block
+ // block
+ }
// Starting at the end of the line reported as the start of the
// catch block,
@@ -406,14 +447,16 @@ public class DroppedException extends PreorderVisitor implements Detector {
while (iter.hasPrevious()) {
Token token = iter.previous();
- if (token.getKind() == Token.WORD && token.getLexeme().equals("catch")) {
+ if (token.getKind() == Token.WORD && "catch".equals(token.getLexeme())) {
foundCatch = true;
break;
}
}
if (!foundCatch)
+ {
return false; // Couldn't find "catch" keyword
+ }
// Scan forward from the "catch" keyword to see what text
// is in the handler block. If the block is non-empty,
@@ -425,8 +468,9 @@ public class DroppedException extends PreorderVisitor implements Detector {
int state = START;
int level = 0;
do {
- if (!iter.hasNext())
+ if (!iter.hasNext()) {
break;
+ }
Token token = iter.next();
int type = token.getKind();
@@ -434,42 +478,50 @@ public class DroppedException extends PreorderVisitor implements Detector {
switch (type) {
case Token.EOL:
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Saw token: [EOL]");
+ }
++numLines;
- if (numLines >= MAX_LINES)
+ if (numLines >= MAX_LINES) {
done = true;
+ }
break;
default:
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Got token: " + value);
+ }
switch (state) {
case START:
- if (value.equals("catch"))
+ if ("catch".equals(value)) {
state = CATCH;
+ }
break;
case CATCH:
- if (value.equals("("))
+ if ("(".equals(value)) {
state = OPEN_PAREN;
+ }
break;
case OPEN_PAREN:
- if (value.equals(")")) {
- if (level == 0)
+ if (")".equals(value)) {
+ if (level == 0) {
state = CLOSE_PAREN;
- else
+ } else {
--level;
- } else if (value.equals("(")) {
+ }
+ } else if ("(".equals(value)) {
++level;
}
break;
case CLOSE_PAREN:
- if (value.equals("{"))
+ if ("{".equals(value)) {
state = OPEN_BRACE;
+ }
break;
case OPEN_BRACE:
- boolean closeBrace = value.equals("}");
- if (DEBUG && !closeBrace)
+ boolean closeBrace = "}".equals(value);
+ if (DEBUG && !closeBrace) {
System.out.println("Found a comment in catch block: " + value);
+ }
return !closeBrace;
}
break;
@@ -483,4 +535,3 @@ public class DroppedException extends PreorderVisitor implements Detector {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/DumbMethodInvocations.java b/src/java/edu/umd/cs/findbugs/detect/DumbMethodInvocations.java
index 1bb75f8..22fb516 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DumbMethodInvocations.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DumbMethodInvocations.java
@@ -1,7 +1,9 @@
package edu.umd.cs.findbugs.detect;
import java.io.File;
+import java.util.Collections;
import java.util.Iterator;
+import java.util.Map;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ConstantPoolGen;
@@ -23,33 +25,52 @@ import edu.umd.cs.findbugs.ba.MethodUnprofitableException;
import edu.umd.cs.findbugs.ba.constant.Constant;
import edu.umd.cs.findbugs.ba.constant.ConstantDataflow;
import edu.umd.cs.findbugs.ba.constant.ConstantFrame;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+import edu.umd.cs.findbugs.detect.BuildStringPassthruGraph.MethodParameter;
+import edu.umd.cs.findbugs.detect.BuildStringPassthruGraph.StringPassthruDatabase;
public class DumbMethodInvocations implements Detector {
+ private static final MethodDescriptor STRING_SUBSTRING =
+ new MethodDescriptor("java/lang/String", "substring", "(I)Ljava/lang/String;");
+
private final BugReporter bugReporter;
private final BugAccumulator bugAccumulator;
+ private final Map<MethodDescriptor, int[]> allFileNameStringMethods;
+ private final Map<MethodDescriptor, int[]> allDatabasePasswordMethods;
+
public DumbMethodInvocations(BugReporter bugReporter) {
this.bugReporter = bugReporter;
this.bugAccumulator = new BugAccumulator(bugReporter);
+
+ StringPassthruDatabase database = Global.getAnalysisCache().getDatabase(StringPassthruDatabase.class);
+ allFileNameStringMethods = database.getFileNameStringMethods();
+ allDatabasePasswordMethods = database.findLinkedMethods(Collections.singleton(new MethodParameter(new MethodDescriptor(
+ "java/sql/DriverManager", "getConnection",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/sql/Connection;", true), 2)));
}
+ @Override
public void visitClassContext(ClassContext classContext) {
Method[] methodList = classContext.getJavaClass().getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
bugAccumulator.reportAccumulatedBugs();
} catch (MethodUnprofitableException mue) {
- if (SystemProperties.getBoolean("unprofitable.debug")) // otherwise
- // don't
- // report
+ if (SystemProperties.getBoolean("unprofitable.debug")) {
+ // don't
+ // report
bugReporter.logError("skipping unprofitable method in " + getClass().getName());
+ }
} catch (CFGBuilderException e) {
bugReporter.logError("Detector " + this.getClass().getName() + " caught exception", e);
} catch (DataflowAnalysisException e) {
@@ -69,8 +90,9 @@ public class DumbMethodInvocations implements Detector {
Location location = i.next();
Instruction ins = location.getHandle().getInstruction();
- if (!(ins instanceof InvokeInstruction))
+ if (!(ins instanceof InvokeInstruction)) {
continue;
+ }
InvokeInstruction iins = (InvokeInstruction) ins;
ConstantFrame frame = constantDataflow.getFactAtLocation(location);
@@ -79,51 +101,56 @@ public class DumbMethodInvocations implements Detector {
continue;
}
- if (iins.getName(cpg).equals("getConnection")
- && iins.getSignature(cpg).equals(
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/sql/Connection;")
- && iins.getClassName(cpg).equals("java.sql.DriverManager")) {
- Constant operandValue = frame.getTopValue();
- if (operandValue.isConstantString()) {
- String password = operandValue.getConstantString();
- if (password.length() == 0)
- bugAccumulator.accumulateBug(new BugInstance(this, "DMI_EMPTY_DB_PASSWORD", NORMAL_PRIORITY)
- .addClassAndMethod(methodGen, sourceFile), classContext, methodGen, sourceFile, location);
- else
- bugAccumulator.accumulateBug(new BugInstance(this, "DMI_CONSTANT_DB_PASSWORD", NORMAL_PRIORITY)
- .addClassAndMethod(methodGen, sourceFile), classContext, methodGen, sourceFile, location);
+ MethodDescriptor md = new MethodDescriptor(iins, cpg);
+ if (allDatabasePasswordMethods.containsKey(md)) {
+ for(int paramNumber : allDatabasePasswordMethods.get(md)) {
+ Constant operandValue = frame.getStackValue(iins.getArgumentTypes(cpg).length-1-paramNumber);
+ if (operandValue.isConstantString()) {
+ String password = operandValue.getConstantString();
+ if (password.length() == 0) {
+ bugAccumulator.accumulateBug(new BugInstance(this, "DMI_EMPTY_DB_PASSWORD", NORMAL_PRIORITY)
+ .addClassAndMethod(methodGen, sourceFile), classContext, methodGen, sourceFile, location);
+ } else {
+ bugAccumulator.accumulateBug(new BugInstance(this, "DMI_CONSTANT_DB_PASSWORD", NORMAL_PRIORITY)
+ .addClassAndMethod(methodGen, sourceFile), classContext, methodGen, sourceFile, location);
+ }
+ }
}
}
- if (iins.getName(cpg).equals("substring") && iins.getSignature(cpg).equals("(I)Ljava/lang/String;")
- && iins.getClassName(cpg).equals("java.lang.String")) {
+ if (md.equals(STRING_SUBSTRING)) {
Constant operandValue = frame.getTopValue();
- if (!operandValue.isConstantInteger())
+ if (!operandValue.isConstantInteger()) {
continue;
+ }
int v = operandValue.getConstantInt();
- if (v == 0)
+ if (v == 0) {
bugAccumulator.accumulateBug(new BugInstance(this, "DMI_USELESS_SUBSTRING", NORMAL_PRIORITY)
- .addClassAndMethod(methodGen, sourceFile), classContext, methodGen, sourceFile, location);
-
- } else if (iins.getName(cpg).equals("<init>") && iins.getSignature(cpg).equals("(Ljava/lang/String;)V")
- && iins.getClassName(cpg).equals("java.io.File")) {
+ .addClassAndMethod(methodGen, sourceFile), classContext, methodGen, sourceFile, location);
+ }
- Constant operandValue = frame.getTopValue();
- if (!operandValue.isConstantString())
- continue;
- String v = operandValue.getConstantString();
- if (isAbsoluteFileName(v) && !v.startsWith("/etc/") && !v.startsWith("/dev/")
- && !v.startsWith("/proc")) {
- int priority = NORMAL_PRIORITY;
- if (v.startsWith("/tmp"))
- priority = LOW_PRIORITY;
- else if (v.indexOf("/home") >= 0)
- priority = HIGH_PRIORITY;
- bugAccumulator.accumulateBug(new BugInstance(this, "DMI_HARDCODED_ABSOLUTE_FILENAME", priority)
- .addClassAndMethod(methodGen, sourceFile).addString(v).describe("FILE_NAME"), classContext,
- methodGen, sourceFile, location);
+ } else if (allFileNameStringMethods.containsKey(md)) {
+
+ for(int paramNumber : allFileNameStringMethods.get(md)) {
+ Constant operandValue = frame.getStackValue(iins.getArgumentTypes(cpg).length-1-paramNumber);
+ if (!operandValue.isConstantString()) {
+ continue;
+ }
+ String v = operandValue.getConstantString();
+ if (isAbsoluteFileName(v) && !v.startsWith("/etc/") && !v.startsWith("/dev/")
+ && !v.startsWith("/proc")) {
+ int priority = NORMAL_PRIORITY;
+ if (v.startsWith("/tmp")) {
+ priority = LOW_PRIORITY;
+ } else if (v.indexOf("/home") >= 0) {
+ priority = HIGH_PRIORITY;
+ }
+ bugAccumulator.accumulateBug(new BugInstance(this, "DMI_HARDCODED_ABSOLUTE_FILENAME", priority)
+ .addClassAndMethod(methodGen, sourceFile).addString(v).describe("FILE_NAME"), classContext,
+ methodGen, sourceFile, location);
+ }
}
}
@@ -132,14 +159,22 @@ public class DumbMethodInvocations implements Detector {
}
private boolean isAbsoluteFileName(String v) {
- if (v.startsWith("/dev/"))
+ if (v.startsWith("/dev/")) {
return false;
- if (v.startsWith("/"))
- return true;
- if (v.startsWith("C:"))
+ }
+ if (v.startsWith("/")) {
return true;
- if (v.startsWith("c:"))
+ }
+ if (v.startsWith("\\\\")) {
+ // UNC pathname like \\Server\share\...
return true;
+ }
+ if (v.length() >= 2 && v.charAt(1) == ':') {
+ char driveletter = v.charAt(0);
+ if((driveletter >= 'A' && driveletter <= 'Z') || (driveletter >= 'a' && driveletter <= 'z')) {
+ return true;
+ }
+ }
try {
File f = new File(v);
return f.isAbsolute();
@@ -148,6 +183,7 @@ public class DumbMethodInvocations implements Detector {
}
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/DumbMethods.java b/src/java/edu/umd/cs/findbugs/detect/DumbMethods.java
index a27ed9c..2ec0328 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DumbMethods.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DumbMethods.java
@@ -45,7 +45,6 @@ import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.ClassAnnotation;
import edu.umd.cs.findbugs.IntAnnotation;
-import edu.umd.cs.findbugs.JavaVersion;
import edu.umd.cs.findbugs.LocalVariableAnnotation;
import edu.umd.cs.findbugs.MethodAnnotation;
import edu.umd.cs.findbugs.OpcodeStack;
@@ -53,12 +52,14 @@ import edu.umd.cs.findbugs.OpcodeStack.Item;
import edu.umd.cs.findbugs.Priorities;
import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.StringAnnotation;
+import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.CFGBuilderException;
import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
import edu.umd.cs.findbugs.ba.Hierarchy;
import edu.umd.cs.findbugs.ba.ObjectTypeFactory;
import edu.umd.cs.findbugs.ba.SignatureParser;
+import edu.umd.cs.findbugs.ba.XField;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.ba.ch.Subtypes2;
import edu.umd.cs.findbugs.ba.type.TypeDataflow;
@@ -72,6 +73,440 @@ import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
public class DumbMethods extends OpcodeStackDetector {
+ private abstract class SubDetector {
+ public void initMethod(Method method) {}
+
+ abstract public void sawOpcode(int seen);
+ }
+
+ private class InvalidMinMaxSubDetector extends SubDetector {
+ Number lowerBound, upperBound;
+
+ @Override
+ public void initMethod(Method method) {
+ lowerBound = upperBound = null;
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if(seen == INVOKESTATIC && getClassConstantOperand().equals("java/lang/Math") && (getMethodDescriptorOperand().getName().equals("max")
+ || getMethodDescriptorOperand().getName().equals("min"))) {
+ Object const1 = stack.getStackItem(0).getConstant();
+ Object const2 = stack.getStackItem(1).getConstant();
+ Number n = null;
+ if(const1 != null ^ const2 != null) {
+ n = (const1 instanceof Number) ? (Number)const1 : (Number)const2;
+ if(getMethodDescriptorOperand().getName().equals("min")) {
+ upperBound = n;
+ } else {
+ lowerBound = n;
+ }
+ } else {
+ upperBound = lowerBound = null;
+ }
+ XMethod rvo1 = stack.getStackItem(0).getReturnValueOf();
+ XMethod rvo2 = stack.getStackItem(1).getReturnValueOf();
+ if(rvo1 != null ^ rvo2 != null) {
+ XMethod rvo = rvo1 == null ? rvo2 : rvo1;
+ if (lowerBound instanceof Comparable && upperBound != null && upperBound.getClass() == lowerBound.getClass()
+ && rvo.getClassDescriptor().getClassName().equals("java/lang/Math")
+ && (rvo.getName().equals("max") || rvo.getName().equals("min"))) {
+ @SuppressWarnings("unchecked")
+ int result = ((Comparable<Number>)lowerBound).compareTo(upperBound);
+ if(result > 0) {
+ accumulator.accumulateBug(
+ new BugInstance("DM_INVALID_MIN_MAX", HIGH_PRIORITY).addClassAndMethod(DumbMethods.this)
+ .addString(String.valueOf(n)),
+ DumbMethods.this);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private class NullMethodsSubDetector extends SubDetector {
+
+ @Override
+ public void sawOpcode(int seen) {
+ if (seen == INVOKESTATIC && ("com/google/common/base/Preconditions".equals(getClassConstantOperand())
+ && "checkNotNull".equals(getNameConstantOperand())
+ || "com/google/common/base/Strings".equals(getClassConstantOperand())
+ && ("nullToEmpty".equals(getNameConstantOperand()) ||
+ "emptyToNull".equals(getNameConstantOperand()) ||
+ "isNullOrEmpty".equals(getNameConstantOperand())))
+ ) {
+ int args = PreorderVisitor.getNumberArguments(getSigConstantOperand());
+
+ OpcodeStack.Item item = stack.getStackItem(args - 1);
+ Object o = item.getConstant();
+ if (o instanceof String) {
+
+ OpcodeStack.Item secondArgument = null;
+ String bugPattern = "DMI_DOH";
+ if (args > 1) {
+ secondArgument = stack.getStackItem(args - 2);
+ Object secondConstant = secondArgument.getConstant();
+ if (!(secondConstant instanceof String)) {
+ bugPattern = "DMI_ARGUMENTS_WRONG_ORDER";
+ }
+ }
+
+ BugInstance bug = new BugInstance(DumbMethods.this, bugPattern, NORMAL_PRIORITY).addClassAndMethod(DumbMethods.this)
+ .addCalledMethod(DumbMethods.this)
+ .addString("Passing String constant as value that should be null checked").describe(StringAnnotation.STRING_MESSAGE)
+ .addString((String) o).describe(StringAnnotation.STRING_CONSTANT_ROLE);
+ if (secondArgument != null) {
+ bug.addValueSource(secondArgument, DumbMethods.this);
+ }
+
+ accumulator.accumulateBug(bug, DumbMethods.this);
+ }
+ }
+
+ if (seen == INVOKESTATIC && ("junit/framework/Assert".equals(getClassConstantOperand()) || "org/junit/Assert".equals(getClassConstantOperand()))
+ && "assertNotNull".equals(getNameConstantOperand())) {
+ int args = PreorderVisitor.getNumberArguments(getSigConstantOperand());
+
+ OpcodeStack.Item item = stack.getStackItem(0);
+ Object o = item.getConstant();
+ if (o instanceof String) {
+
+ OpcodeStack.Item secondArgument = null;
+ String bugPattern = "DMI_DOH";
+ if (args == 2) {
+ secondArgument = stack.getStackItem(1);
+ Object secondConstant = secondArgument.getConstant();
+ if (!(secondConstant instanceof String)) {
+ bugPattern = "DMI_ARGUMENTS_WRONG_ORDER";
+ }
+ }
+
+ BugInstance bug = new BugInstance(DumbMethods.this, bugPattern, NORMAL_PRIORITY).addClassAndMethod(DumbMethods.this)
+ .addCalledMethod(DumbMethods.this).addString("Passing String constant as value that should be null checked").describe(StringAnnotation.STRING_MESSAGE)
+ .addString((String) o).describe(StringAnnotation.STRING_CONSTANT_ROLE);
+ if (secondArgument != null) {
+ bug.addValueSource(secondArgument, DumbMethods.this);
+ }
+
+ accumulator.accumulateBug(bug, DumbMethods.this);
+ }
+ }
+ }
+ }
+
+ private class FutilePoolSizeSubDetector extends SubDetector {
+ @Override
+ public void sawOpcode(int seen) {
+ if (seen == INVOKEVIRTUAL && "java/util/concurrent/ScheduledThreadPoolExecutor".equals(getClassConstantOperand())
+ && "setMaximumPoolSize".equals(getNameConstantOperand())) {
+ accumulator.accumulateBug(new BugInstance(DumbMethods.this,
+ "DMI_FUTILE_ATTEMPT_TO_CHANGE_MAXPOOL_SIZE_OF_SCHEDULED_THREAD_POOL_EXECUTOR", HIGH_PRIORITY)
+ .addClassAndMethod(DumbMethods.this), DumbMethods.this);
+ }
+ }
+ }
+
+ static int saturatingIncrement(int value) {
+ if (value == Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ }
+ return value+1;
+ }
+
+ private class RangeCheckSubDetector extends SubDetector {
+
+
+
+ private void checkRange(Item item, Object minValue, Object maxValue, String pattern) {
+ if(!(item.getConstant() instanceof Number)) {
+ return;
+ }
+ int value = ((Number)item.getConstant()).intValue();
+ int intMin = Integer.MIN_VALUE;
+ int intMax = Integer.MAX_VALUE;
+ if(minValue instanceof Number) {
+ intMin = ((Number)minValue).intValue();
+ }
+ if(maxValue instanceof Number) {
+ intMax = ((Number)maxValue).intValue();
+ } else if(maxValue instanceof String) {
+ intMax = ((String)maxValue).length()-1;
+ } else if (maxValue instanceof OpcodeStack.Item){
+ OpcodeStack.Item maxItem = (OpcodeStack.Item ) maxValue;
+ if (maxItem.getSignature().charAt(0) == '[' && maxItem.getConstant() instanceof Integer) {
+ intMax = ((Integer)maxItem.getConstant())-1;
+
+ }
+ }
+
+ if(value < intMin || value > intMax) {
+ BugInstance bug = new BugInstance(pattern, NORMAL_PRIORITY ).addClassAndMethod(DumbMethods.this).addSourceLine(DumbMethods.this)
+ .addInt(value).describe(IntAnnotation.INT_VALUE);
+
+ if (intMin <= intMax) {
+ if (value < intMin) {
+ bug.addInt(intMin).describe(IntAnnotation.INT_MIN_VALUE);
+ }
+ if (value > intMax) {
+ bug.addInt(intMax) .describe(IntAnnotation.INT_MAX_VALUE);
+ }
+ }
+
+
+ if (isMethodCall()) {
+ bug.addCalledMethod(DumbMethods.this);
+ }
+
+
+
+ accumulator.accumulateBug(bug, DumbMethods.this);
+ }
+ }
+
+
+ @Override
+ public void sawOpcode(int seen) {
+ // System.out.printf("%4d %s%n", getPC(), OPCODE_NAMES[seen]);
+ switch(seen) {
+ case IALOAD:
+ case AALOAD:
+ case SALOAD:
+ case CALOAD:
+ case BALOAD:
+ case LALOAD:
+ case DALOAD:
+ case FALOAD: {
+ checkRange(stack.getStackItem(0), 0, stack.getStackItem(1), "RANGE_ARRAY_INDEX");
+ break;
+ }
+ case IASTORE:
+ case AASTORE:
+ case SASTORE:
+ case CASTORE:
+ case BASTORE:
+ case LASTORE:
+ case DASTORE:
+ case FASTORE: {
+
+ checkRange(stack.getStackItem(1), 0, stack.getStackItem(2), "RANGE_ARRAY_INDEX");
+ break;
+ }
+ case INVOKESTATIC: {
+ MethodDescriptor m = getMethodDescriptorOperand();
+ if(m.getSlashedClassName().equals("java/lang/System") && m.getName().equals("arraycopy")) {
+ // void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
+ Item length = stack.getStackItem(0);
+ Object constantLength = length.getConstant();
+ // if (constantLength instanceof Number && constantLength.equals(0)) {
+ // break;
+ // }
+ Item srcPos = stack.getStackItem(3);
+ Item src = stack.getStackItem(4);
+ checkRange(srcPos, 0, src, "RANGE_ARRAY_OFFSET");
+ Item dest = stack.getStackItem(2);
+ Item destPos = stack.getStackItem(1);
+ checkRange(destPos, 0, dest, "RANGE_ARRAY_OFFSET");
+
+ if(constantLength instanceof Number) {
+ int length1 = Integer.MAX_VALUE;
+ if(src.getConstant() instanceof Integer) {
+ length1 = (int) src.getConstant();
+ }
+ if(srcPos.getConstant() instanceof Integer) {
+ length1 -= (int) srcPos.getConstant();
+ }
+ int length2 = Integer.MAX_VALUE;
+ if(dest.getConstant() instanceof Integer) {
+ length2 = (int) stack.getStackItem(2).getConstant();
+ }
+ if(destPos.getConstant() instanceof Integer) {
+ length2 -= (int) stack.getStackItem(1).getConstant();
+ }
+ checkRange(length, 0, Math.min(length1, length2), "RANGE_ARRAY_LENGTH");
+ }
+ }
+ break;
+ }
+ case INVOKEVIRTUAL:
+ case INVOKESPECIAL: {
+ MethodDescriptor m = getMethodDescriptorOperand();
+ if(m.getSlashedClassName().equals("java/lang/String")) {
+ if((m.getName().equals("charAt") || m.getName().equals("codePointAt")) && m.getSignature().startsWith("(I)")) {
+ checkRange(stack.getStackItem(0), 0, stack.getStackItem(1).getConstant(), "RANGE_STRING_INDEX");
+ }
+ if(m.getName().equals("substring") || m.getName().equals("subSequence")) {
+ int nArgs = getNumberArguments(m.getSignature());
+ Item thisArg = stack.getStackItem(nArgs);
+ Item firstArg = stack.getStackItem(nArgs-1);
+ Object thisConstantValue = thisArg.getConstant();
+ int maxLength = thisConstantValue instanceof String ? ((String)thisConstantValue).length() : Integer.MAX_VALUE;
+ checkRange(firstArg, 0,maxLength, "RANGE_STRING_INDEX");
+ if(nArgs == 2) {
+ Item secondArg = stack.getStackItem(0);
+ checkRange(secondArg, firstArg.getConstant() == null ? 0 : firstArg.getConstant(),
+ maxLength,
+ "RANGE_STRING_INDEX");
+ }
+ }
+ }
+ if ((m.getSignature().startsWith("([BII)") || m.getSignature().startsWith("([CII)") || m.getSignature().startsWith("([III)"))
+ && (((m.getName().equals("write") || m.getName().equals("read")) && m.getSlashedClassName().startsWith(
+ "java/io/")) || (m.getName().equals("<init>") && m.getSlashedClassName().equals("java/lang/String")))) {
+ Item arrayArg = stack.getStackItem(2);
+ Item offsetArg = stack.getStackItem(1);
+ Item lengthArg = stack.getStackItem(0);
+ int length = Integer.MAX_VALUE;
+ if(arrayArg.getConstant() instanceof Integer) {
+ length = (int) arrayArg.getConstant();
+ }
+ if(offsetArg.getConstant() instanceof Integer) {
+ checkRange(offsetArg, 0, saturatingIncrement(length), "RANGE_ARRAY_OFFSET");
+ length -= (int) offsetArg.getConstant();
+ }
+ checkRange(lengthArg, 0, saturatingIncrement(length), "RANGE_ARRAY_LENGTH");
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ private class UrlCollectionSubDetector extends SubDetector {
+ @Override
+ public void sawOpcode(int seen) {
+ if ((seen == INVOKEVIRTUAL && "java/util/HashMap".equals(getClassConstantOperand()) && "get".equals(getNameConstantOperand()))
+ || (seen == INVOKEINTERFACE && "java/util/Map".equals(getClassConstantOperand()) && "get".equals(getNameConstantOperand()))
+ || (seen == INVOKEVIRTUAL && "java/util/HashSet".equals(getClassConstantOperand()) && "contains".equals(getNameConstantOperand()))
+ || (seen == INVOKEINTERFACE && "java/util/Set".equals(getClassConstantOperand()) && "contains".equals(getNameConstantOperand()))) {
+ OpcodeStack.Item top = stack.getStackItem(0);
+ if ("Ljava/net/URL;".equals(top.getSignature())) {
+ accumulator.accumulateBug(new BugInstance(DumbMethods.this, "DMI_COLLECTION_OF_URLS", HIGH_PRIORITY)
+ .addClassAndMethod(DumbMethods.this), DumbMethods.this);
+ }
+ }
+ }
+ }
+
+ private class VacuousComparisonSubDetector extends SubDetector {
+ @Override
+ public void sawOpcode(int seen) {
+ boolean foundVacuousComparison = false;
+ if (seen == IF_ICMPGT || seen == IF_ICMPLE) {
+ OpcodeStack.Item rhs = stack.getStackItem(0);
+ Object rhsConstant = rhs.getConstant();
+ if (rhsConstant instanceof Integer && ((Integer) rhsConstant).intValue() == Integer.MAX_VALUE) {
+ foundVacuousComparison = true;
+ }
+ OpcodeStack.Item lhs = stack.getStackItem(1);
+ Object lhsConstant = lhs.getConstant();
+ if (lhsConstant instanceof Integer && ((Integer) lhsConstant).intValue() == Integer.MIN_VALUE) {
+ foundVacuousComparison = true;
+ }
+
+ }
+ if (seen == IF_ICMPLT || seen == IF_ICMPGE) {
+ OpcodeStack.Item rhs = stack.getStackItem(0);
+ Object rhsConstant = rhs.getConstant();
+ if (rhsConstant instanceof Integer && ((Integer) rhsConstant).intValue() == Integer.MIN_VALUE) {
+ foundVacuousComparison = true;
+ }
+ OpcodeStack.Item lhs = stack.getStackItem(1);
+ Object lhsConstant = lhs.getConstant();
+ if (lhsConstant instanceof Integer && ((Integer) lhsConstant).intValue() == Integer.MAX_VALUE) {
+ foundVacuousComparison = true;
+ }
+
+ }
+ if (foundVacuousComparison) {
+ accumulator.accumulateBug(new BugInstance(DumbMethods.this, "INT_VACUOUS_COMPARISON", getBranchOffset() < 0 ? HIGH_PRIORITY
+ : NORMAL_PRIORITY).addClassAndMethod(DumbMethods.this), DumbMethods.this);
+ }
+ }
+ }
+
+ private class BadCastInEqualsSubDetector extends SubDetector {
+ private boolean isEqualsObject;
+
+ private boolean sawInstanceofCheck;
+
+ private boolean reportedBadCastInEquals;
+
+ @Override
+ public void initMethod(Method method) {
+ isEqualsObject = "equals".equals(getMethodName()) && "(Ljava/lang/Object;)Z".equals(getMethodSig()) && !method.isStatic();
+ sawInstanceofCheck = false;
+ reportedBadCastInEquals = false;
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if (isEqualsObject && !reportedBadCastInEquals) {
+ if (seen == INVOKEVIRTUAL && "isInstance".equals(getNameConstantOperand())
+ && "java/lang/Class".equals(getClassConstantOperand())) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ if (item.getRegisterNumber() == 1) {
+ sawInstanceofCheck = true;
+ }
+ } else if (seen == INSTANCEOF || seen == INVOKEVIRTUAL && "getClass".equals(getNameConstantOperand())
+ && "()Ljava/lang/Class;".equals(getSigConstantOperand())) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ if (item.getRegisterNumber() == 1) {
+ sawInstanceofCheck = true;
+ }
+ } else if (seen == INVOKESPECIAL && "equals".equals(getNameConstantOperand())
+ && "(Ljava/lang/Object;)Z".equals(getSigConstantOperand())) {
+ OpcodeStack.Item item0 = stack.getStackItem(0);
+ OpcodeStack.Item item1 = stack.getStackItem(1);
+ if (item1.getRegisterNumber() + item0.getRegisterNumber() == 1) {
+ sawInstanceofCheck = true;
+ }
+ } else if (seen == CHECKCAST && !sawInstanceofCheck) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ if (item.getRegisterNumber() == 1) {
+ if (getSizeOfSurroundingTryBlock(getPC()) == Integer.MAX_VALUE) {
+ accumulator.accumulateBug(new BugInstance(DumbMethods.this, "BC_EQUALS_METHOD_SHOULD_WORK_FOR_ALL_OBJECTS",
+ NORMAL_PRIORITY).addClassAndMethod(DumbMethods.this), DumbMethods.this);
+ }
+
+ reportedBadCastInEquals = true;
+ }
+ }
+ }
+ }
+ }
+
+ private class RandomOnceSubDetector extends SubDetector {
+ private boolean freshRandomOnTos = false;
+
+ private boolean freshRandomOneBelowTos = false;
+
+ @Override
+ public void initMethod(Method method) {
+ freshRandomOnTos = false;
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if (seen == INVOKEVIRTUAL && "java/util/Random".equals(getClassConstantOperand())
+ && (freshRandomOnTos || freshRandomOneBelowTos)) {
+ accumulator.accumulateBug(new BugInstance(DumbMethods.this, "DMI_RANDOM_USED_ONLY_ONCE", HIGH_PRIORITY)
+ .addClassAndMethod(DumbMethods.this).addCalledMethod(DumbMethods.this), DumbMethods.this);
+
+ }
+ freshRandomOneBelowTos = freshRandomOnTos && isRegisterLoad();
+ freshRandomOnTos = seen == INVOKESPECIAL && "java/util/Random".equals(getClassConstantOperand())
+ && "<init>".equals(getNameConstantOperand());
+ }
+ }
+
+ private final SubDetector[] subDetectors = new SubDetector[] { new VacuousComparisonSubDetector(),
+ new RangeCheckSubDetector(), new BadCastInEqualsSubDetector(), new FutilePoolSizeSubDetector(),
+ new UrlCollectionSubDetector(), new RandomOnceSubDetector(), new NullMethodsSubDetector(),
+ new InvalidMinMaxSubDetector()};
+
private static final ObjectType CONDITION_TYPE = ObjectTypeFactory.getInstance("java.util.concurrent.locks.Condition");
private final BugReporter bugReporter;
@@ -97,12 +532,6 @@ public class DumbMethods extends OpcodeStackDetector {
private boolean isPublicStaticVoidMain;
- private boolean isEqualsObject;
-
- private boolean sawInstanceofCheck;
-
- private boolean reportedBadCastInEquals;
-
private int sawCheckForNonNegativeSignedByte;
private int sinceBufferedInputStreamReady;
@@ -111,19 +540,24 @@ public class DumbMethods extends OpcodeStackDetector {
private boolean checkForBitIorofSignedByte;
- private final boolean jdk15ChecksEnabled;
+ /**
+ * A heuristic - how long a catch block for OutOfMemoryError might be.
+ */
+ private static final int OOM_CATCH_LEN = 20;
+
+ private final boolean testingEnabled;
private final BugAccumulator accumulator;
private final BugAccumulator absoluteValueAccumulator;
private static final int MICROS_PER_DAY_OVERFLOWED_AS_INT
- = 24 * 60 * 60 * 1000 * 1000;
+ = 24 * 60 * 60 * 1000 * 1000;
public DumbMethods(BugReporter bugReporter) {
this.bugReporter = bugReporter;
accumulator = new BugAccumulator(bugReporter);
absoluteValueAccumulator = new BugAccumulator(bugReporter);
- jdk15ChecksEnabled = JavaVersion.getRuntimeVersion().isSameOrNewerThan(JavaVersion.JAVA_1_5);
+ testingEnabled = SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors");
}
boolean isSynthetic;
@@ -131,7 +565,7 @@ public class DumbMethods extends OpcodeStackDetector {
@Override
public void visit(JavaClass obj) {
String superclassName = obj.getSuperclassName();
- isSynthetic = superclassName.equals("java.rmi.server.RemoteStub");
+ isSynthetic = "java.rmi.server.RemoteStub".equals(superclassName);
Attribute[] attributes = obj.getAttributes();
if (attributes != null) {
for (Attribute a : attributes) {
@@ -155,14 +589,16 @@ public class DumbMethods extends OpcodeStackDetector {
@Override
public void visit(Field field) {
ConstantValue value = field.getConstantValue();
- if (value == null) return;
+ if (value == null) {
+ return;
+ }
Constant c = getConstantPool().getConstant(value.getConstantValueIndex());
- if (c instanceof ConstantLong && ((ConstantLong)c).getBytes() == MICROS_PER_DAY_OVERFLOWED_AS_INT) {
+ if (testingEnabled && c instanceof ConstantLong && ((ConstantLong)c).getBytes() == MICROS_PER_DAY_OVERFLOWED_AS_INT) {
bugReporter.reportBug( new BugInstance(this, "TESTING", HIGH_PRIORITY).addClass(this).addField(this)
- .addString("Did you mean MICROS_PER_DAY")
- .addInt(MICROS_PER_DAY_OVERFLOWED_AS_INT)
- .describe(IntAnnotation.INT_VALUE));
+ .addString("Did you mean MICROS_PER_DAY")
+ .addInt(MICROS_PER_DAY_OVERFLOWED_AS_INT)
+ .describe(IntAnnotation.INT_VALUE));
}
}
@@ -170,29 +606,29 @@ public class DumbMethods extends OpcodeStackDetector {
public void visit(Method method) {
String cName = getDottedClassName();
+ for(SubDetector subDetector : subDetectors) {
+ subDetector.initMethod(method);
+ }
+
// System.out.println(getFullyQualifiedMethodName());
- isPublicStaticVoidMain = method.isPublic() && method.isStatic() && getMethodName().equals("main")
+ isPublicStaticVoidMain = method.isPublic() && method.isStatic() && "main".equals(getMethodName())
|| cName.toLowerCase().indexOf("benchmark") >= 0;
- prevOpcodeWasReadLine = false;
- Code code = method.getCode();
- if (code != null) {
- this.exceptionTable = code.getExceptionTable();
- }
- if (this.exceptionTable == null) {
- this.exceptionTable = new CodeException[0];
- }
- primitiveObjCtorSeen = null;
- ctorSeen = false;
- randomNextIntState = 0;
- checkForBitIorofSignedByte = false;
- isEqualsObject = getMethodName().equals("equals") && getMethodSig().equals("(Ljava/lang/Object;)Z") && !method.isStatic();
- sawInstanceofCheck = false;
- reportedBadCastInEquals = false;
- freshRandomOnTos = false;
- sinceBufferedInputStreamReady = 100000;
- sawCheckForNonNegativeSignedByte = -1000;
- sawLoadOfMinValue = false;
- previousMethodCall = null;
+ prevOpcodeWasReadLine = false;
+ Code code = method.getCode();
+ if (code != null) {
+ this.exceptionTable = code.getExceptionTable();
+ }
+ if (this.exceptionTable == null) {
+ this.exceptionTable = new CodeException[0];
+ }
+ primitiveObjCtorSeen = null;
+ ctorSeen = false;
+ randomNextIntState = 0;
+ checkForBitIorofSignedByte = false;
+ sinceBufferedInputStreamReady = 100000;
+ sawCheckForNonNegativeSignedByte = -1000;
+ sawLoadOfMinValue = false;
+ previousMethodCall = null;
}
@@ -202,38 +638,34 @@ public class DumbMethods extends OpcodeStackDetector {
SourceLineAnnotation pendingAbsoluteValueBugSourceLine;
- boolean freshRandomOnTos = false;
-
- boolean freshRandomOneBelowTos = false;
-
boolean sawLoadOfMinValue = false;
MethodDescriptor previousMethodCall = null;
@Override
public void sawOpcode(int seen) {
-
+
if (isMethodCall()) {
MethodDescriptor called = getMethodDescriptorOperand();
if (previousMethodCall != null && !stack.isJumpTarget(getPC())) {
- if (called.getName().equals("toString")
- && called.getClassDescriptor().getClassName().equals("java/lang/Integer")
- && previousMethodCall.getName().equals("valueOf")
- && previousMethodCall.getSignature().equals("(I)Ljava/lang/Integer;")
+ if ("toString".equals(called.getName())
+ && "java/lang/Integer".equals(called.getClassDescriptor().getClassName())
+ && "valueOf".equals(previousMethodCall.getName())
+ && "(I)Ljava/lang/Integer;".equals(previousMethodCall.getSignature())
) {
MethodAnnotation preferred = new MethodAnnotation("java.lang.Integer", "toString", "(I)Ljava/lang/String;", true);
BugInstance bug = new BugInstance(this, "DM_BOXED_PRIMITIVE_TOSTRING", HIGH_PRIORITY).addClassAndMethod(this)
.addCalledMethod(this).addMethod(preferred).describe(MethodAnnotation.SHOULD_CALL);
accumulator.accumulateBug(bug, this);
- } else if (called.getName().equals("intValue")
- && called.getClassDescriptor().getClassName().equals("java/lang/Integer")
- && previousMethodCall.getSlashedClassName().equals("java/lang/Integer")
- && (previousMethodCall.getName().equals("<init>")
- && previousMethodCall.getSignature().equals("(Ljava/lang/String;)V")
- || previousMethodCall.getName().equals("valueOf")
- && previousMethodCall.getSignature().equals("(Ljava/lang/String;)Ljava/lang/Integer;")
+ } else if ("intValue".equals(called.getName())
+ && "java/lang/Integer".equals(called.getClassDescriptor().getClassName())
+ && "java/lang/Integer".equals(previousMethodCall.getSlashedClassName())
+ && ("<init>".equals(previousMethodCall.getName())
+ && "(Ljava/lang/String;)V".equals(previousMethodCall.getSignature())
+ || "valueOf".equals(previousMethodCall.getName())
+ && "(Ljava/lang/String;)Ljava/lang/Integer;".equals(previousMethodCall.getSignature())
)) {
MethodAnnotation preferred = new MethodAnnotation("java.lang.Integer", "parseInt", "(Ljava/lang/String;)I", true);
@@ -241,29 +673,57 @@ public class DumbMethods extends OpcodeStackDetector {
BugInstance bug = new BugInstance(this, "DM_BOXED_PRIMITIVE_FOR_PARSING", HIGH_PRIORITY).addClassAndMethod(this)
.addCalledMethod(this).addMethod(preferred).describe(MethodAnnotation.SHOULD_CALL);
accumulator.accumulateBug(bug, this);
- } else if (called.getName().equals("longValue")
- && called.getClassDescriptor().getClassName().equals("java/lang/Long")
- && previousMethodCall.getSlashedClassName().equals("java/lang/Long")
- && ( previousMethodCall.getName().equals("<init>")
- && previousMethodCall.getSignature().equals("(Ljava/lang/String;)V")
- || previousMethodCall.getName().equals("valueOf")
- && previousMethodCall.getSignature().equals("(Ljava/lang/String;)Ljava/lang/Long;"))
+ } else if ("longValue".equals(called.getName())
+ && "java/lang/Long".equals(called.getClassDescriptor().getClassName())
+ && "java/lang/Long".equals(previousMethodCall.getSlashedClassName())
+ && ( "<init>".equals(previousMethodCall.getName())
+ && "(Ljava/lang/String;)V".equals(previousMethodCall.getSignature())
+ || "valueOf".equals(previousMethodCall.getName())
+ && "(Ljava/lang/String;)Ljava/lang/Long;".equals(previousMethodCall.getSignature()))
) {
MethodAnnotation preferred = new MethodAnnotation("java.lang.Long", "parseLong", "(Ljava/lang/String;)J", true);
BugInstance bug = new BugInstance(this, "DM_BOXED_PRIMITIVE_FOR_PARSING", HIGH_PRIORITY).addClassAndMethod(this)
.addCalledMethod(this).addMethod(preferred).describe(MethodAnnotation.SHOULD_CALL);
accumulator.accumulateBug(bug, this);
+ } else if("compareTo".equals(called.getName())
+ && "valueOf".equals(previousMethodCall.getName())
+ && called.getClassDescriptor().equals(previousMethodCall.getClassDescriptor()) && !previousMethodCall.getSignature().startsWith("(Ljava/lang/String;")
+ ) {
+ String primitiveType = ClassName.getPrimitiveType(called.getClassDescriptor().getClassName());
+ XMethod rvo = stack.getStackItem(1).getReturnValueOf();
+ XField field = stack.getStackItem(1).getXField();
+ String signature;
+ if (rvo != null) {
+ signature = new SignatureParser(rvo.getSignature()).getReturnTypeSignature();
+ } else if (field != null) {
+ signature = field.getSignature();
+ } else {
+ signature = "";
+ }
+ if (primitiveType != null
+ && (previousMethodCall.equals(rvo) || signature.equals(primitiveType))
+ && (getThisClass().getMajor() >= MAJOR_1_7 || getThisClass().getMajor() >= MAJOR_1_4
+ && (primitiveType.equals("D") || primitiveType.equals("F")))) {
+ MethodDescriptor shouldCall = new MethodDescriptor(called.getClassDescriptor().getClassName(), "compare",
+ "(" + primitiveType + primitiveType + ")I", true);
+ BugInstance bug = new BugInstance(this, "DM_BOXED_PRIMITIVE_FOR_COMPARE",
+ primitiveType.equals("Z") ? LOW_PRIORITY : primitiveType.equals("B") ? NORMAL_PRIORITY
+ : HIGH_PRIORITY).addClassAndMethod(this).addCalledMethod(this).addMethod(shouldCall)
+ .describe(MethodAnnotation.SHOULD_CALL);
+ accumulator.accumulateBug(bug, this);
+ }
}
}
previousMethodCall = called;
- } else
+ } else {
previousMethodCall = null;
-
+ }
+
if (seen == LDC || seen == LDC_W || seen == LDC2_W) {
Constant c = getConstantRefOperand();
- if ((c instanceof ConstantInteger && ((ConstantInteger) c).getBytes() == MICROS_PER_DAY_OVERFLOWED_AS_INT
+ if (testingEnabled && (c instanceof ConstantInteger && ((ConstantInteger) c).getBytes() == MICROS_PER_DAY_OVERFLOWED_AS_INT
|| c instanceof ConstantLong && ((ConstantLong) c).getBytes() == MICROS_PER_DAY_OVERFLOWED_AS_INT)) {
BugInstance bug = new BugInstance(this, "TESTING", HIGH_PRIORITY).addClassAndMethod(this)
.addString("Did you mean MICROS_PER_DAY").addInt(MICROS_PER_DAY_OVERFLOWED_AS_INT)
@@ -287,7 +747,7 @@ public class DumbMethods extends OpcodeStackDetector {
checkForCompatibleLongComparison(right, left);
}
- if (stack.getStackDepth() >= 2)
+ if (stack.getStackDepth() >= 2) {
switch (seen) {
case IF_ICMPEQ:
case IF_ICMPNE:
@@ -306,18 +766,22 @@ public class DumbMethods extends OpcodeStackDetector {
XMethod returnValueOf = item0.getReturnValueOf();
if (constant1 instanceof Integer
&& returnValueOf != null
- && returnValueOf.getName().equals("getYear")
- && (returnValueOf.getClassName().equals("java.util.Date") || returnValueOf.getClassName().equals(
- "java.sql.Date"))) {
+ && "getYear".equals(returnValueOf.getName())
+ && ("java.util.Date".equals(returnValueOf.getClassName()) || "java.sql.Date".equals(returnValueOf.getClassName()))) {
int year = (Integer) constant1;
- if (year > 1900)
+ if (testingEnabled && year > 1900) {
accumulator.accumulateBug(
new BugInstance(this, "TESTING", HIGH_PRIORITY).addClassAndMethod(this)
- .addString("Comparison of getYear does understand that it returns year-1900")
- .addMethod(returnValueOf).describe(MethodAnnotation.METHOD_CALLED).addInt(year)
- .describe(IntAnnotation.INT_VALUE), this);
+ .addString("Comparison of getYear does understand that it returns year-1900")
+ .addMethod(returnValueOf).describe(MethodAnnotation.METHOD_CALLED).addInt(year)
+ .describe(IntAnnotation.INT_VALUE), this);
+ }
}
+ break;
+ default:
+ break;
}
+ }
// System.out.printf("%4d %10s: %s\n", getPC(), OPCODE_NAMES[seen],
// stack);
@@ -336,6 +800,7 @@ public class DumbMethods extends OpcodeStackDetector {
pendingAbsoluteValueBug.setPriority(Priorities.LOW_PRIORITY);
}
}
+ /*
if (false)
try {
pendingAbsoluteValueBug.addString(OPCODE_NAMES[getPrevOpcode(1)] + ":" + OPCODE_NAMES[seen] + ":"
@@ -344,6 +809,7 @@ public class DumbMethods extends OpcodeStackDetector {
pendingAbsoluteValueBug.addString(OPCODE_NAMES[getPrevOpcode(1)] + ":" + OPCODE_NAMES[seen]);
}
+ */
absoluteValueAccumulator.accumulateBug(pendingAbsoluteValueBug, pendingAbsoluteValueBugSourceLine);
pendingAbsoluteValueBug = null;
pendingAbsoluteValueBugSourceLine = null;
@@ -351,81 +817,21 @@ public class DumbMethods extends OpcodeStackDetector {
}
if (seen == INVOKESTATIC
- && getClassConstantOperand().equals("org/easymock/EasyMock")
- && (getNameConstantOperand().equals("replay") || getNameConstantOperand().equals("verify") || getNameConstantOperand()
- .startsWith("reset")) && getSigConstantOperand().equals("([Ljava/lang/Object;)V")
- && getPrevOpcode(1) == ANEWARRAY && getPrevOpcode(2) == ICONST_0)
+ && "org/easymock/EasyMock".equals(getClassConstantOperand())
+ && ("replay".equals(getNameConstantOperand()) || "verify".equals(getNameConstantOperand()) || getNameConstantOperand()
+ .startsWith("reset")) && "([Ljava/lang/Object;)V".equals(getSigConstantOperand())
+ && getPrevOpcode(1) == ANEWARRAY && getPrevOpcode(2) == ICONST_0) {
accumulator.accumulateBug(new BugInstance(this, "DMI_VACUOUS_CALL_TO_EASYMOCK_METHOD", NORMAL_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this), this);
-
- if (seen == INVOKESTATIC && (getClassConstantOperand().equals("com/google/common/base/Preconditions")
- && getNameConstantOperand().equals("checkNotNull")
- || getClassConstantOperand().equals("com/google/common/base/Strings")
- && (getNameConstantOperand().equals("nullToEmpty") ||
- getNameConstantOperand().equals("emptyToNull") ||
- getNameConstantOperand().equals("isNullOrEmpty")))
- ) {
- int args = PreorderVisitor.getNumberArguments(getSigConstantOperand());
-
- OpcodeStack.Item item = stack.getStackItem(args - 1);
- Object o = item.getConstant();
- if (o instanceof String) {
-
- OpcodeStack.Item secondArgument = null;
- String bugPattern = "DMI_DOH";
- if (args > 1) {
- secondArgument = stack.getStackItem(args - 2);
- Object secondConstant = secondArgument.getConstant();
- if (!(secondConstant instanceof String)) {
- bugPattern = "DMI_ARGUMENTS_WRONG_ORDER";
- }
- }
-
- BugInstance bug = new BugInstance(this, bugPattern, NORMAL_PRIORITY).addClassAndMethod(this)
- .addCalledMethod(this)
- .addString("Passing String constant as value that should be null checked").describe(StringAnnotation.STRING_MESSAGE)
- .addString((String) o).describe(StringAnnotation.STRING_CONSTANT_ROLE);
- if (secondArgument != null)
- bug.addValueSource(secondArgument, this);
-
- accumulator.accumulateBug(bug, this);
- }
+ .addClassAndMethod(this).addCalledMethod(this), this);
}
- if (seen == INVOKESTATIC && getClassConstantOperand().equals("junit/framework/Assert")
- && getNameConstantOperand().equals("assertNotNull")) {
- int args = PreorderVisitor.getNumberArguments(getSigConstantOperand());
-
- OpcodeStack.Item item = stack.getStackItem(0);
- Object o = item.getConstant();
- if (o instanceof String) {
-
- OpcodeStack.Item secondArgument = null;
- String bugPattern = "DMI_DOH";
- if (args == 2) {
- secondArgument = stack.getStackItem(1);
- Object secondConstant = secondArgument.getConstant();
- if (!(secondConstant instanceof String)) {
- bugPattern = "DMI_ARGUMENTS_WRONG_ORDER";
- }
- }
-
- BugInstance bug = new BugInstance(this, bugPattern, NORMAL_PRIORITY).addClassAndMethod(this)
- .addCalledMethod(this).addString("Passing String constant as value that should be null checked").describe(StringAnnotation.STRING_MESSAGE)
- .addString((String) o).describe(StringAnnotation.STRING_CONSTANT_ROLE);
- if (secondArgument != null)
- bug.addValueSource(secondArgument, this);
-
- accumulator.accumulateBug(bug, this);
- }
- }
if ((seen == INVOKESTATIC || seen == INVOKEVIRTUAL || seen == INVOKESPECIAL || seen == INVOKEINTERFACE)
&& getSigConstantOperand().indexOf("Ljava/lang/Runnable;") >= 0) {
SignatureParser parser = new SignatureParser(getSigConstantOperand());
int count = 0;
for (Iterator<String> i = parser.parameterSignatureIterator(); i.hasNext(); count++) {
String parameter = i.next();
- if (parameter.equals("Ljava/lang/Runnable;")) {
+ if ("Ljava/lang/Runnable;".equals(parameter)) {
OpcodeStack.Item item = stack.getStackItem(parser.getNumParameters() - 1 - count);
if ("Ljava/lang/Thread;".equals(item.getSignature())) {
accumulator.accumulateBug(new BugInstance(this, "DMI_THREAD_PASSED_WHERE_RUNNABLE_EXPECTED",
@@ -437,43 +843,16 @@ public class DumbMethods extends OpcodeStackDetector {
}
- if (prevOpcode == I2L && seen == INVOKESTATIC && getClassConstantOperand().equals("java/lang/Double")
- && getNameConstantOperand().equals("longBitsToDouble")) {
+ if (prevOpcode == I2L && seen == INVOKESTATIC && "java/lang/Double".equals(getClassConstantOperand())
+ && "longBitsToDouble".equals(getNameConstantOperand())) {
accumulator.accumulateBug(new BugInstance(this, "DMI_LONG_BITS_TO_DOUBLE_INVOKED_ON_INT", HIGH_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this), this);
- }
-
- if (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/util/Random")
- && (freshRandomOnTos || freshRandomOneBelowTos)) {
- accumulator.accumulateBug(new BugInstance(this, "DMI_RANDOM_USED_ONLY_ONCE", HIGH_PRIORITY).addClassAndMethod(this)
- .addCalledMethod(this), this);
-
- }
-
- freshRandomOneBelowTos = freshRandomOnTos && isRegisterLoad();
- freshRandomOnTos = seen == INVOKESPECIAL && getClassConstantOperand().equals("java/util/Random")
- && getNameConstantOperand().equals("<init>");
-
- if ((seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/util/HashMap") && getNameConstantOperand().equals(
- "get"))
- || (seen == INVOKEINTERFACE && getClassConstantOperand().equals("java/util/Map") && getNameConstantOperand()
- .equals("get"))
- || (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/util/HashSet") && getNameConstantOperand()
- .equals("contains"))
- || (seen == INVOKEINTERFACE && getClassConstantOperand().equals("java/util/Set") && getNameConstantOperand()
- .equals("contains"))) {
- OpcodeStack.Item top = stack.getStackItem(0);
- if (top.getSignature().equals("Ljava/net/URL;")) {
- accumulator.accumulateBug(new BugInstance(this, "DMI_COLLECTION_OF_URLS", HIGH_PRIORITY).addClassAndMethod(this),
- this);
- }
-
+ .addClassAndMethod(this).addCalledMethod(this), this);
}
/**
* Since you can change the number of core threads for a scheduled
* thread pool executor, disabling this for now
- */
+ *
if (false && seen == INVOKESPECIAL
&& getClassConstantOperand().equals("java/util/concurrent/ScheduledThreadPoolExecutor")
&& getNameConstantOperand().equals("<init>")) {
@@ -486,94 +865,26 @@ public class DumbMethods extends OpcodeStackDetector {
HIGH_PRIORITY).addClassAndMethod(this), this);
}
- if (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/util/concurrent/ScheduledThreadPoolExecutor")
- && getNameConstantOperand().equals("setMaximumPoolSize")) {
- accumulator.accumulateBug(new BugInstance(this,
- "DMI_FUTILE_ATTEMPT_TO_CHANGE_MAXPOOL_SIZE_OF_SCHEDULED_THREAD_POOL_EXECUTOR", HIGH_PRIORITY)
- .addClassAndMethod(this), this);
- }
- if (isEqualsObject && !reportedBadCastInEquals) {
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("isInstance")
- && getClassConstantOperand().equals("java/lang/Class")) {
- OpcodeStack.Item item = stack.getStackItem(0);
- if (item.getRegisterNumber() == 1) {
- sawInstanceofCheck = true;
- }
- } else if (seen == INSTANCEOF || seen == INVOKEVIRTUAL && getNameConstantOperand().equals("getClass")
- && getSigConstantOperand().equals("()Ljava/lang/Class;")) {
- OpcodeStack.Item item = stack.getStackItem(0);
- if (item.getRegisterNumber() == 1) {
- sawInstanceofCheck = true;
- }
- } else if (seen == INVOKESPECIAL && getNameConstantOperand().equals("equals")
- && getSigConstantOperand().equals("(Ljava/lang/Object;)Z")) {
- OpcodeStack.Item item0 = stack.getStackItem(0);
- OpcodeStack.Item item1 = stack.getStackItem(1);
- if (item1.getRegisterNumber() + item0.getRegisterNumber() == 1) {
- sawInstanceofCheck = true;
- }
- } else if (seen == CHECKCAST && !sawInstanceofCheck) {
- OpcodeStack.Item item = stack.getStackItem(0);
- if (item.getRegisterNumber() == 1) {
- if (getSizeOfSurroundingTryBlock(getPC()) == Integer.MAX_VALUE) {
- accumulator.accumulateBug(new BugInstance(this, "BC_EQUALS_METHOD_SHOULD_WORK_FOR_ALL_OBJECTS",
- NORMAL_PRIORITY).addClassAndMethod(this), this);
- }
-
- reportedBadCastInEquals = true;
- }
- }
- }
- {
- boolean foundVacuousComparison = false;
- if (seen == IF_ICMPGT || seen == IF_ICMPLE) {
- OpcodeStack.Item rhs = stack.getStackItem(0);
- Object rhsConstant = rhs.getConstant();
- if (rhsConstant instanceof Integer && ((Integer) rhsConstant).intValue() == Integer.MAX_VALUE) {
- foundVacuousComparison = true;
- }
- OpcodeStack.Item lhs = stack.getStackItem(1);
- Object lhsConstant = lhs.getConstant();
- if (lhsConstant instanceof Integer && ((Integer) lhsConstant).intValue() == Integer.MIN_VALUE) {
- foundVacuousComparison = true;
- }
-
- }
- if (seen == IF_ICMPLT || seen == IF_ICMPGE) {
- OpcodeStack.Item rhs = stack.getStackItem(0);
- Object rhsConstant = rhs.getConstant();
- if (rhsConstant instanceof Integer && ((Integer) rhsConstant).intValue() == Integer.MIN_VALUE) {
- foundVacuousComparison = true;
- }
- OpcodeStack.Item lhs = stack.getStackItem(1);
- Object lhsConstant = lhs.getConstant();
- if (lhsConstant instanceof Integer && ((Integer) lhsConstant).intValue() == Integer.MAX_VALUE) {
- foundVacuousComparison = true;
- }
-
- }
- if (foundVacuousComparison) {
- accumulator.accumulateBug(new BugInstance(this, "INT_VACUOUS_COMPARISON", getBranchOffset() < 0 ? HIGH_PRIORITY
- : NORMAL_PRIORITY).addClassAndMethod(this), this);
- }
-
+ */
+ for(SubDetector subDetector : subDetectors) {
+ subDetector.sawOpcode(seen);
}
if (!sawLoadOfMinValue && seen == INVOKESTATIC &&
- ClassName.isMathClass(getClassConstantOperand()) && getNameConstantOperand().equals("abs")
+ ClassName.isMathClass(getClassConstantOperand()) && "abs".equals(getNameConstantOperand())
) {
OpcodeStack.Item item0 = stack.getStackItem(0);
int special = item0.getSpecialKind();
if (special == OpcodeStack.Item.RANDOM_INT) {
pendingAbsoluteValueBug = new BugInstance(this, "RV_ABSOLUTE_VALUE_OF_RANDOM_INT", HIGH_PRIORITY)
- .addClassAndMethod(this);
+ .addClassAndMethod(this);
pendingAbsoluteValueBugSourceLine = SourceLineAnnotation.fromVisitedInstruction(this);
opcodesSincePendingAbsoluteValueBug = 0;
}
else if (special == OpcodeStack.Item.HASHCODE_INT) {
pendingAbsoluteValueBug = new BugInstance(this, "RV_ABSOLUTE_VALUE_OF_HASHCODE", HIGH_PRIORITY)
- .addClassAndMethod(this);
+ .addClassAndMethod(this);
pendingAbsoluteValueBugSourceLine = SourceLineAnnotation.fromVisitedInstruction(this);
opcodesSincePendingAbsoluteValueBug = 0;
}
@@ -594,7 +905,8 @@ public class DumbMethods extends OpcodeStackDetector {
case OpcodeStack.Item.RANDOM_INT_REMAINDER:
accumulator.accumulateBug(
new BugInstance(this, "RV_REM_OF_RANDOM_INT", HIGH_PRIORITY).addClassAndMethod(this), this);
-
+ break;
+ default:
break;
}
@@ -618,8 +930,8 @@ public class DumbMethods extends OpcodeStackDetector {
int v = switchLabels[i];
if (v <= -129 || v >= 128) {
accumulator.accumulateBug(new BugInstance(this, "INT_BAD_COMPARISON_WITH_SIGNED_BYTE", HIGH_PRIORITY)
- .addClassAndMethod(this).addInt(v).describe(IntAnnotation.INT_VALUE),
- SourceLineAnnotation.fromVisitedInstruction(this, getPC() + switchOffsets[i]));
+ .addClassAndMethod(this).addInt(v).describe(IntAnnotation.INT_VALUE),
+ SourceLineAnnotation.fromVisitedInstruction(this, getPC() + switchOffsets[i]));
}
}
@@ -655,7 +967,8 @@ public class DumbMethods extends OpcodeStackDetector {
case IF_ICMPLE:
seen2 = IF_ICMPGE;
break;
-
+ default:
+ break;
}
}
Object constant1 = item1.getConstant();
@@ -663,7 +976,7 @@ public class DumbMethods extends OpcodeStackDetector {
int v1 = ((Number) constant1).intValue();
if (v1 <= -129 || v1 >= 128 || v1 == 127 && !(seen2 == IF_ICMPEQ || seen2 == IF_ICMPNE
- )) {
+ )) {
int priority = HIGH_PRIORITY;
if (v1 == 127) {
switch (seen2) {
@@ -699,18 +1012,19 @@ public class DumbMethods extends OpcodeStackDetector {
priority = NORMAL_PRIORITY;
}
- if (getPC() - sawCheckForNonNegativeSignedByte < 10)
+ if (getPC() - sawCheckForNonNegativeSignedByte < 10) {
priority++;
+ }
accumulator.accumulateBug(new BugInstance(this, "INT_BAD_COMPARISON_WITH_SIGNED_BYTE", priority)
- .addClassAndMethod(this).addInt(v1).describe(IntAnnotation.INT_VALUE), this);
+ .addClassAndMethod(this).addInt(v1).describe(IntAnnotation.INT_VALUE).addValueSource(item0, this), this);
}
} else if (item0.getSpecialKind() == OpcodeStack.Item.NON_NEGATIVE && constant1 instanceof Number) {
int v1 = ((Number) constant1).intValue();
if (v1 < 0) {
accumulator.accumulateBug(new BugInstance(this, "INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE",
- HIGH_PRIORITY).addClassAndMethod(this).addInt(v1).describe(IntAnnotation.INT_VALUE), this);
+ HIGH_PRIORITY).addClassAndMethod(this).addInt(v1).describe(IntAnnotation.INT_VALUE).addValueSource(item0, this), this);
}
}
@@ -719,6 +1033,54 @@ public class DumbMethods extends OpcodeStackDetector {
}
switch (seen) {
+ case IFGE:
+ case IFLT:
+ if(stack.getStackDepth() > 0 && stack.getStackItem(0).getSpecialKind() == OpcodeStack.Item.NON_NEGATIVE) {
+ OpcodeStack.Item top = stack.getStackItem(0);
+ if (top.getRegisterNumber() != -1 && getMaxPC() > getNextPC() + 6) {
+ if (false) {
+ for(int i = -2; i <= 0; i++) {
+ int o = getPrevOpcode(-i);
+ System.out.printf("%2d %3d %2x %s%n", i, o, o, OPCODE_NAMES[o]);
+ }
+ for(int i = 0; i < 7; i++) {
+ int o = getNextCodeByte(i);
+ System.out.printf("%2d %3d %2x %s%n", i, o, o, OPCODE_NAMES[o]);
+
+ }
+ }
+ int jump1, jump2;
+ if (seen == IFGE) {
+ jump1 = IF_ICMPLT;
+ jump2 = IF_ICMPLE;
+ } else {
+ jump1 = IF_ICMPGE;
+ jump2 = IF_ICMPGT;
+ }
+ int nextCodeByte0 = getNextCodeByte(0);
+ int loadConstant = 1;
+ if (nextCodeByte0 == ILOAD) {
+ loadConstant = 2;
+ }
+ int nextCodeByte1 = getNextCodeByte(loadConstant);
+ int nextCodeByte2 = getNextCodeByte(loadConstant+1);
+ int nextJumpOffset = loadConstant+2;
+ if (nextCodeByte1 == SIPUSH) {
+ nextJumpOffset++;
+ }
+ int nextCodeByteJump = getNextCodeByte(nextJumpOffset);
+
+ if (nextCodeByte0 == getPrevOpcode(1)
+ && (nextCodeByte1 == BIPUSH || nextCodeByte1 == SIPUSH)
+ && (IF_ICMPLT <= nextCodeByteJump && nextCodeByteJump <= IF_ICMPLE))
+ {
+ break;
+ }
+ }
+ accumulator.accumulateBug(new BugInstance(this, "INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE",
+ NORMAL_PRIORITY).addClassAndMethod(this).addInt(0).describe(IntAnnotation.INT_VALUE).addValueSource(top, this), this);
+ }
+ break;
case IAND:
case LAND:
case IOR:
@@ -732,8 +1094,9 @@ public class DumbMethods extends OpcodeStackDetector {
int prevPrevOpcode = getPrevOpcode(2);
if (rhs.hasConstantValue(badValue)
&& (prevOpcode == LDC || prevOpcode == ICONST_0 || prevOpcode == ICONST_M1 || prevOpcode == LCONST_0)
- && prevPrevOpcode != GOTO)
+ && prevPrevOpcode != GOTO) {
reportVacuousBitOperation(seen, lhs);
+ }
}
@@ -761,29 +1124,29 @@ public class DumbMethods extends OpcodeStackDetector {
}
if (prevOpcodeWasReadLine && sinceBufferedInputStreamReady >= 100 && seen == INVOKEVIRTUAL
- && getClassConstantOperand().equals("java/lang/String") && getSigConstantOperand().startsWith("()")) {
+ && "java/lang/String".equals(getClassConstantOperand()) && getSigConstantOperand().startsWith("()")) {
accumulator.accumulateBug(
new BugInstance(this, "NP_IMMEDIATE_DEREFERENCE_OF_READLINE", NORMAL_PRIORITY).addClassAndMethod(this),
this);
}
- if (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/io/BufferedReader")
- && getNameConstantOperand().equals("ready") && getSigConstantOperand().equals("()Z")) {
+ if (seen == INVOKEVIRTUAL && "java/io/BufferedReader".equals(getClassConstantOperand())
+ && "ready".equals(getNameConstantOperand()) && "()Z".equals(getSigConstantOperand())) {
sinceBufferedInputStreamReady = 0;
} else {
sinceBufferedInputStreamReady++;
}
prevOpcodeWasReadLine = (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE)
- && getNameConstantOperand().equals("readLine") && getSigConstantOperand().equals("()Ljava/lang/String;");
+ && "readLine".equals(getNameConstantOperand()) && "()Ljava/lang/String;".equals(getSigConstantOperand());
// System.out.println(randomNextIntState + " " + OPCODE_NAMES[seen]
// + " " + getMethodName());
switch (randomNextIntState) {
case 0:
- if (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/util/Random")
- && getNameConstantOperand().equals("nextDouble") || seen == INVOKESTATIC
- && ClassName.isMathClass(getClassConstantOperand()) && getNameConstantOperand().equals("random")) {
+ if (seen == INVOKEVIRTUAL && "java/util/Random".equals(getClassConstantOperand())
+ && "nextDouble".equals(getNameConstantOperand()) || seen == INVOKESTATIC
+ && ClassName.isMathClass(getClassConstantOperand()) && "random".equals(getNameConstantOperand())) {
randomNextIntState = 1;
}
break;
@@ -791,13 +1154,14 @@ public class DumbMethods extends OpcodeStackDetector {
if (seen == D2I) {
accumulator.accumulateBug(new BugInstance(this, "RV_01_TO_INT", HIGH_PRIORITY).addClassAndMethod(this), this);
randomNextIntState = 0;
- } else if (seen == DMUL)
+ } else if (seen == DMUL) {
randomNextIntState = 4;
- else if (seen == LDC2_W && getConstantRefOperand() instanceof ConstantDouble
- && ((ConstantDouble) getConstantRefOperand()).getBytes() == Integer.MIN_VALUE)
+ } else if (seen == LDC2_W && getConstantRefOperand() instanceof ConstantDouble
+ && ((ConstantDouble) getConstantRefOperand()).getBytes() == Integer.MIN_VALUE) {
randomNextIntState = 0;
- else
+ } else {
randomNextIntState = 2;
+ }
break;
case 2:
@@ -829,9 +1193,8 @@ public class DumbMethods extends OpcodeStackDetector {
if (isPublicStaticVoidMain
&& seen == INVOKEVIRTUAL
&& getClassConstantOperand().startsWith("javax/swing/")
- && (getNameConstantOperand().equals("show") && getSigConstantOperand().equals("()V")
- || getNameConstantOperand().equals("pack") && getSigConstantOperand().equals("()V") || getNameConstantOperand()
- .equals("setVisible") && getSigConstantOperand().equals("(Z)V"))) {
+ && ("show".equals(getNameConstantOperand()) && "()V".equals(getSigConstantOperand())
+ || "pack".equals(getNameConstantOperand()) && "()V".equals(getSigConstantOperand()) || "setVisible".equals(getNameConstantOperand()) && "(Z)V".equals(getSigConstantOperand()))) {
accumulator.accumulateBug(
new BugInstance(this, "SW_SWING_METHODS_INVOKED_IN_SWING_THREAD", LOW_PRIORITY).addClassAndMethod(this),
this);
@@ -854,8 +1217,8 @@ public class DumbMethods extends OpcodeStackDetector {
// }
// }
- if ((seen == INVOKEVIRTUAL) && getNameConstantOperand().equals("isAnnotationPresent")
- && getSigConstantOperand().equals("(Ljava/lang/Class;)Z") && stack.getStackDepth() > 0) {
+ if ((seen == INVOKEVIRTUAL) && "isAnnotationPresent".equals(getNameConstantOperand())
+ && "(Ljava/lang/Class;)Z".equals(getSigConstantOperand()) && stack.getStackDepth() > 0) {
OpcodeStack.Item item = stack.getStackItem(0);
Object value = item.getConstant();
if (value instanceof String) {
@@ -866,16 +1229,16 @@ public class DumbMethods extends OpcodeStackDetector {
ClassDescriptor annotationClass = DescriptorFactory.createClassDescriptor(annotationClassName);
accumulator.accumulateBug(
new BugInstance(this, "DMI_ANNOTATION_IS_NOT_VISIBLE_TO_REFLECTION", HIGH_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this).addClass(annotationClass)
- .describe(ClassAnnotation.ANNOTATION_ROLE), this);
+ .addClassAndMethod(this).addCalledMethod(this).addClass(annotationClass)
+ .describe(ClassAnnotation.ANNOTATION_ROLE), this);
}
}
}
- if ((seen == INVOKEVIRTUAL) && getNameConstantOperand().equals("next")
- && getSigConstantOperand().equals("()Ljava/lang/Object;") && getMethodName().equals("hasNext")
- && getMethodSig().equals("()Z") && stack.getStackDepth() > 0) {
+ if ((seen == INVOKEVIRTUAL) && "next".equals(getNameConstantOperand())
+ && "()Ljava/lang/Object;".equals(getSigConstantOperand()) && "hasNext".equals(getMethodName())
+ && "()Z".equals(getMethodSig()) && stack.getStackDepth() > 0) {
OpcodeStack.Item item = stack.getStackItem(0);
accumulator.accumulateBug(new BugInstance(this, "DMI_CALLING_NEXT_FROM_HASNEXT", item.isInitialParameter()
@@ -884,32 +1247,32 @@ public class DumbMethods extends OpcodeStackDetector {
}
- if ((seen == INVOKESPECIAL) && getClassConstantOperand().equals("java/lang/String")
- && getNameConstantOperand().equals("<init>") && getSigConstantOperand().equals("(Ljava/lang/String;)V")
+ if ((seen == INVOKESPECIAL) && "java/lang/String".equals(getClassConstantOperand())
+ && "<init>".equals(getNameConstantOperand()) && "(Ljava/lang/String;)V".equals(getSigConstantOperand())
&& !Subtypes2.isJSP(getThisClass())) {
accumulator.accumulateBug(new BugInstance(this, "DM_STRING_CTOR", NORMAL_PRIORITY).addClassAndMethod(this), this);
}
- if (seen == INVOKESTATIC && getClassConstantOperand().equals("java/lang/System")
- && getNameConstantOperand().equals("runFinalizersOnExit") || seen == INVOKEVIRTUAL
- && getClassConstantOperand().equals("java/lang/Runtime")
- && getNameConstantOperand().equals("runFinalizersOnExit")) {
+ if (seen == INVOKESTATIC && "java/lang/System".equals(getClassConstantOperand())
+ && "runFinalizersOnExit".equals(getNameConstantOperand()) || seen == INVOKEVIRTUAL
+ && "java/lang/Runtime".equals(getClassConstantOperand())
+ && "runFinalizersOnExit".equals(getNameConstantOperand())) {
accumulator.accumulateBug(
new BugInstance(this, "DM_RUN_FINALIZERS_ON_EXIT", HIGH_PRIORITY).addClassAndMethod(this), this);
}
- if ((seen == INVOKESPECIAL) && getClassConstantOperand().equals("java/lang/String")
- && getNameConstantOperand().equals("<init>") && getSigConstantOperand().equals("()V")) {
+ if ((seen == INVOKESPECIAL) && "java/lang/String".equals(getClassConstantOperand())
+ && "<init>".equals(getNameConstantOperand()) && "()V".equals(getSigConstantOperand())) {
accumulator.accumulateBug(new BugInstance(this, "DM_STRING_VOID_CTOR", NORMAL_PRIORITY).addClassAndMethod(this),
this);
}
- if (!isPublicStaticVoidMain && seen == INVOKESTATIC && getClassConstantOperand().equals("java/lang/System")
- && getNameConstantOperand().equals("exit") && !getMethodName().equals("processWindowEvent")
+ if (!isPublicStaticVoidMain && seen == INVOKESTATIC && "java/lang/System".equals(getClassConstantOperand())
+ && "exit".equals(getNameConstantOperand()) && !"processWindowEvent".equals(getMethodName())
&& !getMethodName().startsWith("windowClos") && getMethodName().indexOf("exit") == -1
&& getMethodName().indexOf("Exit") == -1 && getMethodName().indexOf("crash") == -1
&& getMethodName().indexOf("Crash") == -1 && getMethodName().indexOf("die") == -1
@@ -917,10 +1280,9 @@ public class DumbMethods extends OpcodeStackDetector {
accumulator.accumulateBug(new BugInstance(this, "DM_EXIT", getMethod().isStatic() ? LOW_PRIORITY
: NORMAL_PRIORITY).addClassAndMethod(this), SourceLineAnnotation.fromVisitedInstruction(this));
}
- if (((seen == INVOKESTATIC && getClassConstantOperand().equals("java/lang/System")) || (seen == INVOKEVIRTUAL && getClassConstantOperand()
- .equals("java/lang/Runtime")))
- && getNameConstantOperand().equals("gc")
- && getSigConstantOperand().equals("()V")
+ if (((seen == INVOKESTATIC && "java/lang/System".equals(getClassConstantOperand())) || (seen == INVOKEVIRTUAL && "java/lang/Runtime".equals(getClassConstantOperand())))
+ && "gc".equals(getNameConstantOperand())
+ && "()V".equals(getSigConstantOperand())
&& !getDottedClassName().startsWith("java.lang")
&& !getMethodName().startsWith("gc") && !getMethodName().endsWith("gc")) {
if (gcInvocationBugReport == null) {
@@ -941,8 +1303,8 @@ public class DumbMethods extends OpcodeStackDetector {
// System.out.println("GC invocation at pc " + PC);
}
}
- if (!isSynthetic && (seen == INVOKESPECIAL) && getClassConstantOperand().equals("java/lang/Boolean")
- && getNameConstantOperand().equals("<init>") && !getClassName().equals("java/lang/Boolean")) {
+ if (!isSynthetic && (seen == INVOKESPECIAL) && "java/lang/Boolean".equals(getClassConstantOperand())
+ && "<init>".equals(getNameConstantOperand()) && !"java/lang/Boolean".equals(getClassName())) {
int majorVersion = getThisClass().getMajor();
if (majorVersion >= MAJOR_1_4) {
accumulator.accumulateBug(new BugInstance(this, "DM_BOOLEAN_CTOR", NORMAL_PRIORITY).addClassAndMethod(this),
@@ -950,27 +1312,27 @@ public class DumbMethods extends OpcodeStackDetector {
}
}
- if ((seen == INVOKESTATIC) && getClassConstantOperand().equals("java/lang/System")
- && (getNameConstantOperand().equals("currentTimeMillis") || getNameConstantOperand().equals("nanoTime"))) {
+ if ((seen == INVOKESTATIC) && "java/lang/System".equals(getClassConstantOperand())
+ && ("currentTimeMillis".equals(getNameConstantOperand()) || "nanoTime".equals(getNameConstantOperand()))) {
sawCurrentTimeMillis = true;
}
- if ((seen == INVOKEVIRTUAL) && getClassConstantOperand().equals("java/lang/String")
- && getNameConstantOperand().equals("toString") && getSigConstantOperand().equals("()Ljava/lang/String;")) {
+ if ((seen == INVOKEVIRTUAL) && "java/lang/String".equals(getClassConstantOperand())
+ && "toString".equals(getNameConstantOperand()) && "()Ljava/lang/String;".equals(getSigConstantOperand())) {
accumulator
- .accumulateBug(new BugInstance(this, "DM_STRING_TOSTRING", LOW_PRIORITY).addClassAndMethod(this), this);
+ .accumulateBug(new BugInstance(this, "DM_STRING_TOSTRING", LOW_PRIORITY).addClassAndMethod(this), this);
}
- if ((seen == INVOKEVIRTUAL) && getClassConstantOperand().equals("java/lang/String")
- && (getNameConstantOperand().equals("toUpperCase") || getNameConstantOperand().equals("toLowerCase"))
- && getSigConstantOperand().equals("()Ljava/lang/String;")) {
+ if ((seen == INVOKEVIRTUAL) && "java/lang/String".equals(getClassConstantOperand())
+ && ("toUpperCase".equals(getNameConstantOperand()) || "toLowerCase".equals(getNameConstantOperand()))
+ && "()Ljava/lang/String;".equals(getSigConstantOperand())) {
accumulator.accumulateBug(new BugInstance(this, "DM_CONVERT_CASE", LOW_PRIORITY).addClassAndMethod(this), this);
}
- if ((seen == INVOKESPECIAL) && getNameConstantOperand().equals("<init>")) {
+ if ((seen == INVOKESPECIAL) && "<init>".equals(getNameConstantOperand())) {
String cls = getClassConstantOperand();
String sig = getSigConstantOperand();
String primitiveType = ClassName.getPrimitiveType(cls);
@@ -979,9 +1341,9 @@ public class DumbMethods extends OpcodeStackDetector {
} else {
primitiveObjCtorSeen = null;
}
- } else if ((primitiveObjCtorSeen != null) && (seen == INVOKEVIRTUAL) && getNameConstantOperand().equals("toString")
+ } else if ((primitiveObjCtorSeen != null) && (seen == INVOKEVIRTUAL) && "toString".equals(getNameConstantOperand())
&& getClassConstantOperand().equals(primitiveObjCtorSeen)
- && getSigConstantOperand().equals("()Ljava/lang/String;")) {
+ && "()Ljava/lang/String;".equals(getSigConstantOperand())) {
BugInstance bug = new BugInstance(this, "DM_BOXED_PRIMITIVE_TOSTRING", NORMAL_PRIORITY).addClassAndMethod(this).addCalledMethod(this);
MethodAnnotation preferred = new MethodAnnotation(ClassName.toDottedClassName(primitiveObjCtorSeen),
"toString", "("+ClassName.getPrimitiveType(primitiveObjCtorSeen)+")Ljava/lang/String;", true);
@@ -994,10 +1356,10 @@ public class DumbMethods extends OpcodeStackDetector {
primitiveObjCtorSeen = null;
}
- if ((seen == INVOKESPECIAL) && getNameConstantOperand().equals("<init>")) {
+ if ((seen == INVOKESPECIAL) && "<init>".equals(getNameConstantOperand())) {
ctorSeen = true;
- } else if (ctorSeen && (seen == INVOKEVIRTUAL) && getClassConstantOperand().equals("java/lang/Object")
- && getNameConstantOperand().equals("getClass") && getSigConstantOperand().equals("()Ljava/lang/Class;")) {
+ } else if (ctorSeen && (seen == INVOKEVIRTUAL) && "java/lang/Object".equals(getClassConstantOperand())
+ && "getClass".equals(getNameConstantOperand()) && "()Ljava/lang/Class;".equals(getSigConstantOperand())) {
accumulator.accumulateBug(new BugInstance(this, "DM_NEW_FOR_GETCLASS", NORMAL_PRIORITY).addClassAndMethod(this),
this);
ctorSeen = false;
@@ -1005,17 +1367,17 @@ public class DumbMethods extends OpcodeStackDetector {
ctorSeen = false;
}
- if (jdk15ChecksEnabled && (seen == INVOKEVIRTUAL) && isMonitorWait(getNameConstantOperand(), getSigConstantOperand())) {
+ if ((seen == INVOKEVIRTUAL) && isMonitorWait(getNameConstantOperand(), getSigConstantOperand())) {
checkMonitorWait();
}
- if ((seen == INVOKESPECIAL) && getNameConstantOperand().equals("<init>")
- && getClassConstantOperand().equals("java/lang/Thread")) {
+ if ((seen == INVOKESPECIAL) && "<init>".equals(getNameConstantOperand())
+ && "java/lang/Thread".equals(getClassConstantOperand())) {
String sig = getSigConstantOperand();
- if (sig.equals("()V") || sig.equals("(Ljava/lang/String;)V")
- || sig.equals("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V")) {
+ if ("()V".equals(sig) || "(Ljava/lang/String;)V".equals(sig)
+ || "(Ljava/lang/ThreadGroup;Ljava/lang/String;)V".equals(sig)) {
OpcodeStack.Item invokedOn = stack.getItemMethodInvokedOn(this);
- if (!getMethodName().equals("<init>") || invokedOn.getRegisterNumber() != 0) {
+ if (!"<init>".equals(getMethodName()) || invokedOn.getRegisterNumber() != 0) {
accumulator.accumulateBug(
new BugInstance(this, "DM_USELESS_THREAD", LOW_PRIORITY).addClassAndMethod(this), this);
@@ -1023,11 +1385,11 @@ public class DumbMethods extends OpcodeStackDetector {
}
}
- if (seen == INVOKESPECIAL && getClassConstantOperand().equals("java/math/BigDecimal")
- && getNameConstantOperand().equals("<init>") && getSigConstantOperand().equals("(D)V")) {
+ if (seen == INVOKESPECIAL && "java/math/BigDecimal".equals(getClassConstantOperand())
+ && "<init>".equals(getNameConstantOperand()) && "(D)V".equals(getSigConstantOperand())) {
OpcodeStack.Item top = stack.getStackItem(0);
Object value = top.getConstant();
- if (value instanceof Double) {
+ if (value instanceof Double && !((Double)value).isInfinite() && !((Double)value).isNaN()) {
double arg = ((Double) value).doubleValue();
String dblString = Double.toString(arg);
String bigDecimalString = new BigDecimal(arg).toString();
@@ -1035,7 +1397,7 @@ public class DumbMethods extends OpcodeStackDetector {
if (!ok) {
boolean scary = dblString.length() <= 8 && bigDecimalString.length() > 12
- && dblString.toUpperCase().indexOf("E") == -1;
+ && dblString.toUpperCase().indexOf('E') == -1;
bugReporter.reportBug(new BugInstance(this, "DMI_BIGDECIMAL_CONSTRUCTED_FROM_DOUBLE",
scary ? NORMAL_PRIORITY : LOW_PRIORITY).addClassAndMethod(this).addCalledMethod(this)
.addMethod("java.math.BigDecimal", "valueOf", "(D)Ljava/math/BigDecimal;", true)
@@ -1056,13 +1418,15 @@ public class DumbMethods extends OpcodeStackDetector {
long value = ((Number) right.getConstant()).longValue();
if ( (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE)) {
int priority = Priorities.HIGH_PRIORITY;
- if (value == Integer.MAX_VALUE+1 || value == Integer.MIN_VALUE -1)
+ if (value == Integer.MAX_VALUE+1L || value == Integer.MIN_VALUE-1L) {
priority = Priorities.NORMAL_PRIORITY;
+ }
String stringValue = IntAnnotation.getShortInteger(value)+"L";
- if (value == 0xffffffffL)
+ if (value == 0xffffffffL) {
stringValue = "0xffffffffL";
- else if (value == 0x80000000L)
+ } else if (value == 0x80000000L) {
stringValue = "0x80000000L";
+ }
accumulator.accumulateBug(new BugInstance(this, "INT_BAD_COMPARISON_WITH_INT_VALUE", priority ).addClassAndMethod(this)
.addString(stringValue).describe(StringAnnotation.STRING_NONSTRING_CONSTANT_ROLE)
.addValueSource(left, this) , this);
@@ -1075,34 +1439,32 @@ public class DumbMethods extends OpcodeStackDetector {
* @param item
*/
private void reportVacuousBitOperation(int seen, OpcodeStack.Item item) {
- if (item.getConstant() == null)
+ if (item.getConstant() == null) {
accumulator
- .accumulateBug(
- new BugInstance(this, "INT_VACUOUS_BIT_OPERATION", NORMAL_PRIORITY)
- .addClassAndMethod(this)
- .addString(OPCODE_NAMES[seen])
- .addOptionalAnnotation(
- LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), item, getPC())), this);
+ .accumulateBug(
+ new BugInstance(this, "INT_VACUOUS_BIT_OPERATION", NORMAL_PRIORITY)
+ .addClassAndMethod(this)
+ .addString(OPCODE_NAMES[seen])
+ .addOptionalAnnotation(
+ LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), item, getPC())), this);
+ }
}
/**
* Return index of stack entry that must be nonnegative.
*
* Return -1 if no stack entry is required to be nonnegative.
- *
- * @param seen
- * @return
*/
private int stackEntryThatMustBeNonnegative(int seen) {
switch (seen) {
case INVOKEINTERFACE:
- if (getClassConstantOperand().equals("java/util/List")) {
+ if ("java/util/List".equals(getClassConstantOperand())) {
return getStackEntryOfListCallThatMustBeNonnegative();
}
break;
case INVOKEVIRTUAL:
- if (getClassConstantOperand().equals("java/util/LinkedList")
- || getClassConstantOperand().equals("java/util/ArrayList")) {
+ if ("java/util/LinkedList".equals(getClassConstantOperand())
+ || "java/util/ArrayList".equals(getClassConstantOperand())) {
return getStackEntryOfListCallThatMustBeNonnegative();
}
break;
@@ -1131,10 +1493,10 @@ public class DumbMethods extends OpcodeStackDetector {
private int getStackEntryOfListCallThatMustBeNonnegative() {
String name = getNameConstantOperand();
- if ((name.equals("add") || name.equals("set")) && getSigConstantOperand().startsWith("(I")) {
+ if (("add".equals(name) || "set".equals(name)) && getSigConstantOperand().startsWith("(I")) {
return 1;
}
- if ((name.equals("get") || name.equals("remove")) && getSigConstantOperand().startsWith("(I)")) {
+ if (("get".equals(name) || "remove".equals(name)) && getSigConstantOperand().startsWith("(I)")) {
return 0;
}
return -1;
@@ -1172,7 +1534,7 @@ public class DumbMethods extends OpcodeStackDetector {
private boolean isMonitorWait(String name, String sig) {
// System.out.println("Check call " + name + "," + sig);
- return name.equals("wait") && (sig.equals("()V") || sig.equals("(J)V") || sig.equals("(JI)V"));
+ return "wait".equals(name) && ("()V".equals(sig) || "(J)V".equals(sig) || "(JI)V".equals(sig));
}
@Override
@@ -1183,25 +1545,21 @@ public class DumbMethods extends OpcodeStackDetector {
}
/**
- * A heuristic - how long a catch block for OutOfMemoryError might be.
- */
- private static final int OOM_CATCH_LEN = 20;
-
- /**
* Flush out cached state at the end of a method.
*/
private void flush() {
-
+
if (pendingAbsoluteValueBug != null) {
absoluteValueAccumulator.accumulateBug(pendingAbsoluteValueBug, pendingAbsoluteValueBugSourceLine);
pendingAbsoluteValueBug = null;
pendingAbsoluteValueBugSourceLine = null;
}
accumulator.reportAccumulatedBugs();
- if (sawLoadOfMinValue)
+ if (sawLoadOfMinValue) {
absoluteValueAccumulator.clearBugs();
- else
+ } else {
absoluteValueAccumulator.reportAccumulatedBugs();
+ }
if (gcInvocationBugReport != null && !sawCurrentTimeMillis) {
// Make sure the GC invocation is not in an exception handler
// for OutOfMemoryError.
@@ -1216,7 +1574,7 @@ public class DumbMethods extends OpcodeStackDetector {
Constant constant = cp.getConstant(catchTypeIndex);
if (constant instanceof ConstantClass) {
String exClassName = (String) ((ConstantClass) constant).getConstantValue(cp);
- if (exClassName.equals("java/lang/OutOfMemoryError")) {
+ if ("java/lang/OutOfMemoryError".equals(exClassName)) {
outOfMemoryHandler = true;
break;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/DuplicateBranches.java b/src/java/edu/umd/cs/findbugs/detect/DuplicateBranches.java
index 6dfbd46..f042bf1 100644
--- a/src/java/edu/umd/cs/findbugs/detect/DuplicateBranches.java
+++ b/src/java/edu/umd/cs/findbugs/detect/DuplicateBranches.java
@@ -56,14 +56,15 @@ import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
public class DuplicateBranches extends PreorderVisitor implements Detector {
private ClassContext classContext;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
- private Collection<BugInstance> pendingBugs = new LinkedList<BugInstance>();
+ private final Collection<BugInstance> pendingBugs = new LinkedList<BugInstance>();
public DuplicateBranches(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
this.classContext = classContext;
classContext.getJavaClass().accept(this);
@@ -72,8 +73,9 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
@Override
public void visitMethod(Method method) {
try {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
return;
+ }
CFG cfg = classContext.getCFG(method);
@@ -82,22 +84,26 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
BasicBlock bb = bbi.next();
int numOutgoing = cfg.getNumOutgoingEdges(bb);
- if (numOutgoing == 2)
+ if (numOutgoing == 2) {
findIfElseDuplicates(cfg, method, bb);
- else if (numOutgoing > 2)
+ } else if (numOutgoing > 2) {
findSwitchDuplicates(cfg, method, bb);
+ }
}
} catch (MethodUnprofitableException mue) {
- if (SystemProperties.getBoolean("unprofitable.debug")) // otherwise
- // don't
- // report
+ if (SystemProperties.getBoolean("unprofitable.debug")) {
+ // don't
+ // report
bugReporter.logError("skipping unprofitable method in " + getClass().getName());
+ }
} catch (Exception e) {
bugReporter.logError("Failure examining basic blocks in Duplicate Branches detector", e);
}
- if (pendingBugs.size() <= 2)
- for (BugInstance b : pendingBugs)
+ if (pendingBugs.size() <= 2) {
+ for (BugInstance b : pendingBugs) {
bugReporter.reportBug(b);
+ }
+ }
pendingBugs.clear();
}
@@ -115,12 +121,14 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
}
}
- if ((thenBB == null) || (elseBB == null))
+ if ((thenBB == null) || (elseBB == null)) {
return;
+ }
InstructionHandle thenStartHandle = getDeepFirstInstruction(cfg, thenBB);
InstructionHandle elseStartHandle = getDeepFirstInstruction(cfg, elseBB);
- if ((thenStartHandle == null) || (elseStartHandle == null))
+ if ((thenStartHandle == null) || (elseStartHandle == null)) {
return;
+ }
int thenStartPos = thenStartHandle.getPosition();
int elseStartPos = elseStartHandle.getPosition();
@@ -128,36 +136,42 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
InstructionHandle thenFinishIns = findThenFinish(cfg, thenBB, elseStartPos);
int thenFinishPos = thenFinishIns.getPosition();
- if (!(thenFinishIns.getInstruction() instanceof GotoInstruction))
+ if (!(thenFinishIns.getInstruction() instanceof GotoInstruction)) {
return;
+ }
InstructionHandle elseFinishHandle = ((GotoInstruction) thenFinishIns.getInstruction()).getTarget();
int elseFinishPos = elseFinishHandle.getPosition();
- if (thenFinishPos >= elseStartPos)
+ if (thenFinishPos >= elseStartPos) {
return;
+ }
- if ((thenFinishPos - thenStartPos) != (elseFinishPos - elseStartPos))
+ if ((thenFinishPos - thenStartPos) != (elseFinishPos - elseStartPos)) {
return;
+ }
- if (thenFinishPos <= thenStartPos)
+ if (thenFinishPos <= thenStartPos) {
return;
+ }
byte[] thenBytes = getCodeBytes(method, thenStartPos, thenFinishPos);
byte[] elseBytes = getCodeBytes(method, elseStartPos, elseFinishPos);
- if (!Arrays.equals(thenBytes, elseBytes))
+ if (!Arrays.equals(thenBytes, elseBytes)) {
return;
+ }
// adjust elseFinishPos to be inclusive (for source line attribution)
InstructionHandle elseLastIns = elseFinishHandle.getPrev();
- if (elseLastIns != null)
+ if (elseLastIns != null) {
elseFinishPos = elseLastIns.getPosition();
+ }
pendingBugs.add(new BugInstance(this, "DB_DUPLICATE_BRANCHES", NORMAL_PRIORITY)
- .addClassAndMethod(classContext.getJavaClass(), method)
- .addSourceLineRange(classContext, this, thenStartPos, thenFinishPos)
- .addSourceLineRange(classContext, this, elseStartPos, elseFinishPos));
+ .addClassAndMethod(classContext.getJavaClass(), method)
+ .addSourceLineRange(classContext, this, thenStartPos, thenFinishPos)
+ .addSourceLineRange(classContext, this, elseStartPos, elseFinishPos));
}
/**
@@ -166,14 +180,16 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
*/
private static InstructionHandle getDeepFirstInstruction(CFG cfg, BasicBlock bb) {
InstructionHandle ih = bb.getFirstInstruction();
- if (ih != null)
+ if (ih != null) {
return ih;
+ }
Iterator<Edge> iei = cfg.outgoingEdgeIterator(bb);
while (iei.hasNext()) {
Edge e = iei.next();
String edgeString = e.toString();
- if (EdgeTypes.FALL_THROUGH_EDGE == e.getType())
+ if (EdgeTypes.FALL_THROUGH_EDGE == e.getType()) {
return getDeepFirstInstruction(cfg, e.getTarget());
+ }
}
return null;
}
@@ -193,22 +209,26 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
BasicBlock target = e.getTarget();
InstructionHandle firstIns = getDeepFirstInstruction(cfg, target);
if (firstIns == null)
+ {
continue; // give up on this edge
+ }
int firstInsPosition = firstIns.getPosition();
switchPos[idx++] = firstInsPosition;
InstructionHandle prevIns = firstIns.getPrev(); // prev in
- // bytecode, not
- // flow
- if (prevIns != null)
+ // bytecode, not
+ // flow
+ if (prevIns != null) {
prevHandle.put(firstInsPosition, prevIns);
+ }
} else {
// hmm, this must not be a switch statement, so give up
return;
}
}
- if (idx < 2) // need at least two edges to tango
+ if (idx < 2) {
return;
+ }
Arrays.sort(switchPos, 0, idx); // sort the 'idx' switch positions
@@ -219,7 +239,9 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
HashMap<BigInteger, Collection<Integer>> map = new HashMap<BigInteger, Collection<Integer>>();
for (int i = 0; i < idx; i++) {
if (switchPos[i] + 7 >= switchPos[i + 1])
+ {
continue; // ignore small switch clauses
+ }
int endPos = switchPos[i + 1];
InstructionHandle last = prevHandle.get(switchPos[i + 1]);
@@ -234,11 +256,15 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
// Don't do this since many cases may throw "not implemented".
} else {
if (i + 2 < idx)
+ {
continue; // falls through to next case, so don't store it
- // at all
+ }
+ // at all
if (i + 1 < idx && switchPos[idx] != switchPos[idx - 1])
+ {
continue; // also falls through unless switch has no default
- // case
+ // case
+ }
}
BigInteger clauseAsInt = getCodeBytesAsBigInt(method, switchPos, i, endPos);
@@ -250,11 +276,13 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
BugInstance bug = new BugInstance(this, "DB_DUPLICATE_SWITCH_CLAUSES", LOW_PRIORITY).addClassAndMethod(
classContext.getJavaClass(), method);
for (int i : clauses)
+ {
bug.addSourceLineRange(this.classContext, this, switchPos[i], switchPos[i + 1] - 1); // not
- // endPos,
- // but
- // that's
- // ok
+ }
+ // endPos,
+ // but
+ // that's
+ // ok
pendingBugs.add(bug);
}
}
@@ -274,10 +302,11 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
byte[] clause = getCodeBytes(method, switchPos[i], endPos);
BigInteger clauseAsInt;
- if (clause.length == 0)
+ if (clause.length == 0) {
clauseAsInt = BigInteger.ZERO;
- else
+ } else {
clauseAsInt = new BigInteger(clause);
+ }
return clauseAsInt;
}
@@ -305,8 +334,9 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
InstructionHandle targetFirst = getDeepFirstInstruction(cfg, target);
if (targetFirst != null) {
int targetPos = targetFirst.getPosition();
- if (targetPos > maxGoto)
+ if (targetPos > maxGoto) {
maxGoto = targetPos;
+ }
}
}
}
@@ -395,6 +425,7 @@ public class DuplicateBranches extends PreorderVisitor implements Detector {
return lastIns;
}
+ @Override
public void report() {
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/EmptyZipFileEntry.java b/src/java/edu/umd/cs/findbugs/detect/EmptyZipFileEntry.java
index e005ceb..e58c8e1 100644
--- a/src/java/edu/umd/cs/findbugs/detect/EmptyZipFileEntry.java
+++ b/src/java/edu/umd/cs/findbugs/detect/EmptyZipFileEntry.java
@@ -30,7 +30,7 @@ import edu.umd.cs.findbugs.StatelessDetector;
/**
* This detector is currently disabled by default.
* It generates false positives when creating directory entries.
- *
+ *
*/
public class EmptyZipFileEntry extends BytecodeScanningDetector implements StatelessDetector {
@@ -56,20 +56,22 @@ public class EmptyZipFileEntry extends BytecodeScanningDetector implements State
@Override
public void sawOpcode(int seen) {
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("putNextEntry")) {
+ if (seen == INVOKEVIRTUAL && "putNextEntry".equals(getNameConstantOperand())) {
streamType = getClassConstantOperand();
- if (streamType.equals("java/util/zip/ZipOutputStream") || streamType.equals("java/util/jar/JarOutputStream"))
+ if ("java/util/zip/ZipOutputStream".equals(streamType) || "java/util/jar/JarOutputStream".equals(streamType)) {
sawPutEntry = getPC();
- else
+ } else {
streamType = "";
+ }
} else {
- if (getPC() - sawPutEntry <= 7 && seen == INVOKEVIRTUAL && getNameConstantOperand().equals("closeEntry")
- && getClassConstantOperand().equals(streamType))
+ if (getPC() - sawPutEntry <= 7 && seen == INVOKEVIRTUAL && "closeEntry".equals(getNameConstantOperand())
+ && getClassConstantOperand().equals(streamType)) {
bugReporter
- .reportBug(new BugInstance(this,
- streamType.equals("java/util/zip/ZipOutputStream") ? "AM_CREATES_EMPTY_ZIP_FILE_ENTRY"
- : "AM_CREATES_EMPTY_JAR_FILE_ENTRY", NORMAL_PRIORITY).addClassAndMethod(this)
+ .reportBug(new BugInstance(this,
+ "java/util/zip/ZipOutputStream".equals(streamType) ? "AM_CREATES_EMPTY_ZIP_FILE_ENTRY"
+ : "AM_CREATES_EMPTY_JAR_FILE_ENTRY", NORMAL_PRIORITY).addClassAndMethod(this)
.addSourceLine(this));
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/EqualsOperandShouldHaveClassCompatibleWithThis.java b/src/java/edu/umd/cs/findbugs/detect/EqualsOperandShouldHaveClassCompatibleWithThis.java
index a66c6ab..611af62 100644
--- a/src/java/edu/umd/cs/findbugs/detect/EqualsOperandShouldHaveClassCompatibleWithThis.java
+++ b/src/java/edu/umd/cs/findbugs/detect/EqualsOperandShouldHaveClassCompatibleWithThis.java
@@ -54,10 +54,11 @@ public class EqualsOperandShouldHaveClassCompatibleWithThis extends OpcodeStackD
@Override
public void visit(Code obj) {
- if (getMethodName().equals("equals") && getMethodSig().equals("(Ljava/lang/Object;)Z")) {
+ if ("equals".equals(getMethodName()) && "(Ljava/lang/Object;)Z".equals(getMethodSig())) {
super.visit(obj);
- if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass()))
+ if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass())) {
bugAccumulator.reportAccumulatedBugs();
+ }
bugAccumulator.clearBugs();
}
@@ -65,21 +66,21 @@ public class EqualsOperandShouldHaveClassCompatibleWithThis extends OpcodeStackD
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.bcel.OpcodeStackDetector#sawOpcode(int)
*/
@Override
public void sawOpcode(int seen) {
if (seen == INVOKEVIRTUAL) {
- if (getNameConstantOperand().equals("equals") && getSigConstantOperand().equals("(Ljava/lang/Object;)Z")) {
+ if ("equals".equals(getNameConstantOperand()) && "(Ljava/lang/Object;)Z".equals(getSigConstantOperand())) {
OpcodeStack.Item item = stack.getStackItem(1);
ClassDescriptor c = DescriptorFactory.createClassDescriptorFromSignature(item.getSignature());
check(c);
- } else if (getClassConstantOperand().equals("java/lang/Class")
- && (getNameConstantOperand().equals("isInstance") || getNameConstantOperand().equals("cast"))) {
+ } else if ("java/lang/Class".equals(getClassConstantOperand())
+ && ("isInstance".equals(getNameConstantOperand()) || "cast".equals(getNameConstantOperand()))) {
OpcodeStack.Item item = stack.getStackItem(1);
- if (item.getSignature().equals("Ljava/lang/Class;")) {
+ if ("Ljava/lang/Class;".equals(item.getSignature())) {
Object value = item.getConstant();
if (value instanceof String) {
ClassDescriptor c = DescriptorFactory.createClassDescriptor((String) value);
@@ -102,21 +103,24 @@ public class EqualsOperandShouldHaveClassCompatibleWithThis extends OpcodeStackD
OpcodeStack.Item item = stack.getStackItem(0);
if (item.isInitialParameter() && item.getRegisterNumber() == 1) {
ClassDescriptor thisClassDescriptor = getClassDescriptor();
- if (c.equals(thisClassDescriptor))
+ if (c.equals(thisClassDescriptor)) {
return;
+ }
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
try {
- if (!c.isArray() && (subtypes2.isSubtype(c, thisClassDescriptor) || subtypes2.isSubtype(thisClassDescriptor, c)))
+ if (!c.isArray() && (subtypes2.isSubtype(c, thisClassDescriptor) || subtypes2.isSubtype(thisClassDescriptor, c))) {
return;
+ }
Type thisType = Type.getType(thisClassDescriptor.getSignature());
Type cType = Type.getType(c.getSignature());
IncompatibleTypes check = IncompatibleTypes.getPriorityForAssumingCompatible(thisType, cType, false);
int priority = check.getPriority();
- if ("java/lang/Object".equals(getSuperclassName()) && ClassName.isAnonymous(getClassName()))
+ if ("java/lang/Object".equals(getSuperclassName()) && ClassName.isAnonymous(getClassName())) {
priority++;
+ }
bugAccumulator.accumulateBug(new BugInstance(this, "EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS", priority)
- .addClassAndMethod(this).addType(c).describe(TypeAnnotation.FOUND_ROLE), this);
+ .addClassAndMethod(this).addType(c).describe(TypeAnnotation.FOUND_ROLE), this);
classSummary.checksForEqualTo(thisClassDescriptor, c);
} catch (ClassNotFoundException e) {
diff --git a/src/java/edu/umd/cs/findbugs/detect/ExplicitSerialization.java b/src/java/edu/umd/cs/findbugs/detect/ExplicitSerialization.java
index 25b4c8f..7262559 100644
--- a/src/java/edu/umd/cs/findbugs/detect/ExplicitSerialization.java
+++ b/src/java/edu/umd/cs/findbugs/detect/ExplicitSerialization.java
@@ -70,20 +70,25 @@ public class ExplicitSerialization extends OpcodeStackDetector implements NonRep
if (seen == INVOKEVIRTUAL && writeObject.equals(getXMethodOperand())) {
OpcodeStack.Item top = stack.getStackItem(0);
String signature = top.getSignature();
- while (signature.charAt(0) == '[')
+ while (signature.charAt(0) == '[') {
signature = signature.substring(1);
+ }
ClassDescriptor c = DescriptorFactory.createClassDescriptorFromFieldSignature(signature);
- if (c == null || !Subtypes2.instanceOf(c, Serializable.class))
+ if (c == null || !Subtypes2.instanceOf(c, Serializable.class)) {
return;
+ }
try {
XClass xClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, c);
- if (xClass.isInterface())
+ if (xClass.isInterface()) {
return;
- if (xClass.isSynthetic())
+ }
+ if (xClass.isSynthetic()) {
return;
- if (xClass.isAbstract())
+ }
+ if (xClass.isAbstract()) {
return;
+ }
unreadFields.strongEvidenceForIntendedSerialization(c);
} catch (CheckedAnalysisException e) {
bugReporter.logError("Error looking up xClass of " + c, e);
@@ -94,17 +99,21 @@ public class ExplicitSerialization extends OpcodeStackDetector implements NonRep
OpcodeStack.Item top = stack.getStackItem(0);
if (readObject.equals(top.getReturnValueOf())) {
ClassDescriptor c = getClassDescriptorOperand();
- if (!Subtypes2.instanceOf(c, Serializable.class))
+ if (!Subtypes2.instanceOf(c, Serializable.class)) {
return;
+ }
try {
XClass xClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, c);
- if (xClass.isInterface())
+ if (xClass.isInterface()) {
return;
- if (xClass.isSynthetic())
+ }
+ if (xClass.isSynthetic()) {
return;
- if (xClass.isAbstract())
+ }
+ if (xClass.isAbstract()) {
return;
+ }
unreadFields.strongEvidenceForIntendedSerialization(c);
} catch (CheckedAnalysisException e) {
bugReporter.logError("Error looking up xClass of " + c, e);
diff --git a/src/java/edu/umd/cs/findbugs/detect/FieldItemSummary.java b/src/java/edu/umd/cs/findbugs/detect/FieldItemSummary.java
index 268478d..adfbb62 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FieldItemSummary.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FieldItemSummary.java
@@ -59,7 +59,7 @@ public class FieldItemSummary extends OpcodeStackDetector implements NonReportin
@Override
public void sawOpcode(int seen) {
- if (getMethodName().equals("<init>") && seen == INVOKEVIRTUAL) {
+ if ("<init>".equals(getMethodName()) && seen == INVOKEVIRTUAL) {
XMethod m = getXMethodOperand();
if (m != null && !m.isPrivate() && !m.isFinal()) {
int args = PreorderVisitor.getNumberArguments(m.getSignature());
@@ -71,8 +71,9 @@ public class FieldItemSummary extends OpcodeStackDetector implements NonReportin
for (XMethod called : targets) {
if (!called.isAbstract() && !called.equals(m)
- && subtypes2.isSubtype(called.getClassDescriptor(), getClassDescriptor()))
+ && subtypes2.isSubtype(called.getClassDescriptor(), getClassDescriptor())) {
fieldSummary.setCalledFromSuperConstructor(new ProgramPoint(this), called);
+ }
}
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
@@ -84,34 +85,38 @@ public class FieldItemSummary extends OpcodeStackDetector implements NonReportin
}
- if (seen == INVOKESPECIAL && getMethodName().equals("<init>") && getNameConstantOperand().equals("<init>")) {
+ if (seen == INVOKESPECIAL && "<init>".equals(getMethodName()) && "<init>".equals(getNameConstantOperand())) {
String classOperand = getClassConstantOperand();
OpcodeStack.Item invokedOn = stack.getItemMethodInvokedOn(this);
if (invokedOn.getRegisterNumber() == 0 && !classOperand.equals(getClassName())) {
sawInitializeSuper = true;
XMethod invoked = getXMethodOperand();
- if (invoked != null)
+ if (invoked != null) {
fieldSummary.sawSuperCall(getXMethod(), invoked);
+ }
}
}
if (seen == PUTFIELD || seen == PUTSTATIC) {
XField fieldOperand = getXFieldOperand();
- if (fieldOperand == null)
+ if (fieldOperand == null) {
return;
+ }
touched.add(fieldOperand);
- if (!fieldOperand.getClassDescriptor().getClassName().equals(getClassName()))
+ if (!fieldOperand.getClassDescriptor().getClassName().equals(getClassName())) {
fieldSummary.addWrittenOutsideOfConstructor(fieldOperand);
- else if (seen == PUTFIELD) {
+ } else if (seen == PUTFIELD) {
OpcodeStack.Item addr = stack.getStackItem(1);
{
- if (addr.getRegisterNumber() != 0 || !getMethodName().equals("<init>"))
+ if (addr.getRegisterNumber() != 0 || !"<init>".equals(getMethodName())) {
fieldSummary.addWrittenOutsideOfConstructor(fieldOperand);
+ }
}
- } else if (seen == PUTSTATIC && !getMethodName().equals("<clinit>"))
+ } else if (seen == PUTSTATIC && !"<clinit>".equals(getMethodName())) {
fieldSummary.addWrittenOutsideOfConstructor(fieldOperand);
+ }
OpcodeStack.Item top = stack.getStackItem(0);
fieldSummary.mergeSummary(fieldOperand, top);
}
@@ -123,22 +128,24 @@ public class FieldItemSummary extends OpcodeStackDetector implements NonReportin
sawInitializeSuper = false;
super.visit(obj);
fieldSummary.setFieldsWritten(getXMethod(), touched);
- if (getMethodName().equals("<init>") && sawInitializeSuper) {
+ if ("<init>".equals(getMethodName()) && sawInitializeSuper) {
XClass thisClass = getXClass();
- for (XField f : thisClass.getXFields())
+ for (XField f : thisClass.getXFields()) {
if (!f.isStatic() && !f.isFinal() && !touched.contains(f)) {
OpcodeStack.Item item;
char firstChar = f.getSignature().charAt(0);
- if (firstChar == 'L' || firstChar == '[')
+ if (firstChar == 'L' || firstChar == '[') {
item = OpcodeStack.Item.nullItem(f.getSignature());
- else if (firstChar == 'I')
+ } else if (firstChar == 'I') {
item = new OpcodeStack.Item("I", (Integer) 0);
- else if (firstChar == 'J')
+ } else if (firstChar == 'J') {
item = new OpcodeStack.Item("J", 0L);
- else
+ } else {
item = new OpcodeStack.Item(f.getSignature());
+ }
fieldSummary.mergeSummary(f, item);
}
+ }
}
touched.clear();
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FinalizerNullsFields.java b/src/java/edu/umd/cs/findbugs/detect/FinalizerNullsFields.java
index 009f1c8..3b5e9f2 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FinalizerNullsFields.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FinalizerNullsFields.java
@@ -52,10 +52,11 @@ public class FinalizerNullsFields extends BytecodeScanningDetector {
@Override
public void visit(Method obj) {
- if (obj.getName().equals("finalize"))
+ if ("finalize".equals(obj.getName())) {
inFinalize = true;
- else
+ } else {
inFinalize = false;
+ }
}
@Override
@@ -80,14 +81,14 @@ public class FinalizerNullsFields extends BytecodeScanningDetector {
@Override
public void sawOpcode(int seen) {
- if (state == 0 && seen == ALOAD_0)
+ if (state == 0 && seen == ALOAD_0) {
state++;
- else if (state == 1 && seen == ACONST_NULL)
+ } else if (state == 1 && seen == ACONST_NULL) {
state++;
- else if (state == 2 && seen == PUTFIELD) {
+ } else if (state == 2 && seen == PUTFIELD) {
bugAccumulator.accumulateBug(
new BugInstance(this, "FI_FINALIZER_NULLS_FIELDS", NORMAL_PRIORITY).addClassAndMethod(this)
- .addReferencedField(this), this);
+ .addReferencedField(this), this);
sawFieldNulling = true;
state = 0;
} else if (seen == RETURN) {
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindBadCast2.java b/src/java/edu/umd/cs/findbugs/detect/FindBadCast2.java
index 387af10..a9d9105 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindBadCast2.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindBadCast2.java
@@ -96,13 +96,15 @@ public class FindBadCast2 implements Detector {
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
Method[] methodList = javaClass.getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -138,8 +140,9 @@ public class FindBadCast2 implements Detector {
}
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {
- if (BCELUtil.isSynthetic(method) || !prescreen(classContext, method))
+ if (BCELUtil.isSynthetic(method) || !prescreen(classContext, method)) {
return;
+ }
BugAccumulator accumulator = new BugAccumulator(bugReporter);
CFG cfg = classContext.getCFG(method);
@@ -151,8 +154,9 @@ public class FindBadCast2 implements Detector {
ConstantPoolGen cpg = classContext.getConstantPoolGen();
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
String methodName = methodGen.getClassName() + "." + methodGen.getName();
String sourceFile = classContext.getJavaClass().getSourceFileName();
if (DEBUG) {
@@ -168,22 +172,25 @@ public class FindBadCast2 implements Detector {
InstructionHandle handle = location.getHandle();
Instruction ins = handle.getInstruction();
- if (!(ins instanceof CHECKCAST) && !(ins instanceof INSTANCEOF))
+ if (!(ins instanceof CHECKCAST) && !(ins instanceof INSTANCEOF)) {
continue;
+ }
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
sourceFile, handle);
if (ins instanceof CHECKCAST) {
if (!haveCast.add(sourceLineAnnotation)) {
haveMultipleCast.add(sourceLineAnnotation);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Have multiple casts for " + sourceLineAnnotation);
+ }
}
} else {
if (!haveInstanceOf.add(sourceLineAnnotation)) {
haveMultipleInstanceOf.add(sourceLineAnnotation);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Have multiple instanceof for " + sourceLineAnnotation);
+ }
}
}
}
@@ -226,21 +233,24 @@ public class FindBadCast2 implements Detector {
}
}
- if (!(ins instanceof CHECKCAST) && !(ins instanceof INSTANCEOF))
+ if (!(ins instanceof CHECKCAST) && !(ins instanceof INSTANCEOF)) {
continue;
+ }
boolean isCast = ins instanceof CHECKCAST;
int occurrences = cfg.getLocationsContainingInstructionWithOffset(pc).size();
boolean split = occurrences > 1;
if (lineNumberTable != null) {
int line = lineNumberTable.getSourceLine(handle.getPosition());
- if (line > 0 && linesMentionedMultipleTimes.get(line))
+ if (line > 0 && linesMentionedMultipleTimes.get(line)) {
split = true;
+ }
}
IsNullValueFrame nullFrame = isNullDataflow.getFactAtLocation(location);
- if (!nullFrame.isValid())
+ if (!nullFrame.isValid()) {
continue;
+ }
IsNullValue operandNullness = nullFrame.getTopValue();
if (DEBUG) {
String kind = isCast ? "checkedCast" : "instanceof";
@@ -279,9 +289,10 @@ public class FindBadCast2 implements Detector {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
sourceFile, handle);
assert castSig.length() > 1;
- if (!isCast)
+ if (!isCast) {
accumulator.accumulateBug(new BugInstance(this, "NP_NULL_INSTANCEOF", split ? LOW_PRIORITY : NORMAL_PRIORITY)
- .addClassAndMethod(methodGen, sourceFile).addType(castSig), sourceLineAnnotation);
+ .addClassAndMethod(methodGen, sourceFile).addType(castSig), sourceLineAnnotation);
+ }
continue;
}
@@ -292,8 +303,9 @@ public class FindBadCast2 implements Detector {
final ReferenceType refType = (ReferenceType) operandType;
boolean impliesByGenerics = typeDataflow.getAnalysis().isImpliedByGenericTypes(refType);
- if (impliesByGenerics && !isCast)
+ if (impliesByGenerics && !isCast) {
continue;
+ }
final boolean typesAreEqual = refType.equals(castType);
if (isCast && typesAreEqual) {
@@ -315,44 +327,49 @@ public class FindBadCast2 implements Detector {
if (refSig2.charAt(0) != 'L' || castSig2.charAt(0) != 'L') {
if (castSig2.charAt(0) == '['
- && (refSig2.equals("Ljava/io/Serializable;") || refSig2.equals("Ljava/lang/Object;") || refSig2
- .equals("Ljava/lang/Cloneable;")))
+ && ("Ljava/io/Serializable;".equals(refSig2) || "Ljava/lang/Object;".equals(refSig2) || "Ljava/lang/Cloneable;".equals(refSig2))) {
continue;
+ }
if (refSig2.charAt(0) == '['
- && (castSig2.equals("Ljava/io/Serializable;") || castSig2.equals("Ljava/lang/Object;") || castSig2
- .equals("Ljava/lang/Cloneable;")))
+ && ("Ljava/io/Serializable;".equals(castSig2) || "Ljava/lang/Object;".equals(castSig2) || "Ljava/lang/Cloneable;".equals(castSig2))) {
continue;
+ }
int priority = HIGH_PRIORITY;
- if (split && (castSig2.endsWith("Error;") || castSig2.endsWith("Exception;")))
+ if (split && (castSig2.endsWith("Error;") || castSig2.endsWith("Exception;"))) {
priority = LOW_PRIORITY;
+ }
// report bug only if types are not equal, see bug 3598482
if(!typesAreEqual){
bugReporter.reportBug(new BugInstance(this, isCast ? "BC_IMPOSSIBLE_CAST" : "BC_IMPOSSIBLE_INSTANCEOF", priority)
- .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(refType, castType)
- .addSourceLine(sourceLineAnnotation));
+ .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(refType, castType)
+ .addSourceLine(sourceLineAnnotation));
}
continue;
}
- if (!operandTypeIsExact && refSig2.equals("Ljava/lang/Object;")) {
+ if (!operandTypeIsExact && "Ljava/lang/Object;".equals(refSig2)) {
continue;
}
+ /*
if (false && isCast && haveMultipleCast.contains(sourceLineAnnotation) || !isCast
&& haveMultipleInstanceOf.contains(sourceLineAnnotation)) {
// skip; might be due to JSR inlining
continue;
- }
+ }*/
String castName = castSig2.substring(1, castSig2.length() - 1).replace('/', '.');
String refName = refSig2.substring(1, refSig2.length() - 1).replace('/', '.');
- if (vnaDataflow == null)
+ if (vnaDataflow == null) {
vnaDataflow = classContext.getValueNumberDataflow(method);
+ }
ValueNumberFrame vFrame = vnaDataflow.getFactAtLocation(location);
- if (paramValueNumberSet == null)
+ if (paramValueNumberSet == null) {
paramValueNumberSet = getParameterValueNumbers(classContext, method, cfg);
+ }
ValueNumber valueNumber = vFrame.getTopValue();
BugAnnotation valueSource = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, location, valueNumber, vFrame,
"VALUE_OF");
+ // XXX call below causes 86% of all OpcodeStackDetector.EarlyExitException (getPC() == targetPC) thrown (13000 on java* JDK7 classes)
BugAnnotation source = BugInstance.getSourceForTopStackValue(classContext, method, location);
boolean isParameter = paramValueNumberSet.contains(valueNumber) && source instanceof LocalVariableAnnotation;
@@ -362,16 +379,18 @@ public class FindBadCast2 implements Detector {
boolean upcast = Repository.instanceOf(refJavaClass, castJavaClass);
if (upcast || typesAreEqual) {
- if (!isCast)
+ if (!isCast) {
accumulator.accumulateBug(new BugInstance(this, "BC_VACUOUS_INSTANCEOF", NORMAL_PRIORITY)
- .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(refType, castType),
- sourceLineAnnotation);
+ .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(refType, castType),
+ sourceLineAnnotation);
+ }
} else {
boolean castMayThrow = !Repository.instanceOf(refJavaClass, castJavaClass);
boolean downCast = Repository.instanceOf(castJavaClass, refJavaClass);
- if (!operandTypeIsExact && refName.equals("java.lang.Object"))
+ if (!operandTypeIsExact && "java.lang.Object".equals(refName)) {
continue;
+ }
double rank = 0.0;
boolean castToConcreteCollection = concreteCollectionClasses.contains(castName)
&& abstractCollectionClasses.contains(refName);
@@ -385,14 +404,17 @@ public class FindBadCast2 implements Detector {
if (!operandTypeIsExact) {
rank = Analyze.deepInstanceOf(refJavaClass, castJavaClass);
- if (castToConcreteCollection && rank > 0.6)
+ if (castToConcreteCollection && rank > 0.6) {
rank = (rank + 0.6) / 2;
- else if (castToAbstractCollection && rank > 0.3)
+ } else if (castToAbstractCollection && rank > 0.3) {
rank = (rank + 0.3) / 2;
+ }
}
-
- if (false)
+ /*
+ if (false) {
System.out.println("Rank:\t" + rank + "\t" + refName + "\t" + castName);
+ }
+ */
boolean completeInformation = (!castJavaClass.isInterface() && !refJavaClass.isInterface())
|| refJavaClass.isFinal() || castJavaClass.isFinal();
if (DEBUG) {
@@ -407,41 +429,48 @@ public class FindBadCast2 implements Detector {
System.out.println(" isParameter: " + valueNumber);
System.out.println(" score: " + rank);
System.out.println(" source is: " + valueSource);
- if (catchSize < Integer.MAX_VALUE)
+ if (catchSize < Integer.MAX_VALUE) {
System.out.println(" catch block size is: " + catchSize);
- if (constantClass != null)
+ }
+ if (constantClass != null) {
System.out.println(" constant class " + constantClass + " at " + pcForConstantClass);
- if (handle.getPrev() == null)
+ }
+ if (handle.getPrev() == null) {
System.out.println(" prev is null");
- else
+ } else {
System.out.println(" prev is " + handle.getPrev());
+ }
}
if (!isCast && castMayThrow && valueSource != null) {
String oldCheck = instanceOfChecks.get(valueSource);
- if (oldCheck == null)
+ if (oldCheck == null) {
instanceOfChecks.put(valueSource, castName);
- else if (!oldCheck.equals(castName))
+ } else if (!oldCheck.equals(castName)) {
instanceOfChecks.put(valueSource, "");
+ }
}
if (!downCast && completeInformation || operandTypeIsExact) {
String bugPattern;
if (isCast) {
if (downCast && operandTypeIsExact) {
- if (refSig.equals("[Ljava/lang/Object;") && source instanceof MethodAnnotation
- && ((MethodAnnotation) source).getMethodName().equals("toArray")
- && ((MethodAnnotation) source).getMethodSignature().equals("()[Ljava/lang/Object;"))
+ if ("[Ljava/lang/Object;".equals(refSig) && source instanceof MethodAnnotation
+ && "toArray".equals(((MethodAnnotation) source).getMethodName())
+ && "()[Ljava/lang/Object;".equals(((MethodAnnotation) source).getMethodSignature())) {
bugPattern = "BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY";
- else
+ } else {
bugPattern = "BC_IMPOSSIBLE_DOWNCAST";
- } else
+ }
+ } else {
bugPattern = "BC_IMPOSSIBLE_CAST";
- } else
+ }
+ } else {
bugPattern = "BC_IMPOSSIBLE_INSTANCEOF";
+ }
bugReporter.reportBug(new BugInstance(this, bugPattern, isCast ? HIGH_PRIORITY : NORMAL_PRIORITY)
- .addClassAndMethod(methodGen, sourceFile)
- .addFoundAndExpectedType(refType, castType).addOptionalUniqueAnnotations(valueSource, source)
- .addSourceLine(sourceLineAnnotation));
+ .addClassAndMethod(methodGen, sourceFile)
+ .addFoundAndExpectedType(refType, castType).addOptionalUniqueAnnotations(valueSource, source)
+ .addSourceLine(sourceLineAnnotation));
} else if (isCast && rank < 0.9
&& !valueNumber.hasFlag(ValueNumber.ARRAY_VALUE)) {
@@ -455,89 +484,115 @@ public class FindBadCast2 implements Detector {
priority += 1;
} else if ("".equals(oldCheck)) {
priority += 1;
- if (!(source instanceof LocalVariableAnnotation)) continue;
+ if (!(source instanceof LocalVariableAnnotation)) {
+ continue;
+ }
}
- if (rank > 0.75)
+ if (rank > 0.75) {
priority += 2;
- else if (rank > 0.5)
+ } else if (rank > 0.5) {
priority += 1;
- else if (rank > 0.25)
+ } else if (rank > 0.25) {
priority += 0;
- else
+ } else {
priority--;
+ }
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" priority a: " + priority);
- if (methodGen.getClassName().startsWith(refName) || methodGen.getClassName().startsWith(castName))
+ }
+ if (methodGen.getClassName().startsWith(refName) || methodGen.getClassName().startsWith(castName)) {
priority += 1;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println(" priority b: " + priority);
- if (castJavaClass.isInterface() && !castToAbstractCollection)
+ }
+ if (castJavaClass.isInterface() && !castToAbstractCollection) {
priority++;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println(" priority c: " + priority);
- if (castToConcreteCollection && veryAbstractCollectionClasses.contains(refName))
+ }
+ if (castToConcreteCollection && veryAbstractCollectionClasses.contains(refName)) {
priority--;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println(" priority d: " + priority);
+ }
if (priority <= LOW_PRIORITY && !castToAbstractCollection && !castToConcreteCollection
- && (refJavaClass.isInterface() || refJavaClass.isAbstract()))
+ && (refJavaClass.isInterface() || refJavaClass.isAbstract())) {
priority++;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println(" priority e: " + priority);
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println(" ref name: " + refName);
- if (methodGen.getName().equals("compareTo"))
+ }
+ if ("compareTo".equals(methodGen.getName())) {
priority++;
- else if (methodGen.isPublic() && isParameter && !castName.equals(oldCheck))
+ } else if (methodGen.isPublic() && isParameter && !castName.equals(oldCheck)) {
priority--;
- if (wasMethodInvocationWasGeneric && valueNumber.hasFlag(ValueNumber.RETURN_VALUE))
+ }
+ if (wasMethodInvocationWasGeneric && valueNumber.hasFlag(ValueNumber.RETURN_VALUE)) {
continue;
+ }
if (constantClass != null && pcForConstantClass +20 >= pc && valueNumber.hasFlag(ValueNumber.RETURN_VALUE)
- && ClassName.toDottedClassName(constantClass).equals(castName))
+ && ClassName.toDottedClassName(constantClass).equals(castName)) {
priority += 2;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println(" priority f: " + priority);
- if (source instanceof MethodAnnotation) {
- MethodAnnotation m = (MethodAnnotation) source;
- XMethod xm = m.toXMethod();
- if (xm != null && (xm.isPrivate() || xm.isStatic()) && priority == Priorities.LOW_PRIORITY)
- continue;
- }
-
- if (valueNumber.hasFlag(ValueNumber.RETURN_VALUE) && priority < Priorities.LOW_PRIORITY)
+ }
+ if (source instanceof MethodAnnotation) {
+ MethodAnnotation m = (MethodAnnotation) source;
+ XMethod xm = m.toXMethod();
+ if (xm != null && (xm.isPrivate() || xm.isStatic()) && priority == Priorities.LOW_PRIORITY) {
+ continue;
+ }
+ }
+
+ if (valueNumber.hasFlag(ValueNumber.RETURN_VALUE) && priority < Priorities.LOW_PRIORITY) {
priority = Priorities.LOW_PRIORITY;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println(" priority g: " + priority);
+ }
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" priority h: " + priority);
+ }
- if (catchSize < 15)
+ if (catchSize < 15) {
return;
- if (catchSize < 25)
+ }
+ if (catchSize < 25) {
priority++;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println(" priority i: " + priority);
+ }
- if (priority < HIGH_PRIORITY)
+ if (priority < HIGH_PRIORITY) {
priority = HIGH_PRIORITY;
+ }
if (priority <= LOW_PRIORITY) {
String bug = "BC_UNCONFIRMED_CAST";
- if (valueNumber.hasFlag(ValueNumber.RETURN_VALUE) || valueSource instanceof MethodAnnotation)
+ if (valueNumber.hasFlag(ValueNumber.RETURN_VALUE) || valueSource instanceof MethodAnnotation) {
bug = "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE";
- else if (castToConcreteCollection)
+ } else if (castToConcreteCollection) {
bug = "BC_BAD_CAST_TO_CONCRETE_COLLECTION";
- else if (castToAbstractCollection)
+ } else if (castToAbstractCollection) {
bug = "BC_BAD_CAST_TO_ABSTRACT_COLLECTION";
+ }
BugInstance bugInstance = new BugInstance(this, bug, priority)
- .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(refType, castType)
- .addOptionalAnnotation(valueSource);
+ .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(refType, castType)
+ .addOptionalAnnotation(valueSource);
accumulator.accumulateBug(bugInstance, sourceLineAnnotation);
}
@@ -549,13 +604,14 @@ public class FindBadCast2 implements Detector {
if (DEBUG) {
e.printStackTrace(System.out);
}
- if (isCast && refSig.equals("[Ljava/lang/Object;") && source instanceof MethodAnnotation
- && ((MethodAnnotation) source).getMethodName().equals("toArray")
- && ((MethodAnnotation) source).getMethodSignature().equals("()[Ljava/lang/Object;"))
- bugReporter.reportBug(new BugInstance(this, "BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY", isCast ? HIGH_PRIORITY : NORMAL_PRIORITY)
+ if (isCast && "[Ljava/lang/Object;".equals(refSig) && source instanceof MethodAnnotation
+ && "toArray".equals(((MethodAnnotation) source).getMethodName())
+ && "()[Ljava/lang/Object;".equals(((MethodAnnotation) source).getMethodSignature())) {
+ bugReporter.reportBug(new BugInstance(this, "BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY", HIGH_PRIORITY)
.addClassAndMethod(methodGen, sourceFile)
.addFoundAndExpectedType(refType, castType).addOptionalUniqueAnnotations(valueSource, source)
.addSourceLine(sourceLineAnnotation));
+ }
}
@@ -563,6 +619,7 @@ public class FindBadCast2 implements Detector {
accumulator.reportAccumulatedBugs();
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindBadForLoop.java b/src/java/edu/umd/cs/findbugs/detect/FindBadForLoop.java
index 1013976..8c5042b 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindBadForLoop.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindBadForLoop.java
@@ -49,8 +49,9 @@ public class FindBadForLoop extends OpcodeStackDetector implements StatelessDete
@Override
public void sawOpcode(int seen) {
- if (seen == ISTORE || seen == ISTORE_0 || seen == ISTORE_1 || seen == ISTORE_2 || seen == ISTORE_3)
+ if (seen == ISTORE || seen == ISTORE_0 || seen == ISTORE_1 || seen == ISTORE_2 || seen == ISTORE_3) {
lastRegStore = getRegisterOperand();
+ }
if (lineNumbers != null
&& stack.getStackDepth() >= 2
&& (seen == IF_ICMPGE || seen == IF_ICMPGT || seen == IF_ICMPLT || seen == IF_ICMPLE || seen == IF_ICMPNE || seen == IF_ICMPEQ)) {
@@ -77,7 +78,7 @@ public class FindBadForLoop extends OpcodeStackDetector implements StatelessDete
&& beforeIncLineNumber > incLineNumber) {
bugReporter.reportBug(new BugInstance(this, "QF_QUESTIONABLE_FOR_LOOP", NORMAL_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindBugsSummaryStats.java b/src/java/edu/umd/cs/findbugs/detect/FindBugsSummaryStats.java
index b8548e3..7c32cbc 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindBugsSummaryStats.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindBugsSummaryStats.java
@@ -39,7 +39,7 @@ import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
public class FindBugsSummaryStats extends PreorderVisitor implements Detector, BugReporterObserver, NonReportingDetector {
- private ProjectStats stats;
+ private final ProjectStats stats;
BitSet lines = new BitSet(500);
@@ -61,8 +61,9 @@ public class FindBugsSummaryStats extends PreorderVisitor implements Detector, B
@Override
public void visitJavaClass(JavaClass obj) {
- if (AnalysisContext.currentAnalysisContext().isApplicationClass(obj))
+ if (AnalysisContext.currentAnalysisContext().isApplicationClass(obj)) {
super.visitJavaClass(obj);
+ }
}
@Override
@@ -93,12 +94,14 @@ public class FindBugsSummaryStats extends PreorderVisitor implements Detector, B
@Override
public void visitAfter(JavaClass obj) {
int linesNCSS = 1 + methods + fields;
- if (sawLineNumbers)
+ if (sawLineNumbers) {
linesNCSS += lines.cardinality();
- else
+ } else {
linesNCSS += classCodeSize / 10;
- if (stats != null)
+ }
+ if (stats != null) {
stats.addClass(getDottedClassName(), obj.getSourceFileName(), obj.isInterface(), linesNCSS);
+ }
totalCodeSize += classCodeSize;
totalNCSS += linesNCSS;
totalMethods += methods;
@@ -122,10 +125,12 @@ public class FindBugsSummaryStats extends PreorderVisitor implements Detector, B
this.stats = null;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
classContext.getJavaClass().accept(this);
}
+ @Override
public void report() {
}
@@ -137,6 +142,7 @@ public class FindBugsSummaryStats extends PreorderVisitor implements Detector, B
out.println("fields\t" + totalFields);
}
+ @Override
public void reportBug(BugInstance bug) {
// already added when bug was added to bug collection
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindCircularDependencies.java b/src/java/edu/umd/cs/findbugs/detect/FindCircularDependencies.java
index 6ceba8a..888bdd8 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindCircularDependencies.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindCircularDependencies.java
@@ -35,7 +35,7 @@ import edu.umd.cs.findbugs.BytecodeScanningDetector;
public class FindCircularDependencies extends BytecodeScanningDetector {
private HashMap<String, Set<String>> dependencyGraph = null;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private String clsName;
@@ -54,17 +54,21 @@ public class FindCircularDependencies extends BytecodeScanningDetector {
if ((seen == INVOKESPECIAL) || (seen == INVOKESTATIC) || (seen == INVOKEVIRTUAL)) {
String refClsName = getClassConstantOperand();
refClsName = refClsName.replace('/', '.');
- if (refClsName.startsWith("java"))
+ if (refClsName.startsWith("java")) {
return;
+ }
- if (clsName.equals(refClsName))
+ if (clsName.equals(refClsName)) {
return;
+ }
- if (clsName.startsWith(refClsName) && (refClsName.indexOf("$") >= 0))
+ if (clsName.startsWith(refClsName) && (refClsName.indexOf('$') >= 0)) {
return;
+ }
- if (refClsName.startsWith(clsName) && (clsName.indexOf("$") >= 0))
+ if (refClsName.startsWith(clsName) && (clsName.indexOf('$') >= 0)) {
return;
+ }
Set<String> dependencies = dependencyGraph.get(clsName);
if (dependencies == null) {
@@ -97,8 +101,9 @@ public class FindCircularDependencies extends BytecodeScanningDetector {
dependencyGraph.remove(clsName);
pruneLeaves = true;
}
- if (pruneLeaves)
+ if (pruneLeaves) {
removeDependencyLeaves(dependencyGraph);
+ }
}
dependencyGraph.clear();
@@ -132,12 +137,14 @@ public class FindCircularDependencies extends BytecodeScanningDetector {
private boolean removeLoopLinks(Map<String, Set<String>> dependencyGraph, Set<String> loop) {
Set<String> dependencies = null;
for (String clsName : loop) {
- if (dependencies != null)
+ if (dependencies != null) {
dependencies.remove(clsName);
+ }
dependencies = dependencyGraph.get(clsName);
}
- if (dependencies != null)
+ if (dependencies != null) {
dependencies.remove(loop.iterator().next());
+ }
boolean removedClass = false;
Iterator<String> cIt = loop.iterator();
@@ -166,27 +173,32 @@ public class FindCircularDependencies extends BytecodeScanningDetector {
startClass = startCls;
visited = new HashSet<String>();
loop = new LinkedHashSet<String>();
- if (findLoop(startClass))
+ if (findLoop(startClass)) {
return loop;
+ }
return null;
}
private boolean findLoop(String curClass) {
Set<String> dependencies = dGraph.get(curClass);
- if (dependencies == null)
+ if (dependencies == null) {
return false;
+ }
visited.add(curClass);
loop.add(curClass);
for (String depClass : dependencies) {
- if (depClass.equals(startClass))
+ if (depClass.equals(startClass)) {
return true;
+ }
- if (visited.contains(depClass))
+ if (visited.contains(depClass)) {
continue;
+ }
- if (findLoop(depClass))
+ if (findLoop(depClass)) {
return true;
+ }
}
loop.remove(curClass);
return false;
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindComparatorProblems.java b/src/java/edu/umd/cs/findbugs/detect/FindComparatorProblems.java
new file mode 100644
index 0000000..d31c75b
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/detect/FindComparatorProblems.java
@@ -0,0 +1,134 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.detect;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.bcel.classfile.Code;
+
+import edu.umd.cs.findbugs.BugAccumulator;
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.MethodAnnotation;
+import edu.umd.cs.findbugs.OpcodeStack;
+import edu.umd.cs.findbugs.OpcodeStack.Item;
+import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.ba.ch.Subtypes2;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+
+/**
+ * @author Tagir Valeev
+ */
+public class FindComparatorProblems extends OpcodeStackDetector {
+ private static final MethodDescriptor FLOAT_DESCRIPTOR = new MethodDescriptor("java/lang/Float", "compare", "(FF)I", true);
+ private static final MethodDescriptor DOUBLE_DESCRIPTOR = new MethodDescriptor("java/lang/Double", "compare", "(DD)I", true);
+
+ private boolean isComparator;
+ private int lastEmptyStackPC;
+ private List<int[]> twoDoublesInStack;
+ private final BugAccumulator accumulator;
+
+ public FindComparatorProblems(BugReporter reporter) {
+ this.accumulator = new BugAccumulator(reporter);
+ }
+
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ boolean comparator = Subtypes2.instanceOf(classContext.getClassDescriptor(), "java.util.Comparator");
+ boolean comparable = Subtypes2.instanceOf(classContext.getClassDescriptor(), "java.lang.Comparable");
+ isComparator = comparator;
+ if (comparator || comparable) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
+ public boolean shouldVisitCode(Code obj) {
+ return !getMethodDescriptor().isStatic()
+ && ((isComparator && getMethodName().equals("compare") && getMethodSig().endsWith(")I")) || ((getMethodName()
+ .equals("compareTo") && getMethodSig().equals("(L"+getClassName()+";)I"))));
+ }
+
+ @Override
+ public void visit(Code obj) {
+ this.twoDoublesInStack = new ArrayList<>();
+ this.lastEmptyStackPC = 0;
+ super.visit(obj);
+ this.accumulator.reportAccumulatedBugs();
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if(getStack().getStackDepth() == 0) {
+ this.lastEmptyStackPC = getPC();
+ }
+ if((seen == DCMPG || seen == DCMPL || seen == FCMPL || seen == FCMPG) && getStack().getStackDepth() == 2) {
+ int[] startEnd = new int[] {this.lastEmptyStackPC, getPC()};
+ for(Iterator<int[]> iterator = twoDoublesInStack.iterator(); iterator.hasNext(); ) {
+ int[] oldStartEnd = iterator.next();
+ if(codeEquals(oldStartEnd, startEnd)) {
+ Item item1 = getStack().getStackItem(0);
+ Item item2 = getStack().getStackItem(1);
+ accumulator.accumulateBug(
+ new BugInstance("CO_COMPARETO_INCORRECT_FLOATING", NORMAL_PRIORITY).addClassAndMethod(this)
+ .addType(item1.getSignature())
+ .addMethod(item1.getSignature().equals("D")?DOUBLE_DESCRIPTOR:FLOAT_DESCRIPTOR).describe(MethodAnnotation.SHOULD_CALL)
+ .addValueSource(item1, this)
+ .addValueSource(item2, this), this);
+ iterator.remove();
+ return;
+ }
+ }
+ twoDoublesInStack.add(startEnd);
+ }
+ if (seen == IRETURN) {
+ OpcodeStack.Item top = stack.getStackItem(0);
+ Object o = top.getConstant();
+ if (o instanceof Integer && ((Integer)o).intValue() == Integer.MIN_VALUE) {
+ accumulator.accumulateBug(
+ new BugInstance(this, "CO_COMPARETO_RESULTS_MIN_VALUE", NORMAL_PRIORITY).addClassAndMethod(this), this);
+ }
+ }
+ }
+
+ /**
+ * @param oldStartEnd - int[] {oldStart, oldEnd}
+ * @param startEnd - int[] {start, end}
+ * @return true if code slices are the same
+ */
+ private boolean codeEquals(int[] oldStartEnd, int[] startEnd) {
+ int oldStart = oldStartEnd[0];
+ int oldEnd = oldStartEnd[1];
+ int start = startEnd[0];
+ int end = startEnd[1];
+ if(end-start != oldEnd - oldStart) {
+ return false;
+ }
+ for(int i=start; i<end; i++) {
+ if(getCodeByte(i) != getCodeByte(i-start+oldStart)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindDeadLocalStores.java b/src/java/edu/umd/cs/findbugs/detect/FindDeadLocalStores.java
index c952f84..9e0dfb8 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindDeadLocalStores.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindDeadLocalStores.java
@@ -28,8 +28,6 @@ import org.apache.bcel.Constants;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.JavaClass;
-import org.apache.bcel.classfile.LocalVariable;
-import org.apache.bcel.classfile.LocalVariableTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ACONST_NULL;
import org.apache.bcel.generic.ALOAD;
@@ -56,6 +54,7 @@ import org.apache.bcel.generic.LoadInstruction;
import org.apache.bcel.generic.MULTIANEWARRAY;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.NEWARRAY;
+import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.StoreInstruction;
import org.apache.bcel.generic.Type;
@@ -69,6 +68,7 @@ import edu.umd.cs.findbugs.LocalVariableAnnotation;
import edu.umd.cs.findbugs.Priorities;
import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.SystemProperties;
+import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.CFG;
import edu.umd.cs.findbugs.ba.CFGBuilderException;
import edu.umd.cs.findbugs.ba.ClassContext;
@@ -106,7 +106,8 @@ public class FindDeadLocalStores implements Detector {
@StaticConstant
private static final Set<String> EXCLUDED_LOCALS = new HashSet<String>();
- private static final boolean DO_EXCLUDE_LOCALS = SystemProperties.getProperty(FINDBUGS_EXCLUDED_LOCALS_PROP_NAME) != null;
+ // private static final boolean DO_EXCLUDE_LOCALS = SystemProperties.getProperty(FINDBUGS_EXCLUDED_LOCALS_PROP_NAME) != null;
+
static {
EXCLUDED_LOCALS.add("gxp_locale");
// Get the value of the property...
@@ -116,8 +117,9 @@ public class FindDeadLocalStores implements Detector {
if (exclLocalsProperty != null) {
for (String s : exclLocalsProperty.split(",")) {
String s2 = s.trim();
- if (s2.length() > 0)
+ if (s2.length() > 0) {
EXCLUDED_LOCALS.add(s2);
+ }
}
}
}
@@ -163,14 +165,16 @@ public class FindDeadLocalStores implements Detector {
public FindDeadLocalStores(BugReporter bugReporter) {
this.bugReporter = bugReporter;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Debugging FindDeadLocalStores detector");
+ }
}
private boolean prescreen(ClassContext classContext, Method method) {
return true;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
@@ -178,11 +182,13 @@ public class FindDeadLocalStores implements Detector {
for (Method method : methodList) {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
continue;
+ }
- if (!prescreen(classContext, method))
+ if (!prescreen(classContext, method)) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -195,8 +201,9 @@ public class FindDeadLocalStores implements Detector {
}
private void analyzeMethod(ClassContext classContext, Method method) throws DataflowAnalysisException, CFGBuilderException {
- if (BCELUtil.isSynthetic(method) || (method.getAccessFlags() & Constants.ACC_BRIDGE) == Constants.ACC_BRIDGE)
+ if (BCELUtil.isSynthetic(method) || (method.getAccessFlags() & Constants.ACC_BRIDGE) == Constants.ACC_BRIDGE) {
return;
+ }
if (DEBUG) {
System.out.println(" Analyzing method " + classContext.getJavaClass().getClassName() + "." + method.getName());
@@ -213,22 +220,25 @@ public class FindDeadLocalStores implements Detector {
int[] localIncrementCount = new int[numLocals];
MethodGen methodGen = classContext.getMethodGen(method);
CFG cfg = classContext.getCFG(method);
- if (cfg.isFlagSet(CFG.FOUND_INEXACT_UNCONDITIONAL_THROWERS))
+ if (cfg.isFlagSet(CFG.FOUND_INEXACT_UNCONDITIONAL_THROWERS)) {
return;
+ }
BitSet liveStoreSetAtEntry = llsaDataflow.getAnalysis().getResultFact(cfg.getEntry());
BitSet complainedAbout = new BitSet();
TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
// Get number of locals that are parameters.
int localsThatAreParameters = PreorderVisitor.getNumberArguments(method.getSignature());
- if (!method.isStatic())
+ if (!method.isStatic()) {
localsThatAreParameters++;
+ }
// Scan method to determine number of loads, stores, and increments
// of local variables.
countLocalStoresLoadsAndIncrements(localStoreCount, localLoadCount, localIncrementCount, cfg);
- for (int i = 0; i < localsThatAreParameters; i++)
+ for (int i = 0; i < localsThatAreParameters; i++) {
localStoreCount[i]++;
+ }
// For each source line, keep track of # times
// the line was a live store. This can eliminate false positives
@@ -245,13 +255,15 @@ public class FindDeadLocalStores implements Detector {
try {
WarningPropertySet<WarningProperty> propertySet = new WarningPropertySet<WarningProperty>();
// Skip any instruction which is not a store
- if (!isStore(location))
+ if (!isStore(location)) {
continue;
+ }
// Heuristic: exception handler blocks often contain
// dead stores generated by the compiler.
- if (location.getBasicBlock().isExceptionHandler())
+ if (location.getBasicBlock().isExceptionHandler()) {
propertySet.addProperty(DeadLocalStoreProperty.EXCEPTION_HANDLER);
+ }
InstructionHandle handle = location.getHandle();
int pc = handle.getPosition();
IndexedInstruction ins = (IndexedInstruction) location.getHandle().getInstruction();
@@ -269,11 +281,13 @@ public class FindDeadLocalStores implements Detector {
LocalVariableAnnotation lvAnnotation = LocalVariableAnnotation.getLocalVariableAnnotation(method, location, ins);
String sourceFileName = javaClass.getSourceFileName();
- if (lvAnnotation.getName().equals("?")) {
- if (sourceFileName.endsWith(".groovy"))
+ if ("?".equals(lvAnnotation.getName())) {
+ if (sourceFileName.endsWith(".groovy")) {
continue;
- if (method.getCode().getLocalVariableTable() != null)
+ }
+ if (method.getCode().getLocalVariableTable() != null) {
continue;
+ }
}
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
@@ -291,15 +305,18 @@ public class FindDeadLocalStores implements Detector {
}
String lvName = lvAnnotation.getName();
- if (lvName.charAt(0) == '$' || lvName.charAt(0) == '_')
+ if (lvName.charAt(0) == '$' || lvName.charAt(0) == '_') {
propertySet.addProperty(DeadLocalStoreProperty.SYNTHETIC_NAME);
- if (EXCLUDED_LOCALS.contains(lvName))
+ }
+ if (EXCLUDED_LOCALS.contains(lvName)) {
continue;
+ }
propertySet.setProperty(DeadLocalStoreProperty.LOCAL_NAME, lvName);
boolean isParameter = local < localsThatAreParameters;
- if (isParameter)
+ if (isParameter) {
propertySet.addProperty(DeadLocalStoreProperty.IS_PARAMETER);
+ }
Field shadowedField = null;
@@ -318,23 +335,26 @@ public class FindDeadLocalStores implements Detector {
if (parameterThatIsDeadAtEntry && !complainedAbout.get(local)) {
int priority = storeLive ? LOW_PRIORITY : NORMAL_PRIORITY;
- if (shadowedField != null)
+ if (shadowedField != null) {
priority--;
+ }
pendingBugReportAboutOverwrittenParameter = new BugInstance(this, "IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN",
priority).addClassAndMethod(methodGen, sourceFileName).add(lvAnnotation);
- if (shadowedField != null)
+ if (shadowedField != null) {
pendingBugReportAboutOverwrittenParameter.addField(
FieldAnnotation.fromBCELField(classContext.getJavaClass(), shadowedField)).describe(
- FieldAnnotation.DID_YOU_MEAN_ROLE);
+ FieldAnnotation.DID_YOU_MEAN_ROLE);
+ }
pendingBugReportAboutOverwrittenParameter.addSourceLine(classContext, methodGen, sourceFileName,
location.getHandle());
complainedAbout.set(local);
}
- if (storeLive)
+ if (storeLive) {
continue;
+ }
TypeFrame typeFrame = typeDataflow.getAnalysis().getFactAtLocation(location);
Type typeOfValue = null;
@@ -348,13 +368,13 @@ public class FindDeadLocalStores implements Detector {
Instruction prevIns = prevInsHandle.getInstruction();
boolean foundDeadClassInitialization = false;
String initializationOf = null;
- if (prevIns instanceof ConstantPushInstruction)
+ if (prevIns instanceof ConstantPushInstruction) {
continue; // not an interesting dead store
- else if (prevIns instanceof GETSTATIC) {
+ } else if (prevIns instanceof GETSTATIC) {
GETSTATIC getStatic = (GETSTATIC) prevIns;
ConstantPoolGen cpg = methodGen.getConstantPool();
foundDeadClassInitialization = getStatic.getFieldName(cpg).startsWith("class$")
- && getStatic.getSignature(cpg).equals("Ljava/lang/Class;");
+ && "Ljava/lang/Class;".equals(getStatic.getSignature(cpg));
for (Iterator<Location> j = cfg.locationIterator(); j.hasNext();) {
Location location2 = j.next();
if (location2.getHandle().getPosition() + 15 == location.getHandle().getPosition()) {
@@ -363,8 +383,9 @@ public class FindDeadLocalStores implements Detector {
Object value = ((LDC) instruction2).getValue(methodGen.getConstantPool());
if (value instanceof String) {
String n = (String) value;
- if (n.length() > 0)
+ if (n.length() > 0) {
initializationOf = ClassName.toSignature(n);
+ }
}
}
}
@@ -373,12 +394,24 @@ public class FindDeadLocalStores implements Detector {
} else if (prevIns instanceof LDC) {
LDC ldc = (LDC) prevIns;
Type t = ldc.getType(methodGen.getConstantPool());
- if (t.getSignature().equals("Ljava/lang/Class;")) {
- ConstantClass v = (ConstantClass) ldc.getValue(methodGen.getConstantPool());
- initializationOf = ClassName.toSignature(v.getBytes(javaClass.getConstantPool()));
- foundDeadClassInitialization = true;
- } else
+ if ("Ljava/lang/Class;".equals(t.getSignature())) {
+ Object value = ldc.getValue(methodGen.getConstantPool());
+ if (value instanceof ConstantClass) {
+ ConstantClass v = (ConstantClass) value;
+ initializationOf = ClassName.toSignature(v.getBytes(javaClass.getConstantPool()));
+ foundDeadClassInitialization = true;
+ } else if (value instanceof ObjectType) {
+ ObjectType v = (ObjectType) value;
+ initializationOf = ClassName.toSignature(v.getClassName());
+ foundDeadClassInitialization = true;
+ } else {
+ AnalysisContext.logError("LDC loaded " + value + "at " + location.getHandle().getPosition() + " in " + classContext.getFullyQualifiedMethodName(method));
+ }
+
+ }
+ else {
continue; // not an interesting DLS
+ }
} else if (prevIns instanceof DUP2) {
// Check for the case where, due to the bytecode
@@ -392,8 +425,9 @@ public class FindDeadLocalStores implements Detector {
}
}
if (foundDeadClassInitialization) {
- if (classContext.getJavaClass().getSuperclassName().equals("org.apache.axis.client.Stub"))
+ if ("org.apache.axis.client.Stub".equals(classContext.getJavaClass().getSuperclassName())) {
continue;
+ }
BugInstance bugInstance = new BugInstance(this, "DLS_DEAD_STORE_OF_CLASS_LITERAL",
Priorities.NORMAL_PRIORITY).addClassAndMethod(methodGen, sourceFileName).add(lvAnnotation)
.addType(initializationOf);
@@ -401,83 +435,91 @@ public class FindDeadLocalStores implements Detector {
continue;
}
- if (prevIns instanceof LDC || prevIns instanceof ConstantPushInstruction)
+ if (prevIns instanceof LDC || prevIns instanceof ConstantPushInstruction) {
propertySet.addProperty(DeadLocalStoreProperty.STORE_OF_CONSTANT);
- else if (prevIns instanceof ACONST_NULL) {
+ } else if (prevIns instanceof ACONST_NULL) {
storeOfNull = true;
propertySet.addProperty(DeadLocalStoreProperty.STORE_OF_NULL);
}
}
- if (typeOfValue instanceof BasicType || Type.STRING.equals(typeOfValue))
+ if (typeOfValue instanceof BasicType || Type.STRING.equals(typeOfValue)) {
propertySet.addProperty(DeadLocalStoreProperty.BASE_VALUE);
+ }
// Ignore assignments that were killed by a subsequent
// assignment.
boolean killedBySubsequentStore = llsaDataflow.getAnalysis().killedByStore(liveStoreSet, local);
if (killedBySubsequentStore) {
if (propertySet.containsProperty(DeadLocalStoreProperty.STORE_OF_NULL)
- || propertySet.containsProperty(DeadLocalStoreProperty.STORE_OF_CONSTANT))
+ || propertySet.containsProperty(DeadLocalStoreProperty.STORE_OF_CONSTANT)) {
continue;
+ }
propertySet.addProperty(DeadLocalStoreProperty.KILLED_BY_SUBSEQUENT_STORE);
}
// Ignore dead assignments of null and 0.
// These often indicate defensive programming.
InstructionHandle prev = location.getBasicBlock().getPredecessorOf(location.getHandle());
- int prevOpCode = -1;
+ // int prevOpCode = -1;
if (prev != null) {
if (defensiveConstantValueOpcodes.get(prev.getInstruction().getOpcode())) {
propertySet.addProperty(DeadLocalStoreProperty.DEFENSIVE_CONSTANT_OPCODE);
- prevOpCode = prev.getInstruction().getOpcode();
+ // prevOpCode = prev.getInstruction().getOpcode();
}
if (prev.getInstruction() instanceof GETFIELD) {
InstructionHandle prev2 = prev.getPrev();
- if (prev2 != null && prev2.getInstruction() instanceof ALOAD)
+ if (prev2 != null && prev2.getInstruction() instanceof ALOAD) {
propertySet.addProperty(DeadLocalStoreProperty.CACHING_VALUE);
+ }
}
- if (prev.getInstruction() instanceof LoadInstruction)
+ if (prev.getInstruction() instanceof LoadInstruction) {
propertySet.addProperty(DeadLocalStoreProperty.COPY_VALUE);
- if (prev.getInstruction() instanceof InvokeInstruction)
+ }
+ if (prev.getInstruction() instanceof InvokeInstruction) {
propertySet.addProperty(DeadLocalStoreProperty.METHOD_RESULT);
+ }
}
boolean deadObjectStore = false;
if (ins instanceof IINC) {
// special handling of IINC
- if (method.getName().equals("main") && method.isStatic()
- && method.getSignature().equals("([Ljava/lang/String;)V"))
+ if ("main".equals(method.getName()) && method.isStatic()
+ && "([Ljava/lang/String;)V".equals(method.getSignature())) {
propertySet.addProperty(DeadLocalStoreProperty.DEAD_INCREMENT_IN_MAIN);
+ }
InstructionHandle next = location.getHandle().getNext();
- if (next != null && next.getInstruction() instanceof IRETURN)
+ if (next != null && next.getInstruction() instanceof IRETURN) {
propertySet.addProperty(DeadLocalStoreProperty.DEAD_INCREMENT_IN_RETURN);
- else
+ } else {
propertySet.addProperty(DeadLocalStoreProperty.DEAD_INCREMENT);
+ }
if (localIncrementCount[local] == 1) {
propertySet.addProperty(DeadLocalStoreProperty.SINGLE_DEAD_INCREMENT);
- } else
+ } else {
propertySet.removeProperty(DeadLocalStoreProperty.IS_PARAMETER);
+ }
} else if (ins instanceof ASTORE && prev != null) {
// Look for objects created but never used
Instruction prevIns = prev.getInstruction();
- if ((prevIns instanceof INVOKESPECIAL && ((INVOKESPECIAL) prevIns).getMethodName(methodGen.getConstantPool())
- .equals("<init>"))
+ if ((prevIns instanceof INVOKESPECIAL && "<init>".equals(((INVOKESPECIAL) prevIns).getMethodName(methodGen.getConstantPool())))
|| prevIns instanceof ANEWARRAY
|| prevIns instanceof NEWARRAY
|| prevIns instanceof MULTIANEWARRAY) {
deadObjectStore = true;
- } else if (prevIns instanceof DUP)
+ } else if (prevIns instanceof DUP) {
propertySet.addProperty(DeadLocalStoreProperty.DUP_THEN_STORE);
+ }
}
- if (deadObjectStore)
+ if (deadObjectStore) {
propertySet.addProperty(DeadLocalStoreProperty.DEAD_OBJECT_STORE);
- else if (!killedBySubsequentStore && localStoreCount[local] == 2 && localLoadCount[local] > 0) {
+ } else if (!killedBySubsequentStore && localStoreCount[local] == 2 && localLoadCount[local] > 0) {
// TODO: why is this significant?
propertySet.addProperty(DeadLocalStoreProperty.TWO_STORES_MULTIPLE_LOADS);
@@ -496,47 +538,54 @@ public class FindDeadLocalStores implements Detector {
&& !propertySet.containsProperty(DeadLocalStoreProperty.EXCEPTION_HANDLER)) {
String signatureOfValue = typeOfValue.getSignature();
if ((signatureOfValue.startsWith("Ljava/sql/") || signatureOfValue.startsWith("Ljavax/sql/"))
- && !signatureOfValue.endsWith("Exception"))
+ && !signatureOfValue.endsWith("Exception")) {
propertySet.addProperty(DeadLocalStoreProperty.STORE_OF_DATABASE_VALUE);
+ }
}
if (parameterThatIsDeadAtEntry) {
propertySet.addProperty(DeadLocalStoreProperty.PARAM_DEAD_ON_ENTRY);
- if (pendingBugReportAboutOverwrittenParameter != null)
+ if (pendingBugReportAboutOverwrittenParameter != null) {
pendingBugReportAboutOverwrittenParameter.setPriority(Priorities.HIGH_PRIORITY);
+ }
}
- if (localStoreCount[local] > 3)
+ if (localStoreCount[local] > 3) {
propertySet.addProperty(DeadLocalStoreProperty.MANY_STORES);
+ }
int occurrences = cfg.getLocationsContainingInstructionWithOffset(pc).size();
if (occurrences > 2 || sourceLineAnnotation.getStartLine() > 0
- && linesMentionedMultipleTimes.get(sourceLineAnnotation.getStartLine()))
+ && linesMentionedMultipleTimes.get(sourceLineAnnotation.getStartLine())) {
propertySet.addProperty(DeadLocalStoreProperty.CLONED_STORE);
+ }
String sourceFile = javaClass.getSourceFileName();
- if (Subtypes2.isJSP(javaClass))
+ if (Subtypes2.isJSP(javaClass)) {
propertySet.addProperty(DeadLocalStoreProperty.IN_JSP_PAGE);
- else if (BCELUtil.isSynthetic(javaClass) || sourceFile != null && !sourceFile.endsWith(".java")) {
- if (sourceFile != null && sourceFile.endsWith(".gxp") && (lvName.startsWith("gxp$") || lvName.startsWith("gxp_")))
+ } else if (BCELUtil.isSynthetic(javaClass) || sourceFile != null && !sourceFile.endsWith(".java")) {
+ if (sourceFile != null && sourceFile.endsWith(".gxp") && (lvName.startsWith("gxp$") || lvName.startsWith("gxp_"))) {
continue;
+ }
propertySet.addProperty(DeadLocalStoreProperty.NOT_JAVA);
}
// Report the warning
String bugPattern;
- if (storeOfNull)
+ if (storeOfNull) {
bugPattern = "DLS_DEAD_LOCAL_STORE_OF_NULL";
- else if (shadowedField != null)
+ } else if (shadowedField != null) {
bugPattern = "DLS_DEAD_LOCAL_STORE_SHADOWS_FIELD";
- else if (propertySet.containsProperty(DeadLocalStoreProperty.DEAD_INCREMENT_IN_RETURN))
+ } else if (propertySet.containsProperty(DeadLocalStoreProperty.DEAD_INCREMENT_IN_RETURN)) {
bugPattern = "DLS_DEAD_LOCAL_INCREMENT_IN_RETURN";
- else
+ } else {
bugPattern = "DLS_DEAD_LOCAL_STORE";
+ }
BugInstance bugInstance = new BugInstance(this, bugPattern, NORMAL_PRIORITY).addClassAndMethod(methodGen,
sourceFileName).add(lvAnnotation);
- if (shadowedField != null)
+ if (shadowedField != null) {
bugInstance.addField(FieldAnnotation.fromBCELField(classContext.getJavaClass(), shadowedField)).describe(
FieldAnnotation.DID_YOU_MEAN_ROLE);
+ }
// If in relaxed reporting mode, encode heuristic
// information.
@@ -555,8 +604,9 @@ public class FindDeadLocalStores implements Detector {
accumulator.accumulateBug(bugInstance, sourceLineAnnotation);
} finally {
- if (pendingBugReportAboutOverwrittenParameter != null)
+ if (pendingBugReportAboutOverwrittenParameter != null) {
bugReporter.reportBug(pendingBugReportAboutOverwrittenParameter);
+ }
}
}
@@ -612,13 +662,15 @@ public class FindDeadLocalStores implements Detector {
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
- if (location.getBasicBlock().isExceptionHandler())
+ if (location.getBasicBlock().isExceptionHandler()) {
continue;
+ }
boolean isStore = isStore(location);
boolean isLoad = isLoad(location);
- if (!isStore && !isLoad)
+ if (!isStore && !isLoad) {
continue;
+ }
IndexedInstruction ins = (IndexedInstruction) location.getHandle().getInstruction();
int local = ins.getIndex();
@@ -626,10 +678,11 @@ public class FindDeadLocalStores implements Detector {
localStoreCount[local]++;
localLoadCount[local]++;
localIncrementCount[local]++;
- } else if (isStore)
+ } else if (isStore) {
localStoreCount[local]++;
- else
+ } else {
localLoadCount[local]++;
+ }
}
}
@@ -643,7 +696,7 @@ public class FindDeadLocalStores implements Detector {
* index of the local
* @param pc
* program counter value of the instruction
- */
+ *
private void checkLocalVariableName(LocalVariableTable lvt, int local, int pc,
WarningPropertySet<DeadLocalStoreProperty> propertySet) {
if (lvt != null) {
@@ -654,7 +707,7 @@ public class FindDeadLocalStores implements Detector {
}
}
- }
+ }*/
/**
* Is instruction at given location a store?
@@ -680,8 +733,7 @@ public class FindDeadLocalStores implements Detector {
return (ins instanceof LoadInstruction) || (ins instanceof IINC);
}
+ @Override
public void report() {
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindDoubleCheck.java b/src/java/edu/umd/cs/findbugs/detect/FindDoubleCheck.java
index 5998b85..f310fdd 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindDoubleCheck.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindDoubleCheck.java
@@ -22,22 +22,24 @@ package edu.umd.cs.findbugs.detect;
import java.util.HashSet;
import java.util.Set;
-import org.apache.bcel.Repository;
-import org.apache.bcel.classfile.Field;
-import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
-import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.FieldAnnotation;
-
-public class FindDoubleCheck extends BytecodeScanningDetector {
+import edu.umd.cs.findbugs.OpcodeStack.Item;
+import edu.umd.cs.findbugs.ba.XField;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.detect.FindNoSideEffectMethods.MethodSideEffectStatus;
+import edu.umd.cs.findbugs.detect.FindNoSideEffectMethods.NoSideEffectMethodsDatabase;
+
+public class FindDoubleCheck extends OpcodeStackDetector {
static final boolean DEBUG = false;
int stage = 0;
- int startPC, endPC;
+ int startPC, endPC, assignPC;
int count;
@@ -49,20 +51,26 @@ public class FindDoubleCheck extends BytecodeScanningDetector {
FieldAnnotation pendingFieldLoad;
+ XField currentDoubleCheckField;
+
int countSinceGetReference;
int countSinceGetBoolean;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
+
+ private final NoSideEffectMethodsDatabase nse;
public FindDoubleCheck(BugReporter bugReporter) {
this.bugReporter = bugReporter;
+ this.nse = Global.getAnalysisCache().getDatabase(NoSideEffectMethodsDatabase.class);
}
@Override
public void visit(Method obj) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println(getFullyQualifiedMethodName());
+ }
super.visit(obj);
fields.clear();
twice.clear();
@@ -72,21 +80,25 @@ public class FindDoubleCheck extends BytecodeScanningDetector {
countSinceGetBoolean = 1000;
sawMonitorEnter = false;
pendingFieldLoad = null;
+ currentDoubleCheckField = null;
}
@Override
public void sawOpcode(int seen) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println(getPC() + "\t" + OPCODE_NAMES[seen] + "\t" + stage + "\t" + count + "\t" + countSinceGetReference);
+ }
- if (seen == MONITORENTER)
+ if (seen == MONITORENTER) {
sawMonitorEnter = true;
+ }
if (seen == GETFIELD || seen == GETSTATIC) {
pendingFieldLoad = FieldAnnotation.fromReferencedField(this);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\t" + pendingFieldLoad);
+ }
String sig = getSigConstantOperand();
- if (sig.equals("Z")) {
+ if ("Z".equals(sig)) {
countSinceGetBoolean = 0;
countSinceGetReference++;
} else if (sig.startsWith("L") || sig.startsWith("[")) {
@@ -127,8 +139,9 @@ public class FindDoubleCheck extends BytecodeScanningDetector {
}
} else {
count++;
- if (count > 10)
+ if (count > 10) {
stage = 0;
+ }
}
break;
case 2:
@@ -142,52 +155,73 @@ public class FindDoubleCheck extends BytecodeScanningDetector {
}
}
count++;
- if (count > 10)
+ if (count > 10) {
stage = 0;
+ }
break;
case 3:
if (seen == PUTFIELD || seen == PUTSTATIC) {
FieldAnnotation f = FieldAnnotation.fromReferencedField(this);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("\t" + f);
+ }
if (twice.contains(f) && !getNameConstantOperand().startsWith("class$")
- && !getSigConstantOperand().equals("Ljava/lang/String;")) {
- Field declaration = findField(getClassConstantOperand(), getNameConstantOperand());
- /*
- * System.out.println(f); System.out.println(declaration);
- * System.out.println(getSigConstantOperand());
- */
- if (declaration == null || !declaration.isVolatile())
+ && !"Ljava/lang/String;".equals(getSigConstantOperand())) {
+ XField declaration = getXFieldOperand();
+ if (declaration == null || !declaration.isVolatile()) {
bugReporter.reportBug(new BugInstance(this, "DC_DOUBLECHECK", NORMAL_PRIORITY).addClassAndMethod(this)
.addField(f).describe("FIELD_ON").addSourceLineRange(this, startPC, endPC));
+ } else {
+ if(declaration.isReferenceType()) {
+ currentDoubleCheckField = declaration;
+ assignPC = getPC();
+ }
+ }
+ stage++;
+ }
+ }
+ break;
+ case 4:
+ if(currentDoubleCheckField != null) {
+ switch(seen) {
+ case MONITOREXIT:
stage++;
+ break;
+ case INVOKEINTERFACE:
+ case INVOKESPECIAL:
+ case INVOKEVIRTUAL:
+ if(nse.is(getMethodDescriptorOperand(), MethodSideEffectStatus.OBJ, MethodSideEffectStatus.SE)) {
+ checkStackValue(getNumberArguments(getMethodDescriptorOperand().getSignature()));
+ }
+ break;
+ case PUTFIELD:
+ checkStackValue(1);
+ break;
+ case DASTORE:
+ case FASTORE:
+ case SASTORE:
+ case LASTORE:
+ case BASTORE:
+ case CASTORE:
+ case AASTORE:
+ case IASTORE:
+ checkStackValue(2);
+ break;
}
}
break;
default:
+ break;
}
}
- Field findField(String className, String fieldName) {
- try {
- // System.out.println("Looking for " + className);
- JavaClass fieldDefinedIn = getThisClass();
- if (!className.equals(getClassName())) {
- // System.out.println("Using repository to look for " +
- // className);
-
- fieldDefinedIn = Repository.lookupClass(className);
- }
- Field[] f = fieldDefinedIn.getFields();
- for (Field aF : f)
- if (aF.getName().equals(fieldName)) {
- // System.out.println("Found " + f[i]);
- return aF;
- }
- return null;
- } catch (ClassNotFoundException e) {
- return null;
+ private void checkStackValue(int arg) {
+ Item item = getStack().getStackItem(arg);
+ if(item.getXField() == currentDoubleCheckField) {
+ bugReporter.reportBug(new BugInstance(this, "DC_PARTIALLY_CONSTRUCTED", NORMAL_PRIORITY).addClassAndMethod(this)
+ .addField(currentDoubleCheckField).describe("FIELD_ON").addSourceLine(this).addSourceLine(this, assignPC)
+ .describe("SOURCE_LINE_STORED"));
+ stage++;
}
}
-
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindEmptySynchronizedBlock.java b/src/java/edu/umd/cs/findbugs/detect/FindEmptySynchronizedBlock.java
index cc8f3f9..6128184 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindEmptySynchronizedBlock.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindEmptySynchronizedBlock.java
@@ -33,9 +33,10 @@ public class FindEmptySynchronizedBlock extends BytecodeScanningDetector {
@Override
public void sawOpcode(int seen) {
- if (seen == MONITOREXIT && (getPrevOpcode(2) == MONITORENTER || getPrevOpcode(1) == MONITORENTER))
+ if (seen == MONITOREXIT && (getPrevOpcode(2) == MONITORENTER || getPrevOpcode(1) == MONITORENTER)) {
bugReporter.reportBug(new BugInstance(this, "ESync_EMPTY_SYNC", NORMAL_PRIORITY).addClassAndMethod(this)
.addSourceLine(this));
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindFieldSelfAssignment.java b/src/java/edu/umd/cs/findbugs/detect/FindFieldSelfAssignment.java
index b21d995..9afac07 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindFieldSelfAssignment.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindFieldSelfAssignment.java
@@ -50,12 +50,14 @@ public class FindFieldSelfAssignment extends OpcodeStackDetector implements Stat
state = 0;
lastMethodCall = -1;
- if (DEBUG)
+ if (DEBUG) {
System.out.println(getXMethod());
+ }
super.visit(obj);
possibleOverwrite = null;
- if (DEBUG)
+ if (DEBUG) {
System.out.println();
+ }
initializedFields.clear();
}
@@ -68,8 +70,9 @@ public class FindFieldSelfAssignment extends OpcodeStackDetector implements Stat
@Override
public void sawOpcode(int seen) {
- if (DEBUG)
+ if (DEBUG) {
System.out.printf("%5d %12s %s%n", getPC(), OPCODE_NAMES[seen],stack);
+ }
if (seen == PUTFIELD) {
OpcodeStack.Item top = stack.getStackItem(0);
OpcodeStack.Item next = stack.getStackItem(1);
@@ -80,7 +83,7 @@ public class FindFieldSelfAssignment extends OpcodeStackDetector implements Stat
}
possibleOverwrite = null;
-
+
if (stack.getStackDepth() >= 4 && getNextOpcode() == PUTFIELD) {
OpcodeStack.Item third = stack.getStackItem(2);
OpcodeStack.Item fourth = stack.getStackItem(3);
@@ -88,11 +91,11 @@ public class FindFieldSelfAssignment extends OpcodeStackDetector implements Stat
int registerNumber2 = fourth.getRegisterNumber();
if (f2 != null && f2.equals(getXFieldOperand()) && registerNumber2 >= 0
&& registerNumber2 == third.getFieldLoadedFromRegister()
- && !third.equals(top) && (third.getPC() == -1 || third.getPC() > lastMethodCall)) {
+ && !third.sameValue(top) && (third.getPC() == -1 || third.getPC() > lastMethodCall)) {
possibleOverwrite = f2;
}
}
-
+
XField f = top.getXField();
int registerNumber = next.getRegisterNumber();
if (f != null && f.equals(getXFieldOperand()) && registerNumber >= 0
@@ -101,14 +104,15 @@ public class FindFieldSelfAssignment extends OpcodeStackDetector implements Stat
LocalVariableAnnotation possibleMatch = LocalVariableAnnotation.findMatchingIgnoredParameter(getClassContext(),
getMethod(), getNameConstantOperand(), getSigConstantOperand());
- if (possibleMatch != null)
+ if (possibleMatch != null) {
priority--;
- else
+ } else {
possibleMatch = LocalVariableAnnotation.findUniqueBestMatchingParameter(getClassContext(), getMethod(),
getNameConstantOperand(), getSigConstantOperand());
+ }
if (possibleMatch == null) {
String signature = stack.getLVValue(registerNumber).getSignature();
- for (int i = 0; i < stack.getNumLocalValues(); i++)
+ for (int i = 0; i < stack.getNumLocalValues(); i++) {
if (i != register) {
Item lvValue = stack.getLVValue(i);
if (lvValue != null && lvValue.getSignature().equals(signature)) {
@@ -116,37 +120,44 @@ public class FindFieldSelfAssignment extends OpcodeStackDetector implements Stat
break;
}
}
+ }
}
bugReporter.reportBug(new BugInstance(this, "SA_FIELD_SELF_ASSIGNMENT", priority).addClassAndMethod(this)
.addReferencedField(this).addOptionalAnnotation(possibleMatch).addSourceLine(this));
}
- } else
+ } else {
possibleOverwrite = null;
- if (isMethodCall())
+ }
+ if (isMethodCall()) {
lastMethodCall = getPC();
+ }
switch (state) {
case 0:
- if (seen == DUP)
+ if (seen == DUP) {
state = 6;
+ }
break;
case 6:
if (isRegisterStore()) {
state = 7;
register = getRegisterOperand();
- } else
+ } else {
state = 0;
+ }
break;
case 7:
if (isRegisterStore() && register == getRegisterOperand()) {
bugReporter.reportBug(new BugInstance(this, "SA_LOCAL_DOUBLE_ASSIGNMENT", NORMAL_PRIORITY)
- .addClassAndMethod(this)
- .add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), register, getPC(), getPC() - 1))
- .addSourceLine(this));
+ .addClassAndMethod(this)
+ .add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), register, getPC(), getPC() - 1))
+ .addSourceLine(this));
}
state = 0;
break;
+ default:
+ break;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindFinalizeInvocations.java b/src/java/edu/umd/cs/findbugs/detect/FindFinalizeInvocations.java
index a97e0c3..686e52d 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindFinalizeInvocations.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindFinalizeInvocations.java
@@ -33,7 +33,7 @@ import edu.umd.cs.findbugs.SystemProperties;
public class FindFinalizeInvocations extends BytecodeScanningDetector implements StatelessDetector {
private static final boolean DEBUG = SystemProperties.getBoolean("ffi.debug");
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private final BugAccumulator bugAccumulator;
@@ -46,11 +46,13 @@ public class FindFinalizeInvocations extends BytecodeScanningDetector implements
@Override
public void visit(Method obj) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("FFI: visiting " + getFullyQualifiedMethodName());
- if (getMethodName().equals("finalize") && getMethodSig().equals("()V") && (obj.getAccessFlags() & (ACC_PUBLIC)) != 0)
+ }
+ if ("finalize".equals(getMethodName()) && "()V".equals(getMethodSig()) && (obj.getAccessFlags() & (ACC_PUBLIC)) != 0) {
bugReporter
- .reportBug(new BugInstance(this, "FI_PUBLIC_SHOULD_BE_PROTECTED", NORMAL_PRIORITY).addClassAndMethod(this));
+ .reportBug(new BugInstance(this, "FI_PUBLIC_SHOULD_BE_PROTECTED", NORMAL_PRIORITY).addClassAndMethod(this));
+ }
}
@Override
@@ -58,35 +60,40 @@ public class FindFinalizeInvocations extends BytecodeScanningDetector implements
sawSuperFinalize = false;
super.visit(obj);
bugAccumulator.reportAccumulatedBugs();
- if (!getMethodName().equals("finalize") || !getMethodSig().equals("()V"))
+ if (!"finalize".equals(getMethodName()) || !"()V".equals(getMethodSig())) {
return;
+ }
String overridesFinalizeIn = Lookup.findSuperImplementor(getDottedClassName(), "finalize", "()V", bugReporter);
- boolean superHasNoFinalizer = overridesFinalizeIn.equals("java.lang.Object");
+ boolean superHasNoFinalizer = "java.lang.Object".equals(overridesFinalizeIn);
// System.out.println("superclass: " + superclassName);
if (obj.getCode().length == 1) {
if (superHasNoFinalizer) {
- if (!getMethod().isFinal())
+ if (!getMethod().isFinal()) {
bugReporter.reportBug(new BugInstance(this, "FI_EMPTY", NORMAL_PRIORITY).addClassAndMethod(this));
- } else
+ }
+ } else {
bugReporter.reportBug(new BugInstance(this, "FI_NULLIFY_SUPER", NORMAL_PRIORITY).addClassAndMethod(this)
.addClass(overridesFinalizeIn));
- } else if (obj.getCode().length == 5 && sawSuperFinalize)
+ }
+ } else if (obj.getCode().length == 5 && sawSuperFinalize) {
bugReporter.reportBug(new BugInstance(this, "FI_USELESS", NORMAL_PRIORITY).addClassAndMethod(this));
- else if (!sawSuperFinalize && !superHasNoFinalizer)
+ } else if (!sawSuperFinalize && !superHasNoFinalizer) {
bugReporter.reportBug(new BugInstance(this, "FI_MISSING_SUPER_CALL", NORMAL_PRIORITY).addClassAndMethod(this)
.addClass(overridesFinalizeIn));
+ }
}
@Override
public void sawOpcode(int seen) {
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("finalize") && getSigConstantOperand().equals("()V")) {
+ if (seen == INVOKEVIRTUAL && "finalize".equals(getNameConstantOperand()) && "()V".equals(getSigConstantOperand())) {
bugAccumulator.accumulateBug(
- new BugInstance(this, "FI_EXPLICIT_INVOCATION", getMethodName().equals("finalize")
- && getMethodSig().equals("()V") ? HIGH_PRIORITY : NORMAL_PRIORITY).addClassAndMethod(this)
+ new BugInstance(this, "FI_EXPLICIT_INVOCATION", "finalize".equals(getMethodName())
+ && "()V".equals(getMethodSig()) ? HIGH_PRIORITY : NORMAL_PRIORITY).addClassAndMethod(this)
.addCalledMethod(this), this);
}
- if (seen == INVOKESPECIAL && getNameConstantOperand().equals("finalize"))
+ if (seen == INVOKESPECIAL && "finalize".equals(getNameConstantOperand())) {
sawSuperFinalize = true;
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindFloatEquality.java b/src/java/edu/umd/cs/findbugs/detect/FindFloatEquality.java
index 8ebb1ca..7ad0e00 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindFloatEquality.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindFloatEquality.java
@@ -41,9 +41,9 @@ public class FindFloatEquality extends OpcodeStackDetector implements StatelessD
private int priority;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
- private BugAccumulator bugAccumulator;
+ private final BugAccumulator bugAccumulator;
private int state;
@@ -69,10 +69,11 @@ public class FindFloatEquality extends OpcodeStackDetector implements StatelessD
boolean first = true;
for (SourceLineAnnotation s : found) {
bug.add(s);
- if (first)
+ if (first) {
first = false;
- else
+ } else {
bug.describe(SourceLineAnnotation.ROLE_ANOTHER_INSTANCE);
+ }
}
bugReporter.reportBug(bug);
@@ -82,18 +83,21 @@ public class FindFloatEquality extends OpcodeStackDetector implements StatelessD
}
public boolean isZero(Number n) {
- if (n == null)
+ if (n == null) {
return false;
+ }
double v = n.doubleValue();
return v == 0.0;
}
public boolean okValueToCompareAgainst(Number n) {
- if (n == null)
+ if (n == null) {
return false;
+ }
double v = n.doubleValue();
- if (Double.isInfinite(v) || Double.isNaN(v))
+ if (Double.isInfinite(v) || Double.isNaN(v)) {
return true;
+ }
v = v - Math.floor(v);
return v == 0.0;
}
@@ -107,20 +111,23 @@ public class FindFloatEquality extends OpcodeStackDetector implements StatelessD
case DCMPL:
if (stack.getStackDepth() >= 2) {
OpcodeStack.Item first = stack.getStackItem(0);
- OpcodeStack.Item second = stack.getStackItem(1);
-
- if (first.getRegisterNumber() == second.getRegisterNumber() && first.getRegisterNumber() != -1)
+ OpcodeStack.Item second = stack.getStackItem(1);
+
+ if (first.getRegisterNumber() == second.getRegisterNumber() && first.getRegisterNumber() != -1) {
break;
- if (first.isInitialParameter() && second.isInitialParameter())
+ }
+ if (first.isInitialParameter() && second.isInitialParameter()) {
break;
- if (sameField(first, second))
+ }
+ if (sameField(first, second)) {
break;
-
+ }
+
Number n1 = (Number) first.getConstant();
Number n2 = (Number) second.getConstant();
if (n1 != null && Double.isNaN(n1.doubleValue()) || n2 != null && Double.isNaN(n2.doubleValue())) {
BugInstance bug = new BugInstance(this, "FE_TEST_IF_EQUAL_TO_NOT_A_NUMBER", HIGH_PRIORITY)
- .addClassAndMethod(this);
+ .addClassAndMethod(this);
bugAccumulator.accumulateBug(bug, this);
state = SAW_NOTHING;
break;
@@ -129,28 +136,34 @@ public class FindFloatEquality extends OpcodeStackDetector implements StatelessD
|| second.getSpecialKind() == OpcodeStack.Item.NASTY_FLOAT_MATH && !isZero(n1)
|| first.getSpecialKind() == OpcodeStack.Item.FLOAT_MATH && !okValueToCompareAgainst(n2)
|| second.getSpecialKind() == OpcodeStack.Item.FLOAT_MATH && !okValueToCompareAgainst(n1)) {
- if (priority != HIGH_PRIORITY)
+ if (priority != HIGH_PRIORITY) {
found.clear();
+ }
priority = HIGH_PRIORITY;
state = SAW_COMP;
break;
}
- if (priority == HIGH_PRIORITY)
+ if (priority == HIGH_PRIORITY) {
break;
+ }
// if (first.isInitialParameter() && n2 != null) break;
// if (second.isInitialParameter() && n1 != null) break;
- if (n1 != null && n2 != null)
+ if (n1 != null && n2 != null) {
break;
+ }
- if (okValueToCompareAgainst(n1) || okValueToCompareAgainst(n2))
+ if (okValueToCompareAgainst(n1) || okValueToCompareAgainst(n2)) {
break;
+ }
if (n1 != null && !second.isInitialParameter() || n2 != null && !first.isInitialParameter()) {
- if (priority == LOW_PRIORITY)
+ if (priority == LOW_PRIORITY) {
found.clear();
+ }
priority = NORMAL_PRIORITY;
- } else if (priority == NORMAL_PRIORITY)
+ } else if (priority == NORMAL_PRIORITY) {
break;
+ }
state = SAW_COMP;
}
break;
@@ -174,12 +187,15 @@ public class FindFloatEquality extends OpcodeStackDetector implements StatelessD
}
static boolean sameField(Item i1, Item i2) {
- if (i1.getXField() == null)
+ if (i1.getXField() == null) {
return false;
- if (!i1.getXField().equals(i2.getXField()))
+ }
+ if (!i1.getXField().equals(i2.getXField())) {
return false;
- if (i1.getFieldLoadedFromRegister() != i2.getFieldLoadedFromRegister())
+ }
+ if (i1.getFieldLoadedFromRegister() != i2.getFieldLoadedFromRegister()) {
return false;
+ }
return true;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindFloatMath.java b/src/java/edu/umd/cs/findbugs/detect/FindFloatMath.java
index ae6b003..1353913 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindFloatMath.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindFloatMath.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.StatelessDetector;
public class FindFloatMath extends BytecodeScanningDetector implements StatelessDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public FindFloatMath(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -37,9 +37,10 @@ public class FindFloatMath extends BytecodeScanningDetector implements Stateless
case FMUL:
case FDIV:
if (getFullyQualifiedMethodName().indexOf("float") == -1 && getFullyQualifiedMethodName().indexOf("Float") == -1
- && getFullyQualifiedMethodName().indexOf("FLOAT") == -1)
+ && getFullyQualifiedMethodName().indexOf("FLOAT") == -1) {
bugReporter.reportBug(new BugInstance(this, "FL_MATH_USING_FLOAT_PRECISION", LOW_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
+ }
break;
case FCMPG:
case FCMPL:
@@ -48,10 +49,10 @@ public class FindFloatMath extends BytecodeScanningDetector implements Stateless
case FSUB:
case FREM:
if (getFullyQualifiedMethodName().indexOf("float") == -1 && getFullyQualifiedMethodName().indexOf("Float") == -1
- && getFullyQualifiedMethodName().indexOf("FLOAT") == -1)
-
+ && getFullyQualifiedMethodName().indexOf("FLOAT") == -1) {
bugReporter.reportBug(new BugInstance(this, "FL_MATH_USING_FLOAT_PRECISION", NORMAL_PRIORITY).addClassAndMethod(
this).addSourceLine(this));
+ }
break;
default:
break;
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindHEmismatch.java b/src/java/edu/umd/cs/findbugs/detect/FindHEmismatch.java
index bb7b686..8e1fbdc 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindHEmismatch.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindHEmismatch.java
@@ -41,6 +41,7 @@ import edu.umd.cs.findbugs.Lookup;
import edu.umd.cs.findbugs.MethodAnnotation;
import edu.umd.cs.findbugs.OpcodeStack;
import edu.umd.cs.findbugs.Priorities;
+import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.StatelessDetector;
import edu.umd.cs.findbugs.TypeAnnotation;
import edu.umd.cs.findbugs.ba.AnalysisContext;
@@ -57,71 +58,82 @@ import edu.umd.cs.findbugs.util.ClassName;
import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
public class FindHEmismatch extends OpcodeStackDetector implements StatelessDetector {
- boolean hasFields = false;
- boolean visibleOutsidePackage = false;
+ static final Pattern mapPattern = Pattern.compile("[^y]HashMap<L([^;<]*);");
+ static final Pattern hashTablePattern = Pattern.compile("Hashtable<L([^;<]*);");
+ static final Pattern setPattern = Pattern.compile("[^y]HashSet<L([^;<]*);");
+ static final Pattern predicateOverAnInstance = Pattern.compile("\\(L([^;]+);\\)Z");
+
+ boolean isApplicationClass;
- boolean hasHashCode = false;
+ boolean hasFields;
- boolean hasEqualsObject = false;
+ boolean visibleOutsidePackage;
- boolean hashCodeIsAbstract = false;
+ boolean hasHashCode;
- boolean equalsObjectIsAbstract = false;
+ boolean hasEqualsObject;
- boolean equalsMethodIsInstanceOfEquals = false;
+ boolean hashCodeIsAbstract;
- boolean equalsReimplementesObjectEquals = false;
+ boolean equalsObjectIsAbstract;
- boolean hasCompareToObject = false;
+ boolean equalsMethodIsInstanceOfEquals;
- boolean hasCompareToBridgeMethod = false;
+ boolean hasCompareToObject;
- boolean hasEqualsSelf = false;
+ boolean hasCompareToBridgeMethod;
- boolean hasEqualsOther = false;
+ boolean hasEqualsSelf;
- boolean hasCompareToSelf = false;
+ boolean hasEqualsOther;
- boolean extendsObject = false;
+ boolean hasCompareToSelf;
- MethodAnnotation equalsMethod = null;
+ boolean extendsObject;
- MethodAnnotation equalsOtherMethod = null;
+ MethodAnnotation equalsMethod;
- ClassDescriptor equalsOtherClass = null;
+ MethodAnnotation equalsOtherMethod;
- MethodAnnotation compareToMethod = null;
+ ClassDescriptor equalsOtherClass;
- MethodAnnotation compareToObjectMethod = null;
+ MethodAnnotation compareToMethod;
- MethodAnnotation compareToSelfMethod = null;
+ MethodAnnotation compareToObjectMethod;
- MethodAnnotation hashCodeMethod = null;
+ MethodAnnotation compareToSelfMethod;
- HashSet<String> nonHashableClasses = new HashSet<String>();
+ MethodAnnotation hashCodeMethod;
- public boolean isHashableClassName(String dottedClassName) {
- return !nonHashableClasses.contains(dottedClassName);
- }
+ final HashSet<String> nonHashableClasses;
- Map<String, BugInstance> potentialBugs = new HashMap<String, BugInstance>();
+ final Map<String, BugInstance> potentialBugs;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public FindHEmismatch(BugReporter bugReporter) {
this.bugReporter = bugReporter;
+ nonHashableClasses = new HashSet<String>();
+ potentialBugs = new HashMap<String, BugInstance>();
+ }
+
+ public boolean isHashableClassName(String dottedClassName) {
+ return !nonHashableClasses.contains(dottedClassName);
}
@Override
public void visitAfter(JavaClass obj) {
- if (!obj.isClass())
+ if (!obj.isClass()) {
return;
- if (getDottedClassName().equals("java.lang.Object"))
+ }
+ if ("java.lang.Object".equals(getDottedClassName())) {
return;
+ }
int accessFlags = obj.getAccessFlags();
- if ((accessFlags & ACC_INTERFACE) != 0)
+ if ((accessFlags & ACC_INTERFACE) != 0) {
return;
+ }
visibleOutsidePackage = obj.isPublic() || obj.isProtected();
String whereEqual = getDottedClassName();
@@ -144,7 +156,7 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
}
}
}
- boolean usesDefaultEquals = whereEqual.equals("java.lang.Object");
+ boolean usesDefaultEquals = "java.lang.Object".equals(whereEqual);
String whereHashCode = getDottedClassName();
if (!hasHashCode) {
XClass wh = Lookup.findSuperImplementor(getXClass(), "hashCode", "()I", false, bugReporter);
@@ -153,11 +165,13 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
} else {
whereHashCode = wh.getClassDescriptor().getDottedClassName();
XMethod m = wh.findMethod("hashCode", "()I", false);
- if (m != null && m.isFinal())
+ if (m != null && m.isFinal()) {
inheritedHashCodeIsFinal = true;
+ }
}
}
- boolean usesDefaultHashCode = whereHashCode.equals("java.lang.Object");
+ boolean usesDefaultHashCode = "java.lang.Object".equals(whereHashCode);
+ /*
if (false && (usesDefaultEquals || usesDefaultHashCode)) {
try {
if (Repository.implementationOf(obj, "java/util/Set") || Repository.implementationOf(obj, "java/util/List")
@@ -169,6 +183,7 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
// e.printStackTrace();
}
}
+ */
if (!hasEqualsObject && !hasEqualsSelf && hasEqualsOther) {
BugInstance bug = new BugInstance(this, usesDefaultEquals ? "EQ_OTHER_USE_OBJECT" : "EQ_OTHER_NO_OBJECT",
@@ -179,31 +194,37 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
if (usesDefaultEquals) {
int priority = HIGH_PRIORITY;
- if (usesDefaultHashCode || obj.isAbstract())
+ if (usesDefaultHashCode || obj.isAbstract()) {
priority++;
- if (!visibleOutsidePackage)
+ }
+ if (!visibleOutsidePackage) {
priority++;
+ }
String bugPattern = "EQ_SELF_USE_OBJECT";
BugInstance bug = new BugInstance(this, bugPattern, priority).addClass(getDottedClassName());
- if (equalsMethod != null)
+ if (equalsMethod != null) {
bug.addMethod(equalsMethod);
+ }
bugReporter.reportBug(bug);
} else {
int priority = NORMAL_PRIORITY;
- if (hasFields)
+ if (hasFields) {
priority--;
- if (obj.isAbstract())
+ }
+ if (obj.isAbstract()) {
priority++;
+ }
String bugPattern = "EQ_SELF_NO_OBJECT";
String superclassName = obj.getSuperclassName();
- if (superclassName.equals("java.lang.Enum")) {
+ if ("java.lang.Enum".equals(superclassName)) {
bugPattern = "EQ_DONT_DEFINE_EQUALS_FOR_ENUM";
priority = HIGH_PRIORITY;
}
BugInstance bug = new BugInstance(this, bugPattern, priority).addClass(getDottedClassName());
- if (equalsMethod != null)
+ if (equalsMethod != null) {
bug.addMethod(equalsMethod);
+ }
bugReporter.reportBug(bug);
}
}
@@ -219,89 +240,105 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
if ((hasCompareToObject || hasCompareToSelf) && usesDefaultEquals) {
BugInstance bug = new BugInstance(this, "EQ_COMPARETO_USE_OBJECT_EQUALS", obj.isAbstract() ? Priorities.LOW_PRIORITY
: Priorities.NORMAL_PRIORITY).addClass(this);
- if (compareToSelfMethod != null)
+ if (compareToSelfMethod != null) {
bug.addMethod(compareToSelfMethod);
- else
+ } else {
bug.addMethod(compareToObjectMethod);
+ }
bugReporter.reportBug(bug);
}
if (!hasCompareToObject && !hasCompareToBridgeMethod && hasCompareToSelf) {
- if (!extendsObject)
+ if (!extendsObject) {
bugReporter.reportBug(new BugInstance(this, "CO_SELF_NO_OBJECT", NORMAL_PRIORITY).addClass(getDottedClassName())
.addMethod(compareToMethod));
+ }
}
// if (!hasFields) return;
- if (hasHashCode && !hashCodeIsAbstract && !(hasEqualsObject && !equalsReimplementesObjectEquals || hasEqualsSelf)) {
+ if (hasHashCode && !hashCodeIsAbstract && !(hasEqualsObject || hasEqualsSelf)) {
int priority = LOW_PRIORITY;
- if (usesDefaultEquals)
+ if (usesDefaultEquals) {
bugReporter.reportBug(new BugInstance(this, "HE_HASHCODE_USE_OBJECT_EQUALS", priority).addClass(
getDottedClassName()).addMethod(hashCodeMethod));
- else if (!inheritedEqualsIsFinal)
+ } else if (!inheritedEqualsIsFinal) {
bugReporter.reportBug(new BugInstance(this, "HE_HASHCODE_NO_EQUALS", priority).addClass(getDottedClassName())
.addMethod(hashCodeMethod));
+ }
}
if (equalsObjectIsAbstract) {
// no errors reported
} else if (!hasHashCode && (hasEqualsObject || hasEqualsSelf)) {
EqualsKindSummary.KindOfEquals equalsKind = AnalysisContext.currentAnalysisContext().getEqualsKindSummary()
.get(new ClassAnnotation(obj.getClassName()));
- if (equalsKind == EqualsKindSummary.KindOfEquals.ALWAYS_FALSE)
+ if (equalsKind == EqualsKindSummary.KindOfEquals.ALWAYS_FALSE) {
return;
+ }
if (usesDefaultHashCode) {
int priority = HIGH_PRIORITY;
- if (equalsMethodIsInstanceOfEquals)
+ if (equalsMethodIsInstanceOfEquals) {
priority += 2;
- else if (obj.isAbstract() || !hasEqualsObject)
+ } else if (obj.isAbstract() || !hasEqualsObject) {
priority++;
- if (priority == HIGH_PRIORITY)
+ }
+ if (priority == HIGH_PRIORITY) {
nonHashableClasses.add(getDottedClassName());
+ }
if (!visibleOutsidePackage) {
priority++;
}
BugInstance bug = new BugInstance(this, "HE_EQUALS_USE_HASHCODE", priority).addClass(getDottedClassName());
- if (equalsMethod != null)
+ if (equalsMethod != null) {
bug.addMethod(equalsMethod);
+ }
bugReporter.reportBug(bug);
} else if (!inheritedHashCodeIsFinal && !whereHashCode.startsWith("java.util.Abstract")) {
int priority = LOW_PRIORITY;
- if (hasEqualsObject && inheritedEqualsIsAbstract)
+ if (hasEqualsObject && inheritedEqualsIsAbstract) {
priority++;
- if (hasFields)
+ }
+ if (hasFields) {
priority--;
- if (equalsMethodIsInstanceOfEquals || !hasEqualsObject)
+ }
+ if (equalsMethodIsInstanceOfEquals || !hasEqualsObject) {
priority += 2;
- else if (obj.isAbstract())
+ } else if (obj.isAbstract()) {
priority++;
+ }
BugInstance bug = new BugInstance(this, "HE_EQUALS_NO_HASHCODE", priority).addClass(getDottedClassName());
- if (equalsMethod != null)
+ if (equalsMethod != null) {
bug.addMethod(equalsMethod);
+ }
bugReporter.reportBug(bug);
}
}
if (!hasHashCode && !hasEqualsObject && !hasEqualsSelf && !usesDefaultEquals && usesDefaultHashCode && !obj.isAbstract()
&& inheritedEqualsFromAbstractClass) {
BugInstance bug = new BugInstance(this, "HE_INHERITS_EQUALS_USE_HASHCODE", NORMAL_PRIORITY)
- .addClass(getDottedClassName());
- if (equalsMethod != null)
+ .addClass(getDottedClassName());
+ if (equalsMethod != null) {
bug.addMethod(equalsMethod);
+ }
bugReporter.reportBug(bug);
}
if (!hasEqualsObject && !hasEqualsSelf && !usesDefaultEquals && !obj.isAbstract() && hasFields && inheritedEquals != null
&& !inheritedEqualsIsFinal && !inheritedEqualsFromAbstractClass
&& !inheritedEquals.getClassDescriptor().getSimpleName().contains("Abstract")
- && !inheritedEquals.getClassDescriptor().getClassName().equals("java/lang/Enum")) {
+ && !"java/lang/Enum".equals(inheritedEquals.getClassDescriptor().getClassName())) {
- BugInstance bug = new BugInstance(this, "EQ_DOESNT_OVERRIDE_EQUALS", NORMAL_PRIORITY).addClass(this)
- .addMethod(inheritedEquals).describe(MethodAnnotation.METHOD_DID_YOU_MEAN_TO_OVERRIDE);
+ BugInstance bug = new BugInstance(this, "EQ_DOESNT_OVERRIDE_EQUALS", NORMAL_PRIORITY);
+
+ // create annotation pointing to this class source line 1, otherwise the primary annotation shows parent class
+ SourceLineAnnotation sourceLine = new SourceLineAnnotation(getDottedClassName(), obj.getSourceFileName(), 1, 1, 0, 0);
+ bug.addClass(getDottedClassName()).add(sourceLine);
+ bug.addMethod(inheritedEquals).describe(MethodAnnotation.METHOD_DID_YOU_MEAN_TO_OVERRIDE);
bugReporter.reportBug(bug);
}
}
@Override
public void visit(JavaClass obj) {
- extendsObject = getDottedSuperclassName().equals("java.lang.Object");
+ extendsObject = "java.lang.Object".equals(getDottedSuperclassName());
hasFields = false;
hasHashCode = false;
hasCompareToObject = false;
@@ -322,18 +359,19 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
equalsOtherClass = null;
isApplicationClass = AnalysisContext.currentAnalysisContext().isApplicationClass(obj);
}
-
+
@Override
public boolean shouldVisitCode(Code obj) {
- if (isApplicationClass)
+ if (isApplicationClass) {
return true;
+ }
String name = getMethod().getName();
- if (name.equals("hashCode") || name.equals("equals"))
+ if ("hashCode".equals(name) || "equals".equals(name)) {
return true;
+ }
return false;
-
+
}
- boolean isApplicationClass;
public static int opcode(byte code[], int offset) {
return code[offset] & 0xff;
@@ -342,47 +380,49 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
@Override
public void visit(Field obj) {
int accessFlags = obj.getAccessFlags();
- if ((accessFlags & ACC_STATIC) != 0)
+ if ((accessFlags & ACC_STATIC) != 0) {
return;
- if (!obj.getName().startsWith("this$") && !BCELUtil.isSynthetic(obj) && !obj.isTransient())
+ }
+ if (!obj.getName().startsWith("this$") && !BCELUtil.isSynthetic(obj) && !obj.isTransient()) {
hasFields = true;
+ }
}
- static final Pattern predicateOverAnInstance = Pattern.compile("\\(L([^;]+);\\)Z");
-
@Override
public void visit(Method obj) {
int accessFlags = obj.getAccessFlags();
- if ((accessFlags & ACC_STATIC) != 0)
+ if ((accessFlags & ACC_STATIC) != 0) {
return;
+ }
String name = obj.getName();
String sig = obj.getSignature();
if ((accessFlags & ACC_ABSTRACT) != 0) {
- if (name.equals("equals") && sig.equals("(L" + getClassName() + ";)Z")) {
+ if ("equals".equals(name) && sig.equals("(L" + getClassName() + ";)Z")) {
bugReporter.reportBug(new BugInstance(this, "EQ_ABSTRACT_SELF", LOW_PRIORITY).addClass(getDottedClassName()));
return;
- } else if (name.equals("compareTo") && sig.equals("(L" + getClassName() + ";)I")) {
+ } else if ("compareTo".equals(name) && sig.equals("(L" + getClassName() + ";)I")) {
bugReporter.reportBug(new BugInstance(this, "CO_ABSTRACT_SELF", LOW_PRIORITY).addClass(getDottedClassName()));
return;
}
}
- boolean sigIsObject = sig.equals("(Ljava/lang/Object;)Z");
- if (name.equals("hashCode") && sig.equals("()I")) {
+ boolean sigIsObject = "(Ljava/lang/Object;)Z".equals(sig);
+ if ("hashCode".equals(name) && "()I".equals(sig)) {
hasHashCode = true;
- if (obj.isAbstract())
+ if (obj.isAbstract()) {
hashCodeIsAbstract = true;
+ }
hashCodeMethod = MethodAnnotation.fromVisitedMethod(this);
// System.out.println("Found hashCode for " + betterClassName);
- } else if (obj.isPublic() && name.equals("equals")) {
+ } else if (obj.isPublic() && "equals".equals(name)) {
Matcher m = predicateOverAnInstance.matcher(sig);
if (m.matches()) {
if (sigIsObject) {
equalsMethod = MethodAnnotation.fromVisitedMethod(this);
hasEqualsObject = true;
- if (obj.isAbstract())
+ if (obj.isAbstract()) {
equalsObjectIsAbstract = true;
- else if (!obj.isNative()) {
+ } else if (!obj.isNative()) {
Code code = obj.getCode();
byte[] codeBytes = code.getCode();
if (codeBytes.length == 9) {
@@ -395,8 +435,9 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
int op8 = opcode(codeBytes, 8);
if ((op0 == ALOAD_0 && op1 == ALOAD_1 || op0 == ALOAD_1 && op1 == ALOAD_0)
&& (op2 == IF_ACMPEQ || op2 == IF_ACMPNE) && (op5 == ICONST_0 || op5 == ICONST_1)
- && op6 == IRETURN && (op7 == ICONST_0 || op7 == ICONST_1) && op8 == IRETURN)
+ && op6 == IRETURN && (op7 == ICONST_0 || op7 == ICONST_1) && op8 == IRETURN) {
equalsMethodIsInstanceOfEquals = true;
+ }
} else if (codeBytes.length == 11) {
int op0 = opcode(codeBytes, 0);
int op1 = opcode(codeBytes, 1);
@@ -407,8 +448,9 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
int op10 = opcode(codeBytes, 10);
if ((op0 == ALOAD_0 && op1 == ALOAD_1 || op0 == ALOAD_1 && op1 == ALOAD_0)
&& (op2 == IF_ACMPEQ || op2 == IF_ACMPNE) && (op5 == ICONST_0 || op5 == ICONST_1)
- && op6 == GOTO && (op9 == ICONST_0 || op9 == ICONST_1) && op10 == IRETURN)
+ && op6 == GOTO && (op9 == ICONST_0 || op9 == ICONST_1) && op10 == IRETURN) {
equalsMethodIsInstanceOfEquals = true;
+ }
} else if ((codeBytes.length == 5 && (codeBytes[1] & 0xff) == INSTANCEOF)
|| (codeBytes.length == 15 && (codeBytes[1] & 0xff) == INSTANCEOF && (codeBytes[11] & 0xff) == INVOKESPECIAL)) {
@@ -417,8 +459,9 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
}
} else if (sig.equals("(L" + getClassName() + ";)Z")) {
hasEqualsSelf = true;
- if (equalsMethod == null)
+ if (equalsMethod == null) {
equalsMethod = MethodAnnotation.fromVisitedMethod(this);
+ }
} else {
String arg = m.group(1);
if (getSuperclassName().equals(arg)) {
@@ -432,11 +475,12 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
}
}
- } else if (name.equals("compareTo") && sig.endsWith(")I") && !obj.isStatic()) {
+ } else if ("compareTo".equals(name) && sig.endsWith(")I") && !obj.isStatic()) {
MethodAnnotation tmp = MethodAnnotation.fromVisitedMethod(this);
- if (BCELUtil.isSynthetic(obj))
+ if (BCELUtil.isSynthetic(obj)) {
hasCompareToBridgeMethod = true;
- if (sig.equals("(Ljava/lang/Object;)I")) {
+ }
+ if ("(Ljava/lang/Object;)I".equals(sig)) {
hasCompareToObject = true;
compareToObjectMethod = compareToMethod = tmp;
} else if (sig.equals("(L" + getClassName() + ";)I")) {
@@ -448,9 +492,11 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
Method findMethod(JavaClass clazz, String name, String sig) {
Method[] m = clazz.getMethods();
- for (Method aM : m)
- if (aM.getName().equals(name) && aM.getSignature().equals(sig))
+ for (Method aM : m) {
+ if (aM.getName().equals(name) && aM.getSignature().equals(sig)) {
return aM;
+ }
+ }
return null;
}
@@ -458,23 +504,25 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
public void sawOpcode(int seen) {
if (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) {
String className = getClassConstantOperand();
- if (className.equals("java/util/Map") || className.equals("java/util/HashMap")
- || className.equals("java/util/LinkedHashMap") || className.equals("java/util/concurrent/ConcurrentHashMap")
+ if ("java/util/Map".equals(className) || "java/util/HashMap".equals(className)
+ || "java/util/LinkedHashMap".equals(className) || "java/util/concurrent/ConcurrentHashMap".equals(className)
|| className.contains("Hash")
&& Subtypes2.instanceOf(ClassName.toDottedClassName(className), "java.util.Map")) {
- if (getNameConstantOperand().equals("put")
- && getSigConstantOperand().equals("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
- && stack.getStackDepth() >= 3)
+ if ("put".equals(getNameConstantOperand())
+ && "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;".equals(getSigConstantOperand())
+ && stack.getStackDepth() >= 3) {
check(1);
- else if ((getNameConstantOperand().equals("get") || getNameConstantOperand().equals("remove"))
- && getSigConstantOperand().startsWith("(Ljava/lang/Object;)") && stack.getStackDepth() >= 2)
+ } else if (("get".equals(getNameConstantOperand()) || "remove".equals(getNameConstantOperand()))
+ && getSigConstantOperand().startsWith("(Ljava/lang/Object;)") && stack.getStackDepth() >= 2) {
check(0);
- } else if (className.equals("java/util/Set") || className.equals("java/util/HashSet") || className.contains("Hash")
+ }
+ } else if ("java/util/Set".equals(className) || "java/util/HashSet".equals(className) || className.contains("Hash")
&& Subtypes2.instanceOf(ClassName.toDottedClassName(className), "java.util.Set")) {
- if (getNameConstantOperand().equals("add") || getNameConstantOperand().equals("contains")
- || getNameConstantOperand().equals("remove") && getSigConstantOperand().equals("(Ljava/lang/Object;)Z")
- && stack.getStackDepth() >= 2)
+ if ("add".equals(getNameConstantOperand()) || "contains".equals(getNameConstantOperand())
+ || "remove".equals(getNameConstantOperand()) && "(Ljava/lang/Object;)Z".equals(getSigConstantOperand())
+ && stack.getStackDepth() >= 2) {
check(0);
+ }
}
}
}
@@ -488,68 +536,74 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
- if (type == null)
+ if (type == null) {
return;
+ }
String typeName = type.getClassName();
- if (typeName.startsWith("java.lang"))
+ if (typeName.startsWith("java.lang")) {
return;
+ }
int priority = NORMAL_PRIORITY;
OpcodeStack.Item collection = stack.getStackItem(PreorderVisitor.getNumberArguments(getSigConstantOperand()));
String collectionSignature = collection.getSignature();
if (collectionSignature.indexOf("Tree") >= 0
|| collectionSignature.indexOf("Sorted") >= 0
- || collectionSignature.indexOf("SkipList") >= 0 )
+ || collectionSignature.indexOf("SkipList") >= 0 ) {
return;
+ }
- if (collectionSignature.indexOf("Hash") >= 0)
+ if (collectionSignature.indexOf("Hash") >= 0) {
priority--;
- if (!AnalysisContext.currentAnalysisContext()/* .getSubtypes() */.isApplicationClass(type))
+ }
+ if (!AnalysisContext.currentAnalysisContext()/* .getSubtypes() */.isApplicationClass(type)) {
priority++;
+ }
- if (type.isAbstract() || type.isInterface())
+ if (type.isAbstract() || type.isInterface()) {
priority++;
+ }
potentialBugs.put(
type.getClassName(),
new BugInstance(this, "HE_USE_OF_UNHASHABLE_CLASS", priority).addClassAndMethod(this)
- .addTypeOfNamedClass(type.getClassName()).describe(TypeAnnotation.UNHASHABLE_ROLE).addCalledMethod(this)
- .addSourceLine(this));
+ .addTypeOfNamedClass(type.getClassName()).describe(TypeAnnotation.UNHASHABLE_ROLE).addCalledMethod(this)
+ .addSourceLine(this));
}
- static final Pattern mapPattern = Pattern.compile("[^y]HashMap<L([^;<]*);");
-
- static final Pattern hashTablePattern = Pattern.compile("Hashtable<L([^;<]*);");
-
- static final Pattern setPattern = Pattern.compile("[^y]HashSet<L([^;<]*);");
-
@CheckForNull
@DottedClassName
String findHashedClassInSignature(String sig) {
Matcher m = mapPattern.matcher(sig);
- if (m.find())
+ if (m.find()) {
return m.group(1).replace('/', '.');
+ }
m = hashTablePattern.matcher(sig);
- if (m.find())
+ if (m.find()) {
return m.group(1).replace('/', '.');
+ }
m = setPattern.matcher(sig);
- if (m.find())
+ if (m.find()) {
return m.group(1).replace('/', '.');
+ }
return null;
}
@Override
public void visit(Signature obj) {
- if (!isApplicationClass)
+ if (!isApplicationClass) {
return;
+ }
String sig = obj.getSignature();
String className = findHashedClassInSignature(sig);
- if (className == null)
+ if (className == null) {
return;
- if (className.startsWith("java.lang"))
+ }
+ if (className.startsWith("java.lang")) {
return;
+ }
JavaClass type = null;
try {
@@ -557,28 +611,33 @@ public class FindHEmismatch extends OpcodeStackDetector implements StatelessDete
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
- if (type == null)
+ if (type == null) {
return;
+ }
int priority = NORMAL_PRIORITY;
- if (sig.indexOf("Hash") >= 0)
+ if (sig.indexOf("Hash") >= 0) {
priority--;
- if (type.isAbstract() || type.isInterface())
+ }
+ if (type.isAbstract() || type.isInterface()) {
priority++;
- if (!AnalysisContext.currentAnalysisContext()/* .getSubtypes() */.isApplicationClass(type))
+ }
+ if (!AnalysisContext.currentAnalysisContext()/* .getSubtypes() */.isApplicationClass(type)) {
priority++;
+ }
BugInstance bug = null;
- if (visitingField())
+ if (visitingField()) {
bug = new BugInstance(this, "HE_SIGNATURE_DECLARES_HASHING_OF_UNHASHABLE_CLASS", priority).addClass(this)
.addVisitedField(this).addTypeOfNamedClass(className).describe(TypeAnnotation.UNHASHABLE_ROLE);
- else if (visitingMethod())
+ } else if (visitingMethod()) {
bug = new BugInstance(this, "HE_SIGNATURE_DECLARES_HASHING_OF_UNHASHABLE_CLASS", priority).addClassAndMethod(this)
.addTypeOfNamedClass(className).describe(TypeAnnotation.UNHASHABLE_ROLE);
- else
+ } else {
bug = new BugInstance(this, "HE_SIGNATURE_DECLARES_HASHING_OF_UNHASHABLE_CLASS", priority).addClass(this)
.addClass(this).addTypeOfNamedClass(className).describe(TypeAnnotation.UNHASHABLE_ROLE);
+ }
potentialBugs.put(className, bug);
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindInconsistentSync2.java b/src/java/edu/umd/cs/findbugs/detect/FindInconsistentSync2.java
index b3ea411..13f91ad 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindInconsistentSync2.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindInconsistentSync2.java
@@ -28,6 +28,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import org.apache.bcel.Constants;
@@ -190,8 +191,9 @@ public class FindInconsistentSync2 implements Detector {
public static Collection<SourceLineAnnotation> asSourceLineAnnotation(Collection<FieldAccess> c) {
ArrayList<SourceLineAnnotation> result = new ArrayList<SourceLineAnnotation>(c.size());
- for (FieldAccess f : c)
+ for (FieldAccess f : c) {
result.add(f.asSourceLineAnnotation());
+ }
return result;
}
@@ -207,13 +209,15 @@ public class FindInconsistentSync2 implements Detector {
try {
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
- if (subtypes2.isSubtype(classDescriptor, servlet) && !subtypes2.isSubtype(classDescriptor, singleThreadedServlet))
+ if (subtypes2.isSubtype(classDescriptor, servlet) && !subtypes2.isSubtype(classDescriptor, singleThreadedServlet)) {
return true;
+ }
} catch (ClassNotFoundException e) {
assert true;
}
- if (classDescriptor.getClassName().endsWith("Servlet"))
+ if (classDescriptor.getClassName().endsWith("Servlet")) {
return true;
+ }
return false;
}
@@ -279,10 +283,12 @@ public class FindInconsistentSync2 implements Detector {
}
public void addAccess(MethodDescriptor method, InstructionHandle handle, boolean isLocked) {
- if (!interesting)
+ if (!interesting) {
return;
- if (!SYNC_ACCESS && isLocked)
+ }
+ if (!SYNC_ACCESS && isLocked) {
return;
+ }
if (!servletField && !isLocked && syncAccessList.size() == 0 && unsyncAccessList.size() > 6) {
interesting = false;
@@ -291,21 +297,24 @@ public class FindInconsistentSync2 implements Detector {
return;
}
FieldAccess fa = new FieldAccess(method, handle.getPosition());
- if (isLocked)
+ if (isLocked) {
syncAccessList = Util.addTo(syncAccessList, fa);
- else
+ } else {
unsyncAccessList = Util.addTo(unsyncAccessList, fa);
+ }
}
public Iterator<SourceLineAnnotation> unsyncAccessIterator() {
- if (!interesting)
+ if (!interesting) {
throw new IllegalStateException("Not interesting");
+ }
return FieldAccess.asSourceLineAnnotation(unsyncAccessList).iterator();
}
public Iterator<SourceLineAnnotation> syncAccessIterator() {
- if (!interesting)
+ if (!interesting) {
throw new IllegalStateException("Not interesting");
+ }
return FieldAccess.asSourceLineAnnotation(syncAccessList).iterator();
}
}
@@ -330,10 +339,12 @@ public class FindInconsistentSync2 implements Detector {
this.bugReporter = bugReporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("******** Analyzing class " + javaClass.getClassName());
+ }
// Build self-call graph
SelfCalls selfCalls = new SelfCalls(classContext) {
@@ -350,9 +361,10 @@ public class FindInconsistentSync2 implements Detector {
try {
selfCalls.execute();
CallGraph callGraph = selfCalls.getCallGraph();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Call graph (not unlocked methods): " + callGraph.getNumVertices() + " nodes, "
+ callGraph.getNumEdges() + " edges");
+ }
// Find call edges that are obviously locked
Set<CallSite> obviouslyLockedSites = findObviouslyLockedCallSites(classContext, selfCalls);
lockedMethodSet = findNotUnlockedMethods(classContext, selfCalls, obviouslyLockedSites);
@@ -369,28 +381,33 @@ public class FindInconsistentSync2 implements Detector {
for (Method method : allMethods) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("******** considering method " + method.getName());
+ }
- if (classContext.getMethodGen(method) == null)
+ if (classContext.getMethodGen(method) == null) {
continue;
+ }
- if (method.getName().startsWith("access$"))
+ if (method.getName().startsWith("access$")) {
// Ignore inner class access methods;
// we will treat calls to them as field accesses
continue;
+ }
String name = method.getName();
- boolean inConstructor = name.equals("<init>") || name.equals("<clinit>")
- || name.equals("readObject") || name.equals("clone") || name.equals("close")
- || name.equals("finalize");
+ boolean inConstructor = "<init>".equals(name) || "<clinit>".equals(name)
+ || "readObject".equals(name) || "clone".equals(name) || "close".equals(name)
+ || "finalize".equals(name);
- if (inConstructor)
+ if (inConstructor) {
continue;
+ }
- if (DEBUG)
+ if (DEBUG) {
System.out.println("******** Analyzing method " + method.getName());
+ }
try {
analyzeMethod(classContext, method, lockedMethodSet);
@@ -400,33 +417,40 @@ public class FindInconsistentSync2 implements Detector {
bugReporter.logError("Error analyzing method", e);
}
}
- for (Field f : javaClass.getFields())
+ for (Field f : javaClass.getFields()) {
if (f.isPrivate()) {
XField xf = XFactory.getExactXField(classContext.getClassDescriptor().getClassName(), f);
FieldStats stats = statMap.get(xf);
- if (stats == null)
+ if (stats == null) {
continue;
- if (!stats.isServletField() && !stats.hasAnySynchronizedAccesses())
+ }
+ if (!stats.isServletField() && !stats.hasAnySynchronizedAccesses()) {
statMap.remove(xf);
+ }
}
+ }
}
+ @Override
public void report() {
if(statMap.isEmpty()){
return;
}
JCIPAnnotationDatabase jcipAnotationDatabase = AnalysisContext.currentAnalysisContext().getJCIPAnnotationDatabase();
- for (XField xfield : statMap.keySet()) {
- FieldStats stats = statMap.get(xfield);
- if (!stats.isInteresting())
+ for (Entry<XField, FieldStats> entry : statMap.entrySet()) {
+ XField xfield = entry.getKey();
+ FieldStats stats = entry.getValue();
+ if (!stats.isInteresting()) {
continue;
+ }
boolean notThreadSafe = jcipAnotationDatabase.hasClassAnnotation(xfield.getClassName(), "NotThreadSafe");
- if (notThreadSafe)
+ if (notThreadSafe) {
continue;
+ }
ElementValue guardedByValue = jcipAnotationDatabase.getFieldAnnotation(xfield, "GuardedBy");
boolean guardedByThis;
if(guardedByValue != null){
- guardedByThis = guardedByValue.stringifyValue().equals("this");
+ guardedByThis = "this".equals(guardedByValue.stringifyValue());
} else {
guardedByThis = false;
}
@@ -443,8 +467,9 @@ public class FindInconsistentSync2 implements Detector {
int numNullCheckLocked = stats.getNumAccesses(NULLCHECK_LOCKED);
int extra = 0;
- if (numWriteUnlocked > 0)
+ if (numWriteUnlocked > 0) {
extra = numNullCheckLocked;
+ }
int locked = numReadLocked + numWriteLocked + numNullCheckLocked;
int biasedLocked = numReadLocked + (int) (WRITE_BIAS * (numWriteLocked + numNullCheckLocked + extra));
int unlocked = numReadUnlocked + numWriteUnlocked + numNullCheckUnlocked;
@@ -470,13 +495,15 @@ public class FindInconsistentSync2 implements Detector {
// propertySet.addProperty(InconsistentSyncWarningProperty.NEVER_LOCKED);
}
- if (stats.isServletField() && numWriteLocked == 0 && numWriteUnlocked == 0)
+ if (stats.isServletField() && numWriteLocked == 0 && numWriteUnlocked == 0) {
continue;
+ }
if (DEBUG) {
System.out.println("IS2: " + xfield);
- if (guardedByThis)
+ if (guardedByThis) {
System.out.println("Guarded by this");
+ }
System.out.println(" RL: " + numReadLocked);
System.out.println(" WL: " + numWriteLocked);
System.out.println(" NL: " + numNullCheckLocked);
@@ -495,23 +522,26 @@ public class FindInconsistentSync2 implements Detector {
if (numWriteUnlocked + numWriteLocked == 0) {
// No writes outside of constructor
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" No writes outside of constructor");
+ }
propertySet.addProperty(InconsistentSyncWarningProperty.NEVER_WRITTEN);
// continue;
}
if (numReadUnlocked + numReadLocked == 0) {
// No reads outside of constructor
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" No reads outside of constructor");
+ }
// continue;
propertySet.addProperty(InconsistentSyncWarningProperty.NEVER_READ);
}
if (stats.getNumLocalLocks() == 0) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" No local locks");
+ }
// continue;
propertySet.addProperty(InconsistentSyncWarningProperty.NO_LOCAL_LOCKS);
}
@@ -528,8 +558,9 @@ public class FindInconsistentSync2 implements Detector {
// continue;
propertySet.addProperty(InconsistentSyncWarningProperty.BELOW_MIN_SYNC_PERCENT);
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" Sync %: " + freq);
+ }
if (stats.getNumGetterMethodAccesses() >= unlocked) {
// Unlocked accesses are only in getter method(s).
@@ -538,17 +569,19 @@ public class FindInconsistentSync2 implements Detector {
// At this point, we report the field as being inconsistently
// synchronized
- if (stats.isServletField())
+ if (stats.isServletField()) {
propertySet.addProperty(InconsistentSyncWarningProperty.MUTABLE_SERVLET_FIELD);
+ }
BugInstance bugInstance;
- if (stats.isServletField())
+ if (stats.isServletField()) {
bugInstance = new BugInstance(this, "MSF_MUTABLE_SERVLET_FIELD", Priorities.NORMAL_PRIORITY).addClass(
xfield.getClassName()).addField(xfield);
- else
+ } else {
bugInstance = new BugInstance(this, guardedByThis ? "IS_FIELD_NOT_GUARDED" : "IS2_INCONSISTENT_SYNC",
Priorities.NORMAL_PRIORITY).addClass(xfield.getClassName()).addField(xfield).addInt(printFreq)
.describe(IntAnnotation.INT_SYNC_PERCENT);
+ }
propertySet.decorateBugInstance(bugInstance);
// Add source lines for unsynchronized accesses
@@ -583,29 +616,31 @@ public class FindInconsistentSync2 implements Detector {
*/
private static boolean isConstructor(String methodName) {
- return methodName.equals("<init>") || methodName.equals("<clinit>") || methodName.equals("readObject")
- || methodName.equals("clone") || methodName.equals("close") || methodName.equals("writeObject")
- || methodName.equals("toString") || methodName.equals("init") || methodName.equals("initialize")
- || methodName.equals("dispose") || methodName.equals("finalize") || methodName.equals("this")
- || methodName.equals("_jspInit") || methodName.equals("_jspDestroy");
+ return "<init>".equals(methodName) || "<clinit>".equals(methodName) || "readObject".equals(methodName)
+ || "clone".equals(methodName) || "close".equals(methodName) || "writeObject".equals(methodName)
+ || "toString".equals(methodName) || "init".equals(methodName) || "initialize".equals(methodName)
+ || "dispose".equals(methodName) || "finalize".equals(methodName) || "this".equals(methodName)
+ || "_jspInit".equals(methodName) || "_jspDestroy".equals(methodName);
}
private void analyzeMethod(ClassContext classContext, Method method, Set<Method> lockedMethodSet) throws CFGBuilderException,
- DataflowAnalysisException {
+ DataflowAnalysisException {
InnerClassAccessMap icam = AnalysisContext.currentAnalysisContext().getInnerClassAccessMap();
ConstantPoolGen cpg = classContext.getConstantPoolGen();
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
CFG cfg = classContext.getCFG(method);
LockChecker lockChecker = classContext.getLockChecker(method);
ValueNumberDataflow vnaDataflow = classContext.getValueNumberDataflow(method);
boolean isGetterMethod = isGetterMethod(classContext, method);
MethodDescriptor methodDescriptor = DescriptorFactory.instance().getMethodDescriptor(classContext.getJavaClass(), method);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("**** Analyzing method " + SignatureConverter.convertMethodSignature(methodGen));
+ }
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
@@ -619,16 +654,20 @@ public class FindInconsistentSync2 implements Detector {
if (ins instanceof FieldInstruction) {
InstructionHandle n = location.getHandle().getNext();
isNullCheck = n.getInstruction() instanceof IFNONNULL || n.getInstruction() instanceof IFNULL;
- if (DEBUG && isNullCheck)
+ if (DEBUG && isNullCheck) {
System.out.println("is null check");
+ }
FieldInstruction fins = (FieldInstruction) ins;
xfield = Hierarchy.findXField(fins, cpg);
- if (xfield == null) continue;
+ if (xfield == null) {
+ continue;
+ }
isWrite = ins.getOpcode() == Constants.PUTFIELD;
isLocal = fins.getClassName(cpg).equals(classContext.getJavaClass().getClassName());
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Handling field access: " + location.getHandle() + " (frame="
+ vnaDataflow.getFactAtLocation(location) + ") :" + n);
+ }
} else if (ins instanceof INVOKESTATIC) {
INVOKESTATIC inv = (INVOKESTATIC) ins;
InnerClassAccess access = icam.getInnerClassAccess(inv, cpg);
@@ -636,25 +675,29 @@ public class FindInconsistentSync2 implements Detector {
xfield = access.getField();
isWrite = !access.isLoad();
isLocal = false;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Handling inner class access: " + location.getHandle() + " (frame="
+ vnaDataflow.getFactAtLocation(location) + ")");
+ }
}
}
- if (xfield == null)
+ if (xfield == null) {
continue;
+ }
// We only care about mutable nonvolatile nonpublic instance
// fields.
- if (xfield.isStatic() || xfield.isPublic() || xfield.isVolatile() || xfield.isFinal())
+ if (xfield.isStatic() || xfield.isPublic() || xfield.isVolatile() || xfield.isFinal()) {
continue;
+ }
// The value number frame could be invalid if the basic
// block became unreachable due to edge pruning (dead code).
ValueNumberFrame frame = vnaDataflow.getFactAtLocation(location);
- if (!frame.isValid())
+ if (!frame.isValid()) {
continue;
+ }
// Get lock set and instance value
ValueNumber thisValue = !method.isStatic() ? vnaDataflow.getAnalysis().getThisValue() : null;
@@ -690,12 +733,14 @@ public class FindInconsistentSync2 implements Detector {
// Find the type of the object instance
TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
TypeFrame typeFrame = typeDataflow.getFactAtLocation(location);
- if (!typeFrame.isValid())
+ if (!typeFrame.isValid()) {
continue;
+ }
Type instanceType = typeFrame.getInstance(handle.getInstruction(), cpg);
if (instanceType instanceof TopType) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Freaky: typeFrame is " + typeFrame);
+ }
continue;
}
// Note: instance type can be Null,
@@ -723,12 +768,14 @@ public class FindInconsistentSync2 implements Detector {
kind |= isWrite ? WRITE : isNullCheck ? NULLCHECK : READ;
// if (isLocked || !isConstructor(method.getName())) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("IS2:\t" + SignatureConverter.convertMethodSignature(methodGen) + "\t" + xfield + "\t"
+ ((isWrite ? "W" : "R") + "/" + (isLocked ? "L" : "U")));
+ }
- if (!isLocked && methodDescriptor.getClassDescriptor().isAnonymousClass())
+ if (!isLocked && methodDescriptor.getClassDescriptor().isAnonymousClass()) {
continue;
+ }
FieldStats stats = getStats(xfield);
@@ -740,11 +787,13 @@ public class FindInconsistentSync2 implements Detector {
stats.addAccess(kind);
}
- if (isExplicitlyLocked && isLocal)
+ if (isExplicitlyLocked && isLocal) {
stats.addLocalLock();
+ }
- if (isGetterMethod && !isLocked)
+ if (isGetterMethod && !isLocked) {
stats.addGetterMethodAccess();
+ }
stats.addAccess(methodDescriptor, handle, isLocked);
// }
@@ -765,12 +814,14 @@ public class FindInconsistentSync2 implements Detector {
*/
public static boolean isGetterMethod(ClassContext classContext, Method method) {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return false;
+ }
InstructionList il = methodGen.getInstructionList();
// System.out.println("Checking getter method: " + method.getName());
- if (il.getLength() > 60)
+ if (il.getLength() > 60) {
return false;
+ }
int count = 0;
Iterator<InstructionHandle> it = il.iterator();
@@ -779,8 +830,9 @@ public class FindInconsistentSync2 implements Detector {
switch (ih.getInstruction().getOpcode()) {
case Constants.GETFIELD:
count++;
- if (count > 1)
+ if (count > 1) {
return false;
+ }
break;
case Constants.PUTFIELD:
case Constants.BALOAD:
@@ -832,7 +884,7 @@ public class FindInconsistentSync2 implements Detector {
* which is not really a valid assumption.
*/
private static Set<Method> findNotUnlockedMethods(ClassContext classContext, SelfCalls selfCalls, Set<CallSite> obviouslyLockedSites)
- {
+ {
JavaClass javaClass = classContext.getJavaClass();
Method[] methodList = javaClass.getMethods();
@@ -863,18 +915,21 @@ public class FindInconsistentSync2 implements Detector {
CallSite callSite = edge.getCallSite();
// Ignore obviously locked edges
- if (obviouslyLockedSites.contains(callSite))
+ if (obviouslyLockedSites.contains(callSite)) {
continue;
+ }
// If the calling method is locked, ignore the edge
- if (lockedMethodSet.contains(callSite.getMethod()))
+ if (lockedMethodSet.contains(callSite.getMethod())) {
continue;
+ }
// Calling method is unlocked, so the called method
// is also unlocked.
CallGraphNode target = edge.getTarget();
- if (lockedMethodSet.remove(target.getMethod()))
+ if (lockedMethodSet.remove(target.getMethod())) {
change = true;
+ }
}
} while (change);
@@ -896,7 +951,7 @@ public class FindInconsistentSync2 implements Detector {
* which is not really a valid assumption.
*/
private static Set<Method> findLockedMethods(ClassContext classContext, SelfCalls selfCalls, Set<CallSite> obviouslyLockedSites)
- {
+ {
JavaClass javaClass = classContext.getJavaClass();
Method[] methodList = javaClass.getMethods();
@@ -927,8 +982,9 @@ public class FindInconsistentSync2 implements Detector {
// Calling method is locked, so the called method
// is also locked.
CallGraphNode target = edge.getTarget();
- if (lockedMethodSet.add(target.getMethod()))
+ if (lockedMethodSet.add(target.getMethod())) {
change = true;
+ }
}
}
} while (change);
@@ -1006,8 +1062,9 @@ public class FindInconsistentSync2 implements Detector {
// Only instance method calls qualify as candidates for
// "obviously locked"
Instruction ins = handle.getInstruction();
- if (ins.getOpcode() == Constants.INVOKESTATIC)
+ if (ins.getOpcode() == Constants.INVOKESTATIC) {
continue;
+ }
// Get lock set for site
LockChecker lockChecker = classContext.getLockChecker(method);
@@ -1020,15 +1077,17 @@ public class FindInconsistentSync2 implements Detector {
// NOTE: if the CFG on which the value number analysis was performed
// was pruned, there may be unreachable instructions. Therefore,
// we can't assume the frame is valid.
- if (!frame.isValid())
+ if (!frame.isValid()) {
continue;
+ }
// Find the ValueNumber of the receiver object
int numConsumed = ins.consumeStack(cpg);
MethodGen methodGen = classContext.getMethodGen(method);
assert methodGen != null;
- if (numConsumed == Constants.UNPREDICTABLE)
+ if (numConsumed == Constants.UNPREDICTABLE) {
throw new DataflowAnalysisException("Unpredictable stack consumption", methodGen, handle);
+ }
// if (DEBUG) System.out.println("Getting receiver for frame: " +
// frame);
ValueNumber instance = frame.getStackValue(numConsumed - 1);
@@ -1045,4 +1104,3 @@ public class FindInconsistentSync2 implements Detector {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindJSR166LockMonitorenter.java b/src/java/edu/umd/cs/findbugs/detect/FindJSR166LockMonitorenter.java
index a9f3902..3ecfb69 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindJSR166LockMonitorenter.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindJSR166LockMonitorenter.java
@@ -58,7 +58,7 @@ import edu.umd.cs.findbugs.classfile.DescriptorFactory;
/**
* Find places where ordinary (balanced) synchronization is performed on JSR166
* Lock objects. Suggested by Doug Lea.
- *
+ *
* @author David Hovemeyer
*/
public final class FindJSR166LockMonitorenter implements Detector, StatelessDetector {
@@ -67,7 +67,7 @@ public final class FindJSR166LockMonitorenter implements Detector, StatelessDete
*/
private static final String UTIL_CONCURRRENT_SIG_PREFIX = "Ljava/util/concurrent/";
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private static final ObjectType LOCK_TYPE = ObjectTypeFactory.getInstance("java.util.concurrent.locks.Lock");
@@ -84,22 +84,27 @@ public final class FindJSR166LockMonitorenter implements Detector, StatelessDete
}
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass jclass = classContext.getJavaClass();
- if (jclass.getClassName().startsWith("java.util.concurrent."))
+ if (jclass.getClassName().startsWith("java.util.concurrent.")) {
return;
+ }
Method[] methodList = jclass.getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
// We can ignore methods that don't contain a monitorenter
BitSet bytecodeSet = classContext.getBytecodeSet(method);
- if (bytecodeSet == null)
+ if (bytecodeSet == null) {
continue;
- if (false && !bytecodeSet.get(Constants.MONITORENTER))
+ }
+ if (false && !bytecodeSet.get(Constants.MONITORENTER)) {
continue;
+ }
analyzeMethod(classContext, method);
@@ -134,13 +139,14 @@ public final class FindJSR166LockMonitorenter implements Detector, StatelessDete
String methodName = iv.getMethodName(cpg);
String methodSig = iv.getSignature(cpg);
- if (methodName.equals("wait")
- && (methodSig.equals("()V") || methodSig.equals("(J)V") || methodSig.equals("(JI)V"))
- || (methodName.equals("notify") || methodName.equals("notifyAll")) && methodSig.equals("()V")) {
+ if ("wait".equals(methodName)
+ && ("()V".equals(methodSig) || "(J)V".equals(methodSig) || "(JI)V".equals(methodSig))
+ || ("notify".equals(methodName) || "notifyAll".equals(methodName)) && "()V".equals(methodSig)) {
try {
TypeFrame frame = typeDataflow.getFactAtLocation(location);
- if (!frame.isValid())
+ if (!frame.isValid()) {
continue;
+ }
Type type = frame.getInstance(ins, cpg);
if (!(type instanceof ReferenceType)) {
// Something is deeply wrong if a non-reference type
@@ -151,33 +157,38 @@ public final class FindJSR166LockMonitorenter implements Detector, StatelessDete
}
ClassDescriptor classDescriptor = DescriptorFactory.createClassDescriptorFromSignature(type
.getSignature());
- if (classDescriptor.equals(classContext.getClassDescriptor()))
+ if (classDescriptor.equals(classContext.getClassDescriptor())) {
continue;
- if (!classDescriptor.getClassName().startsWith("java/util/concurrent"))
+ }
+ if (!classDescriptor.getClassName().startsWith("java/util/concurrent")) {
continue;
+ }
XClass c = Lookup.getXClass(classDescriptor);
XMethod m;
int priority = NORMAL_PRIORITY;
- if (methodName.equals("wait")) {
+ if ("wait".equals(methodName)) {
m = c.findMethod("await", "()V", false);
priority = HIGH_PRIORITY;
- } else if (methodName.equals("notify")) {
+ } else if ("notify".equals(methodName)) {
m = c.findMethod("signal", "()V", false);
- if (m == null)
+ if (m == null) {
m = c.findMethod("countDown", "()V", false);
- } else if (methodName.equals("notifyAll")) {
+ }
+ } else if ("notifyAll".equals(methodName)) {
m = c.findMethod("signalAll", "()V", false);
- if (m == null)
+ if (m == null) {
m = c.findMethod("countDown", "()V", false);
- } else
+ }
+ } else {
throw new IllegalStateException("Unexpected methodName: " + methodName);
+ }
- if (m != null && m.isPublic() && c.isPublic())
-
+ if (m != null && m.isPublic() && c.isPublic()) {
bugReporter.reportBug(new BugInstance(this, "JML_JSR166_CALLING_WAIT_RATHER_THAN_AWAIT", priority)
- .addClassAndMethod(classContext.getJavaClass(), method).addCalledMethod(cpg, iv).addMethod(m)
- .describe(MethodAnnotation.METHOD_ALTERNATIVE_TARGET).addType(classDescriptor)
- .describe(TypeAnnotation.FOUND_ROLE).addSourceLine(classContext, method, location));
+ .addClassAndMethod(classContext.getJavaClass(), method).addCalledMethod(cpg, iv).addMethod(m)
+ .describe(MethodAnnotation.METHOD_ALTERNATIVE_TARGET).addType(classDescriptor)
+ .describe(TypeAnnotation.FOUND_ROLE).addSourceLine(classContext, method, location));
+ }
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("Coult not get Type dataflow", e);
@@ -188,13 +199,15 @@ public final class FindJSR166LockMonitorenter implements Detector, StatelessDete
}
- if (ins.getOpcode() != Constants.MONITORENTER)
+ if (ins.getOpcode() != Constants.MONITORENTER) {
continue;
+ }
Type type;
try {
TypeFrame frame = typeDataflow.getFactAtLocation(location);
- if (!frame.isValid())
+ if (!frame.isValid()) {
continue;
+ }
type = frame.getInstance(ins, cpg);
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("Coult not get Type dataflow", e);
@@ -225,15 +238,15 @@ public final class FindJSR166LockMonitorenter implements Detector, StatelessDete
int priority = "Ljava/util/concurrent/CopyOnWriteArrayList;".equals(sig) ? HIGH_PRIORITY : NORMAL_PRIORITY;
bugReporter.reportBug(new BugInstance(this, "JLM_JSR166_UTILCONCURRENT_MONITORENTER", priority)
- .addClassAndMethod(classContext.getJavaClass(), method).addType(sig)
- .addSourceForTopStackValue(classContext, method, location).addSourceLine(classContext, method, location));
+ .addClassAndMethod(classContext.getJavaClass(), method).addType(sig)
+ .addSourceForTopStackValue(classContext, method, location).addSourceLine(classContext, method, location));
}
}
}
+ @Override
public void report() {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindLocalSelfAssignment2.java b/src/java/edu/umd/cs/findbugs/detect/FindLocalSelfAssignment2.java
index 3229aa6..bcb0445 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindLocalSelfAssignment2.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindLocalSelfAssignment2.java
@@ -34,7 +34,7 @@ import edu.umd.cs.findbugs.ba.XField;
public class FindLocalSelfAssignment2 extends BytecodeScanningDetector implements StatelessDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private int previousLoadOf = -1;
@@ -46,7 +46,7 @@ public class FindLocalSelfAssignment2 extends BytecodeScanningDetector implement
this.bugReporter = bugReporter;
}
- private BitSet previousStores = new BitSet();
+ private final BitSet previousStores = new BitSet();
@Override
public void visit(Code obj) {
@@ -62,26 +62,28 @@ public class FindLocalSelfAssignment2 extends BytecodeScanningDetector implement
if (seen == GOTO) {
previousGotoTarget = getBranchTarget();
gotoCount++;
- if (previousGotoTarget < getPC())
+ if (previousGotoTarget < getPC()) {
previousLoadOf = -1;
+ }
} else {
- if (isRegisterLoad())
+ if (isRegisterLoad()) {
previousLoadOf = getRegisterOperand();
- else {
+ } else {
if (isRegisterStore()) {
if (previousLoadOf == getRegisterOperand() && gotoCount < 2 && getPC() != previousGotoTarget) {
int priority = NORMAL_PRIORITY;
String methodName = getMethodName();
- if (methodName.equals("<init>") || methodName.startsWith("set") && getCode().getCode().length <= 5
- || !previousStores.get(getRegisterOperand()))
+ if ("<init>".equals(methodName) || methodName.startsWith("set") && getCode().getCode().length <= 5
+ || !previousStores.get(getRegisterOperand())) {
priority = HIGH_PRIORITY;
+ }
previousStores.set(getRegisterOperand());
XClass c = getXClass();
LocalVariableAnnotation local = LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(),
getRegisterOperand(), getPC(), getPC());
- if (local.getName().equals("?")) {
+ if ("?".equals(local.getName())) {
priority++;
- } else
+ } else {
for (XField f : c.getXFields()) {
if (f.getName().equals(local.getName()) && (f.isStatic() || !getMethod().isStatic())) {
bugReporter.reportBug(new BugInstance(this, "SA_LOCAL_SELF_ASSIGNMENT_INSTEAD_OF_FIELD",
@@ -91,11 +93,13 @@ public class FindLocalSelfAssignment2 extends BytecodeScanningDetector implement
}
}
+ }
bugReporter.reportBug(new BugInstance(this, "SA_LOCAL_SELF_ASSIGNMENT", priority).addClassAndMethod(this)
.add(local).addSourceLine(this));
- } else
+ } else {
previousStores.set(getRegisterOperand());
+ }
}
previousLoadOf = -1;
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindMaskedFields.java b/src/java/edu/umd/cs/findbugs/detect/FindMaskedFields.java
index 649cb71..5eac18d 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindMaskedFields.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindMaskedFields.java
@@ -46,15 +46,15 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.Global;
public class FindMaskedFields extends BytecodeScanningDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private int numParms;
- private Map<String, Field> classFields = new HashMap<String, Field>();
+ private final Map<String, Field> classFields = new HashMap<String, Field>();
private boolean staticMethod;
- private Collection<RememberedBug> rememberedBugs = new LinkedList<RememberedBug>();
+ private final Collection<RememberedBug> rememberedBugs = new LinkedList<RememberedBug>();
static class RememberedBug {
BugInstance bug;
@@ -75,8 +75,9 @@ public class FindMaskedFields extends BytecodeScanningDetector {
@Override
public void visitClassContext(ClassContext classContext) {
JavaClass obj = classContext.getJavaClass();
- if (!obj.isInterface())
+ if (!obj.isInterface()) {
classContext.getJavaClass().accept(this);
+ }
}
@Override
@@ -85,19 +86,21 @@ public class FindMaskedFields extends BytecodeScanningDetector {
Field[] fields = obj.getFields();
String fieldName;
- for (Field field : fields)
+ for (Field field : fields) {
if (!field.isStatic() && !field.isPrivate()) {
fieldName = field.getName();
classFields.put(fieldName, field);
}
+ }
// Walk up the super class chain, looking for name collisions
XClass c = getXClass();
while (true) {
ClassDescriptor s = c.getSuperclassDescriptor();
- if (s == null || s.getClassName().equals("java/lang/Object"))
+ if (s == null || "java/lang/Object".equals(s.getClassName())) {
break;
+ }
try {
c = Global.getAnalysisCache().getClassAnalysis(XClass.class, s);
} catch (CheckedAnalysisException e) {
@@ -107,32 +110,38 @@ public class FindMaskedFields extends BytecodeScanningDetector {
for (XField fld : c.getXFields()) {
if (!fld.isStatic() && (fld.isPublic() || fld.isProtected())) {
fieldName = fld.getName();
- if (fieldName.length() == 1)
+ if (fieldName.length() == 1) {
continue;
- if (fieldName.equals("serialVersionUID"))
+ }
+ if ("serialVersionUID".equals(fieldName)) {
continue;
+ }
String superClassName = s.getClassName();
if (superClassName.startsWith("java/io")
- && (superClassName.endsWith("InputStream") && fieldName.equals("in") || superClassName
- .endsWith("OutputStream") && fieldName.equals("out")))
+ && (superClassName.endsWith("InputStream") && "in".equals(fieldName) || superClassName
+ .endsWith("OutputStream") && "out".equals(fieldName))) {
continue;
+ }
if (classFields.containsKey(fieldName)) {
Field maskingField = classFields.get(fieldName);
String mClassName = getDottedClassName();
FieldAnnotation fa = new FieldAnnotation(mClassName, maskingField.getName(), maskingField.getSignature(),
maskingField.isStatic());
int priority = NORMAL_PRIORITY;
- if (maskingField.isStatic() || maskingField.isFinal())
+ if (maskingField.isStatic() || maskingField.isFinal()) {
priority++;
- else if (fld.getSignature().charAt(0) == 'L' && !fld.getSignature().startsWith("Ljava/lang/")
- || fld.getSignature().charAt(0) == '[')
+ } else if (fld.getSignature().charAt(0) == 'L' && !fld.getSignature().startsWith("Ljava/lang/")
+ || fld.getSignature().charAt(0) == '[') {
priority--;
- if (!fld.getSignature().equals(maskingField.getSignature()))
+ }
+ if (!fld.getSignature().equals(maskingField.getSignature())) {
priority += 2;
- else if (fld.getAccessFlags() != maskingField.getAccessFlags())
+ } else if (fld.getAccessFlags() != maskingField.getAccessFlags()) {
priority++;
- if (fld.isSynthetic() || fld.getName().indexOf('$') >= 0)
+ }
+ if (fld.isSynthetic() || fld.getName().indexOf('$') >= 0) {
priority++;
+ }
FieldAnnotation maskedFieldAnnotation = FieldAnnotation.fromFieldDescriptor(fld.getFieldDescriptor());
BugInstance bug = new BugInstance(this, "MF_CLASS_MASKS_FIELD", priority).addClass(this).addField(fa)
@@ -151,8 +160,9 @@ public class FindMaskedFields extends BytecodeScanningDetector {
public void visit(Method obj) {
super.visit(obj);
numParms = getNumberMethodArguments();
- if (!obj.isStatic())
+ if (!obj.isStatic()) {
numParms++;
+ }
// System.out.println(obj);
// System.out.println(numParms);
staticMethod = obj.isStatic();
@@ -167,17 +177,20 @@ public class FindMaskedFields extends BytecodeScanningDetector {
@Override
public void visit(LocalVariableTable obj) {
if (ENABLE_LOCALS) {
- if (staticMethod)
+ if (staticMethod) {
return;
+ }
LocalVariable[] vars = obj.getLocalVariableTable();
// System.out.println("Num params = " + numParms);
for (LocalVariable var : vars) {
- if (var.getIndex() < numParms)
+ if (var.getIndex() < numParms) {
continue;
+ }
String varName = var.getName();
- if (varName.equals("serialVersionUID"))
+ if ("serialVersionUID".equals(varName)) {
continue;
+ }
Field f = classFields.get(varName);
// System.out.println("Checking " + varName);
// System.out.println(" got " + f);
@@ -187,9 +200,10 @@ public class FindMaskedFields extends BytecodeScanningDetector {
// that is.
if (f != null) {
FieldAnnotation fa = FieldAnnotation.fromBCELField(getDottedClassName(), f);
- if (true || var.getStartPC() > 0)
+ if (true || var.getStartPC() > 0) {
bugReporter.reportBug(new BugInstance(this, "MF_METHOD_MASKS_FIELD", LOW_PRIORITY)
- .addClassAndMethod(this).addField(fa).addSourceLine(this, var.getStartPC() - 1));
+ .addClassAndMethod(this).addField(fa).addSourceLine(this, var.getStartPC() - 1));
+ }
}
}
}
@@ -205,30 +219,37 @@ public class FindMaskedFields extends BytecodeScanningDetector {
int score2 = 0;
int priority = bug.getPriority();
if (unreadFields.classesScanned.contains(rb.maskedField.getClassName())) {
- if (unreadFields.getReadFields().contains(rb.maskedField))
+ if (unreadFields.getReadFields().contains(rb.maskedField)) {
score1++;
- if (unreadFields.getWrittenFields().contains(rb.maskedField))
+ }
+ if (unreadFields.getWrittenFields().contains(rb.maskedField)) {
score1++;
- if (unreadFields.isWrittenOutsideOfInitialization(rb.maskedField))
+ }
+ if (unreadFields.isWrittenOutsideOfInitialization(rb.maskedField)) {
score1++;
- } else
+ }
+ } else {
score1 += 2;
- if (unreadFields.getReadFields().contains(rb.maskingField))
+ }
+ if (unreadFields.getReadFields().contains(rb.maskingField)) {
score2++;
- if (unreadFields.getWrittenFields().contains(rb.maskingField))
+ }
+ if (unreadFields.getWrittenFields().contains(rb.maskingField)) {
score2++;
- if (unreadFields.isWrittenOutsideOfInitialization(rb.maskingField))
+ }
+ if (unreadFields.isWrittenOutsideOfInitialization(rb.maskingField)) {
score2++;
+ }
int score = score1 + score2;
- if (score1 == 0 || score2 == 0)
+ if (score1 == 0 || score2 == 0) {
bug.setPriority(priority + 1);
- else if (score >= 5)
+ } else if (score >= 5) {
bug.setPriority(priority - 1);
- else if (score < 3)
+ } else if (score < 3) {
bug.setPriority(priority + 1);
+ }
bugReporter.reportBug(bug);
}
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindMismatchedWaitOrNotify.java b/src/java/edu/umd/cs/findbugs/detect/FindMismatchedWaitOrNotify.java
index ad335cb..3c9e8f2 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindMismatchedWaitOrNotify.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindMismatchedWaitOrNotify.java
@@ -69,22 +69,26 @@ public final class FindMismatchedWaitOrNotify implements Detector, StatelessDete
}
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass jclass = classContext.getJavaClass();
Method[] methodList = jclass.getMethods();
for (Method method : methodList) {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
continue;
+ }
// Don't bother analyzing the method unless there is both locking
// and a method call.
BitSet bytecodeSet = classContext.getBytecodeSet(method);
- if (bytecodeSet == null)
+ if (bytecodeSet == null) {
continue;
- if (!(bytecodeSet.get(Constants.MONITORENTER) && bytecodeSet.get(Constants.INVOKEVIRTUAL)))
+ }
+ if (!(bytecodeSet.get(Constants.MONITORENTER) && bytecodeSet.get(Constants.INVOKEVIRTUAL))) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -99,8 +103,9 @@ public final class FindMismatchedWaitOrNotify implements Detector, StatelessDete
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
ConstantPoolGen cpg = methodGen.getConstantPool();
CFG cfg = classContext.getCFG(method);
ValueNumberDataflow vnaDataflow = classContext.getValueNumberDataflow(method);
@@ -112,8 +117,9 @@ public final class FindMismatchedWaitOrNotify implements Detector, StatelessDete
InstructionHandle handle = location.getHandle();
Instruction ins = handle.getInstruction();
- if (!(ins instanceof INVOKEVIRTUAL))
+ if (!(ins instanceof INVOKEVIRTUAL)) {
continue;
+ }
INVOKEVIRTUAL inv = (INVOKEVIRTUAL) ins;
String methodName = inv.getName(cpg);
@@ -121,15 +127,18 @@ public final class FindMismatchedWaitOrNotify implements Detector, StatelessDete
if (Hierarchy.isMonitorWait(methodName, methodSig) || Hierarchy.isMonitorNotify(methodName, methodSig)) {
int numConsumed = inv.consumeStack(cpg);
- if (numConsumed == Constants.UNPREDICTABLE)
+ if (numConsumed == Constants.UNPREDICTABLE) {
throw new DataflowAnalysisException("Unpredictable stack consumption", methodGen, handle);
+ }
ValueNumberFrame frame = vnaDataflow.getFactAtLocation(location);
- if (!frame.isValid())
+ if (!frame.isValid()) {
// Probably dead code
continue;
- if (frame.getStackDepth() - numConsumed < 0)
+ }
+ if (frame.getStackDepth() - numConsumed < 0) {
throw new DataflowAnalysisException("Stack underflow", methodGen, handle);
+ }
ValueNumber ref = frame.getValue(frame.getNumSlots() - numConsumed);
LockSet lockSet = dataflow.getFactAtLocation(location);
int lockCount = lockSet.getLockCount(ref.getNumber());
@@ -137,15 +146,16 @@ public final class FindMismatchedWaitOrNotify implements Detector, StatelessDete
if (lockCount == 0) {
Collection<ValueNumber> lockedValueNumbers = lockSet.getLockedValueNumbers(frame);
boolean foundMatch = false;
- for (ValueNumber v : lockedValueNumbers)
+ for (ValueNumber v : lockedValueNumbers) {
if (frame.veryFuzzyMatch(ref, v)) {
foundMatch = true;
break;
}
+ }
if (!foundMatch) {
- String type = methodName.equals("wait") ? "MWN_MISMATCHED_WAIT" : "MWN_MISMATCHED_NOTIFY";
+ String type = "wait".equals(methodName) ? "MWN_MISMATCHED_WAIT" : "MWN_MISMATCHED_NOTIFY";
String sourceFile = classContext.getJavaClass().getSourceFileName();
// Report as medium priority only if the method is
// public.
@@ -163,8 +173,8 @@ public final class FindMismatchedWaitOrNotify implements Detector, StatelessDete
bugAccumulator.reportAccumulatedBugs();
}
+ @Override
public void report() {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindNakedNotify.java b/src/java/edu/umd/cs/findbugs/detect/FindNakedNotify.java
index 019e1bd..c06c04f 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindNakedNotify.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindNakedNotify.java
@@ -37,7 +37,7 @@ import edu.umd.cs.findbugs.StatelessDetector;
public class FindNakedNotify extends BytecodeScanningDetector implements StatelessDetector {
int stage = 0;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
boolean synchronizedMethod;
@@ -57,29 +57,32 @@ public class FindNakedNotify extends BytecodeScanningDetector implements Statele
public void visit(Code obj) {
stage = synchronizedMethod ? 1 : 0;
super.visit(obj);
- if (synchronizedMethod && stage == 4)
+ if (synchronizedMethod && stage == 4) {
bugReporter.reportBug(new BugInstance(this, "NN_NAKED_NOTIFY", NORMAL_PRIORITY).addClassAndMethod(this)
.addSourceLine(this, notifyPC));
+ }
}
@Override
public void sawOpcode(int seen) {
switch (stage) {
case 0:
- if (seen == MONITORENTER)
+ if (seen == MONITORENTER) {
stage = 1;
+ }
break;
case 1:
stage = 2;
break;
case 2:
if (seen == INVOKEVIRTUAL
- && (getNameConstantOperand().equals("notify") || getNameConstantOperand().equals("notifyAll"))
- && getSigConstantOperand().equals("()V")) {
+ && ("notify".equals(getNameConstantOperand()) || "notifyAll".equals(getNameConstantOperand()))
+ && "()V".equals(getSigConstantOperand())) {
stage = 3;
notifyPC = getPC();
- } else
+ } else {
stage = 0;
+ }
break;
case 3:
stage = 4;
@@ -89,8 +92,9 @@ public class FindNakedNotify extends BytecodeScanningDetector implements Statele
bugReporter.reportBug(new BugInstance(this, "NN_NAKED_NOTIFY", NORMAL_PRIORITY).addClassAndMethod(this)
.addSourceLine(this, notifyPC));
stage = 5;
- } else
+ } else {
stage = 0;
+ }
break;
case 5:
break;
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindNoSideEffectMethods.java b/src/java/edu/umd/cs/findbugs/detect/FindNoSideEffectMethods.java
new file mode 100644
index 0000000..eb757bf
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/detect/FindNoSideEffectMethods.java
@@ -0,0 +1,1075 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.detect;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import org.apache.bcel.classfile.Code;
+import org.apache.bcel.classfile.CodeException;
+import org.apache.bcel.classfile.Field;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.Type;
+
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.NonReportingDetector;
+import edu.umd.cs.findbugs.OpcodeStack;
+import edu.umd.cs.findbugs.OpcodeStack.Item;
+import edu.umd.cs.findbugs.ba.AnalysisContext;
+import edu.umd.cs.findbugs.ba.Hierarchy2;
+import edu.umd.cs.findbugs.ba.SignatureParser;
+import edu.umd.cs.findbugs.ba.XClass;
+import edu.umd.cs.findbugs.ba.XField;
+import edu.umd.cs.findbugs.ba.XMethod;
+import edu.umd.cs.findbugs.ba.ch.Subtypes2;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
+import edu.umd.cs.findbugs.classfile.ClassDescriptor;
+import edu.umd.cs.findbugs.classfile.FieldDescriptor;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+import edu.umd.cs.findbugs.util.ClassName;
+
+/**
+ * @author Tagir Valeev
+ */
+public class FindNoSideEffectMethods extends OpcodeStackDetector implements NonReportingDetector {
+ private static final MethodDescriptor GET_CLASS = new MethodDescriptor("java/lang/Object", "getClass", "()Ljava/lang/Class;");
+ private static final MethodDescriptor ARRAY_COPY = new MethodDescriptor("java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", true);
+ private static final MethodDescriptor HASH_CODE = new MethodDescriptor("java/lang/Object", "hashCode", "()I");
+ private static final MethodDescriptor CLASS_GET_NAME = new MethodDescriptor("java/lang/Class", "getName", "()Ljava/lang/String;");
+ // Stub method to generalize array store
+ private static final MethodDescriptor ARRAY_STORE_STUB_METHOD = new MethodDescriptor("java/lang/Array", "set", "(ILjava/lang/Object;)V");
+ // Stub method to generalize field store
+ private static final MethodDescriptor FIELD_STORE_STUB_METHOD = new MethodDescriptor("java/lang/Object", "putField", "(Ljava/lang/Object;)V");
+
+ // Fictional method call targets
+ private static final FieldDescriptor TARGET_THIS = new FieldDescriptor("java/lang/Stub", "this", "V", false);
+ private static final FieldDescriptor TARGET_NEW = new FieldDescriptor("java/lang/Stub", "new", "V", false);
+ private static final FieldDescriptor TARGET_OTHER = new FieldDescriptor("java/lang/Stub", "other", "V", false);
+
+ private static final Set<String> NUMBER_CLASSES = new HashSet<>(Arrays.asList("java/lang/Integer", "java/lang/Long",
+ "java/lang/Double", "java/lang/Float", "java/lang/Byte", "java/lang/Short", "java/math/BigInteger",
+ "java/math/BigDecimal"));
+
+ private static final Set<String> ALLOWED_EXCEPTIONS = new HashSet<>(Arrays.asList("java.lang.InternalError",
+ "java.lang.ArrayIndexOutOfBoundsException", "java.lang.StringIndexOutOfBoundsException",
+ "java.lang.IndexOutOfBoundsException"));
+
+ private static final Set<String> NO_SIDE_EFFECT_COLLECTION_METHODS = new HashSet<>(Arrays.asList("contains", "containsKey",
+ "containsValue", "get", "indexOf", "lastIndexOf", "iterator", "listIterator", "isEmpty", "size", "getOrDefault",
+ "subList", "keys", "elements", "keySet", "entrySet", "values", "stream", "firstKey", "lastKey", "headMap", "tailMap",
+ "subMap", "peek", "mappingCount"));
+
+ private static final Set<String> OBJECT_ONLY_CLASSES = new HashSet<>(Arrays.asList("java/lang/StringBuffer",
+ "java/lang/StringBuilder", "java/util/regex/Matcher", "java/io/ByteArrayOutputStream",
+ "java/util/concurrent/atomic/AtomicBoolean", "java/util/concurrent/atomic/AtomicInteger",
+ "java/util/concurrent/atomic/AtomicLong", "java/awt/Point"));
+
+ // Usual implementation of stub methods which are expected to be more complex in derived classes
+ private static final byte[][] STUB_METHODS = new byte[][] {
+ {(byte) RETURN},
+ {ICONST_0, (byte) IRETURN},
+ {ICONST_1, (byte) IRETURN},
+ {ICONST_M1, (byte) IRETURN},
+ {LCONST_0, (byte) LRETURN},
+ {FCONST_0, (byte) FRETURN},
+ {DCONST_0, (byte) DRETURN},
+ {ACONST_NULL, (byte) ARETURN},
+ {ALOAD_0, (byte) ARETURN},
+ {ALOAD_1, (byte) ARETURN},
+ };
+
+ /**
+ * Known methods which change only this object
+ */
+ private static final Set<MethodDescriptor> OBJECT_ONLY_METHODS = new HashSet<>(Arrays.asList(
+ ARRAY_STORE_STUB_METHOD, FIELD_STORE_STUB_METHOD,
+ new MethodDescriptor("java/util/Iterator", "next", "()Ljava/lang/Object;"),
+ new MethodDescriptor("java/util/Enumeration", "nextElement", "()Ljava/lang/Object;"),
+ new MethodDescriptor("java/lang/Throwable", "fillInStackTrace", "()Ljava/lang/Throwable;")
+ ));
+
+ /**
+ * Known methods which have no side-effect
+ */
+ private static final Set<MethodDescriptor> NO_SIDE_EFFECT_METHODS = new HashSet<>(Arrays.asList(
+ GET_CLASS, CLASS_GET_NAME, HASH_CODE,
+ new MethodDescriptor("java/lang/reflect/Array", "newInstance", "(Ljava/lang/Class;I)Ljava/lang/Object;"),
+ new MethodDescriptor("java/lang/Class", "getResource", "(Ljava/lang/String;)Ljava/net/URL;"),
+ new MethodDescriptor("java/lang/Class", "getSimpleName", "()Ljava/lang/String;"),
+ new MethodDescriptor("java/lang/Class", "getMethods", "()[Ljava/lang/reflect/Method;"),
+ new MethodDescriptor("java/lang/Class", "getSuperclass", "()Ljava/lang/Class;"),
+ new MethodDescriptor("java/lang/Runtime", "availableProcessors", "()I"),
+ new MethodDescriptor("java/lang/Runtime", "maxMemory", "()J"),
+ new MethodDescriptor("java/lang/Runtime", "totalMemory", "()J"),
+ new MethodDescriptor("java/lang/Iterable", "iterator", "()Ljava/util/Iterator;"),
+ new MethodDescriptor("java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I"),
+ new MethodDescriptor("java/util/Arrays", "deepEquals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z", true),
+ new MethodDescriptor("java/util/Enumeration", "hasMoreElements", "()Z"),
+ new MethodDescriptor("java/util/Iterator", "hasNext", "()Z"),
+ new MethodDescriptor("java/util/Comparator", "compare", "(Ljava/lang/Object;Ljava/lang/Object;)I"),
+ new MethodDescriptor("java/util/logging/LogManager", "getLogger", "(Ljava/lang/String;)Ljava/util/logging/Logger;", true),
+ new MethodDescriptor("org/apache/log4j/LogManager", "getLogger", "(Ljava/lang/String;)Lorg/apache/log4j/Logger;", true)
+ ));
+
+ private static final Set<MethodDescriptor> NEW_OBJECT_RETURNING_METHODS = new HashSet<>(Arrays.asList(
+ new MethodDescriptor("java/util/Vector", "elements", "()Ljava/util/Enumeration;"),
+ new MethodDescriptor("java/util/Hashtable", "elements", "()Ljava/util/Enumeration;"),
+ new MethodDescriptor("java/util/Hashtable", "keys", "()Ljava/util/Enumeration;"),
+ new MethodDescriptor("java/lang/reflect/Array", "newInstance", "(Ljava/lang/Class;I)Ljava/lang/Object;")
+ ));
+
+ private static enum SideEffectStatus {
+ SIDE_EFFECT, UNSURE_OBJECT_ONLY, OBJECT_ONLY, UNSURE, NO_SIDE_EFFECT;
+
+ boolean unsure() {
+ return this == UNSURE || this == UNSURE_OBJECT_ONLY;
+ }
+
+ SideEffectStatus toObjectOnly() {
+ switch(this) {
+ case UNSURE:
+ return UNSURE_OBJECT_ONLY;
+ case NO_SIDE_EFFECT:
+ return OBJECT_ONLY;
+ default:
+ return this;
+ }
+ }
+
+ SideEffectStatus toUnsure() {
+ switch(this) {
+ case OBJECT_ONLY:
+ return UNSURE_OBJECT_ONLY;
+ case NO_SIDE_EFFECT:
+ return UNSURE;
+ default:
+ return this;
+ }
+ }
+
+ SideEffectStatus toSure() {
+ switch(this) {
+ case UNSURE_OBJECT_ONLY:
+ return OBJECT_ONLY;
+ case UNSURE:
+ return NO_SIDE_EFFECT;
+ default:
+ return this;
+ }
+ }
+ }
+
+ private static class MethodCall {
+ private final MethodDescriptor method;
+ private final FieldDescriptor target;
+
+ public MethodCall(MethodDescriptor method, FieldDescriptor target) {
+ this.method = method;
+ this.target = target;
+ }
+
+ public MethodDescriptor getMethod() {
+ return method;
+ }
+
+ public FieldDescriptor getTarget() {
+ return target;
+ }
+
+ @Override
+ public int hashCode() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ MethodCall other = (MethodCall) obj;
+ if (!method.equals(other.method)) {
+ return false;
+ }
+ if (!target.equals(other.target)) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Public status of the method in NSE database
+ * TODO: implement CHECK
+ */
+ public static enum MethodSideEffectStatus {
+ NSE, // Non-void method has no side effect
+ NSE_EX, // No side effect method which result value might be ignored for some reason
+ CHECK, // (unimplemented yet) No side effect method which just checks the arguments, throws exceptions and returns one of arguments (or void) like assert or precondition
+ USELESS, // Void method which seems to be useless
+ SE_CLINIT, // Method has no side effect, but it's a constructor or static method of the class having side effect
+ OBJ, // Non-static method which changes only its object
+ SE // Method has side effect or side-effect status for the method is unknown
+ }
+
+ public static class NoSideEffectMethodsDatabase {
+ private final Map<MethodDescriptor, MethodSideEffectStatus> map = new HashMap<>();
+
+ void add(MethodDescriptor m, MethodSideEffectStatus s) {
+ map.put(m, s);
+ }
+
+ public @Nonnull MethodSideEffectStatus status(MethodDescriptor m) {
+ MethodSideEffectStatus s = map.get(m);
+ return s == null ? MethodSideEffectStatus.SE : s;
+ }
+
+ /**
+ * @param m method to check
+ * @param statuses allowed statuses
+ * @return true if method status is one of the statuses
+ */
+ public boolean is(MethodDescriptor m, MethodSideEffectStatus... statuses) {
+ MethodSideEffectStatus s = status(m);
+ for(MethodSideEffectStatus status : statuses) {
+ if(s == status) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasNoSideEffect(MethodDescriptor m) {
+ return status(m) == MethodSideEffectStatus.NSE;
+ }
+
+ public boolean useless(MethodDescriptor m) {
+ return status(m) == MethodSideEffectStatus.USELESS;
+ }
+
+ public boolean excluded(MethodDescriptor m) {
+ return is(m, MethodSideEffectStatus.NSE_EX, MethodSideEffectStatus.SE_CLINIT);
+ }
+ }
+
+ static class EarlyExitException extends RuntimeException {
+ }
+
+ private final Map<MethodDescriptor, SideEffectStatus> statusMap = new HashMap<>();
+ private final Map<MethodDescriptor, List<MethodCall>> callGraph = new HashMap<>();
+ private final Set<MethodDescriptor> getStaticMethods = new HashSet<>();
+ private final Set<MethodDescriptor> uselessVoidCandidates = new HashSet<>();
+
+ private SideEffectStatus status;
+ private ArrayList<MethodCall> calledMethods;
+ private Set<ClassDescriptor> subtypes;
+ private Set<Integer> finallyTargets;
+ private Set<Integer> finallyExceptionRegisters;
+
+ private boolean constructor;
+ private boolean uselessVoidCandidate;
+ private boolean classInit;
+
+ private Set<FieldDescriptor> allowedFields;
+ private Set<MethodDescriptor> fieldsModifyingMethods;
+
+ private final NoSideEffectMethodsDatabase noSideEffectMethods = new NoSideEffectMethodsDatabase();
+
+ public FindNoSideEffectMethods(BugReporter bugReporter) {
+ Global.getAnalysisCache().eagerlyPutDatabase(NoSideEffectMethodsDatabase.class, noSideEffectMethods);
+ }
+
+ @Override
+ public void visit(JavaClass obj) {
+ super.visit(obj);
+ allowedFields = new HashSet<>();
+ fieldsModifyingMethods = new HashSet<>();
+ subtypes = null;
+ if (!obj.isFinal() && !obj.isEnum()) {
+ try {
+ Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
+ subtypes = new HashSet<>(subtypes2.getSubtypes(getClassDescriptor()));
+ subtypes.remove(getClassDescriptor());
+ } catch (ClassNotFoundException e) {
+ }
+ }
+ }
+
+ @Override
+ public void visit(Method method) {
+ constructor = method.getName().equals("<init>");
+ classInit = method.getName().equals("<clinit>");
+ calledMethods = new ArrayList<>();
+ status = SideEffectStatus.NO_SIDE_EFFECT;
+ if (hasNoSideEffect(getMethodDescriptor())) {
+ handleStatus();
+ return;
+ }
+ if(isObjectOnlyMethod(getMethodDescriptor())) {
+ status = SideEffectStatus.OBJECT_ONLY;
+ }
+ if (method.isNative() || changedArg(getMethodDescriptor()) != -1) {
+ status = SideEffectStatus.SIDE_EFFECT;
+ handleStatus();
+ return;
+ }
+ boolean sawImplementation = false;
+ if (classInit) {
+ superClinitCall();
+ }
+ if (!method.isStatic() && !method.isPrivate() && !method.isFinal() && !constructor && subtypes != null) {
+ for (ClassDescriptor subtype : subtypes) {
+ try {
+ XClass xClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, subtype);
+ XMethod matchingMethod = xClass.findMatchingMethod(getMethodDescriptor());
+ if (matchingMethod != null) {
+ sawImplementation = true;
+ sawCall(new MethodCall(matchingMethod.getMethodDescriptor(), TARGET_THIS), false);
+ }
+ } catch (CheckedAnalysisException e) {
+ }
+ }
+ }
+ if (method.isAbstract() || method.isInterface()) {
+ if (!sawImplementation
+ || getClassName().endsWith("Visitor") || getClassName().endsWith("Listener")
+ || getClassName().startsWith("java/sql/")
+ || (getClassName().equals("java/util/concurrent/Future") && !method.getName().startsWith("is"))
+ || (getClassName().equals("java/lang/Process") && method.getName().equals("exitValue"))) {
+ status = SideEffectStatus.SIDE_EFFECT;
+ } else if(isObjectOnlyMethod(getMethodDescriptor())) {
+ status = SideEffectStatus.OBJECT_ONLY;
+ } else {
+ String[] thrownExceptions = getXMethod().getThrownExceptions();
+ if(thrownExceptions != null && thrownExceptions.length > 0) {
+ status = SideEffectStatus.SIDE_EFFECT;
+ }
+ }
+ }
+ if ((status == SideEffectStatus.SIDE_EFFECT || status == SideEffectStatus.OBJECT_ONLY) || method.isAbstract()
+ || method.isInterface() || method.isNative()) {
+ handleStatus();
+ }
+ }
+
+ @Override
+ public void visit(Field obj) {
+ XField xField = getXField();
+ if(!xField.isStatic() && (xField.isPrivate() || xField.isFinal()) && xField.isReferenceType()) {
+ allowedFields.add(xField.getFieldDescriptor());
+ }
+ }
+
+ @Override
+ public void visitAfter(JavaClass obj) {
+ for(MethodDescriptor method : fieldsModifyingMethods) {
+ List<MethodCall> calls = callGraph.get(method);
+ SideEffectStatus prevStatus = statusMap.get(method);
+ status = prevStatus.toSure();
+ calledMethods = new ArrayList<>();
+ for(MethodCall methodCall : calls) {
+ FieldDescriptor target = methodCall.getTarget();
+ if(target != TARGET_NEW && target != TARGET_OTHER && target != TARGET_THIS) {
+ if(allowedFields.contains(target)) {
+ methodCall = new MethodCall(methodCall.getMethod(), TARGET_THIS);
+ } else {
+ methodCall = new MethodCall(methodCall.getMethod(), TARGET_OTHER);
+ }
+ }
+ sawCall(methodCall, false);
+ if(status == SideEffectStatus.SIDE_EFFECT) {
+ break;
+ }
+ }
+ if (status != prevStatus) {
+ statusMap.put(method, status);
+ }
+ if(status.unsure()) {
+ calledMethods.trimToSize();
+ callGraph.put(method, calledMethods);
+ } else {
+ callGraph.remove(method);
+ }
+ }
+ MethodDescriptor clinit = new MethodDescriptor(getClassName(), "<clinit>", "()V", true);
+ if(!statusMap.containsKey(clinit)) {
+ status = SideEffectStatus.NO_SIDE_EFFECT;
+ calledMethods = new ArrayList<>();
+ superClinitCall();
+ statusMap.put(clinit, status);
+ if(status == SideEffectStatus.UNSURE || status == SideEffectStatus.UNSURE_OBJECT_ONLY) {
+ calledMethods.trimToSize();
+ callGraph.put(clinit, calledMethods);
+ }
+ }
+ }
+
+ private void superClinitCall() {
+ ClassDescriptor superclassDescriptor = getXClass().getSuperclassDescriptor();
+ if(superclassDescriptor != null && !superclassDescriptor.getClassName().equals("java/lang/Object")) {
+ sawCall(new MethodCall(new MethodDescriptor(superclassDescriptor.getClassName(), "<clinit>", "()V", true), TARGET_THIS), false);
+ }
+ }
+
+ private void handleStatus() {
+ statusMap.put(getMethodDescriptor(), status);
+ if(status == SideEffectStatus.UNSURE || status == SideEffectStatus.UNSURE_OBJECT_ONLY) {
+ calledMethods.trimToSize();
+ callGraph.put(getMethodDescriptor(), calledMethods);
+ } else {
+ fieldsModifyingMethods.remove(getMethodDescriptor());
+ }
+ }
+
+ @Override
+ public void visit(Code obj) {
+ uselessVoidCandidate = !classInit && !constructor && !getXMethod().isSynthetic() && Type.getReturnType(getMethodSig()) == Type.VOID;
+ byte[] code = obj.getCode();
+ if(code.length == 4 && (code[0] & 0xFF) == GETSTATIC && (code[3] & 0xFF) == ARETURN) {
+ getStaticMethods.add(getMethodDescriptor());
+ handleStatus();
+ return;
+ }
+
+ if (code.length <= 2 && !getXMethod().isStatic() && (getXMethod().isPublic() || getXMethod().isProtected())
+ && !getXMethod().isFinal() && (getXClass().isPublic() || getXClass().isProtected())) {
+ for(byte[] stubMethod : STUB_METHODS) {
+ if (Arrays.equals(stubMethod, code)
+ && (getClassName().endsWith("Visitor") || getClassName().endsWith("Listener") || !hasOtherImplementations(getXMethod()))) {
+ // stub method which can be extended: assume it can be extended with possible side-effect
+ status = SideEffectStatus.SIDE_EFFECT;
+ handleStatus();
+ return;
+ }
+ }
+ }
+ if (statusMap.containsKey(getMethodDescriptor())) {
+ return;
+ }
+ finallyTargets = new HashSet<>();
+ for(CodeException ex : getCode().getExceptionTable()) {
+ if(ex.getCatchType() == 0) {
+ finallyTargets.add(ex.getHandlerPC());
+ }
+ }
+ finallyExceptionRegisters = new HashSet<>();
+ try {
+ super.visit(obj);
+ } catch (EarlyExitException e) {
+ // Ignore
+ }
+ if (uselessVoidCandidate && code.length > 1
+ && (status == SideEffectStatus.UNSURE || status == SideEffectStatus.NO_SIDE_EFFECT)) {
+ uselessVoidCandidates.add(getMethodDescriptor());
+ }
+ handleStatus();
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if (!allowedFields.isEmpty() && seen == PUTFIELD) {
+ Item objItem = getStack().getStackItem(1);
+ if (objItem.getRegisterNumber() == 0) {
+ if (allowedFields.contains(getFieldDescriptorOperand())) {
+ Item valueItem = getStack().getStackItem(0);
+ if (!isNew(valueItem) && !valueItem.isNull()) {
+ allowedFields.remove(getFieldDescriptorOperand());
+ }
+ }
+ }
+ }
+ if (status == SideEffectStatus.SIDE_EFFECT && allowedFields.isEmpty()) {
+ // Nothing to do: skip the rest of the method
+ throw new EarlyExitException();
+ }
+ if (status == SideEffectStatus.SIDE_EFFECT) {
+ return;
+ }
+ switch (seen) {
+ case ASTORE:
+ case ASTORE_0:
+ case ASTORE_1:
+ case ASTORE_2:
+ case ASTORE_3:
+ if(finallyTargets.contains(getPC())) {
+ finallyExceptionRegisters.add(getRegisterOperand());
+ }
+ break;
+ case ATHROW: {
+ Item exceptionItem = getStack().getStackItem(0);
+ if(!finallyExceptionRegisters.remove(exceptionItem.getRegisterNumber())) {
+ uselessVoidCandidate = false;
+ try {
+ JavaClass javaClass = exceptionItem.getJavaClass();
+ if (javaClass != null && ALLOWED_EXCEPTIONS.contains(javaClass.getClassName())) {
+ break;
+ }
+ } catch (ClassNotFoundException e) {
+ }
+ status = SideEffectStatus.SIDE_EFFECT;
+ }
+ break;
+ }
+ case PUTSTATIC:
+ if(classInit) {
+ if(getClassConstantOperand().equals(getClassName())) {
+ break;
+ }
+ }
+ status = SideEffectStatus.SIDE_EFFECT;
+ break;
+ case INVOKEDYNAMIC:
+ status = SideEffectStatus.SIDE_EFFECT;
+ break;
+ case PUTFIELD:
+ sawCall(getMethodCall(FIELD_STORE_STUB_METHOD), false);
+ break;
+ case AASTORE:
+ case DASTORE:
+ case CASTORE:
+ case BASTORE:
+ case IASTORE:
+ case LASTORE:
+ case FASTORE:
+ case SASTORE:
+ sawCall(getMethodCall(ARRAY_STORE_STUB_METHOD), false);
+ break;
+ case INVOKESTATIC:
+ if (changesOnlyNewObjects(getMethodDescriptorOperand())) {
+ break;
+ }
+ sawCall(new MethodCall(getMethodDescriptorOperand(), TARGET_OTHER), false);
+ break;
+ case INVOKESPECIAL:
+ case INVOKEINTERFACE:
+ case INVOKEVIRTUAL: {
+ XMethod xMethodOperand = getXMethodOperand();
+ MethodDescriptor methodDescriptorOperand = xMethodOperand == null ? getMethodDescriptorOperand() : xMethodOperand
+ .getMethodDescriptor();
+ if (changesOnlyNewObjects(getMethodDescriptorOperand())) {
+ break;
+ }
+ MethodCall methodCall = getMethodCall(methodDescriptorOperand);
+ sawCall(methodCall, false);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ private MethodCall getMethodCall(MethodDescriptor methodDescriptorOperand) {
+ Item objItem = getStack().getStackItem(getNumberArguments(methodDescriptorOperand.getSignature()));
+ if (isNew(objItem)) {
+ return new MethodCall(methodDescriptorOperand, TARGET_NEW);
+ }
+ if (objItem.getRegisterNumber() == 0 && !getMethod().isStatic()) {
+ return new MethodCall(methodDescriptorOperand, constructor ? TARGET_NEW : TARGET_THIS);
+ }
+ XField xField = objItem.getXField();
+ if (xField != null) {
+ if (classInit && xField.isStatic() && xField.getClassDescriptor().getClassName().equals(getClassName())) {
+ return new MethodCall(methodDescriptorOperand, TARGET_NEW);
+ }
+ if (!getMethodDescriptor().isStatic() && objItem.getFieldLoadedFromRegister() == 0
+ && allowedFields.contains(xField.getFieldDescriptor())) {
+ fieldsModifyingMethods.add(getMethodDescriptor());
+ return new MethodCall(methodDescriptorOperand, xField.getFieldDescriptor());
+ }
+ }
+ return new MethodCall(methodDescriptorOperand, TARGET_OTHER);
+ }
+
+ private void sawCall(MethodCall methodCall, boolean finalPass) {
+ if (status == SideEffectStatus.SIDE_EFFECT) {
+ return;
+ }
+ MethodDescriptor methodDescriptor = methodCall.getMethod();
+ if (hasNoSideEffect(methodDescriptor)) {
+ sawNoSideEffectCall(methodDescriptor);
+ return;
+ }
+ FieldDescriptor target = methodCall.getTarget();
+ SideEffectStatus calledStatus = isObjectOnlyMethod(methodDescriptor) ? SideEffectStatus.OBJECT_ONLY : statusMap
+ .get(methodDescriptor);
+ if (calledStatus == null) {
+ calledStatus = finalPass ? hasNoSideEffectUnknown(methodDescriptor) ? SideEffectStatus.NO_SIDE_EFFECT : SideEffectStatus.SIDE_EFFECT
+ : SideEffectStatus.UNSURE;
+ }
+ switch(calledStatus) {
+ case NO_SIDE_EFFECT:
+ sawNoSideEffectCall(methodDescriptor);
+ return;
+ case SIDE_EFFECT:
+ status = SideEffectStatus.SIDE_EFFECT;
+ return;
+ case OBJECT_ONLY:
+ if(target == TARGET_THIS) {
+ status = status.toObjectOnly();
+ } else if(target == TARGET_OTHER) {
+ status = SideEffectStatus.SIDE_EFFECT;
+ } else if(target != TARGET_NEW) {
+ status = status.toObjectOnly();
+ sawUnsureCall(methodCall);
+ }
+ return;
+ case UNSURE_OBJECT_ONLY:
+ if(target == TARGET_NEW) {
+ sawUnsureCall(methodCall);
+ } else if(target == TARGET_OTHER) {
+ status = SideEffectStatus.SIDE_EFFECT;
+ } else {
+ status = status.toObjectOnly();
+ sawUnsureCall(methodCall);
+ }
+ return;
+ case UNSURE:
+ sawUnsureCall(methodCall);
+ return;
+ }
+ }
+
+ /**
+ * @param methodDescriptor
+ */
+ private void sawNoSideEffectCall(MethodDescriptor methodDescriptor) {
+ if(uselessVoidCandidate && Type.getReturnType(methodDescriptor.getSignature()) == Type.VOID
+ && !methodDescriptor.getName().equals("<init>")) {
+ /* To reduce false-positives we do not mark method as useless void if it calls
+ * another useless void method. If that another method also in the scope of our project
+ * then we will report it instead. If there's a cycle of no-side-effect calls, then
+ * it's probably some delegation pattern and methods can be extended in future/derived
+ * projects to do something useful.
+ */
+ uselessVoidCandidate = false;
+ }
+ }
+
+ private void sawUnsureCall(MethodCall methodCall) {
+ calledMethods.add(methodCall);
+ status = status.toUnsure();
+ }
+
+ /**
+ * @param item stack item to check
+ * @return true if this stack item is known to be newly created
+ */
+ private static boolean isNew(OpcodeStack.Item item) {
+ if(item.isNewlyAllocated()) {
+ return true;
+ }
+ XMethod returnValueOf = item.getReturnValueOf();
+ if(returnValueOf == null) {
+ return false;
+ }
+ if("iterator".equals(returnValueOf.getName())
+ && "()Ljava/util/Iterator;".equals(returnValueOf.getSignature())
+ && Subtypes2.instanceOf(returnValueOf.getClassName(), "java.lang.Iterable")) {
+ return true;
+ }
+ if(returnValueOf.getClassName().startsWith("[") && returnValueOf.getName().equals("clone")) {
+ return true;
+ }
+ if(NEW_OBJECT_RETURNING_METHODS.contains(returnValueOf.getMethodDescriptor())) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean changesOnlyNewObjects(MethodDescriptor methodDescriptor) {
+ int arg = changedArg(methodDescriptor);
+ if(arg == -1) {
+ return false;
+ }
+ int nArgs = getNumberArguments(methodDescriptor.getSignature());
+ if(!isNew(getStack().getStackItem(nArgs-arg-1))) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @param m method to check
+ * @return array of argument numbers (0-based) which this method writes into or null if we don't know anything about this method
+ */
+ private static int changedArg(MethodDescriptor m) {
+ if(m.equals(ARRAY_COPY)) {
+ return 2;
+ }
+ if(m.getName().equals("toArray") && m.getSignature().equals("([Ljava/lang/Object;)[Ljava/lang/Object;")
+ && Subtypes2.instanceOf(m.getClassDescriptor(), "java.util.Collection")) {
+ return 0;
+ }
+ if ((m.getName().equals("sort") || m.getName().equals("fill") || m.getName().equals("reverse") || m.getName().equals(
+ "shuffle"))
+ && (m.getSlashedClassName().equals("java/util/Arrays") || m.getSlashedClassName().equals("java/util/Collections"))) {
+ return 0;
+ }
+ return -1;
+ }
+
+ /**
+ * @param m method to check
+ * @return true if given method is known to have no side effects
+ */
+ private static boolean hasNoSideEffect(MethodDescriptor m) {
+ String className = m.getSlashedClassName();
+ if("java/lang/String".equals(className)) {
+ return !(m.getName().equals("getChars") || (m.getName().equals("getBytes") && m.getSignature().equals("(II[BI)V")));
+ }
+ if("java/lang/Math".equals(className)) {
+ return !m.getName().equals("random");
+ }
+ if("java/lang/Throwable".equals(className)) {
+ return m.getName().startsWith("get");
+ }
+ if("java/lang/Character".equals(className)) {
+ return !m.getName().equals("toChars");
+ }
+ if("java/lang/Class".equals(className) && m.getName().startsWith("is")) {
+ return true;
+ }
+ if("java/awt/Color".equals(className) && m.getName().equals("<init>")) {
+ return true;
+ }
+ if("java/util/regex/Pattern".contains(className)) {
+ // Pattern.compile is often used to check the PatternSyntaxException, thus we consider it as side-effect method
+ return !m.getName().equals("compile") && !m.getName().equals("<init>");
+ }
+ if(className.startsWith("[") && m.getName().equals("clone")) {
+ return true;
+ }
+ if(className.startsWith("org/w3c/dom/") && (m.getName().startsWith("get") || m.getName().startsWith("has") || m.getName().equals("item"))) {
+ return true;
+ }
+ if(className.startsWith("java/util/") &&
+ (className.endsWith("Set") || className.endsWith("Map") || className.endsWith("Collection")
+ || className.endsWith("List") || className.endsWith("Queue") || className.endsWith("Deque")
+ || className.endsWith("Vector")) || className.endsWith("Hashtable") || className.endsWith("Dictionary")) {
+ // LinkedHashSet in accessOrder mode changes internal state during get/getOrDefault
+ if(className.equals("java/util/LinkedHashMap") && m.getName().startsWith("get")) {
+ return false;
+ }
+ if(NO_SIDE_EFFECT_COLLECTION_METHODS.contains(m.getName()) || (m.getName().equals("toArray") && m.getSignature().equals("()[Ljava/lang/Object;"))) {
+ return true;
+ }
+ }
+ if(m.getName().equals("binarySearch") && (m.getSlashedClassName().equals("java/util/Arrays") || m.getSlashedClassName().equals("java/util/Collections"))) {
+ return true;
+ }
+ if(m.getName().startsWith("$SWITCH_TABLE$")) {
+ return true;
+ }
+ if(m.getName().equals("<init>") && isObjectOnlyClass(className)) {
+ return true;
+ }
+ if(m.getName().equals("toString") && m.getSignature().equals("()Ljava/lang/String;") && m.getSlashedClassName().startsWith("java/")) {
+ return true;
+ }
+ if(NUMBER_CLASSES.contains(className)) {
+ return !m.getSignature().startsWith("(Ljava/lang/String;");
+ }
+ if(!m.isStatic() && m.getName().equals("equals") &&
+ m.getSignature().equals("(Ljava/lang/Object;)Z")) {
+ return true;
+ }
+ if(NO_SIDE_EFFECT_METHODS.contains(m)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param m method to check
+ * @return true if we may assume that given unseen method has no side effect
+ */
+ private static boolean hasNoSideEffectUnknown(MethodDescriptor m) {
+ if(m.isStatic() && m.getName().equals("<clinit>")) {
+ // No side effect for class initializer of unseen class
+ return true;
+ }
+ if(!m.isStatic() && m.getName().equals("toString") && m.getSignature().equals("()Ljava/lang/String;")) {
+ // We assume no side effect for unseen toString methods
+ return true;
+ }
+ if(!m.isStatic() && m.getName().equals("hashCode") && m.getSignature().equals("()I")) {
+ // We assume no side effect for unseen hashCode methods
+ return true;
+ }
+ if(m.isStatic() && m.getName().equals("values") && m.getSignature().startsWith("()")) {
+ // We assume no side effect for unseen enums
+ return Subtypes2.instanceOf(m.getClassDescriptor(), "java.lang.Enum");
+ }
+ return false;
+ }
+
+ /**
+ * @param m method to check
+ * @return true if given method is known to change its object only
+ */
+ private static boolean isObjectOnlyMethod(MethodDescriptor m) {
+ if (m.isStatic() || m.getName().equals("<init>")) {
+ return false;
+ }
+ String className = m.getSlashedClassName();
+ if(isObjectOnlyClass(className)) {
+ return true;
+ }
+ if(className.startsWith("javax/xml/") && m.getName().startsWith("next")) {
+ return true;
+ }
+ if ((className.startsWith("java/net/") || className.startsWith("javax/servlet"))
+ && (m.getName().startsWith("remove") || m.getName().startsWith("add") || m.getName().startsWith("set"))) {
+ return true;
+ }
+ if(OBJECT_ONLY_METHODS.contains(m)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param className class to check
+ * @return true if all methods of this class are known to be object-only or no-side-effect
+ */
+ private static boolean isObjectOnlyClass(String className) {
+ if(OBJECT_ONLY_CLASSES.contains(className)) {
+ return true;
+ }
+ if(className.startsWith("java/lang/") && (className.endsWith("Error") || className.endsWith("Exception"))) {
+ return true;
+ }
+ return className.startsWith("java/util/") &&
+ (className.endsWith("Set") || className.endsWith("Map") || className.endsWith("Collection")
+ || className.endsWith("List") || className.endsWith("Queue") || className.endsWith("Deque")
+ || className.endsWith("Vector"));
+ }
+
+ @Override
+ public void report() {
+ computeFinalStatus();
+ Set<String> sideEffectClinit = new HashSet<>();
+ for(Entry<MethodDescriptor, SideEffectStatus> entry : statusMap.entrySet()) {
+ if (entry.getValue() == SideEffectStatus.SIDE_EFFECT && entry.getKey().isStatic() && entry.getKey().getName().equals("<clinit>")) {
+ sideEffectClinit.add(entry.getKey().getSlashedClassName());
+ }
+ }
+ for(Entry<MethodDescriptor, SideEffectStatus> entry : statusMap.entrySet()) {
+ MethodDescriptor m = entry.getKey();
+ if (entry.getValue() == SideEffectStatus.NO_SIDE_EFFECT) {
+ String returnType = new SignatureParser(m.getSignature()).getReturnTypeSignature();
+ if (!returnType.equals("V") || m.getName().equals("<init>")) {
+ if(m.equals(GET_CLASS)) {
+ /* We do not mark getClass() call as pure, because it can appear in code like this:
+ public class Outer {
+ public class Inner {}
+ public void test(Outer n) { n.new Inner(); }
+ }
+ The test method is compiled into (assumably it's done to generate NPE if n is null)
+ 0: new #16 // class a/Outer$Inner
+ 3: aload_1
+ 4: dup
+ 5: invokevirtual #18 // Method java/lang/Object.getClass:()Ljava/lang/Class;
+ 8: pop
+ 9: invokespecial #22 // Method a/Outer$Inner."<init>":(La/Outer;)V
+ 12: return
+ So we would have a false-positive here
+ */
+ continue;
+ }
+ if (m.getName().startsWith("access$") && (!(m instanceof XMethod) || ((XMethod)m).getAccessMethodForMethod() == null)) {
+ /* We skip field access methods, because they can unnecessarily be used for static calls
+ * (probably by older javac)
+ */
+ continue;
+ }
+ if (m.getName().startsWith("jjStopStringLiteral")) {
+ /* Some old JJTree versions may generate redundant calls to this method
+ * Skip it as reports in generated code don't help much
+ */
+ continue;
+ }
+ if (m.isStatic() || m.getName().equals("<init>")) {
+ if(sideEffectClinit.contains(m.getSlashedClassName())) {
+ /* Skip static methods and constructors for classes which have
+ * side-effect class initializer
+ */
+ noSideEffectMethods.add(m, MethodSideEffectStatus.SE_CLINIT);
+ continue;
+ }
+ }
+ if(m.equals(CLASS_GET_NAME) // used sometimes to trigger class loading
+ || m.equals(HASH_CODE) // found intended hashCode call several times in different projects, need further research
+ ) {
+ noSideEffectMethods.add(m, MethodSideEffectStatus.NSE_EX);
+ continue;
+ }
+ if (m.isStatic() && getStaticMethods.contains(m) && !m.getSlashedClassName().startsWith("java/")) {
+ String returnSlashedClassName = ClassName.fromFieldSignature(returnType);
+ if(returnSlashedClassName != null) {
+ String returnClass = ClassName.toDottedClassName(returnSlashedClassName);
+ if(ClassName.extractPackageName(returnClass).equals(m.getClassDescriptor().getPackageName())) {
+ /* Skip methods which only retrieve static field from the same package
+ * As they as often used to trigger class initialization
+ */
+ noSideEffectMethods.add(m, MethodSideEffectStatus.NSE_EX);
+ continue;
+ }
+ }
+ }
+ noSideEffectMethods.add(m, MethodSideEffectStatus.NSE);
+ } else { // void methods
+ if(uselessVoidCandidates.contains(m)) {
+ if(m.getName().equals("maybeForceBuilderInitialization") && m.getSignature().equals("()V")) {
+ // Autogenerated by Google protocol buffer compiler
+ continue;
+ }
+ noSideEffectMethods.add(m, MethodSideEffectStatus.USELESS);
+ }
+ }
+ } else if(entry.getValue() == SideEffectStatus.OBJECT_ONLY) {
+ noSideEffectMethods.add(m, MethodSideEffectStatus.OBJ);
+ }
+ }
+ }
+
+ /**
+ * @param xMethod
+ * @return true if this has other implementations
+ */
+ private static boolean hasOtherImplementations(XMethod xMethod) {
+ Set<XMethod> superMethods = Hierarchy2.findSuperMethods(xMethod);
+ superMethods.add(xMethod);
+ Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
+ Set<ClassDescriptor> subtypes = new HashSet<>();
+ for(XMethod superMethod : superMethods) {
+ try {
+ subtypes.addAll(subtypes2.getSubtypes(superMethod.getClassDescriptor()));
+ } catch (ClassNotFoundException e) {
+ // ignore
+ }
+ }
+ subtypes.remove(xMethod.getClassDescriptor());
+ for (ClassDescriptor subtype : subtypes) {
+ try {
+ XClass xClass = subtype.getXClass();
+ XMethod subMethod = xClass.findMatchingMethod(xMethod.getMethodDescriptor());
+ if (subMethod != null) {
+ if(!subMethod.isAbstract() ) {
+ return true;
+ }
+ }
+ } catch (CheckedAnalysisException e) {
+ // ignore
+ }
+ }
+ return false;
+ }
+
+ private void computeFinalStatus() {
+ boolean changed = true;
+ while (changed) {
+ changed = false;
+ Iterator<Entry<MethodDescriptor, List<MethodCall>>> iterator = callGraph.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Entry<MethodDescriptor, List<MethodCall>> entry = iterator.next();
+ MethodDescriptor method = entry.getKey();
+ uselessVoidCandidate = uselessVoidCandidates.contains(method);
+ SideEffectStatus prevStatus = statusMap.get(method);
+ status = prevStatus.toSure();
+ calledMethods = new ArrayList<>();
+ for(MethodCall methodCall : entry.getValue()) {
+ sawCall(methodCall, true);
+ if(status == SideEffectStatus.SIDE_EFFECT) {
+ break;
+ }
+ }
+ if (!uselessVoidCandidate || (status != SideEffectStatus.UNSURE && status != SideEffectStatus.NO_SIDE_EFFECT)) {
+ uselessVoidCandidates.remove(method);
+ }
+ if (status != prevStatus || !entry.getValue().equals(calledMethods)) {
+ statusMap.put(method, status);
+ if (status.unsure()) {
+ entry.setValue(calledMethods);
+ } else {
+ iterator.remove();
+ }
+ changed = true;
+ }
+ }
+ }
+ for(Entry<MethodDescriptor, List<MethodCall>> entry : callGraph.entrySet()) {
+ MethodDescriptor method = entry.getKey();
+ status = statusMap.get(method);
+ if(status == SideEffectStatus.UNSURE) {
+ boolean safeCycle = true;
+ for(MethodCall methodCall : entry.getValue()) {
+ SideEffectStatus calledStatus = statusMap.get(methodCall.getMethod());
+ if(calledStatus != SideEffectStatus.UNSURE && calledStatus != SideEffectStatus.NO_SIDE_EFFECT) {
+ safeCycle = false;
+ break;
+ }
+ }
+ if(safeCycle) {
+ statusMap.put(method, SideEffectStatus.NO_SIDE_EFFECT);
+ uselessVoidCandidate = uselessVoidCandidates.contains(method);
+ if(uselessVoidCandidate) {
+ for(MethodCall call : entry.getValue()) {
+ uselessVoidCandidate = false;
+ if((call.getMethod().equals(method) && call.getTarget() == TARGET_THIS) || method.isStatic()) {
+ uselessVoidCandidate = true;
+ } else {
+ if(call.getMethod() instanceof XMethod) {
+ XMethod xMethod = (XMethod) call.getMethod();
+ if(xMethod.isFinal() || (!xMethod.isPublic() && !xMethod.isProtected())) {
+ uselessVoidCandidate = true;
+ }
+ }
+ }
+ if(!uselessVoidCandidate) {
+ break;
+ }
+ }
+ if(!uselessVoidCandidate) {
+ uselessVoidCandidates.remove(method);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindNonSerializableStoreIntoSession.java b/src/java/edu/umd/cs/findbugs/detect/FindNonSerializableStoreIntoSession.java
index 738fd59..ac15027 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindNonSerializableStoreIntoSession.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindNonSerializableStoreIntoSession.java
@@ -43,12 +43,14 @@ public class FindNonSerializableStoreIntoSession implements Detector {
this.bugAccumulator = new BugAccumulator(bugReporter);
}
+ @Override
public void visitClassContext(ClassContext classContext) {
Method[] methodList = classContext.getJavaClass().getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -64,14 +66,17 @@ public class FindNonSerializableStoreIntoSession implements Detector {
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
BitSet bytecodeSet = classContext.getBytecodeSet(method);
- if (bytecodeSet == null)
+ if (bytecodeSet == null) {
return;
+ }
// We don't adequately model instanceof interfaces yet
- if (bytecodeSet.get(Constants.INSTANCEOF) || bytecodeSet.get(Constants.CHECKCAST))
+ if (bytecodeSet.get(Constants.INSTANCEOF) || bytecodeSet.get(Constants.CHECKCAST)) {
return;
+ }
CFG cfg = classContext.getCFG(method);
TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
ConstantPoolGen cpg = classContext.getConstantPoolGen();
@@ -87,16 +92,19 @@ public class FindNonSerializableStoreIntoSession implements Detector {
InstructionHandle handle = location.getHandle();
Instruction ins = handle.getInstruction();
- if (!(ins instanceof INVOKEINTERFACE))
+ if (!(ins instanceof INVOKEINTERFACE)) {
continue;
+ }
INVOKEINTERFACE invoke = (INVOKEINTERFACE) ins;
String mName = invoke.getMethodName(cpg);
- if (!mName.equals("setAttribute"))
+ if (!"setAttribute".equals(mName)) {
continue;
+ }
String cName = invoke.getClassName(cpg);
- if (!cName.equals("javax.servlet.http.HttpSession"))
+ if (!"javax.servlet.http.HttpSession".equals(cName)) {
continue;
+ }
TypeFrame frame = typeDataflow.getFactAtLocation(location);
if (!frame.isValid()) {
@@ -130,8 +138,8 @@ public class FindNonSerializableStoreIntoSession implements Detector {
bugAccumulator.accumulateBug(new BugInstance(this, "J2EE_STORE_OF_NON_SERIALIZABLE_OBJECT_INTO_SESSION",
isSerializable < 0.15 ? HIGH_PRIORITY : isSerializable > 0.5 ? LOW_PRIORITY : NORMAL_PRIORITY)
- .addClassAndMethod(methodGen, sourceFile).addType(problem).describe(TypeAnnotation.FOUND_ROLE),
- sourceLineAnnotation);
+ .addClassAndMethod(methodGen, sourceFile).addType(problem).describe(TypeAnnotation.FOUND_ROLE),
+ sourceLineAnnotation);
}
} catch (ClassNotFoundException e) {
@@ -140,6 +148,7 @@ public class FindNonSerializableStoreIntoSession implements Detector {
}
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindNonSerializableValuePassedToWriteObject.java b/src/java/edu/umd/cs/findbugs/detect/FindNonSerializableValuePassedToWriteObject.java
index 0844729..db9ecc7 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindNonSerializableValuePassedToWriteObject.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindNonSerializableValuePassedToWriteObject.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.ba.type.TypeFrame;
public class FindNonSerializableValuePassedToWriteObject implements Detector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private static final boolean DEBUG = false;
@@ -39,12 +39,14 @@ public class FindNonSerializableValuePassedToWriteObject implements Detector {
this.bugReporter = bugReporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
Method[] methodList = classContext.getJavaClass().getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -59,14 +61,17 @@ public class FindNonSerializableValuePassedToWriteObject implements Detector {
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
BitSet bytecodeSet = classContext.getBytecodeSet(method);
- if (bytecodeSet == null)
+ if (bytecodeSet == null) {
return;
+ }
// We don't adequately model instanceof interfaces yet
- if (bytecodeSet.get(Constants.INSTANCEOF) || bytecodeSet.get(Constants.CHECKCAST))
+ if (bytecodeSet.get(Constants.INSTANCEOF) || bytecodeSet.get(Constants.CHECKCAST)) {
return;
+ }
CFG cfg = classContext.getCFG(method);
TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
ConstantPoolGen cpg = classContext.getConstantPoolGen();
@@ -83,16 +88,19 @@ public class FindNonSerializableValuePassedToWriteObject implements Detector {
int pc = handle.getPosition();
Instruction ins = handle.getInstruction();
- if (!(ins instanceof InvokeInstruction))
+ if (!(ins instanceof InvokeInstruction)) {
continue;
+ }
InvokeInstruction invoke = (InvokeInstruction) ins;
String mName = invoke.getMethodName(cpg);
- if (!mName.equals("writeObject"))
+ if (!"writeObject".equals(mName)) {
continue;
+ }
String cName = invoke.getClassName(cpg);
- if (!cName.equals("java.io.ObjectOutput") && !cName.equals("java.io.ObjectOutputStream"))
+ if (!"java.io.ObjectOutput".equals(cName) && !"java.io.ObjectOutputStream".equals(cName)) {
continue;
+ }
TypeFrame frame = typeDataflow.getFactAtLocation(location);
if (!frame.isValid()) {
@@ -119,16 +127,19 @@ public class FindNonSerializableValuePassedToWriteObject implements Detector {
double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(refType);
- if (isSerializable >= 0.9)
+ if (isSerializable >= 0.9) {
continue;
-
+ }
+
ReferenceType problem = DeepSubtypeAnalysis.getLeastSerializableTypeComponent(refType);
double isRemote = DeepSubtypeAnalysis.isDeepRemote(refType);
- if (isRemote >= 0.9)
+ if (isRemote >= 0.9) {
continue;
- if (isSerializable < isRemote)
+ }
+ if (isSerializable < isRemote) {
isSerializable = isRemote;
+ }
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext,
@@ -145,6 +156,7 @@ public class FindNonSerializableValuePassedToWriteObject implements Detector {
}
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindNonShortCircuit.java b/src/java/edu/umd/cs/findbugs/detect/FindNonShortCircuit.java
index d478e58..ab4eb7a 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindNonShortCircuit.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindNonShortCircuit.java
@@ -55,7 +55,7 @@ public class FindNonShortCircuit extends OpcodeStackDetector implements Stateles
boolean sawMethodCall, sawMethodCallOld;
- private BugAccumulator bugAccumulator;
+ private final BugAccumulator bugAccumulator;
public FindNonShortCircuit(BugReporter bugReporter) {
this.bugAccumulator = new BugAccumulator(bugReporter);
@@ -116,8 +116,9 @@ public class FindNonShortCircuit extends OpcodeStackDetector implements Stateles
break;
case INVOKEVIRTUAL:
- if (getNameConstantOperand().equals("length") && getClassConstantOperand().equals("java/lang/String"))
+ if ("length".equals(getNameConstantOperand()) && "java/lang/String".equals(getClassConstantOperand())) {
break;
+ }
sawDanger = true;
sawMethodCall = true;
break;
@@ -153,13 +154,16 @@ public class FindNonShortCircuit extends OpcodeStackDetector implements Stateles
OpcodeStack.Item item0 = stack.getStackItem(0);
OpcodeStack.Item item1 = stack.getStackItem(1);
if (item0.getConstant() == null && item1.getConstant() == null && distance < 4) {
- if (item0.getRegisterNumber() >= 0 && item1.getRegisterNumber() >= 0)
- if (false)
- clearAll();
+ // if (item0.getRegisterNumber() >= 0 && item1.getRegisterNumber() >= 0) {
+ // if (false) {
+ // clearAll();
+ // }
+ // }
operator = seen;
stage2 = 1;
- } else
+ } else {
stage2 = 0;
+ }
break;
case IFEQ:
case IFNE:
@@ -188,13 +192,15 @@ public class FindNonShortCircuit extends OpcodeStackDetector implements Stateles
String pattern = "NS_NON_SHORT_CIRCUIT";
if (sawDangerOld) {
- if (sawNullTestVeryOld)
+ if (sawNullTestVeryOld) {
priority = HIGH_PRIORITY;
+ }
if (sawMethodCallOld || sawNumericTestVeryOld && sawArrayDangerOld) {
priority = HIGH_PRIORITY;
pattern = "NS_DANGEROUS_NON_SHORT_CIRCUIT";
- } else
+ } else {
priority = NORMAL_PRIORITY;
+ }
}
bugAccumulator.accumulateBug(new BugInstance(this, pattern, priority).addClassAndMethod(this), this);
@@ -212,6 +218,9 @@ public class FindNonShortCircuit extends OpcodeStackDetector implements Stateles
case ILOAD_2:
case ILOAD_3:
clearAll();
+ break;
+ default:
+ break;
}
break;
case ICONST_1:
@@ -231,16 +240,17 @@ public class FindNonShortCircuit extends OpcodeStackDetector implements Stateles
break;
case GOTO:
- if (stage1 == 1)
+ if (stage1 == 1) {
stage1 = 2;
- else {
+ } else {
stage1 = 0;
clearAll();
}
break;
case ICONST_0:
- if (stage1 == 2)
+ if (stage1 == 2) {
sawBooleanValue();
+ }
stage1 = 0;
break;
case INVOKEINTERFACE:
@@ -248,8 +258,9 @@ public class FindNonShortCircuit extends OpcodeStackDetector implements Stateles
case INVOKESPECIAL:
case INVOKESTATIC:
String sig = getSigConstantOperand();
- if (sig.endsWith(")Z"))
+ if (sig.endsWith(")Z")) {
sawBooleanValue();
+ }
stage1 = 0;
break;
default:
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindNullDeref.java b/src/java/edu/umd/cs/findbugs/detect/FindNullDeref.java
index 772391b..a9a0355 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindNullDeref.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindNullDeref.java
@@ -90,7 +90,6 @@ import edu.umd.cs.findbugs.ba.XField;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.ba.XMethodParameter;
import edu.umd.cs.findbugs.ba.interproc.ParameterProperty;
-import edu.umd.cs.findbugs.ba.interproc.PropertyDatabase;
import edu.umd.cs.findbugs.ba.jsr305.TypeQualifierAnnotation;
import edu.umd.cs.findbugs.ba.jsr305.TypeQualifierApplications;
import edu.umd.cs.findbugs.ba.jsr305.TypeQualifierValue;
@@ -146,7 +145,7 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
private static final boolean MARK_DOOMED = SystemProperties.getBoolean("fnd.markdoomed", true);
- private static final boolean REPORT_SAFE_METHOD_TARGETS = true;
+ // private static final boolean REPORT_SAFE_METHOD_TARGETS = true;
private static final String METHOD = SystemProperties.getProperty("fnd.method");
@@ -180,6 +179,7 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
this.bugAccumulator = new BugAccumulator(bugReporter);
}
+ @Override
public void visitClassContext(ClassContext classContext) {
this.classContext = classContext;
@@ -187,21 +187,25 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
JavaClass jclass = classContext.getJavaClass();
String className = jclass.getClassName();
- if (CLASS != null && !className.equals(CLASS))
+ if (CLASS != null && !className.equals(CLASS)) {
return;
+ }
List<Method> methodsInCallOrder = classContext.getMethodsInCallOrder();
for (Method method : methodsInCallOrder) {
try {
- if (method.isAbstract() || method.isNative() || method.getCode() == null)
+ if (method.isAbstract() || method.isNative() || method.getCode() == null) {
continue;
+ }
currentMethod = SignatureConverter.convertMethodSignature(jclass, method);
- if (METHOD != null && !method.getName().equals(METHOD))
+ if (METHOD != null && !method.getName().equals(METHOD)) {
continue;
- if (DEBUG || DEBUG_NULLARG)
+ }
+ if (DEBUG || DEBUG_NULLARG) {
System.out.println("Checking for NP in " + currentMethod);
+ }
analyzeMethod(classContext, method);
} catch (MissingClassException e) {
bugReporter.reportMissingClass(e.getClassNotFoundException());
@@ -214,19 +218,20 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
}
}
- private void analyzeMethod(ClassContext classContext, Method method) throws DataflowAnalysisException, CFGBuilderException
-
- {
- if (DEBUG || DEBUG_NULLARG)
+ private void analyzeMethod(ClassContext classContext, Method method) throws DataflowAnalysisException, CFGBuilderException {
+ if (DEBUG || DEBUG_NULLARG) {
System.out.println("Pre FND ");
+ }
- if ((method.getAccessFlags() & Constants.ACC_VOLATILE) != 0)
+ if ((method.getAccessFlags() & Constants.ACC_BRIDGE) != 0) {
return;
+ }
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
if (!checkedDatabases) {
checkDatabases();
checkedDatabases = true;
@@ -241,8 +246,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
if (value instanceof Type) {
String className = ((Type) value).getClassName();
- if (className.equals("java.lang.NullPointerException"))
+ if ("java.lang.NullPointerException".equals(className)) {
return;
+ }
}
}
@@ -251,8 +257,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
this.method = method;
this.methodAnnotation = getMethodNullnessAnnotation();
- if (DEBUG || DEBUG_NULLARG)
+ if (DEBUG || DEBUG_NULLARG) {
System.out.println("FND: " + SignatureConverter.convertMethodSignature(methodGen));
+ }
this.previouslyDeadBlocks = findPreviouslyDeadBlocks();
@@ -305,9 +312,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
unconditionalDerefParamDatabase = analysisContext.getUnconditionalDerefParamDatabase();
}
- private <DatabaseType extends PropertyDatabase<?, ?>> boolean isDatabaseNonEmpty(DatabaseType database) {
- return database != null && !database.isEmpty();
- }
+ // private <DatabaseType extends PropertyDatabase<?, ?>> boolean isDatabaseNonEmpty(DatabaseType database) {
+ // return database != null && !database.isEmpty();
+ // }
/**
* See if the currently-visited method declares a
@@ -344,8 +351,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
Instruction ins = location.getHandle().getInstruction();
try {
ValueNumberFrame vnaFrame = classContext.getValueNumberDataflow(method).getFactAtLocation(location);
- if (!vnaFrame.isValid())
+ if (!vnaFrame.isValid()) {
continue;
+ }
if (ins instanceof InvokeInstruction) {
examineCallSite(location, cpg, typeDataflow);
@@ -376,23 +384,27 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
// Don't check equals() calls.
// If an equals() call unconditionally dereferences the parameter,
// it is the fault of the method, not the caller.
- if (methodName.equals("equals") && signature.equals("(Ljava/lang/Object;)Z"))
+ if ("equals".equals(methodName) && "(Ljava/lang/Object;)Z".equals(signature)) {
return;
+ }
int returnTypeStart = signature.indexOf(')');
- if (returnTypeStart < 0)
+ if (returnTypeStart < 0) {
return;
+ }
String paramList = signature.substring(0, returnTypeStart + 1);
- if (paramList.equals("()") || (paramList.indexOf("L") < 0 && paramList.indexOf('[') < 0))
+ if ("()".equals(paramList) || (paramList.indexOf('L') < 0 && paramList.indexOf('[') < 0)) {
// Method takes no arguments, or takes no reference arguments
return;
+ }
// See if any null arguments are passed
IsNullValueFrame frame = classContext.getIsNullValueDataflow(method).getFactAtLocation(location);
- if (!frame.isValid())
+ if (!frame.isValid()) {
return;
-
+ }
+ /*
if (false && methodName.equals("checkNotNull")
&& invokeInstruction.getClassName(cpg).equals("com.google.common.base.Preconditions")) {
SignatureParser sigParser = new SignatureParser(signature);
@@ -426,14 +438,15 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
}
BugInstance warning = new BugInstance(this, pattern, priority)
- .addClassAndMethod(classContext.getJavaClass(), method).addOptionalAnnotation(annotation)
- .addCalledMethod(cpg, invokeInstruction).addSourceLine(classContext, method, location);
+ .addClassAndMethod(classContext.getJavaClass(), method).addOptionalAnnotation(annotation)
+ .addCalledMethod(cpg, invokeInstruction).addSourceLine(classContext, method, location);
bugReporter.reportBug(warning);
}
}
-
+ */
BitSet nullArgSet = frame.getArgumentSet(invokeInstruction, cpg, new DataflowValueChooser<IsNullValue>() {
+ @Override
public boolean choose(IsNullValue value) {
// Only choose non-exception values.
// Values null on an exception path might be due to
@@ -442,13 +455,15 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
}
});
BitSet definitelyNullArgSet = frame.getArgumentSet(invokeInstruction, cpg, new DataflowValueChooser<IsNullValue>() {
+ @Override
public boolean choose(IsNullValue value) {
return value.isDefinitelyNull();
}
});
nullArgSet.and(definitelyNullArgSet);
- if (nullArgSet.isEmpty())
+ if (nullArgSet.isEmpty()) {
return;
+ }
if (DEBUG_NULLARG) {
System.out.println("Null arguments passed: " + nullArgSet);
System.out.println("Frame is: " + frame);
@@ -473,8 +488,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
throws DataflowAnalysisException {
IsNullValueFrame frame = invDataflow.getFactAtLocation(location);
- if (!frame.isValid())
+ if (!frame.isValid()) {
return;
+ }
IsNullValue tos = frame.getTopValue();
if (tos.isDefinitelyNull()) {
XField field = XFactory.createXField(ins, cpg);
@@ -512,11 +528,13 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
IsNullValueDataflow invDataflow = classContext.getIsNullValueDataflow(method);
IsNullValueFrame frame = invDataflow.getFactAtLocation(location);
ValueNumberFrame vnaFrame = classContext.getValueNumberDataflow(method).getFactAtLocation(location);
- if (!vnaFrame.isValid())
+ if (!vnaFrame.isValid()) {
return;
+ }
ValueNumber valueNumber = vnaFrame.getTopValue();
- if (!frame.isValid())
+ if (!frame.isValid()) {
return;
+ }
IsNullValue tos = frame.getTopValue();
if (tos.isDefinitelyNull()) {
BugAnnotation variable = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, location, valueNumber, vnaFrame,
@@ -524,13 +542,14 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
String bugPattern = "NP_NONNULL_RETURN_VIOLATION";
int priority = NORMAL_PRIORITY;
- if (tos.isDefinitelyNull() && !tos.isException())
+ if (tos.isDefinitelyNull() && !tos.isException()) {
priority = HIGH_PRIORITY;
+ }
String methodName = method.getName();
- if (methodName.equals("clone")) {
+ if ("clone".equals(methodName)) {
bugPattern = "NP_CLONE_COULD_RETURN_NULL";
priority = NORMAL_PRIORITY;
- } else if (methodName.equals("toString")) {
+ } else if ("toString".equals(methodName)) {
bugPattern = "NP_TOSTRING_COULD_RETURN_NULL";
priority = NORMAL_PRIORITY;
}
@@ -547,8 +566,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
for (Iterator<Location> i = classContext.getCFG(method).locationIterator(); i.hasNext();) {
Location loc = i.next();
int pc2 = loc.getHandle().getPosition();
- if (pc2 >= pc || pc2 < pc - 30)
+ if (pc2 >= pc || pc2 < pc - 30) {
continue;
+ }
Instruction ins = loc.getHandle().getInstruction();
if ((ins instanceof IFNONNULL || ins instanceof IFNULL || ins instanceof NullnessConversationInstruction)
&& !seen.get(pc2)) {
@@ -570,21 +590,14 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
public static final Set<String> catchTypesForNull = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
"java/lang/NullPointerException", "java/lang/RuntimeException", "java/lang/Exception")));
- private boolean catchesNull(Location location) {
-
- ConstantPool constantPool = classContext.getJavaClass().getConstantPool();
- Code code = method.getCode();
-
- return catchesNull(constantPool, code, location);
- }
-
public static boolean catchesNull(ConstantPool constantPool, Code code, Location location) {
int position = location.getHandle().getPosition();
for (String t : catchTypesForNull) {
int catchSize = Util.getSizeOfSurroundingTryBlock(constantPool, code, t, position);
- if (catchSize < Integer.MAX_VALUE)
+ if (catchSize < Integer.MAX_VALUE) {
return true;
+ }
}
return false;
@@ -593,7 +606,7 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
private boolean safeCallToPrimateParseMethod(XMethod calledMethod, Location location) {
int position = location.getHandle().getPosition();
- if (calledMethod.getClassName().equals("java.lang.Integer")) {
+ if ("java.lang.Integer".equals(calledMethod.getClassName())) {
ConstantPool constantPool = classContext.getJavaClass().getConstantPool();
Code code = method.getCode();
@@ -601,31 +614,37 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
int catchSize;
catchSize = Util.getSizeOfSurroundingTryBlock(constantPool, code, "java/lang/NumberFormatException", position);
- if (catchSize < Integer.MAX_VALUE)
+ if (catchSize < Integer.MAX_VALUE) {
return true;
+ }
catchSize = Util.getSizeOfSurroundingTryBlock(constantPool, code, "java/lang/IllegalArgumentException", position);
- if (catchSize < Integer.MAX_VALUE)
+ if (catchSize < Integer.MAX_VALUE) {
return true;
+ }
catchSize = Util.getSizeOfSurroundingTryBlock(constantPool, code, "java/lang/RuntimeException", position);
- if (catchSize < Integer.MAX_VALUE)
+ if (catchSize < Integer.MAX_VALUE) {
return true;
+ }
catchSize = Util.getSizeOfSurroundingTryBlock(constantPool, code, "java/lang/Exception", position);
- if (catchSize < Integer.MAX_VALUE)
+ if (catchSize < Integer.MAX_VALUE) {
return true;
+ }
}
return false;
}
private void checkUnconditionallyDereferencedParam(Location location, ConstantPoolGen cpg, TypeDataflow typeDataflow,
InvokeInstruction invokeInstruction, BitSet nullArgSet, BitSet definitelyNullArgSet)
- throws DataflowAnalysisException, ClassNotFoundException {
+ throws DataflowAnalysisException, ClassNotFoundException {
- if (inExplictCatchNullBlock(location))
+ if (inExplictCatchNullBlock(location)) {
return;
+ }
boolean caught = inIndirectCatchNullBlock(location);
- if (caught && skipIfInsideCatchNull())
+ if (caught && skipIfInsideCatchNull()) {
return;
+ }
// See what methods might be called here
XMethod calledMethod = XFactory.createXMethod(invokeInstruction, cpg);
@@ -635,7 +654,7 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
nullArgSet = (BitSet) nullArgSet.clone();
definitelyNullArgSet = (BitSet) definitelyNullArgSet.clone();
ClassDescriptor nonnullClassDesc = DescriptorFactory.createClassDescriptor(javax.annotation.Nonnull.class);
- TypeQualifierValue nonnullTypeQualifierValue = TypeQualifierValue.getValue(nonnullClassDesc, null);
+ TypeQualifierValue<?> nonnullTypeQualifierValue = TypeQualifierValue.getValue(nonnullClassDesc, null);
for (int i = nullArgSet.nextSetBit(0); i >= 0; i = nullArgSet.nextSetBit(i + 1)) {
TypeQualifierAnnotation tqa = TypeQualifierApplications.getEffectiveTypeQualifierAnnotation(calledMethod, i,
nonnullTypeQualifierValue);
@@ -663,27 +682,31 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
}
ParameterProperty property = unconditionalDerefParamDatabase.getProperty(targetMethod.toMethodDescriptor());
- if (property == null)
+ if (property == null) {
continue;
+ }
if (DEBUG_NULLARG) {
System.out.println("\tUnconditionally dereferenced params: " + property);
}
BitSet targetUnconditionallyDereferencedNullArgSet = property.getMatchingParameters(nullArgSet);
- if (targetUnconditionallyDereferencedNullArgSet.isEmpty())
+ if (targetUnconditionallyDereferencedNullArgSet.isEmpty()) {
continue;
+ }
dangerousCallTargetList.add(targetMethod);
unconditionallyDereferencedNullArgSet.or(targetUnconditionallyDereferencedNullArgSet);
- if (!property.getMatchingParameters(definitelyNullArgSet).isEmpty())
+ if (!property.getMatchingParameters(definitelyNullArgSet).isEmpty()) {
veryDangerousCallTargetList.add(targetMethod);
+ }
}
- if (dangerousCallTargetList.isEmpty())
+ if (dangerousCallTargetList.isEmpty()) {
return;
+ }
WarningPropertySet<WarningProperty> propertySet = new WarningPropertySet<WarningProperty>();
@@ -716,29 +739,32 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
return;
}
- if (caught)
+ if (caught) {
priority++;
- if (dangerousCallTargetList.size() > veryDangerousCallTargetList.size())
+ }
+ if (dangerousCallTargetList.size() > veryDangerousCallTargetList.size()) {
priority++;
- else
+ } else {
propertySet.addProperty(NullArgumentWarningProperty.ACTUAL_PARAMETER_GUARANTEED_NULL);
+ }
XMethod calledFrom = XFactory.createXMethod(classContext.getJavaClass(), method);
- if (safeCallToPrimateParseMethod(calledMethod, location))
+ if (safeCallToPrimateParseMethod(calledMethod, location)) {
return;
+ }
BugInstance warning = new BugInstance(this, bugType, priority).addClassAndMethod(classContext.getJavaClass(), method)
.addMethod(calledMethod).describe(MethodAnnotation.METHOD_CALLED).addSourceLine(classContext, method, location);
- boolean uncallable = false;
+ // boolean uncallable = false;
if (!AnalysisContext.currentXFactory().isCalledDirectlyOrIndirectly(calledFrom) && calledFrom.isPrivate()) {
propertySet.addProperty(GeneralWarningProperty.IN_UNCALLABLE_METHOD);
- uncallable = true;
+ // uncallable = true;
}
// Check which params might be null
addParamAnnotations(location, definitelyNullArgSet, unconditionallyDereferencedNullArgSet, propertySet, warning);
- if (bugType.equals("NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS")) {
+ if ("NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS".equals(bugType)) {
// Add annotations for dangerous method call targets
for (JavaClassAndMethod dangerousCallTarget : veryDangerousCallTargetList) {
warning.addMethod(dangerousCallTarget).describe(MethodAnnotation.METHOD_DANGEROUS_TARGET_ACTUAL_GUARANTEED_NULL);
@@ -787,10 +813,11 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
for (int i = violatedParamSet.nextSetBit(0); i >= 0; i = violatedParamSet.nextSetBit(i + 1)) {
boolean definitelyNull = definitelyNullArgSet.get(i);
- if (definitelyNull)
+ if (definitelyNull) {
propertySet.addProperty(NullArgumentWarningProperty.ARG_DEFINITELY_NULL);
+ }
ValueNumber valueNumber = null;
- if (vnaFrame != null)
+ if (vnaFrame != null) {
try {
valueNumber = vnaFrame.getArgument(instruction, classContext.getConstantPoolGen(), i, sigParser);
BugAnnotation variableAnnotation = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, location,
@@ -799,6 +826,7 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
} catch (DataflowAnalysisException e) {
AnalysisContext.logError("error", e);
}
+ }
// Note: we report params as being indexed starting from 1, not
// 0
@@ -821,11 +849,13 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
private void checkNonNullParam(Location location, ConstantPoolGen cpg, TypeDataflow typeDataflow,
InvokeInstruction invokeInstruction, BitSet nullArgSet, BitSet definitelyNullArgSet) {
- if (inExplictCatchNullBlock(location))
+ if (inExplictCatchNullBlock(location)) {
return;
+ }
boolean caught = inIndirectCatchNullBlock(location);
- if (caught && skipIfInsideCatchNull())
+ if (caught && skipIfInsideCatchNull()) {
return;
+ }
XMethod m = XFactory.createXMethod(invokeInstruction, cpg);
@@ -855,10 +885,12 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
}
int priority = definitelyNull ? HIGH_PRIORITY : NORMAL_PRIORITY;
- if (caught)
+ if (caught) {
priority++;
- if (m.isPrivate() && priority == HIGH_PRIORITY)
+ }
+ if (m.isPrivate() && priority == HIGH_PRIORITY) {
priority = NORMAL_PRIORITY;
+ }
String description = definitelyNull ? "INT_NULL_ARG" : "INT_MAYBE_NULL_ARG";
WarningPropertySet<WarningProperty> propertySet = new WarningPropertySet<WarningProperty>();
Set<Location> derefLocationSet = Collections.singleton(location);
@@ -867,12 +899,13 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
boolean duplicated = isDuplicated(propertySet, location.getHandle().getPosition(), false);
- if (duplicated)
+ if (duplicated) {
return;
+ }
BugInstance warning = new BugInstance(this, "NP_NONNULL_PARAM_VIOLATION", priority)
- .addClassAndMethod(classContext.getJavaClass(), method).addMethod(m)
- .describe(MethodAnnotation.METHOD_CALLED).addParameterAnnotation(i, description)
- .addOptionalAnnotation(variableAnnotation).addSourceLine(classContext, method, location);
+ .addClassAndMethod(classContext.getJavaClass(), method).addMethod(m)
+ .describe(MethodAnnotation.METHOD_CALLED).addParameterAnnotation(i, description)
+ .addOptionalAnnotation(variableAnnotation).addSourceLine(classContext, method, location);
propertySet.decorateBugInstance(warning);
bugReporter.reportBug(warning);
@@ -881,6 +914,7 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
}
+ @Override
public void report() {
}
@@ -894,16 +928,19 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
* {@link #foundNullDeref(Location,ValueNumber,IsNullValue,ValueNumberFrame,boolean)}
* instead
*/
+ @Override
@Deprecated
public void foundNullDeref(Location location, ValueNumber valueNumber, IsNullValue refValue, ValueNumberFrame vnaFrame) {
foundNullDeref(location, valueNumber, refValue, vnaFrame, true);
}
+ @Override
public void foundNullDeref(Location location, ValueNumber valueNumber, IsNullValue refValue, ValueNumberFrame vnaFrame,
boolean isConsistent) {
WarningPropertySet<WarningProperty> propertySet = new WarningPropertySet<WarningProperty>();
- if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))
+ if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
return;
+ }
boolean onExceptionPath = refValue.isException();
if (onExceptionPath) {
@@ -916,66 +953,68 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
Instruction ins = location.getHandle().getInstruction();
if (ins instanceof InvokeInstruction && refValue.isDefinitelyNull()) {
InvokeInstruction iins = (InvokeInstruction) ins;
- if (iins.getMethodName(classContext.getConstantPoolGen()).equals("close")
- && iins.getSignature(classContext.getConstantPoolGen()).equals("()V"))
+ if ("close".equals(iins.getMethodName(classContext.getConstantPoolGen()))
+ && "()V".equals(iins.getSignature(classContext.getConstantPoolGen()))) {
propertySet.addProperty(NullDerefProperty.CLOSING_NULL);
+ }
}
boolean duplicated = isDuplicated(propertySet, pc, isConsistent);
- if (inExplictCatchNullBlock(location))
+ if (inExplictCatchNullBlock(location)) {
return;
+ }
boolean caught = inIndirectCatchNullBlock(location);
- if (caught && skipIfInsideCatchNull())
+ if (caught && skipIfInsideCatchNull()) {
return;
+ }
if (refValue.isDefinitelyNull()) {
String type = "NP_ALWAYS_NULL";
if (propertySet.containsProperty(NullDerefProperty.CLOSING_NULL)
- && !propertySet.containsProperty(NullDerefProperty.DEREFS_ARE_CLONED))
+ && !propertySet.containsProperty(NullDerefProperty.DEREFS_ARE_CLONED)) {
type = "NP_CLOSING_NULL";
- else if (onExceptionPath)
+ } else if (onExceptionPath) {
type = "NP_ALWAYS_NULL_EXCEPTION";
- else if (duplicated)
+ } else if (duplicated) {
type = "NP_NULL_ON_SOME_PATH";
+ }
int priority = onExceptionPath ? NORMAL_PRIORITY : HIGH_PRIORITY;
- if (caught)
+ if (caught) {
priority++;
+ }
reportNullDeref(propertySet, location, type, priority, variable);
} else if (refValue.mightBeNull() && refValue.isParamValue()) {
String type;
int priority = NORMAL_PRIORITY;
- if (caught)
+ if (caught) {
priority++;
+ }
- if (method.getName().equals("equals") && method.getSignature().equals("(Ljava/lang/Object;)Z")) {
- if (caught)
+ if ("equals".equals(method.getName()) && "(Ljava/lang/Object;)Z".equals(method.getSignature())) {
+ if (caught) {
return;
+ }
type = "NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT";
- } else
+ } else {
type = "NP_ARGUMENT_MIGHT_BE_NULL";
+ }
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Reporting null on some path: value=" + refValue);
+ }
reportNullDeref(propertySet, location, type, priority, variable);
}
}
- /**
- * @param propertySet
- * @param pc
- * @param isConsistent
- * @return
- */
public boolean isDuplicated(WarningPropertySet<WarningProperty> propertySet, int pc, boolean isConsistent) {
boolean duplicated = false;
if (!isConsistent) {
- if (propertySet.containsProperty(NullDerefProperty.DEREFS_ARE_CLONED))
+ if (propertySet.containsProperty(NullDerefProperty.DEREFS_ARE_CLONED)) {
duplicated = true;
-
- else
+ } else {
try {
CFG cfg = classContext.getCFG(method);
if (cfg.getLocationsContainingInstructionWithOffset(pc).size() > 1) {
@@ -985,6 +1024,7 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
} catch (CFGBuilderException e) {
AnalysisContext.logError("Error while analyzing " + classContext.getFullyQualifiedMethodName(method), e);
}
+ }
}
return duplicated;
}
@@ -994,10 +1034,11 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
BugAnnotation variable) {
BugInstance bugInstance = new BugInstance(this, type, priority).addClassAndMethod(classContext.getJavaClass(), method);
- if (variable != null)
+ if (variable != null) {
bugInstance.add(variable);
- else
+ } else {
bugInstance.add(new LocalVariableAnnotation("?", -1, -1));
+ }
bugInstance.addSourceLine(classContext, method, location).describe("SOURCE_LINE_DEREF");
if (FindBugsAnalysisFeatures.isRelaxedMode()) {
@@ -1014,19 +1055,22 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
InstructionHandle ins = target.getFirstInstruction();
int maxCount = 7;
while (ins != null) {
- if (maxCount-- <= 0)
+ if (maxCount-- <= 0) {
break;
+ }
Instruction i = ins.getInstruction();
if (i instanceof ATHROW) {
return true;
}
- if (i instanceof InstructionTargeter || i instanceof ReturnInstruction)
+ if (i instanceof InstructionTargeter || i instanceof ReturnInstruction) {
return false;
+ }
ins = ins.getNext();
}
return false;
}
+ @Override
public void foundRedundantNullCheck(Location location, RedundantBranch redundantBranch) {
boolean isChecked = redundantBranch.firstValue.isChecked();
@@ -1034,19 +1078,22 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
boolean isParameter = redundantBranch.firstValue.isParamValue();
Location locationOfKaBoom = redundantBranch.firstValue.getLocationOfKaBoom();
- if (isParameter && !wouldHaveBeenAKaboom)
+ if (isParameter && !wouldHaveBeenAKaboom) {
return;
+ }
boolean createdDeadCode = false;
boolean infeasibleEdgeSimplyThrowsException = false;
Edge infeasibleEdge = redundantBranch.infeasibleEdge;
if (infeasibleEdge != null) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Check if " + redundantBranch + " creates dead code");
+ }
BasicBlock target = infeasibleEdge.getTarget();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Target block is "
+ (target.isExceptionThrower() ? " exception thrower" : " not exception thrower"));
+ }
// If the block is empty, it probably doesn't matter that it was
// killed.
// FIXME: really, we should crawl the immediately reachable blocks
@@ -1057,32 +1104,37 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
if (!empty) {
try {
if (classContext.getCFG(method).getNumIncomingEdges(target) > 1) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Target of infeasible edge has multiple incoming edges");
+ }
empty = true;
}
} catch (CFGBuilderException e) {
assert true; // ignore it
}
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Target block is " + (empty ? "empty" : "not empty"));
+ }
if (!empty) {
- if (isThrower(target))
+ if (isThrower(target)) {
infeasibleEdgeSimplyThrowsException = true;
+ }
}
if (!empty && !previouslyDeadBlocks.get(target.getLabel())) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("target was alive previously");
+ }
// Block was not dead before the null pointer analysis.
// See if it is dead now by inspecting the null value frame.
// If it's TOP, then the block became dead.
IsNullValueFrame invFrame = invDataflow.getStartFact(target);
createdDeadCode = invFrame.isTop();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("target is now " + (createdDeadCode ? "dead" : "alive"));
+ }
}
}
@@ -1114,15 +1166,18 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
valueIsNull = false;
priority = isChecked ? HIGH_PRIORITY : NORMAL_PRIORITY;
}
- if (infeasibleEdgeSimplyThrowsException)
+ if (infeasibleEdgeSimplyThrowsException) {
priority++;
+ }
} else {
- if (stack != null)
+ if (stack != null) {
item2 = stack.getStackItem(1);
+ }
boolean bothNull = redundantBranch.firstValue.isDefinitelyNull() && redundantBranch.secondValue.isDefinitelyNull();
- if (redundantBranch.secondValue.isChecked())
+ if (redundantBranch.secondValue.isChecked()) {
isChecked = true;
+ }
if (redundantBranch.secondValue.wouldHaveBeenAKaboom()) {
wouldHaveBeenAKaboom = true;
locationOfKaBoom = redundantBranch.secondValue.getLocationOfKaBoom();
@@ -1140,39 +1195,46 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
if (wouldHaveBeenAKaboom) {
priority = HIGH_PRIORITY;
warning = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE";
- if (locationOfKaBoom == null)
+ if (locationOfKaBoom == null) {
throw new NullPointerException("location of KaBoom is null");
+ }
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println(createdDeadCode + " " + infeasibleEdgeSimplyThrowsException + " " + valueIsNull + " " + priority);
+ }
if (createdDeadCode && !infeasibleEdgeSimplyThrowsException) {
priority += 0;
} else if (createdDeadCode && infeasibleEdgeSimplyThrowsException) {
// throw clause
- if (valueIsNull)
+ if (valueIsNull) {
priority += 0;
- else
+ } else {
priority += 1;
+ }
} else {
// didn't create any dead code
priority += 1;
}
-
+
if (DEBUG) {
- System.out.println("RCN" + priority + " " + redundantBranch.firstValue + " =? " + redundantBranch.secondValue + " : "
+ System.out.println("RCN " + priority + " " + redundantBranch.firstValue + " =? " + redundantBranch.secondValue + " : "
+ warning);
- if (isChecked)
+ if (isChecked) {
System.out.println("isChecked");
- if (wouldHaveBeenAKaboom)
+ }
+ if (wouldHaveBeenAKaboom) {
System.out.println("wouldHaveBeenAKaboom");
- if (createdDeadCode)
+ }
+ if (createdDeadCode) {
System.out.println("createdDeadCode");
+ }
}
- if (priority > LOW_PRIORITY)
+ if (priority > LOW_PRIORITY) {
return;
+ }
BugAnnotation variableAnnotation = null;
try {
// Get the value number
@@ -1181,15 +1243,17 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
Instruction ins = location.getHandle().getInstruction();
ValueNumber valueNumber = vnaFrame.getInstance(ins, classContext.getConstantPoolGen());
- if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))
+ if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
return;
+ }
variableAnnotation = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, location, valueNumber, vnaFrame,
"VALUE_OF");
if (variableAnnotation instanceof LocalVariableAnnotation) {
LocalVariableAnnotation local = (LocalVariableAnnotation) variableAnnotation;
if (!local.isNamed()) {
- if (warning.equals("RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"))
+ if ("RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE".equals(warning)) {
return;
+ }
priority++;
}
}
@@ -1207,23 +1271,28 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
BugInstance.getFieldOrMethodValueSource(item1), BugInstance.getFieldOrMethodValueSource(item2));
if (!foundSource) {
- if (warning.equals("RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"))
+ if ("RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE".equals(warning)) {
return;
+ }
bugInstance.setPriority(priority+1);
bugInstance.add(fallback);
}
- if (wouldHaveBeenAKaboom)
+ if (wouldHaveBeenAKaboom) {
bugInstance.addSourceLine(classContext, method, locationOfKaBoom);
+ }
if (FindBugsAnalysisFeatures.isRelaxedMode()) {
WarningPropertySet<WarningProperty> propertySet = new WarningPropertySet<WarningProperty>();
WarningPropertyUtil.addPropertiesForDataMining(propertySet, classContext, method, location);
- if (isChecked)
+ if (isChecked) {
propertySet.addProperty(NullDerefProperty.CHECKED_VALUE);
- if (wouldHaveBeenAKaboom)
+ }
+ if (wouldHaveBeenAKaboom) {
propertySet.addProperty(NullDerefProperty.WOULD_HAVE_BEEN_A_KABOOM);
- if (createdDeadCode)
+ }
+ if (createdDeadCode) {
propertySet.addProperty(NullDerefProperty.CREATED_DEAD_CODE);
+ }
propertySet.decorateBugInstance(bugInstance);
}
@@ -1242,8 +1311,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
Instruction ins = location.getHandle().getInstruction();
ValueNumber valueNumber = vnaFrame.getInstance(ins, classContext.getConstantPoolGen());
- if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))
+ if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
return null;
+ }
variableAnnotation = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, location, valueNumber, vnaFrame,
"VALUE_OF");
@@ -1270,17 +1340,21 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
int minPC(Collection<Location> locs) {
int result = 1000000;
- for (Location l : locs)
- if (result > l.getHandle().getPosition())
+ for (Location l : locs) {
+ if (result > l.getHandle().getPosition()) {
result = l.getHandle().getPosition();
+ }
+ }
return result;
}
int maxPC(Collection<Location> locs) {
int result = -1000000;
- for (Location l : locs)
- if (result < l.getHandle().getPosition())
+ for (Location l : locs) {
+ if (result < l.getHandle().getPosition()) {
result = l.getHandle().getPosition();
+ }
+ }
return result;
}
@@ -1296,19 +1370,22 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
int pos = h.getPosition();
if (ln == null) {
- if (pos > firstPos + 15)
+ if (pos > firstPos + 15) {
break;
+ }
} else {
int line = ln.getSourceLine(pos);
- if (line != firstLine)
+ if (line != firstLine) {
break;
+ }
}
Instruction i = h.getInstruction();
if (i instanceof InvokeInstruction) {
InvokeInstruction ii = (InvokeInstruction) i;
String name = ii.getMethodName(classContext.getConstantPoolGen());
- if (name.startsWith("check") || name.startsWith("assert"))
+ if (name.startsWith("check") || name.startsWith("assert")) {
return true;
+ }
}
h = h.getNext();
}
@@ -1323,18 +1400,21 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
* foundGuaranteedNullDeref(java.util.Set, java.util.Set,
* edu.umd.cs.findbugs.ba.vna.ValueNumber, boolean)
*/
+ @Override
public void foundGuaranteedNullDeref(@Nonnull
- Set<Location> assignedNullLocationSet, @Nonnull
- Set<Location> derefLocationSet, SortedSet<Location> doomedLocations, ValueNumberDataflow vna, ValueNumber refValue,
+ Set<Location> assignedNullLocationSet, @Nonnull
+ Set<Location> derefLocationSet, SortedSet<Location> doomedLocations, ValueNumberDataflow vna, ValueNumber refValue,
@CheckForNull
BugAnnotation variableAnnotation, NullValueUnconditionalDeref deref, boolean npeIfStatementCovered) {
- if (refValue.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))
+ if (refValue.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
return;
+ }
if (DEBUG) {
System.out.println("Found guaranteed null deref in " + method.getName());
- for (Location loc : doomedLocations)
+ for (Location loc : doomedLocations) {
System.out.println("Doomed at " + loc);
+ }
}
String bugType;
@@ -1342,39 +1422,46 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
int priority = npeIfStatementCovered ? HIGH_PRIORITY : NORMAL_PRIORITY;
if (deref.isMethodReturnValue()) {
- if (deref.isReadlineValue())
+ if (deref.isReadlineValue()) {
bugType = "NP_DEREFERENCE_OF_READLINE_VALUE";
- else
+ } else {
bugType = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE";
- } else if (derefLocationSet.size() > 1)
- if (!deref.isAlwaysOnExceptionPath())
- bugType = "NP_GUARANTEED_DEREF";
- else
- bugType = "NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH";
- else if (!deref.isAlwaysOnExceptionPath())
- bugType = "NP_NULL_ON_SOME_PATH";
- else
- bugType = "NP_NULL_ON_SOME_PATH_EXCEPTION";
+ }
+ } else if (derefLocationSet.size() > 1) {
+ if (!deref.isAlwaysOnExceptionPath()) {
+ bugType = "NP_GUARANTEED_DEREF";
+ } else {
+ bugType = "NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH";
+ }
+ } else if (!deref.isAlwaysOnExceptionPath()) {
+ bugType = "NP_NULL_ON_SOME_PATH";
+ } else {
+ bugType = "NP_NULL_ON_SOME_PATH_EXCEPTION";
+ }
boolean allCallToAssertionMethod = !doomedLocations.isEmpty();
for (Location loc : doomedLocations) {
- if (!callToAssertionMethod(loc))
+ if (!callToAssertionMethod(loc)) {
allCallToAssertionMethod = false;
+ }
}
- if (allCallToAssertionMethod)
+ if (allCallToAssertionMethod) {
return;
+ }
// Add Locations in the set of locations at least one of which
// is guaranteed to be dereferenced
SortedSet<Location> sourceLocations;
- if (doomedLocations.isEmpty() || doomedLocations.size() > 3 && doomedLocations.size() > assignedNullLocationSet.size())
+ if (doomedLocations.isEmpty() || doomedLocations.size() > 3 && doomedLocations.size() > assignedNullLocationSet.size()) {
sourceLocations = new TreeSet<Location>(assignedNullLocationSet);
- else
+ } else {
sourceLocations = doomedLocations;
+ }
- if (doomedLocations.isEmpty() || derefLocationSet.isEmpty())
+ if (doomedLocations.isEmpty() || derefLocationSet.isEmpty()) {
return;
+ }
WarningPropertySet<WarningProperty> propertySet = new WarningPropertySet<WarningProperty>();
@@ -1384,9 +1471,12 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
int distance1 = minDereferencePC - maxPC(assignedNullLocationSet);
int distance2 = minDereferencePC - maxPC(doomedLocations);
int distance = Math.max(distance1, distance2);
- if (false)
+ /*
+ if (false) {
System.out.printf("%9d %9d %9d RANGE %s.%s%s\n", distance, distance1, distance2, classContext.getClassDescriptor()
.toDottedClassName(), method.getName(), method.getSignature());
+ }
+ */
// Create BugInstance
@@ -1395,12 +1485,13 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
SortedSet<SourceLineAnnotation> knownNullLocations = new TreeSet<SourceLineAnnotation>();
for (Location loc : sourceLocations) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, method, loc);
- if (sourceLineAnnotation == null)
+ if (sourceLineAnnotation == null) {
continue;
+ }
int startLine = sourceLineAnnotation.getStartLine();
- if (startLine == -1)
+ if (startLine == -1) {
knownNullLocations.add(sourceLineAnnotation);
- else if (!knownNull.get(startLine)) {
+ } else if (!knownNull.get(startLine)) {
knownNull.set(startLine);
knownNullLocations.add(sourceLineAnnotation);
}
@@ -1424,9 +1515,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);
}
- if (pu == null)
+ if (pu == null) {
assert true; // nothing to do
- else if (deref.isReadlineValue()) {
+ } else if (deref.isReadlineValue()) {
bugType = "NP_DEREFERENCE_OF_READLINE_VALUE";
priority = NORMAL_PRIORITY;
} else if (deref.isMethodReturnValue() && !deref.isReadlineValue()) {
@@ -1436,10 +1527,10 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
bugType = "NP_NONNULL_RETURN_VIOLATION";
String methodName = method.getName();
String methodSig = method.getSignature();
- if (methodName.equals("clone") && methodSig.equals("()Ljava/lang/Object;")) {
+ if ("clone".equals(methodName) && "()Ljava/lang/Object;".equals(methodSig)) {
bugType = "NP_CLONE_COULD_RETURN_NULL";
priority = NORMAL_PRIORITY;
- } else if (methodName.equals("toString") && methodSig.equals("()Ljava/lang/String;")) {
+ } else if ("toString".equals(methodName) && "()Ljava/lang/String;".equals(methodSig)) {
bugType = "NP_TOSTRING_COULD_RETURN_NULL";
priority = NORMAL_PRIORITY;
}
@@ -1453,13 +1544,16 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
XMethodParameter mp = pu.getNonNullParameter();
if (mp != null) {
invokedXMethod = mp.getMethod();
- for (Location derefLoc : derefLocationSet)
- if (safeCallToPrimateParseMethod(invokedXMethod, derefLoc))
+ for (Location derefLoc : derefLocationSet) {
+ if (safeCallToPrimateParseMethod(invokedXMethod, derefLoc)) {
return;
+ }
+ }
invokedMethod = MethodAnnotation.fromXMethod(mp.getMethod());
if (mp.getParameterNumber() == 0
- && TypeQualifierNullnessAnnotationDatabase.assertsFirstParameterIsNonnull(invokedXMethod))
+ && TypeQualifierNullnessAnnotationDatabase.assertsFirstParameterIsNonnull(invokedXMethod)) {
return;
+ }
parameterNumber = mp.getParameterNumber();
bugType = "NP_NULL_PARAM_DEREF";
}
@@ -1469,58 +1563,68 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
boolean hasManyNullTests = true;
for (SourceLineAnnotation sourceLineAnnotation : knownNullLocations) {
- if (!hasManyPreceedingNullTests(sourceLineAnnotation.getStartBytecode()))
+ if (!hasManyPreceedingNullTests(sourceLineAnnotation.getStartBytecode())) {
hasManyNullTests = false;
+ }
}
if (hasManyNullTests) {
- if (bugType.equals("NP_NULL_ON_SOME_PATH") || bugType.equals("NP_GUARANTEED_DEREF"))
+ if ("NP_NULL_ON_SOME_PATH".equals(bugType) || "NP_GUARANTEED_DEREF".equals(bugType)) {
bugType = "NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE";
- else
+ } else {
priority++;
+ }
}
BugInstance bugInstance = new BugInstance(this, bugType, priority).addClassAndMethod(classContext.getJavaClass(), method);
if (invokedMethod != null) {
assert invokedXMethod != null;
XMethod i = invokedXMethod.resolveAccessMethodForMethod();
- if (i != invokedXMethod)
+ if (i != invokedXMethod) {
bugInstance.addMethod(i).describe(MethodAnnotation.METHOD_CALLED);
- else
+ } else {
bugInstance.addMethod(invokedMethod).describe(MethodAnnotation.METHOD_CALLED)
- .addParameterAnnotation(parameterNumber, "INT_MAYBE_NULL_ARG");
+ .addParameterAnnotation(parameterNumber, "INT_MAYBE_NULL_ARG");
+ }
}
- if (storedField != null)
+ if (storedField != null) {
bugInstance.addField(storedField).describe("FIELD_STORED");
+ }
bugInstance.addOptionalAnnotation(variableAnnotation);
- if (variableAnnotation instanceof FieldAnnotation)
+ if (variableAnnotation instanceof FieldAnnotation) {
bugInstance.describe("FIELD_CONTAINS_VALUE");
+ }
addPropertiesForDereferenceLocations(propertySet, derefLocationSet, false);
- if (deref.isAlwaysOnExceptionPath())
+ if (deref.isAlwaysOnExceptionPath()) {
propertySet.addProperty(NullDerefProperty.ALWAYS_ON_EXCEPTION_PATH);
+ }
- if (!assignedNullLocationSet.isEmpty() && distance > 100)
+ if (!assignedNullLocationSet.isEmpty() && distance > 100) {
propertySet.addProperty(NullDerefProperty.LONG_RANGE_NULL_SOURCE);
+ }
propertySet.decorateBugInstance(bugInstance);
- if (bugType.equals("NP_DEREFERENCE_OF_READLINE_VALUE")) {
+ if ("NP_DEREFERENCE_OF_READLINE_VALUE".equals(bugType)) {
int source = -9999;
- if (knownNullLocations.size() == 1)
+ if (knownNullLocations.size() == 1) {
source = knownNullLocations.iterator().next().getEndBytecode();
+ }
for (Location loc : derefLocationSet) {
int pos = loc.getHandle().getPosition();
- if (pos != source + 3) // immediate dereferences are handled by
+ if (pos != source + 3) {
// another detector
bugAccumulator.accumulateBug(bugInstance,
SourceLineAnnotation.fromVisitedInstruction(classContext, method, loc));
+ }
}
} else {
- for (Location loc : derefLocationSet)
+ for (Location loc : derefLocationSet) {
bugInstance.addSourceLine(classContext, method, loc).describe(getDescription(loc, refValue));
+ }
if (sourceLocations == doomedLocations && assignedNullLocationSet.size() == 1) {
Location assignedNull = assignedNullLocationSet.iterator().next();
@@ -1528,8 +1632,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
assignedNull);
if (sourceLineAnnotation != null) {
int startLine = sourceLineAnnotation.getStartLine();
- if (startLine > 0 && !knownNull.get(startLine))
+ if (startLine > 0 && !knownNull.get(startLine)) {
bugInstance.add(sourceLineAnnotation).describe("SOURCE_LINE_NULL_VALUE");
+ }
}
}
@@ -1542,12 +1647,6 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
}
}
- /**
- * @param propertySet
- * @param derefLocationSet
- * @param isConsistent
- * TODO
- */
private void addPropertiesForDereferenceLocations(WarningPropertySet<WarningProperty> propertySet,
Collection<Location> derefLocationSet, boolean isConsistent) {
boolean derefOutsideCatchBlock = false;
@@ -1558,12 +1657,14 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
for (Location loc : derefLocationSet) {
if (!inExplictCatchNullBlock(loc)) {
derefOutsideCatchNullBlock = true;
- if (!inIndirectCatchNullBlock(loc))
+ if (!inIndirectCatchNullBlock(loc)) {
derefOutsideCatchBlock = true;
+ }
}
- if (!isDoomed(loc))
+ if (!isDoomed(loc)) {
allDerefsAtDoomedLocations = false;
+ }
}
if (!derefOutsideCatchNullBlock) {
@@ -1578,59 +1679,58 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
boolean uniqueDereferenceLocations = uniqueLocations(derefLocationSet);
if (!derefOutsideCatchBlock) {
- if (!uniqueDereferenceLocations || skipIfInsideCatchNull())
+ if (!uniqueDereferenceLocations || skipIfInsideCatchNull()) {
propertySet.addProperty(GeneralWarningProperty.FALSE_POSITIVE);
- else
+ } else {
propertySet.addProperty(NullDerefProperty.DEREFS_IN_CATCH_BLOCKS);
+ }
}
- if (!isConsistent && !uniqueDereferenceLocations)
+ if (!isConsistent && !uniqueDereferenceLocations) {
// Add a WarningProperty
propertySet.addProperty(NullDerefProperty.DEREFS_ARE_CLONED);
+ }
addPropertiesForMethodContainingWarning(propertySet);
}
- /**
- * @param derefLocationSet
- * @return
- */
private boolean uniqueLocations(Collection<Location> derefLocationSet) {
boolean uniqueDereferenceLocations = false;
CodeException[] exceptionTable = method.getCode().getExceptionTable();
- if (exceptionTable == null)
+ if (exceptionTable == null) {
return true;
+ }
checkForCatchAll: {
- for (CodeException e : exceptionTable)
- if (e.getCatchType() == 0)
+ for (CodeException e : exceptionTable) {
+ if (e.getCatchType() == 0) {
break checkForCatchAll;
+ }
+ }
return true;
}
LineNumberTable table = method.getLineNumberTable();
- if (table == null)
+ if (table == null) {
uniqueDereferenceLocations = true;
- else {
+ } else {
BitSet linesMentionedMultipleTimes = classContext.linesMentionedMultipleTimes(method);
for (Location loc : derefLocationSet) {
int lineNumber = table.getSourceLine(loc.getHandle().getPosition());
- if (lineNumber > 0 && !linesMentionedMultipleTimes.get(lineNumber))
+ if (lineNumber > 0 && !linesMentionedMultipleTimes.get(lineNumber)) {
uniqueDereferenceLocations = true;
+ }
}
}
return uniqueDereferenceLocations;
}
- /**
- * @param propertySet
- * @param xMethod
- */
private void addPropertiesForMethodContainingWarning(WarningPropertySet<WarningProperty> propertySet) {
XMethod xMethod = XFactory.createXMethod(classContext.getJavaClass(), method);
boolean uncallable = !AnalysisContext.currentXFactory().isCalledDirectlyOrIndirectly(xMethod) && xMethod.isPrivate();
- if (uncallable)
+ if (uncallable) {
propertySet.addProperty(GeneralWarningProperty.IN_UNCALLABLE_METHOD);
+ }
}
private boolean isDoomed(Location loc) {
@@ -1656,8 +1756,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
try {
UsagesRequiringNonNullValues usages = classContext.getUsagesRequiringNonNullValues(method);
pu = usages.get(loc, refValue, vnaDataflow);
- if (pu == null)
+ if (pu == null) {
return "SOURCE_LINE_DEREF";
+ }
return pu.getDescription();
} catch (DataflowAnalysisException e) {
AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);
@@ -1673,8 +1774,9 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
int pc = loc.getHandle().getPosition();
int catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),
"java/lang/NullPointerException", pc);
- if (catchSize < Integer.MAX_VALUE)
+ if (catchSize < Integer.MAX_VALUE) {
return true;
+ }
return false;
}
@@ -1682,18 +1784,19 @@ public class FindNullDeref implements Detector, UseAnnotationDatabase, NullDeref
int pc = loc.getHandle().getPosition();
int catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),
"java/lang/Exception", pc);
- if (catchSize < 5)
+ if (catchSize < 5) {
return true;
+ }
catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),
"java/lang/RuntimeException", pc);
- if (catchSize < 5)
+ if (catchSize < 5) {
return true;
+ }
catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),
"java/lang/Throwable", pc);
- if (catchSize < 5)
+ if (catchSize < 5) {
return true;
+ }
return false;
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindNullDerefsInvolvingNonShortCircuitEvaluation.java b/src/java/edu/umd/cs/findbugs/detect/FindNullDerefsInvolvingNonShortCircuitEvaluation.java
index f11681d..2394bca 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindNullDerefsInvolvingNonShortCircuitEvaluation.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindNullDerefsInvolvingNonShortCircuitEvaluation.java
@@ -66,11 +66,6 @@ public class FindNullDerefsInvolvingNonShortCircuitEvaluation extends OpcodeStac
}
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.bcel.OpcodeStackDetector#sawOpcode(int)
- */
@Override
public void sawOpcode(int seen) {
if (seen == IAND || seen == IOR) {
@@ -91,14 +86,16 @@ public class FindNullDerefsInvolvingNonShortCircuitEvaluation extends OpcodeStac
// null guarantees a branch
boolean nullGuaranteesZero = seen == IAND;
boolean nullGuaranteesBranch = nullGuaranteesZero ^ (nextOpcode == IFNE);
- if (DEBUG)
+ if (DEBUG) {
System.out.println(item.getPC() + " null guarantees " + nullGuaranteesBranch + " branch");
+ }
try {
CFG cfg = getClassContext().getCFG(getMethod());
Location produced = findLocation(cfg, item.getPC());
Location branch = findLocation(cfg, getPC() + 1);
- if (produced == null || branch == null)
+ if (produced == null || branch == null) {
return;
+ }
IfInstruction branchInstruction = (IfInstruction) branch.getHandle().getInstruction();
@@ -109,8 +106,9 @@ public class FindNullDerefsInvolvingNonShortCircuitEvaluation extends OpcodeStac
ValueNumberFrame valueNumberFact = valueNumberDataflow.getFactAtLocation(produced);
IsNullValueFrame isNullFact = isNullValueDataflow.getFactAtLocation(produced);
ValueNumber value = valueNumberFact.getTopValue();
- if (isNullFact.getTopValue().isDefinitelyNotNull())
+ if (isNullFact.getTopValue().isDefinitelyNotNull()) {
return;
+ }
if (DEBUG) {
System.out.println("Produced: " + produced);
System.out.println(valueNumberFact);
@@ -123,8 +121,9 @@ public class FindNullDerefsInvolvingNonShortCircuitEvaluation extends OpcodeStac
}
Location guaranteed = findLocation(cfg, nullGuaranteesBranch ? branchInstruction.getTarget() : branch.getHandle()
.getNext());
- if (guaranteed == null)
+ if (guaranteed == null) {
return;
+ }
UnconditionalValueDerefSet unconditionalDeref = unconditionalValueDerefDataflow.getFactAtLocation(guaranteed);
if (DEBUG) {
@@ -144,14 +143,16 @@ public class FindNullDerefsInvolvingNonShortCircuitEvaluation extends OpcodeStac
bug = new BugInstance(this, "NP_GUARANTEED_DEREF", NORMAL_PRIORITY).addClassAndMethod(this);
bug.addOptionalAnnotation(variableAnnotation);
bug.addSourceLine(tested).describe("SOURCE_LINE_KNOWN_NULL");
- for (Location dereferenced : unconditionalDerefLocationSet)
+ for (Location dereferenced : unconditionalDerefLocationSet) {
bug.addSourceLine(getClassContext(), getMethod(), dereferenced).describe("SOURCE_LINE_DEREF");
+ }
} else {
bug = new BugInstance(this, "NP_NULL_ON_SOME_PATH", NORMAL_PRIORITY).addClassAndMethod(this);
bug.addOptionalAnnotation(variableAnnotation);
- for (Location dereferenced : unconditionalDerefLocationSet)
+ for (Location dereferenced : unconditionalDerefLocationSet) {
bug.addSourceLine(getClassContext(), getMethod(), dereferenced).describe("SOURCE_LINE_DEREF");
+ }
bug.addSourceLine(tested).describe("SOURCE_LINE_KNOWN_NULL");
@@ -173,8 +174,9 @@ public class FindNullDerefsInvolvingNonShortCircuitEvaluation extends OpcodeStac
Location findLocation(CFG cfg, int pc) {
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location loc = i.next();
- if (loc.getHandle().getPosition() == pc)
+ if (loc.getHandle().getPosition() == pc) {
return loc;
+ }
}
return null;
}
@@ -183,8 +185,9 @@ public class FindNullDerefsInvolvingNonShortCircuitEvaluation extends OpcodeStac
Location findLocation(CFG cfg, InstructionHandle handle) {
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location loc = i.next();
- if (loc.getHandle() == handle)
+ if (loc.getHandle() == handle) {
return loc;
+ }
}
return null;
}
@@ -194,8 +197,10 @@ public class FindNullDerefsInvolvingNonShortCircuitEvaluation extends OpcodeStac
|| item.getSpecialKind() == OpcodeStack.Item.NONZERO_MEANS_NULL && seen == IOR;
}
+ /*
private void emitWarning() {
- System.out.println("Warn about " + getMethodName()); // TODO
+ System.out.println("Warn about " + getMethodName());
}
+ */
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindOpenStream.java b/src/java/edu/umd/cs/findbugs/detect/FindOpenStream.java
index 0c45a76..1ca9b00 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindOpenStream.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindOpenStream.java
@@ -59,7 +59,7 @@ import edu.umd.cs.findbugs.ba.ResourceValueFrame;
* method, and are not closed on all paths out of the method. Note that "stream"
* is a bit misleading, since we also use the detector to look for database
* resources that aren't closed.
- *
+ *
* @author David Hovemeyer
*/
public final class FindOpenStream extends ResourceTrackingDetector<Stream, StreamResourceTracker> implements StatelessDetector {
@@ -77,10 +77,10 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
* List of base classes of tracked resources.
*/
static final ObjectType[] streamBaseList = { ObjectTypeFactory.getInstance("java.io.InputStream"),
- ObjectTypeFactory.getInstance("java.io.OutputStream"), ObjectTypeFactory.getInstance("java.util.zip.ZipFile"),
- ObjectTypeFactory.getInstance("java.io.Reader"), ObjectTypeFactory.getInstance("java.io.Writer"),
- ObjectTypeFactory.getInstance("java.sql.Connection"),
- ObjectTypeFactory.getInstance("java.sql.Statement"), ObjectTypeFactory.getInstance("java.sql.ResultSet") };
+ ObjectTypeFactory.getInstance("java.io.OutputStream"), ObjectTypeFactory.getInstance("java.util.zip.ZipFile"),
+ ObjectTypeFactory.getInstance("java.io.Reader"), ObjectTypeFactory.getInstance("java.io.Writer"),
+ ObjectTypeFactory.getInstance("java.sql.Connection"),
+ ObjectTypeFactory.getInstance("java.sql.Statement"), ObjectTypeFactory.getInstance("java.sql.ResultSet") };
/**
* StreamFactory objects used to detect resources created within analyzed
@@ -96,7 +96,7 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
streamFactoryCollection.add(new IOStreamFactory("java.io.InputStream", new String[] { "java.io.ByteArrayInputStream",
"java.io.StringBufferInputStream", "java.io.PipedInputStream" }, "OS_OPEN_STREAM"));
streamFactoryCollection.add(new IOStreamFactory("java.io.OutputStream", new String[] { "java.io.ByteArrayOutputStream",
- "java.io.PipedOutputStream" }, "OS_OPEN_STREAM"));
+ "java.io.PipedOutputStream" }, "OS_OPEN_STREAM"));
streamFactoryCollection.add(new IOStreamFactory("java.io.Reader", new String[] { "java.io.StringReader",
"java.io.CharArrayReader", "java.io.PipedReader" }, "OS_OPEN_STREAM"));
streamFactoryCollection.add(new IOStreamFactory("java.io.Writer", new String[] { "java.io.StringWriter",
@@ -120,7 +120,7 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
"()Ljavax/servlet/ServletOutputStream;"));
streamFactoryCollection.add(new MethodReturnValueStreamFactory("javax.servlet.ServletResponse", "getWriter",
"()Ljava/io/PrintWriter;"));
-
+
// Ignore System.{in,out,err}
streamFactoryCollection.add(new StaticFieldLoadStreamFactory("java.io.InputStream", "java.lang.System", "in",
"Ljava/io/InputStream;"));
@@ -208,7 +208,7 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
public final int priority;
public final Stream stream;
-
+
@Override
public String toString() {
return stream.toString();
@@ -227,7 +227,7 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
* ----------------------------------------------------------------------
*/
- private List<PotentialOpenStream> potentialOpenStreamList;
+ private final List<PotentialOpenStream> potentialOpenStreamList;
/*
* ----------------------------------------------------------------------
@@ -254,11 +254,11 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
// class containing one of these words, then we don't run the
// detector on the class.
private static final String[] PRESCREEN_CLASS_LIST = { "Stream", "Reader", "Writer", "ZipFile", "JarFile", "DriverManager",
- "Connection", "Statement" };
+ "Connection", "Statement" };
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.Detector#visitClassContext(edu.umd.cs.findbugs.ba
* .ClassContext)
@@ -288,8 +288,9 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
}
if (className != null) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("FindOpenStream: saw class " + className);
+ }
for (String aPRESCREEN_CLASS_LIST : PRESCREEN_CLASS_LIST) {
if (className.indexOf(aPRESCREEN_CLASS_LIST) >= 0) {
@@ -309,8 +310,9 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
@Override
public boolean prescreen(ClassContext classContext, Method method, boolean mightClose) {
BitSet bytecodeSet = classContext.getBytecodeSet(method);
- if (bytecodeSet == null)
+ if (bytecodeSet == null) {
return false;
+ }
return bytecodeSet.get(Constants.NEW) || bytecodeSet.get(Constants.INVOKEINTERFACE)
|| bytecodeSet.get(Constants.INVOKESPECIAL) || bytecodeSet.get(Constants.INVOKESTATIC)
|| bytecodeSet.get(Constants.INVOKEVIRTUAL);
@@ -322,7 +324,7 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
}
public static boolean isMainMethod(Method method) {
- return method.isStatic() && method.getName().equals("main") && method.getSignature().equals("([Ljava/lang/String;)V");
+ return method.isStatic() && "main".equals(method.getName()) && "([Ljava/lang/String;)V".equals(method.getSignature());
}
@Override
@@ -333,8 +335,9 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
JavaClass javaClass = classContext.getJavaClass();
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
CFG cfg = classContext.getCFG(method);
// Add Streams passed into the method as parameters.
@@ -349,7 +352,7 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
for (Type type : parameterTypeList) {
if (type instanceof ObjectType) {
ObjectType objectType = (ObjectType) type;
-
+
for (ObjectType streamBase : streamBaseList) {
if (Hierarchy.isSubtype(objectType, streamBase)) {
// OK, found a parameter that is a resource.
@@ -403,8 +406,9 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
for (Iterator<Stream> i = resourceCollection.resourceIterator(); i.hasNext();) {
Stream stream = i.next();
StreamEquivalenceClass equivalenceClass = resourceTracker.getStreamEquivalenceClass(stream);
- if (stream.isClosed())
+ if (stream.isClosed()) {
equivalenceClass.setClosed();
+ }
}
// Iterate through potential open streams, reporting warnings
@@ -413,29 +417,34 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
// that was closed).
for (PotentialOpenStream pos : potentialOpenStreamList) {
Stream stream = pos.stream;
- if (stream.isClosed())
+ if (stream.isClosed()) {
// Stream was in an equivalence class with another
// stream that was properly closed.
continue;
+ }
- if (stream.isUninteresting())
+ if (stream.isUninteresting()) {
continue;
+ }
Location openLocation = stream.getOpenLocation();
- if (openLocation == null)
+ if (openLocation == null) {
continue;
+ }
- if (IGNORE_WRAPPED_UNINTERESTING_STREAMS && resourceTracker.isUninterestingStreamEscape(stream))
+ if (IGNORE_WRAPPED_UNINTERESTING_STREAMS && resourceTracker.isUninterestingStreamEscape(stream)) {
continue;
+ }
String sourceFile = javaClass.getSourceFileName();
String leakClass = stream.getStreamBase();
- if (isMainMethod(method) && (leakClass.contains("InputStream") || leakClass.contains("Reader")))
+ if (isMainMethod(method) && (leakClass.contains("InputStream") || leakClass.contains("Reader"))) {
return;
+ }
bugAccumulator.accumulateBug(new BugInstance(this, pos.bugType, pos.priority)
- .addClassAndMethod(methodGen, sourceFile).addTypeOfNamedClass(leakClass)
- .describe(TypeAnnotation.CLOSEIT_ROLE), SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
+ .addClassAndMethod(methodGen, sourceFile).addTypeOfNamedClass(leakClass)
+ .describe(TypeAnnotation.CLOSEIT_ROLE), SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
sourceFile, stream.getLocation().getHandle()));
}
}
@@ -447,7 +456,7 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
if (DEBUG) {
System.out.printf("Result for %s in %s%n", stream, methodGen);
dataflow.dumpDataflow(dataflow.getAnalysis());
-
+
}
ResourceValueFrame exitFrame = dataflow.getResultFact(cfg.getExit());
@@ -499,4 +508,3 @@ public final class FindOpenStream extends ResourceTrackingDetector<Stream, Strea
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindPuzzlers.java b/src/java/edu/umd/cs/findbugs/detect/FindPuzzlers.java
index 8470e43..ee76221 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindPuzzlers.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindPuzzlers.java
@@ -43,6 +43,7 @@ import edu.umd.cs.findbugs.OpcodeStack;
import edu.umd.cs.findbugs.OpcodeStack.Item;
import edu.umd.cs.findbugs.Priorities;
import edu.umd.cs.findbugs.SourceLineAnnotation;
+import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.XFactory;
import edu.umd.cs.findbugs.ba.XField;
@@ -64,9 +65,12 @@ public class FindPuzzlers extends OpcodeStackDetector {
final BugAccumulator bugAccumulator;
+ private final boolean testingEnabled;
+
public FindPuzzlers(BugReporter bugReporter) {
this.bugReporter = bugReporter;
this.bugAccumulator = new BugAccumulator(bugReporter);
+ testingEnabled = SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors");
}
@Override
@@ -111,10 +115,10 @@ public class FindPuzzlers extends OpcodeStackDetector {
XMethod previousMethodInvocation;
boolean isTigerOrHigher;
-
+
static ClassDescriptor ITERATOR = DescriptorFactory.createClassDescriptor(Iterator.class);
static ClassDescriptor MAP_ENTRY = DescriptorFactory.createClassDescriptor(Map.Entry.class);
-
+
@Override
public void visit(JavaClass obj) {
@@ -137,22 +141,26 @@ public class FindPuzzlers extends OpcodeStackDetector {
}
private int adjustPriority(int factor, int priority) {
- if (factor <= 4)
+ if (factor <= 4) {
return LOW_PRIORITY + 2;
- if (factor <= 10000)
+ }
+ if (factor <= 10000) {
return priority + 1;
- if (factor <= 60 * 60 * 1000)
+ }
+ if (factor <= 60 * 60 * 1000) {
return priority;
+ }
return priority - 1;
}
private int adjustMultiplier(Object constant, int mul) {
- if (!(constant instanceof Integer))
+ if (!(constant instanceof Integer)) {
return mul;
+ }
return Math.abs(((Integer) constant).intValue()) * mul;
}
-
+
@Override
public boolean beforeOpcode(int seen) {
super.beforeOpcode(seen);
@@ -163,37 +171,39 @@ public class FindPuzzlers extends OpcodeStackDetector {
@Override
public void sawOpcode(int seen) {
-
+
if (stack.isTop()) {
pendingUnreachableBranch = null;
- if (becameTop == -1)
+ if (becameTop == -1) {
becameTop = getPC();
- if (seen == GOTO && getBranchTarget() < becameTop) {
+ }
+ if (testingEnabled && seen == GOTO && getBranchTarget() < becameTop) {
pendingUnreachableBranch = new BugInstance(this, "TESTING", NORMAL_PRIORITY)
.addClassAndMethod(this).addString("Unreachable loop body").addSourceLineRange(this, becameTop, getPC());
}
return;
-
+
}
if (pendingUnreachableBranch != null) {
- bugReporter.reportBug(pendingUnreachableBranch);
- pendingUnreachableBranch = null;
+ bugReporter.reportBug(pendingUnreachableBranch);
+ pendingUnreachableBranch = null;
}
becameTop = -1;
- if (seen == INVOKESPECIAL && getNameConstantOperand().equals("<init>") && getSigConstantOperand().equals("(Ljava/util/Collection;)V")
- && getClassConstantOperand().contains("Set")
- || (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) && getNameConstantOperand().equals("addAll") && getSigConstantOperand().equals("(Ljava/util/Collection;)Z")) {
+ if (seen == INVOKESPECIAL && "<init>".equals(getNameConstantOperand()) && "(Ljava/util/Collection;)V".equals(getSigConstantOperand())
+ && getClassConstantOperand().contains("Set")
+ || (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) && "addAll".equals(getNameConstantOperand()) && "(Ljava/util/Collection;)Z".equals(getSigConstantOperand())) {
OpcodeStack.Item top = stack.getStackItem(0);
XMethod returnValueOf = top.getReturnValueOf();
- if (returnValueOf != null && returnValueOf.getName().equals("entrySet")) {
+ if (returnValueOf != null && "entrySet".equals(returnValueOf.getName())) {
String name = returnValueOf.getClassName();
int priority = Priorities.LOW_PRIORITY;
- if (name.equals("java.util.Map"))
+ if ("java.util.Map".equals(name)) {
priority = Priorities.NORMAL_PRIORITY;
- else if (name.equals(EnumMap.class.getName())
- || name.equals(IdentityHashMap.class.getName()))
+ } else if (name.equals(EnumMap.class.getName())
+ || name.equals(IdentityHashMap.class.getName())) {
priority = Priorities.HIGH_PRIORITY;
+ }
bugReporter.reportBug(new BugInstance(this, "DMI_ENTRY_SETS_MAY_REUSE_ENTRY_OBJECTS", priority)
.addClassAndMethod(this).addCalledMethod(returnValueOf).addCalledMethod(this).addValueSource(top, this).addSourceLine(this));
}
@@ -201,23 +211,26 @@ public class FindPuzzlers extends OpcodeStackDetector {
}
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("hashCode") && getSigConstantOperand().equals("()I")
+ if (seen == INVOKEVIRTUAL && "hashCode".equals(getNameConstantOperand()) && "()I".equals(getSigConstantOperand())
&& stack.getStackDepth() > 0) {
OpcodeStack.Item item0 = stack.getStackItem(0);
- if (item0.getSignature().charAt(0) == '[')
+ if (item0.getSignature().charAt(0) == '[') {
bugReporter.reportBug(new BugInstance(this, "DMI_INVOKING_HASHCODE_ON_ARRAY", NORMAL_PRIORITY)
- .addClassAndMethod(this).addValueSource(item0, this).addSourceLine(this));
+ .addClassAndMethod(this).addValueSource(item0, this).addSourceLine(this));
+ }
}
if (seen != RETURN && isReturn(seen) && isRegisterStore(getPrevOpcode(1))) {
int priority = Priorities.NORMAL_PRIORITY;
- if (getMethodSig().endsWith(")Z"))
+ if (getMethodSig().endsWith(")Z")) {
priority = Priorities.HIGH_PRIORITY;
- else {
- if (getMethodSig().endsWith(")Ljava/lang/String;"))
+ } else {
+ if (getMethodSig().endsWith(")Ljava/lang/String;")) {
priority = Priorities.LOW_PRIORITY;
- if (getPC() == getCode().getCode().length - 1)
+ }
+ if (getPC() == getCode().getCode().length - 1) {
priority++;
+ }
}
bugReporter.reportBug(new BugInstance(this, "DLS_DEAD_LOCAL_STORE_IN_RETURN", priority).addClassAndMethod(this)
.addSourceLine(this));
@@ -225,8 +238,9 @@ public class FindPuzzlers extends OpcodeStackDetector {
// System.out.println(getPC() + " " + OPCODE_NAMES[seen] + " " +
// ternaryConversionState);
if (seen == IMUL) {
- if (imul_distance != 1)
+ if (imul_distance != 1) {
resetIMulCastLong();
+ }
imul_distance = 0;
if (stack.getStackDepth() > 1) {
OpcodeStack.Item item0 = stack.getStackItem(0);
@@ -234,8 +248,9 @@ public class FindPuzzlers extends OpcodeStackDetector {
imul_constant = adjustMultiplier(item0.getConstant(), imul_constant);
imul_constant = adjustMultiplier(item1.getConstant(), imul_constant);
- if (item0.isInitialParameter() || item1.isInitialParameter())
+ if (item0.isInitialParameter() || item1.isInitialParameter()) {
imul_operand_is_parameter = true;
+ }
}
} else {
imul_distance++;
@@ -243,8 +258,9 @@ public class FindPuzzlers extends OpcodeStackDetector {
if (prevOpCode == IMUL && seen == I2L) {
int priority = adjustPriority(imul_constant, NORMAL_PRIORITY);
- if (priority >= LOW_PRIORITY && imul_constant != 1000 && imul_constant != 60 && imul_operand_is_parameter)
+ if (priority >= LOW_PRIORITY && imul_constant != 1000 && imul_constant != 60 && imul_operand_is_parameter) {
priority = NORMAL_PRIORITY;
+ }
if (priority <= best_priority_for_ICAST_INTEGER_MULTIPLY_CAST_TO_LONG) {
best_priority_for_ICAST_INTEGER_MULTIPLY_CAST_TO_LONG = priority;
bugAccumulator.accumulateBug(
@@ -252,17 +268,19 @@ public class FindPuzzlers extends OpcodeStackDetector {
}
}
- if (getMethodName().equals("<clinit>") && (seen == PUTSTATIC || seen == GETSTATIC || seen == INVOKESTATIC)) {
+ if ("<clinit>".equals(getMethodName()) && (seen == PUTSTATIC || seen == GETSTATIC || seen == INVOKESTATIC)) {
String clazz = getClassConstantOperand();
if (!clazz.equals(getClassName())) {
try {
JavaClass targetClass = Repository.lookupClass(clazz);
if (Repository.instanceOf(targetClass, getThisClass())) {
int priority = NORMAL_PRIORITY;
- if (seen == GETSTATIC)
+ if (seen == GETSTATIC) {
priority--;
- if (!targetClass.isPublic())
+ }
+ if (!targetClass.isPublic()) {
priority++;
+ }
bugAccumulator.accumulateBug(new BugInstance(this, "IC_SUPERCLASS_USES_SUBCLASS_DURING_INITIALIZATION",
priority).addClassAndMethod(this).addClass(getClassConstantOperand()), this);
@@ -273,6 +291,7 @@ public class FindPuzzlers extends OpcodeStackDetector {
}
}
+ /*
if (false && (seen == INVOKEVIRTUAL) && getNameConstantOperand().equals("equals")
&& getSigConstantOperand().equals("(Ljava/lang/Object;)Z") && stack.getStackDepth() > 1) {
OpcodeStack.Item item0 = stack.getStackItem(0);
@@ -283,15 +302,17 @@ public class FindPuzzlers extends OpcodeStackDetector {
new BugInstance(this, "EC_BAD_ARRAY_COMPARE", NORMAL_PRIORITY).addClassAndMethod(this), this);
}
}
+ */
if (seen >= IALOAD && seen <= SALOAD || seen >= IASTORE && seen <= SASTORE) {
Item index = stack.getStackItem(0);
if (index.getSpecialKind() == Item.AVERAGE_COMPUTED_USING_DIVISION) {
SourceLineAnnotation where;
- if (index.getPC() >= 0)
+ if (index.getPC() >= 0) {
where = SourceLineAnnotation.fromVisitedInstruction(this, index.getPC());
- else
+ } else {
where = SourceLineAnnotation.fromVisitedInstruction(this);
+ }
bugAccumulator.accumulateBug(
new BugInstance(this, "IM_AVERAGE_COMPUTATION_COULD_OVERFLOW", NORMAL_PRIORITY).addClassAndMethod(this),
where);
@@ -300,19 +321,53 @@ public class FindPuzzlers extends OpcodeStackDetector {
}
if ((seen == IFEQ || seen == IFNE) && getPrevOpcode(1) == IMUL
- && (getPrevOpcode(2) == SIPUSH || getPrevOpcode(2) == BIPUSH) && getPrevOpcode(3) == IREM)
+ && (getPrevOpcode(2) == SIPUSH || getPrevOpcode(2) == BIPUSH) && getPrevOpcode(3) == IREM) {
bugAccumulator.accumulateBug(
new BugInstance(this, "IM_MULTIPLYING_RESULT_OF_IREM", LOW_PRIORITY).addClassAndMethod(this), this);
+ }
if (seen == I2S && getPrevOpcode(1) == IUSHR && !shiftOfNonnegativeValue
&& (!constantArgumentToShift || valueOfConstantArgumentToShift % 16 != 0) || seen == I2B
&& getPrevOpcode(1) == IUSHR && !shiftOfNonnegativeValue
- && (!constantArgumentToShift || valueOfConstantArgumentToShift % 8 != 0))
-
+ && (!constantArgumentToShift || valueOfConstantArgumentToShift % 8 != 0)) {
bugAccumulator.accumulateBug(
new BugInstance(this, "ICAST_QUESTIONABLE_UNSIGNED_RIGHT_SHIFT", NORMAL_PRIORITY).addClassAndMethod(this),
this);
+ }
+
+
+ if (seen == IADD && (getNextOpcode() == ISHL || getNextOpcode() == LSHL) && stack.getStackDepth() >=3) {
+ OpcodeStack.Item l = stack.getStackItem(2);
+ OpcodeStack.Item v = stack.getStackItem(1);
+ Object constantValue = v.getConstant();
+ // Ignore 1 << (const + var) as it's usually intended
+ if (constantValue instanceof Integer && !Integer.valueOf(1).equals(l.getConstant())) {
+ int c = ((Integer) constantValue).intValue();
+ int priority = LOW_PRIORITY;
+ // If (foo << 32 + var) encountered, then ((foo << 32) + var) is absolutely meaningless,
+ // but (foo << (32 + var)) can be meaningful for negative var values
+ if (c < 32 || (c < 64 && getNextOpcode() == LSHL)) {
+ if (c == 8) {
+ priority--;
+ }
+ if (getPrevOpcode(1) == IAND) {
+ priority--;
+ }
+ if (getMethodName().equals("hashCode") && getMethodSig().equals("()I")
+ && (getCode().getCode()[getNextPC() + 1] & 0xFF) == IRETURN) {
+ // commonly observed error is hashCode body like "return foo << 16 + bar;"
+ priority = HIGH_PRIORITY;
+ }
+ bugAccumulator.accumulateBug(new BugInstance(this, "BSHIFT_WRONG_ADD_PRIORITY", priority)
+ .addClassAndMethod(this)
+ .addInt(c).describe(IntAnnotation.INT_SHIFT)
+ .addValueSource(stack.getStackItem(2), this)
+ .addValueSource(stack.getStackItem(0), this)
+ , this);
+ }
+ }
+ }
constantArgumentToShift = false;
shiftOfNonnegativeValue = false;
if ((seen == IUSHR || seen == ISHR || seen == ISHL)) {
@@ -328,12 +383,13 @@ public class FindPuzzlers extends OpcodeStackDetector {
if (rightHandSide instanceof Integer) {
constantArgumentToShift = true;
valueOfConstantArgumentToShift = ((Integer) rightHandSide);
- if (valueOfConstantArgumentToShift < 0 || valueOfConstantArgumentToShift >= 32)
+ if (valueOfConstantArgumentToShift < 0 || valueOfConstantArgumentToShift >= 32) {
bugAccumulator.accumulateBug(new BugInstance(this, "ICAST_BAD_SHIFT_AMOUNT",
valueOfConstantArgumentToShift < 0 ? LOW_PRIORITY : (valueOfConstantArgumentToShift == 32
- && getMethodName().equals("hashCode") ? NORMAL_PRIORITY : HIGH_PRIORITY))
- .addClassAndMethod(this).addInt(valueOfConstantArgumentToShift).describe(IntAnnotation.INT_SHIFT)
- .addValueSource(stack.getStackItem(1), this), this);
+ && "hashCode".equals(getMethodName()) ? NORMAL_PRIORITY : HIGH_PRIORITY))
+ .addClassAndMethod(this).addInt(valueOfConstantArgumentToShift).describe(IntAnnotation.INT_SHIFT)
+ .addValueSource(stack.getStackItem(1), this), this);
+ }
}
if (leftHandSide != null && leftHandSide instanceof Integer && ((Integer) leftHandSide) > 0) {
// boring; lie so other detectors won't get concerned
@@ -345,25 +401,26 @@ public class FindPuzzlers extends OpcodeStackDetector {
}
if (seen == INVOKEVIRTUAL && stack.getStackDepth() > 0
- && (getClassConstantOperand().equals("java/util/Date") || getClassConstantOperand().equals("java/sql/Date"))
- && getNameConstantOperand().equals("setMonth") && getSigConstantOperand().equals("(I)V")) {
+ && ("java/util/Date".equals(getClassConstantOperand()) || "java/sql/Date".equals(getClassConstantOperand()))
+ && "setMonth".equals(getNameConstantOperand()) && "(I)V".equals(getSigConstantOperand())) {
OpcodeStack.Item item = stack.getStackItem(0);
Object o = item.getConstant();
if (o != null && o instanceof Integer) {
int v = (Integer) o;
- if (v < 0 || v > 11)
+ if (v < 0 || v > 11) {
bugReporter.reportBug(new BugInstance(this, "DMI_BAD_MONTH", HIGH_PRIORITY).addClassAndMethod(this).addInt(v)
.describe(IntAnnotation.INT_VALUE).addCalledMethod(this).addSourceLine(this));
+ }
}
}
- if (seen == INVOKEVIRTUAL && stack.getStackDepth() > 1 && getClassConstantOperand().equals("java/util/Calendar")
- && getNameConstantOperand().equals("set")
+ if (seen == INVOKEVIRTUAL && stack.getStackDepth() > 1 && "java/util/Calendar".equals(getClassConstantOperand())
+ && "set".equals(getNameConstantOperand())
|| seen == INVOKESPECIAL && stack.getStackDepth() > 1
- && getClassConstantOperand().equals("java/util/GregorianCalendar") && getNameConstantOperand().equals("<init>")
+ && "java/util/GregorianCalendar".equals(getClassConstantOperand()) && "<init>".equals(getNameConstantOperand())
- ) {
+ ) {
String sig = getSigConstantOperand();
if (sig.startsWith("(III")) {
int pos = sig.length() - 5;
@@ -371,9 +428,10 @@ public class FindPuzzlers extends OpcodeStackDetector {
Object o = item.getConstant();
if (o != null && o instanceof Integer) {
int v = (Integer) o;
- if (v < 0 || v > 11)
+ if (v < 0 || v > 11) {
bugReporter.reportBug(new BugInstance(this, "DMI_BAD_MONTH", NORMAL_PRIORITY).addClassAndMethod(this)
.addInt(v).describe(IntAnnotation.INT_VALUE).addCalledMethod(this).addSourceLine(this));
+ }
}
}
}
@@ -386,32 +444,37 @@ public class FindPuzzlers extends OpcodeStackDetector {
}
if (seen == IINC) {
prevOpcodeIncrementedRegister = getRegisterOperand();
- } else
+ } else {
prevOpcodeIncrementedRegister = -1;
+ }
// Java Puzzlers, Chapter 2, puzzle 1
// Look for ICONST_2 IREM ICONST_1 IF_ICMPNE L1
switch (badlyComputingOddState) {
case 0:
- if (seen == ICONST_2)
+ if (seen == ICONST_2) {
badlyComputingOddState++;
+ }
break;
case 1:
if (seen == IREM) {
OpcodeStack.Item item = stack.getStackItem(1);
- if (!item.isNonNegative() && item.getSpecialKind() != OpcodeStack.Item.MATH_ABS)
+ if (!item.isNonNegative() && item.getSpecialKind() != OpcodeStack.Item.MATH_ABS) {
badlyComputingOddState++;
- else
+ } else {
badlyComputingOddState = 0;
- } else
+ }
+ } else {
badlyComputingOddState = 0;
+ }
break;
case 2:
- if (seen == ICONST_1)
+ if (seen == ICONST_1) {
badlyComputingOddState++;
- else
+ } else {
badlyComputingOddState = 0;
+ }
break;
case 3:
if (seen == IF_ICMPEQ || seen == IF_ICMPNE) {
@@ -420,43 +483,47 @@ public class FindPuzzlers extends OpcodeStackDetector {
}
badlyComputingOddState = 0;
break;
+ default:
+ break;
}
// Java Puzzlers, chapter 3, puzzle 12
if (seen == INVOKEVIRTUAL
&& stack.getStackDepth() > 0
- && (getNameConstantOperand().equals("toString") && getSigConstantOperand().equals("()Ljava/lang/String;")
- || getNameConstantOperand().equals("append")
- && getSigConstantOperand().equals("(Ljava/lang/Object;)Ljava/lang/StringBuilder;")
- && getClassConstantOperand().equals("java/lang/StringBuilder")
- || getNameConstantOperand().equals("append")
- && getSigConstantOperand().equals("(Ljava/lang/Object;)Ljava/lang/StringBuffer;")
- && getClassConstantOperand().equals("java/lang/StringBuffer") || (getNameConstantOperand()
- .equals("print") || getNameConstantOperand().equals("println"))
- && getSigConstantOperand().equals("(Ljava/lang/Object;)V"))) {
+ && ("toString".equals(getNameConstantOperand()) && "()Ljava/lang/String;".equals(getSigConstantOperand())
+ || "append".equals(getNameConstantOperand())
+ && "(Ljava/lang/Object;)Ljava/lang/StringBuilder;".equals(getSigConstantOperand())
+ && "java/lang/StringBuilder".equals(getClassConstantOperand())
+ || "append".equals(getNameConstantOperand())
+ && "(Ljava/lang/Object;)Ljava/lang/StringBuffer;".equals(getSigConstantOperand())
+ && "java/lang/StringBuffer".equals(getClassConstantOperand()) || ("print".equals(getNameConstantOperand()) || "println".equals(getNameConstantOperand()))
+ && "(Ljava/lang/Object;)V".equals(getSigConstantOperand()))) {
OpcodeStack.Item item = stack.getStackItem(0);
String signature = item.getSignature();
if (signature != null && signature.startsWith("[")) {
- boolean debuggingContext = signature.equals("[Ljava/lang/StackTraceElement;");
+ boolean debuggingContext = "[Ljava/lang/StackTraceElement;".equals(signature);
if (!debuggingContext) {
for (CodeException e : getCode().getExceptionTable()) {
- if (e.getHandlerPC() <= getPC() && e.getHandlerPC() + 30 >= getPC())
+ if (e.getHandlerPC() <= getPC() && e.getHandlerPC() + 30 >= getPC()) {
debuggingContext = true;
+ }
}
for (int i = 1; !debuggingContext && i < stack.getStackDepth(); i++) {
OpcodeStack.Item e = stack.getStackItem(i);
- if (e.getSignature().indexOf("Logger") >= 0 || e.getSignature().indexOf("Exception") >= 0)
+ if (e.getSignature().indexOf("Logger") >= 0 || e.getSignature().indexOf("Exception") >= 0) {
debuggingContext = true;
+ }
XField f = e.getXField();
- if (f != null && (SYSTEM_ERR.equals(f.getFieldDescriptor()) || SYSTEM_OUT.equals(f.getFieldDescriptor())))
+ if (f != null && (SYSTEM_ERR.equals(f.getFieldDescriptor()) || SYSTEM_OUT.equals(f.getFieldDescriptor()))) {
debuggingContext = true;
+ }
}
}
- String name = null;
+ // String name = null;
int reg = item.getRegisterNumber();
Collection<BugAnnotation> as = new ArrayList<BugAnnotation>();
XField field = item.getXField();
@@ -471,16 +538,18 @@ public class FindPuzzlers extends OpcodeStackDetector {
getPC() - 1);
if (lva.isNamed()) {
as.add(lva);
- if (fieldAnnotation != null)
+ if (fieldAnnotation != null) {
as.add(fieldAnnotation);
+ }
} else {
- if (fieldAnnotation != null)
+ if (fieldAnnotation != null) {
as.add(fieldAnnotation);
+ }
as.add(lva);
}
- } else if (fieldAnnotation != null)
+ } else if (fieldAnnotation != null) {
as.add(fieldAnnotation);
- else {
+ } else {
XMethod m = item.getReturnValueOf();
if (m != null) {
MethodAnnotation methodAnnotation = MethodAnnotation.fromXMethod(m);
@@ -491,7 +560,7 @@ public class FindPuzzlers extends OpcodeStackDetector {
int priority = debuggingContext ? NORMAL_PRIORITY : HIGH_PRIORITY;
if (!as.isEmpty()) {
bugAccumulator.accumulateBug(new BugInstance(this, "DMI_INVOKING_TOSTRING_ON_ARRAY", priority)
- .addClassAndMethod(this).addAnnotations(as), this);
+ .addClassAndMethod(this).addAnnotations(as), this);
} else {
bugAccumulator.accumulateBug(
new BugInstance(this, "DMI_INVOKING_TOSTRING_ON_ANONYMOUS_ARRAY", priority).addClassAndMethod(this),
@@ -508,12 +577,13 @@ public class FindPuzzlers extends OpcodeStackDetector {
&& classNameForPreviousMethod.equals(classNameForThisMethod.replace('/', '.'))
&& previousMethodInvocation.getName().endsWith("Value")
&& previousMethodInvocation.getSignature().length() == 3
- && getNameConstantOperand().equals("valueOf")
- && getSigConstantOperand().charAt(1) == previousMethodInvocation.getSignature().charAt(2))
- bugAccumulator.accumulateBug(
- new BugInstance(this, "BX_UNBOXING_IMMEDIATELY_REBOXED", NORMAL_PRIORITY).addClassAndMethod(this)
- .addCalledMethod(this),
- this);
+ && "valueOf".equals(getNameConstantOperand())
+ && getSigConstantOperand().charAt(1) == previousMethodInvocation.getSignature().charAt(2)) {
+ bugAccumulator.accumulateBug(
+ new BugInstance(this, "BX_UNBOXING_IMMEDIATELY_REBOXED", NORMAL_PRIORITY).addClassAndMethod(this)
+ .addCalledMethod(this),
+ this);
+ }
}
@@ -523,42 +593,47 @@ public class FindPuzzlers extends OpcodeStackDetector {
if (classNameForPreviousMethod.startsWith("java.lang.")
&& classNameForPreviousMethod.equals(classNameForThisMethod.replace('/', '.'))
&& getNameConstantOperand().endsWith("Value") && getSigConstantOperand().length() == 3) {
- if (getSigConstantOperand().charAt(2) == previousMethodInvocation.getSignature().charAt(1))
+ if (getSigConstantOperand().charAt(2) == previousMethodInvocation.getSignature().charAt(1)) {
bugAccumulator.accumulateBug(
new BugInstance(this, "BX_BOXING_IMMEDIATELY_UNBOXED", NORMAL_PRIORITY).addClassAndMethod(this),
this);
-
- else
+ } else {
bugAccumulator.accumulateBug(new BugInstance(this, "BX_BOXING_IMMEDIATELY_UNBOXED_TO_PERFORM_COERCION",
NORMAL_PRIORITY).addClassAndMethod(this), this);
+ }
ternaryConversionState = 1;
- } else
+ } else {
ternaryConversionState = 0;
+ }
} else if (seen == INVOKEVIRTUAL) {
if (getClassConstantOperand().startsWith("java/lang") && getNameConstantOperand().endsWith("Value")
- && getSigConstantOperand().length() == 3)
+ && getSigConstantOperand().length() == 3) {
ternaryConversionState = 1;
- else
+ } else {
ternaryConversionState = 0;
+ }
} else if (ternaryConversionState == 1) {
- if (I2L < seen && seen <= I2S)
+ if (I2L < seen && seen <= I2S) {
ternaryConversionState = 2;
- else
+ } else {
ternaryConversionState = 0;
+ }
} else if (ternaryConversionState == 2) {
ternaryConversionState = 0;
- if (seen == GOTO)
+ if (seen == GOTO) {
bugReporter.reportBug(new BugInstance(this, "BX_UNBOXED_AND_COERCED_FOR_TERNARY_OPERATOR", NORMAL_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
- } else
+ .addClassAndMethod(this).addSourceLine(this));
+ }
+ } else {
ternaryConversionState = 0;
+ }
}
- AssertInvokedFromRun: if (seen == INVOKESTATIC)
+ AssertInvokedFromRun: if (seen == INVOKESTATIC) {
if ((getNameConstantOperand().startsWith("assert") || getNameConstantOperand().startsWith("fail"))
- && getMethodName().equals("run") && implementsRunnable(getThisClass())) {
+ && "run".equals(getMethodName()) && implementsRunnable(getThisClass())) {
int size1 = Util.getSizeOfSurroundingTryBlock(getConstantPool(), getMethod().getCode(), "java/lang/Throwable",
getPC());
int size2 = Util.getSizeOfSurroundingTryBlock(getConstantPool(), getMethod().getCode(), "java/lang/Error",
@@ -571,8 +646,9 @@ public class FindPuzzlers extends OpcodeStackDetector {
if (!dottedClassName.startsWith("junit")) {
try {
JavaClass targetClass = AnalysisContext.currentAnalysisContext().lookupClass(dottedClassName);
- if (!targetClass.getSuperclassName().startsWith("junit"))
+ if (!targetClass.getSuperclassName().startsWith("junit")) {
break AssertInvokedFromRun;
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
break AssertInvokedFromRun;
@@ -585,21 +661,22 @@ public class FindPuzzlers extends OpcodeStackDetector {
}
}
+ }
if (seen == INVOKESPECIAL && getClassConstantOperand().startsWith("java/lang/")
- && getNameConstantOperand().equals("<init>") && getSigConstantOperand().length() == 4)
-
+ && "<init>".equals(getNameConstantOperand()) && getSigConstantOperand().length() == 4) {
previousMethodInvocation = XFactory.createReferencedXMethod(this);
- else if (seen == INVOKESTATIC && getClassConstantOperand().startsWith("java/lang/")
- && getNameConstantOperand().equals("valueOf") && getSigConstantOperand().length() == 4)
+ } else if (seen == INVOKESTATIC && getClassConstantOperand().startsWith("java/lang/")
+ && "valueOf".equals(getNameConstantOperand()) && getSigConstantOperand().length() == 4) {
previousMethodInvocation = XFactory.createReferencedXMethod(this);
- else if (seen == INVOKEVIRTUAL && getClassConstantOperand().startsWith("java/lang/")
+ } else if (seen == INVOKEVIRTUAL && getClassConstantOperand().startsWith("java/lang/")
&& getNameConstantOperand().endsWith("Value")
- && getSigConstantOperand().length() == 3)
+ && getSigConstantOperand().length() == 3) {
previousMethodInvocation = XFactory.createReferencedXMethod(this);
- else
+ } else {
previousMethodInvocation = null;
+ }
- if (seen == IAND || seen == LAND) {
+ if (testingEnabled && seen == IAND || seen == LAND) {
OpcodeStack.Item rhs = stack.getStackItem(0);
OpcodeStack.Item lhs = stack.getStackItem(1);
Object constant = rhs.getConstant();
@@ -611,10 +688,11 @@ public class FindPuzzlers extends OpcodeStackDetector {
if (constant instanceof Number && (seen == LAND || value.getSpecialKind() == OpcodeStack.Item.RESULT_OF_L2I)) {
long constantValue = ((Number) constant).longValue();
if ((constantValue == 0xEFFFFFFFL || constantValue == 0xEFFFFFFFFFFFFFFFL || seen == IAND
- && constantValue == 0xEFFFFFFF))
+ && constantValue == 0xEFFFFFFF)) {
bugAccumulator.accumulateBug(new BugInstance(this, "TESTING", seen == LAND ? HIGH_PRIORITY : NORMAL_PRIORITY)
- .addClassAndMethod(this).addString("Possible failed attempt to mask lower 31 bits of an int")
- .addValueSource(value, this), this);
+ .addClassAndMethod(this).addString("Possible failed attempt to mask lower 31 bits of an int")
+ .addValueSource(value, this), this);
+ }
}
}
@@ -623,21 +701,14 @@ public class FindPuzzlers extends OpcodeStackDetector {
OpcodeStack.Item top = stack.getStackItem(0);
XMethod m = top.getReturnValueOf();
if (m != null) {
- if (m.getName().equals("compareTo") || m.getName().equals("compare"))
+ if ("compareTo".equals(m.getName()) || "compare".equals(m.getName())) {
bugAccumulator.accumulateBug(new BugInstance(this, "RV_NEGATING_RESULT_OF_COMPARETO", NORMAL_PRIORITY)
.addClassAndMethod(this)
.addCalledMethod(m).addValueSource(top, this), this);
+ }
}
}
- if (seen == IRETURN && (getMethod().getName().equals("compareTo") || getMethod().getName().equals("compare"))) {
- OpcodeStack.Item top = stack.getStackItem(0);
- Object o = top.getConstant();
- if (o instanceof Integer && ((Integer)o).intValue() == Integer.MIN_VALUE)
- bugAccumulator.accumulateBug(new BugInstance(this, "CO_COMPARETO_RESULTS_MIN_VALUE", NORMAL_PRIORITY)
- .addClassAndMethod(this), this);
-
- }
prevOpCode = seen;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindRefComparison.java b/src/java/edu/umd/cs/findbugs/detect/FindRefComparison.java
index 88c9402..de559d0 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindRefComparison.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindRefComparison.java
@@ -123,7 +123,7 @@ import edu.umd.cs.findbugs.util.ClassName;
public class FindRefComparison implements Detector, ExtendedTypes {
private static final boolean DEBUG = SystemProperties.getBoolean("frc.debug");
- private static final boolean REPORT_ALL_REF_COMPARISONS = true || SystemProperties.getBoolean("findbugs.refcomp.reportAll");
+ private static final boolean REPORT_ALL_REF_COMPARISONS = true /*|| SystemProperties.getBoolean("findbugs.refcomp.reportAll")*/;
private static final int BASE_ES_PRIORITY = SystemProperties.getInt("es.basePriority", NORMAL_PRIORITY);
@@ -179,7 +179,7 @@ public class FindRefComparison implements Detector, ExtendedTypes {
private static final byte T_PARAMETER_STRING = T_AVAIL_TYPE + 2;
- private static final byte T_STATIC_FINAL_PUBLIC_CONSTANT = T_AVAIL_TYPE + 3;
+ // private static final byte T_STATIC_FINAL_PUBLIC_CONSTANT = T_AVAIL_TYPE + 3;
private static final String STRING_SIGNATURE = "Ljava/lang/String;";
@@ -187,16 +187,7 @@ public class FindRefComparison implements Detector, ExtendedTypes {
* @author pugh
*/
private final static class SpecialTypeAnalysis extends TypeAnalysis {
- /**
- * @param method
- * @param methodGen
- * @param cfg
- * @param dfs
- * @param typeMerger
- * @param visitor
- * @param lookupFailureCallback
- * @param exceptionSetFactory
- */
+
private SpecialTypeAnalysis(Method method, MethodGen methodGen, CFG cfg, DepthFirstSearch dfs, TypeMerger typeMerger,
TypeFrameModelingVisitor visitor, RepositoryLookupFailureCallback lookupFailureCallback,
ExceptionSetFactory exceptionSetFactory) {
@@ -266,10 +257,12 @@ public class FindRefComparison implements Detector, ExtendedTypes {
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (!(obj instanceof FinalConstant))
+ }
+ if (!(obj instanceof FinalConstant)) {
return false;
+ }
FinalConstant other = (FinalConstant) obj;
return super.equals(other) && this.field.equals(other.field);
@@ -411,7 +404,7 @@ public class FindRefComparison implements Detector, ExtendedTypes {
consumeStack(obj);
String className = obj.getClassName(getCPG());
- if (className.equals("java.lang.String")) {
+ if ("java.lang.String".equals(className)) {
pushValue(dynamicStringTypeInstance);
} else {
pushReturnType(obj);
@@ -423,27 +416,30 @@ public class FindRefComparison implements Detector, ExtendedTypes {
@Override
public void visitINVOKESPECIAL(INVOKESPECIAL obj) {
- if (returnsString(obj))
+ if (returnsString(obj)) {
handleInstanceMethod(obj);
- else
+ } else {
super.visitINVOKESPECIAL(obj);
+ }
}
@Override
public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) {
- if (returnsString(obj))
+ if (returnsString(obj)) {
handleInstanceMethod(obj);
- else
+ } else {
super.visitINVOKEINTERFACE(obj);
+ }
}
@Override
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) {
- if (returnsString(obj))
+ if (returnsString(obj)) {
handleInstanceMethod(obj);
- else
+ } else {
super.visitINVOKEVIRTUAL(obj);
+ }
}
private boolean returnsString(InvokeInstruction inv) {
@@ -459,10 +455,10 @@ public class FindRefComparison implements Detector, ExtendedTypes {
String methodName = obj.getName(getCPG());
// System.out.println(className + "." + methodName);
- if (methodName.equals("intern") && className.equals("java.lang.String")) {
+ if ("intern".equals(methodName) && "java.lang.String".equals(className)) {
sawStringIntern = true;
pushValue(staticStringTypeInstance);
- } else if (methodName.equals("toString") || className.equals("java.lang.String")) {
+ } else if ("toString".equals(methodName) || "java.lang.String".equals(className)) {
pushValue(dynamicStringTypeInstance);
// System.out.println(" dynamic");
} else {
@@ -476,11 +472,14 @@ public class FindRefComparison implements Detector, ExtendedTypes {
Type type = obj.getType(getCPG());
if (isString(type)) {
Object value = obj.getValue(getCPG());
- if (value instanceof String && ((String)value).length() == 0)
+ if (value instanceof String && ((String)value).length() == 0) {
pushValue( emptyStringTypeInstance);
- else pushValue( staticStringTypeInstance);
+ } else {
+ pushValue( staticStringTypeInstance);
+ }
+ } else {
+ pushValue(type);
}
- else pushValue(type);
}
@Override
@@ -490,7 +489,7 @@ public class FindRefComparison implements Detector, ExtendedTypes {
}
private boolean isString(Type type) {
- return type.getSignature().equals(STRING_SIGNATURE);
+ return STRING_SIGNATURE.equals(type.getSignature());
}
@Override
@@ -517,16 +516,17 @@ public class FindRefComparison implements Detector, ExtendedTypes {
}
}
- if (type.getSignature().equals(STRING_SIGNATURE)) {
+ if (STRING_SIGNATURE.equals(type.getSignature())) {
handleLoad(obj);
- } else
+ } else {
super.visitGETSTATIC(obj);
+ }
}
@Override
public void visitGETFIELD(GETFIELD obj) {
Type type = obj.getType(getCPG());
- if (type.getSignature().equals(STRING_SIGNATURE)) {
+ if (STRING_SIGNATURE.equals(type.getSignature())) {
handleLoad(obj);
} else {
XField xf = XFactory.createXField(obj, cpg);
@@ -558,8 +558,9 @@ public class FindRefComparison implements Detector, ExtendedTypes {
consumeStack(obj);
Type type = obj.getType(getCPG());
- if (!type.getSignature().equals(STRING_SIGNATURE))
+ if (!STRING_SIGNATURE.equals(type.getSignature())) {
throw new IllegalArgumentException("type is not String: " + type);
+ }
try {
String className = obj.getClassName(getCPG());
String fieldName = obj.getName(getCPG());
@@ -642,6 +643,8 @@ public class FindRefComparison implements Detector, ExtendedTypes {
private final Set<String> suspiciousSet;
+ private final boolean testingEnabled;
+
/*
* ----------------------------------------------------------------------
* Implementation
@@ -662,8 +665,10 @@ public class FindRefComparison implements Detector, ExtendedTypes {
suspiciousSet.add(tok.nextToken());
}
}
+ testingEnabled = SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors");
}
+ @Override
public void visitClassContext(ClassContext classContext) {
this.classContext = classContext;
@@ -726,7 +731,7 @@ public class FindRefComparison implements Detector, ExtendedTypes {
}
private void analyzeMethod(ClassContext classContext, final Method method) throws CFGBuilderException,
- DataflowAnalysisException {
+ DataflowAnalysisException {
MethodGen methodGen = classContext.getMethodGen(method);
if (methodGen == null) {
@@ -782,6 +787,7 @@ public class FindRefComparison implements Detector, ExtendedTypes {
final boolean likelyTestcase = TestCaseDetector.likelyTestCase(XFactory.createXMethod(jclass, method));
decorateWarnings(stringComparisonList, new WarningDecorator() {
+ @Override
public void decorate(WarningWithProperties warn) {
if (mightBeLaterCheckedUsingEquals(warn)) {
warn.propertySet.addProperty(RefComparisonWarningProperty.SAW_CALL_TO_EQUALS);
@@ -790,13 +796,15 @@ public class FindRefComparison implements Detector, ExtendedTypes {
if (likelyTestcase) {
warn.propertySet.addProperty(RefComparisonWarningProperty.COMPARE_IN_TEST_CASE);
}
-
+ /*
if (false && !(method.isPublic() || method.isProtected())) {
warn.propertySet.addProperty(RefComparisonWarningProperty.PRIVATE_METHOD);
}
+ */
}
});
decorateWarnings(refComparisonList, new WarningDecorator() {
+ @Override
public void decorate(WarningWithProperties warn) {
if (likelyTestcase) {
warn.propertySet.addProperty(RefComparisonWarningProperty.COMPARE_IN_TEST_CASE);
@@ -815,20 +823,22 @@ public class FindRefComparison implements Detector, ExtendedTypes {
}
boolean mightBeLaterCheckedUsingEquals(WarningWithProperties warning) {
- for (BugAnnotation a : warning.instance.getAnnotations())
+ for (BugAnnotation a : warning.instance.getAnnotations()) {
if (a instanceof TypeAnnotation) {
String signature = ((TypeAnnotation) a).getTypeDescriptor();
Integer pc = comparedForEqualityInThisMethod.get(signature);
- if (pc != null && pc > warning.location.getHandle().getPosition())
+ if (pc != null && pc > warning.location.getHandle().getPosition()) {
return true;
+ }
}
+ }
return false;
}
private void inspectLocation(JavaClass jclass, ConstantPoolGen cpg, Method method, MethodGen methodGen,
LinkedList<WarningWithProperties> refComparisonList, LinkedList<WarningWithProperties> stringComparisonList,
RefComparisonTypeFrameModelingVisitor visitor, TypeDataflow typeDataflow, Location location)
- throws DataflowAnalysisException {
+ throws DataflowAnalysisException {
Instruction ins = location.getHandle().getInstruction();
short opcode = ins.getOpcode();
if (opcode == Constants.IF_ACMPEQ || opcode == Constants.IF_ACMPNE) {
@@ -840,30 +850,31 @@ public class FindRefComparison implements Detector, ExtendedTypes {
@DottedClassName String className = inv.getClassName(cpg);
String methodName = inv.getMethodName(cpg);
String methodSig = inv.getSignature(cpg);
- if ( methodName.equals("assertSame") && methodSig.equals("(Ljava/lang/Object;Ljava/lang/Object;)V")) {
+ if ( "assertSame".equals(methodName) && "(Ljava/lang/Object;Ljava/lang/Object;)V".equals(methodSig)) {
checkRefComparison(location, jclass, method, methodGen, visitor, typeDataflow, stringComparisonList,
refComparisonList);
- } else if ( methodName.equals("assertFalse") && methodSig.equals("(Z)V")) {
+ } else if ( "assertFalse".equals(methodName) && "(Z)V".equals(methodSig)) {
SourceLineAnnotation lastLocation = bugAccumulator.getLastBugLocation();
InstructionHandle prevHandle = location.getHandle().getPrev();
if (lastLocation != null && prevHandle != null && lastLocation.getEndBytecode() == prevHandle.getPosition()){
- bugAccumulator.forgetLastBug();
- if (DEBUG)
- System.out.println("Forgetting last bug due to call to " + className +"." + methodName);
+ bugAccumulator.forgetLastBug();
+ if (DEBUG) {
+ System.out.println("Forgetting last bug due to call to " + className +"." + methodName);
+ }
}
} else {
- boolean equalsMethod = !isStatic && methodName.equals("equals") && methodSig.equals("(Ljava/lang/Object;)Z")
- || isStatic && methodName.equals("assertEquals")
- && methodSig.equals("(Ljava/lang/Object;Ljava/lang/Object;)V")
- || isStatic && methodName.equals("equal") && methodSig.equals("(Ljava/lang/Object;Ljava/lang/Object;)Z")
- && className.equals("com.google.common.base.Objects")
- || isStatic && methodName.equals("equals") && methodSig.equals("(Ljava/lang/Object;Ljava/lang/Object;)Z")
- && className.equals("java.util.Objects");
-
- if (equalsMethod) {
- checkEqualsComparison(location, jclass, method, methodGen, cpg, typeDataflow);
- }
+ boolean equalsMethod = !isStatic && "equals".equals(methodName) && "(Ljava/lang/Object;)Z".equals(methodSig)
+ || isStatic && "assertEquals".equals(methodName)
+ && "(Ljava/lang/Object;Ljava/lang/Object;)V".equals(methodSig)
+ || isStatic && "equal".equals(methodName) && "(Ljava/lang/Object;Ljava/lang/Object;)Z".equals(methodSig)
+ && "com.google.common.base.Objects".equals(className)
+ || isStatic && "equals".equals(methodName) && "(Ljava/lang/Object;Ljava/lang/Object;)Z".equals(methodSig)
+ && "java.util.Objects".equals(className);
+
+ if (equalsMethod) {
+ checkEqualsComparison(location, jclass, method, methodGen, cpg, typeDataflow);
+ }
}
}
@@ -883,8 +894,9 @@ public class FindRefComparison implements Detector, ExtendedTypes {
int bestPriority = Integer.MAX_VALUE;
for (WarningWithProperties warn : warningList) {
int priority = warn.instance.getPriority();
- if (bestPriority > priority)
+ if (bestPriority > priority) {
bestPriority = priority;
+ }
if (reportAll) {
if (relaxed) {
@@ -898,19 +910,20 @@ public class FindRefComparison implements Detector, ExtendedTypes {
}
}
- if (!reportAll)
+ if (!reportAll) {
for (WarningWithProperties warn : warningList) {
- BugInstance bug = warn.instance;
int priority = warn.instance.getPriority();
- if (priority <= bestPriority)
+ if (priority <= bestPriority) {
bugAccumulator.accumulateBug(warn.instance, warn.sourceLine);
+ }
}
+ }
}
private void checkRefComparison(Location location, JavaClass jclass, Method method, MethodGen methodGen,
RefComparisonTypeFrameModelingVisitor visitor, TypeDataflow typeDataflow,
List<WarningWithProperties> stringComparisonList, List<WarningWithProperties> refComparisonList)
- throws DataflowAnalysisException {
+ throws DataflowAnalysisException {
InstructionHandle handle = location.getHandle();
@@ -932,28 +945,32 @@ public class FindRefComparison implements Detector, ExtendedTypes {
String sourceFile = jclass.getSourceFileName();
boolean isAssertSame = handle.getInstruction() instanceof INVOKESTATIC;
- if (isAssertSame)
+ if (isAssertSame) {
+ if(testingEnabled) {
+ bugAccumulator.accumulateBug(
+ new BugInstance(this, "TESTING", result.getPriority())
+ .addClassAndMethod(methodGen, sourceFile)
+ .addString("Calling assertSame with two distinct objects")
+ .addFoundAndExpectedType(rhsType, lhsType)
+ .addSomeSourceForTopTwoStackValues(classContext, method, location),
+ SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, handle));
+ }
+ } else {
bugAccumulator.accumulateBug(
- new BugInstance(this, "TESTING", result.getPriority())
- .addClassAndMethod(methodGen, sourceFile)
- .addString("Calling assertSame with two distinct objects")
- .addFoundAndExpectedType(rhsType, lhsType)
- .addSomeSourceForTopTwoStackValues(classContext, method, location),
+ new BugInstance(this, "EC_UNRELATED_TYPES_USING_POINTER_EQUALITY", result.getPriority())
+ .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType, lhsType)
+ .addSomeSourceForTopTwoStackValues(classContext, method, location),
SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, handle));
- else
- bugAccumulator.accumulateBug(
- new BugInstance(this, "EC_UNRELATED_TYPES_USING_POINTER_EQUALITY", result.getPriority())
- .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType, lhsType)
- .addSomeSourceForTopTwoStackValues(classContext, method, location),
- SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, handle));
+ }
return;
}
- if (lhsType.equals(Type.OBJECT) && rhsType.equals(Type.OBJECT))
+ if (lhsType.equals(Type.OBJECT) && rhsType.equals(Type.OBJECT)) {
return;
+ }
String lhs = SignatureConverter.convert(lhsType.getSignature());
String rhs = SignatureConverter.convert(rhsType.getSignature());
- if (lhs.equals("java.lang.String") || rhs.equals("java.lang.String")) {
+ if ("java.lang.String".equals(lhs) || "java.lang.String".equals(rhs)) {
handleStringComparison(jclass, method, methodGen, visitor, stringComparisonList, location, lhsType, rhsType);
} else if (suspiciousSet.contains(lhs)) {
handleSuspiciousRefComparison(jclass, method, methodGen, refComparisonList, location, lhs,
@@ -1001,10 +1018,11 @@ public class FindRefComparison implements Detector, ExtendedTypes {
propertySet.addProperty(RefComparisonWarningProperty.STRING_PARAMETER);
}
} else if (type1 == T_STATIC_STRING || type2 == T_STATIC_STRING) {
- if (lhsType instanceof EmptyStringType || rhsType instanceof EmptyStringType)
+ if (lhsType instanceof EmptyStringType || rhsType instanceof EmptyStringType) {
propertySet.addProperty(RefComparisonWarningProperty.EMPTY_AND_UNKNOWN);
- else
+ } else {
propertySet.addProperty(RefComparisonWarningProperty.STATIC_AND_UNKNOWN);
+ }
} else if (visitor.sawStringIntern()) {
propertySet.addProperty(RefComparisonWarningProperty.SAW_INTERN);
}
@@ -1014,51 +1032,53 @@ public class FindRefComparison implements Detector, ExtendedTypes {
.addType("Ljava/lang/String;").describe(TypeAnnotation.FOUND_ROLE).addSomeSourceForTopTwoStackValues(classContext, method, location);
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
sourceFile, location.getHandle());
- if (sourceLineAnnotation != null) {
- WarningWithProperties warn = new WarningWithProperties(instance, propertySet, sourceLineAnnotation, location);
- stringComparisonList.add(warn);
- }
+ WarningWithProperties warn = new WarningWithProperties(instance, propertySet, sourceLineAnnotation, location);
+ stringComparisonList.add(warn);
}
private void handleSuspiciousRefComparison(JavaClass jclass, Method method, MethodGen methodGen,
List<WarningWithProperties> refComparisonList, Location location, String lhs, ReferenceType lhsType,
ReferenceType rhsType) {
XField xf = null;
- if (lhsType instanceof FinalConstant)
+ if (lhsType instanceof FinalConstant) {
xf = ((FinalConstant) lhsType).getXField();
- else if (rhsType instanceof FinalConstant)
+ } else if (rhsType instanceof FinalConstant) {
xf = ((FinalConstant) rhsType).getXField();
+ }
String sourceFile = jclass.getSourceFileName();
String bugPattern = "RC_REF_COMPARISON";
int priority = Priorities.HIGH_PRIORITY;
- if (lhs.equals("java.lang.Boolean")) {
+ if ("java.lang.Boolean".equals(lhs)) {
bugPattern = "RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN";
priority = Priorities.NORMAL_PRIORITY;
} else if (xf != null && xf.isStatic() && xf.isFinal()) {
bugPattern = "RC_REF_COMPARISON_BAD_PRACTICE";
- if (xf.isPublic() || !methodGen.isPublic())
+ if (xf.isPublic() || !methodGen.isPublic()) {
priority = Priorities.NORMAL_PRIORITY;
+ }
}
BugInstance instance = new BugInstance(this, bugPattern, priority).addClassAndMethod(methodGen, sourceFile)
.addType("L" + lhs.replace('.', '/') + ";").describe(TypeAnnotation.FOUND_ROLE);
- if (xf != null)
+ if (xf != null) {
instance.addField(xf).describe(FieldAnnotation.LOADED_FROM_ROLE);
- else
+ } else {
instance.addSomeSourceForTopTwoStackValues(classContext, method, location);
+ }
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
sourceFile, location.getHandle());
- if (sourceLineAnnotation != null)
- refComparisonList.add(new WarningWithProperties(instance, new WarningPropertySet<WarningProperty>(),
- sourceLineAnnotation, location));
+
+ refComparisonList.add(new WarningWithProperties(instance, new WarningPropertySet<WarningProperty>(),
+ sourceLineAnnotation, location));
}
private Map<String, Integer> comparedForEqualityInThisMethod;
void addEqualsCheck(String type, int pc) {
Integer oldPC = comparedForEqualityInThisMethod.get(type);
- if (oldPC == null || pc < oldPC)
+ if (oldPC == null || pc < oldPC) {
comparedForEqualityInThisMethod.put(type, pc);
+ }
}
private void checkEqualsComparison(Location location, JavaClass jclass, Method method, MethodGen methodGen,
@@ -1068,7 +1088,7 @@ public class FindRefComparison implements Detector, ExtendedTypes {
InstructionHandle next = handle.getNext();
if (next != null && next.getInstruction() instanceof INVOKESTATIC) {
INVOKESTATIC is = (INVOKESTATIC) next.getInstruction();
- if (is.getMethodName(cpg).equals("assertFalse")) {
+ if ("assertFalse".equals(is.getMethodName(cpg))) {
return;
}
}
@@ -1105,8 +1125,9 @@ public class FindRefComparison implements Detector, ExtendedTypes {
IsNullValueFrame isNullFrame = isNullDataflow.getFactAtLocation(location);
BugAnnotation a = BugInstance.getSourceForTopStackValue(classContext, method, location);
int priority = NORMAL_PRIORITY;
- if (a instanceof FieldAnnotation && ((FieldAnnotation) a).isStatic())
+ if (a instanceof FieldAnnotation && ((FieldAnnotation) a).isStatic()) {
priority = LOW_PRIORITY;
+ }
if (isNullFrame.isValid() && isNullFrame.getTopValue().isDefinitelyNull()) {
String type = "EC_NULL_ARG";
if (calledMethodAnnotation != null && calledMethodAnnotation.isStatic()){
@@ -1114,9 +1135,10 @@ public class FindRefComparison implements Detector, ExtendedTypes {
priority = LOW_PRIORITY;
}
BugInstance bug = new BugInstance(this, type, priority + priorityModifier).addClassAndMethod(methodGen, sourceFile)
- .addOptionalAnnotation(calledMethodAnnotation);
- if (type.equals("DMI_DOH"))
+ .addOptionalAnnotation(calledMethodAnnotation);
+ if ("DMI_DOH".equals(type)) {
bug.addString("Use \"== null\" to check for a value being null");
+ }
bugAccumulator.accumulateBug(
bug,
SourceLineAnnotation.fromVisitedInstruction(this.classContext, methodGen, sourceFile,
@@ -1143,10 +1165,11 @@ public class FindRefComparison implements Detector, ExtendedTypes {
if (lhsType_ instanceof ArrayType && rhsType_ instanceof ArrayType) {
String pattern = "EC_BAD_ARRAY_COMPARE";
IncompatibleTypes result2 = IncompatibleTypes.getPriorityForAssumingCompatible(lhsType_, rhsType_, true);
- if (result2.getPriority() <= Priorities.NORMAL_PRIORITY)
+ if (result2.getPriority() <= Priorities.NORMAL_PRIORITY) {
pattern = "EC_INCOMPATIBLE_ARRAY_COMPARE";
- else if (calledMethodAnnotation != null && calledMethodAnnotation.getClassName().equals("org.testng.Assert"))
+ } else if (calledMethodAnnotation != null && "org.testng.Assert".equals(calledMethodAnnotation.getClassName())) {
return;
+ }
bugAccumulator.accumulateBug(new BugInstance(this, pattern, NORMAL_PRIORITY).addClassAndMethod(methodGen, sourceFile)
.addFoundAndExpectedType(rhsType_, lhsType_)
.addSomeSourceForTopTwoStackValues(classContext, method, location)
@@ -1160,23 +1183,27 @@ public class FindRefComparison implements Detector, ExtendedTypes {
addEqualsCheck(rhsType_.getSignature(), handle.getPosition());
}
- if (result == IncompatibleTypes.SEEMS_OK) return;
+ if (result == IncompatibleTypes.SEEMS_OK) {
+ return;
+ }
- if (result.getPriority() > Priorities.LOW_PRIORITY)
+ if (result.getPriority() > Priorities.LOW_PRIORITY) {
return;
+ }
- if (result == IncompatibleTypes.ARRAY_AND_NON_ARRAY || result == IncompatibleTypes.ARRAY_AND_OBJECT) {
+ if (result == IncompatibleTypes.ARRAY_AND_NON_ARRAY || result == IncompatibleTypes.ARRAY_AND_OBJECT) {
String lhsSig = lhsType_.getSignature();
String rhsSig = rhsType_.getSignature();
boolean allOk = checkForWeirdEquals(lhsSig, rhsSig, new HashSet<XMethod>());
- if (allOk)
+ if (allOk) {
priorityModifier += 2;
+ }
bugAccumulator.accumulateBug(new BugInstance(this, "EC_ARRAY_AND_NONARRAY", result.getPriority() + priorityModifier)
- .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType_, lhsType_)
- .addSomeSourceForTopTwoStackValues(classContext, method, location)
- .addOptionalAnnotation(calledMethodAnnotation, MethodAnnotation.METHOD_CALLED),
- SourceLineAnnotation.fromVisitedInstruction(this.classContext, methodGen, sourceFile, location.getHandle()));
+ .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType_, lhsType_)
+ .addSomeSourceForTopTwoStackValues(classContext, method, location)
+ .addOptionalAnnotation(calledMethodAnnotation, MethodAnnotation.METHOD_CALLED),
+ SourceLineAnnotation.fromVisitedInstruction(this.classContext, methodGen, sourceFile, location.getHandle()));
} else if (result == IncompatibleTypes.INCOMPATIBLE_CLASSES) {
String lhsSig = lhsType_.getSignature();
String rhsSig = rhsType_.getSignature();
@@ -1188,15 +1215,16 @@ public class FindRefComparison implements Detector, ExtendedTypes {
if (true) {
Set<XMethod> targets = new HashSet<XMethod>();
boolean allOk = checkForWeirdEquals(lhsSig, rhsSig, targets);
- if (allOk)
+ if (allOk) {
priorityModifier += 2;
+ }
int priority = result.getPriority() + priorityModifier;
bugAccumulator.accumulateBug(
new BugInstance(this, "EC_UNRELATED_TYPES", priority)
- .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType_, lhsType_)
- .addSomeSourceForTopTwoStackValues(classContext, method, location).addEqualsMethodUsed(targets)
- .addOptionalAnnotation(calledMethodAnnotation, MethodAnnotation.METHOD_CALLED),
+ .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType_, lhsType_)
+ .addSomeSourceForTopTwoStackValues(classContext, method, location).addEqualsMethodUsed(targets)
+ .addOptionalAnnotation(calledMethodAnnotation, MethodAnnotation.METHOD_CALLED),
SourceLineAnnotation.fromVisitedInstruction(this.classContext, methodGen, sourceFile,
location.getHandle()));
}
@@ -1204,60 +1232,45 @@ public class FindRefComparison implements Detector, ExtendedTypes {
|| result == IncompatibleTypes.UNRELATED_FINAL_CLASS_AND_INTERFACE) {
bugAccumulator.accumulateBug(
new BugInstance(this, "EC_UNRELATED_CLASS_AND_INTERFACE", result.getPriority() + priorityModifier)
- .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType_, lhsType_)
- .addSomeSourceForTopTwoStackValues(classContext, method, location)
- .addEqualsMethodUsed(DescriptorFactory.createClassDescriptorFromSignature(lhsType_.getSignature()))
- .addOptionalAnnotation(calledMethodAnnotation, MethodAnnotation.METHOD_CALLED),
+ .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType_, lhsType_)
+ .addSomeSourceForTopTwoStackValues(classContext, method, location)
+ .addEqualsMethodUsed(DescriptorFactory.createClassDescriptorFromSignature(lhsType_.getSignature()))
+ .addOptionalAnnotation(calledMethodAnnotation, MethodAnnotation.METHOD_CALLED),
SourceLineAnnotation.fromVisitedInstruction(this.classContext, methodGen, sourceFile, location.getHandle()));
} else if (result == IncompatibleTypes.UNRELATED_INTERFACES) {
bugAccumulator.accumulateBug(
new BugInstance(this, "EC_UNRELATED_INTERFACES", result.getPriority() + priorityModifier)
- .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType_, lhsType_)
- .addSomeSourceForTopTwoStackValues(classContext, method, location)
- .addEqualsMethodUsed(DescriptorFactory.createClassDescriptorFromSignature(lhsType_.getSignature()))
- .addOptionalAnnotation(calledMethodAnnotation, MethodAnnotation.METHOD_CALLED),
- SourceLineAnnotation.fromVisitedInstruction(this.classContext, methodGen, sourceFile, location.getHandle()));
- } else if (result != IncompatibleTypes.UNCHECKED && result.getPriority() <= Priorities.LOW_PRIORITY) {
- bugAccumulator.accumulateBug(new BugInstance(this, "EC_UNRELATED_TYPES", result.getPriority() + priorityModifier)
.addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType_, lhsType_)
.addSomeSourceForTopTwoStackValues(classContext, method, location)
+ .addEqualsMethodUsed(DescriptorFactory.createClassDescriptorFromSignature(lhsType_.getSignature()))
.addOptionalAnnotation(calledMethodAnnotation, MethodAnnotation.METHOD_CALLED),
SourceLineAnnotation.fromVisitedInstruction(this.classContext, methodGen, sourceFile, location.getHandle()));
+ } else if (result != IncompatibleTypes.UNCHECKED && result.getPriority() <= Priorities.LOW_PRIORITY) {
+ bugAccumulator.accumulateBug(new BugInstance(this, "EC_UNRELATED_TYPES", result.getPriority() + priorityModifier)
+ .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType_, lhsType_)
+ .addSomeSourceForTopTwoStackValues(classContext, method, location)
+ .addOptionalAnnotation(calledMethodAnnotation, MethodAnnotation.METHOD_CALLED),
+ SourceLineAnnotation.fromVisitedInstruction(this.classContext, methodGen, sourceFile, location.getHandle()));
}
}
- /**
- * @param cpg
- * @param inv
- */
public @CheckForNull MethodAnnotation getMethodCalledAnnotation(ConstantPoolGen cpg, InvokeInstruction inv) {
MethodDescriptor invokedMethod = getInvokedMethod(cpg, inv);
- boolean standardEquals = invokedMethod.getName().equals("equals")
- && invokedMethod.getSignature().equals("(Ljava/lang/Object;)Z") && !invokedMethod.isStatic();
+ boolean standardEquals = "equals".equals(invokedMethod.getName())
+ && "(Ljava/lang/Object;)Z".equals(invokedMethod.getSignature()) && !invokedMethod.isStatic();
return standardEquals ? null : MethodAnnotation.fromMethodDescriptor(invokedMethod);
}
- /**
- * @param cpg
- * @param inv
- * @return
- */
public MethodDescriptor getInvokedMethod(ConstantPoolGen cpg, InvokeInstruction inv) {
String invoked = inv.getClassName(cpg);
String methodName = inv.getMethodName(cpg);
String methodSig = inv.getSignature(cpg);
MethodDescriptor invokedMethod =
- DescriptorFactory.instance().getMethodDescriptor(ClassName.toSlashedClassName(invoked), methodName, methodSig, inv instanceof INVOKESTATIC);
+ DescriptorFactory.instance().getMethodDescriptor(ClassName.toSlashedClassName(invoked), methodName, methodSig, inv instanceof INVOKESTATIC);
return invokedMethod;
}
- /**
- * @param lhsSig
- * @param rhsSig
- * @param targets
- * @return
- */
private boolean checkForWeirdEquals(String lhsSig, String rhsSig, Set<XMethod> targets) {
boolean allOk = false;
try {
@@ -1269,9 +1282,11 @@ public class FindRefComparison implements Detector, ExtendedTypes {
targets.addAll(Hierarchy2.resolveVirtualMethodCallTargets(expectedClassDescriptor, "equals", "(Ljava/lang/Object;)Z",
false, false));
allOk = targets.size() > 0;
- for (XMethod m2 : targets)
- if (!classSummary.mightBeEqualTo(m2.getClassDescriptor(), actualClassDescriptor))
+ for (XMethod m2 : targets) {
+ if (!classSummary.mightBeEqualTo(m2.getClassDescriptor(), actualClassDescriptor)) {
allOk = false;
+ }
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
@@ -1279,9 +1294,9 @@ public class FindRefComparison implements Detector, ExtendedTypes {
return allOk;
}
+ @Override
public void report() {
// do nothing
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindReturnRef.java b/src/java/edu/umd/cs/findbugs/detect/FindReturnRef.java
index d25c2f7..b66beaf 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindReturnRef.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindReturnRef.java
@@ -52,7 +52,7 @@ public class FindReturnRef extends OpcodeStackDetector {
boolean fieldIsStatic;
- private BugAccumulator bugAccumulator;
+ private final BugAccumulator bugAccumulator;
// private LocalVariableTable variableNames;
@@ -74,14 +74,16 @@ public class FindReturnRef extends OpcodeStackDetector {
@Override
public void visit(Method obj) {
check = publicClass && (obj.getAccessFlags() & (ACC_PUBLIC)) != 0;
- if (!check)
+ if (!check) {
return;
+ }
staticMethod = (obj.getAccessFlags() & (ACC_STATIC)) != 0;
// variableNames = obj.getLocalVariableTable();
parameterCount = getNumberMethodArguments();
- if (!staticMethod)
+ if (!staticMethod) {
parameterCount++;
+ }
thisOnTOS = false;
fieldOnTOS = false;
@@ -92,36 +94,40 @@ public class FindReturnRef extends OpcodeStackDetector {
@Override
public void visit(Code obj) {
- if (check)
+ if (check) {
super.visit(obj);
+ }
}
@Override
public void sawOpcode(int seen) {
- if (!check)
+ if (!check) {
return;
+ }
if (staticMethod && seen == PUTSTATIC && MutableStaticFields.mutableSignature(getSigConstantOperand())) {
OpcodeStack.Item top = stack.getStackItem(0);
- if (isPotentialCapture(top))
+ if (isPotentialCapture(top)) {
bugAccumulator.accumulateBug(
new BugInstance(this, "EI_EXPOSE_STATIC_REP2", NORMAL_PRIORITY)
- .addClassAndMethod(this)
- .addReferencedField(this)
- .add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), top.getRegisterNumber(),
- getPC(), getPC() - 1)), this);
+ .addClassAndMethod(this)
+ .addReferencedField(this)
+ .add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), top.getRegisterNumber(),
+ getPC(), getPC() - 1)), this);
+ }
}
if (!staticMethod && seen == PUTFIELD && MutableStaticFields.mutableSignature(getSigConstantOperand())) {
OpcodeStack.Item top = stack.getStackItem(0);
OpcodeStack.Item target = stack.getStackItem(1);
- if (isPotentialCapture(top) && target.getRegisterNumber() == 0)
+ if (isPotentialCapture(top) && target.getRegisterNumber() == 0) {
bugAccumulator.accumulateBug(
new BugInstance(this, "EI_EXPOSE_REP2", NORMAL_PRIORITY)
- .addClassAndMethod(this)
- .addReferencedField(this)
- .add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), top.getRegisterNumber(),
- getPC(), getPC() - 1)), this);
+ .addClassAndMethod(this)
+ .addReferencedField(this)
+ .add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), top.getRegisterNumber(),
+ getPC(), getPC() - 1)), this);
+ }
}
if (seen == ALOAD_0 && !staticMethod) {
@@ -153,13 +159,13 @@ public class FindReturnRef extends OpcodeStackDetector {
}
thisOnTOS = false;
if (check && fieldOnTOS && seen == ARETURN
- /*
- * && !sigOnStack.equals("Ljava/lang/String;") &&
- * sigOnStack.indexOf("Exception") == -1 && sigOnStack.indexOf("[") >= 0
- */
- && nameOnStack.indexOf("EMPTY") == -1 && MutableStaticFields.mutableSignature(sigOnStack)) {
+ /*
+ * && !sigOnStack.equals("Ljava/lang/String;") &&
+ * sigOnStack.indexOf("Exception") == -1 && sigOnStack.indexOf("[") >= 0
+ */
+ && nameOnStack.indexOf("EMPTY") == -1 && MutableStaticFields.mutableSignature(sigOnStack)) {
bugAccumulator.accumulateBug(new BugInstance(this, staticMethod ? "MS_EXPOSE_REP" : "EI_EXPOSE_REP", NORMAL_PRIORITY)
- .addClassAndMethod(this).addField(classNameOnStack, nameOnStack, sigOnStack, fieldIsStatic), this);
+ .addClassAndMethod(this).addField(classNameOnStack, nameOnStack, sigOnStack, fieldIsStatic), this);
}
fieldOnTOS = false;
@@ -167,12 +173,16 @@ public class FindReturnRef extends OpcodeStackDetector {
}
private boolean isPotentialCapture(OpcodeStack.Item top) {
- if (!top.isInitialParameter())
+ if (!top.isInitialParameter()) {
return false;
- if ((getMethod().getAccessFlags() & ACC_VARARGS) == 0)
+ }
+ if ((getMethod().getAccessFlags() & ACC_VARARGS) == 0) {
return true;
+ }
if (top.getRegisterNumber() == parameterCount - 1)
+ {
return false; // var-arg parameter
+ }
return true;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindRoughConstants.java b/src/java/edu/umd/cs/findbugs/detect/FindRoughConstants.java
new file mode 100644
index 0000000..c1b3e30
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/detect/FindRoughConstants.java
@@ -0,0 +1,219 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2007 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package edu.umd.cs.findbugs.detect;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.bcel.classfile.Constant;
+import org.apache.bcel.classfile.ConstantDouble;
+import org.apache.bcel.classfile.ConstantFloat;
+import org.apache.bcel.classfile.ConstantPool;
+import org.apache.bcel.classfile.JavaClass;
+
+import edu.umd.cs.findbugs.BugAccumulator;
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.BytecodeScanningDetector;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import edu.umd.cs.findbugs.ba.ClassContext;
+
+public class FindRoughConstants extends BytecodeScanningDetector {
+
+ static class BadConstant {
+ double base;
+ double factor;
+ String replacement;
+ double value;
+ int basePriority;
+
+ Set<Number> approxSet = new HashSet<Number>();
+
+ BadConstant(double base, double factor, String replacement, int basePriority) {
+ this.base = base;
+ this.factor = factor;
+ this.value = this.base * this.factor;
+ this.replacement = replacement;
+ this.basePriority = basePriority;
+ BigDecimal valueBig = BigDecimal.valueOf(value);
+ BigDecimal baseBig = BigDecimal.valueOf(base);
+ BigDecimal factorBig = BigDecimal.valueOf(factor);
+ for (int prec = 0; prec < 14; prec++) {
+ addApprox(baseBig.round(new MathContext(prec, RoundingMode.FLOOR)).multiply(factorBig));
+ addApprox(baseBig.round(new MathContext(prec, RoundingMode.CEILING)).multiply(factorBig));
+ addApprox(valueBig.round(new MathContext(prec, RoundingMode.FLOOR)));
+ addApprox(valueBig.round(new MathContext(prec, RoundingMode.CEILING)));
+ }
+ }
+
+ @SuppressFBWarnings("FE_FLOATING_POINT_EQUALITY")
+ public boolean exact(Number candidate) {
+ if (candidate instanceof Double) {
+ return candidate.doubleValue() == value;
+ }
+ return candidate.floatValue() == (float) value;
+ }
+
+ public double diff(double candidate) {
+ return Math.abs(value - candidate) / value;
+ }
+
+ public boolean equalPrefix(Number candidate) {
+ return approxSet.contains(candidate);
+ }
+
+ @SuppressFBWarnings("FE_FLOATING_POINT_EQUALITY")
+ private void addApprox(BigDecimal roundFloor) {
+ double approxDouble = roundFloor.doubleValue();
+ if (approxDouble != value && Math.abs(approxDouble - value) / value < 0.001) {
+ approxSet.add(approxDouble);
+ }
+ float approxFloat = roundFloor.floatValue();
+ if (Math.abs(approxFloat - value) / value < 0.001) {
+ approxSet.add(approxFloat);
+ approxSet.add((double) approxFloat);
+ }
+ }
+ }
+
+ private static final BadConstant[] badConstants = new BadConstant[] {
+ new BadConstant(Math.PI, 1, "Math.PI", HIGH_PRIORITY),
+ new BadConstant(Math.PI, 1/2.0, "Math.PI/2", NORMAL_PRIORITY),
+ new BadConstant(Math.PI, 1/3.0, "Math.PI/3", LOW_PRIORITY),
+ new BadConstant(Math.PI, 1/4.0, "Math.PI/4", LOW_PRIORITY),
+ new BadConstant(Math.PI, 2, "2*Math.PI", NORMAL_PRIORITY),
+ new BadConstant(Math.E, 1, "Math.E", LOW_PRIORITY)
+ };
+
+ private final BugAccumulator bugAccumulator;
+
+ private BugInstance lastBug;
+ private int lastPriority;
+
+ public FindRoughConstants(BugReporter bugReporter) {
+ this.bugAccumulator = new BugAccumulator(bugReporter);
+ }
+
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ if(hasInterestingConstant(classContext.getJavaClass().getConstantPool())) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
+ public void visitAfter(JavaClass obj) {
+ bugAccumulator.reportAccumulatedBugs();
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if (seen == LDC || seen == LDC_W || seen == LDC2_W) {
+ Constant c = getConstantRefOperand();
+ if (c instanceof ConstantFloat) {
+ checkConst(((ConstantFloat) c).getBytes());
+ } else if (c instanceof ConstantDouble) {
+ checkConst(((ConstantDouble) c).getBytes());
+ }
+ return;
+ }
+ // Lower priority if the constant is put into array immediately or after the boxing:
+ // this is likely to be just similar number in some predefined dataset (like lookup table)
+ if(seen == INVOKESTATIC && lastBug != null) {
+ if (getNextOpcode() == AASTORE
+ && getNameConstantOperand().equals("valueOf")
+ && (getClassConstantOperand().equals("java/lang/Double") || getClassConstantOperand().equals(
+ "java/lang/Float"))) {
+ lastBug = ((BugInstance)lastBug.clone());
+ lastBug.setPriority(lastPriority+1);
+ bugAccumulator.forgetLastBug();
+ bugAccumulator.accumulateBug(lastBug, this);
+ }
+ }
+ lastBug = null;
+ }
+
+ private boolean hasInterestingConstant(ConstantPool cp) {
+ for(Constant constant : cp.getConstantPool()) {
+ if(constant instanceof ConstantFloat) {
+ float val = ((ConstantFloat)constant).getBytes();
+ if(isInteresting(val, val)) {
+ return true;
+ }
+ }
+ if(constant instanceof ConstantDouble) {
+ double val = ((ConstantDouble)constant).getBytes();
+ if(isInteresting(val, val)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean isInteresting(Number constValue, double candidate) {
+ for (BadConstant badConstant : badConstants) {
+ if(getPriority(badConstant, constValue, candidate) < IGNORE_PRIORITY) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private int getPriority(BadConstant badConstant, Number constValue, double candidate) {
+ if (badConstant.exact(constValue)) {
+ return IGNORE_PRIORITY;
+ }
+ double diff = badConstant.diff(candidate);
+ if (diff > 1e-3) {
+ return IGNORE_PRIORITY;
+ }
+ if (badConstant.equalPrefix(constValue)) {
+ return diff > 1e-4 ? badConstant.basePriority+1 :
+ diff < 1e-6 ? badConstant.basePriority-1 : badConstant.basePriority;
+ }
+ if (diff > 1e-7) {
+ return IGNORE_PRIORITY;
+ }
+ return badConstant.basePriority+1;
+ }
+
+ private void checkConst(Number constValue) {
+ double candidate = constValue.doubleValue();
+ if (Double.isNaN(candidate) || Double.isInfinite(candidate)) {
+ return;
+ }
+ for (BadConstant badConstant : badConstants) {
+ int priority = getPriority(badConstant, constValue, candidate);
+ if(getNextOpcode() == FASTORE || getNextOpcode() == DASTORE) {
+ priority++;
+ }
+ if(priority < IGNORE_PRIORITY) {
+ lastPriority = priority;
+ lastBug = new BugInstance(this, "CNT_ROUGH_CONSTANT_VALUE", priority).addClassAndMethod(this)
+ .addString(constValue.toString()).addString(badConstant.replacement);
+ bugAccumulator.accumulateBug(lastBug, this);
+ return;
+ }
+ }
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindRunInvocations.java b/src/java/edu/umd/cs/findbugs/detect/FindRunInvocations.java
index dc15d3f..9def381 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindRunInvocations.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindRunInvocations.java
@@ -59,19 +59,21 @@ public class FindRunInvocations extends BytecodeScanningDetector implements Stat
@Override
public void sawOpcode(int seen) {
- if (alreadySawStart)
+ if (alreadySawStart) {
return;
- if ((seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) && getSigConstantOperand().equals("()V")
+ }
+ if ((seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) && "()V".equals(getSigConstantOperand())
&& isThread(getDottedClassConstantOperand())) {
- if (getNameConstantOperand().equals("start"))
+ if ("start".equals(getNameConstantOperand())) {
alreadySawStart = true;
- else {
- boolean isJustThread = !getDottedClassConstantOperand().equals("java.lang.Thread");
- if (amVisitingMainMethod() && getPC() == getCode().getLength() - 4 && isJustThread)
+ } else {
+ boolean isJustThread = !"java.lang.Thread".equals(getDottedClassConstantOperand());
+ if (amVisitingMainMethod() && getPC() == getCode().getLength() - 4 && isJustThread) {
return;
- else if (getNameConstantOperand().equals("run"))
+ } else if ("run".equals(getNameConstantOperand())) {
bugAccumulator.accumulateBug(new BugInstance(this, "RU_INVOKE_RUN", isJustThread ? HIGH_PRIORITY
: NORMAL_PRIORITY).addClassAndMethod(this), this);
+ }
}
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindSelfComparison.java b/src/java/edu/umd/cs/findbugs/detect/FindSelfComparison.java
index ca2a527..319e8f0 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindSelfComparison.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindSelfComparison.java
@@ -56,12 +56,13 @@ public class FindSelfComparison extends OpcodeStackDetector {
XField putFieldXField;
int lastMethodCall;
-
+
static final boolean DEBUG = SystemProperties.getBoolean("fsc.debug");
@Override
public void visit(Code obj) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println(getFullyQualifiedMethodName());
+ }
whichRegister = -1;
registerLoadCount = 0;
lastMethodCall = -1;
@@ -69,8 +70,9 @@ public class FindSelfComparison extends OpcodeStackDetector {
super.visit(obj);
resetDoubleAssignmentState();
bugAccumulator.reportAccumulatedBugs();
- if (DEBUG)
+ if (DEBUG) {
System.out.println();
+ }
}
private void resetDoubleAssignmentState() {
@@ -87,12 +89,14 @@ public class FindSelfComparison extends OpcodeStackDetector {
@Override
public void sawOpcode(int seen) {
- if (DEBUG)
+ if (DEBUG) {
System.out.printf("%3d %-15s %s%n", getPC(), OPCODE_NAMES[seen], stack);
-
-
- if (stack.hasIncomingBranches(getPC()))
+ }
+
+
+ if (stack.hasIncomingBranches(getPC())) {
resetDoubleAssignmentState();
+ }
if (seen == PUTFIELD) {
OpcodeStack.Item obj = stack.getStackItem(1);
@@ -101,30 +105,36 @@ public class FindSelfComparison extends OpcodeStackDetector {
XClass x = getXClassOperand();
checkPUTFIELD: if (putFieldPC + 10 > getPC() && f != null && obj != null && f.equals(putFieldXField)
- && !f.isSynthetic() && obj.equals(putFieldObj) && x != null) {
+ && !f.isSynthetic() && obj.sameValue(putFieldObj) && x != null) {
+
LineNumberTable table = getCode().getLineNumberTable();
if (table != null) {
int first = table.getSourceLine(putFieldPC);
int second = table.getSourceLine(getPC());
- if (first + 1 != second && first != second)
+ if (first + 1 != second && first != second) {
break checkPUTFIELD;
- } else if (putFieldPC + 3 != getPC())
+ }
+ } else if (putFieldPC + 3 != getPC()) {
break checkPUTFIELD;
+ }
int priority = NORMAL_PRIORITY;
- if (value.equals(putFieldValue) && putFieldPC + 3 != getPC())
+ if (value.equals(putFieldValue) && putFieldPC + 3 != getPC()) {
priority++;
+ }
boolean storeOfDefaultValue = putFieldValue.isNull() || putFieldValue.hasConstantValue(0);
- if (storeOfDefaultValue)
+ if (storeOfDefaultValue) {
priority++;
- if (f.isVolatile())
+ }
+ if (f.isVolatile()) {
priority++;
+ }
XField intendedTarget = null;
double minimumDistance = 2;
int matches = 0;
- for (XField f2 : x.getXFields())
+ for (XField f2 : x.getXFields()) {
if (!f.equals(f2) && !f2.isStatic() && !f2.isFinal() && !f2.isSynthetic()
&& f2.getSignature().equals(f.getSignature())) {
@@ -136,14 +146,17 @@ public class FindSelfComparison extends OpcodeStackDetector {
}
}
- if (minimumDistance > 0.6 && (matches > 1 || storeOfDefaultValue))
+ }
+ if (minimumDistance > 0.6 && (matches > 1 || storeOfDefaultValue)) {
intendedTarget = null;
- else if (intendedTarget != null)
+ } else if (intendedTarget != null) {
priority--;
+ }
BugInstance bug = new BugInstance(this, "SA_FIELD_DOUBLE_ASSIGNMENT", priority).addClassAndMethod(this)
.addReferencedField(this);
- if (intendedTarget != null)
+ if (intendedTarget != null) {
bug.addField(intendedTarget).describe(FieldAnnotation.DID_YOU_MEAN_ROLE);
+ }
bugAccumulator.accumulateBug(bug, this);
}
@@ -152,26 +165,31 @@ public class FindSelfComparison extends OpcodeStackDetector {
putFieldObj = obj;
putFieldValue = value;
- } else if (isReturn(seen))
+ } else if (isReturn(seen)) {
resetDoubleAssignmentState();
- else if (seen == GETFIELD && Util.nullSafeEquals(getXFieldOperand(), putFieldXField)) {
+ } else if (seen == GETFIELD && Util.nullSafeEquals(getXFieldOperand(), putFieldXField)) {
OpcodeStack.Item obj = stack.getStackItem(0);
- if (obj.equals(putFieldObj))
+ if (obj.sameValue(putFieldObj)) {
resetDoubleAssignmentState();
+ }
}
switch (seen) {
case INVOKEVIRTUAL:
case INVOKEINTERFACE:
-// case INVOKESTATIC:
- if (getClassName().toLowerCase().indexOf("test") >= 0)
+ // case INVOKESTATIC:
+ if (getClassName().toLowerCase().indexOf("test") >= 0) {
break;
- if (getMethodName().toLowerCase().indexOf("test") >= 0)
+ }
+ if (getMethodName().toLowerCase().indexOf("test") >= 0) {
break;
- if (getSuperclassName().toLowerCase().indexOf("test") >= 0)
+ }
+ if (getSuperclassName().toLowerCase().indexOf("test") >= 0) {
break;
- if (getNextOpcode() == POP)
+ }
+ if (getNextOpcode() == POP) {
break;
+ }
String name = getNameConstantOperand();
boolean booleanComparisonMethod = FindSelfComparison2.booleanComparisonMethod(name);
@@ -181,8 +199,9 @@ public class FindSelfComparison extends OpcodeStackDetector {
int numParameters = parser.getNumParameters();
if ((numParameters == 1 || seen == INVOKESTATIC && numParameters == 2)
&& (booleanComparisonMethod && sig.endsWith(";)Z")
- || FindSelfComparison2.comparatorMethod(name) && sig.endsWith(";)I")))
+ || FindSelfComparison2.comparatorMethod(name) && sig.endsWith(";)I"))) {
checkForSelfOperation(seen, "COMPARISON");
+ }
}
break;
@@ -211,11 +230,14 @@ public class FindSelfComparison extends OpcodeStackDetector {
case IF_ICMPLT:
case IF_ICMPGE:
checkForSelfOperation(seen, "COMPARISON");
+ break;
+ default:
+ break;
}
if (isRegisterLoad() && seen != IINC) {
- if (getRegisterOperand() == whichRegister)
+ if (getRegisterOperand() == whichRegister) {
registerLoadCount++;
- else {
+ } else {
whichRegister = getRegisterOperand();
registerLoadCount = 1;
}
@@ -223,9 +245,10 @@ public class FindSelfComparison extends OpcodeStackDetector {
whichRegister = -1;
registerLoadCount = 0;
}
-
- if (isMethodCall())
+
+ if (isMethodCall()) {
lastMethodCall = getPC();
+ }
}
@@ -236,14 +259,16 @@ public class FindSelfComparison extends OpcodeStackDetector {
private void checkForSelfOperation(int opCode, String op) {
{
-
+
OpcodeStack.Item item0 = stack.getStackItem(0);
OpcodeStack.Item item1 = stack.getStackItem(1);
- if (item0.getSignature().equals("D") || item0.getSignature().equals("F"))
+ if ("D".equals(item0.getSignature()) || "F".equals(item0.getSignature())) {
return;
- if (item1.getSignature().equals("D") || item1.getSignature().equals("F"))
+ }
+ if ("D".equals(item1.getSignature()) || "F".equals(item1.getSignature())) {
return;
+ }
BitSet linesMentionedMultipleTimes = getClassContext().linesMentionedMultipleTimes(getMethod());
SourceLineAnnotation source = SourceLineAnnotation.fromVisitedInstruction(this);
@@ -255,16 +280,18 @@ public class FindSelfComparison extends OpcodeStackDetector {
int line0 = lineNumberTable.getSourceLine(item0.getPC());
int line1 = lineNumberTable.getSourceLine(item1.getPC());
int firstPos = Math.min(item0.getPC(), item1.getPC());
- if (firstPos < lastMethodCall && line0 != line1)
+ if (firstPos < lastMethodCall && line0 != line1) {
return;
+ }
linesDifference = Math.abs(line0 - line1);
} else {
int firstPos = Math.min(item0.getPC(), item1.getPC());
int lastPos = Math.max(item0.getPC(), item1.getPC());
- if (firstPos < lastMethodCall && lastPos - firstPos > 4)
+ if (firstPos < lastMethodCall && lastPos - firstPos > 4) {
return;
+ }
linesDifference = (lastPos - firstPos)/10;
}
}
@@ -274,28 +301,32 @@ public class FindSelfComparison extends OpcodeStackDetector {
int fr1 = item1.getFieldLoadedFromRegister();
if (field0 != null && field0.equals(field1) && (field0.isStatic() || fr0 != -1 && fr0 == fr1)) {
int priority = NORMAL_PRIORITY;
- if (field0.isVolatile())
+ if (field0.isVolatile()) {
priority++;
+ }
if (linesDifference > 1) {
- if (possibleClone)
+ if (possibleClone) {
return;
+ }
priority++;
}
-
+
BugInstance bug = new BugInstance(this, "SA_FIELD_SELF_" + op, priority)
- .addClassAndMethod(this).addField(field0);
-
- if (this.isMethodCall())
+ .addClassAndMethod(this).addField(field0);
+
+ if (this.isMethodCall()) {
bug.addCalledMethod(this);
+ }
bugAccumulator.accumulateBug(bug, this);
}
- else if (opCode == IXOR && item0.equals(item1)) {
+ else if (opCode == IXOR && item0.sameValue(item1)) {
LocalVariableAnnotation localVariableAnnotation = LocalVariableAnnotation.getLocalVariableAnnotation(this, item0);
- if (localVariableAnnotation != null)
+ if (localVariableAnnotation != null) {
bugAccumulator.accumulateBug(
new BugInstance(this, "SA_LOCAL_SELF_" + op, linesDifference > 1 ? NORMAL_PRIORITY : HIGH_PRIORITY).addClassAndMethod(this).add(
localVariableAnnotation), this);
+ }
}
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindSelfComparison2.java b/src/java/edu/umd/cs/findbugs/detect/FindSelfComparison2.java
index 943ad6b..abb064b 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindSelfComparison2.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindSelfComparison2.java
@@ -1,29 +1,6 @@
package edu.umd.cs.findbugs.detect;
-import static org.apache.bcel.Constants.DCMPG;
-import static org.apache.bcel.Constants.DCMPL;
-import static org.apache.bcel.Constants.FCMPG;
-import static org.apache.bcel.Constants.FCMPL;
-import static org.apache.bcel.Constants.IAND;
-import static org.apache.bcel.Constants.IF_ACMPEQ;
-import static org.apache.bcel.Constants.IF_ACMPNE;
-import static org.apache.bcel.Constants.IF_ICMPEQ;
-import static org.apache.bcel.Constants.IF_ICMPGE;
-import static org.apache.bcel.Constants.IF_ICMPGT;
-import static org.apache.bcel.Constants.IF_ICMPLE;
-import static org.apache.bcel.Constants.IF_ICMPLT;
-import static org.apache.bcel.Constants.IF_ICMPNE;
-import static org.apache.bcel.Constants.INVOKEINTERFACE;
-import static org.apache.bcel.Constants.INVOKEVIRTUAL;
-import static org.apache.bcel.Constants.IOR;
-import static org.apache.bcel.Constants.ISUB;
-import static org.apache.bcel.Constants.IXOR;
-import static org.apache.bcel.Constants.LAND;
-import static org.apache.bcel.Constants.LCMP;
-import static org.apache.bcel.Constants.LOR;
-import static org.apache.bcel.Constants.LSUB;
-import static org.apache.bcel.Constants.LXOR;
-import static org.apache.bcel.Constants.POP;
+import static org.apache.bcel.Constants.*;
import java.util.BitSet;
import java.util.Iterator;
@@ -38,7 +15,6 @@ import edu.umd.cs.findbugs.BugAnnotation;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.Detector;
-import edu.umd.cs.findbugs.FieldAnnotation;
import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.ba.CFG;
@@ -62,20 +38,23 @@ public class FindSelfComparison2 implements Detector {
this.bugReporter = bugReporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
Method[] methodList = classContext.getJavaClass().getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
} catch (MethodUnprofitableException mue) {
- if (SystemProperties.getBoolean("unprofitable.debug")) // otherwise
- // don't
- // report
+ if (SystemProperties.getBoolean("unprofitable.debug")) {
+ // don't
+ // report
bugReporter.logError("skipping unprofitable method in " + getClass().getName());
+ }
} catch (CFGBuilderException e) {
bugReporter.logError("Detector " + this.getClass().getName() + " caught exception", e);
} catch (DataflowAnalysisException e) {
@@ -84,13 +63,13 @@ public class FindSelfComparison2 implements Detector {
}
}
- static boolean booleanComparisonMethod(String methodName) {
- return methodName.equals("equals") ||methodName.equals("endsWith") || methodName.equals("startsWith")
- || methodName.equals("contains") || methodName.equals("equalsIgnoreCase");
+ static boolean booleanComparisonMethod(String methodName) {
+ return "equals".equals(methodName) ||"endsWith".equals(methodName) || "startsWith".equals(methodName)
+ || "contains".equals(methodName) || "equalsIgnoreCase".equals(methodName);
}
- static boolean comparatorMethod(String methodName) {
- return methodName.equals("compareTo") || methodName.equals("compareToIgnoreCase");
+ static boolean comparatorMethod(String methodName) {
+ return "compareTo".equals(methodName) || "compareToIgnoreCase".equals(methodName);
}
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {
CFG cfg = classContext.getCFG(method);
@@ -109,21 +88,26 @@ public class FindSelfComparison2 implements Detector {
InvokeInstruction iins = (InvokeInstruction) ins;
String invoking = iins.getName(cpg);
if ( comparatorMethod(invoking) || booleanComparisonMethod(invoking) ) {
- if (methodGen.getName().toLowerCase().indexOf("test") >= 0)
+ if (methodGen.getName().toLowerCase().indexOf("test") >= 0) {
break;
- if (methodGen.getClassName().toLowerCase().indexOf("test") >= 0)
+ }
+ if (methodGen.getClassName().toLowerCase().indexOf("test") >= 0) {
break;
- if (classContext.getJavaClass().getSuperclassName().toLowerCase().indexOf("test") >= 0)
+ }
+ if (classContext.getJavaClass().getSuperclassName().toLowerCase().indexOf("test") >= 0) {
break;
- if (location.getHandle().getNext().getInstruction().getOpcode() == POP)
+ }
+ if (location.getHandle().getNext().getInstruction().getOpcode() == POP) {
break;
+ }
String sig = iins.getSignature(cpg);
SignatureParser parser = new SignatureParser(sig);
if (parser.getNumParameters() == 1
- && ( booleanComparisonMethod(invoking) && sig.endsWith(";)Z") || comparatorMethod(invoking) && sig.endsWith(";)I")))
+ && ( booleanComparisonMethod(invoking) && sig.endsWith(";)Z") || comparatorMethod(invoking) && sig.endsWith(";)I"))) {
checkForSelfOperation(classContext, location, valueNumberDataflow, "COMPARISON", method, methodGen,
sourceFile);
+ }
}
break;
@@ -153,7 +137,9 @@ public class FindSelfComparison2 implements Detector {
case IF_ICMPLT:
case IF_ICMPGE:
checkForSelfOperation(classContext, location, valueNumberDataflow, "COMPARISON", method, methodGen, sourceFile);
-
+ break;
+ default:
+ break;
}
}
@@ -161,70 +147,77 @@ public class FindSelfComparison2 implements Detector {
/**
* @param classContext
- * TODO
* @param location
* @param method
- * TODO
* @param methodGen
- * TODO
* @param sourceFile
- * TODO
- * @param string
* @throws DataflowAnalysisException
*/
private void checkForSelfOperation(ClassContext classContext, Location location, ValueNumberDataflow valueNumberDataflow,
String op, Method method, MethodGen methodGen, String sourceFile) throws DataflowAnalysisException {
ValueNumberFrame frame = valueNumberDataflow.getFactAtLocation(location);
- if (!frame.isValid())
+ if (!frame.isValid()) {
return;
+ }
Instruction ins = location.getHandle().getInstruction();
int opcode = ins.getOpcode();
int offset = 1;
- if (opcode == LCMP || opcode == LXOR || opcode == LAND || opcode == LOR || opcode == LSUB)
+ if (opcode == LCMP || opcode == LXOR || opcode == LAND || opcode == LOR || opcode == LSUB) {
offset = 2;
+ }
ValueNumber v0 = frame.getStackValue(0);
ValueNumber v1 = frame.getStackValue(offset);
- if (!v1.equals(v0))
+ if (!v1.equals(v0)) {
return;
- if (v0.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT) || v0.hasFlag(ValueNumber.CONSTANT_VALUE))
+ }
+ if (v0.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT) || v0.hasFlag(ValueNumber.CONSTANT_VALUE)) {
return;
+ }
int priority = HIGH_PRIORITY;
- if (opcode == ISUB || opcode == LSUB || opcode == INVOKEINTERFACE || opcode == INVOKEVIRTUAL)
+ if (opcode == ISUB || opcode == LSUB || opcode == INVOKEINTERFACE || opcode == INVOKEVIRTUAL) {
priority = NORMAL_PRIORITY;
+ }
XField field = ValueNumberSourceInfo.findXFieldFromValueNumber(method, location, v0, frame);
BugAnnotation annotation;
String prefix;
if (field != null) {
- if (field.isVolatile())
+ if (field.isVolatile()) {
return;
- if (true)
+ }
+ if (true) {
return; // don't report these; too many false positives
- annotation = FieldAnnotation.fromXField(field);
- prefix = "SA_FIELD_SELF_";
+ }
+ // annotation = FieldAnnotation.fromXField(field);
+ // prefix = "SA_FIELD_SELF_";
} else {
annotation = ValueNumberSourceInfo.findLocalAnnotationFromValueNumber(method, location, v0, frame);
prefix = "SA_LOCAL_SELF_";
- if (opcode == ISUB)
+ if (opcode == ISUB) {
return; // only report this if simple detector reports it
+ }
}
- if (annotation == null)
+ if (annotation == null) {
return;
+ }
SourceLineAnnotation sourceLine = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile,
location.getHandle());
int line = sourceLine.getStartLine();
BitSet occursMultipleTimes = classContext.linesMentionedMultipleTimes(method);
- if (line > 0 && occursMultipleTimes.get(line))
+ if (line > 0 && occursMultipleTimes.get(line)) {
return;
+ }
BugInstance bug = new BugInstance(this, prefix + op, priority).addClassAndMethod(methodGen, sourceFile);
- if (ins instanceof InvokeInstruction)
+ if (ins instanceof InvokeInstruction) {
bug.addCalledMethod(classContext.getConstantPoolGen(), (InvokeInstruction) ins);
+ }
bug.add(annotation)
- .addSourceLine(classContext, methodGen, sourceFile, location.getHandle());
+ .addSourceLine(classContext, methodGen, sourceFile, location.getHandle());
bugReporter.reportBug(bug);
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindSleepWithLockHeld.java b/src/java/edu/umd/cs/findbugs/detect/FindSleepWithLockHeld.java
index fae3b2e..02a83f2 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindSleepWithLockHeld.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindSleepWithLockHeld.java
@@ -42,7 +42,7 @@ import edu.umd.cs.findbugs.ba.LockSet;
/**
* Find calls to Thread.sleep() made with a lock held.
- *
+ *
* @author David Hovemeyer
*/
public class FindSleepWithLockHeld implements Detector {
@@ -56,16 +56,19 @@ public class FindSleepWithLockHeld implements Detector {
this.bugAccumulator = new BugAccumulator(bugReporter);
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
Method[] methodList = javaClass.getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
- if (!prescreen(classContext, method))
+ if (!prescreen(classContext, method)) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -79,15 +82,18 @@ public class FindSleepWithLockHeld implements Detector {
private boolean prescreen(ClassContext classContext, Method method) {
BitSet bytecodeSet = classContext.getBytecodeSet(method);
- if (bytecodeSet == null)
+ if (bytecodeSet == null) {
return false;
+ }
// method must acquire a lock
- if (!bytecodeSet.get(Constants.MONITORENTER) && !method.isSynchronized())
+ if (!bytecodeSet.get(Constants.MONITORENTER) && !method.isSynchronized()) {
return false;
+ }
// and contain a static method invocation
- if (!bytecodeSet.get(Constants.INVOKESTATIC))
+ if (!bytecodeSet.get(Constants.INVOKESTATIC)) {
return false;
+ }
return true;
}
@@ -102,11 +108,13 @@ public class FindSleepWithLockHeld implements Detector {
Location location = i.next();
Instruction ins = location.getHandle().getInstruction();
- if (!(ins instanceof INVOKESTATIC))
+ if (!(ins instanceof INVOKESTATIC)) {
continue;
+ }
- if (!isSleep((INVOKESTATIC) ins, classContext.getConstantPoolGen()))
+ if (!isSleep((INVOKESTATIC) ins, classContext.getConstantPoolGen())) {
continue;
+ }
// System.out.println("Found sleep at " + location.getHandle());
@@ -122,14 +130,16 @@ public class FindSleepWithLockHeld implements Detector {
private boolean isSleep(INVOKESTATIC ins, ConstantPoolGen cpg) {
String className = ins.getClassName(cpg);
- if (!className.equals("java.lang.Thread"))
+ if (!"java.lang.Thread".equals(className)) {
return false;
+ }
String methodName = ins.getMethodName(cpg);
String signature = ins.getSignature(cpg);
- return methodName.equals("sleep") && (signature.equals("(J)V") || signature.equals("(JI)V"));
+ return "sleep".equals(methodName) && ("(J)V".equals(signature) || "(JI)V".equals(signature));
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindSpinLoop.java b/src/java/edu/umd/cs/findbugs/detect/FindSpinLoop.java
index e9fe8ca..97da48f 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindSpinLoop.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindSpinLoop.java
@@ -35,7 +35,7 @@ public class FindSpinLoop extends BytecodeScanningDetector implements StatelessD
int start;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private FieldAnnotation lastFieldSeen;
@@ -45,8 +45,9 @@ public class FindSpinLoop extends BytecodeScanningDetector implements StatelessD
@Override
public void visit(Method obj) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Saw " + getFullyQualifiedMethodName());
+ }
stage = 0;
}
@@ -60,40 +61,46 @@ public class FindSpinLoop extends BytecodeScanningDetector implements StatelessD
case ALOAD_2:
case ALOAD_3:
case ALOAD:
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" ALOAD at PC " + getPC());
+ }
start = getPC();
stage = 1;
break;
case GETSTATIC:
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" getfield in stage " + stage);
+ }
lastFieldSeen = FieldAnnotation.fromReferencedField(this);
start = getPC();
stage = 2;
break;
case GETFIELD:
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" getfield in stage " + stage);
+ }
lastFieldSeen = FieldAnnotation.fromReferencedField(this);
if (stage == 1 || stage == 2) {
stage = 2;
- } else
+ } else {
stage = 0;
+ }
break;
case GOTO:
case IFNE:
case IFEQ:
case IFNULL:
case IFNONNULL:
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" conditional branch in stage " + stage + " to " + getBranchTarget());
+ }
if (stage == 2 && getBranchTarget() == start) {
bugReporter.reportBug(new BugInstance(this, "SP_SPIN_ON_FIELD", NORMAL_PRIORITY).addClassAndMethod(this)
.addReferencedField(lastFieldSeen).addSourceLine(this, start));
stage = 0;
- } else if (getBranchTarget() < getPC())
+ } else if (getBranchTarget() < getPC()) {
stage = 0;
+ }
break;
default:
stage = 0;
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindSqlInjection.java b/src/java/edu/umd/cs/findbugs/detect/FindSqlInjection.java
index 748963d..d17a1d4 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindSqlInjection.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindSqlInjection.java
@@ -19,7 +19,10 @@
package edu.umd.cs.findbugs.detect;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
import java.util.regex.Pattern;
import javax.annotation.CheckForNull;
@@ -30,7 +33,6 @@ import org.apache.bcel.generic.AALOAD;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.GETFIELD;
import org.apache.bcel.generic.GETSTATIC;
-import org.apache.bcel.generic.INVOKEINTERFACE;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionHandle;
@@ -45,6 +47,7 @@ import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.Detector;
import edu.umd.cs.findbugs.SourceLineAnnotation;
+import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.ba.BasicBlock;
import edu.umd.cs.findbugs.ba.CFG;
import edu.umd.cs.findbugs.ba.CFGBuilderException;
@@ -59,6 +62,11 @@ import edu.umd.cs.findbugs.ba.type.TopType;
import edu.umd.cs.findbugs.ba.type.TypeDataflow;
import edu.umd.cs.findbugs.ba.type.TypeFrame;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+import edu.umd.cs.findbugs.detect.BuildStringPassthruGraph.MethodParameter;
+import edu.umd.cs.findbugs.detect.BuildStringPassthruGraph.StringPassthruDatabase;
+import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
/**
* Find potential SQL injection vulnerabilities.
@@ -68,6 +76,32 @@ import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
* @author Matt Hargett
*/
public class FindSqlInjection implements Detector {
+ private static final String[] PREPARE_STATEMENT_SIGNATURES = new String[] {
+ "(Ljava/lang/String;)Ljava/sql/PreparedStatement;",
+ "(Ljava/lang/String;I)Ljava/sql/PreparedStatement;",
+ "(Ljava/lang/String;II)Ljava/sql/PreparedStatement;",
+ "(Ljava/lang/String;III)Ljava/sql/PreparedStatement;",
+ "(Ljava/lang/String;[I)Ljava/sql/PreparedStatement;",
+ "(Ljava/lang/String;[Ljava/lang/String;)Ljava/sql/PreparedStatement;",
+ };
+
+ private static final MethodDescriptor[] EXECUTE_METHODS = new MethodDescriptor[] {
+ new MethodDescriptor("java/sql/Statement", "executeQuery", "(Ljava/lang/String;)Ljava/sql/ResultSet;"),
+ new MethodDescriptor("java/sql/Statement", "executeUpdate", "(Ljava/lang/String;)I"),
+ new MethodDescriptor("java/sql/Statement", "executeUpdate", "(Ljava/lang/String;I)I"),
+ new MethodDescriptor("java/sql/Statement", "executeUpdate", "(Ljava/lang/String;[I)I"),
+ new MethodDescriptor("java/sql/Statement", "executeUpdate", "(Ljava/lang/String;[Ljava/lang/String;)I"),
+ new MethodDescriptor("java/sql/Statement", "executeLargeUpdate", "(Ljava/lang/String;)J"),
+ new MethodDescriptor("java/sql/Statement", "executeLargeUpdate", "(Ljava/lang/String;I)J"),
+ new MethodDescriptor("java/sql/Statement", "executeLargeUpdate", "(Ljava/lang/String;[I)J"),
+ new MethodDescriptor("java/sql/Statement", "executeLargeUpdate", "(Ljava/lang/String;[Ljava/lang/String;)J"),
+ new MethodDescriptor("java/sql/Statement", "execute", "(Ljava/lang/String;)Z"),
+ new MethodDescriptor("java/sql/Statement", "execute", "(Ljava/lang/String;I)Z"),
+ new MethodDescriptor("java/sql/Statement", "execute", "(Ljava/lang/String;[I)Z"),
+ new MethodDescriptor("java/sql/Statement", "execute", "(Ljava/lang/String;[Ljava/lang/String;)Z"),
+ new MethodDescriptor("java/sql/Statement", "addBatch", "(Ljava/lang/String;)V"),
+ };
+
private static class StringAppendState {
// remember the smallest position at which we saw something that
// concerns us
@@ -151,19 +185,43 @@ public class FindSqlInjection implements Detector {
BugAccumulator bugAccumulator;
+ final Map<MethodDescriptor, int[]> preparedStatementMethods;
+ final Map<MethodDescriptor, int[]> executeMethods;
+ final Set<MethodDescriptor> allMethods = new HashSet<>();
+
+ private final boolean testingEnabled;
+
public FindSqlInjection(BugReporter bugReporter) {
this.bugReporter = bugReporter;
this.bugAccumulator = new BugAccumulator(bugReporter);
+ testingEnabled = SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors");
+ Set<MethodParameter> baseExecuteMethods = new HashSet<>();
+ for(MethodDescriptor executeMethod : EXECUTE_METHODS) {
+ baseExecuteMethods.add(new MethodParameter(executeMethod, 0));
+ }
+ executeMethods = Global.getAnalysisCache().getDatabase(StringPassthruDatabase.class).findLinkedMethods(baseExecuteMethods);
+ Set<MethodParameter> basePrepareMethods = new HashSet<>();
+ for(String signature : PREPARE_STATEMENT_SIGNATURES) {
+ basePrepareMethods.add(new MethodParameter(new MethodDescriptor("java/sql/Connection", "prepareStatement", signature), 0));
+ }
+ preparedStatementMethods = Global.getAnalysisCache().getDatabase(StringPassthruDatabase.class).findLinkedMethods(basePrepareMethods);
+ allMethods.addAll(executeMethods.keySet());
+ allMethods.addAll(preparedStatementMethods.keySet());
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
+ if(!PreorderVisitor.hasInterestingMethod(javaClass.getConstantPool(), allMethods)) {
+ return;
+ }
Method[] methodList = javaClass.getMethods();
for (Method method : methodList) {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -187,7 +245,7 @@ public class FindSqlInjection implements Detector {
if (ins instanceof INVOKEVIRTUAL) {
INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) ins;
- if (invoke.getMethodName(cpg).equals("append") && invoke.getClassName(cpg).startsWith("java.lang.StringB")) {
+ if ("append".equals(invoke.getMethodName(cpg)) && invoke.getClassName(cpg).startsWith("java.lang.StringB")) {
String sig = invoke.getSignature(cpg);
char firstChar = sig.charAt(1);
return firstChar == '[' || firstChar == 'L';
@@ -223,7 +281,7 @@ public class FindSqlInjection implements Detector {
}
private StringAppendState updateStringAppendState(Location location, ConstantPoolGen cpg, StringAppendState stringAppendState)
- {
+ {
InstructionHandle handle = location.getHandle();
Instruction ins = handle.getInstruction();
if (!isConstantStringLoad(location, cpg)) {
@@ -233,54 +291,17 @@ public class FindSqlInjection implements Detector {
LDC load = (LDC) ins;
Object value = load.getValue(cpg);
String stringValue = ((String) value).trim();
- if (stringValue.startsWith(",") || stringValue.endsWith(","))
+ if (stringValue.startsWith(",") || stringValue.endsWith(",")) {
stringAppendState.setSawComma(handle);
- if (isCloseQuote(stringValue) && stringAppendState.getSawOpenQuote(handle))
- stringAppendState.setSawCloseQuote(handle);
- if (isOpenQuote(stringValue))
- stringAppendState.setSawOpenQuote(handle);
-
- return stringAppendState;
- }
-
- private boolean isPreparedStatementDatabaseSink(Instruction ins, ConstantPoolGen cpg) {
- if (!(ins instanceof INVOKEINTERFACE)) {
- return false;
- }
-
- INVOKEINTERFACE invoke = (INVOKEINTERFACE) ins;
-
- String methodName = invoke.getMethodName(cpg);
- String methodSignature = invoke.getSignature(cpg);
- String interfaceName = invoke.getClassName(cpg);
- if (methodName.equals("prepareStatement") && interfaceName.equals("java.sql.Connection")
- && methodSignature.startsWith("(Ljava/lang/String;")) {
- return true;
}
-
- return false;
- }
-
- private boolean isExecuteDatabaseSink(InvokeInstruction ins, ConstantPoolGen cpg) {
- if (!(ins instanceof INVOKEINTERFACE)) {
- return false;
+ if (isCloseQuote(stringValue) && stringAppendState.getSawOpenQuote(handle)) {
+ stringAppendState.setSawCloseQuote(handle);
}
-
- INVOKEINTERFACE invoke = (INVOKEINTERFACE) ins;
-
- String methodName = invoke.getMethodName(cpg);
- String methodSignature = invoke.getSignature(cpg);
- String interfaceName = invoke.getClassName(cpg);
- if (methodName.startsWith("execute") && interfaceName.equals("java.sql.Statement")
- && methodSignature.startsWith("(Ljava/lang/String;")) {
- return true;
+ if (isOpenQuote(stringValue)) {
+ stringAppendState.setSawOpenQuote(handle);
}
- return false;
- }
-
- private boolean isDatabaseSink(InvokeInstruction ins, ConstantPoolGen cpg) {
- return isPreparedStatementDatabaseSink(ins, cpg) || isExecuteDatabaseSink(ins, cpg);
+ return stringAppendState;
}
private StringAppendState getStringAppendState(CFG cfg, ConstantPoolGen cpg) throws CFGBuilderException {
@@ -288,8 +309,9 @@ public class FindSqlInjection implements Detector {
String sig = method.getSignature();
sig = sig.substring(0, sig.indexOf(')'));
- if (sig.indexOf("java/lang/String") >= 0)
+ if (sig.indexOf("java/lang/String") >= 0) {
stringAppendState.setSawInitialTaint();
+ }
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
InstructionHandle handle = location.getHandle();
@@ -300,8 +322,9 @@ public class FindSqlInjection implements Detector {
stringAppendState.setSawAppend(handle);
Location prevLocation = getPreviousLocation(cfg, location, true);
- if (prevLocation != null && !isSafeValue(prevLocation, cpg))
+ if (prevLocation != null && !isSafeValue(prevLocation, cpg)) {
stringAppendState.setSawUnsafeAppend(handle);
+ }
} else if (ins instanceof InvokeInstruction) {
InvokeInstruction inv = (InvokeInstruction) ins;
@@ -311,8 +334,8 @@ public class FindSqlInjection implements Detector {
if (sig2.indexOf("java/lang/String") >= 0) {
String methodName = inv.getMethodName(cpg);
String className = inv.getClassName(cpg);
- if (methodName.equals("valueOf") && className.equals("java.lang.String")
- && sig1.equals("(Ljava/lang/Object;)Ljava/lang/String;")) {
+ if ("valueOf".equals(methodName) && "java.lang.String".equals(className)
+ && "(Ljava/lang/Object;)Ljava/lang/String;".equals(sig1)) {
try {
TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
TypeFrame frame = typeDataflow.getFactAtLocation(location);
@@ -326,15 +349,16 @@ public class FindSqlInjection implements Detector {
continue;
}
String sig3 = operandType.getSignature();
- if (!sig3.equals("Ljava/lang/String;"))
+ if (!"Ljava/lang/String;".equals(sig3)) {
stringAppendState.setSawTaint(handle);
+ }
} catch (CheckedAnalysisException e) {
stringAppendState.setSawTaint(handle);
}
- } else if (className.startsWith("java.lang.String") || className.equals("java.lang.Long")
- || className.equals("java.lang.Integer") || className.equals("java.lang.Float")
- || className.equals("java.lang.Double") || className.equals("java.lang.Short")
- || className.equals("java.lang.Byte") || className.equals("java.lang.Character")) {
+ } else if (className.startsWith("java.lang.String") || "java.lang.Long".equals(className)
+ || "java.lang.Integer".equals(className) || "java.lang.Float".equals(className)
+ || "java.lang.Double".equals(className) || "java.lang.Short".equals(className)
+ || "java.lang.Byte".equals(className) || "java.lang.Character".equals(className)) {
// ignore it
assert true;
} else if (methodName.startsWith("to") && methodName.endsWith("String") && methodName.length() > 8) {
@@ -343,15 +367,17 @@ public class FindSqlInjection implements Detector {
} else if (className.startsWith("javax.servlet") && methodName.startsWith("get")) {
stringAppendState.setSawTaint(handle);
stringAppendState.setSawSeriousTaint(handle);
- } else
+ } else {
stringAppendState.setSawTaint(handle);
+ }
}
} else if (ins instanceof GETFIELD) {
GETFIELD getfield = (GETFIELD) ins;
String sig2 = getfield.getSignature(cpg);
- if (sig2.indexOf("java/lang/String") >= 0)
+ if (sig2.indexOf("java/lang/String") >= 0) {
stringAppendState.setSawTaint(handle);
+ }
}
}
@@ -360,12 +386,14 @@ public class FindSqlInjection implements Detector {
private boolean isSafeValue(Location location, ConstantPoolGen cpg) throws CFGBuilderException {
Instruction prevIns = location.getHandle().getInstruction();
- if (prevIns instanceof LDC || prevIns instanceof GETSTATIC)
+ if (prevIns instanceof LDC || prevIns instanceof GETSTATIC) {
return true;
+ }
if (prevIns instanceof InvokeInstruction) {
String methodName = ((InvokeInstruction) prevIns).getMethodName(cpg);
- if (methodName.startsWith("to") && methodName.endsWith("String") && methodName.length() > 8)
+ if (methodName.startsWith("to") && methodName.endsWith("String") && methodName.length() > 8) {
return true;
+ }
}
if (prevIns instanceof AALOAD) {
CFG cfg = classContext.getCFG(method);
@@ -375,8 +403,9 @@ public class FindSqlInjection implements Detector {
Location prev2 = getPreviousLocation(cfg, prev, true);
if (prev2 != null && prev2.getHandle().getInstruction() instanceof GETSTATIC) {
GETSTATIC getStatic = (GETSTATIC) prev2.getHandle().getInstruction();
- if (getStatic.getSignature(cpg).equals("[Ljava/lang/String;"))
+ if ("[Ljava/lang/String;".equals(getStatic.getSignature(cpg))) {
return true;
+ }
}
}
}
@@ -399,23 +428,24 @@ public class FindSqlInjection implements Detector {
Location getPreviousLocation(CFG cfg, Location startLocation, boolean skipNops) {
Location loc = startLocation;
InstructionHandle prev = getPreviousInstruction(loc.getHandle(), skipNops);
- if (prev != null)
+ if (prev != null) {
return new Location(prev, loc.getBasicBlock());
+ }
BasicBlock block = loc.getBasicBlock();
while (true) {
block = cfg.getPredecessorWithEdgeType(block, EdgeTypes.FALL_THROUGH_EDGE);
- if (block == null)
+ if (block == null) {
return null;
+ }
InstructionHandle lastInstruction = block.getLastInstruction();
- if (lastInstruction != null)
+ if (lastInstruction != null) {
return new Location(lastInstruction, block);
+ }
}
}
private BugInstance generateBugInstance(JavaClass javaClass, MethodGen methodGen, InstructionHandle handle,
- StringAppendState stringAppendState) {
- Instruction instruction = handle.getInstruction();
- ConstantPoolGen cpg = methodGen.getConstantPool();
+ StringAppendState stringAppendState, boolean isExecute) {
int priority = LOW_PRIORITY;
boolean sawSeriousTaint = false;
if (stringAppendState.getSawAppend(handle)) {
@@ -436,18 +466,20 @@ public class FindSqlInjection implements Detector {
}
String description = "TESTING";
- if (instruction instanceof InvokeInstruction && isExecuteDatabaseSink((InvokeInstruction) instruction, cpg)) {
+ if (isExecute) {
description = "SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE";
- } else if (isPreparedStatementDatabaseSink(instruction, cpg)) {
+ } else {
description = "SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING";
}
BugInstance bug = new BugInstance(this, description, priority);
bug.addClassAndMethod(methodGen, javaClass.getSourceFileName());
- if (description.equals("TESTING"))
+ if ("TESTING".equals(description)) {
bug.addString("Incomplete report invoking non-constant SQL string");
- if (sawSeriousTaint)
+ }
+ if (sawSeriousTaint) {
bug.addString("non-constant SQL string involving HTTP taint");
+ }
return bug;
}
@@ -461,8 +493,9 @@ public class FindSqlInjection implements Detector {
this.method = method;
this.classContext = classContext;
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
ConstantPoolGen cpg = methodGen.getConstantPool();
CFG cfg = classContext.getCFG(method);
@@ -473,35 +506,55 @@ public class FindSqlInjection implements Detector {
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
Instruction ins = location.getHandle().getInstruction();
- if (!(ins instanceof InvokeInstruction))
+ if (!(ins instanceof InvokeInstruction)) {
continue;
+ }
InvokeInstruction invoke = (InvokeInstruction) ins;
- if (isDatabaseSink(invoke, cpg)) {
- ConstantFrame frame = dataflow.getFactAtLocation(location);
- int numArguments = frame.getNumArguments(invoke, cpg);
- Constant value = frame.getStackValue(numArguments - 1);
-
- if (!value.isConstantString()) {
- // TODO: verify it's the same string represented by
- // stringAppendState
- // FIXME: will false positive on const/static strings
- // returns by methods
- Location prev = getPreviousLocation(cfg, location, true);
- if (prev == null || !isSafeValue(prev, cpg)) {
- BugInstance bug = generateBugInstance(javaClass, methodGen, location.getHandle(), stringAppendState);
- bugAccumulator.accumulateBug(
- bug,
- SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
- javaClass.getSourceFileName(), location.getHandle()));
+ MethodDescriptor md = new MethodDescriptor(invoke, cpg);
+ boolean executeMethod;
+ int[] params = preparedStatementMethods.get(md);
+ int paramNumber;
+ // Currently only one method parameter is checked, though it's the most common case
+ // TODO: support methods which take several SQL statements
+ if(params != null) {
+ executeMethod = false;
+ paramNumber = params[0];
+ } else {
+ params = executeMethods.get(md);
+ if(params != null) {
+ executeMethod = true;
+ paramNumber = params[0];
+ } else {
+ continue;
+ }
+ }
+ ConstantFrame frame = dataflow.getFactAtLocation(location);
+ int numArguments = frame.getNumArguments(invoke, cpg);
+ Constant value = frame.getStackValue(numArguments - 1 - paramNumber);
+
+ if (!value.isConstantString()) {
+ // TODO: verify it's the same string represented by
+ // stringAppendState
+ // FIXME: will false positive on const/static strings
+ // returns by methods
+ Location prev = getPreviousLocation(cfg, location, true);
+ if (prev == null || !isSafeValue(prev, cpg)) {
+ BugInstance bug = generateBugInstance(javaClass, methodGen, location.getHandle(), stringAppendState, executeMethod);
+ if(!testingEnabled && "TESTING".equals(bug.getType())){
+ continue;
}
+ bugAccumulator.accumulateBug(
+ bug,
+ SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
+ javaClass.getSourceFileName(), location.getHandle()));
}
}
}
bugAccumulator.reportAccumulatedBugs();
}
+ @Override
public void report() {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindTwoLockWait.java b/src/java/edu/umd/cs/findbugs/detect/FindTwoLockWait.java
index 3a67094..e812086 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindTwoLockWait.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindTwoLockWait.java
@@ -47,13 +47,13 @@ import edu.umd.cs.findbugs.ba.LockDataflow;
public final class FindTwoLockWait implements Detector, StatelessDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private JavaClass javaClass;
- private Collection<BugInstance> possibleWaitBugs = new LinkedList<BugInstance>();
+ private final Collection<BugInstance> possibleWaitBugs = new LinkedList<BugInstance>();
- private Collection<SourceLineAnnotation> possibleNotifyLocations = new LinkedList<SourceLineAnnotation>();
+ private final Collection<SourceLineAnnotation> possibleNotifyLocations = new LinkedList<SourceLineAnnotation>();
public FindTwoLockWait(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -68,6 +68,7 @@ public final class FindTwoLockWait implements Detector, StatelessDetector {
}
}
+ @Override
public void visitClassContext(ClassContext classContext) {
javaClass = classContext.getJavaClass();
possibleWaitBugs.clear();
@@ -75,11 +76,13 @@ public final class FindTwoLockWait implements Detector, StatelessDetector {
Method[] methodList = javaClass.getMethods();
for (Method method : methodList) {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
continue;
+ }
- if (!preScreen(methodGen))
+ if (!preScreen(methodGen)) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -90,12 +93,14 @@ public final class FindTwoLockWait implements Detector, StatelessDetector {
bugReporter.logError("Error analyzing " + method.toString(), e);
}
}
- if (!possibleNotifyLocations.isEmpty())
+ if (!possibleNotifyLocations.isEmpty()) {
for (BugInstance bug : possibleWaitBugs) {
- for (SourceLineAnnotation notifyLine : possibleNotifyLocations)
+ for (SourceLineAnnotation notifyLine : possibleNotifyLocations) {
bug.addSourceLine(notifyLine).describe("SOURCE_NOTIFICATION_DEADLOCK");
+ }
bugReporter.reportBug(bug);
}
+ }
}
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {
@@ -119,13 +124,14 @@ public final class FindTwoLockWait implements Detector, StatelessDetector {
InstructionHandle handle = mg.getInstructionList().getStart();
while (handle != null && !(lockCount >= 2 && sawWaitOrNotify)) {
Instruction ins = handle.getInstruction();
- if (ins instanceof MONITORENTER)
+ if (ins instanceof MONITORENTER) {
++lockCount;
- else if (ins instanceof INVOKEVIRTUAL) {
+ } else if (ins instanceof INVOKEVIRTUAL) {
INVOKEVIRTUAL inv = (INVOKEVIRTUAL) ins;
String methodName = inv.getMethodName(cpg);
- if (methodName.equals("wait") || methodName.startsWith("notify"))
+ if ("wait".equals(methodName) || methodName.startsWith("notify")) {
sawWaitOrNotify = true;
+ }
}
handle = handle.getNext();
@@ -158,8 +164,8 @@ public final class FindTwoLockWait implements Detector, StatelessDetector {
}
}
+ @Override
public void report() {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindUncalledPrivateMethods.java b/src/java/edu/umd/cs/findbugs/detect/FindUncalledPrivateMethods.java
index cddead8..d1ea93a 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindUncalledPrivateMethods.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindUncalledPrivateMethods.java
@@ -22,6 +22,12 @@ package edu.umd.cs.findbugs.detect;
import java.util.HashSet;
import org.apache.bcel.classfile.AnnotationEntry;
+import org.apache.bcel.classfile.Constant;
+import org.apache.bcel.classfile.ConstantCP;
+import org.apache.bcel.classfile.ConstantMethodHandle;
+import org.apache.bcel.classfile.ConstantNameAndType;
+import org.apache.bcel.classfile.ConstantPool;
+import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.Method;
import edu.umd.cs.findbugs.BugInstance;
@@ -30,12 +36,13 @@ import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.MethodAnnotation;
import edu.umd.cs.findbugs.StatelessDetector;
import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.util.ClassName;
/**
* Detector to find private methods that are never called.
*/
public class FindUncalledPrivateMethods extends BytecodeScanningDetector implements StatelessDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private String className;
@@ -49,18 +56,23 @@ public class FindUncalledPrivateMethods extends BytecodeScanningDetector impleme
@Override
public void visitMethod(Method obj) {
+ if (!obj.isPrivate() || obj.isSynthetic()) {
+ return;
+ }
super.visitMethod(obj);
- if (obj.isPrivate() && !getMethodName().equals("writeReplace") && !getMethodName().equals("readResolve")
- && !getMethodName().equals("readObject") && !getMethodName().equals("readObjectNoData")
- && !getMethodName().equals("writeObject") && getMethodName().indexOf("debug") == -1
- && getMethodName().indexOf("Debug") == -1 && getMethodName().indexOf("trace") == -1
- && getMethodName().indexOf("Trace") == -1 && !getMethodName().equals("<init>")
- && !getMethodName().equals("<clinit>")) {
+ String methodName = getMethodName();
+ if (!"writeReplace".equals(methodName) && !"readResolve".equals(methodName)
+ && !"readObject".equals(methodName) && !"readObjectNoData".equals(methodName)
+ && !"writeObject".equals(methodName)
+ && methodName.indexOf("debug") == -1 && methodName.indexOf("Debug") == -1
+ && methodName.indexOf("trace") == -1 && methodName.indexOf("Trace") == -1
+ && !"<init>".equals(methodName) && !"<clinit>".equals(methodName)) {
for(AnnotationEntry a : obj.getAnnotationEntries()) {
String typeName = a.getAnnotationType();
- if (typeName.equals("Ljavax/annotation/PostConstruct;")
- || typeName.equals("Ljavax/annotation/PreDestroy;"))
+ if ("Ljavax/annotation/PostConstruct;".equals(typeName)
+ || "Ljavax/annotation/PreDestroy;".equals(typeName)) {
return;
+ }
}
definedPrivateMethods.add(MethodAnnotation.fromVisitedMethod(this));
}
@@ -78,8 +90,6 @@ public class FindUncalledPrivateMethods extends BytecodeScanningDetector impleme
seen == INVOKESTATIC);
calledMethods.add(called);
calledMethodNames.add(getNameConstantOperand().toLowerCase());
- // System.out.println("Saw call to " + called);
-
}
break;
default:
@@ -95,6 +105,26 @@ public class FindUncalledPrivateMethods extends BytecodeScanningDetector impleme
className = classContext.getJavaClass().getClassName();
String[] parts = className.split("[$+.]");
String simpleClassName = parts[parts.length - 1];
+
+ ConstantPool cp = classContext.getJavaClass().getConstantPool();
+ for(Constant constant : cp.getConstantPool()) {
+ if(constant instanceof ConstantMethodHandle) {
+ int kind = ((ConstantMethodHandle) constant).getReferenceKind();
+ if(kind >= 5 && kind <= 9) {
+ Constant ref = cp.getConstant(((ConstantMethodHandle)constant).getReferenceIndex());
+ if(ref instanceof ConstantCP) {
+ String className = cp.getConstantString(((ConstantCP) ref).getClassIndex(), CONSTANT_Class);
+ ConstantNameAndType nameAndType = (ConstantNameAndType) cp.getConstant(((ConstantCP) ref).getNameAndTypeIndex());
+ String name = ((ConstantUtf8)cp.getConstant(nameAndType.getNameIndex())).getBytes();
+ String signature = ((ConstantUtf8)cp.getConstant(nameAndType.getSignatureIndex())).getBytes();
+ MethodAnnotation called = new MethodAnnotation(ClassName.toDottedClassName(className), name, signature, kind==6 /* invokestatic */);
+ calledMethods.add(called);
+ calledMethodNames.add(name.toLowerCase());
+ }
+ }
+ }
+ }
+
super.visitClassContext(classContext);
definedPrivateMethods.removeAll(calledMethods);
@@ -103,10 +133,12 @@ public class FindUncalledPrivateMethods extends BytecodeScanningDetector impleme
// System.out.println("Checking " + m);
int priority = LOW_PRIORITY;
String methodName = m.getMethodName();
- if (methodName.equals(simpleClassName) && m.getMethodSignature().equals("()V"))
+ if (methodName.equals(simpleClassName) && "()V".equals(m.getMethodSignature())) {
continue;
- if (methodName.length() > 1 && calledMethodNames.contains(methodName.toLowerCase()))
+ }
+ if (methodName.length() > 1 && calledMethodNames.contains(methodName.toLowerCase())) {
priority = NORMAL_PRIORITY;
+ }
BugInstance bugInstance = new BugInstance(this, "UPM_UNCALLED_PRIVATE_METHOD", priority).addClass(this).addMethod(m);
bugReporter.reportBug(bugInstance);
}
@@ -116,4 +148,3 @@ public class FindUncalledPrivateMethods extends BytecodeScanningDetector impleme
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindUnconditionalWait.java b/src/java/edu/umd/cs/findbugs/detect/FindUnconditionalWait.java
index 16f59f9..0236851 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindUnconditionalWait.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindUnconditionalWait.java
@@ -36,7 +36,7 @@ import edu.umd.cs.findbugs.StatelessDetector;
public class FindUnconditionalWait extends BytecodeScanningDetector implements StatelessDetector {
int stage = 0;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public FindUnconditionalWait(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -49,25 +49,29 @@ public class FindUnconditionalWait extends BytecodeScanningDetector implements S
@Override
public void sawBranchTo(int target) {
- if (stage == 1)
+ if (stage == 1) {
stage = 0;
+ }
}
@Override
public void sawOpcode(int seen) {
switch (stage) {
case 0:
- if (seen == MONITORENTER)
+ if (seen == MONITORENTER) {
stage = 1;
+ }
break;
case 1:
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("wait")) {
+ if (seen == INVOKEVIRTUAL && "wait".equals(getNameConstantOperand())) {
bugReporter.reportBug(new BugInstance(this, "UW_UNCOND_WAIT",
- getSigConstantOperand().equals("()V") ? NORMAL_PRIORITY : LOW_PRIORITY).addClassAndMethod(this)
+ "()V".equals(getSigConstantOperand()) ? NORMAL_PRIORITY : LOW_PRIORITY).addClassAndMethod(this)
.addSourceLine(this));
stage = 2;
}
break;
+ default:
+ break;
}
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindUninitializedGet.java b/src/java/edu/umd/cs/findbugs/detect/FindUninitializedGet.java
index 59011d2..4715358 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindUninitializedGet.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindUninitializedGet.java
@@ -58,7 +58,7 @@ public class FindUninitializedGet extends BytecodeScanningDetector implements St
boolean thisOnTOS = false;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public FindUninitializedGet(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -82,8 +82,9 @@ public class FindUninitializedGet extends BytecodeScanningDetector implements St
@Override
public void visitAnnotation(String annotationClass, Map<String, ElementValue> map, boolean runtimeVisible) {
- if (!visitingField())
+ if (!visitingField()) {
return;
+ }
if (UnreadFields.isInjectionAttribute(annotationClass)) {
containerFields.add(FieldAnnotation.fromVisitedField(this));
}
@@ -96,14 +97,15 @@ public class FindUninitializedGet extends BytecodeScanningDetector implements St
initializedFields.clear();
thisOnTOS = false;
- inConstructor = getMethodName().equals("<init>") && getMethodSig().indexOf(getClassName()) == -1;
+ inConstructor = "<init>".equals(getMethodName()) && getMethodSig().indexOf(getClassName()) == -1;
}
@Override
public void visit(Code obj) {
- if (!inConstructor)
+ if (!inConstructor) {
return;
+ }
uninitializedFieldReadAndCheckedForNonnull = null;
super.visit(obj);
for (BugInstance bug : pendingBugs) {
@@ -117,18 +119,21 @@ public class FindUninitializedGet extends BytecodeScanningDetector implements St
Iterator<BugInstance> i = pendingBugs.iterator();
while (i.hasNext()) {
BugInstance bug = i.next();
- if (bug.getPrimarySourceLineAnnotation().getStartBytecode() >= target)
+ if (bug.getPrimarySourceLineAnnotation().getStartBytecode() >= target) {
i.remove();
+ }
}
}
@Override
public void sawOpcode(int seen) {
- if (!inConstructor)
+ if (!inConstructor) {
return;
+ }
if (uninitializedFieldReadAndCheckedForNonnull != null) {
- if (seen == NEW && getClassConstantOperand().endsWith("Exception"))
+ if (seen == NEW && getClassConstantOperand().endsWith("Exception")) {
uninitializedFieldReadAndCheckedForNonnull.raisePriority();
+ }
uninitializedFieldReadAndCheckedForNonnull = null;
}
@@ -137,10 +142,9 @@ public class FindUninitializedGet extends BytecodeScanningDetector implements St
return;
}
- if (seen == PUTFIELD && getClassConstantOperand().equals(getClassName()))
+ if (seen == PUTFIELD && getClassConstantOperand().equals(getClassName())) {
initializedFields.add(FieldAnnotation.fromReferencedField(this));
-
- else if (thisOnTOS && seen == GETFIELD && getClassConstantOperand().equals(getClassName())) {
+ } else if (thisOnTOS && seen == GETFIELD && getClassConstantOperand().equals(getClassName())) {
UnreadFieldsData unreadFields = AnalysisContext.currentAnalysisContext().getUnreadFieldsData();
XField xField = XFactory.createReferencedXField(this);
FieldAnnotation f = FieldAnnotation.fromReferencedField(this);
@@ -151,18 +155,19 @@ public class FindUninitializedGet extends BytecodeScanningDetector implements St
// OPCODE_NAMES[nextOpcode]);
LocalVariableAnnotation possibleTarget = LocalVariableAnnotation.findMatchingIgnoredParameter(getClassContext(),
getMethod(), getNameConstantOperand(), xField.getSignature());
- if (possibleTarget == null)
+ if (possibleTarget == null) {
possibleTarget = LocalVariableAnnotation.findUniqueBestMatchingParameter(getClassContext(), getMethod(),
getNameConstantOperand(), getSigConstantOperand());
+ }
int priority = unreadFields.getReadFields().contains(xField) ? NORMAL_PRIORITY : LOW_PRIORITY;
boolean priorityLoweredBecauseOfIfNonnullTest = false;
- if (possibleTarget != null)
+ if (possibleTarget != null) {
priority--;
- else {
+ } else {
FieldSummary fieldSummary = AnalysisContext.currentAnalysisContext().getFieldSummary();
- if (fieldSummary.callsOverriddenMethodsFromSuperConstructor(getClassDescriptor()))
+ if (fieldSummary.callsOverriddenMethodsFromSuperConstructor(getClassDescriptor())) {
priority++;
- else if (nextOpcode == IFNONNULL) {
+ } else if (nextOpcode == IFNONNULL) {
priority++;
priorityLoweredBecauseOfIfNonnullTest = true;
}
@@ -176,12 +181,11 @@ public class FindUninitializedGet extends BytecodeScanningDetector implements St
}
initializedFields.add(f);
}
- } else if ((seen == INVOKESPECIAL && !(getNameConstantOperand().equals("<init>") && !getClassConstantOperand().equals(
+ } else if ((seen == INVOKESPECIAL && !("<init>".equals(getNameConstantOperand()) && !getClassConstantOperand().equals(
getClassName())))
- || (seen == INVOKESTATIC && getNameConstantOperand().equals("doPrivileged") && getClassConstantOperand().equals(
- "java/security/AccessController"))
- || (seen == INVOKEVIRTUAL && getClassConstantOperand().equals(getClassName()))
- || (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("start"))) {
+ || (seen == INVOKESTATIC && "doPrivileged".equals(getNameConstantOperand()) && "java/security/AccessController".equals(getClassConstantOperand()))
+ || (seen == INVOKEVIRTUAL && getClassConstantOperand().equals(getClassName()))
+ || (seen == INVOKEVIRTUAL && "start".equals(getNameConstantOperand()))) {
inConstructor = false;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindUnrelatedTypesInGenericContainer.java b/src/java/edu/umd/cs/findbugs/detect/FindUnrelatedTypesInGenericContainer.java
index 7b93353..b0b409a 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindUnrelatedTypesInGenericContainer.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindUnrelatedTypesInGenericContainer.java
@@ -245,13 +245,15 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
*
* @see edu.umd.cs.findbugs.Detector#visitClassContext(edu.umd.cs.findbugs.ba.ClassContext)
*/
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
Method[] methodList = javaClass.getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -259,11 +261,11 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
assert true; // move along; nothing to see
} catch (CFGBuilderException e) {
String msg = "Detector " + this.getClass().getName() + " caught exception while analyzing "
- + javaClass.getClassName() + "." + method.getName() + " : " + method.getSignature();
+ + javaClass.getClassName() + "." + method.getName() + " : " + method.getSignature();
bugReporter.logError(msg, e);
} catch (DataflowAnalysisException e) {
String msg = "Detector " + this.getClass().getName() + " caught exception while analyzing "
- + javaClass.getClassName() + "." + method.getName() + " : " + method.getSignature();
+ + javaClass.getClassName() + "." + method.getName() + " : " + method.getSignature();
bugReporter.logError(msg, e);
}
}
@@ -275,9 +277,9 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
public boolean prescreen(ClassContext classContext, Method method) {
BitSet bytecodeSet = classContext.getBytecodeSet(method);
return bytecodeSet != null
- && (bytecodeSet.get(Constants.INVOKEINTERFACE) || bytecodeSet.get(Constants.INVOKEVIRTUAL)
- || bytecodeSet.get(Constants.INVOKESPECIAL) || bytecodeSet.get(Constants.INVOKESTATIC) || bytecodeSet
- .get(Constants.INVOKENONVIRTUAL));
+ && (bytecodeSet.get(Constants.INVOKEINTERFACE) || bytecodeSet.get(Constants.INVOKEVIRTUAL)
+ || bytecodeSet.get(Constants.INVOKESPECIAL) || bytecodeSet.get(Constants.INVOKESTATIC) || bytecodeSet
+ .get(Constants.INVOKENONVIRTUAL));
}
/**
@@ -285,12 +287,14 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
* code
*/
private boolean isSynthetic(Method m) {
- if ((m.getAccessFlags() & Constants.ACC_SYNTHETIC) != 0)
+ if ((m.getAccessFlags() & Constants.ACC_SYNTHETIC) != 0) {
return true;
+ }
Attribute[] attrs = m.getAttributes();
for (Attribute attr : attrs) {
- if (attr instanceof Synthetic)
+ if (attr instanceof Synthetic) {
return true;
+ }
}
return false;
}
@@ -300,14 +304,15 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
static {
baseGenericTypes.addAll(Arrays.asList(new String[] { "java.util.Map", "java.util.Collection", "java.lang.Iterable",
"java.util.Iterator", "com.google.common.collect.Multimap", "com.google.common.collect.Multiset",
- "com.google.common.collect.Table" }));
+ "com.google.common.collect.Table" }));
}
private boolean isGenericCollection(ClassDescriptor operandClass) {
String dottedClassName = operandClass.getDottedClassName();
- if (baseGenericTypes.contains(dottedClassName))
+ if (baseGenericTypes.contains(dottedClassName)) {
return true;
+ }
String found = null;
for(String c : baseGenericTypes) {
@@ -316,42 +321,52 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
break;
}
}
- if (found == null)
+ if (found == null) {
return false;
- if (dottedClassName.startsWith("java.util.") || dottedClassName.startsWith("com.google.common.collect.") )
+ }
+ if (dottedClassName.startsWith("java.util.") || dottedClassName.startsWith("com.google.common.collect.") ) {
return true;
+ }
try {
XClass xclass = Global.getAnalysisCache().getClassAnalysis(XClass.class, operandClass);
String sig = xclass.getSourceSignature();
- if (sig == null)
+ if (sig == null) {
return false;
+ }
String typeParameter = null;
List<String> split = GenericUtilities.split(sig, true);
if (sig.charAt(0) == '<') {
int end = sig.indexOf(':');
- if (end > 0)
+ if (end > 0) {
typeParameter = sig.substring(1, end);
+ }
}
- if (DEBUG) System.out.println(dottedClassName + " " + typeParameter + " " + split);
+ if (DEBUG) {
+ System.out.println(dottedClassName + " " + typeParameter + " " + split);
+ }
for (String s : split) {
int i = s.indexOf('<');
- if (i < 0)
+ if (i < 0) {
continue;
- if (s.charAt(0) != 'L')
+ }
+ if (s.charAt(0) != 'L') {
throw new IllegalStateException("unexpected non signature: " + s);
+ }
ClassDescriptor c = DescriptorFactory.createClassDescriptor(s.substring(1, i));
String superTypeParameter = s.substring(i+1);
if (isGenericCollection(c) && (typeParameter == null || superTypeParameter.startsWith("T" + typeParameter))) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println(operandClass + " is a subtype of " + s);
+ }
return true;
}
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Not a subtype");
+ }
} catch (CheckedAnalysisException e1) {
@@ -361,11 +376,13 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
}
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {
- if (isSynthetic(method) || !prescreen(classContext, method))
+ if (isSynthetic(method) || !prescreen(classContext, method)) {
return;
+ }
XMethod xmethod = XFactory.createXMethod(classContext.getJavaClass(), method);
- if (xmethod.isSynthetic())
+ if (xmethod.isSynthetic()) {
return;
+ }
BugAccumulator accumulator = new BugAccumulator(bugReporter);
@@ -375,8 +392,9 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
ConstantPoolGen cpg = classContext.getConstantPoolGen();
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
String fullMethodName = methodGen.getClassName() + "." + methodGen.getName();
String sourceFile = classContext.getJavaClass().getSourceFileName();
@@ -391,8 +409,9 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
Instruction ins = handle.getInstruction();
// Only consider invoke instructions
- if (!(ins instanceof InvokeInstruction))
+ if (!(ins instanceof InvokeInstruction)) {
continue;
+ }
InvokeInstruction inv = (InvokeInstruction) ins;
@@ -405,18 +424,21 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
SignatureParser sigParser = new SignatureParser(inv.getSignature(cpg));
Collection<Info> collection = callMap.get(call);
- if (!callMap.containsKey(call))
+ if (!callMap.containsKey(call)) {
continue;
+ }
for(Info info : collection) {
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("at " + handle.getPosition() + " Checking call to " + info.interfaceForCall + " : " + invokedMethod);
+ }
try {
- if (!subtypes2.isSubtype(invokedMethod.getClassDescriptor(), info.interfaceForCall))
+ if (!subtypes2.isSubtype(invokedMethod.getClassDescriptor(), info.interfaceForCall)) {
continue;
+ }
} catch (ClassNotFoundException e) {
- if (info.interfaceForCall.getClassName().equals("java/util/Collection")
- && invokedMethod.getClassName().equals("com.google.common.collect.Multiset")) {
+ if ("java/util/Collection".equals(info.interfaceForCall.getClassName())
+ && "com.google.common.collect.Multiset".equals(invokedMethod.getClassName())) {
assert true;
// we know this is OK without needing to find definition of Multiset
} else {
@@ -439,10 +461,11 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
int lhsPos;
- if (inv instanceof INVOKESTATIC)
+ if (inv instanceof INVOKESTATIC) {
lhsPos = sigParser.getSlotsFromTopOfStackForParameter(0);
- else
+ } else {
lhsPos = sigParser.getTotalArgumentSize();
+ }
int stackPos = sigParser.getSlotsFromTopOfStackForParameter(pos);
@@ -477,7 +500,7 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
if (objectVN.equals(argVN)) {
String bugPattern = "DMI_COLLECTIONS_SHOULD_NOT_CONTAIN_THEMSELVES";
int priority = HIGH_PRIORITY;
- if (invokedMethodName.equals("removeAll")) {
+ if ("removeAll".equals(invokedMethodName)) {
bugPattern = "DMI_USING_REMOVEALL_TO_CLEAR_COLLECTION";
priority = NORMAL_PRIORITY;
} else if (invokedMethodName.endsWith("All")) {
@@ -491,8 +514,9 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
if (nextIns instanceof InvokeInstruction) {
XMethod nextMethod = XFactory.createXMethod((InvokeInstruction) nextIns, cpg);
- if (nextMethod.getName().equals("assertFalse"))
+ if ("assertFalse".equals(nextMethod.getName())) {
continue;
+ }
}
}
}
@@ -508,41 +532,48 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
// Only consider generic...
Type objectType = frame.getStackValue(lhsPos);
- if (!(objectType instanceof GenericObjectType))
+ if (!(objectType instanceof GenericObjectType)) {
continue;
+ }
GenericObjectType operand = (GenericObjectType) objectType;
int expectedTypeParameters = 1;
String simpleName = info.interfaceForCall.getSimpleName();
- if ( simpleName.toLowerCase().endsWith("map") || simpleName.equals("Hashtable"))
+ if ( simpleName.toLowerCase().endsWith("map") || "Hashtable".equals(simpleName)) {
expectedTypeParameters = 2;
- else if (simpleName.equals("Table"))
+ } else if ("Table".equals(simpleName)) {
expectedTypeParameters = 3;
+ }
// ... containers
- if (!operand.hasParameters())
+ if (!operand.hasParameters()) {
continue;
- if (operand.getNumParameters() != expectedTypeParameters)
+ }
+ if (operand.getNumParameters() != expectedTypeParameters) {
continue;
+ }
ClassDescriptor operandClass = DescriptorFactory.getClassDescriptor(operand);
- if (!isGenericCollection(operandClass))
+ if (!isGenericCollection(operandClass)) {
continue;
+ }
if (expectedTypeParameters == 2 &&
Subtypes2.instanceOf(operandClass, Map.class)
- && !TypeFrameModelingVisitor.isStraightGenericMap(operandClass))
+ && !TypeFrameModelingVisitor.isStraightGenericMap(operandClass)) {
continue;
+ }
Type expectedType;
- if (allMethod)
+ if (allMethod) {
expectedType = operand;
- else
+ } else {
expectedType = operand.getParameterAt(typeArgument);
+ }
Type actualType = frame.getStackValue(stackPos);
Type equalsType = actualType;
if (allMethod) {
if (!(actualType instanceof GenericObjectType)) {
- continue;
+ continue;
}
equalsType = ((GenericObjectType)actualType).getParameterAt(typeArgument);
}
@@ -550,46 +581,50 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
IncompatibleTypes matchResult = compareTypes(expectedType, actualType, allMethod);
- boolean parmIsObject = expectedType.getSignature().equals("Ljava/lang/Object;");
+ boolean parmIsObject = "Ljava/lang/Object;".equals(expectedType.getSignature());
boolean selfOperation = !allMethod && operand.equals(actualType) && !parmIsObject;
if (!allMethod && !parmIsObject && actualType instanceof GenericObjectType) {
GenericObjectType p2 = (GenericObjectType) actualType;
List<? extends ReferenceType> parameters = p2.getParameters();
- if (parameters != null && parameters.equals(operand.getParameters()))
+ if (parameters != null && parameters.equals(operand.getParameters())) {
selfOperation = true;
+ }
}
- if (!selfOperation && ( matchResult == IncompatibleTypes.SEEMS_OK || matchResult.getPriority() == Priorities.IGNORE_PRIORITY))
+ if (!selfOperation && ( matchResult == IncompatibleTypes.SEEMS_OK || matchResult.getPriority() == Priorities.IGNORE_PRIORITY)) {
continue;
+ }
- if (invokedMethodName.startsWith("contains") || invokedMethodName.equals("remove")) {
+ if (invokedMethodName.startsWith("contains") || "remove".equals(invokedMethodName)) {
InstructionHandle next = handle.getNext();
if (next != null) {
Instruction nextIns = next.getInstruction();
if (nextIns instanceof InvokeInstruction) {
XMethod nextMethod = XFactory.createXMethod((InvokeInstruction) nextIns, cpg);
- if (nextMethod.getName().equals("assertFalse"))
+ if ("assertFalse".equals(nextMethod.getName())) {
continue;
+ }
}
}
- } else if (invokedMethodName.equals("get") || invokedMethodName.equals("remove")) {
+ } else if ("get".equals(invokedMethodName) || "remove".equals(invokedMethodName)) {
InstructionHandle next = handle.getNext();
if (next != null) {
Instruction nextIns = next.getInstruction();
if (nextIns instanceof InvokeInstruction) {
XMethod nextMethod = XFactory.createXMethod((InvokeInstruction) nextIns, cpg);
- if (nextMethod.getName().equals("assertNull"))
+ if ("assertNull".equals(nextMethod.getName())) {
continue;
+ }
}
}
}
boolean noisy = false;
- if (invokedMethodName.equals("get")) {
+ if ("get".equals(invokedMethodName)) {
UnconditionalValueDerefDataflow unconditionalValueDerefDataflow = classContext
- .getUnconditionalValueDerefDataflow(method);
+ .getUnconditionalValueDerefDataflow(method);
UnconditionalValueDerefSet unconditionalDeref = unconditionalValueDerefDataflow.getFactAtLocation(location);
ValueNumberFrame vnAfter = vnDataflow.getFactAfterLocation(location);
@@ -603,18 +638,21 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
// Report a bug that mentions each of the failed arguments in
// matches
- if (expectedType instanceof GenericObjectType)
+ if (expectedType instanceof GenericObjectType) {
expectedType = ((GenericObjectType) expectedType).getUpperBound();
+ }
int priority = matchResult.getPriority();
- if (!operandClass.getClassName().startsWith("java/util") && priority == Priorities.HIGH_PRIORITY)
+ if (!operandClass.getClassName().startsWith("java/util") && priority == Priorities.HIGH_PRIORITY) {
priority = Math.max(priority, Priorities.NORMAL_PRIORITY);
- if (TestCaseDetector.likelyTestCase(xmethod))
+ }
+ if (TestCaseDetector.likelyTestCase(xmethod)) {
priority = Math.max(priority, Priorities.NORMAL_PRIORITY);
- else if (selfOperation)
+ } else if (selfOperation) {
priority = Priorities.HIGH_PRIORITY;
+ }
ClassDescriptor expectedClassDescriptor = DescriptorFactory
- .createClassOrObjectDescriptorFromSignature(expectedType.getSignature());
+ .createClassOrObjectDescriptorFromSignature(expectedType.getSignature());
ClassDescriptor actualClassDescriptor = DescriptorFactory.createClassOrObjectDescriptorFromSignature(equalsType
.getSignature());
ClassSummary classSummary = AnalysisContext.currentAnalysisContext().getClassSummary();
@@ -623,11 +661,14 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
targets = Hierarchy2.resolveVirtualMethodCallTargets(actualClassDescriptor, "equals",
"(Ljava/lang/Object;)Z", false, false);
boolean allOk = targets.size() > 0;
- for (XMethod m2 : targets)
- if (!classSummary.mightBeEqualTo(m2.getClassDescriptor(), expectedClassDescriptor))
+ for (XMethod m2 : targets) {
+ if (!classSummary.mightBeEqualTo(m2.getClassDescriptor(), expectedClassDescriptor)) {
allOk = false;
- if (allOk)
+ }
+ }
+ if (allOk) {
priority += 2;
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
@@ -670,18 +711,22 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
private IncompatibleTypes compareTypes(Type expectedType, Type actualType, boolean ignoreBaseType) {
// XXX equality not implemented for GenericObjectType
// if (parmType.equals(argType)) return true;
- if (expectedType == actualType)
+ if (expectedType == actualType) {
return IncompatibleTypes.SEEMS_OK;
+ }
// Compare type signatures instead
String expectedString = GenericUtilities.getString(expectedType);
String actualString = GenericUtilities.getString(actualType);
- if (expectedString.equals(actualString))
+ if (expectedString.equals(actualString)) {
return IncompatibleTypes.SEEMS_OK;
+ }
if (expectedType.equals(Type.OBJECT))
+ {
return IncompatibleTypes.SEEMS_OK;
- // if either type is java.lang.Object, then automatically true!
- // again compare strings...
+ // if either type is java.lang.Object, then automatically true!
+ // again compare strings...
+ }
String objString = GenericUtilities.getString(Type.OBJECT);
@@ -695,6 +740,9 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
if (actualString.equals(objString) && expectedCat == TypeCategory.TYPE_VARIABLE) {
return IncompatibleTypes.SEEMS_OK;
}
+ if (expectedCat == TypeCategory.WILDCARD) {
+ return IncompatibleTypes.SEEMS_OK;
+ }
if (ignoreBaseType) {
if (expectedCat == TypeCategory.PARAMETERIZED && argCat == TypeCategory.PARAMETERIZED) {
GenericObjectType parmGeneric = (GenericObjectType) expectedType;
@@ -704,33 +752,40 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
return IncompatibleTypes.SEEMS_OK;
}
- if (actualType.equals(Type.OBJECT) && expectedCat == TypeCategory.ARRAY_TYPE)
+ if (actualType.equals(Type.OBJECT) && expectedCat == TypeCategory.ARRAY_TYPE) {
return IncompatibleTypes.ARRAY_AND_OBJECT;
+ }
// -~- plain objects are easy
- if (expectedCat == TypeCategory.PLAIN_OBJECT_TYPE && argCat == TypeCategory.PLAIN_OBJECT_TYPE)
+ if (expectedCat == TypeCategory.PLAIN_OBJECT_TYPE && argCat == TypeCategory.PLAIN_OBJECT_TYPE) {
return IncompatibleTypes.getPriorityForAssumingCompatible(expectedType, actualType, false);
+ }
- if (expectedCat == TypeCategory.PARAMETERIZED && argCat == TypeCategory.PLAIN_OBJECT_TYPE)
+ if (expectedCat == TypeCategory.PARAMETERIZED && argCat == TypeCategory.PLAIN_OBJECT_TYPE) {
return IncompatibleTypes.getPriorityForAssumingCompatible((GenericObjectType) expectedType, actualType);
- if (expectedCat == TypeCategory.PLAIN_OBJECT_TYPE && argCat == TypeCategory.PARAMETERIZED)
+ }
+ if (expectedCat == TypeCategory.PLAIN_OBJECT_TYPE && argCat == TypeCategory.PARAMETERIZED) {
return IncompatibleTypes.getPriorityForAssumingCompatible((GenericObjectType) actualType, expectedType);
+ }
// -~- parmType is: "? extends Another Type" OR "? super Another Type"
- if (expectedCat == TypeCategory.WILDCARD_EXTENDS || expectedCat == TypeCategory.WILDCARD_SUPER)
+ if (expectedCat == TypeCategory.WILDCARD_EXTENDS || expectedCat == TypeCategory.WILDCARD_SUPER) {
return compareTypes(((GenericObjectType) expectedType).getExtension(), actualType, ignoreBaseType);
+ }
// -~- Not handling type variables
- if (expectedCat == TypeCategory.TYPE_VARIABLE || argCat == TypeCategory.TYPE_VARIABLE)
+ if (expectedCat == TypeCategory.TYPE_VARIABLE || argCat == TypeCategory.TYPE_VARIABLE) {
return IncompatibleTypes.SEEMS_OK;
+ }
// -~- Array Types: compare dimensions, then base type
if (expectedCat == TypeCategory.ARRAY_TYPE && argCat == TypeCategory.ARRAY_TYPE) {
ArrayType parmArray = (ArrayType) expectedType;
ArrayType argArray = (ArrayType) actualType;
- if (parmArray.getDimensions() != argArray.getDimensions())
+ if (parmArray.getDimensions() != argArray.getDimensions()) {
return IncompatibleTypes.ARRAY_AND_NON_ARRAY;
+ }
return compareTypes(parmArray.getBasicType(), argArray.getBasicType(), ignoreBaseType);
}
@@ -748,8 +803,9 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
// base types should be related
{
IncompatibleTypes result = compareTypes(parmGeneric.getObjectType(), argGeneric.getObjectType(), ignoreBaseType);
- if (!result.equals(IncompatibleTypes.SEEMS_OK))
+ if (!result.equals(IncompatibleTypes.SEEMS_OK)) {
return result;
+ }
}
return compareTypeParameters(parmGeneric, argGeneric);
@@ -766,8 +822,9 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
}
// -~- Wildcard e.g. List<*>.contains(...)
- if (expectedCat == TypeCategory.WILDCARD) // No Way to know
+ if (expectedCat == TypeCategory.WILDCARD) {
return IncompatibleTypes.SEEMS_OK;
+ }
// -~- Non Reference types
// if ( parmCat == TypeCategory.NON_REFERENCE_TYPE ||
@@ -789,8 +846,9 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
}
for (int x = 0; x < p; x++) {
IncompatibleTypes result = compareTypes(parmGeneric.getParameterAt(x), argGeneric.getParameterAt(x), false);
- if (result != IncompatibleTypes.SEEMS_OK)
+ if (result != IncompatibleTypes.SEEMS_OK) {
return result;
+ }
}
return IncompatibleTypes.SEEMS_OK;
}
@@ -800,8 +858,9 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
// XXX equality not implemented for GenericObjectType
// if (parmType.equals(argType)) return true;
// Compare type signatures instead
- if (GenericUtilities.getString(parmType).equals(GenericUtilities.getString(argType)))
+ if (GenericUtilities.getString(parmType).equals(GenericUtilities.getString(argType))) {
return true;
+ }
if (parmType instanceof GenericObjectType) {
GenericObjectType o = (GenericObjectType) parmType;
@@ -810,22 +869,26 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
}
}
// ignore type variables for now
- if (parmType instanceof GenericObjectType && !((GenericObjectType) parmType).hasParameters())
+ if (parmType instanceof GenericObjectType && !((GenericObjectType) parmType).hasParameters()) {
return true;
- if (argType instanceof GenericObjectType && !((GenericObjectType) argType).hasParameters())
+ }
+ if (argType instanceof GenericObjectType && !((GenericObjectType) argType).hasParameters()) {
return true;
+ }
// Case: Both are generic containers
if (parmType instanceof GenericObjectType && argType instanceof GenericObjectType) {
return true;
} else {
// Don't consider non reference types (should not be possible)
- if (!(parmType instanceof ReferenceType && argType instanceof ReferenceType))
+ if (!(parmType instanceof ReferenceType && argType instanceof ReferenceType)) {
return true;
+ }
// Don't consider non object types (for now)
- if (!(parmType instanceof ObjectType && argType instanceof ObjectType))
+ if (!(parmType instanceof ObjectType && argType instanceof ObjectType)) {
return true;
+ }
// Otherwise, compare base types ignoring generic information
try {
@@ -842,6 +905,7 @@ public class FindUnrelatedTypesInGenericContainer implements Detector {
*
* @see edu.umd.cs.findbugs.Detector#report()
*/
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindUnreleasedLock.java b/src/java/edu/umd/cs/findbugs/detect/FindUnreleasedLock.java
index 6ce8ba6..51e2313 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindUnreleasedLock.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindUnreleasedLock.java
@@ -67,7 +67,7 @@ import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
import edu.umd.cs.findbugs.bcel.BCELUtil;
class Lock extends ResourceCreationPoint {
- private ValueNumber lockValue;
+ private final ValueNumber lockValue;
public Lock(Location location, String lockClass, ValueNumber lockValue) {
super(location, lockClass);
@@ -85,11 +85,11 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
private int numAcquires = 0;
private static class LockFrameModelingVisitor extends ResourceValueFrameModelingVisitor {
- private LockResourceTracker resourceTracker;
+ private final LockResourceTracker resourceTracker;
- private Lock lock;
+ private final Lock lock;
- private ValueNumberDataflow vnaDataflow;
+ private final ValueNumberDataflow vnaDataflow;
// private IsNullValueDataflow isNullDataflow;
@@ -110,25 +110,29 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
int status = -1;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("PC : " + handle.getPosition() + " " + ins);
+ }
if (DEBUG && ins instanceof InvokeInstruction) {
InvokeInstruction iins = (InvokeInstruction) ins;
System.out.println(" " + ins.toString(cpg.getConstantPool()));
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("resource frame before instruction: " + frame.toString());
+ }
// Is a lock acquired or released by this instruction?
Location creationPoint = lock.getLocation();
if (handle == creationPoint.getHandle() && basicBlock == creationPoint.getBasicBlock()) {
status = ResourceValueFrame.OPEN;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("OPEN");
+ }
} else if (resourceTracker.isResourceClose(basicBlock, handle, cpg, lock, frame)) {
status = ResourceValueFrame.CLOSED;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("CLOSE");
+ }
}
// Model use of instance values in frame slots
@@ -141,20 +145,23 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
if (DEBUG) {
System.out.println("vna frame after instruction: " + vnaFrame.toString());
System.out.println("Lock value number: " + lock.getLockValue());
- if (lock.getLockValue().hasFlag(ValueNumber.RETURN_VALUE))
+ if (lock.getLockValue().hasFlag(ValueNumber.RETURN_VALUE)) {
System.out.println("is return value");
+ }
}
for (int i = 0; i < updatedNumSlots; ++i) {
if (DEBUG) {
System.out.println("Slot " + i);
System.out.println(" Lock value number: " + vnaFrame.getValue(i));
- if (vnaFrame.getValue(i).hasFlag(ValueNumber.RETURN_VALUE))
+ if (vnaFrame.getValue(i).hasFlag(ValueNumber.RETURN_VALUE)) {
System.out.println(" is return value");
+ }
}
if (vnaFrame.fuzzyMatch(lock.getLockValue(), vnaFrame.getValue(i))) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Saw lock value!");
+ }
frame.setValue(i, ResourceValue.instance());
}
}
@@ -163,8 +170,9 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
if (status != -1) {
frame.setStatus(status);
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("resource frame after instruction: " + frame.toString());
+ }
}
@@ -175,13 +183,13 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
}
class LockResourceTracker implements ResourceTracker<Lock> {
- private RepositoryLookupFailureCallback lookupFailureCallback;
+ private final RepositoryLookupFailureCallback lookupFailureCallback;
- private CFG cfg;
+ private final CFG cfg;
- private ValueNumberDataflow vnaDataflow;
+ private final ValueNumberDataflow vnaDataflow;
- private IsNullValueDataflow isNullDataflow;
+ private final IsNullValueDataflow isNullDataflow;
public LockResourceTracker(RepositoryLookupFailureCallback lookupFailureCallback, CFG cfg,
ValueNumberDataflow vnaDataflow, IsNullValueDataflow isNullDataflow) {
@@ -191,28 +199,32 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
this.isNullDataflow = isNullDataflow;
}
+ @Override
public Lock isResourceCreation(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg)
throws DataflowAnalysisException {
InvokeInstruction inv = toInvokeInstruction(handle.getInstruction());
- if (inv == null)
+ if (inv == null) {
return null;
+ }
String className = inv.getClassName(cpg);
String methodName = inv.getName(cpg);
String methodSig = inv.getSignature(cpg);
try {
- if (methodName.equals("lock") && methodSig.equals("()V")
+ if ("lock".equals(methodName) && "()V".equals(methodSig)
&& Hierarchy.isSubtype(className, "java.util.concurrent.locks.Lock")) {
Location location = new Location(handle, basicBlock);
ValueNumberFrame frame = vnaDataflow.getFactAtLocation(location);
ValueNumber lockValue = frame.getTopValue();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Lock value is " + lockValue.getNumber() + ", frame=" + frame.toString());
- if (DEBUG)
+ }
+ if (DEBUG) {
++numAcquires;
+ }
return new Lock(location, className, lockValue);
}
} catch (ClassNotFoundException e) {
@@ -221,18 +233,20 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
return null;
}
+ @Override
public boolean mightCloseResource(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg)
throws DataflowAnalysisException {
InvokeInstruction inv = toInvokeInstruction(handle.getInstruction());
- if (inv == null)
+ if (inv == null) {
return false;
+ }
String className = inv.getClassName(cpg);
String methodName = inv.getName(cpg);
String methodSig = inv.getSignature(cpg);
try {
- if (methodName.equals("unlock") && methodSig.equals("()V")
+ if ("unlock".equals(methodName) && "()V".equals(methodSig)
&& Hierarchy.isSubtype(className, "java.util.concurrent.locks.Lock")) {
return true;
@@ -244,26 +258,31 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
return false;
}
+ @Override
public boolean isResourceClose(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg, Lock resource,
ResourceValueFrame frame) throws DataflowAnalysisException {
- if (!mightCloseResource(basicBlock, handle, cpg))
+ if (!mightCloseResource(basicBlock, handle, cpg)) {
return false;
+ }
ResourceValue topValue = frame.getTopValue();
return topValue.isInstance();
}
+ @Override
public ResourceValueFrameModelingVisitor createVisitor(Lock resource, ConstantPoolGen cpg) {
return new LockFrameModelingVisitor(cpg, this, resource, vnaDataflow, isNullDataflow);
}
+ @Override
public boolean ignoreImplicitExceptions(Lock resource) {
// JSR166 locks should be ALWAYS be released,
// including when implicit runtime exceptions are thrown
return false;
}
+ @Override
public boolean ignoreExceptionEdge(Edge edge, Lock resource, ConstantPoolGen cpg) {
try {
@@ -281,11 +300,13 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
}
// Ignore exceptions from getfield instructions where the
// object reference is known not to be null
- if (fieldName.equals("lock"))
+ if ("lock".equals(fieldName)) {
return true;
+ }
IsNullValueFrame frame = isNullDataflow.getFactAtLocation(location);
- if (!frame.isValid())
+ if (!frame.isValid()) {
return false;
+ }
IsNullValue receiver = frame.getInstance(ins, cpg);
boolean notNull = receiver.isDefinitelyNotNull();
if (DEBUG && notNull) {
@@ -296,12 +317,15 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
InvokeInstruction iins = (InvokeInstruction) ins;
String methodName = iins.getMethodName(cpg);
// System.out.println("Method " + methodName);
- if (methodName.startsWith("access$"))
+ if (methodName.startsWith("access$")) {
return true;
- if (methodName.equals("readLock") || methodName.equals("writeLock"))
+ }
+ if ("readLock".equals(methodName) || "writeLock".equals(methodName)) {
return true;
- if (methodName.equals("lock") || methodName.equals("unlock"))
+ }
+ if ("lock".equals(methodName) || "unlock".equals(methodName)) {
return true;
+ }
}
if (DEBUG) {
System.out.println("FOUND Exception thrower at: " + location);
@@ -313,6 +337,7 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
return false;
}
+ @Override
public boolean isParamInstance(Lock resource, int slot) {
// There is nothing special about Lock objects passed
// into the method as parameters.
@@ -321,8 +346,9 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
private InvokeInstruction toInvokeInstruction(Instruction ins) {
short opcode = ins.getOpcode();
- if (opcode != Constants.INVOKEVIRTUAL && opcode != Constants.INVOKEINTERFACE)
+ if (opcode != Constants.INVOKEVIRTUAL && opcode != Constants.INVOKEINTERFACE) {
return null;
+ }
return (InvokeInstruction) ins;
}
}
@@ -339,7 +365,7 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.Detector#visitClassContext(edu.umd.cs.findbugs.ba
* .ClassContext)
@@ -351,31 +377,37 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
// We can ignore classes that were compiled for anything
// less than JDK 1.5. This should avoid lots of unnecessary work
// when analyzing code for older VM targets.
- if (BCELUtil.preTiger(jclass))
+ if (BCELUtil.preTiger(jclass)) {
return;
+ }
boolean sawUtilConcurrentLocks = false;
- for (Constant c : jclass.getConstantPool().getConstantPool())
+ for (Constant c : jclass.getConstantPool().getConstantPool()) {
if (c instanceof ConstantMethodref) {
ConstantMethodref m = (ConstantMethodref) c;
ConstantClass cl = (ConstantClass) jclass.getConstantPool().getConstant(m.getClassIndex());
ConstantUtf8 name = (ConstantUtf8) jclass.getConstantPool().getConstant(cl.getNameIndex());
String nameAsString = name.getBytes();
- if (nameAsString.startsWith("java/util/concurrent/locks"))
+ if (nameAsString.startsWith("java/util/concurrent/locks")) {
sawUtilConcurrentLocks = true;
+ }
}
- if (sawUtilConcurrentLocks)
+ }
+ if (sawUtilConcurrentLocks) {
super.visitClassContext(classContext);
+ }
}
@Override
public boolean prescreen(ClassContext classContext, Method method, boolean mightClose) {
- if (!mightClose)
+ if (!mightClose) {
return false;
+ }
BitSet bytecodeSet = classContext.getBytecodeSet(method);
- if (bytecodeSet == null)
+ if (bytecodeSet == null) {
return false;
+ }
MethodGen methodGen = classContext.getMethodGen(method);
@@ -385,7 +417,7 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
@Override
public LockResourceTracker getResourceTracker(ClassContext classContext, Method method) throws CFGBuilderException,
- DataflowAnalysisException {
+ DataflowAnalysisException {
return new LockResourceTracker(bugReporter, classContext.getCFG(method), classContext.getValueNumberDataflow(method),
classContext.getIsNullValueDataflow(method));
}
@@ -418,7 +450,9 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
InstructionHandle handle = location.getHandle();
InstructionHandle nextInstruction = handle.getNext();
if (nextInstruction.getInstruction() instanceof RETURN)
+ {
return; // don't report as error; intentional
+ }
bugAccumulator.accumulateBug(new BugInstance(this, bugType, priority).addClassAndMethod(methodGen, sourceFile),
SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, handle));
}
@@ -426,8 +460,9 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
@Override
public void report() {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("numAcquires=" + numAcquires);
+ }
}
// /* ----------------------------------------------------------------------
@@ -469,4 +504,3 @@ public class FindUnreleasedLock extends ResourceTrackingDetector<Lock, FindUnrel
// }
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindUnsatisfiedObligation.java b/src/java/edu/umd/cs/findbugs/detect/FindUnsatisfiedObligation.java
index 197f718..a4e523a 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindUnsatisfiedObligation.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindUnsatisfiedObligation.java
@@ -45,6 +45,7 @@ import edu.umd.cs.findbugs.IntAnnotation;
import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.StringAnnotation;
import edu.umd.cs.findbugs.SystemProperties;
+import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.BasicBlock;
import edu.umd.cs.findbugs.ba.CFG;
import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
@@ -67,6 +68,7 @@ import edu.umd.cs.findbugs.ba.type.TypeFrame;
import edu.umd.cs.findbugs.bcel.CFGDetector;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
+import edu.umd.cs.findbugs.classfile.DescriptorFactory;
import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.classfile.IAnalysisCache;
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
@@ -74,12 +76,12 @@ import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Find unsatisfied obligations in Java methods. Examples: open streams, open
* database connections, etc.
- *
+ *
* <p>
* See Weimer and Necula, <a href="http://doi.acm.org/10.1145/1028976.1029011"
* >Finding and preventing run-time error handling mistakes</a>, OOPSLA 2004.
* </p>
- *
+ *
* @author David Hovemeyer
*/
public class FindUnsatisfiedObligation extends CFGDetector {
@@ -111,7 +113,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
private final BugReporter bugReporter;
- private ObligationPolicyDatabase database;
+ private final ObligationPolicyDatabase database;
public FindUnsatisfiedObligation(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -144,8 +146,9 @@ public class FindUnsatisfiedObligation extends CFGDetector {
}
}
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println(classDescriptor + " isn't interesting for obligation analysis");
+ }
}
@Override
@@ -170,7 +173,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
/**
* Determine whether the state has "balanced" obligation counts for the
* consumed and produced Obligation types.
- *
+ *
* @param state
* a State
* @return true if the obligation counts are balanced, false otherwise
@@ -297,7 +300,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
// Apply the false-positive suppression heuristics
int leakCount = getAdjustedLeakCount(state, id);
-
+
if (leakCount > 0) {
leakedObligationMap.put(obligation, state);
@@ -310,13 +313,25 @@ public class FindUnsatisfiedObligation extends CFGDetector {
private void reportWarning(Obligation obligation, State state, StateSet factAtExit) {
String className = obligation.getClassName();
- if (methodDescriptor.isStatic() && methodDescriptor.getName().equals("main")
- && methodDescriptor.getSignature().equals("([Ljava/lang/String;)V")
+ if (methodDescriptor.isStatic() && "main".equals(methodDescriptor.getName())
+ && "([Ljava/lang/String;)V".equals(methodDescriptor.getSignature())
&& (className.contains("InputStream") || className.contains("Reader") || factAtExit.isOnExceptionPath())) {
// Don't report unclosed input streams and readers in main()
// methods
return;
}
+
+ if (methodDescriptor.getName().equals("<init>")) {
+ try {
+
+ if (subtypes2.isSubtype(methodDescriptor.getClassDescriptor(), DescriptorFactory.createClassDescriptorFromDottedClassName(obligation.getClassName()))) {
+ return;
+ }
+
+ } catch (Exception e) {
+ AnalysisContext.logError("huh", e);
+ }
+ }
String bugPattern = factAtExit.isOnExceptionPath() ? "OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE" : "OBL_UNSATISFIED_OBLIGATION";
BugInstance bugInstance = new BugInstance(FindUnsatisfiedObligation.this, bugPattern,
NORMAL_PRIORITY).addClassAndMethod(methodDescriptor).addClass(className).describe("CLASS_REFTYPE");
@@ -361,10 +376,10 @@ public class FindUnsatisfiedObligation extends CFGDetector {
List<PossibleObligationTransfer> transferList;
public PostProcessingPathVisitor(Obligation possiblyLeakedObligation/*
- * ,
- * int
- * initialLeakCount
- */, State state) {
+ * ,
+ * int
+ * initialLeakCount
+ */, State state) {
this.possiblyLeakedObligation = possiblyLeakedObligation;
this.state = state;
this.adjustedLeakCount = state.getObligationSet().getCount(possiblyLeakedObligation.getId());
@@ -381,6 +396,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
return couldNotAnalyze;
}
+ @Override
public void visitBasicBlock(BasicBlock basicBlock) {
curBlock = basicBlock;
@@ -393,11 +409,14 @@ public class FindUnsatisfiedObligation extends CFGDetector {
}
}
+ @Override
public void visitInstructionHandle(InstructionHandle handle) {
try {
Instruction ins = handle.getInstruction();
short opcode = ins.getOpcode();
- if (DEBUG) System.out.printf("%3d %s%n", handle.getPosition(),Constants.OPCODE_NAMES[opcode]);
+ if (DEBUG) {
+ System.out.printf("%3d %s%n", handle.getPosition(),Constants.OPCODE_NAMES[opcode]);
+ }
if (opcode == Constants.PUTFIELD || opcode == Constants.PUTSTATIC || opcode == Constants.ARETURN) {
//
@@ -416,8 +435,9 @@ public class FindUnsatisfiedObligation extends CFGDetector {
possiblyLeakedObligation.getType())) {
// Remove one obligation of this type
adjustedLeakCount--;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("removing obligation to close " + tosType + " at " + handle.getPosition());
+ }
}
}
@@ -508,7 +528,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
}
String methodName = inv.getMethodName(cpg);
- Type producedType = methodName.equals("<init>") ? inv.getReferenceType(cpg) : inv.getReturnType(cpg);
+ Type producedType = "<init>".equals(methodName) ? inv.getReferenceType(cpg) : inv.getReturnType(cpg);
if (DEBUG_FP && !(producedType instanceof ObjectType)) {
System.out.println("Produced type " + producedType + " not an ObjectType");
@@ -557,6 +577,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
}
}
+ @Override
public void visitEdge(Edge edge) {
if (DEBUG_FP) {
System.out.println("visit edge " + edge);
@@ -598,7 +619,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
* <li>return statements (if an instance of the obligation type is
* returned from the method, subtract one from leak count)</li>
* </ul>
- *
+ *
* @return the adjusted leak count (positive if leaked obligation,
* negative if attempt to release an un-acquired obligation)
*/
@@ -641,6 +662,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
BasicBlock curBlock;
+ @Override
public void visitBasicBlock(BasicBlock basicBlock) {
curBlock = basicBlock;
@@ -656,7 +678,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
if (entryState.getObligationSet().getCount(obligation.getId()) > 0) {
lastSourceLine = SourceLineAnnotation.forFirstLineOfMethod(methodDescriptor);
lastSourceLine
- .setDescription(SourceLineAnnotation.ROLE_OBLIGATION_CREATED_BY_WILLCLOSE_PARAMETER);
+ .setDescription(SourceLineAnnotation.ROLE_OBLIGATION_CREATED_BY_WILLCLOSE_PARAMETER);
bugInstance.add(lastSourceLine);
sawFirstCreation = true;
@@ -669,6 +691,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
}
}
+ @Override
public void visitInstructionHandle(InstructionHandle handle) {
boolean isCreation = (dataflow.getAnalysis().getActionCache().addsObligation(curBlock, handle, obligation));
@@ -696,6 +719,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
}
}
+ @Override
public void visitEdge(Edge edge) {
if (REPORT_PATH_DEBUG) {
System.out.println("Edge of type " + Edge.edgeTypeToString(edge.getType()) + " to "
@@ -720,7 +744,7 @@ public class FindUnsatisfiedObligation extends CFGDetector {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector#report()
*/
public void report() {
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindUnsyncGet.java b/src/java/edu/umd/cs/findbugs/detect/FindUnsyncGet.java
index 744c428..cdf57e9 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindUnsyncGet.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindUnsyncGet.java
@@ -34,14 +34,14 @@ import edu.umd.cs.findbugs.MethodAnnotation;
public class FindUnsyncGet extends BytecodeScanningDetector {
String prevClassName = " none ";
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
static final int doNotConsider = ACC_PRIVATE | ACC_STATIC | ACC_NATIVE;
// Maps of property names to get and set methods
- private HashMap<String, MethodAnnotation> getMethods = new HashMap<String, MethodAnnotation>();
+ private final HashMap<String, MethodAnnotation> getMethods = new HashMap<String, MethodAnnotation>();
- private HashMap<String, MethodAnnotation> setMethods = new HashMap<String, MethodAnnotation>();
+ private final HashMap<String, MethodAnnotation> setMethods = new HashMap<String, MethodAnnotation>();
public FindUnsyncGet(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -75,8 +75,9 @@ public class FindUnsyncGet extends BytecodeScanningDetector {
@Override
public void visit(Method obj) {
int flags = obj.getAccessFlags();
- if ((flags & doNotConsider) != 0)
+ if ((flags & doNotConsider) != 0) {
return;
+ }
String name = obj.getName();
boolean isSynchronized = (flags & ACC_SYNCHRONIZED) != 0;
/*
@@ -84,17 +85,17 @@ public class FindUnsyncGet extends BytecodeScanningDetector {
* returnValue = sig.charAt(1 + sig.indexOf(')')); boolean firstArgIsRef
* = (firstArg == 'L') || (firstArg == '['); boolean returnValueIsRef =
* (returnValue == 'L') || (returnValue == '[');
- *
+ *
* System.out.println(className + "." + name + " " + firstArgIsRef + " "
* + returnValueIsRef + " " + isSynchronized + " " + isNative );
*/
if (name.startsWith("get") && !isSynchronized
- // && returnValueIsRef
- ) {
+ // && returnValueIsRef
+ ) {
getMethods.put(name.substring(3), MethodAnnotation.fromVisitedMethod(this));
} else if (name.startsWith("set") && isSynchronized
- // && firstArgIsRef
- ) {
+ // && firstArgIsRef
+ ) {
setMethods.put(name.substring(3), MethodAnnotation.fromVisitedMethod(this));
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindUseOfNonSerializableValue.java b/src/java/edu/umd/cs/findbugs/detect/FindUseOfNonSerializableValue.java
index e9b307b..f763bb9 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindUseOfNonSerializableValue.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindUseOfNonSerializableValue.java
@@ -53,6 +53,7 @@ public class FindUseOfNonSerializableValue implements Detector {
this.bugAccumulator = new BugAccumulator(bugReporter);
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
boolean skip = false;
@@ -63,11 +64,12 @@ public class FindUseOfNonSerializableValue implements Detector {
@DottedClassName String clazz = m.getClass(constantPool);
ConstantNameAndType nt = (ConstantNameAndType) constantPool.getConstant(m.getNameAndTypeIndex(), Constants.CONSTANT_NameAndType);
String name = nt.getName(constantPool);
- if (name.equals("setAttribute") && clazz.equals("javax.servlet.http.HttpSession") || (name.equals("writeObject")
- && (clazz.equals("java.io.ObjectOutput")
- || clazz.equals("java.io.ObjectOutputStream")))) {
- if (DEBUG)
+ if ("setAttribute".equals(name) && "javax.servlet.http.HttpSession".equals(clazz) || ("writeObject".equals(name)
+ && ("java.io.ObjectOutput".equals(clazz)
+ || "java.io.ObjectOutputStream".equals(clazz)))) {
+ if (DEBUG) {
System.out.println("Found call to " + clazz + "." + name);
+ }
skip = false;
break;
@@ -75,15 +77,18 @@ public class FindUseOfNonSerializableValue implements Detector {
}
}
- if (skip)
+ if (skip) {
return;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println(this.getClass().getSimpleName() + " Checking " + javaClass.getClassName());
+ }
Method[] methodList = javaClass.getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -103,28 +108,33 @@ public class FindUseOfNonSerializableValue implements Detector {
if (ins instanceof InvokeInstruction) {
InvokeInstruction invoke = (InvokeInstruction) ins;
- String mName = invoke.getMethodName(cpg);
+ String mName = invoke.getMethodName(cpg);
String cName = invoke.getClassName(cpg);
- if (mName.equals("setAttribute") && cName.equals("javax.servlet.http.HttpSession"))
+ if ("setAttribute".equals(mName) && "javax.servlet.http.HttpSession".equals(cName)) {
return Use.STORE_INTO_HTTP_SESSION;
- if (mName.equals("writeObject")
- && (cName.equals("java.io.ObjectOutput")
- || cName.equals("java.io.ObjectOutputStream")))
+ }
+ if ("writeObject".equals(mName)
+ && ("java.io.ObjectOutput".equals(cName)
+ || "java.io.ObjectOutputStream".equals(cName))) {
return Use.PASSED_TO_WRITE_OBJECT;
+ }
}
- return null;
+ return null;
}
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
BitSet bytecodeSet = classContext.getBytecodeSet(method);
- if (bytecodeSet == null)
+ if (bytecodeSet == null) {
return;
+ }
// We don't adequately model instanceof interfaces yet
- if (bytecodeSet.get(Constants.INSTANCEOF) || bytecodeSet.get(Constants.CHECKCAST))
+ if (bytecodeSet.get(Constants.INSTANCEOF) || bytecodeSet.get(Constants.CHECKCAST)) {
return;
+ }
CFG cfg = classContext.getCFG(method);
TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
ConstantPoolGen cpg = classContext.getConstantPoolGen();
@@ -141,8 +151,9 @@ public class FindUseOfNonSerializableValue implements Detector {
Instruction ins = handle.getInstruction();
Use use = getUse(cpg, ins);
- if (use == null)
+ if (use == null) {
continue;
+ }
TypeFrame frame = typeDataflow.getFactAtLocation(location);
if (!frame.isValid()) {
@@ -179,22 +190,24 @@ public class FindUseOfNonSerializableValue implements Detector {
case PASSED_TO_WRITE_OBJECT:
pattern = "DMI_NONSERIALIZABLE_OBJECT_WRITTEN";
double isRemote = DeepSubtypeAnalysis.isDeepRemote(refType);
- if (isRemote >= 0.9)
+ if (isRemote >= 0.9) {
continue;
- if (isSerializable < isRemote)
+ }
+ if (isSerializable < isRemote) {
isSerializable = isRemote;
+ }
break;
case STORE_INTO_HTTP_SESSION:
pattern = "J2EE_STORE_OF_NON_SERIALIZABLE_OBJECT_INTO_SESSION";
break;
- default:
- throw new IllegalStateException();
+ default:
+ throw new IllegalStateException();
}
bugAccumulator.accumulateBug(new BugInstance(this, pattern,
isSerializable < 0.15 ? HIGH_PRIORITY : isSerializable > 0.5 ? LOW_PRIORITY : NORMAL_PRIORITY)
- .addClassAndMethod(methodGen, sourceFile).addType(problem).describe(TypeAnnotation.FOUND_ROLE),
- sourceLineAnnotation);
+ .addClassAndMethod(methodGen, sourceFile).addType(problem).describe(TypeAnnotation.FOUND_ROLE),
+ sourceLineAnnotation);
}
} catch (ClassNotFoundException e) {
@@ -203,6 +216,7 @@ public class FindUseOfNonSerializableValue implements Detector {
}
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindUselessControlFlow.java b/src/java/edu/umd/cs/findbugs/detect/FindUselessControlFlow.java
index 4b6897c..aa8cead 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FindUselessControlFlow.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FindUselessControlFlow.java
@@ -34,13 +34,13 @@ import edu.umd.cs.findbugs.StatelessDetector;
/**
* A Detector to look for useless control flow. For example,
- *
+ *
* <pre>
* if (argv.length == 1)
* ;
* System.out.println("Hello, " + argv[0]);
* </pre>
- *
+ *
* In this kind of bug, we'll see an ifcmp instruction where the IF target is
* the same as the fall-through target.
* <p/>
@@ -48,7 +48,7 @@ import edu.umd.cs.findbugs.StatelessDetector;
* The idea for this detector came from Richard P. King, and the idea of looking
* for if instructions with identical branch and fall-through targets is from
* Mike Fagan.
- *
+ *
* @author David Hovemeyer
*/
public class FindUselessControlFlow extends BytecodeScanningDetector implements StatelessDetector {
@@ -73,7 +73,7 @@ public class FindUselessControlFlow extends BytecodeScanningDetector implements
ifInstructionSet.set(Constants.IFNONNULL);
}
- private BugAccumulator bugAccumulator;
+ private final BugAccumulator bugAccumulator;
public FindUselessControlFlow(BugReporter bugReporter) {
this.bugAccumulator = new BugAccumulator(bugReporter);
@@ -98,15 +98,17 @@ public class FindUselessControlFlow extends BytecodeScanningDetector implements
int nextLine = getNextSourceLine(lineNumbers, branchLineNumber);
if (branchLineNumber + 1 == targetLineNumber || branchLineNumber == targetLineNumber
- && nextLine == branchLineNumber + 1)
+ && nextLine == branchLineNumber + 1) {
priority = HIGH_PRIORITY;
- else if (branchLineNumber + 2 < Math.max(targetLineNumber, nextLine))
+ } else if (branchLineNumber + 2 < Math.max(targetLineNumber, nextLine)) {
priority = LOW_PRIORITY;
- } else
+ }
+ } else {
priority = LOW_PRIORITY;
+ }
bugAccumulator.accumulateBug(new BugInstance(this,
priority == HIGH_PRIORITY ? "UCF_USELESS_CONTROL_FLOW_NEXT_LINE" : "UCF_USELESS_CONTROL_FLOW", priority)
- .addClassAndMethod(this), this);
+ .addClassAndMethod(this), this);
}
}
}
@@ -116,12 +118,12 @@ public class FindUselessControlFlow extends BytecodeScanningDetector implements
for (LineNumber ln : lineNumbers.getLineNumberTable()) {
int thisLine = ln.getLineNumber();
- if (sourceLine < thisLine && thisLine < result)
+ if (sourceLine < thisLine && thisLine < result) {
result = thisLine;
+ }
}
return result;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/FindUselessObjects.java b/src/java/edu/umd/cs/findbugs/detect/FindUselessObjects.java
new file mode 100644
index 0000000..93e8164
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/detect/FindUselessObjects.java
@@ -0,0 +1,703 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.detect;
+
+import static org.apache.bcel.Constants.*;
+
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.bcel.classfile.LocalVariable;
+import org.apache.bcel.classfile.LocalVariableTable;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.ANEWARRAY;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.IINC;
+import org.apache.bcel.generic.INVOKESPECIAL;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.InvokeInstruction;
+import org.apache.bcel.generic.MULTIANEWARRAY;
+import org.apache.bcel.generic.NEWARRAY;
+import org.apache.bcel.generic.POP;
+import org.apache.bcel.generic.POP2;
+import org.apache.bcel.generic.StoreInstruction;
+import org.apache.bcel.generic.Type;
+
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.Detector;
+import edu.umd.cs.findbugs.StringAnnotation;
+import edu.umd.cs.findbugs.ba.BasicBlock;
+import edu.umd.cs.findbugs.ba.CFG;
+import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
+import edu.umd.cs.findbugs.ba.EdgeTypes;
+import edu.umd.cs.findbugs.ba.Location;
+import edu.umd.cs.findbugs.ba.XClass;
+import edu.umd.cs.findbugs.ba.XMethod;
+import edu.umd.cs.findbugs.ba.type.TypeAnalysis;
+import edu.umd.cs.findbugs.ba.type.TypeFrame;
+import edu.umd.cs.findbugs.ba.vna.ValueNumber;
+import edu.umd.cs.findbugs.ba.vna.ValueNumberAnalysis;
+import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
+import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
+import edu.umd.cs.findbugs.classfile.DescriptorFactory;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+import edu.umd.cs.findbugs.detect.FindNoSideEffectMethods.MethodSideEffectStatus;
+import edu.umd.cs.findbugs.detect.FindNoSideEffectMethods.NoSideEffectMethodsDatabase;
+
+/**
+ * @author Tagir Valeev
+ */
+public class FindUselessObjects implements Detector {
+ private final BugReporter reporter;
+ private final NoSideEffectMethodsDatabase noSideEffectMethods;
+
+ private static class ValueInfo {
+ Location created;
+ String var;
+ int origValue;
+ boolean hasObjectOnlyCall;
+ boolean escaped;
+ boolean used;
+ boolean derivedEscaped;
+ public BitSet origValues;
+ public BitSet derivedValues = new BitSet();
+ Type type;
+
+ public ValueInfo(int origValue, Location location, Type type) {
+ this.created = location;
+ this.origValue = origValue;
+ this.type = type;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + (escaped ? "E" : "-") + (hasObjectOnlyCall ? "O" : "-") + (used ? "U" : "-")
+ + (derivedEscaped ? "D" : "-") + "] " + (var == null ? "" : var + " ") + type + " " + created;
+ }
+ }
+
+ private class UselessValuesContext {
+ ValueNumberAnalysis vna;
+ TypeAnalysis ta;
+ CFG cfg;
+ int count;
+ Map<Integer, ValueInfo> observedValues = new HashMap<>();
+ ConstantPoolGen cpg;
+ Map<Integer, Set<ValueInfo>> values;
+ ValueNumber thisValue;
+ ClassContext classContext;
+ Method method;
+
+ UselessValuesContext(ClassContext classContext, Method method) throws CheckedAnalysisException {
+ this.classContext = classContext;
+ this.method = method;
+ cfg = classContext.getCFG(method);
+ cpg = cfg.getMethodGen().getConstantPool();
+ ta = classContext.getTypeDataflow(method).getAnalysis();
+ vna = classContext.getValueNumberDataflow(method).getAnalysis();
+ }
+
+ void initObservedValues() throws DataflowAnalysisException {
+ for(Iterator<Location> iterator = cfg.locationIterator(); iterator.hasNext(); ) {
+ Location location = iterator.next();
+ Instruction instruction = location.getHandle().getInstruction();
+ if(instruction instanceof ANEWARRAY || instruction instanceof NEWARRAY || instruction instanceof MULTIANEWARRAY) {
+ int number = vna.getFactAfterLocation(location).getTopValue().getNumber();
+ TypeFrame typeFrame = ta.getFactAfterLocation(location);
+ if(typeFrame.isValid()) {
+ Type type = typeFrame.getTopValue();
+ observedValues.put(number, new ValueInfo(number, location, type));
+ }
+ } else if(instruction instanceof INVOKESPECIAL) {
+ InvokeInstruction inv = (InvokeInstruction) instruction;
+ if (inv.getMethodName(cpg).equals("<init>")
+ && noSideEffectMethods.hasNoSideEffect(new MethodDescriptor(inv, cpg))) {
+ int number = vna.getFactAtLocation(location).getStackValue(inv.consumeStack(cpg)-1).getNumber();
+ TypeFrame typeFrame = ta.getFactAtLocation(location);
+ if(typeFrame.isValid()) {
+ Type type = typeFrame.getStackValue(inv.consumeStack(cpg)-1);
+ observedValues.put(number, new ValueInfo(number, location, type));
+ }
+ }
+ }
+ }
+ thisValue = vna.getThisValue();
+ if(thisValue != null) {
+ observedValues.remove(thisValue.getNumber());
+ }
+ count = observedValues.size();
+ }
+
+ void enhanceViaMergeTree() {
+ values = new HashMap<>();
+ for (Entry<Integer, ValueInfo> entry : observedValues.entrySet()) {
+ BitSet outputSet = vna.getMergeTree().getTransitiveOutputSet(entry.getKey());
+ outputSet.set(entry.getKey());
+ entry.getValue().origValues = outputSet;
+ for (int i = outputSet.nextSetBit(0); i >= 0; i = outputSet.nextSetBit(i+1)) {
+ Set<ValueInfo> list = values.get(i);
+ if(list == null) {
+ list = new HashSet<>();
+ values.put(i, list);
+ }
+ list.add(entry.getValue());
+ }
+ }
+ }
+
+ boolean setEscape(Set<ValueInfo> vals) {
+ boolean result = false;
+ for(ValueInfo vi : vals) {
+ result |= !vi.escaped;
+ vi.escaped = true;
+ count--;
+ }
+ return result;
+ }
+
+ boolean setDerivedEscape(Set<ValueInfo> vals, ValueNumber vn) {
+ boolean result = false;
+ for(ValueInfo vi : vals) {
+ if(vi.origValues.get(vn.getNumber())) {
+ result |= !vi.derivedEscaped;
+ vi.derivedEscaped = true;
+ }
+ }
+ return result;
+ }
+
+ boolean setUsed(Set<ValueInfo> vals) {
+ boolean result = false;
+ for(ValueInfo vi : vals) {
+ result |= !vi.used;
+ vi.used = true;
+ }
+ return result;
+ }
+
+ boolean setObjectOnly(Set<ValueInfo> vals, ValueNumber vn) {
+ boolean result = false;
+ for(ValueInfo vi : vals) {
+ if(vi.origValues.get(vn.getNumber()) || (!vi.derivedEscaped && vi.derivedValues.get(vn.getNumber()))) {
+ result |= !vi.hasObjectOnlyCall;
+ vi.hasObjectOnlyCall = true;
+ } else {
+ result |= !vi.escaped;
+ vi.escaped = true;
+ count--;
+ }
+ }
+ return result;
+ }
+
+ boolean propagateValues(Set<ValueInfo> vals, ValueNumber origNumber, ValueNumber vn) {
+ int number = vn.getNumber();
+ if(vals.size() == 1 && vals.iterator().next().origValue == number) {
+ return false;
+ }
+ boolean result = setUsed(vals);
+ if(origNumber != null) {
+ for(ValueInfo vi : vals) {
+ if(vi.origValues.get(origNumber.getNumber()) && !vi.derivedValues.get(number)) {
+ vi.derivedValues.set(number);
+ result = true;
+ }
+ }
+ }
+ Set<ValueInfo> list = values.get(number);
+ if(list == null) {
+ list = new HashSet<>();
+ values.put(number, list);
+ }
+ result |= list.addAll(vals);
+ BitSet outputSet = vna.getMergeTree().getTransitiveOutputSet(number);
+ for (int i = outputSet.nextSetBit(0); i >= 0; i = outputSet.nextSetBit(i+1)) {
+ list = values.get(i);
+ if(list == null) {
+ list = new HashSet<>();
+ values.put(i, list);
+ }
+ result |= list.addAll(vals);
+ }
+ return result;
+ }
+
+ boolean propagateToReturnValue(Set<ValueInfo> vals, ValueNumber vn, GenLocation location, MethodDescriptor m)
+ throws DataflowAnalysisException {
+ for(ValueInfo vi : vals) {
+ if(vi.type.getSignature().startsWith("[") && vi.hasObjectOnlyCall && vi.var == null && vn.getNumber() == vi.origValue) {
+ // Ignore initialized arrays passed to methods
+ vi.escaped = true;
+ count--;
+ }
+ }
+ if (Type.getReturnType(m.getSignature()) == Type.VOID || location instanceof ExceptionLocation) {
+ return false;
+ }
+ InstructionHandle nextHandle = location.getHandle().getNext();
+ if (nextHandle == null || (nextHandle.getInstruction() instanceof POP || nextHandle.getInstruction() instanceof POP2)) {
+ return false;
+ }
+ return propagateValues(vals, null, location.frameAfter().getTopValue());
+ }
+
+ boolean isEmpty() {
+ return count == 0;
+ }
+
+ Iterator<GenLocation> genIterator() {
+ return new Iterator<FindUselessObjects.GenLocation>() {
+ Iterator<Location> locIterator = cfg.locationIterator();
+ Iterator<BasicBlock> blockIterator = cfg.blockIterator();
+ GenLocation next = advance();
+
+ private GenLocation advance() {
+ if(locIterator.hasNext()) {
+ return new RegularLocation(ta, vna, locIterator.next());
+ }
+ while(blockIterator.hasNext()) {
+ BasicBlock block = blockIterator.next();
+ if(block.isExceptionThrower() && cfg.getOutgoingEdgeWithType(block, EdgeTypes.FALL_THROUGH_EDGE) == null) {
+ return new ExceptionLocation(ta, vna, block);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ @Override
+ public GenLocation next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ GenLocation cur = next;
+ next = advance();
+ return cur;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ boolean escaped(ValueNumber vn) {
+ Set<ValueInfo> vals = values.get(vn.getNumber());
+ if(vals == null) {
+ return true;
+ }
+ for(ValueInfo vi : vals) {
+ if(vi.escaped) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Set<ValueInfo> getLiveVals(ValueNumber vn) {
+ Set<ValueInfo> vals = this.values.get(vn.getNumber());
+ if(vals == null) {
+ return null;
+ }
+ if(vals.size() == 1) {
+ return vals.iterator().next().escaped ? null : vals;
+ }
+ Set<ValueInfo> result = new HashSet<>();
+ for(ValueInfo vi : vals) {
+ if(!vi.escaped) {
+ result.add(vi);
+ }
+ }
+ return result.isEmpty() ? null : result;
+ }
+
+ void report() {
+ for(ValueInfo vi : observedValues.values()) {
+ if(!vi.escaped) {
+ if(vi.hasObjectOnlyCall && vi.used && vi.var == null) {
+ continue;
+ }
+ if(vi.hasObjectOnlyCall || (vi.used && vi.var != null)) {
+ BugInstance bug = new BugInstance(vi.var == null ? "UC_USELESS_OBJECT_STACK" : "UC_USELESS_OBJECT",
+ NORMAL_PRIORITY).addClassAndMethod(classContext.getJavaClass(), method);
+ if(vi.var != null) {
+ bug.add(new StringAnnotation(vi.var));
+ }
+ reporter.reportBug(bug.addType(vi.type).addSourceLine(classContext, method, vi.created));
+ }
+ }
+ }
+ }
+ }
+
+ private static interface GenLocation {
+ InstructionHandle getHandle();
+ TypeFrame typeFrameBefore() throws DataflowAnalysisException;
+ ValueNumberFrame frameBefore();
+ ValueNumberFrame frameAfter();
+ }
+
+ private static class RegularLocation implements GenLocation {
+ Location loc;
+ ValueNumberAnalysis vna;
+ TypeAnalysis ta;
+
+ public RegularLocation(TypeAnalysis ta, ValueNumberAnalysis vna, Location loc) {
+ this.ta = ta;
+ this.vna = vna;
+ this.loc = loc;
+ }
+
+ @Override
+ public InstructionHandle getHandle() {
+ return loc.getHandle();
+ }
+
+ @Override
+ public ValueNumberFrame frameBefore() {
+ return vna.getFactAtLocation(loc);
+ }
+
+ @Override
+ public ValueNumberFrame frameAfter() {
+ return vna.getFactAfterLocation(loc);
+ }
+
+ @Override
+ public TypeFrame typeFrameBefore() throws DataflowAnalysisException {
+ return ta.getFactAtLocation(loc);
+ }
+
+ @Override
+ public String toString() {
+ return loc.toString();
+ }
+ }
+
+ private static class ExceptionLocation implements GenLocation {
+ BasicBlock b;
+ ValueNumberAnalysis vna;
+ TypeAnalysis ta;
+
+ public ExceptionLocation(TypeAnalysis ta, ValueNumberAnalysis vna, BasicBlock block) {
+ this.vna = vna;
+ this.ta = ta;
+ this.b = block;
+ }
+
+ @Override
+ public InstructionHandle getHandle() {
+ return b.getExceptionThrower();
+ }
+
+ @Override
+ public ValueNumberFrame frameBefore() {
+ return vna.getStartFact(b);
+ }
+
+ @Override
+ public ValueNumberFrame frameAfter() {
+ return vna.getResultFact(b);
+ }
+
+ @Override
+ public TypeFrame typeFrameBefore() {
+ return ta.getStartFact(b);
+ }
+
+ @Override
+ public String toString() {
+ return "ex: "+b.getExceptionThrower()+" at "+b;
+ }
+ }
+
+ public FindUselessObjects(BugReporter reporter) {
+ this.reporter = reporter;
+ this.noSideEffectMethods = Global.getAnalysisCache().getDatabase(NoSideEffectMethodsDatabase.class);
+ }
+
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ for(Method method : classContext.getMethodsInCallOrder()) {
+ if(method.isAbstract() || method.isNative()) {
+ continue;
+ }
+ try {
+ analyzeMethod(classContext, method);
+ } catch (CheckedAnalysisException e) {
+ reporter.logError("Error analyzing "+method+" (class: "+classContext.getJavaClass().getClassName()+")", e);
+ }
+ }
+ }
+
+ private void analyzeMethod(ClassContext classContext, Method method) throws CheckedAnalysisException {
+ LocalVariableTable lvt = method.getLocalVariableTable();
+ UselessValuesContext context = new UselessValuesContext(classContext, method);
+ context.initObservedValues();
+ if(context.isEmpty()) {
+ return;
+ }
+ context.enhanceViaMergeTree();
+ boolean changed;
+ do {
+ changed = false;
+ for(Iterator<GenLocation> iterator = context.genIterator(); iterator.hasNext() && !context.isEmpty(); ) {
+ GenLocation location = iterator.next();
+ Instruction inst = location.getHandle().getInstruction();
+ ValueNumberFrame before = location.frameBefore();
+ if (!before.isValid()) {
+ continue;
+ }
+ if(inst instanceof IINC) {
+ int index = ((IINC)inst).getIndex();
+ Set<ValueInfo> vals = context.getLiveVals(before.getValue(index));
+ if(vals != null) {
+ changed |= context.propagateValues(vals, null, location.frameAfter().getValue(index));
+ }
+ continue;
+ }
+ int nconsumed = inst.consumeStack(context.cpg);
+ if(nconsumed > 0) {
+ ValueNumber[] vns = new ValueNumber[nconsumed];
+ before.getTopStackWords(vns);
+ for(int i=0; i<nconsumed; i++) {
+ ValueNumber vn = vns[i];
+ Set<ValueInfo> vals = context.getLiveVals(vn);
+ if(vals != null) {
+ switch(inst.getOpcode()) {
+ case ASTORE:
+ case ASTORE_0:
+ case ASTORE_1:
+ case ASTORE_2:
+ case ASTORE_3:
+ for(ValueInfo vi : vals) {
+ if(vi.var == null && vi.origValue == vn.getNumber()) {
+ int index = ((StoreInstruction)inst).getIndex();
+ LocalVariable lv = lvt == null ? null : lvt.getLocalVariable(index, location.getHandle().getNext().getPosition());
+ vi.var = lv == null ? "var$"+index : lv.getName();
+ vi.hasObjectOnlyCall = false;
+ changed = true;
+ }
+ }
+ break;
+ case POP:
+ case POP2:
+ case DUP:
+ case DUP2:
+ case DUP_X1:
+ case DUP2_X1:
+ case ISTORE:
+ case ISTORE_0:
+ case ISTORE_1:
+ case ISTORE_2:
+ case ISTORE_3:
+ case LSTORE:
+ case LSTORE_0:
+ case LSTORE_1:
+ case LSTORE_2:
+ case LSTORE_3:
+ case FSTORE:
+ case FSTORE_0:
+ case FSTORE_1:
+ case FSTORE_2:
+ case FSTORE_3:
+ case DSTORE:
+ case DSTORE_0:
+ case DSTORE_1:
+ case DSTORE_2:
+ case DSTORE_3:
+ case SWAP:
+ case IMPDEP1:
+ case IMPDEP2:
+ case CHECKCAST:
+ case MONITORENTER:
+ break;
+ case IADD:
+ case LADD:
+ case FADD:
+ case DADD:
+ case ISUB:
+ case LSUB:
+ case FSUB:
+ case DSUB:
+ case IMUL:
+ case DMUL:
+ case LMUL:
+ case FMUL:
+ case IDIV:
+ case DDIV:
+ case LDIV:
+ case FDIV:
+ case INEG:
+ case LNEG:
+ case FNEG:
+ case DNEG:
+ case IREM:
+ case LREM:
+ case FREM:
+ case DREM:
+ case ISHL:
+ case LSHL:
+ case ISHR:
+ case LSHR:
+ case IUSHR:
+ case LUSHR:
+ case IAND:
+ case LAND:
+ case IOR:
+ case LOR:
+ case IXOR:
+ case LXOR:
+ case I2L:
+ case I2F:
+ case I2D:
+ case L2I:
+ case L2F:
+ case L2D:
+ case F2I:
+ case F2L:
+ case F2D:
+ case D2I:
+ case D2L:
+ case D2F:
+ case I2B:
+ case I2C:
+ case I2S:
+ case LCMP:
+ case FCMPL:
+ case FCMPG:
+ case DCMPL:
+ case DCMPG:
+ case ARRAYLENGTH:
+ changed |= context.propagateValues(vals, null, location.frameAfter().getTopValue());
+ break;
+ case GETFIELD:
+ case AALOAD:
+ case DALOAD:
+ case BALOAD:
+ case CALOAD:
+ case LALOAD:
+ case SALOAD:
+ case IALOAD:
+ changed |= context.propagateValues(vals, vn, location.frameAfter().getTopValue());
+ break;
+ case AASTORE:
+ case DASTORE:
+ case BASTORE:
+ case CASTORE:
+ case LASTORE:
+ case SASTORE:
+ case IASTORE:
+ case PUTFIELD:
+ if(i == 0) {
+ ValueNumber value = vns[vns.length-1];
+ if(!value.hasFlag(ValueNumber.CONSTANT_VALUE) && !value.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT) &&
+ !context.observedValues.containsKey(value.getNumber())) {
+ changed |= context.setDerivedEscape(vals, vn);
+ }
+ changed |= context.setObjectOnly(vals, vn);
+ } else {
+ if(context.escaped(vns[0])) {
+ changed |= context.setEscape(vals);
+ } else {
+ changed |= context.propagateValues(vals, null, vns[0]);
+ }
+ }
+ break;
+ case INVOKESTATIC:
+ case INVOKESPECIAL:
+ case INVOKEINTERFACE:
+ case INVOKEVIRTUAL:
+ MethodDescriptor m = new MethodDescriptor((InvokeInstruction) inst, context.cpg);
+ XMethod xMethod = null;
+ try {
+ Type type = location.typeFrameBefore().getStackValue(nconsumed-1);
+ xMethod = Global
+ .getAnalysisCache()
+ .getClassAnalysis(XClass.class,
+ DescriptorFactory.createClassDescriptorFromSignature(type.getSignature()))
+ .findMatchingMethod(m);
+ } catch (CheckedAnalysisException e) {
+ // ignore
+ }
+ if(xMethod != null) {
+ m = xMethod.getMethodDescriptor();
+ }
+ MethodSideEffectStatus status = noSideEffectMethods.status(m);
+ if(status == MethodSideEffectStatus.NSE || status == MethodSideEffectStatus.SE_CLINIT) {
+ if(m.getName().equals("<init>")) {
+ if(vns[0].equals(context.thisValue)) {
+ changed |= context.setEscape(vals);
+ } else {
+ changed |= context.propagateValues(vals, null, vns[0]);
+ }
+ } else {
+ changed |= context.propagateToReturnValue(vals, vn, location, m);
+ }
+ break;
+ }
+ if(status == MethodSideEffectStatus.OBJ) {
+ if(i == 0) {
+ changed |= context.setDerivedEscape(vals, vn);
+ changed |= context.propagateToReturnValue(vals, vn, location, m);
+ changed |= context.setObjectOnly(vals, vn);
+ break;
+ } else {
+ if(!context.escaped(vns[0])) {
+ changed |= context.propagateValues(vals, null, vns[0]);
+ changed |= context.propagateToReturnValue(vals, vn, location, m);
+ break;
+ }
+ }
+ }
+ changed |= context.setEscape(vals);
+ break;
+ default:
+ changed |= context.setEscape(vals);
+ break;
+ }
+ }
+ }
+ }
+ }
+ } while(changed);
+ context.report();
+ }
+
+ @Override
+ public void report() {
+ }
+
+}
diff --git a/src/java/edu/umd/cs/findbugs/detect/FormatStringChecker.java b/src/java/edu/umd/cs/findbugs/detect/FormatStringChecker.java
index 17b5b07..55c8737 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FormatStringChecker.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FormatStringChecker.java
@@ -120,35 +120,37 @@ public class FormatStringChecker extends OpcodeStackDetector {
&& "format".equals(nm) || "java/io/PrintStream".equals(cl) && "format".equals(nm)
|| "java/io/PrintStream".equals(cl) && "printf".equals(nm) || cl.endsWith("Writer")
&& "format".equals(nm) || cl.endsWith("Writer") && "printf".equals(nm)) || cl.endsWith("Logger")
- && nm.endsWith("fmt")) {
+ && nm.endsWith("fmt")) {
- if (formatString.indexOf('\n') >= 0)
+ if (formatString.indexOf('\n') >= 0) {
bugReporter.reportBug(new BugInstance(this, "VA_FORMAT_STRING_USES_NEWLINE", NORMAL_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this).addString(formatString)
- .describe(StringAnnotation.FORMAT_STRING_ROLE).addSourceLine(this));
+ .addClassAndMethod(this).addCalledMethod(this).addString(formatString)
+ .describe(StringAnnotation.FORMAT_STRING_ROLE).addSourceLine(this));
+ }
try {
String[] signatures = new String[arguments.length];
- for (int i = 0; i < signatures.length; i++)
+ for (int i = 0; i < signatures.length; i++) {
signatures[i] = arguments[i].getSignature();
+ }
Formatter.check(formatString, signatures);
} catch (IllegalFormatConversionException e) {
- if (e.getConversion() == 'b')
+ if (e.getConversion() == 'b') {
bugReporter.reportBug(new BugInstance(this, "VA_FORMAT_STRING_BAD_CONVERSION_TO_BOOLEAN", HIGH_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this).addType(e.getArgumentSignature())
- .describe(TypeAnnotation.FOUND_ROLE).addString(e.getFormatSpecifier())
- .describe(StringAnnotation.FORMAT_SPECIFIER_ROLE).addString(formatString)
- .describe(StringAnnotation.FORMAT_STRING_ROLE)
- .addValueSource(arguments[e.getArgIndex()], getMethod(), getPC()).addSourceLine(this));
- else if (e.getArgumentSignature().charAt(0) == '[' && e.getConversion() == 's')
+ .addClassAndMethod(this).addCalledMethod(this).addType(e.getArgumentSignature())
+ .describe(TypeAnnotation.FOUND_ROLE).addString(e.getFormatSpecifier())
+ .describe(StringAnnotation.FORMAT_SPECIFIER_ROLE).addString(formatString)
+ .describe(StringAnnotation.FORMAT_STRING_ROLE)
+ .addValueSource(arguments[e.getArgIndex()], getMethod(), getPC()).addSourceLine(this));
+ } else if (e.getArgumentSignature().charAt(0) == '[' && e.getConversion() == 's') {
bugReporter.reportBug(new BugInstance(this, "VA_FORMAT_STRING_BAD_CONVERSION_FROM_ARRAY", HIGH_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this).addType(e.getArgumentSignature())
- .describe(TypeAnnotation.FOUND_ROLE).addString(e.getFormatSpecifier())
- .describe(StringAnnotation.FORMAT_SPECIFIER_ROLE).addString(formatString)
- .describe(StringAnnotation.FORMAT_STRING_ROLE)
- .addValueSource(arguments[e.getArgIndex()], getMethod(), getPC()).addSourceLine(this));
- else {
+ .addClassAndMethod(this).addCalledMethod(this).addType(e.getArgumentSignature())
+ .describe(TypeAnnotation.FOUND_ROLE).addString(e.getFormatSpecifier())
+ .describe(StringAnnotation.FORMAT_SPECIFIER_ROLE).addString(formatString)
+ .describe(StringAnnotation.FORMAT_STRING_ROLE)
+ .addValueSource(arguments[e.getArgIndex()], getMethod(), getPC()).addSourceLine(this));
+ } else {
String aSig = e.getArgumentSignature();
char conversion = e.getConversion();
if ((conversion == 't' || conversion == 'T') && aSig.charAt(0) == 'L') {
@@ -156,40 +158,42 @@ public class FormatStringChecker extends OpcodeStackDetector {
assert argDescriptor != null : "sig started with L, should get descriptor";
String arg = argDescriptor.toDottedClassName();
try {
- if (Hierarchy.isSubtype(arg, java.util.Date.class.getName())
- || Hierarchy.isSubtype(arg, java.util.Calendar.class.getName())) {
+ if (arg.equals("java.time.LocalDate")
+ || Hierarchy.isSubtype(arg, java.util.Date.class.getName())
+ || Hierarchy.isSubtype(arg, java.util.Calendar.class.getName())
+ || Hierarchy.isSubtype(arg, "java.time.temporal.TemporalAccessor")) {
return;
}
} catch (ClassNotFoundException e1) {
- AnalysisContext.reportMissingClass(e1);
+ AnalysisContext.reportMissingClass(e1);
}
}
bugReporter.reportBug(new BugInstance(this, "VA_FORMAT_STRING_BAD_CONVERSION", HIGH_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this).addType(aSig)
- .describe(TypeAnnotation.FOUND_ROLE).addString(e.getFormatSpecifier())
- .describe(StringAnnotation.FORMAT_SPECIFIER_ROLE).addString(formatString)
- .describe(StringAnnotation.FORMAT_STRING_ROLE)
- .addValueSource(arguments[e.getArgIndex()], getMethod(), getPC()).addSourceLine(this));
+ .addClassAndMethod(this).addCalledMethod(this).addType(aSig)
+ .describe(TypeAnnotation.FOUND_ROLE).addString(e.getFormatSpecifier())
+ .describe(StringAnnotation.FORMAT_SPECIFIER_ROLE).addString(formatString)
+ .describe(StringAnnotation.FORMAT_STRING_ROLE)
+ .addValueSource(arguments[e.getArgIndex()], getMethod(), getPC()).addSourceLine(this));
}
} catch (IllegalArgumentException e) {
bugReporter.reportBug(new BugInstance(this, "VA_FORMAT_STRING_ILLEGAL", HIGH_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this).addString(formatString)
- .describe(StringAnnotation.FORMAT_STRING_ROLE).addSourceLine(this));
+ .addClassAndMethod(this).addCalledMethod(this).addString(formatString)
+ .describe(StringAnnotation.FORMAT_STRING_ROLE).addSourceLine(this));
} catch (MissingFormatArgumentException e) {
if (e.pos < 0) {
bugReporter.reportBug(new BugInstance(this, "VA_FORMAT_STRING_NO_PREVIOUS_ARGUMENT", HIGH_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this).addString(e.formatSpecifier)
- .describe(StringAnnotation.FORMAT_SPECIFIER_ROLE).addString(formatString)
- .describe(StringAnnotation.FORMAT_STRING_ROLE).addSourceLine(this));
+ .addClassAndMethod(this).addCalledMethod(this).addString(e.formatSpecifier)
+ .describe(StringAnnotation.FORMAT_SPECIFIER_ROLE).addString(formatString)
+ .describe(StringAnnotation.FORMAT_STRING_ROLE).addSourceLine(this));
} else {
bugReporter.reportBug(new BugInstance(this, "VA_FORMAT_STRING_MISSING_ARGUMENT", HIGH_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(this).addString(e.formatSpecifier)
- .describe(StringAnnotation.FORMAT_SPECIFIER_ROLE).addString(formatString)
- .describe(StringAnnotation.FORMAT_STRING_ROLE).addInt(e.pos + 1)
- .describe(IntAnnotation.INT_EXPECTED_ARGUMENTS).addInt(arguments.length)
- .describe(IntAnnotation.INT_ACTUAL_ARGUMENTS).addSourceLine(this));
+ .addClassAndMethod(this).addCalledMethod(this).addString(e.formatSpecifier)
+ .describe(StringAnnotation.FORMAT_SPECIFIER_ROLE).addString(formatString)
+ .describe(StringAnnotation.FORMAT_STRING_ROLE).addInt(e.pos + 1)
+ .describe(IntAnnotation.INT_EXPECTED_ARGUMENTS).addInt(arguments.length)
+ .describe(IntAnnotation.INT_ACTUAL_ARGUMENTS).addSourceLine(this));
}
} catch (ExtraFormatArgumentsException e) {
@@ -197,8 +201,9 @@ public class FormatStringChecker extends OpcodeStackDetector {
String pattern = "VA_FORMAT_STRING_EXTRA_ARGUMENTS_PASSED";
if (e.used == 0) {
priority = HIGH_PRIORITY;
- if (formatString.indexOf("{0") >= 0 || formatString.indexOf("{1") >= 0)
+ if (formatString.indexOf("{0") >= 0 || formatString.indexOf("{1") >= 0) {
pattern = "VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED";
+ }
}
bugReporter.reportBug(new BugInstance(this, pattern, priority).addClassAndMethod(this).addCalledMethod(this)
diff --git a/src/java/edu/umd/cs/findbugs/detect/FunctionsThatMightBeMistakenForProcedures.java b/src/java/edu/umd/cs/findbugs/detect/FunctionsThatMightBeMistakenForProcedures.java
index 78a287e..eb22744 100644
--- a/src/java/edu/umd/cs/findbugs/detect/FunctionsThatMightBeMistakenForProcedures.java
+++ b/src/java/edu/umd/cs/findbugs/detect/FunctionsThatMightBeMistakenForProcedures.java
@@ -50,11 +50,14 @@ public class FunctionsThatMightBeMistakenForProcedures extends OpcodeStackDetect
final BugReporter bugReporter;
+ private final boolean testingEnabled;
+
final static boolean REPORT_INFERRED_METHODS = SystemProperties.getBoolean("mrc.inferred.report");
public FunctionsThatMightBeMistakenForProcedures(BugReporter bugReporter) {
this.bugReporter = bugReporter;
setVisitMethodsInCallOrder(true);
+ testingEnabled = SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors");
}
boolean isInnerClass, hasNonFinalFields;
@@ -68,10 +71,12 @@ public class FunctionsThatMightBeMistakenForProcedures extends OpcodeStackDetect
@Override
public void visit(Field obj) {
- if (obj.getName().equals("this$0"))
+ if ("this$0".equals(obj.getName())) {
isInnerClass = true;
- if (!obj.isFinal() && !obj.isStatic() && !BCELUtil.isSynthetic(obj))
+ }
+ if (!obj.isFinal() && !obj.isStatic() && !BCELUtil.isSynthetic(obj)) {
hasNonFinalFields = true;
+ }
}
@Override
@@ -107,8 +112,9 @@ public class FunctionsThatMightBeMistakenForProcedures extends OpcodeStackDetect
String returnType = parser.getReturnTypeSignature();
@SlashedClassName
String r = ClassName.fromFieldSignature(returnType);
- if (r == null || !r.equals(getClassName()))
+ if (r == null || !r.equals(getClassName())) {
return;
+ }
// System.out.println("Checking " + getFullyQualifiedMethodName());
boolean funky = false;
for (int i = 0; i < parser.getNumParameters(); i++) {
@@ -129,24 +135,25 @@ public class FunctionsThatMightBeMistakenForProcedures extends OpcodeStackDetect
funky = true;
}
-// if (false) {
-// XClass c = getXClass();
-// String classSourceSig = c.getSourceSignature();
-// if (!genericReturnValue.equals(classSourceSig))
-// return;
-// }
+ // if (false) {
+ // XClass c = getXClass();
+ // String classSourceSig = c.getSourceSignature();
+ // if (!genericReturnValue.equals(classSourceSig))
+ // return;
+ // }
}
-// System.out.println("Investigating " + getFullyQualifiedMethodName());
+ // System.out.println("Investigating " + getFullyQualifiedMethodName());
returnSelf = returnOther = updates = returnNew = returnUnknown = 0;
- if (REPORT_INFERRED_METHODS
- && AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass()))
+ if (testingEnabled && REPORT_INFERRED_METHODS
+ && AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass())) {
inferredMethod = new BugInstance("TESTING", NORMAL_PRIORITY).addClassAndMethod(this);
- else
+ } else {
inferredMethod = null;
+ }
super.visit(code); // make callbacks to sawOpcode for all opcodes
-// System.out.printf(" %3d %3d %3d %3d%n", returnSelf, updates, returnOther, returnNew);
+ // System.out.printf(" %3d %3d %3d %3d%n", returnSelf, updates, returnOther, returnNew);
if (returnSelf > 0 && returnOther == 0) {
okToIgnore.add(m);
@@ -155,16 +162,21 @@ public class FunctionsThatMightBeMistakenForProcedures extends OpcodeStackDetect
} else if (returnOther > 0 && returnOther >= returnSelf && returnNew > 0 && returnNew >= returnOther - 1) {
int priority = HIGH_PRIORITY;
- if (returnSelf > 0 || updates > 0)
+ if (returnSelf > 0 || updates > 0) {
priority++;
- if (returnUnknown > 0)
+ }
+ if (returnUnknown > 0) {
priority++;
- if (returnNew > 0 && priority > NORMAL_PRIORITY)
+ }
+ if (returnNew > 0 && priority > NORMAL_PRIORITY) {
priority = NORMAL_PRIORITY;
- if (updates > 0)
+ }
+ if (updates > 0) {
priority = LOW_PRIORITY;
- if (priority <= HIGH_PRIORITY)
+ }
+ if (priority <= HIGH_PRIORITY) {
doNotIgnoreHigh.add(m);
+ }
if (priority <= NORMAL_PRIORITY) {
// System.out.printf(" adding %d %s%n", priority,
// MethodAnnotation.fromVisitedMethod(this).getSourceLines());
@@ -192,25 +204,29 @@ public class FunctionsThatMightBeMistakenForProcedures extends OpcodeStackDetect
switch (seen) {
case INVOKEVIRTUAL:
case INVOKESPECIAL: {
- if (getMethod().isStatic() || !hasNonFinalFields)
+ if (getMethod().isStatic() || !hasNonFinalFields) {
break;
+ }
String name = getNameConstantOperand();
String sig = getSigConstantOperand();
if ((name.startsWith("set") || name.startsWith("update")) || sig.endsWith(")V")) {
Item invokedOn = stack.getItemMethodInvokedOn(this);
- if (invokedOn.isInitialParameter() && invokedOn.getRegisterNumber() == 0)
+ if (invokedOn.isInitialParameter() && invokedOn.getRegisterNumber() == 0) {
updates++;
- if (inferredMethod != null)
+ }
+ if (inferredMethod != null) {
inferredMethod.addCalledMethod(this);
+ }
}
break;
}
case ARETURN: {
OpcodeStack.Item rv = stack.getStackItem(0);
- if (rv.isNull())
+ if (rv.isNull()) {
break;
+ }
if (rv.isInitialParameter()) {
returnSelf++;
break;
@@ -221,18 +237,19 @@ public class FunctionsThatMightBeMistakenForProcedures extends OpcodeStackDetect
returnSelf++;
break;
}
- if (inferredMethod != null)
+ if (inferredMethod != null) {
inferredMethod.addCalledMethod(xMethod);
+ }
if (okToIgnore.contains(xMethod) ) {
returnSelf++;
break;
}
- if (xMethod.getName().equals("<init>")) {
+ if ("<init>".equals(xMethod.getName())) {
String sig = xMethod.getSignature();
// returning a newly constructed value
boolean voidConstructor;
if (!isInnerClass) {
- voidConstructor = sig.equals("()V");
+ voidConstructor = "()V".equals(sig);
} else {
SignatureParser parser = new SignatureParser(sig);
voidConstructor = parser.getNumParameters() <= 1;
@@ -252,21 +269,23 @@ public class FunctionsThatMightBeMistakenForProcedures extends OpcodeStackDetect
returnUnknown++;
break;
}
- if (xMethod.getName().equals("<init>") || doNotIgnoreHigh.contains(xMethod)) {
+ if ("<init>".equals(xMethod.getName()) || doNotIgnoreHigh.contains(xMethod)) {
returnOther++;
// System.out.println(" calls " + xMethod);
// System.out.println(" at " +
// MethodAnnotation.fromXMethod(xMethod).getSourceLines());
- if (xMethod.getName().equals("<init>") || doNotIgnore.contains(xMethod))
+ if ("<init>".equals(xMethod.getName()) || doNotIgnore.contains(xMethod)) {
returnNew++;
+ }
} else if (doNotIgnore.contains(xMethod)) {
returnOther++;
// System.out.println(" calls " + xMethod);
// System.out.println(" at " +
// MethodAnnotation.fromXMethod(xMethod).getSourceLines());
- } else
+ } else {
returnUnknown++;
+ }
}
break;
@@ -274,12 +293,16 @@ public class FunctionsThatMightBeMistakenForProcedures extends OpcodeStackDetect
OpcodeStack.Item rv = stack.getStackItem(1);
if (rv.getRegisterNumber() == 0 && rv.isInitialParameter()) {
- if (inferredMethod != null)
+ if (inferredMethod != null) {
inferredMethod.addReferencedField(this);
+ }
updates++;
}
}
+ break;
+ default:
+ break;
}
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/HugeSharedStringConstants.java b/src/java/edu/umd/cs/findbugs/detect/HugeSharedStringConstants.java
index 6c15309..3eb0b13 100644
--- a/src/java/edu/umd/cs/findbugs/detect/HugeSharedStringConstants.java
+++ b/src/java/edu/umd/cs/findbugs/detect/HugeSharedStringConstants.java
@@ -62,8 +62,9 @@ public class HugeSharedStringConstants extends BytecodeScanningDetector {
@Override
public void visit(ConstantString s) {
String value = s.getBytes(getConstantPool());
- if (value.length() < SIZE_OF_HUGE_CONSTANT)
+ if (value.length() < SIZE_OF_HUGE_CONSTANT) {
return;
+ }
String key = getStringKey(value);
SortedSet<String> set = map.get(key);
if (set == null) {
@@ -75,14 +76,16 @@ public class HugeSharedStringConstants extends BytecodeScanningDetector {
@Override
public void visit(ConstantValue s) {
- if (!visitingField())
+ if (!visitingField()) {
return;
+ }
int i = s.getConstantValueIndex();
Constant c = getConstantPool().getConstant(i);
if (c instanceof ConstantString) {
String value = ((ConstantString) c).getBytes(getConstantPool());
- if (value.length() < SIZE_OF_HUGE_CONSTANT)
+ if (value.length() < SIZE_OF_HUGE_CONSTANT) {
return;
+ }
String key = getStringKey(value);
definition.put(key, XFactory.createXField(this));
stringSize.put(key, value.length());
@@ -94,24 +97,29 @@ public class HugeSharedStringConstants extends BytecodeScanningDetector {
public void report() {
for (Map.Entry<String, SortedSet<String>> e : map.entrySet()) {
Set<String> occursIn = e.getValue();
- if (occursIn.size() == 1)
+ if (occursIn.size() == 1) {
continue;
+ }
XField field = definition.get(e.getKey());
- if (field == null)
+ if (field == null) {
continue;
+ }
Integer length = stringSize.get(e.getKey());
int overhead = length * (occursIn.size() - 1);
- if (overhead < 3 * SIZE_OF_HUGE_CONSTANT)
+ if (overhead < 3 * SIZE_OF_HUGE_CONSTANT) {
continue;
+ }
String className = field.getClassName();
BugInstance bug = new BugInstance(this, "HSC_HUGE_SHARED_STRING_CONSTANT",
overhead > 20 * SIZE_OF_HUGE_CONSTANT ? HIGH_PRIORITY
: (overhead > 8 * SIZE_OF_HUGE_CONSTANT ? NORMAL_PRIORITY : LOW_PRIORITY)).addClass(className)
- .addField(field).addInt(length).addInt(occursIn.size()).describe(IntAnnotation.INT_OCCURRENCES);
- for (String c : occursIn)
- if (!c.equals(className))
+ .addField(field).addInt(length).addInt(occursIn.size()).describe(IntAnnotation.INT_OCCURRENCES);
+ for (String c : occursIn) {
+ if (!c.equals(className)) {
bug.addClass(c);
+ }
+ }
bugReporter.reportBug(bug);
diff --git a/src/java/edu/umd/cs/findbugs/detect/IDivResultCastToDouble.java b/src/java/edu/umd/cs/findbugs/detect/IDivResultCastToDouble.java
index 373d3fd..0c7f401 100644
--- a/src/java/edu/umd/cs/findbugs/detect/IDivResultCastToDouble.java
+++ b/src/java/edu/umd/cs/findbugs/detect/IDivResultCastToDouble.java
@@ -14,21 +14,22 @@ import edu.umd.cs.findbugs.util.ClassName;
public class IDivResultCastToDouble extends BytecodeScanningDetector {
private static final boolean DEBUG = SystemProperties.getBoolean("idcd.debug");
- private final BugReporter bugReporter;
+ // private final BugReporter bugReporter;
private final BugAccumulator bugAccumulator;
private int prevOpCode;
public IDivResultCastToDouble(BugReporter bugReporter) {
- this.bugReporter = bugReporter;
+ // this.bugReporter = bugReporter;
this.bugAccumulator = new BugAccumulator(bugReporter);
}
@Override
public void visit(Method obj) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Visiting " + obj);
+ }
}
@Override
@@ -42,17 +43,18 @@ public class IDivResultCastToDouble extends BytecodeScanningDetector {
@Override
public void sawOpcode(int seen) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Saw opcode " + OPCODE_NAMES[seen] + " " + pendingIdivCastToDivBugLocation);
+ }
if ((prevOpCode == I2D || prevOpCode == L2D) && seen == INVOKESTATIC && ClassName.isMathClass(getClassConstantOperand())
- && getNameConstantOperand().equals("ceil")) {
+ && "ceil".equals(getNameConstantOperand())) {
bugAccumulator
- .accumulateBug(new BugInstance(this, "ICAST_INT_CAST_TO_DOUBLE_PASSED_TO_CEIL", HIGH_PRIORITY)
- .addClassAndMethod(this), this);
+ .accumulateBug(new BugInstance(this, "ICAST_INT_CAST_TO_DOUBLE_PASSED_TO_CEIL", HIGH_PRIORITY)
+ .addClassAndMethod(this), this);
pendingIdivCastToDivBugLocation = null;
} else if ((prevOpCode == I2F || prevOpCode == L2F) && seen == INVOKESTATIC
- && ClassName.isMathClass(getClassConstantOperand()) && getNameConstantOperand().equals("round")) {
+ && ClassName.isMathClass(getClassConstantOperand()) && "round".equals(getNameConstantOperand())) {
bugAccumulator.accumulateBug(
new BugInstance(this, "ICAST_INT_CAST_TO_FLOAT_PASSED_TO_ROUND", NORMAL_PRIORITY).addClassAndMethod(this),
this);
@@ -64,8 +66,9 @@ public class IDivResultCastToDouble extends BytecodeScanningDetector {
pendingIdivCastToDivBugLocation = null;
}
- if (prevOpCode == IDIV && (seen == I2D || seen == I2F) || prevOpCode == LDIV && (seen == L2D || seen == L2F))
+ if (prevOpCode == IDIV && (seen == I2D || seen == I2F) || prevOpCode == LDIV && (seen == L2D || seen == L2F)) {
pendingIdivCastToDivBugLocation = SourceLineAnnotation.fromVisitedInstruction(this);
+ }
prevOpCode = seen;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/IOStreamFactory.java b/src/java/edu/umd/cs/findbugs/detect/IOStreamFactory.java
index bada760..5a7a8fa 100644
--- a/src/java/edu/umd/cs/findbugs/detect/IOStreamFactory.java
+++ b/src/java/edu/umd/cs/findbugs/detect/IOStreamFactory.java
@@ -34,12 +34,16 @@ import edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback;
* instructions.
*/
public class IOStreamFactory implements StreamFactory {
- private ObjectType baseClassType;
+ private final ObjectType baseClassType;
- private ObjectType[] uninterestingSubclassTypeList;
+ private final ObjectType[] uninterestingSubclassTypeList;
- private String bugType;
+ private final String bugType;
+ @Override
+ public String toString() {
+ return "IOStreamFactory("+baseClassType+")";
+ }
public IOStreamFactory(String baseClass, String[] uninterestingSubclassList, String bugType) {
this.baseClassType = ObjectTypeFactory.getInstance(baseClass);
this.uninterestingSubclassTypeList = new ObjectType[uninterestingSubclassList.length];
@@ -49,14 +53,16 @@ public class IOStreamFactory implements StreamFactory {
this.bugType = bugType;
}
+ @Override
public Stream createStream(Location location, ObjectType type, ConstantPoolGen cpg,
RepositoryLookupFailureCallback lookupFailureCallback) {
try {
Instruction ins = location.getHandle().getInstruction();
- if (ins.getOpcode() != Constants.NEW)
+ if (ins.getOpcode() != Constants.NEW) {
return null;
+ }
if (Hierarchy.isSubtype(type, baseClassType)) {
boolean isUninteresting = false;
@@ -67,9 +73,10 @@ public class IOStreamFactory implements StreamFactory {
}
}
Stream result = new Stream(location, type.getClassName(), baseClassType.getClassName())
- .setIgnoreImplicitExceptions(true);
- if (!isUninteresting)
+ .setIgnoreImplicitExceptions(true);
+ if (!isUninteresting) {
result.setInteresting(bugType);
+ }
return result;
}
} catch (ClassNotFoundException e) {
@@ -80,4 +87,3 @@ public class IOStreamFactory implements StreamFactory {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/IncompatMask.java b/src/java/edu/umd/cs/findbugs/detect/IncompatMask.java
index 197d5eb..4312ef9 100644
--- a/src/java/edu/umd/cs/findbugs/detect/IncompatMask.java
+++ b/src/java/edu/umd/cs/findbugs/detect/IncompatMask.java
@@ -29,7 +29,7 @@ import edu.umd.cs.findbugs.StatelessDetector;
/**
* Find comparisons involving values computed with bitwise operations whose
* outcomes are fixed at compile time.
- *
+ *
* @author Tom Truscott <trt at unx.sas.com>
*/
public class IncompatMask extends BytecodeScanningDetector implements StatelessDetector {
@@ -41,7 +41,7 @@ public class IncompatMask extends BytecodeScanningDetector implements StatelessD
boolean isLong;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public IncompatMask(BugReporter bugReporter) {
this.state = 0;
@@ -55,19 +55,21 @@ public class IncompatMask extends BytecodeScanningDetector implements StatelessD
}
private void checkState(int expectedState) {
- if (state == expectedState)
+ if (state == expectedState) {
state++;
- else
+ } else {
state = 0;
+ }
}
private void noteVal(long val) {
- if (state == 0)
+ if (state == 0) {
arg0 = val;
- else if (state == 2)
+ } else if (state == 2) {
arg1 = val;
- else
+ } else {
state = -1;
+ }
state++;
}
@@ -84,8 +86,9 @@ public class IncompatMask extends BytecodeScanningDetector implements StatelessD
static int populationCount(long i) {
int result = 0;
while (i != 0) {
- if ((i & 1) == 1)
+ if ((i & 1) == 1) {
result++;
+ }
i >>>= 1;
}
return result;
@@ -160,16 +163,17 @@ public class IncompatMask extends BytecodeScanningDetector implements StatelessD
case IFLT:
case IFGT:
case IFGE:
- if (state == 3 && isLong || state == 2 & !isLong) {
+ if (state == 3 && isLong || state == 2 && !isLong) {
long bits = getFlagBits(isLong, arg0);
boolean highbit = !isLong && (bits & 0x80000000) != 0 || isLong && bits < 0 && bits << 1 == 0;
boolean onlyLowBits = bits >>> 12 == 0;
BugInstance bug;
- if (highbit)
+ if (highbit) {
bug = new BugInstance(this, "BIT_SIGNED_CHECK_HIGH_BIT", (seen == IFLE || seen == IFGT) ? HIGH_PRIORITY
: NORMAL_PRIORITY);
- else
+ } else {
bug = new BugInstance(this, "BIT_SIGNED_CHECK", onlyLowBits ? LOW_PRIORITY : NORMAL_PRIORITY);
+ }
bugReporter.reportBug(bug.addClassAndMethod(this).addSourceLine(this));
}
state = 0;
@@ -183,13 +187,13 @@ public class IncompatMask extends BytecodeScanningDetector implements StatelessD
state = 3;
}
- /* fallthrough */
-
+ //$FALL-THROUGH$
case IF_ICMPEQ:
case IF_ICMPNE:
checkState(3);
- if (state != 4)
+ if (state != 4) {
return;
+ }
break; /* the only break in this switch! gross */
case GOTO:
@@ -219,8 +223,9 @@ public class IncompatMask extends BytecodeScanningDetector implements StatelessD
if (dif != 0) {
// System.out.println("Match at offset " + getPC());
BugInstance bug = new BugInstance(this, t, HIGH_PRIORITY).addClassAndMethod(this);
- if (!t.equals("BIT_AND_ZZ"))
+ if (!"BIT_AND_ZZ".equals(t)) {
bug.addString("0x" + Long.toHexString(arg0)).addString("0x" + Long.toHexString(arg1));
+ }
bug.addSourceLine(this);
bugReporter.reportBug(bug);
@@ -228,18 +233,16 @@ public class IncompatMask extends BytecodeScanningDetector implements StatelessD
state = 0;
}
- /**
- * @return
- */
static long getFlagBits(boolean isLong, long arg0) {
long bits = arg0;
if (isLong) {
- if (populationCount(bits) > populationCount(~bits))
+ if (populationCount(bits) > populationCount(~bits)) {
bits = ~bits;
- } else if (populationCount(0xffffffffL & bits) > populationCount(0xffffffffL & ~bits))
+ }
+ } else if (populationCount(0xffffffffL & bits) > populationCount(0xffffffffL & ~bits)) {
bits = 0xffffffffL & ~bits;
+ }
return bits;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/InconsistentAnnotations.java b/src/java/edu/umd/cs/findbugs/detect/InconsistentAnnotations.java
index a036c63..9fbcd33 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InconsistentAnnotations.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InconsistentAnnotations.java
@@ -41,7 +41,7 @@ import edu.umd.cs.findbugs.classfile.DescriptorFactory;
public class InconsistentAnnotations implements Detector, UseAnnotationDatabase {
- public final TypeQualifierValue nonnullTypeQualifierValue;
+ public final TypeQualifierValue<?> nonnullTypeQualifierValue;
final BugReporter reporter;
@@ -51,6 +51,7 @@ public class InconsistentAnnotations implements Detector, UseAnnotationDatabase
this.reporter = reporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass jclass = classContext.getJavaClass();
@@ -73,7 +74,7 @@ public class InconsistentAnnotations implements Detector, UseAnnotationDatabase
reporter.reportBug(new BugInstance(this, "NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE",
NORMAL_PRIORITY).addClassAndMethod(jclass, method).add(
- LocalVariableAnnotation.getParameterLocalVariableAnnotation(method, paramLocal)));
+ LocalVariableAnnotation.getParameterLocalVariableAnnotation(method, paramLocal)));
}
@@ -83,6 +84,7 @@ public class InconsistentAnnotations implements Detector, UseAnnotationDatabase
}
+ @Override
public void report() {
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/InconsistentSyncWarningProperty.java b/src/java/edu/umd/cs/findbugs/detect/InconsistentSyncWarningProperty.java
index 8ef55d5..9913204 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InconsistentSyncWarningProperty.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InconsistentSyncWarningProperty.java
@@ -23,7 +23,7 @@ import edu.umd.cs.findbugs.props.PriorityAdjustment;
/**
* Warning properties for inconsistent synchronization detector.
- *
+ *
* @author David Hovemeyer
*/
public class InconsistentSyncWarningProperty extends AbstractWarningProperty {
diff --git a/src/java/edu/umd/cs/findbugs/detect/InefficientIndexOf.java b/src/java/edu/umd/cs/findbugs/detect/InefficientIndexOf.java
new file mode 100644
index 0000000..0840f89
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/detect/InefficientIndexOf.java
@@ -0,0 +1,85 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2006, University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.detect;
+
+import java.util.Arrays;
+import java.util.List;
+
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.OpcodeStack;
+import edu.umd.cs.findbugs.StringAnnotation;
+import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+
+/**
+ * Use whenever possible String.indexOf(int) instead of String.indexOf(String),
+ * or String.lastIndexOf(int) instead of String.lastIndexOf(String).
+ *
+ * @author Reto Merz
+ */
+public class InefficientIndexOf extends OpcodeStackDetector {
+ private final BugReporter bugReporter;
+
+ private static final List<MethodDescriptor> methods = Arrays.asList(
+ new MethodDescriptor("java/lang/String", "indexOf", "(Ljava/lang/String;)I"),
+ new MethodDescriptor("java/lang/String", "lastIndexOf", "(Ljava/lang/String;)I"),
+ new MethodDescriptor("java/lang/String", "indexOf", "(Ljava/lang/String;I)I"),
+ new MethodDescriptor("java/lang/String", "lastIndexOf", "(Ljava/lang/String;I)I")
+ );
+
+ public InefficientIndexOf(BugReporter bugReporter) {
+ this.bugReporter = bugReporter;
+ }
+
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ if(hasInterestingMethod(classContext.getJavaClass().getConstantPool(), methods)) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if (seen == INVOKEVIRTUAL && stack.getStackDepth() > 0 && "java/lang/String".equals(getClassConstantOperand())) {
+
+ boolean lastIndexOf = "lastIndexOf".equals(getNameConstantOperand());
+ if (lastIndexOf || "indexOf".equals(getNameConstantOperand())) {
+
+ int stackOff = -1;
+ if ("(Ljava/lang/String;)I".equals(getSigConstantOperand())) { // sig: String
+ stackOff = 0;
+ } else if ("(Ljava/lang/String;I)I".equals(getSigConstantOperand())) { // sig: String, int
+ stackOff = 1;
+ }
+ if (stackOff > -1) {
+ OpcodeStack.Item item = stack.getStackItem(stackOff);
+ Object o = item.getConstant();
+ if (o != null && ((String) o).length() == 1) {
+ bugReporter.reportBug(new BugInstance(this, lastIndexOf ? "IIO_INEFFICIENT_LAST_INDEX_OF" : "IIO_INEFFICIENT_INDEX_OF", LOW_PRIORITY).addClassAndMethod(this)
+ .describe(StringAnnotation.STRING_MESSAGE).addCalledMethod(this).addSourceLine(this));
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/java/edu/umd/cs/findbugs/detect/InefficientInitializationInsideLoop.java b/src/java/edu/umd/cs/findbugs/detect/InefficientInitializationInsideLoop.java
new file mode 100644
index 0000000..b9d0458
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/detect/InefficientInitializationInsideLoop.java
@@ -0,0 +1,181 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.detect;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.bcel.classfile.Method;
+
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.OpcodeStack.Item;
+import edu.umd.cs.findbugs.StringAnnotation;
+import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.ba.XMethod;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+
+/**
+ * @author Tagir Valeev
+ */
+public class InefficientInitializationInsideLoop extends OpcodeStackDetector {
+ private static final MethodDescriptor NODELIST_GET_LENGTH = new MethodDescriptor("org/w3c/dom/NodeList", "getLength", "()I");
+ private static final MethodDescriptor PATTERN_COMPILE = new MethodDescriptor("java/util/regex/Pattern", "compile", "(Ljava/lang/String;)Ljava/util/regex/Pattern;", true);
+ private static final MethodDescriptor PATTERN_COMPILE_2 = new MethodDescriptor("java/util/regex/Pattern", "compile", "(Ljava/lang/String;I)Ljava/util/regex/Pattern;", true);
+ private static final MethodDescriptor PATTERN_MATCHES = new MethodDescriptor("java/util/regex/Pattern", "matches", "(Ljava/lang/String;Ljava/lang/CharSequence;)Z", true);
+ private static final MethodDescriptor STRING_REPLACEALL = new MethodDescriptor("java/lang/String", "replaceAll", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ private static final MethodDescriptor STRING_REPLACEFIRST = new MethodDescriptor("java/lang/String", "replaceFirst", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ private static final MethodDescriptor STRING_MATCHES = new MethodDescriptor("java/lang/String", "matches", "(Ljava/lang/String;)Z");
+ private static final MethodDescriptor STRING_SPLIT = new MethodDescriptor("java/lang/String", "split", "(Ljava/lang/String;)[Ljava/lang/String;");
+ private static final MethodDescriptor STRING_SPLIT_2 = new MethodDescriptor("java/lang/String", "split", "(Ljava/lang/String;I)[Ljava/lang/String;");
+
+ private static final Set<MethodDescriptor> implicitPatternMethods = new HashSet<>(Arrays.asList(PATTERN_MATCHES,
+ STRING_MATCHES, STRING_REPLACEALL, STRING_REPLACEFIRST, STRING_SPLIT, STRING_SPLIT_2));
+
+ private static final List<MethodDescriptor> methods = new ArrayList<>();
+
+ static {
+ methods.add(NODELIST_GET_LENGTH);
+ methods.add(PATTERN_COMPILE);
+ methods.add(PATTERN_COMPILE_2);
+ methods.addAll(implicitPatternMethods);
+ }
+
+ private SortedMap<Integer, BugInstance> matched;
+
+ private SortedMap<Integer, Integer> conditions;
+
+ private SortedMap<Integer, Integer> sources;
+
+ private final BugReporter bugReporter;
+
+ public InefficientInitializationInsideLoop(BugReporter bugReporter) {
+ this.bugReporter = bugReporter;
+ }
+
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ if (hasInterestingMethod(classContext.getJavaClass().getConstantPool(), methods)
+ || hasInterestingClass(classContext.getJavaClass().getConstantPool(),
+ Collections.singleton("java/sql/Connection"))) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
+ public void visitMethod(Method obj) {
+ matched = new TreeMap<>();
+ conditions = new TreeMap<>();
+ sources = new TreeMap<>();
+ super.visitMethod(obj);
+ }
+
+ /**
+ * Since JDK 1.7 there's a special branch in String.split which works very fast for one-character pattern
+ * We do not report a bug if this case takes place
+ * (in fact precompilation will make split much slower since this fast path doesn't use regexp engine at all)
+ * @param regex regex to test whether it's suitable for the fast path
+ * @return true if fast path is possible
+ */
+ private boolean isFastPath(String regex) {
+ char ch;
+ return (((regex.length() == 1 && ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || (regex.length() == 2
+ && regex.charAt(0) == '\\' && (((ch = regex.charAt(1)) - '0') | ('9' - ch)) < 0 && ((ch - 'a') | ('z' - ch)) < 0 && ((ch - 'A') | ('Z' - ch)) < 0)) && (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE));
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if (seen == INVOKEINTERFACE && getClassConstantOperand().equals("java/sql/Connection")
+ && getMethodDescriptorOperand().getName().equals("prepareStatement") && hasConstantArguments()) {
+ matched.put(getPC(), new BugInstance(this, "IIL_PREPARE_STATEMENT_IN_LOOP", NORMAL_PRIORITY).addClassAndMethod(this)
+ .addSourceLine(this, getPC()).addCalledMethod(this));
+ } else if (seen == INVOKEINTERFACE && getMethodDescriptorOperand().equals(NODELIST_GET_LENGTH)) {
+ Item item = getStack().getStackItem(0);
+ XMethod returnValueOf = item.getReturnValueOf();
+ if(returnValueOf != null && returnValueOf.getClassName().startsWith("org.w3c.dom.") && returnValueOf.getName().startsWith("getElementsByTagName")) {
+ matched.put(getPC(),
+ new BugInstance(this, "IIL_ELEMENTS_GET_LENGTH_IN_LOOP", NORMAL_PRIORITY).addClassAndMethod(this)
+ .addSourceLine(this, getPC()).addCalledMethod(this));
+ sources.put(getPC(), item.getPC());
+ }
+ } else if (seen == INVOKESTATIC
+ && (getMethodDescriptorOperand().equals(PATTERN_COMPILE) || getMethodDescriptorOperand()
+ .equals(PATTERN_COMPILE_2)) && hasConstantArguments()) {
+ String regex = getFirstArgument();
+ matched.put(getPC(), new BugInstance(this, "IIL_PATTERN_COMPILE_IN_LOOP", NORMAL_PRIORITY).addClassAndMethod(this)
+ .addSourceLine(this, getPC()).addCalledMethod(this).addString(regex).describe(StringAnnotation.REGEX_ROLE));
+ } else if ((seen == INVOKESTATIC || seen == INVOKEVIRTUAL) && implicitPatternMethods.contains(getMethodDescriptorOperand())) {
+ String regex = getFirstArgument();
+ if (regex != null && !(getNameConstantOperand().equals("split") && isFastPath(regex))) {
+ BugInstance bug = new BugInstance(this, "IIL_PATTERN_COMPILE_IN_LOOP_INDIRECT", LOW_PRIORITY)
+ .addClassAndMethod(this).addSourceLine(this, getPC()).addCalledMethod(this).addString(regex)
+ .describe(StringAnnotation.REGEX_ROLE);
+ matched.put(getPC(), bug);
+ }
+ } else if (isBranch(seen) && getBranchOffset() > 0) {
+ conditions.put(getPC(), getBranchTarget());
+ } else if (!matched.isEmpty() && isBranch(seen) && getBranchOffset() < 0) {
+ for (Entry<Integer, BugInstance> entry : matched.tailMap(getBranchTarget()).entrySet()) {
+ Integer source = sources.get(entry.getKey());
+ if(source != null && (source > getBranchTarget() && source < getPC())) {
+ // Object was created in the same loop: ignore
+ return;
+ }
+ for (int target : conditions.subMap(getBranchTarget(), entry.getKey()).values()) {
+ if (target > entry.getKey() && target < getPC()) {
+ return;
+ }
+ }
+ bugReporter.reportBug(entry.getValue());
+ }
+ }
+ }
+
+ /**
+ * @return first argument of the called method if it's a constant
+ */
+ private String getFirstArgument() {
+ Object value = getStack().getStackItem(getNumberArguments(getMethodDescriptorOperand().getSignature()) - 1)
+ .getConstant();
+ return value == null ? null : value.toString();
+ }
+
+ /**
+ * @return true if only constants are passed to the called method
+ */
+ private boolean hasConstantArguments() {
+ int nArgs = getNumberArguments(getMethodDescriptorOperand().getSignature());
+ for (int i = 0; i < nArgs; i++) {
+ if (getStack().getStackItem(i).getConstant() == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/src/java/edu/umd/cs/findbugs/detect/InefficientMemberAccess.java b/src/java/edu/umd/cs/findbugs/detect/InefficientMemberAccess.java
index 620f04c..138e9a1 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InefficientMemberAccess.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InefficientMemberAccess.java
@@ -26,13 +26,16 @@ import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.StatelessDetector;
+import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.ba.InnerClassAccess;
+import edu.umd.cs.findbugs.ba.SignatureParser;
public class InefficientMemberAccess extends BytecodeScanningDetector implements StatelessDetector {
public static final String ACCESS_PREFIX = "access$";
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private String clsName;
@@ -44,8 +47,9 @@ public class InefficientMemberAccess extends BytecodeScanningDetector implements
public void visitClassContext(ClassContext classContext) {
JavaClass cls = classContext.getJavaClass();
clsName = cls.getClassName();
- if (clsName.indexOf("$") >= 0)
+ if (clsName.indexOf('$') >= 0) {
super.visitClassContext(classContext);
+ }
}
@Override
@@ -53,24 +57,52 @@ public class InefficientMemberAccess extends BytecodeScanningDetector implements
if (seen == INVOKESTATIC) {
String methodName = getNameConstantOperand();
- if (!methodName.startsWith(ACCESS_PREFIX))
+ if (!methodName.startsWith(ACCESS_PREFIX)) {
return;
+ }
String methodSig = getSigConstantOperand();
Type[] argTypes = Type.getArgumentTypes(methodSig);
- if ((argTypes.length < 1) || (argTypes.length > 2))
+ if ((argTypes.length < 1) || (argTypes.length > 2)) {
return;
+ }
String parCls = argTypes[0].getSignature();
- if (parCls.length() < 3)
+ if (parCls.length() < 3) {
return;
+ }
parCls = parCls.substring(1, parCls.length() - 1);
- if (!parCls.equals(getClassConstantOperand()))
+ if (!parCls.equals(getClassConstantOperand())) {
return;
- if ((argTypes.length == 2) && !argTypes[1].getSignature().equals(Type.getReturnType(methodSig).getSignature()))
+ }
+ if ((argTypes.length == 2) && !argTypes[1].getSignature().equals(new SignatureParser(methodSig).getReturnTypeSignature())) {
return;
+ }
+
+ InnerClassAccess access = null;
+ try {
+ String dottedClassConstantOperand = getDottedClassConstantOperand();
+ access = AnalysisContext.currentAnalysisContext().getInnerClassAccessMap().getInnerClassAccess(dottedClassConstantOperand, methodName);
+ if(access != null) {
+ // if the enclosing class of the field differs from the enclosing class of the method, we shouln't report
+ // because there is nothing wrong: see bug 1226
+ if (!access.getField().getClassName().equals(dottedClassConstantOperand)) {
+ return;
+ }
+ // the access method is created to access the synthetic reference to the enclosing class, we shouln't report
+ // user can't do anything here, see bug 1191
+ if(access.getField().isSynthetic()){
+ return;
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ }
- bugReporter.reportBug(new BugInstance(this, "IMA_INEFFICIENT_MEMBER_ACCESS", LOW_PRIORITY).addClassAndMethod(this)
- .addSourceLine(this));
+ BugInstance bug = new BugInstance(this, "IMA_INEFFICIENT_MEMBER_ACCESS", LOW_PRIORITY).addClassAndMethod(this)
+ .addSourceLine(this);
+ if(access != null) {
+ bug.addField(access.getField());
+ }
+ bugReporter.reportBug(bug);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/InefficientToArray.java b/src/java/edu/umd/cs/findbugs/detect/InefficientToArray.java
index 9b53e4f..e578f46 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InefficientToArray.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InefficientToArray.java
@@ -20,6 +20,9 @@
package edu.umd.cs.findbugs.detect;
+import java.util.Collections;
+import java.util.List;
+
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.JavaClass;
@@ -33,17 +36,21 @@ import edu.umd.cs.findbugs.StatelessDetector;
import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Find occurrences of collection.toArray( new Foo[0] ); This causes another
* memory allocation through reflection Much better to do collection.toArray(
* new Foo[collection.size()] );
- *
+ *
* @author Dave Brosius
*/
public class InefficientToArray extends BytecodeScanningDetector implements StatelessDetector {
private static final boolean DEBUG = SystemProperties.getBoolean("ita.debug");
+ private static final List<MethodDescriptor> methods = Collections.singletonList(new MethodDescriptor("", "toArray",
+ "([Ljava/lang/Object;)[Ljava/lang/Object;"));
+
static final int SEEN_NOTHING = 0;
static final int SEEN_ICONST_0 = 1;
@@ -52,9 +59,9 @@ public class InefficientToArray extends BytecodeScanningDetector implements Stat
private final static JavaClass collectionClass;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
- private BugAccumulator bugAccumulator;
+ private final BugAccumulator bugAccumulator;
private int state = SEEN_NOTHING;
@@ -75,14 +82,16 @@ public class InefficientToArray extends BytecodeScanningDetector implements Stat
@Override
public void visitClassContext(ClassContext classContext) {
- if (collectionClass != null)
+ if (collectionClass != null && hasInterestingMethod(classContext.getJavaClass().getConstantPool(), methods)) {
classContext.getJavaClass().accept(this);
+ }
}
@Override
public void visit(Method obj) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("------------------- Analyzing " + obj.getName() + " ----------------");
+ }
state = SEEN_NOTHING;
super.visit(obj);
}
@@ -96,31 +105,35 @@ public class InefficientToArray extends BytecodeScanningDetector implements Stat
@Override
public void sawOpcode(int seen) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("State: " + state + " Opcode: " + OPCODE_NAMES[seen]);
+ }
switch (state) {
case SEEN_NOTHING:
- if (seen == ICONST_0)
+ if (seen == ICONST_0) {
state = SEEN_ICONST_0;
+ }
break;
case SEEN_ICONST_0:
if (seen == ANEWARRAY) {
state = SEEN_ANEWARRAY;
- } else
+ } else {
state = SEEN_NOTHING;
+ }
break;
case SEEN_ANEWARRAY:
- if (((seen == INVOKEVIRTUAL) || (seen == INVOKEINTERFACE)) && (getNameConstantOperand().equals("toArray"))
- && (getSigConstantOperand().equals("([Ljava/lang/Object;)[Ljava/lang/Object;"))) {
+ if (((seen == INVOKEVIRTUAL) || (seen == INVOKEINTERFACE)) && ("toArray".equals(getNameConstantOperand()))
+ && ("([Ljava/lang/Object;)[Ljava/lang/Object;".equals(getSigConstantOperand()))) {
try {
String clsName = getDottedClassConstantOperand();
JavaClass cls = Repository.lookupClass(clsName);
- if (cls.implementationOf(collectionClass))
+ if (cls.implementationOf(collectionClass)) {
bugAccumulator.accumulateBug(
new BugInstance(this, "ITA_INEFFICIENT_TO_ARRAY", LOW_PRIORITY).addClassAndMethod(this), this);
+ }
} catch (ClassNotFoundException cnfe) {
bugReporter.reportMissingClass(cnfe);
@@ -136,4 +149,3 @@ public class InefficientToArray extends BytecodeScanningDetector implements Stat
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/InfiniteLoop.java b/src/java/edu/umd/cs/findbugs/detect/InfiniteLoop.java
index aeff427..905f9d8 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InfiniteLoop.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InfiniteLoop.java
@@ -41,14 +41,15 @@ import edu.umd.cs.findbugs.visitclass.Util;
public class InfiniteLoop extends OpcodeStackDetector {
- private static final boolean active = true;
+ // private static final boolean active = true;
ArrayList<BitSet> regModifiedAt = new ArrayList<BitSet>();
@Nonnull
BitSet getModifiedBitSet(int reg) {
- while (regModifiedAt.size() <= reg)
+ while (regModifiedAt.size() <= reg) {
regModifiedAt.add(new BitSet());
+ }
return regModifiedAt.get(reg);
}
@@ -58,13 +59,15 @@ public class InfiniteLoop extends OpcodeStackDetector {
}
private void clearRegModified() {
- for (BitSet b : regModifiedAt)
+ for (BitSet b : regModifiedAt) {
b.clear();
+ }
}
private boolean isRegModified(int reg, int firstPC, int lastPC) {
- if (reg < 0)
+ if (reg < 0) {
return false;
+ }
BitSet b = getModifiedBitSet(reg);
int modified = b.nextSetBit(firstPC);
return (modified >= firstPC && modified <= lastPC);
@@ -90,10 +93,12 @@ public class InfiniteLoop extends OpcodeStackDetector {
@Override
public boolean equals(Object o) {
- if (o == null)
+ if (o == null) {
return false;
- if (this.getClass() != o.getClass())
+ }
+ if (this.getClass() != o.getClass()) {
return false;
+ }
Jump that = (Jump) o;
return this.from == that.from && this.to == that.to;
}
@@ -107,9 +112,11 @@ public class InfiniteLoop extends OpcodeStackDetector {
BackwardsBranch(OpcodeStack stack, int from, int to) {
super(from, to);
numLastUpdates = stack.getNumLastUpdates();
- for (int i = 0; i < numLastUpdates; i++)
- if (stack.getLastUpdate(i) < to)
+ for (int i = 0; i < numLastUpdates; i++) {
+ if (stack.getLastUpdate(i) < to) {
invariantRegisters.add(i);
+ }
+ }
}
@Override
@@ -119,8 +126,9 @@ public class InfiniteLoop extends OpcodeStackDetector {
@Override
public boolean equals(Object o) {
- if (!super.equals(o))
+ if (!super.equals(o)) {
return false;
+ }
BackwardsBranch that = (BackwardsBranch) o;
return this.invariantRegisters.equals(that.invariantRegisters) && this.numLastUpdates == that.numLastUpdates;
}
@@ -142,10 +150,11 @@ public class InfiniteLoop extends OpcodeStackDetector {
@Override
public boolean equals(Object o) {
- if (!super.equals(o))
+ if (!super.equals(o)) {
return false;
+ }
ForwardConditionalBranch that = (ForwardConditionalBranch) o;
- return this.item0.equals(that.item0) && this.item1.equals(that.item1);
+ return this.item0.sameValue(that.item0) && this.item1.sameValue(that.item1);
}
}
@@ -161,18 +170,22 @@ public class InfiniteLoop extends OpcodeStackDetector {
LinkedList<Jump> forwardJumps = new LinkedList<Jump>();
void purgeForwardJumps(int before) {
- if (true)
+ if (true) {
return;
+ /*
for (Iterator<Jump> i = forwardJumps.iterator(); i.hasNext();) {
Jump j = i.next();
if (j.to < before)
i.remove();
}
+ */
+ }
}
void addForwardJump(int from, int to) {
- if (from >= to)
+ if (from >= to) {
return;
+ }
purgeForwardJumps(from);
forwardJumps.add(new Jump(from, to));
}
@@ -182,9 +195,11 @@ public class InfiniteLoop extends OpcodeStackDetector {
int from2 = getBackwardsReach(from);
assert from2 <= from;
from = from2;
- for (Jump f : forwardJumps)
- if (f.from >= from && f.to > result)
+ for (Jump f : forwardJumps) {
+ if (f.from >= from && f.to > result) {
result = f.to;
+ }
+ }
return result;
}
@@ -194,8 +209,9 @@ public class InfiniteLoop extends OpcodeStackDetector {
@Override
public void visit(Code obj) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println(getFullyQualifiedMethodName());
+ }
clearRegModified();
backwardBranches.clear();
forwardConditionalBranches.clear();
@@ -206,16 +222,21 @@ public class InfiniteLoop extends OpcodeStackDetector {
LinkedList<ForwardConditionalBranch> myForwardBranches = new LinkedList<ForwardConditionalBranch>();
int myBackwardsReach = getBackwardsReach(bb.to);
- for (ForwardConditionalBranch fcb : forwardConditionalBranches)
- if (myBackwardsReach < fcb.from && fcb.from < bb.from && bb.from < fcb.to)
+ for (ForwardConditionalBranch fcb : forwardConditionalBranches) {
+ if (myBackwardsReach < fcb.from && fcb.from < bb.from && bb.from < fcb.to) {
myForwardBranches.add(fcb);
+ }
+ }
- if (myForwardBranches.size() != 1)
+ if (myForwardBranches.size() != 1) {
continue;
+ }
ForwardConditionalBranch fcb = myForwardBranches.get(0);
- for (Jump fj : forwardJumps)
- if (fcb.from != fj.from && myBackwardsReach < fj.from && fj.from < bb.from && bb.from < fj.to)
+ for (Jump fj : forwardJumps) {
+ if (fcb.from != fj.from && myBackwardsReach < fj.from && fj.from < bb.from && bb.from < fj.to) {
continue backwardBranchLoop;
+ }
+ }
if (isConstant(fcb.item0, bb) && isConstant(fcb.item1, bb)) {
SourceLineAnnotation loopBottom = SourceLineAnnotation.fromVisitedInstruction(getClassContext(), this, bb.from);
@@ -233,10 +254,11 @@ public class InfiniteLoop extends OpcodeStackDetector {
constantSince(fcb.item0));
int lastChangeLine = lastChange.getEndLine();
if (loopBottomLine != -1 && lastChangeLine != -1 && loopTopLine != -1 && loopTopLine <= lastChangeLine
- && lastChangeLine < loopBottomLine)
+ && lastChangeLine < loopBottomLine) {
continue backwardBranchLoop;
+ }
bug.add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), reg0, fcb.from, bb.from))
- .addSourceLine(lastChange).describe(SourceLineAnnotation.DESCRIPTION_LAST_CHANGE);
+ .addSourceLine(lastChange).describe(SourceLineAnnotation.DESCRIPTION_LAST_CHANGE);
}
int reg1 = fcb.item1.getRegisterNumber();
if (reg1 >= 0 && reg1 != reg0 && fcb.item1.getConstant() == null) {
@@ -244,36 +266,37 @@ public class InfiniteLoop extends OpcodeStackDetector {
constantSince(fcb.item1));
int lastChangeLine = lastChange.getEndLine();
if (loopBottomLine != -1 && lastChangeLine != -1 && loopTopLine != -1 && loopTopLine <= lastChangeLine
- && lastChangeLine < loopBottomLine)
+ && lastChangeLine < loopBottomLine) {
continue backwardBranchLoop;
+ }
bug.add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), reg1, fcb.from, bb.from))
- .addSourceLine(lastChange).describe(SourceLineAnnotation.DESCRIPTION_LAST_CHANGE);
+ .addSourceLine(lastChange).describe(SourceLineAnnotation.DESCRIPTION_LAST_CHANGE);
}
boolean reg1Invariant = true;
- if (reg1 >= 0)
+ if (reg1 >= 0) {
reg1Invariant = !isRegModified(reg1, myBackwardsReach, bb.from);
- if (reg0Invariant && reg1Invariant)
+ }
+ if (reg0Invariant && reg1Invariant) {
bugReporter.reportBug(bug);
+ }
}
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println();
-
+ }
+
}
- /**
- * @param item0
- * @param invariantRegisters
- * @return
- */
private boolean isConstant(Item item0, BackwardsBranch bb) {
int reg = item0.getRegisterNumber();
- if (reg >= 0)
+ if (reg >= 0) {
return bb.invariantRegisters.contains(reg) || reg >= bb.numLastUpdates;
- if (item0.getConstant() != null)
+ }
+ if (item0.getConstant() != null) {
return true;
+ }
return false;
}
@@ -285,17 +308,21 @@ public class InfiniteLoop extends OpcodeStackDetector {
static final boolean DEBUG = false;
@Override
public void sawOpcode(int seen) {
- if (DEBUG)
+ if (DEBUG) {
System.out.printf("%3d %-15s %s%n", getPC(), OPCODE_NAMES[seen], stack);
- if (isRegisterStore())
+ }
+ if (isRegisterStore()) {
regModifiedAt(getRegisterOperand(), getPC());
+ }
switch (seen) {
case GOTO:
if (getBranchOffset() < 0) {
BackwardsBranch bb = new BackwardsBranch(stack, getPC(), getBranchTarget());
- if (bb.invariantRegisters.size() > 0)
+ if (bb.invariantRegisters.size() > 0) {
backwardBranches.add(bb);
+ }
addBackwardsReach();
+ /*
if (false) {
int target = getBranchTarget();
if (getFurthestJump(target) > getPC())
@@ -306,6 +333,7 @@ public class InfiniteLoop extends OpcodeStackDetector {
.addSourceLine(this, getPC());
reportPossibleBug(bug);
}
+ */
}
break;
@@ -322,12 +350,15 @@ public class InfiniteLoop extends OpcodeStackDetector {
case LOOKUPSWITCH:
case TABLESWITCH: {
OpcodeStack.Item item0 = stack.getStackItem(0);
- if (getDefaultSwitchOffset() > 0)
+ if (getDefaultSwitchOffset() > 0) {
forwardConditionalBranches.add(new ForwardConditionalBranch(item0, item0, getPC(), getPC()
+ getDefaultSwitchOffset()));
- for (int offset : getSwitchOffsets())
- if (offset > 0)
+ }
+ for (int offset : getSwitchOffsets()) {
+ if (offset > 0) {
forwardConditionalBranches.add(new ForwardConditionalBranch(item0, item0, getPC(), getPC() + offset));
+ }
+ }
break;
}
case IFNE:
@@ -345,23 +376,26 @@ public class InfiniteLoop extends OpcodeStackDetector {
forwardConditionalBranches.add(new ForwardConditionalBranch(item0, item0, getPC(), target));
break;
}
- if (getFurthestJump(target) > getPC())
+ if (getFurthestJump(target) > getPC()) {
break;
+ }
if (constantSince(item0, target)) {
int since0 = constantSince(item0);
BugInstance bug = new BugInstance(this, "IL_INFINITE_LOOP", HIGH_PRIORITY).addClassAndMethod(this).addSourceLine(
this, getPC());
int reg0 = item0.getRegisterNumber();
- if (reg0 >= 0)
+ if (reg0 >= 0) {
bug.add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), reg0, getPC(), target))
- .addSourceLine(this, since0);
- if (reg0 < 0 || !isRegModified(reg0, target, getPC()))
+ .addSourceLine(this, since0);
+ }
+ if (reg0 < 0 || !isRegModified(reg0, target, getPC())) {
reportPossibleBug(bug);
+ }
}
}
- break;
+ break;
case IF_ACMPEQ:
case IF_ACMPNE:
case IF_ICMPNE:
@@ -378,8 +412,9 @@ public class InfiniteLoop extends OpcodeStackDetector {
forwardConditionalBranches.add(new ForwardConditionalBranch(item0, item1, getPC(), target));
break;
}
- if (getFurthestJump(target) > getPC())
+ if (getFurthestJump(target) > getPC()) {
break;
+ }
if (constantSince(item0, target) && constantSince(item1, target)) {
// int since0 = constantSince(item0);
@@ -387,16 +422,20 @@ public class InfiniteLoop extends OpcodeStackDetector {
BugInstance bug = new BugInstance(this, "IL_INFINITE_LOOP", HIGH_PRIORITY).addClassAndMethod(this).addSourceLine(
this, getPC());
int reg0 = item0.getRegisterNumber();
- if (reg0 >= 0)
+ if (reg0 >= 0) {
bug.add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), reg0, getPC(), target));
+ }
int reg1 = item1.getRegisterNumber();
- if (reg1 >= 0)
+ if (reg1 >= 0) {
bug.add(LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), reg1, getPC(), target));
+ }
reportPossibleBug(bug);
}
}
+ break;
+ default:
break;
}
@@ -406,66 +445,71 @@ public class InfiniteLoop extends OpcodeStackDetector {
*
*/
private void addBackwardsReach() {
- if (getBranchOffset() >= 0)
+ if (getBranchOffset() >= 0) {
return;
+ }
int target = getBranchTarget();
- for (Jump j : backwardReach)
- if (j.to < target && target <= j.from)
+ for (Jump j : backwardReach) {
+ if (j.to < target && target <= j.from) {
target = j.to;
+ }
+ }
assert target <= getBranchTarget();
assert target < getPC();
for (Iterator<Jump> i = backwardReach.iterator(); i.hasNext();) {
Jump j = i.next();
- if (target <= j.to && getPC() >= j.from)
+ if (target <= j.to && getPC() >= j.from) {
i.remove();
+ }
}
backwardReach.add(new Jump(getPC(), target));
}
private int getBackwardsReach(int target) {
int originalTarget = target;
- for (Jump j : backwardReach)
- if (j.to < target && target <= j.from)
+ for (Jump j : backwardReach) {
+ if (j.to < target && target <= j.from) {
target = j.to;
+ }
+ }
assert target <= originalTarget;
return target;
}
- /**
- * @param item1
- * @param branchTarget
- * @return
- */
private boolean constantSince(Item item1, int branchTarget) {
int reg = item1.getRegisterNumber();
- if (reg >= 0)
+ if (reg >= 0) {
return stack.getLastUpdate(reg) < getBackwardsReach(branchTarget);
- if (item1.getConstant() != null)
+ }
+ if (item1.getConstant() != null) {
return true;
+ }
return false;
}
private int constantSince(Item item1) {
int reg = item1.getRegisterNumber();
- if (reg >= 0)
+ if (reg >= 0) {
return stack.getLastUpdate(reg);
+ }
return Integer.MAX_VALUE;
}
void reportPossibleBug(BugInstance bug) {
int catchSize = Util.getSizeOfSurroundingTryBlock(getConstantPool(), getCode(), "java/io/EOFException", getPC());
- if (catchSize < Integer.MAX_VALUE)
+ if (catchSize < Integer.MAX_VALUE) {
bug.lowerPriorityALot();
- else {
+ } else {
catchSize = Util.getSizeOfSurroundingTryBlock(getConstantPool(), getCode(), "java/lang/NoSuchElementException",
getPC());
- if (catchSize < Integer.MAX_VALUE)
+ if (catchSize < Integer.MAX_VALUE) {
bug.lowerPriorityALot();
- else {
+ } else {
LocalVariableAnnotation lv = bug.getPrimaryLocalVariableAnnotation();
- if (lv == null && getMethodName().equals("run"))
+ if (lv == null && "run".equals(getMethodName())) {
bug.lowerPriority();
+ }
}
}
bugReporter.reportBug(bug);
diff --git a/src/java/edu/umd/cs/findbugs/detect/InfiniteRecursiveLoop.java b/src/java/edu/umd/cs/findbugs/detect/InfiniteRecursiveLoop.java
index ec91471..84cb4d1 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InfiniteRecursiveLoop.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InfiniteRecursiveLoop.java
@@ -33,13 +33,13 @@ import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
public class InfiniteRecursiveLoop extends OpcodeStackDetector implements StatelessDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private boolean seenTransferOfControl;
private boolean seenReturn;
- private boolean seenThrow;
+ // private boolean seenThrow;
private boolean seenStateChange;
@@ -56,7 +56,7 @@ public class InfiniteRecursiveLoop extends OpcodeStackDetector implements Statel
seenTransferOfControl = false;
seenStateChange = false;
seenReturn = false;
- seenThrow = false;
+ // seenThrow = false;
largestBranchTarget = -1;
if (DEBUG) {
@@ -68,10 +68,12 @@ public class InfiniteRecursiveLoop extends OpcodeStackDetector implements Statel
@Override
public void sawBranchTo(int target) {
- if (target == getNextPC())
+ if (target == getNextPC()) {
return;
- if (largestBranchTarget < target)
+ }
+ if (largestBranchTarget < target) {
largestBranchTarget = target;
+ }
seenTransferOfControl = true;
}
@@ -82,36 +84,38 @@ public class InfiniteRecursiveLoop extends OpcodeStackDetector implements Statel
*/
@Override
public void sawOpcode(int seen) {
- if (seenReturn && seenTransferOfControl && seenStateChange)
+ if (seenReturn && seenTransferOfControl && seenStateChange) {
return;
+ }
if (DEBUG) {
System.out.println(stack);
System.out.println(getPC() + " : " + OPCODE_NAMES[seen]);
}
- if ((seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) && getNameConstantOperand().equals("add")
- && getSigConstantOperand().equals("(Ljava/lang/Object;)Z") && stack.getStackDepth() >= 2) {
+ if ((seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) && "add".equals(getNameConstantOperand())
+ && "(Ljava/lang/Object;)Z".equals(getSigConstantOperand()) && stack.getStackDepth() >= 2) {
OpcodeStack.Item it0 = stack.getStackItem(0);
int r0 = it0.getRegisterNumber();
OpcodeStack.Item it1 = stack.getStackItem(1);
int r1 = it1.getRegisterNumber();
- if (r0 == r1 && r0 > 0)
+ if (r0 == r1 && r0 > 0) {
bugReporter.reportBug(new BugInstance(this, "IL_CONTAINER_ADDED_TO_ITSELF", NORMAL_PRIORITY).addClassAndMethod(
this).addSourceLine(this));
+ }
}
if ((seen == INVOKEVIRTUAL || seen == INVOKESPECIAL || seen == INVOKEINTERFACE || seen == INVOKESTATIC)
&& getNameConstantOperand().equals(getMethodName())
&& getSigConstantOperand().equals(getMethodSig())
&& (seen == INVOKESTATIC) == getMethod().isStatic()
- && (seen == INVOKESPECIAL) == (getMethod().isPrivate() && !getMethod().isStatic() || getMethodName().equals(
- "<init>"))) {
+ && (seen == INVOKESPECIAL) == (getMethod().isPrivate() && !getMethod().isStatic() || "<init>".equals(getMethodName()))) {
Type arguments[] = getMethod().getArgumentTypes();
// stack.getStackDepth() >= parameters
int parameters = arguments.length;
- if (!getMethod().isStatic())
+ if (!getMethod().isStatic()) {
parameters++;
+ }
XMethod xMethod = XFactory.createReferencedXMethod(this);
if (DEBUG) {
System.out.println("IL: Checking...");
@@ -123,8 +127,9 @@ public class InfiniteRecursiveLoop extends OpcodeStackDetector implements Statel
// Invocation of same method
// Now need to see if parameters are the same
int firstParameter = 0;
- if (getMethodName().equals("<init>"))
+ if ("<init>".equals(getMethodName())) {
firstParameter = 1;
+ }
// match1 should be true if it is any call to the exact same
// method
@@ -137,19 +142,22 @@ public class InfiniteRecursiveLoop extends OpcodeStackDetector implements Statel
boolean match1 = !seenStateChange;
for (int i = firstParameter; match1 && i < parameters; i++) {
OpcodeStack.Item it = stack.getStackItem(parameters - 1 - i);
- if (!it.isInitialParameter() || it.getRegisterNumber() != i)
+ if (!it.isInitialParameter() || it.getRegisterNumber() != i) {
match1 = false;
+ }
}
- boolean sameMethod = seen == INVOKESTATIC || getNameConstantOperand().equals("<init>");
+ boolean sameMethod = seen == INVOKESTATIC || "<init>".equals(getNameConstantOperand());
if (!sameMethod) {
// Have to check if first parmeter is the same
// know there must be a this argument
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Stack is " + stack);
+ }
OpcodeStack.Item p = stack.getStackItem(parameters - 1);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("parameters = " + parameters + ", Item is " + p);
+ }
String sig = p.getSignature();
sameMethod = p.isInitialParameter() && p.getRegisterNumber() == 0 && sig.equals("L" + getClassName() + ";");
@@ -168,13 +176,14 @@ public class InfiniteRecursiveLoop extends OpcodeStackDetector implements Statel
boolean match2 = sameMethod && !seenTransferOfControl;
boolean match3 = sameMethod && !seenReturn && largestBranchTarget < getPC();
if (match1 || match2 || match3) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("IL: " + sameMethod + " " + match1 + " " + match2 + " " + match3);
- int priority = HIGH_PRIORITY;
- if (!match1 && !match2 && seenThrow)
- priority = NORMAL_PRIORITY;
- if (seen == INVOKEINTERFACE)
- priority = NORMAL_PRIORITY;
+ }
+ // int priority = HIGH_PRIORITY;
+ // if (!match1 && !match2 && seenThrow)
+ // priority = NORMAL_PRIORITY;
+ // if (seen == INVOKEINTERFACE)
+ // priority = NORMAL_PRIORITY;
bugReporter.reportBug(new BugInstance(this, "IL_INFINITE_RECURSIVE_LOOP", HIGH_PRIORITY).addClassAndMethod(
this).addSourceLine(this));
}
@@ -192,7 +201,7 @@ public class InfiniteRecursiveLoop extends OpcodeStackDetector implements Statel
seenTransferOfControl = true;
break;
case ATHROW:
- seenThrow = true;
+ // seenThrow = true;
seenTransferOfControl = true;
break;
case PUTSTATIC:
@@ -211,11 +220,14 @@ public class InfiniteRecursiveLoop extends OpcodeStackDetector implements Statel
case INVOKESPECIAL:
case INVOKEINTERFACE:
case INVOKESTATIC:
- if (getNameConstantOperand().equals("print") || getNameConstantOperand().equals("println")
- || getNameConstantOperand().equals("log") || getNameConstantOperand().equals("toString"))
+ if ("print".equals(getNameConstantOperand()) || "println".equals(getNameConstantOperand())
+ || "log".equals(getNameConstantOperand()) || "toString".equals(getNameConstantOperand())) {
break;
+ }
seenStateChange = true;
break;
+ default:
+ break;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/InheritanceUnsafeGetResource.java b/src/java/edu/umd/cs/findbugs/detect/InheritanceUnsafeGetResource.java
index 660b5cc..f16bec7 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InheritanceUnsafeGetResource.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InheritanceUnsafeGetResource.java
@@ -37,7 +37,7 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
public class InheritanceUnsafeGetResource extends BytecodeScanningDetector implements StatelessDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private boolean classIsFinal;
@@ -77,15 +77,16 @@ public class InheritanceUnsafeGetResource extends BytecodeScanningDetector imple
@Override
public void sawOpcode(int seen) {
- if (reportedForThisClass)
+ if (reportedForThisClass) {
return;
+ }
switch (seen) {
case LDC:
Constant constantValue = getConstantRefOperand();
- if (constantValue instanceof ConstantClass)
+ if (constantValue instanceof ConstantClass) {
sawGetClass = -100;
- else if (constantValue instanceof ConstantString) {
+ } else if (constantValue instanceof ConstantString) {
stringConstant = ((ConstantString) constantValue).getBytes(getConstantPool());
}
break;
@@ -94,21 +95,21 @@ public class InheritanceUnsafeGetResource extends BytecodeScanningDetector imple
state = 1;
break;
case INVOKEVIRTUAL:
- if (getClassConstantOperand().equals("java/lang/Class")
- && (getNameConstantOperand().equals("getResource") || getNameConstantOperand().equals("getResourceAsStream"))
+ if ("java/lang/Class".equals(getClassConstantOperand())
+ && ("getResource".equals(getNameConstantOperand()) || "getResourceAsStream".equals(getNameConstantOperand()))
&& sawGetClass + 10 >= getPC()) {
int priority = NORMAL_PRIORITY;
- if (prevOpcode == LDC && stringConstant != null && stringConstant.length() > 0 && stringConstant.charAt(0) == '/')
+ if (prevOpcode == LDC && stringConstant != null && stringConstant.length() > 0 && stringConstant.charAt(0) == '/') {
priority = LOW_PRIORITY;
- else {
+ } else {
priority = adjustPriority(priority);
}
bugReporter.reportBug(new BugInstance(this, "UI_INHERITANCE_UNSAFE_GETRESOURCE", priority)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
reportedForThisClass = true;
} else if (state == 1 && !methodIsStatic && !classIsFinal && classIsVisibleToOtherPackages
- && getNameConstantOperand().equals("getClass") && getSigConstantOperand().equals("()Ljava/lang/Class;")) {
+ && "getClass".equals(getNameConstantOperand()) && "()Ljava/lang/Class;".equals(getSigConstantOperand())) {
sawGetClass = getPC();
}
state = 0;
@@ -117,15 +118,16 @@ public class InheritanceUnsafeGetResource extends BytecodeScanningDetector imple
state = 0;
break;
}
- if (seen != LDC)
+ if (seen != LDC) {
stringConstant = null;
+ }
prevOpcode = seen;
}
/**
* Adjust the priority of a warning about to be reported.
- *
+ *
* @param priority
* initial priority
* @return adjusted priority
diff --git a/src/java/edu/umd/cs/findbugs/detect/InitializationChain.java b/src/java/edu/umd/cs/findbugs/detect/InitializationChain.java
index 1d98be8..ace6e89 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InitializationChain.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InitializationChain.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
@@ -46,20 +47,20 @@ public class InitializationChain extends BytecodeScanningDetector {
Map<String, Set<String>> classRequires = new TreeMap<String, Set<String>>();
-
-
- private BugReporter bugReporter;
- private Map<XMethod, Set<XField>> staticFieldsRead = new HashMap<XMethod, Set<XField>>();
- private Set<XField> staticFieldsReadInAnyConstructor = new HashSet<XField>();
+
+ private final BugReporter bugReporter;
+
+ private final Map<XMethod, Set<XField>> staticFieldsRead = new HashMap<XMethod, Set<XField>>();
+ private final Set<XField> staticFieldsReadInAnyConstructor = new HashSet<XField>();
private Set<XField> fieldsReadInThisConstructor = new HashSet<XField>();
- private Set<XMethod> constructorsInvokedInStaticInitializer = new HashSet<XMethod>();
- private List<InvocationInfo> invocationInfo = new ArrayList<InvocationInfo>();
- private Set<XField> warningGiven = new HashSet<XField>();
+ private final Set<XMethod> constructorsInvokedInStaticInitializer = new HashSet<XMethod>();
+ private final List<InvocationInfo> invocationInfo = new ArrayList<InvocationInfo>();
+ private final Set<XField> warningGiven = new HashSet<XField>();
private InvocationInfo lastInvocation;
-
+
static class InvocationInfo {
public InvocationInfo(XMethod constructor, int pc) {
this.constructor = constructor;
@@ -82,25 +83,27 @@ public class InitializationChain extends BytecodeScanningDetector {
Method staticInitializer = null;
for(Method m : obj.getMethods()) {
String name = m.getName();
- if (name.equals("<clinit>"))
+ if ("<clinit>".equals(name)) {
staticInitializer = m;
- else if (name.equals("<init>"))
+ } else if ("<init>".equals(name)) {
visitOrder.add(m);
-
+ }
+
}
- if (staticInitializer != null)
+ if (staticInitializer != null) {
visitOrder.add(staticInitializer);
+ }
return visitOrder;
}
-
-
+
+
@Override
public void visit(Code obj) {
fieldsReadInThisConstructor = new HashSet<XField>();
super.visit(obj);
staticFieldsRead.put(getXMethod(), fieldsReadInThisConstructor);
requires.remove(getDottedClassName());
- if (getDottedClassName().equals("java.lang.System")) {
+ if ("java.lang.System".equals(getDottedClassName())) {
requires.add("java.io.FileInputStream");
requires.add("java.io.FileOutputStream");
requires.add("java.io.BufferedInputStream");
@@ -115,9 +118,9 @@ public class InitializationChain extends BytecodeScanningDetector {
@Override
public void visitAfter(JavaClass obj) {
-
+
staticFieldsRead.clear();
-
+
staticFieldsReadInAnyConstructor.clear();
fieldsReadInThisConstructor.clear();
@@ -131,7 +134,7 @@ public class InitializationChain extends BytecodeScanningDetector {
public void sawOpcode(int seen) {
InvocationInfo prev = lastInvocation;
lastInvocation = null;
- if (getMethodName().equals("<init>")) {
+ if ("<init>".equals(getMethodName())) {
if (seen == GETSTATIC && getClassConstantOperand().equals(getClassName())) {
staticFieldsReadInAnyConstructor.add(getXFieldOperand());
fieldsReadInThisConstructor.add(getXFieldOperand());
@@ -139,42 +142,45 @@ public class InitializationChain extends BytecodeScanningDetector {
return;
}
- if (seen == INVOKESPECIAL && getNameConstantOperand().equals("<init>") && getClassConstantOperand().equals(getClassName())) {
-
+ if (seen == INVOKESPECIAL && "<init>".equals(getNameConstantOperand()) && getClassConstantOperand().equals(getClassName())) {
+
XMethod m = getXMethodOperand();
Set<XField> read = staticFieldsRead.get(m);
if (constructorsInvokedInStaticInitializer.add(m) && read != null && !read.isEmpty()) {
lastInvocation = new InvocationInfo(m, getPC());
invocationInfo.add(lastInvocation);
-
- }
-
+
+ }
+
}
if (seen == PUTSTATIC && getClassConstantOperand().equals(getClassName())) {
- XField f = getXFieldOperand();
- if (prev != null)
- prev.field = f;
- if (staticFieldsReadInAnyConstructor.contains(f) && !warningGiven.contains(f)) {
- for(InvocationInfo i : invocationInfo) {
- Set<XField> fields = staticFieldsRead.get(i.constructor);
- if (fields != null && fields.contains(f)) {
- warningGiven.add(f);
- BugInstance bug = new BugInstance(this, "SI_INSTANCE_BEFORE_FINALS_ASSIGNED", NORMAL_PRIORITY).addClassAndMethod(this);
- if (i.field != null) {
- bug.addField(i.field).describe(FieldAnnotation.STORED_ROLE);
- }
- bug.addMethod(i.constructor).describe(MethodAnnotation.METHOD_CONSTRUCTOR);
- bug.addReferencedField(this).describe(FieldAnnotation.VALUE_OF_ROLE).addSourceLine(this, i.pc);
- bugReporter.reportBug(bug);
- break;
-
- }
- }
- }
-
- } else if (seen == PUTSTATIC || seen == GETSTATIC || seen == INVOKESTATIC || seen == NEW)
- if (getPC() + 6 < codeBytes.length)
+ XField f = getXFieldOperand();
+ if (prev != null) {
+ prev.field = f;
+ }
+ if (staticFieldsReadInAnyConstructor.contains(f) && !warningGiven.contains(f)) {
+ for(InvocationInfo i : invocationInfo) {
+ Set<XField> fields = staticFieldsRead.get(i.constructor);
+ if (fields != null && fields.contains(f)) {
+ warningGiven.add(f);
+ BugInstance bug = new BugInstance(this, "SI_INSTANCE_BEFORE_FINALS_ASSIGNED", NORMAL_PRIORITY).addClassAndMethod(this);
+ if (i.field != null) {
+ bug.addField(i.field).describe(FieldAnnotation.STORED_ROLE);
+ }
+ bug.addMethod(i.constructor).describe(MethodAnnotation.METHOD_CONSTRUCTOR);
+ bug.addReferencedField(this).describe(FieldAnnotation.VALUE_OF_ROLE).addSourceLine(this, i.pc);
+ bugReporter.reportBug(bug);
+ break;
+
+ }
+ }
+ }
+
+ } else if (seen == PUTSTATIC || seen == GETSTATIC || seen == INVOKESTATIC || seen == NEW) {
+ if (getPC() + 6 < codeBytes.length) {
requires.add(getDottedClassConstantOperand());
+ }
+ }
}
public void compute() {
@@ -184,13 +190,15 @@ public class InitializationChain extends BytecodeScanningDetector {
Set<String> needs = classRequires.get(c);
needs.retainAll(allClasses);
Set<String> extra = new TreeSet<String>();
- for (String need : needs)
+ for (String need : needs) {
extra.addAll(classRequires.get(need));
+ }
needs.addAll(extra);
needs.retainAll(allClasses);
classRequires.put(c, needs);
- if (needs.isEmpty())
+ if (needs.isEmpty()) {
emptyClasses.add(c);
+ }
}
for (String c : emptyClasses) {
classRequires.remove(c);
@@ -200,8 +208,9 @@ public class InitializationChain extends BytecodeScanningDetector {
@Override
public void report() {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Finishing computation");
+ }
compute();
compute();
compute();
@@ -210,18 +219,21 @@ public class InitializationChain extends BytecodeScanningDetector {
compute();
compute();
compute();
- Set<String> allClasses = classRequires.keySet();
- for (String c : allClasses) {
- if (DEBUG)
+ for (Entry<String, Set<String>> entry : classRequires.entrySet()) {
+ String c = entry.getKey();
+ if (DEBUG) {
System.out.println("Class " + c + " requires:");
- for (String needs : (classRequires.get(c))) {
- if (DEBUG)
+ }
+ for (String needs : entry.getValue()) {
+ if (DEBUG) {
System.out.println(" " + needs);
+ }
Set<String> s = classRequires.get(needs);
- if (s != null && s.contains(c) && c.compareTo(needs) < 0)
+ if (s != null && s.contains(c) && c.compareTo(needs) < 0) {
bugReporter.reportBug(new BugInstance(this, "IC_INIT_CIRCULARITY", NORMAL_PRIORITY).addClass(c).addClass(
needs));
+ }
}
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/InitializeNonnullFieldsInConstructor.java b/src/java/edu/umd/cs/findbugs/detect/InitializeNonnullFieldsInConstructor.java
index 6c720bf..1958f18 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InitializeNonnullFieldsInConstructor.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InitializeNonnullFieldsInConstructor.java
@@ -69,20 +69,18 @@ public class InitializeNonnullFieldsInConstructor extends OpcodeStackDetector {
super.visit(obj);
XField f = XFactory.createXField(this);
if (checkForInitialization(f) && !f.isSynthetic()) {
- if (f.isStatic())
+ if (f.isStatic()) {
nonnullStaticFields.add(f);
- else
+ } else {
nonnullFields.add(f);
+ }
}
}
- /**
- * @param f
- * @return
- */
public boolean checkForInitialization(XField f) {
- if (!f.isReferenceType() || f.isFinal())
+ if (!f.isReferenceType() || f.isFinal()) {
return false;
+ }
NullnessAnnotation annotation = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase()
.getResolvedAnnotation(f, false);
boolean isNonnull = annotation == NullnessAnnotation.NONNULL;
@@ -91,27 +89,31 @@ public class InitializeNonnullFieldsInConstructor extends OpcodeStackDetector {
@Override
public void visit(Code code) {
- boolean interesting = getMethodName().equals("<init>") || getMethodName().equals("<clinit>");
- if (!interesting)
+ boolean interesting = "<init>".equals(getMethodName()) || "<clinit>".equals(getMethodName());
+ if (!interesting) {
return;
+ }
secondaryConstructor = false;
HashSet<XField> needToInitialize = getMethod().isStatic() ? nonnullStaticFields : nonnullFields;
- if (needToInitialize.isEmpty())
+ if (needToInitialize.isEmpty()) {
return;
+ }
// initialize any variables we want to initialize for the method
super.visit(code); // make callbacks to sawOpcode for all opcodes
if (!secondaryConstructor && !initializedFields.containsAll(needToInitialize)) {
int priority = Priorities.NORMAL_PRIORITY;
- if (needToInitialize.size() - initializedFields.size() == 1 && needToInitialize.size() > 1)
+ if (needToInitialize.size() - initializedFields.size() == 1 && needToInitialize.size() > 1) {
priority = Priorities.HIGH_PRIORITY;
+ }
for (XField f : needToInitialize) {
- if (initializedFields.contains(f))
+ if (initializedFields.contains(f)) {
continue;
+ }
BugInstance b = new BugInstance(this, "NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", priority)
- .addClassAndMethod(this).addField(f);
+ .addClassAndMethod(this).addField(f);
bugReporter.reportBug(b);
}
@@ -125,12 +127,13 @@ public class InitializeNonnullFieldsInConstructor extends OpcodeStackDetector {
@Override
public void sawOpcode(int seen) {
- if (secondaryConstructor)
+ if (secondaryConstructor) {
return;
+ }
switch (seen) {
case Constants.INVOKESPECIAL:
- if (!getMethod().isStatic() && getNameConstantOperand().equals("<init>") && isSelfOperation()) {
+ if (!getMethod().isStatic() && "<init>".equals(getNameConstantOperand()) && isSelfOperation()) {
OpcodeStack.Item invokedOn = stack.getItemMethodInvokedOn(this);
if (invokedOn.isInitialParameter() && invokedOn.getRegisterNumber() == 0) {
secondaryConstructor = true;
@@ -139,28 +142,34 @@ public class InitializeNonnullFieldsInConstructor extends OpcodeStackDetector {
}
break;
case Constants.PUTFIELD:
- if (getMethod().isStatic())
+ if (getMethod().isStatic()) {
return;
+ }
OpcodeStack.Item left = stack.getStackItem(1);
if (left.isInitialParameter() && left.getRegisterNumber() == 0 && isSelfOperation()) {
XField f = getXFieldOperand();
- if (f == null)
+ if (f == null) {
break;
- if (checkForInitialization(f))
+ }
+ if (checkForInitialization(f)) {
initializedFields.add(f);
+ }
}
break;
case Constants.PUTSTATIC:
- if (!getMethod().isStatic())
+ if (!getMethod().isStatic()) {
break;
+ }
if (isSelfOperation()) {
XField f = getXFieldOperand();
- if (f == null)
+ if (f == null) {
break;
+ }
- if (checkForInitialization(f))
+ if (checkForInitialization(f)) {
initializedFields.add(f);
+ }
}
break;
default:
diff --git a/src/java/edu/umd/cs/findbugs/detect/InstanceFieldLoadStreamFactory.java b/src/java/edu/umd/cs/findbugs/detect/InstanceFieldLoadStreamFactory.java
index cd4a040..b6bf88c 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InstanceFieldLoadStreamFactory.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InstanceFieldLoadStreamFactory.java
@@ -30,11 +30,11 @@ import edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback;
/**
* StreamFactory for stream objects loaded from instance fields.
- *
+ *
* @author David Hovemeyer
*/
public class InstanceFieldLoadStreamFactory implements StreamFactory {
- private String streamBaseClass;
+ private final String streamBaseClass;
private String bugPatternType;
@@ -42,7 +42,7 @@ public class InstanceFieldLoadStreamFactory implements StreamFactory {
* Constructor. By default, Streams created by this factory will not be
* marked as interesting. The setBugPatternType() method should be called to
* make the factory produce interesting streams.
- *
+ *
* @param streamBaseClass
* the base class of the streams produced by the factory
*/
@@ -53,7 +53,7 @@ public class InstanceFieldLoadStreamFactory implements StreamFactory {
/**
* Set the bug pattern type reported for unclosed streams loaded from this
* field. This makes the created streams "interesting".
- *
+ *
* @param bugPatternType
* the bug pattern type
*/
@@ -62,25 +62,30 @@ public class InstanceFieldLoadStreamFactory implements StreamFactory {
return this;
}
+ @Override
public Stream createStream(Location location, ObjectType type, ConstantPoolGen cpg,
RepositoryLookupFailureCallback lookupFailureCallback) {
Instruction ins = location.getHandle().getInstruction();
- if (ins.getOpcode() != Constants.GETFIELD)
+ if (ins.getOpcode() != Constants.GETFIELD) {
return null;
+ }
String fieldClass = type.getClassName();
try {
- if (fieldClass.startsWith("["))
+ if (fieldClass.startsWith("[")) {
return null;
- if (!Hierarchy.isSubtype(fieldClass, streamBaseClass))
+ }
+ if (!Hierarchy.isSubtype(fieldClass, streamBaseClass)) {
return null;
+ }
Stream stream = new Stream(location, fieldClass, streamBaseClass);
stream.setIsOpenOnCreation(true);
stream.setOpenLocation(location);
- if (bugPatternType != null)
+ if (bugPatternType != null) {
stream.setInteresting(bugPatternType);
+ }
// System.out.println("Instance field stream at " + location);
return stream;
@@ -91,4 +96,3 @@ public class InstanceFieldLoadStreamFactory implements StreamFactory {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/InstantiateStaticClass.java b/src/java/edu/umd/cs/findbugs/detect/InstantiateStaticClass.java
index 0e2e78b..6c1d6fb 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InstantiateStaticClass.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InstantiateStaticClass.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
public class InstantiateStaticClass extends BytecodeScanningDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public InstantiateStaticClass(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -40,59 +40,71 @@ public class InstantiateStaticClass extends BytecodeScanningDetector {
@Override
public void sawOpcode(int seen) {
- if ((seen == INVOKESPECIAL) && getNameConstantOperand().equals("<init>") && getSigConstantOperand().equals("()V")) {
- XClass xClass = getXClassOperand();
- if (xClass == null)
- return;
- String clsName = getClassConstantOperand();
- if (clsName.equals("java/lang/Object"))
- return;
-
- // ignore superclass synthesized ctor calls
- if (getMethodName().equals("<init>") && (getPC() == 1))
- return;
-
- // ignore the typesafe enumerated constant pattern
- if (getMethodName().equals("<clinit>") && (getClassName().equals(clsName)))
- return;
-
- if (isStaticOnlyClass(xClass))
- bugReporter.reportBug(new BugInstance(this, "ISC_INSTANTIATE_STATIC_CLASS", LOW_PRIORITY).addClassAndMethod(
- this).addSourceLine(this));
+ if ((seen == INVOKESPECIAL) && "<init>".equals(getNameConstantOperand()) && "()V".equals(getSigConstantOperand())) {
+ XClass xClass = getXClassOperand();
+ if (xClass == null) {
+ return;
}
-
+ String clsName = getClassConstantOperand();
+ if ("java/lang/Object".equals(clsName)) {
+ return;
+ }
+
+ // ignore superclass synthesized ctor calls
+ if ("<init>".equals(getMethodName()) && (getPC() == 1)) {
+ return;
+ }
+
+ // ignore the typesafe enumerated constant pattern
+ if ("<clinit>".equals(getMethodName()) && (getClassName().equals(clsName))) {
+ return;
+ }
+
+ if (isStaticOnlyClass(xClass)) {
+ bugReporter.reportBug(new BugInstance(this, "ISC_INSTANTIATE_STATIC_CLASS", LOW_PRIORITY).addClassAndMethod(
+ this).addSourceLine(this));
+ }
+ }
+
}
private boolean isStaticOnlyClass(XClass xClass) {
- if (xClass.getInterfaceDescriptorList().length > 0)
+ if (xClass.getInterfaceDescriptorList().length > 0) {
return false;
+ }
ClassDescriptor superclassDescriptor = xClass.getSuperclassDescriptor();
- if (superclassDescriptor == null)
+ if (superclassDescriptor == null) {
return false;
+ }
String superClassName = superclassDescriptor.getClassName();
- if (!superClassName.equals("java/lang/Object"))
+ if (!"java/lang/Object".equals(superClassName)) {
return false;
+ }
int staticCount = 0;
List<? extends XMethod> methods = xClass.getXMethods();
for (XMethod m : methods) {
- if (m.isStatic()) {
+ // !m.isSynthetic(): bug #1282: No warning should be generated if only static methods are synthetic
+ if (m.isStatic() && !m.isSynthetic()) {
staticCount++;
- } else if (!m.getName().equals("<init>") || !m.getSignature().equals("()V"))
+ } else if (!"<init>".equals(m.getName()) || !"()V".equals(m.getSignature())) {
return false;
+ }
}
List<? extends XField> fields = xClass.getXFields();
for (XField f : fields) {
if (f.isStatic()) {
staticCount++;
- } else if (!f.isPrivate())
+ } else if (!f.isPrivate()) {
return false;
+ }
}
- if (staticCount == 0)
+ if (staticCount == 0) {
return false;
+ }
return true;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/IntCast2LongAsInstant.java b/src/java/edu/umd/cs/findbugs/detect/IntCast2LongAsInstant.java
index 0d6654e..c5ab431 100644
--- a/src/java/edu/umd/cs/findbugs/detect/IntCast2LongAsInstant.java
+++ b/src/java/edu/umd/cs/findbugs/detect/IntCast2LongAsInstant.java
@@ -81,7 +81,7 @@ public class IntCast2LongAsInstant extends OpcodeStackDetector {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector#report()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/detect/InvalidJUnitTest.java b/src/java/edu/umd/cs/findbugs/detect/InvalidJUnitTest.java
index 398d9f3..fad477d 100644
--- a/src/java/edu/umd/cs/findbugs/detect/InvalidJUnitTest.java
+++ b/src/java/edu/umd/cs/findbugs/detect/InvalidJUnitTest.java
@@ -43,7 +43,7 @@ public class InvalidJUnitTest extends BytecodeScanningDetector {
private static final int SEEN_ALOAD_0 = 1;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private int state;
@@ -55,16 +55,18 @@ public class InvalidJUnitTest extends BytecodeScanningDetector {
@Override
public void visitClassContext(ClassContext classContext) {
- if (!enabled())
+ if (!enabled()) {
return;
+ }
JavaClass jClass = classContext.getJavaClass();
XClass xClass = classContext.getXClass();
try {
- if (!isJunit3TestCase(xClass))
+ if (!isJunit3TestCase(xClass)) {
return;
+ }
if ((jClass.getAccessFlags() & ACC_ABSTRACT) == 0) {
if (!hasTestMethods(jClass)) {
bugReporter.reportBug(new BugInstance(this, "IJU_NO_TESTS", LOW_PRIORITY).addClass(jClass));
@@ -80,18 +82,22 @@ public class InvalidJUnitTest extends BytecodeScanningDetector {
private boolean isJunit3TestCase(XClass jClass) throws ClassNotFoundException {
ClassDescriptor sDesc = jClass.getSuperclassDescriptor();
- if (sDesc == null)
+ if (sDesc == null) {
return false;
+ }
String sName = sDesc.getClassName();
- if (sName.equals("junit/framework/TestCase"))
+ if (sName.equals("junit/framework/TestCase")) {
return true;
- if (sName.equals("java/lang/Object"))
+ }
+ if (sName.equals("java/lang/Object")) {
return false;
+ }
try {
XClass sClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, sDesc);
- if (sClass == null)
+ if (sClass == null) {
return false;
+ }
return isJunit3TestCase(sClass);
} catch (CheckedAnalysisException e) {
return false;
@@ -103,18 +109,22 @@ public class InvalidJUnitTest extends BytecodeScanningDetector {
boolean foundTest = false;
Method[] methods = jClass.getMethods();
for (Method m : methods) {
- if (m.isPublic() && m.getName().startsWith("test") && m.getSignature().equals("()V"))
+ if (m.isPublic() && m.getName().startsWith("test") && m.getSignature().equals("()V")) {
return true;
- if (m.getName().startsWith("runTest") && m.getSignature().endsWith("()V"))
+ }
+ if (m.getName().startsWith("runTest") && m.getSignature().endsWith("()V")) {
return true;
+ }
}
- if (hasSuite(methods))
+ if (hasSuite(methods)) {
return true;
+ }
try {
JavaClass sClass = jClass.getSuperClass();
- if (sClass != null)
+ if (sClass != null) {
return hasTestMethods(sClass);
+ }
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
@@ -126,10 +136,11 @@ public class InvalidJUnitTest extends BytecodeScanningDetector {
private boolean hasSuite(Method[] methods) {
for (Method m : methods) {
if (m.getName().equals("suite") && m.isPublic() && m.isStatic()
- // && m.getReturnType().equals(junit.framework.Test.class)
- // && m.getArgumentTypes().length == 0
- && m.getSignature().equals("()Ljunit/framework/Test;"))
+ // && m.getReturnType().equals(junit.framework.Test.class)
+ // && m.getArgumentTypes().length == 0
+ && m.getSignature().equals("()Ljunit/framework/Test;")) {
return true;
+ }
}
return false;
}
@@ -138,7 +149,7 @@ public class InvalidJUnitTest extends BytecodeScanningDetector {
* Check whether or not this detector should be enabled. The detector is
* disabled if the TestCase class cannot be found (meaning we don't have
* junit.jar on the aux classpath).
- *
+ *
* @return true if it should be enabled, false if not
*/
private boolean enabled() {
@@ -147,14 +158,16 @@ public class InvalidJUnitTest extends BytecodeScanningDetector {
@Override
public void visit(Method obj) {
- if (getMethodName().equals("suite") && !obj.isStatic())
+ if (getMethodName().equals("suite") && !obj.isStatic()) {
bugReporter.reportBug(new BugInstance(this, "IJU_SUITE_NOT_STATIC", NORMAL_PRIORITY).addClassAndMethod(this));
+ }
if (getMethodName().equals("suite") && obj.getSignature().startsWith("()") && obj.isStatic()) {
if ((!obj.getSignature().equals("()Ljunit/framework/Test;") && !obj.getSignature().equals(
"()Ljunit/framework/TestSuite;"))
- || !obj.isPublic())
+ || !obj.isPublic()) {
bugReporter.reportBug(new BugInstance(this, "IJU_BAD_SUITE_METHOD", NORMAL_PRIORITY).addClassAndMethod(this));
+ }
}
}
@@ -167,20 +180,23 @@ public class InvalidJUnitTest extends BytecodeScanningDetector {
&& !getMethod().isPrivate() && getMethodSig().equals("()V")) {
sawSuperCall = false;
super.visit(obj);
- if (sawSuperCall)
+ if (sawSuperCall) {
return;
+ }
JavaClass we = Lookup.findSuperImplementor(getThisClass(), getMethodName(), "()V", bugReporter);
if (we != null && !we.getClassName().equals("junit.framework.TestCase")) {
// OK, got a bug
int offset = 0;
- if (getMethodName().equals("tearDown"))
+ if (getMethodName().equals("tearDown")) {
offset = obj.getCode().length - 1;
+ }
Method superMethod = Lookup.findImplementation(we, getMethodName(), "()V");
Code superCode = superMethod.getCode();
- if (superCode != null && superCode.getCode().length > 3)
+ if (superCode != null && superCode.getCode().length > 3) {
bugReporter.reportBug(new BugInstance(this, getMethodName().equals("setUp") ? "IJU_SETUP_NO_SUPER"
: "IJU_TEARDOWN_NO_SUPER", NORMAL_PRIORITY).addClassAndMethod(this).addMethod(we, superMethod)
.describe(MethodAnnotation.METHOD_OVERRIDDEN).addSourceLine(this, offset));
+ }
}
}
}
@@ -189,14 +205,16 @@ public class InvalidJUnitTest extends BytecodeScanningDetector {
public void sawOpcode(int seen) {
switch (state) {
case SEEN_NOTHING:
- if (seen == ALOAD_0)
+ if (seen == ALOAD_0) {
state = SEEN_ALOAD_0;
+ }
break;
case SEEN_ALOAD_0:
if ((seen == INVOKESPECIAL) && (getNameConstantOperand().equals(getMethodName()))
- && (getSigConstantOperand().equals("()V")))
+ && (getSigConstantOperand().equals("()V"))) {
sawSuperCall = true;
+ }
state = SEEN_NOTHING;
break;
default:
@@ -205,4 +223,3 @@ public class InvalidJUnitTest extends BytecodeScanningDetector {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/IteratorIdioms.java b/src/java/edu/umd/cs/findbugs/detect/IteratorIdioms.java
index 60748d2..d02cf3f 100644
--- a/src/java/edu/umd/cs/findbugs/detect/IteratorIdioms.java
+++ b/src/java/edu/umd/cs/findbugs/detect/IteratorIdioms.java
@@ -63,7 +63,7 @@ public class IteratorIdioms extends BytecodeScanningDetector implements Stateles
@Override
public void visit(Method method) {
- if(method.isPublic() && method.getName().equals("next") && method.getArgumentTypes().length == 0){
+ if(method.isPublic() && "next".equals(method.getName()) && method.getArgumentTypes().length == 0){
shouldVisitCode = true;
super.visit(method);
} else {
@@ -88,7 +88,7 @@ public class IteratorIdioms extends BytecodeScanningDetector implements Stateles
@Override
public void sawOpcode(int seen) {
- if (seen == NEW && getClassConstantOperand().equals("java/util/NoSuchElementException")) {
+ if (seen == NEW && "java/util/NoSuchElementException".equals(getClassConstantOperand())) {
sawNoSuchElement = true;
} else if (seen == INVOKESPECIAL || seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) {
sawCall = true;
diff --git a/src/java/edu/umd/cs/findbugs/detect/LazyInit.java b/src/java/edu/umd/cs/findbugs/detect/LazyInit.java
index ea23779..6c6a787 100644
--- a/src/java/edu/umd/cs/findbugs/detect/LazyInit.java
+++ b/src/java/edu/umd/cs/findbugs/detect/LazyInit.java
@@ -80,7 +80,7 @@ import edu.umd.cs.findbugs.classfile.Global;
*/
public final class LazyInit extends ByteCodePatternDetector implements StatelessDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private static final boolean DEBUG = SystemProperties.getBoolean("lazyinit.debug");
@@ -91,8 +91,8 @@ public final class LazyInit extends ByteCodePatternDetector implements Stateless
static {
pattern.add(new Load("f", "val").label("start")).add(new IfNull("val").label("test"))
- .add(new Wild(1, 1).label("createObject").dominatedBy("test"))
- .add(new Store("f", pattern.dummyVariable()).label("end").dominatedBy("createObject"));
+ .add(new Wild(1, 1).label("createObject").dominatedBy("test"))
+ .add(new Store("f", pattern.dummyVariable()).label("end").dominatedBy("createObject"));
}
public LazyInit(BugReporter bugReporter) {
@@ -122,27 +122,32 @@ public final class LazyInit extends ByteCodePatternDetector implements Stateless
@Override
public boolean prescreen(Method method, ClassContext classContext) {
- if (method.getName().equals("<clinit>"))
+ if ("<clinit>".equals(method.getName())) {
return false;
-
+ }
+
Code code = method.getCode();
- if (code.getCode().length > 5000)
+ if (code.getCode().length > 5000) {
return false;
-
+ }
+
BitSet bytecodeSet = classContext.getBytecodeSet(method);
- if (bytecodeSet == null)
+ if (bytecodeSet == null) {
return false;
+ }
// The pattern requires a get/put pair accessing the same field.
boolean hasGetStatic = bytecodeSet.get(Constants.GETSTATIC);
boolean hasPutStatic = bytecodeSet.get(Constants.PUTSTATIC);
- if (!hasGetStatic || !hasPutStatic)
+ if (!hasGetStatic || !hasPutStatic) {
return false;
+ }
// If the method is synchronized, then we'll assume that
// things are properly synchronized
- if (method.isSynchronized())
+ if (method.isSynchronized()) {
return false;
+ }
reported.clear();
return true;
@@ -150,222 +155,241 @@ public final class LazyInit extends ByteCodePatternDetector implements Stateless
@Override
public void reportMatch(ClassContext classContext, Method method, ByteCodePatternMatch match) throws CFGBuilderException,
- DataflowAnalysisException {
+ DataflowAnalysisException {
JavaClass javaClass = classContext.getJavaClass();
MethodGen methodGen = classContext.getMethodGen(method);
CFG cfg = classContext.getCFG(method);
- // Get the variable referenced in the pattern instance.
- BindingSet bindingSet = match.getBindingSet();
- Binding binding = bindingSet.lookup("f");
+ // Get the variable referenced in the pattern instance.
+ BindingSet bindingSet = match.getBindingSet();
+ Binding binding = bindingSet.lookup("f");
- // Look up the field as an XField.
- // If it is volatile, then the instance is not a bug.
- FieldVariable field = (FieldVariable) binding.getVariable();
- XField xfield = Hierarchy.findXField(field.getClassName(), field.getFieldName(), field.getFieldSig(),
- field.isStatic());
- if (!xfield.isResolved())
- return;
+ // Look up the field as an XField.
+ // If it is volatile, then the instance is not a bug.
+ FieldVariable field = (FieldVariable) binding.getVariable();
+ XField xfield = Hierarchy.findXField(field.getClassName(), field.getFieldName(), field.getFieldSig(),
+ field.isStatic());
+ if (!xfield.isResolved()) {
+ return;
+ }
- // XXX: for now, ignore lazy initialization of instance fields
- if (!xfield.isStatic())
- return;
+ // XXX: for now, ignore lazy initialization of instance fields
+ if (!xfield.isStatic()) {
+ return;
+ }
- // Definitely ignore synthetic class$ fields
- if (xfield.getName().startsWith("class$") || xfield.getName().startsWith("array$")) {
- if (DEBUG)
- System.out.println("Ignoring field " + xfield.getName());
- return;
+ // Definitely ignore synthetic class$ fields
+ if (xfield.getName().startsWith("class$") || xfield.getName().startsWith("array$")) {
+ if (DEBUG) {
+ System.out.println("Ignoring field " + xfield.getName());
}
+ return;
+ }
- // Ignore non-reference fields
- String signature = xfield.getSignature();
- if (!signature.startsWith("[") && !signature.startsWith("L")) {
- if (DEBUG)
- System.out.println("Ignoring non-reference field " + xfield.getName());
- return;
+ // Ignore non-reference fields
+ String signature = xfield.getSignature();
+ if (!signature.startsWith("[") && !signature.startsWith("L")) {
+ if (DEBUG) {
+ System.out.println("Ignoring non-reference field " + xfield.getName());
}
+ return;
+ }
- // Strings are (mostly) safe to pass by data race in 1.5
- if (signature.equals("Ljava/lang/String;"))
- return;
+ // Strings are (mostly) safe to pass by data race in 1.5
+ if ("Ljava/lang/String;".equals(signature)) {
+ return;
+ }
- // GUI types should not be accessed from multiple threads
+ // GUI types should not be accessed from multiple threads
- if (signature.charAt(0) == 'L') {
- ClassDescriptor fieldType = DescriptorFactory.createClassDescriptorFromFieldSignature(signature);
+ if (signature.charAt(0) == 'L') {
+ ClassDescriptor fieldType = DescriptorFactory.createClassDescriptorFromFieldSignature(signature);
- while (fieldType != null) {
- XClass fieldClass;
- try {
- fieldClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, fieldType);
- } catch (CheckedAnalysisException e) {
- break;
- }
+ while (fieldType != null) {
+ XClass fieldClass;
+ try {
+ fieldClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, fieldType);
+ } catch (CheckedAnalysisException e) {
+ break;
+ }
- String name = fieldClass.getClassDescriptor().getClassName();
- if (name.startsWith("java/awt") || name.startsWith("javax/swing"))
- return;
- if (name.equals("java/lang/Object"))
- break;
- fieldType = fieldClass.getSuperclassDescriptor();
+ String name = fieldClass.getClassDescriptor().getClassName();
+ if (name.startsWith("java/awt") || name.startsWith("javax/swing")) {
+ return;
+ }
+ if ("java/lang/Object".equals(name)) {
+ break;
}
+ fieldType = fieldClass.getSuperclassDescriptor();
}
+ }
- // Get locations matching the beginning of the object creation,
- // and the final field store.
- PatternElementMatch createBegin = match.getFirstLabeledMatch("createObject");
- PatternElementMatch store = match.getFirstLabeledMatch("end");
- PatternElementMatch test = match.getFirstLabeledMatch("test");
- InstructionHandle testInstructionHandle = test.getMatchedInstructionInstructionHandle();
- if (reported.get(testInstructionHandle.getPosition()))
- return;
-
- // Get all blocks
- //
- // (1) dominated by the wildcard instruction matching
- // the beginning of the instructions creating the object, and
- // (2) postdominated by the field store
- //
- // Exception edges are not considered in computing
- // dominators/postdominators.
- // We will consider this to be all of the code that creates
- // the object.
- DominatorsAnalysis domAnalysis = classContext.getNonExceptionDominatorsAnalysis(method);
- PostDominatorsAnalysis postDomAnalysis = classContext.getNonExceptionPostDominatorsAnalysis(method);
- BitSet extent = domAnalysis.getAllDominatedBy(createBegin.getBasicBlock());
- BitSet postDom = postDomAnalysis.getAllDominatedBy(store.getBasicBlock());
- // System.out.println("Extent: " + extent);
- if (DEBUG) {
- System.out.println("test dominates: " + extent);
- System.out.println("Field store postdominates " + postDom);
- }
- extent.and(postDom);
- if (DEBUG) {
- System.out.println("extent: " + extent);
- }
- // Check all instructions in the object creation extent
- //
- // (1) to determine the common lock set, and
- // (2) to check for NEW and Invoke instructions that might create an
- // object
- //
- // We ignore matches where a lock is held consistently,
- // or if the extent does not appear to create a new object.
- LockDataflow lockDataflow = classContext.getLockDataflow(method);
- LockSet lockSet = null;
- boolean sawNEW = false, sawINVOKE = false;
- for (BasicBlock block : cfg.getBlocks(extent)) {
- for (Iterator<InstructionHandle> j = block.instructionIterator(); j.hasNext();) {
- InstructionHandle handle = j.next();
- if (handle.equals(store.getMatchedInstructionInstructionHandle()))
- break;
- Location location = new Location(handle, block);
+ // Get locations matching the beginning of the object creation,
+ // and the final field store.
+ PatternElementMatch createBegin = match.getFirstLabeledMatch("createObject");
+ PatternElementMatch store = match.getFirstLabeledMatch("end");
+ PatternElementMatch test = match.getFirstLabeledMatch("test");
+ InstructionHandle testInstructionHandle = test.getMatchedInstructionInstructionHandle();
+ if (reported.get(testInstructionHandle.getPosition())) {
+ return;
+ }
- // Keep track of whether we saw any instructions
- // that might actually have created a new object.
- Instruction ins = handle.getInstruction();
- if (DEBUG)
- System.out.println(location);
- if (ins instanceof AllocationInstruction)
+ // Get all blocks
+ //
+ // (1) dominated by the wildcard instruction matching
+ // the beginning of the instructions creating the object, and
+ // (2) postdominated by the field store
+ //
+ // Exception edges are not considered in computing
+ // dominators/postdominators.
+ // We will consider this to be all of the code that creates
+ // the object.
+ DominatorsAnalysis domAnalysis = classContext.getNonExceptionDominatorsAnalysis(method);
+ PostDominatorsAnalysis postDomAnalysis = classContext.getNonExceptionPostDominatorsAnalysis(method);
+ BitSet extent = domAnalysis.getAllDominatedBy(createBegin.getBasicBlock());
+ BitSet postDom = postDomAnalysis.getAllDominatedBy(store.getBasicBlock());
+ // System.out.println("Extent: " + extent);
+ if (DEBUG) {
+ System.out.println("test dominates: " + extent);
+ System.out.println("Field store postdominates " + postDom);
+ }
+ extent.and(postDom);
+ if (DEBUG) {
+ System.out.println("extent: " + extent);
+ }
+ // Check all instructions in the object creation extent
+ //
+ // (1) to determine the common lock set, and
+ // (2) to check for NEW and Invoke instructions that might create an
+ // object
+ //
+ // We ignore matches where a lock is held consistently,
+ // or if the extent does not appear to create a new object.
+ LockDataflow lockDataflow = classContext.getLockDataflow(method);
+ LockSet lockSet = null;
+ boolean sawNEW = false, sawINVOKE = false;
+ for (BasicBlock block : cfg.getBlocks(extent)) {
+ for (Iterator<InstructionHandle> j = block.instructionIterator(); j.hasNext();) {
+ InstructionHandle handle = j.next();
+ if (handle.equals(store.getMatchedInstructionInstructionHandle())) {
+ break;
+ }
+ Location location = new Location(handle, block);
+
+ // Keep track of whether we saw any instructions
+ // that might actually have created a new object.
+ Instruction ins = handle.getInstruction();
+ if (DEBUG) {
+ System.out.println(location);
+ }
+ if (ins instanceof AllocationInstruction) {
+ sawNEW = true;
+ } else if (ins instanceof InvokeInstruction) {
+ if (ins instanceof INVOKESTATIC
+ && ((INVOKESTATIC) ins).getMethodName(classContext.getConstantPoolGen()).startsWith("new")) {
sawNEW = true;
- else if (ins instanceof InvokeInstruction) {
- if (ins instanceof INVOKESTATIC
- && ((INVOKESTATIC) ins).getMethodName(classContext.getConstantPoolGen()).startsWith("new"))
- sawNEW = true;
- sawINVOKE = true;
}
+ sawINVOKE = true;
+ }
- // Compute lock set intersection for all matched
- // instructions.
- LockSet insLockSet = lockDataflow.getFactAtLocation(location);
- if (lockSet == null) {
- lockSet = new LockSet();
- lockSet.copyFrom(insLockSet);
- } else
- lockSet.intersectWith(insLockSet);
+ // Compute lock set intersection for all matched
+ // instructions.
+ LockSet insLockSet = lockDataflow.getFactAtLocation(location);
+ if (lockSet == null) {
+ lockSet = new LockSet();
+ lockSet.copyFrom(insLockSet);
+ } else {
+ lockSet.intersectWith(insLockSet);
}
}
+ }
+
+ if (!(sawNEW || sawINVOKE)) {
+ return;
+ }
+ if (lockSet == null) {
+ throw new IllegalStateException("lock set is null");
+ }
+ if (!lockSet.isEmpty()) {
+ return;
+ }
+
+ boolean sawGetStaticAfterPutStatic = false;
+ check: if (signature.startsWith("[") || signature.startsWith("L")) {
+
+ BitSet postStore = domAnalysis.getAllDominatedBy(store.getBasicBlock());
+ for (BasicBlock block : cfg.getBlocks(postStore)) {
+ for (Iterator<InstructionHandle> j = block.instructionIterator(); j.hasNext();) {
+ InstructionHandle handle = j.next();
+
+ InstructionHandle nextHandle = handle.getNext();
+ Instruction ins = handle.getInstruction();
- if (!(sawNEW || sawINVOKE))
- return;
- if (lockSet == null)
- throw new IllegalStateException("lock set is null");
- if (!lockSet.isEmpty())
- return;
-
- boolean sawGetStaticAfterPutStatic = false;
- check: if (signature.startsWith("[") || signature.startsWith("L")) {
-
- BitSet postStore = domAnalysis.getAllDominatedBy(store.getBasicBlock());
- for (BasicBlock block : cfg.getBlocks(postStore)) {
- for (Iterator<InstructionHandle> j = block.instructionIterator(); j.hasNext();) {
- InstructionHandle handle = j.next();
-
- InstructionHandle nextHandle = handle.getNext();
- Instruction ins = handle.getInstruction();
-
- if (ins instanceof GETSTATIC && potentialInitialization(nextHandle)) {
- XField field2 = XFactory.createXField((FieldInstruction) ins, methodGen.getConstantPool());
- if (xfield.equals(field2)) {
- sawGetStaticAfterPutStatic = true;
- break check;
- }
+ if (ins instanceof GETSTATIC && potentialInitialization(nextHandle)) {
+ XField field2 = XFactory.createXField((FieldInstruction) ins, methodGen.getConstantPool());
+ if (xfield.equals(field2)) {
+ sawGetStaticAfterPutStatic = true;
+ break check;
}
}
}
}
+ }
+
+ // Compute the priority:
+ // - ignore lazy initialization of instance fields
+ // - when it's done in a public method, emit a high priority warning
+ // - protected or default access method, emit a medium priority
+ // warning
+ // - otherwise, low priority
+
+ if (!sawGetStaticAfterPutStatic && xfield.isVolatile()) {
+ return;
+ }
+ int priority = LOW_PRIORITY;
+ boolean isDefaultAccess = (method.getAccessFlags() & (Constants.ACC_PUBLIC | Constants.ACC_PRIVATE | Constants.ACC_PROTECTED)) == 0;
+ if (method.isPublic()) {
+ priority = NORMAL_PRIORITY;
+ } else if (method.isProtected() || isDefaultAccess) {
+ priority = NORMAL_PRIORITY;
+ }
+ if (signature.startsWith("[") || signature.startsWith("Ljava/util/")) {
+ priority--;
+ }
+ if (!sawNEW) {
+ priority++;
+ }
+ if (!sawGetStaticAfterPutStatic && priority < LOW_PRIORITY) {
+ priority = LOW_PRIORITY;
+ }
+ if (classContext.getXClass().usesConcurrency()) {
+ priority--;
+ }
+ // Report the bug.
+ InstructionHandle start = match.getLabeledInstruction("start");
+ InstructionHandle end = match.getLabeledInstruction("end");
+ String sourceFile = javaClass.getSourceFileName();
+ bugReporter.reportBug(new BugInstance(this, sawGetStaticAfterPutStatic ? "LI_LAZY_INIT_UPDATE_STATIC"
+ : "LI_LAZY_INIT_STATIC", priority).addClassAndMethod(methodGen, sourceFile).addField(xfield)
+ .describe("FIELD_ON").addSourceLine(classContext, methodGen, sourceFile, start, end));
+ reported.set(testInstructionHandle.getPosition());
- // Compute the priority:
- // - ignore lazy initialization of instance fields
- // - when it's done in a public method, emit a high priority warning
- // - protected or default access method, emit a medium priority
- // warning
- // - otherwise, low priority
-
- if (!sawGetStaticAfterPutStatic && xfield.isVolatile())
- return;
- int priority = LOW_PRIORITY;
- boolean isDefaultAccess = (method.getAccessFlags() & (Constants.ACC_PUBLIC | Constants.ACC_PRIVATE | Constants.ACC_PROTECTED)) == 0;
- if (method.isPublic())
- priority = NORMAL_PRIORITY;
- else if (method.isProtected() || isDefaultAccess)
- priority = NORMAL_PRIORITY;
- if (signature.startsWith("[") || signature.startsWith("Ljava/util/"))
- priority--;
- if (!sawNEW)
- priority++;
- if (!sawGetStaticAfterPutStatic && priority < LOW_PRIORITY)
- priority = LOW_PRIORITY;
- if (classContext.getXClass().usesConcurrency())
- priority--;
- // Report the bug.
- InstructionHandle start = match.getLabeledInstruction("start");
- InstructionHandle end = match.getLabeledInstruction("end");
- String sourceFile = javaClass.getSourceFileName();
- bugReporter.reportBug(new BugInstance(this, sawGetStaticAfterPutStatic ? "LI_LAZY_INIT_UPDATE_STATIC"
- : "LI_LAZY_INIT_STATIC", priority).addClassAndMethod(methodGen, sourceFile).addField(xfield)
- .describe("FIELD_ON").addSourceLine(classContext, methodGen, sourceFile, start, end));
- reported.set(testInstructionHandle.getPosition());
-
}
- /**
- * @param nextHandle
- * @return
- */
private boolean potentialInitialization(InstructionHandle nextHandle) {
- if (nextHandle == null)
+ if (nextHandle == null) {
return true;
+ }
Instruction instruction = nextHandle.getInstruction();
- if (instruction instanceof ReturnInstruction)
+ if (instruction instanceof ReturnInstruction) {
return false;
- if (instruction instanceof IfInstruction)
+ }
+ if (instruction instanceof IfInstruction) {
return false;
+ }
return true;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/LoadOfKnownNullValue.java b/src/java/edu/umd/cs/findbugs/detect/LoadOfKnownNullValue.java
index e1fa5f1..baf6b4d 100644
--- a/src/java/edu/umd/cs/findbugs/detect/LoadOfKnownNullValue.java
+++ b/src/java/edu/umd/cs/findbugs/detect/LoadOfKnownNullValue.java
@@ -10,6 +10,8 @@ import org.apache.bcel.generic.ALOAD;
import org.apache.bcel.generic.ARETURN;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.GOTO;
+import org.apache.bcel.generic.IFNULL;
+import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.MethodGen;
@@ -34,32 +36,36 @@ import edu.umd.cs.findbugs.ba.npe.IsNullValueFrame;
import edu.umd.cs.findbugs.ba.vna.ValueNumber;
import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
import edu.umd.cs.findbugs.ba.vna.ValueNumberSourceInfo;
+import edu.umd.cs.findbugs.visitclass.Util;
public class LoadOfKnownNullValue implements Detector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
- private BugAccumulator bugAccumulator;
+ private final BugAccumulator bugAccumulator;
public LoadOfKnownNullValue(BugReporter bugReporter) {
this.bugReporter = bugReporter;
this.bugAccumulator = new BugAccumulator(bugReporter);
}
+ @Override
public void visitClassContext(ClassContext classContext) {
Method[] methodList = classContext.getJavaClass().getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
} catch (MethodUnprofitableException mue) {
- if (SystemProperties.getBoolean("unprofitable.debug")) // otherwise
- // don't
- // report
+ if (SystemProperties.getBoolean("unprofitable.debug")) {
+ // don't
+ // report
bugReporter.logError("skipping unprofitable method in " + getClass().getName());
+ }
} catch (CFGBuilderException e) {
bugReporter.logError("Detector " + this.getClass().getName() + " caught exception", e);
} catch (DataflowAnalysisException e) {
@@ -86,8 +92,9 @@ public class LoadOfKnownNullValue implements Detector {
InstructionHandle handle = location.getHandle();
Instruction ins = handle.getInstruction();
- if (!(ins instanceof ALOAD))
+ if (!(ins instanceof ALOAD)) {
continue;
+ }
IsNullValueFrame frame = nullValueDataflow.getFactAtLocation(location);
if (!frame.isValid()) {
@@ -103,8 +110,9 @@ public class LoadOfKnownNullValue implements Detector {
IsNullValue v = frame.getValue(index);
if (!v.isDefinitelyNull()) {
int sourceLine = lineNumbers.getSourceLine(handle.getPosition());
- if (sourceLine > 0)
+ if (sourceLine > 0) {
linesWithLoadsOfNotDefinitelyNullValues.set(sourceLine);
+ }
}
}
}
@@ -115,8 +123,9 @@ public class LoadOfKnownNullValue implements Detector {
Location location = i.next();
InstructionHandle handle = location.getHandle();
Instruction ins = handle.getInstruction();
- if (!(ins instanceof ALOAD))
+ if (!(ins instanceof ALOAD)) {
continue;
+ }
IsNullValueFrame frame = nullValueDataflow.getFactAtLocation(location);
if (!frame.isValid()) {
// This basic block is probably dead
@@ -129,8 +138,9 @@ public class LoadOfKnownNullValue implements Detector {
int index = load.getIndex();
IsNullValue v = frame.getValue(index);
- if (!v.isDefinitelyNull())
+ if (!v.isDefinitelyNull()) {
sometimesGood.put(handle, null);
+ }
}
// System.out.println(nullValueDataflow);
@@ -139,11 +149,13 @@ public class LoadOfKnownNullValue implements Detector {
InstructionHandle handle = location.getHandle();
Instruction ins = handle.getInstruction();
- if (!(ins instanceof ALOAD))
+ if (!(ins instanceof ALOAD)) {
continue;
+ }
- if (sometimesGood.containsKey(handle))
+ if (sometimesGood.containsKey(handle)) {
continue;
+ }
IsNullValueFrame frame = nullValueDataflow.getFactAtLocation(location);
if (!frame.isValid()) {
// This basic block is probably dead
@@ -157,7 +169,14 @@ public class LoadOfKnownNullValue implements Detector {
int index = load.getIndex();
IsNullValue v = frame.getValue(index);
if (v.isDefinitelyNull()) {
- Instruction next = handle.getNext().getInstruction();
+ InstructionHandle nextHandle = handle.getNext();
+ Instruction next = nextHandle.getInstruction();
+ int position = location
+ .getHandle().getPosition();
+ int catchSizeANY = Util.getSizeOfSurroundingTryBlock(method, "", position);
+ if (catchSizeANY < Integer.MAX_VALUE && isNullTestedClose( classContext, load, nextHandle, next)) {
+ continue;
+ }
InstructionHandle prevHandle = handle.getPrev();
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
sourceFile, handle);
@@ -181,8 +200,9 @@ public class LoadOfKnownNullValue implements Detector {
}
int startLine = sourceLineAnnotation.getStartLine();
if (startLine > 0 && lineMentionedMultipleTimes.get(startLine)
- && linesWithLoadsOfNotDefinitelyNullValues.get(startLine))
+ && linesWithLoadsOfNotDefinitelyNullValues.get(startLine)) {
continue;
+ }
int previousLine = prevSourceLineAnnotation.getEndLine();
if (startLine < previousLine) {
@@ -191,18 +211,20 @@ public class LoadOfKnownNullValue implements Detector {
continue;
}
int priority = NORMAL_PRIORITY;
- if (!v.isChecked())
+ if (!v.isChecked()) {
priority++;
-
+ }
+
BugAnnotation variableAnnotation = null;
try {
// Get the value number
ValueNumberFrame vnaFrame = classContext.getValueNumberDataflow(method).getFactAfterLocation(location);
if (vnaFrame.isValid()) {
-
+
ValueNumber valueNumber = vnaFrame.getTopValue();
- if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))
+ if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
return;
+ }
variableAnnotation = ValueNumberSourceInfo.findAnnotationFromValueNumber(method, location, valueNumber, vnaFrame,
"VALUE_OF");
if (variableAnnotation instanceof LocalVariableAnnotation) {
@@ -226,13 +248,64 @@ public class LoadOfKnownNullValue implements Detector {
bugAccumulator.accumulateBug(
new BugInstance(this, "NP_LOAD_OF_KNOWN_NULL_VALUE", priority).addClassAndMethod(methodGen, sourceFile)
- .addOptionalAnnotation(variableAnnotation),
+ .addOptionalAnnotation(variableAnnotation),
sourceLineAnnotation);
}
}
}
+ /**
+ * @param classContext
+ * @param nextHandle
+ * @param next
+ */
+ private boolean isNullTestedClose(ClassContext classContext, ALOAD load, InstructionHandle nextHandle, Instruction next) {
+ if (!(next instanceof IFNULL)) {
+ return false;
+ }
+
+ IFNULL ifNull = (IFNULL) next;
+ InstructionHandle nextNextHandle = nextHandle.getNext(); // aload
+ if (nextNextHandle == null) {
+ return false;
+ }
+ Instruction nextInstruction = nextNextHandle.getInstruction();
+
+ if (!(nextInstruction instanceof ALOAD)) {
+ return false;
+ }
+ ALOAD nextLoad = (ALOAD) nextInstruction;
+ if (load.getIndex() != nextLoad.getIndex()) {
+ return false;
+ }
+ InstructionHandle nextNextNextHandle = nextNextHandle.getNext(); // invoke
+ if (nextNextNextHandle == null) {
+ return false;
+ }
+ Instruction nextNextNextInstruction = nextNextNextHandle.getInstruction();
+ if (!(nextNextNextInstruction instanceof INVOKEVIRTUAL)) {
+ return false;
+ }
+ INVOKEVIRTUAL invokeVirtual = (INVOKEVIRTUAL) nextNextNextInstruction;
+ String methodName = invokeVirtual.getMethodName(classContext.getConstantPoolGen());
+ String methodSig = invokeVirtual.getSignature(classContext.getConstantPoolGen());
+ if (!"close".equals(methodName)) {
+ return false;
+ }
+ if (!"()V".equals(methodSig)) {
+ return false;
+ }
+ InstructionHandle nextNextNextNextHandle = nextNextNextHandle.getNext(); // after
+ if (ifNull.getTarget() != nextNextNextNextHandle) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/LostLoggerDueToWeakReference.java b/src/java/edu/umd/cs/findbugs/detect/LostLoggerDueToWeakReference.java
index 3fc38e6..e515484 100644
--- a/src/java/edu/umd/cs/findbugs/detect/LostLoggerDueToWeakReference.java
+++ b/src/java/edu/umd/cs/findbugs/detect/LostLoggerDueToWeakReference.java
@@ -19,7 +19,9 @@
package edu.umd.cs.findbugs.detect;
+import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import org.apache.bcel.classfile.Code;
@@ -27,7 +29,9 @@ import edu.umd.cs.findbugs.BugAccumulator;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.OpcodeStack;
+import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
/**
@@ -40,15 +44,18 @@ import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
* that memory, which means that the logger configuration is lost.
*/
public class LostLoggerDueToWeakReference extends OpcodeStackDetector {
+ private static final List<MethodDescriptor> methods = Arrays.asList(
+ new MethodDescriptor("java/util/logging/Logger", "getLogger", "(Ljava/lang/String;)Ljava/util/logging/Logger;", true),
+ new MethodDescriptor("java/util/logging/Logger", "getLogger", "(Ljava/lang/String;Ljava/lang/String;)Ljava/util/logging/Logger;", true));
- final BugReporter bugReporter;
+ // final BugReporter bugReporter;
final BugAccumulator bugAccumulator;
final HashSet<String> namesOfSetterMethods = new HashSet<String>();
public LostLoggerDueToWeakReference(BugReporter bugReporter) {
- this.bugReporter = bugReporter;
+ // this.bugReporter = bugReporter;
this.bugAccumulator = new BugAccumulator(bugReporter);
namesOfSetterMethods.add("addHandler");
namesOfSetterMethods.add("setUseParentHandlers");
@@ -57,19 +64,29 @@ public class LostLoggerDueToWeakReference extends OpcodeStackDetector {
}
@Override
+ public void visitClassContext(ClassContext classContext) {
+ if(hasInterestingMethod(classContext.getJavaClass().getConstantPool(), methods)) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
public void visit(Code code) {
if (getMethodSig().indexOf("Logger") == -1) {
sawGetLogger = -1;
loggerEscaped = loggerImported = false;
super.visit(code); // make callbacks to sawOpcode for all opcodes
+ /*
if (false) {
System.out.println(getFullyQualifiedMethodName());
System.out.printf("%d %s %s\n", sawGetLogger, loggerEscaped, loggerImported);
}
+ */
if (sawGetLogger >= 0 && !loggerEscaped && !loggerImported) {
bugAccumulator.reportAccumulatedBugs();
- } else
+ } else {
bugAccumulator.clearBugs();
+ }
}
}
@@ -81,24 +98,27 @@ public class LostLoggerDueToWeakReference extends OpcodeStackDetector {
@Override
public void sawOpcode(int seen) {
- if (loggerEscaped || loggerImported)
+ if (loggerEscaped || loggerImported) {
return;
+ }
switch (seen) {
case INVOKESTATIC:
- if (getClassConstantOperand().equals("java/util/logging/Logger") && getNameConstantOperand().equals("getLogger")) {
+ if ("java/util/logging/Logger".equals(getClassConstantOperand()) && "getLogger".equals(getNameConstantOperand())) {
OpcodeStack.Item item = stack.getStackItem(0);
- if (!"".equals(item.getConstant()))
+ if (!"".equals(item.getConstant())) {
sawGetLogger = getPC();
+ }
break;
}
checkForImport();
break;
case INVOKEVIRTUAL:
- if (getClassConstantOperand().equals("java/util/logging/Logger")
+ if ("java/util/logging/Logger".equals(getClassConstantOperand())
&& namesOfSetterMethods.contains(getNameConstantOperand())) {
int priority = HIGH_PRIORITY;
- if (getMethod().isStatic() && getMethodName().equals("main") && getMethodSig().equals("([Ljava/lang/String;)V"))
+ if (getMethod().isStatic() && "main".equals(getMethodName()) && "([Ljava/lang/String;)V".equals(getMethodSig())) {
priority = NORMAL_PRIORITY;
+ }
OpcodeStack.Item item = stack.getItemMethodInvokedOn(this);
BugInstance bug = new BugInstance(this, "LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE", priority)
@@ -118,8 +138,9 @@ public class LostLoggerDueToWeakReference extends OpcodeStackDetector {
case CHECKCAST:
String sig = getClassConstantOperand();
- if (sig.indexOf("Logger") >= 0)
+ if (sig.indexOf("Logger") >= 0) {
loggerImported = true;
+ }
break;
case GETFIELD:
@@ -129,36 +150,44 @@ public class LostLoggerDueToWeakReference extends OpcodeStackDetector {
case PUTFIELD:
case PUTSTATIC:
checkForFieldEscape();
+ break;
+ default:
+ break;
}
}
private void checkForImport() {
- if (getSigConstantOperand().endsWith("Logger;"))
+ if (getSigConstantOperand().endsWith("Logger;")) {
loggerImported = true;
+ }
}
private void checkForMethodExportImport() {
int numArguments = PreorderVisitor.getNumberArguments(getSigConstantOperand());
for (int i = 0; i < numArguments; i++) {
OpcodeStack.Item item = stack.getStackItem(i);
- if (item.getSignature().endsWith("Logger;"))
+ if (item.getSignature().endsWith("Logger;")) {
loggerEscaped = true;
+ }
}
String sig = getSigConstantOperand();
- int pos = sig.indexOf(")");
+ int pos = sig.indexOf(')');
int loggerPos = sig.indexOf("Logger");
- if (0 <= loggerPos && loggerPos < pos)
+ if (0 <= loggerPos && loggerPos < pos) {
loggerEscaped = true;
+ }
}
private void checkForFieldEscape() {
String sig = getSigConstantOperand();
- if (sig.indexOf("Logger") >= 0)
+ if (sig.indexOf("Logger") >= 0) {
loggerEscaped = true;
+ }
OpcodeStack.Item item = stack.getStackItem(0);
- if (item.getSignature().endsWith("Logger;"))
+ if (item.getSignature().endsWith("Logger;")) {
loggerEscaped = true;
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/MethodReturnCheck.java b/src/java/edu/umd/cs/findbugs/detect/MethodReturnCheck.java
index a37ae40..95a7834 100644
--- a/src/java/edu/umd/cs/findbugs/detect/MethodReturnCheck.java
+++ b/src/java/edu/umd/cs/findbugs/detect/MethodReturnCheck.java
@@ -22,6 +22,7 @@ import java.util.BitSet;
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Code;
+import org.apache.bcel.generic.Type;
import edu.umd.cs.findbugs.BugAccumulator;
import edu.umd.cs.findbugs.BugInstance;
@@ -38,7 +39,11 @@ import edu.umd.cs.findbugs.ba.CheckReturnValueAnnotation;
import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.ba.XFactory;
import edu.umd.cs.findbugs.ba.XMethod;
+import edu.umd.cs.findbugs.ba.ch.Subtypes2;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.detect.FindNoSideEffectMethods.NoSideEffectMethodsDatabase;
+import edu.umd.cs.findbugs.util.ClassName;
import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
/**
@@ -75,8 +80,13 @@ public class MethodReturnCheck extends OpcodeStackDetector implements UseAnnotat
private int callPC;
+ private final NoSideEffectMethodsDatabase noSideEffectMethods;
+
+ private boolean sawExcludedNSECall;
+
public MethodReturnCheck(BugReporter bugReporter) {
this.bugAccumulator = new BugAccumulator(bugReporter);
+ this.noSideEffectMethods = Global.getAnalysisCache().getDatabase(NoSideEffectMethodsDatabase.class);
}
@Override
@@ -87,35 +97,50 @@ public class MethodReturnCheck extends OpcodeStackDetector implements UseAnnotat
@Override
public void visitAfter(Code code) {
+ if(bugAccumulator.getLastBugLocation() == null && !sawExcludedNSECall && noSideEffectMethods.useless(getMethodDescriptor())) {
+ // Do not report UC_USELESS_VOID_METHOD if something was already reported inside the current method
+ // it's likely that UC_USELESS_VOID_METHOD is just the consequence of the previous report
+ bugAccumulator.accumulateBug(new BugInstance(this, "UC_USELESS_VOID_METHOD",
+ code.getCode().length > 40 ? HIGH_PRIORITY : code.getCode().length > 15 ? NORMAL_PRIORITY : LOW_PRIORITY)
+ .addClassAndMethod(getMethodDescriptor()), this);
+ }
+ sawExcludedNSECall = false;
bugAccumulator.reportAccumulatedBugs();
}
private boolean badUseOfCompareResult(Item left, Item right) {
XMethod m = left.getReturnValueOf();
- if (m == null)
+ if (m == null) {
return false;
+ }
String name = m.getName();
-
- if (!name.startsWith("compare"))
+
+ if (!name.startsWith("compare")) {
return false;
-
+ }
+
Object value = right.getConstant();
- if (!(value instanceof Integer) || ((Integer) value).intValue() == 0)
+ if (!(value instanceof Integer) || ((Integer) value).intValue() == 0) {
return false;
- if (!m.isPublic() && m.isResolved())
+ }
+ if (!m.isPublic() && m.isResolved()) {
return false;
-
-
+ }
+
+
if (m.isStatic() || !m.isResolved()) {
- if (name.equals("compare") && m.getClassName().startsWith("com.google.common.primitives."))
+ if ("compare".equals(name) && m.getClassName().startsWith("com.google.common.primitives.")) {
return true;
+ }
}
if (!m.isStatic() || !m.isResolved()) {
- if (name.equals("compareTo") && m.getSignature().equals("(Ljava/lang/Object;)I"))
+ if ("compareTo".equals(name) && "(Ljava/lang/Object;)I".equals(m.getSignature())) {
return true;
- if (name.equals("compare") && m.getSignature().equals("(Ljava/lang/Object;Ljava/lang/Object;)I"))
+ }
+ if ("compare".equals(name) && "(Ljava/lang/Object;Ljava/lang/Object;)I".equals(m.getSignature())) {
return true;
+ }
}
return false;
@@ -124,11 +149,13 @@ public class MethodReturnCheck extends OpcodeStackDetector implements UseAnnotat
@Override
public void sawOpcode(int seen) {
- if (DEBUG)
+ if (DEBUG) {
System.out.printf("%3d %10s %3s %s%n", getPC(), OPCODE_NAMES[seen], state, stack);
+ }
switch (seen) {
case Constants.IF_ICMPEQ:
+
case Constants.IF_ICMPNE:
OpcodeStack.Item left = stack.getStackItem(1);
OpcodeStack.Item right = stack.getStackItem(0);
@@ -136,24 +163,28 @@ public class MethodReturnCheck extends OpcodeStackDetector implements UseAnnotat
XMethod returnValueOf = left.getReturnValueOf();
assert returnValueOf != null;
bugAccumulator.accumulateBug(new BugInstance(this, "RV_CHECK_COMPARETO_FOR_SPECIFIC_RETURN_VALUE", NORMAL_PRIORITY)
- .addClassAndMethod(this).addMethod(returnValueOf).describe(MethodAnnotation.METHOD_CALLED).addValueSource(right, this), this);
+ .addClassAndMethod(this).addMethod(returnValueOf).describe(MethodAnnotation.METHOD_CALLED).addValueSource(right, this), this);
} else if (badUseOfCompareResult(right, left)) {
XMethod returnValueOf = right.getReturnValueOf();
assert returnValueOf != null;
bugAccumulator.accumulateBug(new BugInstance(this, "RV_CHECK_COMPARETO_FOR_SPECIFIC_RETURN_VALUE", NORMAL_PRIORITY)
- .addClassAndMethod(this).addMethod(returnValueOf).describe(MethodAnnotation.METHOD_CALLED).addValueSource(left, this), this);
+ .addClassAndMethod(this).addMethod(returnValueOf).describe(MethodAnnotation.METHOD_CALLED).addValueSource(left, this), this);
}
+ break;
+ default:
+ break;
}
- checkForInitWithoutCopyOnStack: if (seen == INVOKESPECIAL && getNameConstantOperand().equals("<init>")) {
+ checkForInitWithoutCopyOnStack: if (seen == INVOKESPECIAL && "<init>".equals(getNameConstantOperand())) {
int arguments = PreorderVisitor.getNumberArguments(getSigConstantOperand());
OpcodeStack.Item invokedOn = stack.getStackItem(arguments);
- if (invokedOn.isNewlyAllocated() && (!getMethodName().equals("<init>") || invokedOn.getRegisterNumber() != 0)) {
+ if (invokedOn.isNewlyAllocated() && (!"<init>".equals(getMethodName()) || invokedOn.getRegisterNumber() != 0)) {
for (int i = arguments + 1; i < stack.getStackDepth(); i++) {
OpcodeStack.Item item = stack.getStackItem(i);
- if (item.isNewlyAllocated() && item.getSignature().equals(invokedOn.getSignature()))
+ if (item.isNewlyAllocated() && item.getSignature().equals(invokedOn.getSignature())) {
break checkForInitWithoutCopyOnStack;
+ }
}
callSeen = XFactory.createReferencedXMethod(this);
@@ -166,16 +197,18 @@ public class MethodReturnCheck extends OpcodeStackDetector implements UseAnnotat
}
}
- if (state == SAW_INVOKE && isPop(seen))
+ if (state == SAW_INVOKE && isPop(seen)) {
sawMethodCallWithIgnoredReturnValue();
- else if (INVOKE_OPCODE_SET.get(seen)) {
+ } else if (INVOKE_OPCODE_SET.get(seen)) {
callPC = getPC();
callSeen = XFactory.createReferencedXMethod(this);
state = SAW_INVOKE;
- if (DEBUG)
+ if (DEBUG) {
System.out.println(" invoking " + callSeen);
- } else
+ }
+ } else {
state = SCAN;
+ }
if (seen == NEW) {
previousOpcodeWasNEW = true;
@@ -185,8 +218,9 @@ public class MethodReturnCheck extends OpcodeStackDetector implements UseAnnotat
if (annotation != null && annotation != CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE) {
int priority = annotation.getPriority();
if (!checkReturnAnnotationDatabase.annotationIsDirect(callSeen)
- && !callSeen.getSignature().endsWith(callSeen.getClassName().replace('.', '/') + ";"))
+ && !callSeen.getSignature().endsWith(callSeen.getClassName().replace('.', '/') + ";")) {
priority++;
+ }
bugAccumulator.accumulateBug(new BugInstance(this, annotation.getPattern(), priority).addClassAndMethod(this)
.addCalledMethod(this), this);
}
@@ -204,34 +238,69 @@ public class MethodReturnCheck extends OpcodeStackDetector implements UseAnnotat
{
CheckReturnValueAnnotation annotation = checkReturnAnnotationDatabase.getResolvedAnnotation(callSeen, false);
if (annotation == null) {
- XFactory xFactory = AnalysisContext.currentXFactory();
-
- if (xFactory.isFunctionshatMightBeMistakenForProcedures(callSeen.getMethodDescriptor())) {
- annotation = CheckReturnValueAnnotation.CHECK_RETURN_VALUE_INFERRED;
+ if (noSideEffectMethods.excluded(callSeen.getMethodDescriptor())) {
+ sawExcludedNSECall = true;
+ }
+ if (noSideEffectMethods.hasNoSideEffect(callSeen.getMethodDescriptor())) {
+ int priority = NORMAL_PRIORITY;
+ Type callReturnType = Type.getReturnType(callSeen.getMethodDescriptor().getSignature());
+ Type methodReturnType = Type.getReturnType(getMethodSig());
+ if(callReturnType.equals(methodReturnType) && callReturnType != Type.BOOLEAN && callReturnType != Type.VOID) {
+ priority = HIGH_PRIORITY;
+ } else {
+ String callReturnClass = callSeen.getName().equals("<init>") ?
+ callSeen.getClassDescriptor().getClassName() :
+ ClassName.fromFieldSignature(callReturnType.getSignature());
+
+ String methodReturnClass = ClassName.fromFieldSignature(methodReturnType.getSignature());
+ if(callReturnClass != null && methodReturnClass != null &&
+ Subtypes2.instanceOf(ClassName.toDottedClassName(callReturnClass), ClassName.toDottedClassName(methodReturnClass))) {
+ priority = HIGH_PRIORITY;
+ }
+ }
+ int catchSize = getSizeOfSurroundingTryBlock(getPC());
+ if(catchSize <= 2) {
+ priority++;
+ }
+ BugInstance warning = new BugInstance(this, "RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT", priority)
+ .addClassAndMethod(this).addMethod(callSeen).describe(MethodAnnotation.METHOD_CALLED);
+ bugAccumulator.accumulateBug(warning, SourceLineAnnotation.fromVisitedInstruction(this, callPC));
+ } else {
+ XFactory xFactory = AnalysisContext.currentXFactory();
+
+ if (xFactory.isFunctionshatMightBeMistakenForProcedures(callSeen.getMethodDescriptor())) {
+ annotation = CheckReturnValueAnnotation.CHECK_RETURN_VALUE_INFERRED;
+ }
}
}
if (annotation != null && annotation.getPriority() <= LOW_PRIORITY) {
int popPC = getPC();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Saw POP @" + popPC);
+ }
int catchSize = getSizeOfSurroundingTryBlock(popPC);
int priority = annotation.getPriority();
- if (catchSize <= 1)
+ if (catchSize <= 1) {
priority += 2;
- else if (catchSize <= 2)
+ } else if (catchSize <= 2) {
priority += 1;
+ }
if (!checkReturnAnnotationDatabase.annotationIsDirect(callSeen)
- && !callSeen.getSignature().endsWith(callSeen.getClassName().replace('.', '/') + ";"))
+ && !callSeen.getSignature().endsWith(callSeen.getClassName().replace('.', '/') + ";")) {
priority++;
- if (callSeen.isPrivate())
+ }
+ if (callSeen.isPrivate()) {
priority++;
- if (callSeen.getName().equals("clone") || callSeen.getName().startsWith("get"))
+ }
+ if ("clone".equals(callSeen.getName()) || callSeen.getName().startsWith("get")) {
priority++;
+ }
String pattern = annotation.getPattern();
- if (callSeen.getName().equals("<init>")
- && (callSeen.getClassName().endsWith("Exception") || callSeen.getClassName().endsWith("Error")))
+ if ("<init>".equals(callSeen.getName())
+ && (callSeen.getClassName().endsWith("Exception") || callSeen.getClassName().endsWith("Error"))) {
pattern = "RV_EXCEPTION_NOT_THROWN";
+ }
BugInstance warning = new BugInstance(this, pattern, priority).addClassAndMethod(this).addMethod(callSeen)
.describe(MethodAnnotation.METHOD_CALLED);
bugAccumulator.accumulateBug(warning, SourceLineAnnotation.fromVisitedInstruction(this, callPC));
diff --git a/src/java/edu/umd/cs/findbugs/detect/MethodReturnValueStreamFactory.java b/src/java/edu/umd/cs/findbugs/detect/MethodReturnValueStreamFactory.java
index a6357a4..4eb9417 100644
--- a/src/java/edu/umd/cs/findbugs/detect/MethodReturnValueStreamFactory.java
+++ b/src/java/edu/umd/cs/findbugs/detect/MethodReturnValueStreamFactory.java
@@ -47,19 +47,19 @@ public class MethodReturnValueStreamFactory implements StreamFactory {
invokeOpcodeSet.set(Constants.INVOKEVIRTUAL);
}
- private ObjectType baseClassType;
+ private final ObjectType baseClassType;
- private String methodName;
+ private final String methodName;
- private String methodSig;
+ private final String methodSig;
- private boolean isUninteresting;
+ private final boolean isUninteresting;
private String bugType;
/**
* Constructor. The Streams created will be marked as uninteresting.
- *
+ *
* @param baseClass
* base class through which the method will be called (we check
* instances of the base class and all subtypes)
@@ -77,7 +77,7 @@ public class MethodReturnValueStreamFactory implements StreamFactory {
/**
* Constructor. The Streams created will be marked as interesting.
- *
+ *
* @param baseClass
* base class through which the method will be called (we check
* instances of the base class and all subtypes)
@@ -97,6 +97,7 @@ public class MethodReturnValueStreamFactory implements StreamFactory {
this.bugType = bugType;
}
+ @Override
public Stream createStream(Location location, ObjectType type, ConstantPoolGen cpg,
RepositoryLookupFailureCallback lookupFailureCallback) {
@@ -105,30 +106,35 @@ public class MethodReturnValueStreamFactory implements StreamFactory {
// For now, just support instance methods
short opcode = ins.getOpcode();
- if (!invokeOpcodeSet.get(opcode))
+ if (!invokeOpcodeSet.get(opcode)) {
return null;
+ }
// Is invoked class a subtype of the base class we want
// FIXME: should test be different for INVOKESPECIAL and
// INVOKESTATIC?
InvokeInstruction inv = (InvokeInstruction) ins;
ReferenceType classType = inv.getReferenceType(cpg);
- if (!Hierarchy.isSubtype(classType, baseClassType))
+ if (!Hierarchy.isSubtype(classType, baseClassType)) {
return null;
+ }
// See if method name and signature match
String methodName = inv.getMethodName(cpg);
String methodSig = inv.getSignature(cpg);
- if (!this.methodName.equals(methodName) || !this.methodSig.equals(methodSig))
+ if (!this.methodName.equals(methodName) || !this.methodSig.equals(methodSig)) {
return null;
+ }
String streamClass = type.getClassName();
- if (streamClass.equals("java.sql.CallableStatement"))
+ if ("java.sql.CallableStatement".equals(streamClass)) {
streamClass = "java.sql.PreparedStatement";
+ }
Stream result = new Stream(location, streamClass, streamClass).setIgnoreImplicitExceptions(true).setIsOpenOnCreation(
true);
- if (!isUninteresting)
+ if (!isUninteresting) {
result.setInteresting(bugType);
+ }
return result;
} catch (ClassNotFoundException e) {
lookupFailureCallback.reportMissingClass(e);
@@ -138,4 +144,3 @@ public class MethodReturnValueStreamFactory implements StreamFactory {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/Methods.java b/src/java/edu/umd/cs/findbugs/detect/Methods.java
index 04b0ed1..9a9685b 100644
--- a/src/java/edu/umd/cs/findbugs/detect/Methods.java
+++ b/src/java/edu/umd/cs/findbugs/detect/Methods.java
@@ -30,10 +30,12 @@ public class Methods extends PreorderVisitor implements Detector, NonReportingDe
public Methods(BugReporter bugReporter) {
}
+ @Override
public void visitClassContext(ClassContext classContext) {
classContext.getJavaClass().accept(this);
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/MultithreadedInstanceAccess.java b/src/java/edu/umd/cs/findbugs/detect/MultithreadedInstanceAccess.java
index 3f6dc8f..1460918 100644
--- a/src/java/edu/umd/cs/findbugs/detect/MultithreadedInstanceAccess.java
+++ b/src/java/edu/umd/cs/findbugs/detect/MultithreadedInstanceAccess.java
@@ -44,7 +44,7 @@ public class MultithreadedInstanceAccess extends OpcodeStackDetector {
private static final String SERVLET_NAME = "javax.servlet.Servlet";
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private Set<JavaClass> mtClasses;
@@ -61,8 +61,9 @@ public class MultithreadedInstanceAccess extends OpcodeStackDetector {
}
private Set<JavaClass> getMtClasses() {
- if (mtClasses != null)
+ if (mtClasses != null) {
return mtClasses;
+ }
mtClasses = new HashSet<JavaClass>();
try {
@@ -84,8 +85,9 @@ public class MultithreadedInstanceAccess extends OpcodeStackDetector {
try {
JavaClass cls = classContext.getJavaClass();
String superClsName = cls.getSuperclassName();
- if ("java.lang.Object".equals(superClsName))
+ if ("java.lang.Object".equals(superClsName)) {
return;
+ }
if (STRUTS_ACTION_NAME.equals(superClsName)) {
mtClassName = STRUTS_ACTION_NAME;
@@ -124,17 +126,18 @@ public class MultithreadedInstanceAccess extends OpcodeStackDetector {
writingField = false;
}
-
+
@Override
public boolean shouldVisitCode(Code code) {
- return !getMethodName().equals("<init>") && !getMethodName().equals("init");
-
+ return !"<init>".equals(getMethodName()) && !"init".equals(getMethodName());
+
}
@Override
public void sawField() {
- if ((monitorCount > 0) || (!writingField))
+ if ((monitorCount > 0) || (!writingField)) {
return;
+ }
ConstantFieldref fieldRef;
Constant c = getConstantRefOperand();
@@ -156,15 +159,16 @@ public class MultithreadedInstanceAccess extends OpcodeStackDetector {
ConstantUtf8 nameCons = (ConstantUtf8) cp.getConstant(nameIdx);
ConstantUtf8 typeCons = (ConstantUtf8) cp.getConstant(ntc.getSignatureIndex());
- if (alreadyReported.contains(nameCons.getBytes()))
+ if (alreadyReported.contains(nameCons.getBytes())) {
return;
+ }
alreadyReported.add(nameCons.getBytes());
bugReporter.reportBug(new BugInstance(this,
STRUTS_ACTION_NAME.equals(mtClassName) ? "MTIA_SUSPECT_STRUTS_INSTANCE_FIELD"
: "MTIA_SUSPECT_SERVLET_INSTANCE_FIELD", LOW_PRIORITY)
- .addField(
- new FieldAnnotation(getDottedClassName(), nameCons.getBytes(), typeCons.getBytes(),
- false)).addClass(this).addSourceLine(this));
+ .addField(
+ new FieldAnnotation(getDottedClassName(), nameCons.getBytes(), typeCons.getBytes(),
+ false)).addClass(this).addSourceLine(this));
}
break;
}
@@ -175,10 +179,11 @@ public class MultithreadedInstanceAccess extends OpcodeStackDetector {
@Override
public void sawOpcode(int seen) {
- if (seen == MONITORENTER)
+ if (seen == MONITORENTER) {
monitorCount++;
- else if (seen == MONITOREXIT)
+ } else if (seen == MONITOREXIT) {
monitorCount--;
+ }
writingField = ((seen == PUTFIELD) || (seen == PUTFIELD_QUICK) || (seen == PUTFIELD_QUICK_W));
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/MutableEnum.java b/src/java/edu/umd/cs/findbugs/detect/MutableEnum.java
new file mode 100644
index 0000000..7bfd5ad
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/detect/MutableEnum.java
@@ -0,0 +1,92 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.detect;
+
+import org.apache.bcel.classfile.Code;
+
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.OpcodeStack.Item;
+import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.ba.XField;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+
+/**
+ * @author Tagir Valeev
+ */
+public class MutableEnum extends OpcodeStackDetector {
+
+ private final BugReporter reporter;
+ private boolean skip;
+
+ public MutableEnum(BugReporter reporter) {
+ this.reporter = reporter;
+ }
+
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ if(!classContext.getJavaClass().isEnum() || !classContext.getJavaClass().isPublic()) {
+ return;
+ }
+ boolean hasInterestingField = false;
+ for(XField field : classContext.getXClass().getXFields()) {
+ if(!field.isStatic() && !field.isFinal() && !field.isSynthetic()) {
+ if(field.isPublic()) {
+ reporter.reportBug(new BugInstance("ME_MUTABLE_ENUM_FIELD", NORMAL_PRIORITY).addClass(classContext.getJavaClass())
+ .addField(field));
+ } else {
+ hasInterestingField = true;
+ }
+ }
+ }
+ if(hasInterestingField) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
+ public boolean shouldVisitCode(Code obj) {
+ skip = false;
+ if(getXMethod().isPublic() && getNumberMethodArguments() > 0) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if(skip) {
+ return;
+ }
+ if(isBranch(seen) || seen == ATHROW || isReturn(seen)) {
+ skip = true;
+ }
+ if(seen == PUTFIELD) {
+ XField xField = getXFieldOperand();
+ if(xField != null && xField.getClassDescriptor().getClassName().equals(getClassName())) {
+ Item val = getStack().getStackItem(0);
+ if(val.isInitialParameter()) {
+ reporter.reportBug(new BugInstance("ME_ENUM_FIELD_SETTER", NORMAL_PRIORITY).addClassAndMethod(this).addField(xField)
+ .addSourceLine(this));
+ }
+ }
+ }
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/detect/MutableLock.java b/src/java/edu/umd/cs/findbugs/detect/MutableLock.java
index 1c42a88..c1747f2 100644
--- a/src/java/edu/umd/cs/findbugs/detect/MutableLock.java
+++ b/src/java/edu/umd/cs/findbugs/detect/MutableLock.java
@@ -38,7 +38,7 @@ public class MutableLock extends BytecodeScanningDetector implements StatelessDe
boolean thisOnTOS = false;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public MutableLock(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -53,8 +53,9 @@ public class MutableLock extends BytecodeScanningDetector implements StatelessDe
@Override
public void visit(Field obj) {
super.visit(obj);
- if (obj.isFinal())
+ if (obj.isFinal()) {
finalFields.add(obj.getName());
+ }
}
@Override
@@ -75,18 +76,21 @@ public class MutableLock extends BytecodeScanningDetector implements StatelessDe
setFields.clear();
break;
case PUTFIELD:
- if (getClassConstantOperand().equals(getClassName()))
+ if (getClassConstantOperand().equals(getClassName())) {
setFields.add(getNameConstantOperand());
+ }
break;
case GETFIELD:
if (thisOnTOS && getClassConstantOperand().equals(getClassName()) && setFields.contains(getNameConstantOperand())
&& asUnsignedByte(codeBytes[getPC() + 3]) == DUP && asUnsignedByte(codeBytes[getPC() + 5]) == MONITORENTER
- && !finalFields.contains(getNameConstantOperand()))
+ && !finalFields.contains(getNameConstantOperand())) {
bugReporter.reportBug(new BugInstance(this, "ML_SYNC_ON_UPDATED_FIELD", NORMAL_PRIORITY).addClassAndMethod(this)
.addReferencedField(this).addSourceLine(this, getPC() + 5));
+ }
break;
default:
+ break;
}
thisOnTOS = false;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/MutableStaticFields.java b/src/java/edu/umd/cs/findbugs/detect/MutableStaticFields.java
index aa5b419..29c6df2 100644
--- a/src/java/edu/umd/cs/findbugs/detect/MutableStaticFields.java
+++ b/src/java/edu/umd/cs/findbugs/detect/MutableStaticFields.java
@@ -19,6 +19,8 @@
package edu.umd.cs.findbugs.detect;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@@ -37,10 +39,37 @@ import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.XClass;
import edu.umd.cs.findbugs.ba.XField;
+import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
+import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.Global;
public class MutableStaticFields extends BytecodeScanningDetector {
+ private static final Set<String> COLLECTION_SUPERCLASSES = new HashSet<>(Arrays.asList("java/util/Collection",
+ "java/util/List", "java/util/Set", "java/util/Map", "java/util/AbstractList", "java/util/SortedSet",
+ "java/util/SortedMap", "java/util/NavigableMap", "java/util/Dictionary"));
+
+ private static final Set<String> MUTABLE_COLLECTION_CLASSES = new HashSet<>(Arrays.asList("java/util/ArrayList",
+ "java/util/HashSet", "java/util/HashMap", "java/util/Hashtable", "java/util/IdentityHashMap",
+ "java/util/LinkedHashSet", "java/util/LinkedList", "java/util/LinkedHashMap", "java/util/TreeSet",
+ "java/util/TreeMap", "java/util/Properties"));
+
+ private static enum AllowedParameter {
+ NONE, EMPTY_ARRAY
+ }
+
+ private static final Map<String, Map<String, AllowedParameter>> MUTABLE_COLLECTION_METHODS = new HashMap<>();
+ static {
+ MUTABLE_COLLECTION_METHODS.put("java/util/Arrays", Collections.singletonMap("asList", AllowedParameter.EMPTY_ARRAY));
+ Map<String, AllowedParameter> listsMap = new HashMap<>();
+ listsMap.put("newArrayList", AllowedParameter.NONE);
+ listsMap.put("newLinkedList", AllowedParameter.NONE);
+ MUTABLE_COLLECTION_METHODS.put("com/google/common/collect/Lists", listsMap);
+ Map<String, AllowedParameter> setsMap = new HashMap<>();
+ setsMap.put("newHashSet", AllowedParameter.NONE);
+ setsMap.put("newTreeSet", AllowedParameter.NONE);
+ MUTABLE_COLLECTION_METHODS.put("com/google/common/collect/Sets", setsMap);
+ }
static String extractPackage(String c) {
int i = c.lastIndexOf('/');
@@ -51,16 +80,18 @@ public class MutableStaticFields extends BytecodeScanningDetector {
}
static boolean mutableSignature(String sig) {
- return sig.equals("Ljava/util/Hashtable;") || sig.equals("Ljava/util/Date;") ||
- sig.equals("Ljava/sql/Date;") ||
- sig.equals("Ljava/sql/Timestamp;") ||
- sig.charAt(0) == '[';
+ return sig.equals("Ljava/util/Hashtable;") || sig.equals("Ljava/util/Date;") ||
+ sig.equals("Ljava/sql/Date;") ||
+ sig.equals("Ljava/sql/Timestamp;") ||
+ sig.charAt(0) == '[';
}
LinkedList<XField> seen = new LinkedList<XField>();
boolean publicClass;
+ boolean mutableCollectionJustCreated = false;
+
boolean zeroOnTOS;
boolean emptyArrayOnTOS;
@@ -73,12 +104,16 @@ public class MutableStaticFields extends BytecodeScanningDetector {
Set<XField> unsafeValue = new HashSet<XField>();
+ Set<XField> mutableCollection = new HashSet<XField>();
+
Set<XField> notFinal = new HashSet<XField>();
Set<XField> outsidePackage = new HashSet<XField>();
+
Set<XField> needsRefactoringToBeFinal = new HashSet<XField>();
-
+
Set<XField> writtenInMethod = new HashSet<XField>();
+
Set<XField> writtenTwiceInMethod = new HashSet<XField>();
Map<XField, SourceLineAnnotation> firstFieldUse = new HashMap<XField, SourceLineAnnotation>();
@@ -114,14 +149,15 @@ public class MutableStaticFields extends BytecodeScanningDetector {
// System.out.println(methodName);
inStaticInitializer = getMethodName().equals("<clinit>");
}
-
+
@Override
public void visit(Code obj) {
writtenInMethod.clear();
writtenTwiceInMethod.clear();
super.visit(obj);
- if (inStaticInitializer)
+ if (inStaticInitializer) {
needsRefactoringToBeFinal.addAll(writtenTwiceInMethod);
+ }
writtenInMethod.clear();
writtenTwiceInMethod.clear();
}
@@ -141,7 +177,7 @@ public class MutableStaticFields extends BytecodeScanningDetector {
break;
}
- boolean samePackage = packageName.equals(extractPackage(getClassConstantOperand()));
+ boolean samePackage = packageName.equals(extractPackage(xField.getFieldDescriptor().getSlashedClassName()));
boolean initOnly = seen == GETSTATIC || getClassName().equals(getClassConstantOperand()) && inStaticInitializer;
boolean safeValue = seen == GETSTATIC || emptyArrayOnTOS
|| AnalysisContext.currentXFactory().isEmptyArrayField(xField) || !mutableSignature(getSigConstantOperand());
@@ -150,8 +186,12 @@ public class MutableStaticFields extends BytecodeScanningDetector {
readAnywhere.add(xField);
}
if (seen == PUTSTATIC) {
- if (!writtenInMethod.add(xField))
+ if (xField.isFinal() && mutableCollectionJustCreated) {
+ mutableCollection.add(xField);
+ }
+ if (!writtenInMethod.add(xField)) {
writtenTwiceInMethod.add(xField);
+ }
}
if (!samePackage) {
@@ -185,9 +225,64 @@ public class MutableStaticFields extends BytecodeScanningDetector {
zeroOnTOS = true;
emptyArrayOnTOS = false;
return;
+ case INVOKESPECIAL:
+ if (inStaticInitializer && "<init>".equals(getMethodDescriptorOperand().getName())) {
+ ClassDescriptor classDescriptor = getClassDescriptorOperand();
+ if (MUTABLE_COLLECTION_CLASSES.contains(classDescriptor.getClassName())) {
+ mutableCollectionJustCreated = true;
+ return;
+ }
+ try {
+ /* Check whether it's statically initialized anonymous class like this:
+ * public static final Map map = new HashMap() {{put("a", "b");}}
+ * We do not check whether all modification methods are overridden or not for simplicity:
+ * Skip if there's at least one method is present
+ */
+ XClass xClass = classDescriptor.getXClass();
+ ClassDescriptor superclassDescriptor = xClass.getSuperclassDescriptor();
+ if (superclassDescriptor != null
+ && MUTABLE_COLLECTION_CLASSES.contains(superclassDescriptor.getClassName())) {
+ mutableCollectionJustCreated = true;
+ for (XMethod xMethod : xClass.getXMethods()) {
+ if (xMethod != null && !"<init>".equals(xMethod.getName()) && !"<clinit>".equals(xMethod.getName())) {
+ mutableCollectionJustCreated = false;
+ break;
+ }
+ }
+ return;
+ }
+ } catch (CheckedAnalysisException e) {
+ // ignore
+ }
+ }
+ break;
+ case INVOKESTATIC:
+ if (inStaticInitializer) {
+ Map<String, AllowedParameter> methods = MUTABLE_COLLECTION_METHODS.get(getMethodDescriptorOperand()
+ .getSlashedClassName());
+ if (methods != null) {
+ String name = getMethodDescriptorOperand().getName();
+ AllowedParameter allowedParameter = methods.get(name);
+ if (allowedParameter == AllowedParameter.NONE
+ || (allowedParameter == AllowedParameter.EMPTY_ARRAY && !emptyArrayOnTOS)) {
+ mutableCollectionJustCreated = true;
+ return;
+ }
+ }
+ }
+ break;
}
zeroOnTOS = false;
emptyArrayOnTOS = false;
+ mutableCollectionJustCreated = false;
+ }
+
+ private boolean isCollection(String signature) {
+ if (signature.startsWith("L") && signature.endsWith(";")) {
+ String fieldClass = signature.substring(1, signature.length() - 1);
+ return COLLECTION_SUPERCLASSES.contains(fieldClass) || MUTABLE_COLLECTION_CLASSES.contains(fieldClass);
+ }
+ return false;
}
private boolean interesting(XField f) {
@@ -197,9 +292,11 @@ public class MutableStaticFields extends BytecodeScanningDetector {
if (!f.isStatic() || f.isSynthetic() || f.isVolatile()) {
return false;
}
- boolean isHashtable = f.getSignature().equals("Ljava/util/Hashtable;");
+ if (!f.isFinal()) {
+ return true;
+ }
boolean isArray = f.getSignature().charAt(0) == '[';
- if (f.isFinal() && !(isArray || isHashtable)) {
+ if (!(isArray || isCollection(f.getSignature()))) {
return false;
}
return true;
@@ -225,10 +322,9 @@ public class MutableStaticFields extends BytecodeScanningDetector {
return;
}
- boolean isHashtable = getFieldSig().equals("Ljava/util/Hashtable;");
boolean isArray = getFieldSig().charAt(0) == '[';
- if (isFinal && !(isHashtable || isArray)) {
+ if (isFinal && !(isArray || isCollection(getFieldSig()))) {
return;
}
if (isEclipseNLS && getFieldSig().equals("Ljava/lang/String;")) {
@@ -250,8 +346,9 @@ public class MutableStaticFields extends BytecodeScanningDetector {
String fieldSig = f.getSignature();
String fieldName = f.getName();
boolean couldBeFinal = !isFinal && !notFinal.contains(f);
- boolean isPublic = f.isPublic();
+ // boolean isPublic = f.isPublic();
boolean couldBePackage = !outsidePackage.contains(f);
+ boolean isMutableCollection = mutableCollection.contains(f);
boolean movedOutofInterface = false;
try {
@@ -263,13 +360,13 @@ public class MutableStaticFields extends BytecodeScanningDetector {
boolean isHashtable = fieldSig.equals("Ljava/util/Hashtable;");
boolean isArray = fieldSig.charAt(0) == '[' && unsafeValue.contains(f);
boolean isReadAnywhere = readAnywhere.contains(f);
- if (false) {
- System.out.println(className + "." + fieldName + " : " + fieldSig + "\t" + isHashtable + "\t" + isArray);
- }
+ // if (false) {
+ // System.out.println(className + "." + fieldName + " : " + fieldSig + "\t" + isHashtable + "\t" + isArray);
+ // }
String bugType;
int priority = NORMAL_PRIORITY;
- if (isFinal && !isHashtable && !isArray) {
+ if (isFinal && !isHashtable && !isArray && !isMutableCollection) {
continue;
} else if (movedOutofInterface) {
bugType = "MS_OOI_PKGPROTECT";
@@ -277,13 +374,14 @@ public class MutableStaticFields extends BytecodeScanningDetector {
bugType = "MS_FINAL_PKGPROTECT";
} else if (couldBeFinal && !isHashtable && !isArray) {
bugType = "MS_SHOULD_BE_FINAL";
- if (needsRefactoringToBeFinal.contains(f))
+ if (needsRefactoringToBeFinal.contains(f)) {
bugType = "MS_SHOULD_BE_REFACTORED_TO_BE_FINAL";
+ }
if (fieldName.equals(fieldName.toUpperCase()) || fieldSig.charAt(0) == 'L') {
priority = HIGH_PRIORITY;
}
} else if (couldBePackage) {
- bugType = "MS_PKGPROTECT";
+ bugType = isMutableCollection ? "MS_MUTABLE_COLLECTION_PKGPROTECT" : "MS_PKGPROTECT";
} else if (isHashtable) {
bugType = "MS_MUTABLE_HASHTABLE";
if (!isFinal) {
@@ -291,9 +389,12 @@ public class MutableStaticFields extends BytecodeScanningDetector {
}
} else if (isArray) {
bugType = "MS_MUTABLE_ARRAY";
- if (fieldSig.indexOf("L") >= 0 || !isFinal) {
+ if (fieldSig.indexOf('L') >= 0 || !isFinal) {
priority = HIGH_PRIORITY;
}
+ } else if (isMutableCollection) {
+ bugType = "MS_MUTABLE_COLLECTION";
+ priority = HIGH_PRIORITY;
} else if (!isFinal) {
bugType = "MS_CANNOT_BE_FINAL";
} else {
diff --git a/src/java/edu/umd/cs/findbugs/detect/Naming.java b/src/java/edu/umd/cs/findbugs/detect/Naming.java
index 95c4234..58fcd77 100644
--- a/src/java/edu/umd/cs/findbugs/detect/Naming.java
+++ b/src/java/edu/umd/cs/findbugs/detect/Naming.java
@@ -61,7 +61,9 @@ import edu.umd.cs.findbugs.props.WarningPropertySet;
import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
public class Naming extends PreorderVisitor implements Detector {
+
public static class NamingProperty extends AbstractWarningProperty {
+
private NamingProperty(String name, PriorityAdjustment priorityAdjustment) {
super(name, priorityAdjustment);
}
@@ -71,7 +73,6 @@ public class Naming extends PreorderVisitor implements Detector {
public static final NamingProperty METHOD_IS_DEPRECATED = new NamingProperty("CONFUSING_METHOD_IS_DEPRECATED",
PriorityAdjustment.LOWER_PRIORITY);
-
}
String baseClassName;
@@ -80,37 +81,48 @@ public class Naming extends PreorderVisitor implements Detector {
public static @CheckForNull
XMethod definedIn(JavaClass clazz, XMethod m) {
- for (Method m2 : clazz.getMethods())
- if (m.getName().equals(m2.getName()) && m.getSignature().equals(m2.getSignature()) && m.isStatic() == m2.isStatic())
+ for (Method m2 : clazz.getMethods()) {
+ if (m.getName().equals(m2.getName()) && m.getSignature().equals(m2.getSignature()) && m.isStatic() == m2.isStatic()) {
return XFactory.createXMethod(clazz, m2);
+ }
+ }
return null;
}
public static boolean confusingMethodNamesWrongCapitalization(XMethod m1, XMethod m2) {
- if (m1.isStatic() != m2.isStatic())
+ if (m1.isStatic() != m2.isStatic()) {
return false;
- if (m1.getClassName().equals(m2.getClassName()))
+ }
+ if (m1.getClassName().equals(m2.getClassName())) {
return false;
- if (m1.getName().equals(m2.getName()))
+ }
+ if (m1.getName().equals(m2.getName())) {
return false;
+ }
if (m1.getName().equalsIgnoreCase(m2.getName())
- && removePackageNamesFromSignature(m1.getSignature()).equals(removePackageNamesFromSignature(m2.getSignature())))
+ && removePackageNamesFromSignature(m1.getSignature()).equals(removePackageNamesFromSignature(m2.getSignature()))) {
return true;
+ }
return false;
}
public static boolean confusingMethodNamesWrongPackage(XMethod m1, XMethod m2) {
- if (m1.isStatic() != m2.isStatic())
+ if (m1.isStatic() != m2.isStatic()) {
return false;
- if (m1.getClassName().equals(m2.getClassName()))
+ }
+ if (m1.getClassName().equals(m2.getClassName())) {
return false;
+ }
- if (!m1.getName().equals(m2.getName()))
+ if (!m1.getName().equals(m2.getName())) {
return false;
- if (m1.getSignature().equals(m2.getSignature()))
+ }
+ if (m1.getSignature().equals(m2.getSignature())) {
return false;
- if (removePackageNamesFromSignature(m1.getSignature()).equals(removePackageNamesFromSignature(m2.getSignature())))
+ }
+ if (removePackageNamesFromSignature(m1.getSignature()).equals(removePackageNamesFromSignature(m2.getSignature()))) {
return true;
+ }
return false;
}
@@ -119,21 +131,24 @@ public class Naming extends PreorderVisitor implements Detector {
HashSet<String> visited = new HashSet<String>();
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public Naming(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
classContext.getJavaClass().accept(this);
}
private boolean checkSuper(XMethod m, Set<XMethod> others) {
- if (m.isStatic())
+ if (m.isStatic()) {
return false;
- if (m.getName().equals("<init>") || m.getName().equals("<clinit>"))
+ }
+ if ("<init>".equals(m.getName()) || "<clinit>".equals(m.getName())) {
return false;
+ }
for (XMethod m2 : others) {
try {
if ((confusingMethodNamesWrongCapitalization(m, m2) || confusingMethodNamesWrongPackage(m, m2))
@@ -157,24 +172,27 @@ public class Naming extends PreorderVisitor implements Detector {
}
XFactory xFactory = AnalysisContext.currentXFactory();
- if (m3 == null && xFactory.isCalled(m))
+ if (m3 == null && xFactory.isCalled(m)) {
propertySet.addProperty(NamingProperty.METHOD_IS_CALLED);
- else if (m.isDeprecated() || m2.isDeprecated())
+ } else if (m.isDeprecated() || m2.isDeprecated()) {
propertySet.addProperty(NamingProperty.METHOD_IS_DEPRECATED);
+ }
if (!m.getName().equals(m2.getName()) && m.getName().equalsIgnoreCase(m2.getName())) {
String pattern = intentional ? "NM_VERY_CONFUSING_INTENTIONAL" : "NM_VERY_CONFUSING";
Set<XMethod> overrides = Hierarchy2.findSuperMethods(m);
if (!overrides.isEmpty()) {
- if (intentional || allAbstract(overrides))
+ if (intentional || allAbstract(overrides)) {
break;
+ }
priority++;
}
BugInstance bug = new BugInstance(this, pattern, priority).addClass(m.getClassName()).addMethod(m)
.addClass(m2.getClassName()).describe(ClassAnnotation.SUPERCLASS_ROLE).addMethod(m2)
.describe(MethodAnnotation.METHOD_DID_YOU_MEAN_TO_OVERRIDE);
- if (m3 != null)
+ if (m3 != null) {
bug.addMethod(m3).describe(MethodAnnotation.METHOD_OVERRIDDEN);
+ }
propertySet.decorateBugInstance(bug);
bugReporter.reportBug(bug);
} else if (!m.getSignature().equals(m2.getSignature())
@@ -183,8 +201,9 @@ public class Naming extends PreorderVisitor implements Detector {
String pattern = intentional ? "NM_WRONG_PACKAGE_INTENTIONAL" : "NM_WRONG_PACKAGE";
Set<XMethod> overrides = Hierarchy2.findSuperMethods(m);
if (!overrides.isEmpty()) {
- if (intentional || allAbstract(overrides))
+ if (intentional || allAbstract(overrides)) {
break;
+ }
priority++;
}
Iterator<String> s = new SignatureParser(m.getSignature()).parameterSignatureIterator();
@@ -197,8 +216,9 @@ public class Naming extends PreorderVisitor implements Detector {
.addMethod(m).addClass(m2.getClassName()).describe(ClassAnnotation.SUPERCLASS_ROLE)
.addMethod(m2).describe(MethodAnnotation.METHOD_DID_YOU_MEAN_TO_OVERRIDE)
.addFoundAndExpectedType(p, p2);
- if (m3 != null)
+ if (m3 != null) {
bug.addMethod(m3).describe(MethodAnnotation.METHOD_OVERRIDDEN);
+ }
propertySet.decorateBugInstance(bug);
bugReporter.reportBug(bug);
@@ -216,29 +236,27 @@ public class Naming extends PreorderVisitor implements Detector {
return false;
}
- /**
- * @param overrides
- * @return
- */
private boolean allAbstract(Set<XMethod> overrides) {
boolean allAbstract = true;
for (XMethod m4 : overrides) {
- if (!m4.isAbstract())
+ if (!m4.isAbstract()) {
allAbstract = false;
+ }
}
return allAbstract;
}
- @SuppressWarnings("unchecked")
private boolean checkNonSuper(XMethod m, Set<XMethod> others) {
- if (m.isStatic())
+ if (m.isStatic()) {
return false;
- if (m.getName().startsWith("<init>") || m.getName().startsWith("<clinit>"))
+ }
+ if (m.getName().startsWith("<init>") || m.getName().startsWith("<clinit>")) {
return false;
+ }
for (XMethod m2 : others) {
if (confusingMethodNamesWrongCapitalization(m, m2)) {
- XMethod mm1 = m;
- XMethod mm2 = m2;
+ XMethod mm1;
+ XMethod mm2;
if (m.compareTo(m2) < 0) {
mm1 = m;
mm2 = m2;
@@ -254,34 +272,40 @@ public class Naming extends PreorderVisitor implements Detector {
return false;
}
+ @Override
public void report() {
for (Map.Entry<String, TreeSet<XMethod>> e : canonicalToXMethod.entrySet()) {
TreeSet<XMethod> conflictingMethods = e.getValue();
HashSet<String> trueNames = new HashSet<String>();
- for (XMethod m : conflictingMethods)
+ for (XMethod m : conflictingMethods) {
trueNames.add(m.getName() + m.getSignature());
- if (trueNames.size() <= 1)
+ }
+ if (trueNames.size() <= 1) {
continue;
+ }
for (Iterator<XMethod> j = conflictingMethods.iterator(); j.hasNext();) {
- if (checkSuper(j.next(), conflictingMethods))
+ if (checkSuper(j.next(), conflictingMethods)) {
j.remove();
+ }
}
for (XMethod conflictingMethod : conflictingMethods) {
- if (checkNonSuper(conflictingMethod, conflictingMethods))
+ if (checkNonSuper(conflictingMethod, conflictingMethods)) {
break;
+ }
}
}
}
public String stripPackageName(String className) {
- if (className.indexOf('.') >= 0)
+ if (className.indexOf('.') >= 0) {
return className.substring(className.lastIndexOf('.') + 1);
- else if (className.indexOf('/') >= 0)
+ } else if (className.indexOf('/') >= 0) {
return className.substring(className.lastIndexOf('/') + 1);
- else
+ } else {
return className;
+ }
}
public boolean sameSimpleName(String class1, String class2) {
@@ -290,40 +314,45 @@ public class Naming extends PreorderVisitor implements Detector {
@Override
public void visitJavaClass(JavaClass obj) {
- if (BCELUtil.isSynthetic(obj))
+ if (BCELUtil.isSynthetic(obj)) {
return;
+ }
String name = obj.getClassName();
- if (!visited.add(name))
+ if (!visited.add(name)) {
return;
+ }
String superClassName = obj.getSuperclassName();
- if (!name.equals("java.lang.Object")) {
+ if (!"java.lang.Object".equals(name)) {
if (sameSimpleName(superClassName, name)) {
bugReporter.reportBug(new BugInstance(this, "NM_SAME_SIMPLE_NAME_AS_SUPERCLASS", HIGH_PRIORITY).addClass(name)
.addClass(superClassName));
}
- for (String interfaceName : obj.getInterfaceNames())
+ for (String interfaceName : obj.getInterfaceNames()) {
if (sameSimpleName(interfaceName, name)) {
bugReporter.reportBug(new BugInstance(this, "NM_SAME_SIMPLE_NAME_AS_INTERFACE", NORMAL_PRIORITY).addClass(
name).addClass(interfaceName));
}
+ }
}
- if (obj.isInterface())
+ if (obj.isInterface()) {
return;
+ }
- if (superClassName.equals("java.lang.Object") && !visited.contains(superClassName))
+ if ("java.lang.Object".equals(superClassName) && !visited.contains(superClassName)) {
try {
visitJavaClass(obj.getSuperClass());
} catch (ClassNotFoundException e) {
// ignore it
}
+ }
super.visitJavaClass(obj);
}
/**
* Determine whether the class descriptor ultimately inherits from
* java.lang.Exception
- *
+ *
* @param d
* class descriptor we want to check
* @return true iff the descriptor ultimately inherits from Exception
@@ -354,7 +383,7 @@ public class Naming extends PreorderVisitor implements Detector {
* message constants. Unfortunately these fields often has bad names which
* does not follow Java code convention, so FB reports tons of warnings for
* such Eclipse message fields.
- *
+ *
* @see edu.umd.cs.findbugs.detect.MutableStaticFields
*/
private boolean isEclipseNLS;
@@ -364,14 +393,17 @@ public class Naming extends PreorderVisitor implements Detector {
String name = obj.getClassName();
String[] parts = name.split("[$+.]");
baseClassName = parts[parts.length - 1];
- for (String p : name.split("[.]"))
- if (p.length() == 1)
+ for (String p : name.split("[.]")) {
+ if (p.length() == 1) {
return;
- if (name.indexOf("Proto$") >= 0)
+ }
+ }
+ if (name.indexOf("Proto$") >= 0) {
return;
+ }
classIsPublicOrProtected = obj.isPublic() || obj.isProtected();
if (Character.isLetter(baseClassName.charAt(0)) && !Character.isUpperCase(baseClassName.charAt(0))
- && baseClassName.indexOf("_") == -1) {
+ && baseClassName.indexOf('_') == -1) {
int priority = classIsPublicOrProtected ? NORMAL_PRIORITY : LOW_PRIORITY;
bugReporter.reportBug(new BugInstance(this, "NM_CLASS_NAMING_CONVENTION", priority).addClass(this));
@@ -385,14 +417,18 @@ public class Naming extends PreorderVisitor implements Detector {
}
int badFieldNames = 0;
- for (Field f : obj.getFields())
- if (f.getName().length() >= 2 && badFieldName(f))
+ for (Field f : obj.getFields()) {
+ if (f.getName().length() >= 2 && badFieldName(f)) {
badFieldNames++;
+ }
+ }
hasBadFieldNames = badFieldNames > 3 && badFieldNames > obj.getFields().length / 3;
int badMethodNames = 0;
- for (Method m : obj.getMethods())
- if (badMethodName(m.getName()))
+ for (Method m : obj.getMethods()) {
+ if (badMethodName(m.getName())) {
badMethodNames++;
+ }
+ }
hasBadMethodNames = badMethodNames > 3 && badMethodNames > obj.getMethods().length / 3;
isEclipseNLS = "org.eclipse.osgi.util.NLS".equals(obj.getSuperclassName());
super.visit(obj);
@@ -400,12 +436,13 @@ public class Naming extends PreorderVisitor implements Detector {
@Override
public void visit(Field obj) {
- if (getFieldName().length() == 1)
+ if (getFieldName().length() == 1) {
return;
+ }
if (isEclipseNLS) {
int flags = obj.getAccessFlags();
- if ((flags & ACC_STATIC) != 0 && ((flags & ACC_PUBLIC) != 0) && getFieldSig().equals("Ljava/lang/String;")) {
+ if ((flags & ACC_STATIC) != 0 && ((flags & ACC_PUBLIC) != 0) && "Ljava/lang/String;".equals(getFieldSig())) {
// ignore "public statis String InstallIUCommandTooltip;"
// messages from Eclipse NLS bundles
return;
@@ -414,48 +451,52 @@ public class Naming extends PreorderVisitor implements Detector {
if (badFieldName(obj)) {
bugReporter.reportBug(new BugInstance(this, "NM_FIELD_NAMING_CONVENTION", classIsPublicOrProtected
&& (obj.isPublic() || obj.isProtected()) && !hasBadFieldNames ? NORMAL_PRIORITY : LOW_PRIORITY)
- .addClass(this).addVisitedField(this));
+ .addClass(this).addVisitedField(this));
}
}
- /**
- * @param obj
- * @return
- */
private boolean badFieldName(Field obj) {
String fieldName = obj.getName();
return !obj.isFinal() && Character.isLetter(fieldName.charAt(0)) && !Character.isLowerCase(fieldName.charAt(0))
- && fieldName.indexOf("_") == -1 && Character.isLetter(fieldName.charAt(1))
+ && fieldName.indexOf('_') == -1 && Character.isLetter(fieldName.charAt(1))
&& Character.isLowerCase(fieldName.charAt(1));
}
private final static Pattern sigType = Pattern.compile("L([^;]*/)?([^/]+;)");
-
+
private static @CheckForNull
String getSignatureOfOuterClass(JavaClass obj) {
- for (Field f : obj.getFields())
- if (f.getName().startsWith("this$"))
+ for (Field f : obj.getFields()) {
+ if (f.getName().startsWith("this$")) {
return f.getSignature();
+ }
+ }
return null;
}
private boolean markedAsNotUsable(Method obj) {
- for (Attribute a : obj.getAttributes())
- if (a instanceof Deprecated)
+ for (Attribute a : obj.getAttributes()) {
+ if (a instanceof Deprecated) {
return true;
+ }
+ }
Code code = obj.getCode();
- if (code == null)
+ if (code == null) {
return false;
+ }
byte[] codeBytes = code.getCode();
if (codeBytes.length > 1 && codeBytes.length < 10) {
int lastOpcode = codeBytes[codeBytes.length - 1] & 0xff;
- if (lastOpcode != ATHROW)
+ if (lastOpcode != ATHROW) {
return false;
- for (int b : codeBytes)
- if ((b & 0xff) == RETURN)
+ }
+ for (int b : codeBytes) {
+ if ((b & 0xff) == RETURN) {
return false;
+ }
+ }
return true;
}
return false;
@@ -463,9 +504,11 @@ public class Naming extends PreorderVisitor implements Detector {
private static @CheckForNull
Method findVoidConstructor(JavaClass clazz) {
- for (Method m : clazz.getMethods())
- if (isVoidConstructor(clazz, m))
+ for (Method m : clazz.getMethods()) {
+ if (isVoidConstructor(clazz, m)) {
return m;
+ }
+ }
return null;
}
@@ -473,68 +516,83 @@ public class Naming extends PreorderVisitor implements Detector {
@Override
public void visit(Method obj) {
String mName = getMethodName();
- if (mName.length() == 1)
+ if (mName.length() == 1) {
return;
- if (mName.equals("isRequestedSessionIdFromURL") || mName.equals("isRequestedSessionIdFromUrl"))
+ }
+ if ("isRequestedSessionIdFromURL".equals(mName) || "isRequestedSessionIdFromUrl".equals(mName)) {
return;
+ }
String sig = getMethodSig();
- if (mName.equals(baseClassName) && sig.equals("()V")) {
+ if (mName.equals(baseClassName) && "()V".equals(sig)) {
Code code = obj.getCode();
Method realVoidConstructor = findVoidConstructor(getThisClass());
if (code != null && !markedAsNotUsable(obj)) {
int priority = NORMAL_PRIORITY;
- if (codeDoesSomething(code))
+ if (codeDoesSomething(code)) {
priority--;
- else if (!obj.isPublic() && getThisClass().isPublic())
+ } else if (!obj.isPublic() && getThisClass().isPublic()) {
priority--;
+ }
boolean instanceMembers = false;
- for (Method m : this.getThisClass().getMethods())
- if (!m.isStatic() && m != obj && !isVoidConstructor(getThisClass(), m))
+ for (Method m : this.getThisClass().getMethods()) {
+ if (!m.isStatic() && m != obj && !isVoidConstructor(getThisClass(), m)) {
instanceMembers = true;
- for (Field f : this.getThisClass().getFields())
- if (!f.isStatic())
+ }
+ }
+ for (Field f : this.getThisClass().getFields()) {
+ if (!f.isStatic()) {
instanceMembers = true;
- if (!codeDoesSomething(code) && !instanceMembers && getSuperclassName().equals("java/lang/Object"))
+ }
+ }
+ if (!codeDoesSomething(code) && !instanceMembers && "java/lang/Object".equals(getSuperclassName())) {
priority += 2;
- if (hasBadMethodNames)
+ }
+ if (hasBadMethodNames) {
priority++;
- if (!getXClass().getAnnotations().isEmpty())
+ }
+ if (!getXClass().getAnnotations().isEmpty()) {
priority++;
- if (realVoidConstructor != null)
+ }
+ if (realVoidConstructor != null) {
priority = LOW_PRIORITY;
+ }
bugReporter.reportBug(new BugInstance(this, "NM_METHOD_CONSTRUCTOR_CONFUSION", priority).addClassAndMethod(this)
.lowerPriorityIfDeprecated());
return;
}
- } else if (badMethodName(mName))
+ } else if (badMethodName(mName)) {
bugReporter.reportBug(new BugInstance(this, "NM_METHOD_NAMING_CONVENTION", classIsPublicOrProtected
&& (obj.isPublic() || obj.isProtected()) && !hasBadMethodNames ? NORMAL_PRIORITY : LOW_PRIORITY)
- .addClassAndMethod(this));
+ .addClassAndMethod(this));
+ }
- if (obj.isAbstract())
+ if (obj.isAbstract()) {
return;
- if (obj.isPrivate())
+ }
+ if (obj.isPrivate()) {
return;
+ }
- if (mName.equals("equal") && sig.equals("(Ljava/lang/Object;)Z")) {
+ if ("equal".equals(mName) && "(Ljava/lang/Object;)Z".equals(sig)) {
bugReporter.reportBug(new BugInstance(this, "NM_BAD_EQUAL", HIGH_PRIORITY).addClassAndMethod(this)
.lowerPriorityIfDeprecated());
return;
}
- if (mName.equals("hashcode") && sig.equals("()I")) {
+ if ("hashcode".equals(mName) && "()I".equals(sig)) {
bugReporter.reportBug(new BugInstance(this, "NM_LCASE_HASHCODE", HIGH_PRIORITY).addClassAndMethod(this)
.lowerPriorityIfDeprecated());
return;
}
- if (mName.equals("tostring") && sig.equals("()Ljava/lang/String;")) {
+ if ("tostring".equals(mName) && "()Ljava/lang/String;".equals(sig)) {
bugReporter.reportBug(new BugInstance(this, "NM_LCASE_TOSTRING", HIGH_PRIORITY).addClassAndMethod(this)
.lowerPriorityIfDeprecated());
return;
}
- if (obj.isPrivate() || obj.isStatic() || mName.equals("<init>"))
+ if (obj.isPrivate() || obj.isStatic() || "<init>".equals(mName)) {
return;
+ }
String sig2 = removePackageNamesFromSignature(sig);
String allSmall = mName.toLowerCase() + sig2;
@@ -553,18 +611,15 @@ public class Naming extends PreorderVisitor implements Detector {
private static boolean isVoidConstructor(JavaClass clazz, Method m) {
String outerClassSignature = getSignatureOfOuterClass(clazz);
- if (outerClassSignature == null)
+ if (outerClassSignature == null) {
outerClassSignature = "";
- return m.getName().equals("<init>") && m.getSignature().equals("(" + outerClassSignature + ")V");
+ }
+ return "<init>".equals(m.getName()) && m.getSignature().equals("(" + outerClassSignature + ")V");
}
- /**
- * @param mName
- * @return
- */
private boolean badMethodName(String mName) {
return mName.length() >= 2 && Character.isLetter(mName.charAt(0)) && !Character.isLowerCase(mName.charAt(0))
- && Character.isLetter(mName.charAt(1)) && Character.isLowerCase(mName.charAt(1)) && mName.indexOf("_") == -1;
+ && Character.isLetter(mName.charAt(1)) && Character.isLowerCase(mName.charAt(1)) && mName.indexOf('_') == -1;
}
private boolean codeDoesSomething(Code code) {
@@ -573,7 +628,7 @@ public class Naming extends PreorderVisitor implements Detector {
}
private static String removePackageNamesFromSignature(String sig) {
- int end = sig.indexOf(")");
+ int end = sig.indexOf(')');
Matcher m = sigType.matcher(sig.substring(0, end));
return m.replaceAll("L$2") + sig.substring(end);
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/Noise.java b/src/java/edu/umd/cs/findbugs/detect/Noise.java
index d3b19c3..39002b1 100644
--- a/src/java/edu/umd/cs/findbugs/detect/Noise.java
+++ b/src/java/edu/umd/cs/findbugs/detect/Noise.java
@@ -51,19 +51,22 @@ public class Noise extends OpcodeStackDetector {
// data is next..size-1, 0..next-1
public void push(byte b) {
data[next++] = b;
- if (next == size)
+ if (next == size) {
next = 0;
+ }
}
public void reset() {
next = 0;
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < size; i++) {
data[i] = 0;
+ }
}
public void push(String s) {
- for (byte b : UTF8.getBytes(s))
+ for (byte b : UTF8.getBytes(s)) {
push(b);
+ }
}
public void pushHash(Object x) {
@@ -91,20 +94,22 @@ public class Noise extends OpcodeStackDetector {
if ((hash & 0x1ff0) == 0) {
hash = hash & 0xf;
- if (hash < 1)
+ if (hash < 1) {
return Priorities.HIGH_PRIORITY;
- else if (hash < 1 + 2)
+ } else if (hash < 1 + 2) {
return Priorities.NORMAL_PRIORITY;
- else if (hash < 1 + 2 + 4)
+ } else if (hash < 1 + 2 + 4) {
return Priorities.LOW_PRIORITY;
- else
+ } else {
return Priorities.IGNORE_PRIORITY;
- } else
+ }
+ } else {
return Priorities.IGNORE_PRIORITY + 1;
+ }
}
}
- final BugReporter bugReporter;
+ // final BugReporter bugReporter;
final BugAccumulator accumulator;
@@ -113,7 +118,7 @@ public class Noise extends OpcodeStackDetector {
byte[] primer;
public Noise(BugReporter bugReporter) throws NoSuchAlgorithmException {
- this.bugReporter = bugReporter;
+ // this.bugReporter = bugReporter;
this.accumulator = new BugAccumulator(bugReporter);
hq = new HashQueue(24);
}
@@ -147,12 +152,6 @@ public class Noise extends OpcodeStackDetector {
hq.push(getClassConstantOperand());
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.bcel.OpcodeStackDetector#sawOpcode(int)
- */
-
@Override
public void sawOpcode(int seen) {
int priority;
@@ -162,28 +161,31 @@ public class Noise extends OpcodeStackDetector {
case INVOKESPECIAL:
case INVOKESTATIC:
hq.pushHash(getClassConstantOperand());
- if (getNameConstantOperand().indexOf('$') == -1)
+ if (getNameConstantOperand().indexOf('$') == -1) {
hq.pushHash(getNameConstantOperand());
+ }
hq.pushHash(getSigConstantOperand());
priority = hq.getPriority();
- if (priority <= Priorities.LOW_PRIORITY)
+ if (priority <= Priorities.LOW_PRIORITY) {
accumulator.accumulateBug(new BugInstance(this, "NOISE_METHOD_CALL", priority).addClassAndMethod(this)
.addCalledMethod(this), this);
-
+ }
break;
case GETFIELD:
case PUTFIELD:
case GETSTATIC:
case PUTSTATIC:
hq.pushHash(getClassConstantOperand());
- if (getNameConstantOperand().indexOf('$') == -1)
+ if (getNameConstantOperand().indexOf('$') == -1) {
hq.pushHash(getNameConstantOperand());
+ }
hq.pushHash(getSigConstantOperand());
priority = hq.getPriority();
- if (priority <= Priorities.LOW_PRIORITY)
+ if (priority <= Priorities.LOW_PRIORITY) {
accumulator.accumulateBug(new BugInstance(this, "NOISE_FIELD_REFERENCE", priority).addClassAndMethod(this)
.addReferencedField(this), this);
+ }
break;
case CHECKCAST:
case INSTANCEOF:
@@ -241,10 +243,14 @@ public class Noise extends OpcodeStackDetector {
case BASTORE:
hq.push(seen);
priority = hq.getPriority();
- if (priority <= Priorities.LOW_PRIORITY)
+ if (priority <= Priorities.LOW_PRIORITY) {
accumulator.accumulateBug(
new BugInstance(this, "NOISE_OPERATION", priority).addClassAndMethod(this).addString(OPCODE_NAMES[seen]),
this);
+ }
+ break;
+ default:
+ break;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/NoiseNullDeref.java b/src/java/edu/umd/cs/findbugs/detect/NoiseNullDeref.java
index 0dc3418..5ba8c37 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NoiseNullDeref.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NoiseNullDeref.java
@@ -90,7 +90,7 @@ import edu.umd.cs.findbugs.visitclass.Util;
* A Detector to find instructions where a NullPointerException might be raised.
* We also look for useless reference comparisons involving null and non-null
* values.
- *
+ *
* @author David Hovemeyer
* @author William Pugh
* @see edu.umd.cs.findbugs.ba.npe.IsNullValueAnalysis
@@ -101,7 +101,7 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
private static final boolean DEBUG_NULLARG = SystemProperties.getBoolean("fnd.debug.nullarg");
- private static final boolean DEBUG_NULLRETURN = SystemProperties.getBoolean("fnd.debug.nullreturn");
+ // private static final boolean DEBUG_NULLRETURN = SystemProperties.getBoolean("fnd.debug.nullreturn");
private static final boolean MARK_DOOMED = SystemProperties.getBoolean("fnd.markdoomed", true);
@@ -126,6 +126,7 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
this.bugAccumulator = new BugAccumulator(bugReporter);
}
+ @Override
public void visitClassContext(ClassContext classContext) {
this.classContext = classContext;
@@ -134,22 +135,27 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
JavaClass jclass = classContext.getJavaClass();
String className = jclass.getClassName();
String superClassName = jclass.getSuperclassName();
- if (superClassName.endsWith("ProtocolMessage"))
+ if (superClassName.endsWith("ProtocolMessage")) {
return;
- if (CLASS != null && !className.equals(CLASS))
+ }
+ if (CLASS != null && !className.equals(CLASS)) {
return;
+ }
Method[] methodList = jclass.getMethods();
for (Method method : methodList) {
try {
- if (method.isAbstract() || method.isNative() || method.getCode() == null)
+ if (method.isAbstract() || method.isNative() || method.getCode() == null) {
continue;
+ }
currentMethod = SignatureConverter.convertMethodSignature(jclass, method);
- if (METHOD != null && !method.getName().equals(METHOD))
+ if (METHOD != null && !method.getName().equals(METHOD)) {
continue;
- if (DEBUG || DEBUG_NULLARG)
+ }
+ if (DEBUG || DEBUG_NULLARG) {
System.out.println("Checking for NP in " + currentMethod);
+ }
analyzeMethod(classContext, method);
} catch (MissingClassException e) {
bugReporter.reportMissingClass(e.getClassNotFoundException());
@@ -162,22 +168,23 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
}
}
- private void analyzeMethod(ClassContext classContext, Method method) throws DataflowAnalysisException, CFGBuilderException
-
- {
- if (DEBUG || DEBUG_NULLARG)
+ private void analyzeMethod(ClassContext classContext, Method method) throws DataflowAnalysisException, CFGBuilderException {
+ if (DEBUG || DEBUG_NULLARG) {
System.out.println("Pre FND ");
+ }
MethodGen methodGen = classContext.getMethodGen(method);
- if (methodGen == null)
+ if (methodGen == null) {
return;
+ }
// UsagesRequiringNonNullValues uses =
// classContext.getUsagesRequiringNonNullValues(method);
this.method = method;
- if (DEBUG || DEBUG_NULLARG)
+ if (DEBUG || DEBUG_NULLARG) {
System.out.println("FND: " + SignatureConverter.convertMethodSignature(methodGen));
+ }
findPreviouslyDeadBlocks();
@@ -197,7 +204,7 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
/**
* Find set of blocks which were known to be dead before doing the null
* pointer analysis.
- *
+ *
* @return set of previously dead blocks, indexed by block id
* @throws CFGBuilderException
* @throws DataflowAnalysisException
@@ -219,6 +226,7 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
static class CheckCallSitesAndReturnInstructions {
}
+ @Override
public void report() {
}
@@ -232,18 +240,22 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
* {@link #foundNullDeref(Location,ValueNumber,IsNullValue,ValueNumberFrame,boolean)}
* instead
*/
+ @Override
@Deprecated
public void foundNullDeref(Location location, ValueNumber valueNumber, IsNullValue refValue, ValueNumberFrame vnaFrame) {
foundNullDeref(location, valueNumber, refValue, vnaFrame, true);
}
+ @Override
public void foundNullDeref(Location location, ValueNumber valueNumber, IsNullValue refValue, ValueNumberFrame vnaFrame,
boolean isConsistent) {
- if (!refValue.isNullOnComplicatedPath23())
+ if (!refValue.isNullOnComplicatedPath23()) {
return;
+ }
WarningPropertySet<WarningProperty> propertySet = new WarningPropertySet<WarningProperty>();
- if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))
+ if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
return;
+ }
boolean onExceptionPath = refValue.isException();
if (onExceptionPath) {
@@ -262,8 +274,9 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
cause = MethodAnnotation.fromXMethod(invokedMethod);
cause.setDescription(MethodAnnotation.METHOD_CALLED);
- if (iins.getMethodName(cpg).equals("close") && iins.getSignature(cpg).equals("()V"))
+ if ("close".equals(iins.getMethodName(cpg)) && "()V".equals(iins.getSignature(cpg))) {
propertySet.addProperty(NullDerefProperty.CLOSING_NULL);
+ }
} else if (ins instanceof FieldInstruction) {
FieldInstruction fins = (FieldInstruction) ins;
XField referencedField = XFactory.createXField(fins, cpg);
@@ -274,13 +287,15 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
}
boolean caught = inCatchNullBlock(location);
- if (caught && skipIfInsideCatchNull())
+ if (caught && skipIfInsideCatchNull()) {
return;
+ }
int basePriority = Priorities.NORMAL_PRIORITY;
- if (!refValue.isNullOnComplicatedPath2())
+ if (!refValue.isNullOnComplicatedPath2()) {
basePriority--;
+ }
reportNullDeref(propertySet, location, "NOISE_NULL_DEREFERENCE", basePriority, cause, variable);
}
@@ -290,10 +305,11 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
BugInstance bugInstance = new BugInstance(this, type, priority).addClassAndMethod(classContext.getJavaClass(), method);
bugInstance.add(cause);
- if (variable != null)
+ if (variable != null) {
bugInstance.add(variable);
- else
+ } else {
bugInstance.add(new LocalVariableAnnotation("?", -1, -1));
+ }
bugInstance.addSourceLine(classContext, method, location).describe("SOURCE_LINE_DEREF");
if (FindBugsAnalysisFeatures.isRelaxedMode()) {
@@ -310,49 +326,44 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
InstructionHandle ins = target.getFirstInstruction();
int maxCount = 7;
while (ins != null) {
- if (maxCount-- <= 0)
+ if (maxCount-- <= 0) {
break;
+ }
Instruction i = ins.getInstruction();
if (i instanceof ATHROW) {
return true;
}
- if (i instanceof InstructionTargeter || i instanceof ReturnInstruction)
+ if (i instanceof InstructionTargeter || i instanceof ReturnInstruction) {
return false;
+ }
ins = ins.getNext();
}
return false;
}
+ @Override
public void foundRedundantNullCheck(Location location, RedundantBranch redundantBranch) {
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.npe.NullDerefAndRedundantComparisonCollector#
- * foundGuaranteedNullDeref(java.util.Set, java.util.Set,
- * edu.umd.cs.findbugs.ba.vna.ValueNumber, boolean)
- */
+ @Override
public void foundGuaranteedNullDeref(@Nonnull Set<Location> assignedNullLocationSet, @Nonnull Set<Location> derefLocationSet,
SortedSet<Location> doomedLocations, ValueNumberDataflow vna, ValueNumber refValue,
@CheckForNull BugAnnotation variableAnnotation, NullValueUnconditionalDeref deref, boolean npeIfStatementCovered) {
}
- /**
- * @param propertySet
- * @param derefLocationSet
- */
private void addPropertiesForDereferenceLocations(WarningPropertySet<WarningProperty> propertySet,
Collection<Location> derefLocationSet) {
boolean derefOutsideCatchBlock = false;
boolean allDerefsAtDoomedLocations = true;
for (Location loc : derefLocationSet) {
- if (!inCatchNullBlock(loc))
+ if (!inCatchNullBlock(loc)) {
derefOutsideCatchBlock = true;
+ }
- if (!isDoomed(loc))
+ if (!isDoomed(loc)) {
allDerefsAtDoomedLocations = false;
+ }
}
if (allDerefsAtDoomedLocations) {
@@ -362,49 +373,45 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
boolean uniqueDereferenceLocations = uniqueLocations(derefLocationSet);
if (!derefOutsideCatchBlock) {
- if (!uniqueDereferenceLocations || skipIfInsideCatchNull())
+ if (!uniqueDereferenceLocations || skipIfInsideCatchNull()) {
propertySet.addProperty(GeneralWarningProperty.FALSE_POSITIVE);
- else
+ } else {
propertySet.addProperty(NullDerefProperty.DEREFS_IN_CATCH_BLOCKS);
+ }
}
- if (!uniqueDereferenceLocations)
+ if (!uniqueDereferenceLocations) {
// Add a WarningProperty
propertySet.addProperty(NullDerefProperty.DEREFS_ARE_CLONED);
+ }
addPropertiesForMethodContainingWarning(propertySet);
}
- /**
- * @param derefLocationSet
- * @return
- */
private boolean uniqueLocations(Collection<Location> derefLocationSet) {
boolean uniqueDereferenceLocations = false;
LineNumberTable table = method.getLineNumberTable();
- if (table == null)
+ if (table == null) {
uniqueDereferenceLocations = true;
- else {
+ } else {
BitSet linesMentionedMultipleTimes = classContext.linesMentionedMultipleTimes(method);
for (Location loc : derefLocationSet) {
int lineNumber = table.getSourceLine(loc.getHandle().getPosition());
- if (!linesMentionedMultipleTimes.get(lineNumber))
+ if (!linesMentionedMultipleTimes.get(lineNumber)) {
uniqueDereferenceLocations = true;
+ }
}
}
return uniqueDereferenceLocations;
}
- /**
- * @param propertySet
- * @param xMethod
- */
private void addPropertiesForMethodContainingWarning(WarningPropertySet<WarningProperty> propertySet) {
XMethod xMethod = XFactory.createXMethod(classContext.getJavaClass(), method);
boolean uncallable = !AnalysisContext.currentXFactory().isCalledDirectlyOrIndirectly(xMethod) && xMethod.isPrivate();
- if (uncallable)
+ if (uncallable) {
propertySet.addProperty(GeneralWarningProperty.IN_UNCALLABLE_METHOD);
+ }
}
private boolean isDoomed(Location loc) {
@@ -430,8 +437,9 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
try {
UsagesRequiringNonNullValues usages = classContext.getUsagesRequiringNonNullValues(method);
pu = usages.get(loc, refValue, vnaDataflow);
- if (pu == null)
+ if (pu == null) {
return "SOURCE_LINE_DEREF";
+ }
return pu.getDescription();
} catch (DataflowAnalysisException e) {
AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);
@@ -447,23 +455,25 @@ public class NoiseNullDeref implements Detector, UseAnnotationDatabase, NullDere
int pc = loc.getHandle().getPosition();
int catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),
"java/lang/NullPointerException", pc);
- if (catchSize < Integer.MAX_VALUE)
+ if (catchSize < Integer.MAX_VALUE) {
return true;
+ }
catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),
"java/lang/Exception", pc);
- if (catchSize < 5)
+ if (catchSize < 5) {
return true;
+ }
catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),
"java/lang/RuntimeException", pc);
- if (catchSize < 5)
+ if (catchSize < 5) {
return true;
+ }
catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),
"java/lang/Throwable", pc);
- if (catchSize < 5)
+ if (catchSize < 5) {
return true;
+ }
return false;
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/NoteAnnotationRetention.java b/src/java/edu/umd/cs/findbugs/detect/NoteAnnotationRetention.java
index 424f395..7034376 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NoteAnnotationRetention.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NoteAnnotationRetention.java
@@ -44,12 +44,14 @@ public class NoteAnnotationRetention extends AnnotationVisitor implements Detect
@Override
public void visitAnnotation(String annotationClass, Map<String, ElementValue> map, boolean runtimeVisible) {
- if (!annotationClass.equals("java.lang.annotation.Retention"))
+ if (!"java.lang.annotation.Retention".equals(annotationClass)) {
return;
+ }
EnumElementValue v = (EnumElementValue) map.get("value");
- if ("RUNTIME".equals(v.getEnumValueString()))
+ if ("RUNTIME".equals(v.getEnumValueString())) {
runtimeRetention = true;
+ }
}
@Override
@@ -59,20 +61,25 @@ public class NoteAnnotationRetention extends AnnotationVisitor implements Detect
@Override
public void visitAfter(JavaClass obj) {
- for (String i : obj.getInterfaceNames())
- if (i.equals("java.lang.annotation.Annotation"))
+ for (String i : obj.getInterfaceNames()) {
+ if ("java.lang.annotation.Annotation".equals(i)) {
AnalysisContext.currentAnalysisContext().getAnnotationRetentionDatabase()
- .setRuntimeRetention(getDottedClassName(), runtimeRetention);
+ .setRuntimeRetention(getDottedClassName(), runtimeRetention);
+ }
+ }
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
- if (!BCELUtil.preTiger(javaClass))
+ if (!BCELUtil.preTiger(javaClass)) {
javaClass.accept(this);
+ }
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/NoteCheckReturnValueAnnotations.java b/src/java/edu/umd/cs/findbugs/detect/NoteCheckReturnValueAnnotations.java
index 9a3a8e7..3911741 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NoteCheckReturnValueAnnotations.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NoteCheckReturnValueAnnotations.java
@@ -35,13 +35,16 @@ public class NoteCheckReturnValueAnnotations extends BuildCheckReturnAnnotationD
public NoteCheckReturnValueAnnotations(BugReporter bugReporter) {
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
- if (!BCELUtil.preTiger(javaClass))
+ if (!BCELUtil.preTiger(javaClass)) {
javaClass.accept(this);
+ }
}
+ @Override
public void report() {
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/NoteDirectlyRelevantTypeQualifiers.java b/src/java/edu/umd/cs/findbugs/detect/NoteDirectlyRelevantTypeQualifiers.java
index 7f32a80..20c5c75 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NoteDirectlyRelevantTypeQualifiers.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NoteDirectlyRelevantTypeQualifiers.java
@@ -53,6 +53,7 @@ public class NoteDirectlyRelevantTypeQualifiers extends DismantleBytecode implem
public NoteDirectlyRelevantTypeQualifiers(BugReporter bugReporter) {
}
+ @Override
public void visitClassContext(ClassContext classContext) {
if (qualifiers == null) {
qualifiers = AnalysisContext.currentAnalysisContext().getDirectlyRelevantTypeQualifiersDatabase();
@@ -97,9 +98,10 @@ public class NoteDirectlyRelevantTypeQualifiers extends DismantleBytecode implem
// stemming from called methods.
if (!Analysis.FIND_EFFECTIVE_RELEVANT_QUALIFIERS) {
- XMethod m = getXMethodOperand();
- if (m != null)
- updateApplicableAnnotations(m);
+ XMethod m = getXMethodOperand();
+ if (m != null) {
+ updateApplicableAnnotations(m);
+ }
}
break;
@@ -115,6 +117,8 @@ public class NoteDirectlyRelevantTypeQualifiers extends DismantleBytecode implem
break;
}
+ default:
+ break;
}
}
@@ -127,6 +131,7 @@ public class NoteDirectlyRelevantTypeQualifiers extends DismantleBytecode implem
Analysis.addKnownTypeQualifiersForParameters(applicableApplications, m);
}
+ @Override
public void report() {
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/NoteJCIPAnnotation.java b/src/java/edu/umd/cs/findbugs/detect/NoteJCIPAnnotation.java
index 784f083..41ef20a 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NoteJCIPAnnotation.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NoteJCIPAnnotation.java
@@ -54,7 +54,7 @@ public class NoteJCIPAnnotation extends AnnotationVisitor implements Detector, N
return;
}
JCIPAnnotationDatabase annotationDatabase = AnalysisContext.currentAnalysisContext()
- .getJCIPAnnotationDatabase();
+ .getJCIPAnnotationDatabase();
ElementValue value = map.get("value");
ClassMember member;
if (visitingField()) {
@@ -68,6 +68,7 @@ public class NoteJCIPAnnotation extends AnnotationVisitor implements Detector, N
annotationDatabase.addEntryForClassMember(member, annotationClass, value);
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
if (!BCELUtil.preTiger(javaClass)) {
@@ -76,6 +77,7 @@ public class NoteJCIPAnnotation extends AnnotationVisitor implements Detector, N
}
+ @Override
public void report() {
// noop
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/NoteNonNullAnnotations.java b/src/java/edu/umd/cs/findbugs/detect/NoteNonNullAnnotations.java
index d5a8b92..796f314 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NoteNonNullAnnotations.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NoteNonNullAnnotations.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.bcel.BCELUtil;
/**
* Scan classes for @NonNull, @PossiblyNull and @CheckForNull annotations, and
* convey them to FindNullDeref.
- *
+ *
* @deprecated AnnotationDatabases are being phased out, since annotations are
* now stored directly in the XClass/XMethod/XField objects.
* Resolving nullness annotations will be handled through the
@@ -44,20 +44,20 @@ public class NoteNonNullAnnotations extends BuildNonNullAnnotationDatabase imple
super(getDatabase());
}
- /**
- * @return
- */
private static NullnessAnnotationDatabase getDatabase() {
return null;
- }
+ }
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
- if (!BCELUtil.preTiger(javaClass))
+ if (!BCELUtil.preTiger(javaClass)) {
javaClass.accept(this);
+ }
}
+ @Override
public void report() {
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/NoteNonnullReturnValues.java b/src/java/edu/umd/cs/findbugs/detect/NoteNonnullReturnValues.java
index bc91d84..6e1db53 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NoteNonnullReturnValues.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NoteNonnullReturnValues.java
@@ -28,23 +28,25 @@ import edu.umd.cs.findbugs.SystemProperties;
/**
* As a first scanning pass, make a note of unconditionally dereferenced
* parameters for later use by FindNullDerefs.
- *
+ *
* @author David Hovemeyer
*/
public class NoteNonnullReturnValues extends BuildNonnullReturnDatabase implements Detector, NonReportingDetector,
- InterproceduralFirstPassDetector {
+InterproceduralFirstPassDetector {
public NoteNonnullReturnValues(BugReporter bugReporter) {
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector#report()
*/
+ @Override
public void report() {
- if (SystemProperties.getBoolean("findbugs.statistics"))
+ if (SystemProperties.getBoolean("findbugs.statistics")) {
System.err.println(returnsNonNull + "/" + returnsReference + " methods return nonnull values");
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/NoteSuppressedWarnings.java b/src/java/edu/umd/cs/findbugs/detect/NoteSuppressedWarnings.java
index 1609c01..ebfa85d 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NoteSuppressedWarnings.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NoteSuppressedWarnings.java
@@ -55,6 +55,7 @@ public class NoteSuppressedWarnings extends AnnotationVisitor implements Detecto
suppressionMatcher = AnalysisContext.currentAnalysisContext().getSuppressionMatcher();
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass javaClass = classContext.getJavaClass();
if (!BCELUtil.preTiger(javaClass)) {
@@ -63,8 +64,9 @@ public class NoteSuppressedWarnings extends AnnotationVisitor implements Detecto
int i = name.lastIndexOf('.');
String packageName = i < 0 ? "" : name.substring(0, i);
if (name.endsWith(".package-info")) {
- if (!packages.add(packageName))
+ if (!packages.add(packageName)) {
return;
+ }
} else if (packages.add(packageName)) {
JavaClass packageInfoClass;
try {
@@ -80,20 +82,19 @@ public class NoteSuppressedWarnings extends AnnotationVisitor implements Detecto
@Override
public void visitAnnotation(String annotationClass, Map<String, ElementValue> map, boolean runtimeVisible) {
- if (!isSuppressWarnings(annotationClass))
+ if (!isSuppressWarnings(annotationClass)) {
return;
+ }
String[] suppressed = getAnnotationParameterAsStringArray(map, "value");
- if (suppressed == null || suppressed.length == 0)
+ if (suppressed == null || suppressed.length == 0) {
suppressWarning(null);
- else
- for (String s : suppressed)
+ } else {
+ for (String s : suppressed) {
suppressWarning(s);
+ }
+ }
}
- /**
- * @param annotationClass
- * @return
- */
public boolean isSuppressWarnings(String annotationClass) {
return annotationClass.endsWith("SuppressWarnings")
|| annotationClass.endsWith("SuppressFBWarnings");
@@ -101,17 +102,21 @@ public class NoteSuppressedWarnings extends AnnotationVisitor implements Detecto
@Override
public void visitParameterAnnotation(int p, String annotationClass, Map<String, ElementValue> map, boolean runtimeVisible) {
- if (!isSuppressWarnings(annotationClass))
+ if (!isSuppressWarnings(annotationClass)) {
return;
- if (!getMethod().isStatic())
+ }
+ if (!getMethod().isStatic()) {
p++;
+ }
String[] suppressed = getAnnotationParameterAsStringArray(map, "value");
- if (suppressed == null || suppressed.length == 0)
+ if (suppressed == null || suppressed.length == 0) {
suppressWarning(p, null);
- else
- for (String s : suppressed)
+ } else {
+ for (String s : suppressed) {
suppressWarning(p, s);
+ }
+ }
}
private void suppressWarning(int parameter, String pattern) {
@@ -125,17 +130,19 @@ public class NoteSuppressedWarnings extends AnnotationVisitor implements Detecto
private void suppressWarning(String pattern) {
String className = getDottedClassName();
ClassAnnotation clazz = new ClassAnnotation(className);
- if (className.endsWith(".package-info"))
+ if (className.endsWith(".package-info")) {
suppressionMatcher.addPackageSuppressor(new PackageWarningSuppressor(pattern, getPackageName().replace('/', '.')));
- else if (visitingMethod())
+ } else if (visitingMethod()) {
suppressionMatcher
- .addSuppressor(new MethodWarningSuppressor(pattern, clazz, MethodAnnotation.fromVisitedMethod(this)));
- else if (visitingField())
+ .addSuppressor(new MethodWarningSuppressor(pattern, clazz, MethodAnnotation.fromVisitedMethod(this)));
+ } else if (visitingField()) {
suppressionMatcher.addSuppressor(new FieldWarningSuppressor(pattern, clazz, FieldAnnotation.fromVisitedField(this)));
- else
+ } else {
suppressionMatcher.addSuppressor(new ClassWarningSuppressor(pattern, clazz));
+ }
}
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/NoteUnconditionalParamDerefs.java b/src/java/edu/umd/cs/findbugs/detect/NoteUnconditionalParamDerefs.java
index 9f797ba..d540dd6 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NoteUnconditionalParamDerefs.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NoteUnconditionalParamDerefs.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.NonReportingDetector;
* @author David Hovemeyer
*/
public class NoteUnconditionalParamDerefs extends BuildUnconditionalParamDerefDatabase implements NonReportingDetector,
- InterproceduralFirstPassDetector {
+InterproceduralFirstPassDetector {
final BugReporter reporter;
@@ -44,6 +44,7 @@ public class NoteUnconditionalParamDerefs extends BuildUnconditionalParamDerefDa
*
* @see edu.umd.cs.findbugs.Detector#report()
*/
+ @Override
public void report() {
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/NullArgumentWarningProperty.java b/src/java/edu/umd/cs/findbugs/detect/NullArgumentWarningProperty.java
index a61af11..1dea314 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NullArgumentWarningProperty.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NullArgumentWarningProperty.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.props.PriorityAdjustment;
/**
* Warning property for a null argument being passed to a method which might
* dereference it.
- *
+ *
* @author David Hovemeyer
*/
public class NullArgumentWarningProperty extends AbstractWarningProperty {
diff --git a/src/java/edu/umd/cs/findbugs/detect/NumberConstructor.java b/src/java/edu/umd/cs/findbugs/detect/NumberConstructor.java
index 7caea1f..7024e4e 100644
--- a/src/java/edu/umd/cs/findbugs/detect/NumberConstructor.java
+++ b/src/java/edu/umd/cs/findbugs/detect/NumberConstructor.java
@@ -19,7 +19,9 @@
package edu.umd.cs.findbugs.detect;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
@@ -30,11 +32,9 @@ import edu.umd.cs.findbugs.BugAccumulator;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.ba.ClassContext;
-import edu.umd.cs.findbugs.ba.XFactory;
-import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
-import edu.umd.cs.findbugs.util.ClassName;
/**
* Detector to find calls to Number constructors with base type argument in Java
@@ -56,15 +56,17 @@ import edu.umd.cs.findbugs.util.ClassName;
public class NumberConstructor extends OpcodeStackDetector {
static class Pair {
- final XMethod boxingMethod;
- public Pair(XMethod boxingMethod, XMethod parsingMethod) {
+ final MethodDescriptor boxingMethod;
+ final MethodDescriptor parsingMethod;
+ public Pair(MethodDescriptor boxingMethod, MethodDescriptor parsingMethod) {
this.boxingMethod = boxingMethod;
this.parsingMethod = parsingMethod;
}
- final XMethod parsingMethod;
}
private final Map<String, Pair> boxClasses = new HashMap<String, Pair>();
+ private final List<MethodDescriptor> methods = new ArrayList<>();
+
private final BugAccumulator bugAccumulator;
/**
@@ -86,9 +88,11 @@ public class NumberConstructor extends OpcodeStackDetector {
}
private void handle(@SlashedClassName String className, boolean isFloatingPoint, String sig) {
- XMethod boxingMethod = XFactory.createXMethod(ClassName.toDottedClassName(className), "valueOf", sig + "L" + className +";", true);
- XMethod parsingMethod = XFactory.createXMethod(ClassName.toDottedClassName(className), "valueOf", "(Ljava/lang/String;)" + "L" + className +";", true);
+ MethodDescriptor boxingMethod = new MethodDescriptor(className, "valueOf", sig + "L" + className +";", true);
+ MethodDescriptor parsingMethod = new MethodDescriptor(className, "valueOf", "(Ljava/lang/String;)" + "L" + className +";", true);
boxClasses.put(className, new Pair(boxingMethod, parsingMethod));
+ methods.add(new MethodDescriptor(className, "<init>", "(Ljava/lang/String;)V"));
+ methods.add(new MethodDescriptor(className, "<init>", sig+"V"));
}
/**
@@ -100,7 +104,7 @@ public class NumberConstructor extends OpcodeStackDetector {
@Override
public void visitClassContext(ClassContext classContext) {
int majorVersion = classContext.getJavaClass().getMajor();
- if (majorVersion >= MAJOR_1_5) {
+ if (majorVersion >= MAJOR_1_5 && hasInterestingMethod(classContext.getJavaClass().getConstantPool(), methods)) {
super.visitClassContext(classContext);
}
}
@@ -116,25 +120,28 @@ public class NumberConstructor extends OpcodeStackDetector {
String args = sig1.substring(0, lastParen+1);
return sig2.startsWith(args);
}
-
- private @CheckForNull XMethod getShouldCall() {
+
+ private @CheckForNull MethodDescriptor getShouldCall() {
String cls = getClassConstantOperand();
Pair pair = boxClasses.get(cls);
- if (pair == null)
+ if (pair == null) {
return null;
- XMethod shouldCall ;
- if (getSigConstantOperand().startsWith("(Ljava/lang/String;)"))
+ }
+ MethodDescriptor shouldCall;
+ if (getSigConstantOperand().startsWith("(Ljava/lang/String;)")) {
shouldCall = pair.parsingMethod;
- else
+ } else {
shouldCall = pair.boxingMethod;
-
+ }
+
if (shouldCall == null) {
return null;
}
- if (matchArguments(getSigConstantOperand(), shouldCall.getSignature()))
+ if (matchArguments(getSigConstantOperand(), shouldCall.getSignature())) {
return shouldCall;
-
+ }
+
return null;
}
@Override
@@ -148,13 +155,14 @@ public class NumberConstructor extends OpcodeStackDetector {
return;
}
@SlashedClassName String cls = getClassConstantOperand();
- XMethod shouldCall = getShouldCall();
- if (shouldCall == null)
+ MethodDescriptor shouldCall = getShouldCall();
+ if (shouldCall == null) {
return;
+ }
int prio;
String type;
- if (cls.equals("java/lang/Float") || cls.equals("java/lang/Double")) {
+ if ("java/lang/Float".equals(cls) || "java/lang/Double".equals(cls)) {
prio = LOW_PRIORITY;
type = "DM_FP_NUMBER_CTOR";
} else {
@@ -162,8 +170,9 @@ public class NumberConstructor extends OpcodeStackDetector {
Object constantValue = stack.getStackItem(0).getConstant();
if (constantValue instanceof Number) {
long value = ((Number) constantValue).longValue();
- if (value < -128 || value > 127)
+ if (value < -128 || value > 127) {
prio = LOW_PRIORITY;
+ }
}
type = "DM_NUMBER_CTOR";
}
diff --git a/src/java/edu/umd/cs/findbugs/bugReporter/MaxRankDecorator.java b/src/java/edu/umd/cs/findbugs/detect/OptionalReturnNull.java
similarity index 55%
copy from src/java/edu/umd/cs/findbugs/bugReporter/MaxRankDecorator.java
copy to src/java/edu/umd/cs/findbugs/detect/OptionalReturnNull.java
index df80acf..3972d8c 100644
--- a/src/java/edu/umd/cs/findbugs/bugReporter/MaxRankDecorator.java
+++ b/src/java/edu/umd/cs/findbugs/detect/OptionalReturnNull.java
@@ -1,6 +1,6 @@
/*
* FindBugs - Find Bugs in Java programs
- * Copyright (C) 2003-2008 University of Maryland
+ * Copyright (C) 2003-2007 University of Maryland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,33 +16,33 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-
-package edu.umd.cs.findbugs.bugReporter;
-
-import javax.annotation.Nonnull;
+package edu.umd.cs.findbugs.detect;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
-import edu.umd.cs.findbugs.ComponentPlugin;
/**
- * @author pugh
+ * Methods with "Optional" return type should never return null.
+ *
+ * @author Andrey Loskutov
*/
-public class MaxRankDecorator extends BugReporterDecorator {
-
- final int maxRank;
+public class OptionalReturnNull extends TypeReturnNull {
- public MaxRankDecorator(ComponentPlugin<BugReporterDecorator> plugin, BugReporter delegate) {
- super(plugin, delegate);
- maxRank = Integer.parseInt(plugin.getProperties().getProperty("maxRank"));
+ public OptionalReturnNull(BugReporter bugReporter) {
+ super(bugReporter);
}
@Override
- public void reportBug(@Nonnull BugInstance bugInstance) {
- int rank = bugInstance.getBugRank();
- if (rank <= maxRank)
- getDelegate().reportBug(bugInstance);
+ protected boolean matchesReturnSignature(String returnSignature) {
+ return "Ljava/util/Optional;".equals(returnSignature)
+ || "Lcom/google/common/base/Optional;".equals(returnSignature);
+ }
+ @Override
+ protected void accumulateBug() {
+ bugAccumulator.accumulateBug(new BugInstance(this, "NP_OPTIONAL_RETURN_NULL",
+ HIGH_PRIORITY).addClassAndMethod(this), this);
}
+
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/OverridingEqualsNotSymmetrical.java b/src/java/edu/umd/cs/findbugs/detect/OverridingEqualsNotSymmetrical.java
index 2b8d722..6fc8316 100644
--- a/src/java/edu/umd/cs/findbugs/detect/OverridingEqualsNotSymmetrical.java
+++ b/src/java/edu/umd/cs/findbugs/detect/OverridingEqualsNotSymmetrical.java
@@ -78,43 +78,44 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
@Override
public void visit(Code obj) {
- if (getMethodName().equals(EQUALS_NAME) && !getMethod().isStatic() && getMethod().isPublic()
- && getMethodSig().equals(EQUALS_SIGNATURE)) {
+ if (EQUALS_NAME.equals(getMethodName()) && !getMethod().isStatic() && getMethod().isPublic()
+ && EQUALS_SIGNATURE.equals(getMethodSig())) {
sawCheckedCast = sawSuperEquals = sawInstanceOf = sawGetClass = sawReturnSuper = sawCompare = sawReturnNonSuper = prevWasSuperEquals = sawGoodEqualsClass = sawBadEqualsClass = dangerDanger = sawInstanceOfSupertype = alwaysTrue = alwaysFalse = sawStaticDelegate = sawEqualsBuilder = false;
sawInitialIdentityCheck = obj.getCode().length == 11 || obj.getCode().length == 9;
equalsCalls = 0;
super.visit(obj);
EqualsKindSummary.KindOfEquals kind = EqualsKindSummary.KindOfEquals.UNKNOWN;
- if (alwaysTrue)
+ if (alwaysTrue) {
kind = EqualsKindSummary.KindOfEquals.ALWAYS_TRUE;
- else if (alwaysFalse)
+ } else if (alwaysFalse) {
kind = EqualsKindSummary.KindOfEquals.ALWAYS_FALSE;
- else if (sawReturnSuper && !sawReturnNonSuper)
+ } else if (sawReturnSuper && !sawReturnNonSuper) {
kind = EqualsKindSummary.KindOfEquals.RETURNS_SUPER;
- else if (sawSuperEquals)
+ } else if (sawSuperEquals) {
kind = EqualsKindSummary.KindOfEquals.INVOKES_SUPER;
- else if (sawInstanceOfSupertype)
+ } else if (sawInstanceOfSupertype) {
kind = EqualsKindSummary.KindOfEquals.INSTANCE_OF_SUPERCLASS_EQUALS;
- else if (sawInstanceOf)
+ } else if (sawInstanceOf) {
kind = getThisClass().isAbstract() ? EqualsKindSummary.KindOfEquals.ABSTRACT_INSTANCE_OF
: EqualsKindSummary.KindOfEquals.INSTANCE_OF_EQUALS;
- else if (sawGetClass && sawGoodEqualsClass)
+ } else if (sawGetClass && sawGoodEqualsClass) {
kind = getThisClass().isAbstract() ? EqualsKindSummary.KindOfEquals.ABSTRACT_GETCLASS_GOOD_EQUALS
: EqualsKindSummary.KindOfEquals.GETCLASS_GOOD_EQUALS;
- else if (sawGetClass && sawBadEqualsClass)
+ } else if (sawGetClass && sawBadEqualsClass) {
kind = EqualsKindSummary.KindOfEquals.GETCLASS_BAD_EQUALS;
- else if (equalsCalls == 1 || sawStaticDelegate || sawEqualsBuilder)
+ } else if (equalsCalls == 1 || sawStaticDelegate || sawEqualsBuilder) {
kind = EqualsKindSummary.KindOfEquals.DELEGATE_EQUALS;
- else if (sawInitialIdentityCheck)
+ } else if (sawInitialIdentityCheck) {
kind = EqualsKindSummary.KindOfEquals.TRIVIAL_EQUALS;
- else if (sawCheckedCast)
+ } else if (sawCheckedCast) {
kind = EqualsKindSummary.KindOfEquals.CHECKED_CAST_EQUALS;
- else if (sawCompare)
+ } else if (sawCompare) {
kind = EqualsKindSummary.KindOfEquals.COMPARE_EQUALS;
- else {
- if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass()))
+ } else {
+ if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass())) {
bugReporter
- .reportBug(new BugInstance(this, "EQ_UNUSUAL", Priorities.NORMAL_PRIORITY).addClassAndMethod(this));
+ .reportBug(new BugInstance(this, "EQ_UNUSUAL", Priorities.NORMAL_PRIORITY).addClassAndMethod(this));
+ }
}
ClassAnnotation classAnnotation = new ClassAnnotation(getDottedClassName());
equalsKindSummary.put(classAnnotation, kind);
@@ -153,8 +154,9 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
}
String superClassName = getSuperclassName().replace('/', '.');
- if (!superClassName.equals("java.lang.Object"))
+ if (!"java.lang.Object".equals(superClassName)) {
parentMap.put(classAnnotation, new ClassAnnotation(superClassName));
+ }
equalsMethod.put(classAnnotation, getMethodDescriptor());
}
@@ -194,10 +196,11 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
private void count(EqualsKindSummary.KindOfEquals k) {
Integer v = count.get(k);
- if (v == null)
+ if (v == null) {
count.put(k, 1);
- else
+ } else {
count.put(k, v + 1);
+ }
}
@Override
@@ -210,27 +213,30 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
&& seen == INVOKESTATIC
&& getCode().getCode().length == 6
&& (getPrevOpcode(1) == ALOAD_0 && getPrevOpcode(2) == ALOAD_1 || getPrevOpcode(1) == ALOAD_1
- && getPrevOpcode(2) == ALOAD_0))
+ && getPrevOpcode(2) == ALOAD_0)) {
sawStaticDelegate = true;
+ }
if ((seen == INVOKESTATIC || seen == INVOKESPECIAL || seen == INVOKEVIRTUAL)
- && (getClassConstantOperand().equals("org/apache/commons/lang/builder/EqualsBuilder")
- || getClassConstantOperand().equals("org/apache/commons/lang3/builder/EqualsBuilder")))
+ && ("org/apache/commons/lang/builder/EqualsBuilder".equals(getClassConstantOperand())
+ || "org/apache/commons/lang3/builder/EqualsBuilder".equals(getClassConstantOperand()))) {
sawEqualsBuilder = true;
+ }
if (seen == IRETURN && getPC() == 1 && getPrevOpcode(1) == ICONST_0) {
alwaysFalse = true;
- if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass()))
+ if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass())) {
bugReporter.reportBug(new BugInstance(this, "EQ_ALWAYS_FALSE", Priorities.HIGH_PRIORITY).addClassAndMethod(this)
.addSourceLine(this));
+ }
}
if (seen == IRETURN && getPC() == 1 && getPrevOpcode(1) == ICONST_1) {
alwaysTrue = true;
- if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass()))
-
+ if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass())) {
bugReporter.reportBug(new BugInstance(this, "EQ_ALWAYS_TRUE", Priorities.HIGH_PRIORITY).addClassAndMethod(this)
.addSourceLine(this));
+ }
}
if (seen == IF_ACMPEQ || seen == IF_ACMPNE) {
@@ -239,83 +245,87 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
if (callToInvoke(seen)) {
equalsCalls++;
checkForComparingClasses();
- if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass()) && dangerDanger)
+ if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass()) && dangerDanger) {
bugReporter.reportBug(new BugInstance(this, "EQ_COMPARING_CLASS_NAMES", Priorities.NORMAL_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
+ }
}
- if ((seen == INVOKEINTERFACE || seen == INVOKEVIRTUAL) && getNameConstantOperand().equals("compare")
+ if ((seen == INVOKEINTERFACE || seen == INVOKEVIRTUAL) && "compare".equals(getNameConstantOperand())
&& stack.getStackDepth() >= 2) {
Item left = stack.getStackItem(1);
Item right = stack.getStackItem(0);
- if (left.getRegisterNumber() + right.getRegisterNumber() == 1)
+ if (left.getRegisterNumber() + right.getRegisterNumber() == 1) {
sawCompare = true;
+ }
}
dangerDanger = false;
- if (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/lang/Class")
- && getNameConstantOperand().equals("getName") && getSigConstantOperand().equals("()Ljava/lang/String;")
+ if (seen == INVOKEVIRTUAL && "java/lang/Class".equals(getClassConstantOperand())
+ && "getName".equals(getNameConstantOperand()) && "()Ljava/lang/String;".equals(getSigConstantOperand())
&& stack.getStackDepth() >= 2) {
Item left = stack.getStackItem(1);
XMethod leftM = left.getReturnValueOf();
Item right = stack.getStackItem(0);
XMethod rightM = right.getReturnValueOf();
- if (leftM != null && rightM != null && leftM.getName().equals("getName") && rightM.getName().equals("getClass")) {
+ if (leftM != null && rightM != null && "getName".equals(leftM.getName()) && "getClass".equals(rightM.getName())) {
dangerDanger = true;
}
}
- if (seen == INVOKESPECIAL && getNameConstantOperand().equals(EQUALS_NAME)
- && getSigConstantOperand().equals(EQUALS_SIGNATURE)) {
+ if (seen == INVOKESPECIAL && EQUALS_NAME.equals(getNameConstantOperand())
+ && EQUALS_SIGNATURE.equals(getSigConstantOperand())) {
sawSuperEquals = prevWasSuperEquals = true;
} else {
if (seen == IRETURN) {
- if (prevWasSuperEquals)
+ if (prevWasSuperEquals) {
sawReturnSuper = true;
- else
+ } else {
sawReturnNonSuper = true;
+ }
}
prevWasSuperEquals = false;
}
if (seen == INSTANCEOF && stack.getStackDepth() > 0 && stack.getStackItem(0).getRegisterNumber() == 1) {
ClassDescriptor instanceOfCheck = getClassDescriptorOperand();
- if (instanceOfCheck.equals(getClassDescriptor()))
+ if (instanceOfCheck.equals(getClassDescriptor())) {
sawInstanceOf = true;
- else
+ } else {
try {
- if (AnalysisContext.currentAnalysisContext().getSubtypes2().isSubtype(getClassDescriptor(), instanceOfCheck))
+ if (AnalysisContext.currentAnalysisContext().getSubtypes2().isSubtype(getClassDescriptor(), instanceOfCheck)) {
sawInstanceOfSupertype = true;
+ }
} catch (ClassNotFoundException e) {
sawInstanceOfSupertype = true;
}
+ }
}
if (seen == CHECKCAST && stack.getStackDepth() > 0 && stack.getStackItem(0).getRegisterNumber() == 1) {
ClassDescriptor castTo = getClassDescriptorOperand();
- if (castTo.equals(getClassDescriptor()))
+ if (castTo.equals(getClassDescriptor())) {
sawCheckedCast = true;
+ }
try {
- if (AnalysisContext.currentAnalysisContext().getSubtypes2().isSubtype(getClassDescriptor(), castTo))
+ if (AnalysisContext.currentAnalysisContext().getSubtypes2().isSubtype(getClassDescriptor(), castTo)) {
sawCheckedCast = true;
+ }
} catch (ClassNotFoundException e) {
sawCheckedCast = true;
}
}
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("getClass")
- && getSigConstantOperand().equals("()Ljava/lang/Class;")) {
+ if (seen == INVOKEVIRTUAL && "getClass".equals(getNameConstantOperand())
+ && "()Ljava/lang/Class;".equals(getSigConstantOperand())) {
sawGetClass = true;
}
}
- /**
- * @param seen
- * @return
- */
private boolean callToInvoke(int seen) {
- if (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE || seen == INVOKESPECIAL)
- return invokesMethodWithEqualLikeName() && getSigConstantOperand().equals(EQUALS_SIGNATURE);
+ if (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE || seen == INVOKESPECIAL) {
+ return invokesMethodWithEqualLikeName() && EQUALS_SIGNATURE.equals(getSigConstantOperand());
+ }
if (seen == INVOKESTATIC) {
String sig = getSigConstantOperand();
return invokesMethodWithEqualLikeName() && sig.endsWith("Ljava/lang/Object;)Z");
@@ -338,9 +348,9 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
XMethod leftM = left.getReturnValueOf();
Item right = stack.getStackItem(0);
XMethod rightM = right.getReturnValueOf();
- if (left.getSignature().equals("Ljava/lang/Class;") && right.getSignature().equals("Ljava/lang/Class;")) {
- boolean leftMatch = leftM != null && leftM.getName().equals("getClass");
- boolean rightMatch = rightM != null && rightM.getName().equals("getClass");
+ if ("Ljava/lang/Class;".equals(left.getSignature()) && "Ljava/lang/Class;".equals(right.getSignature())) {
+ boolean leftMatch = leftM != null && "getClass".equals(leftM.getName());
+ boolean rightMatch = rightM != null && "getClass".equals(rightM.getName());
if (leftMatch && rightMatch) {
sawGoodEqualsClass = true;
} else {
@@ -355,7 +365,7 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
int priority = Priorities.NORMAL_PRIORITY;
BugInstance bug = new BugInstance(this, "EQ_GETCLASS_AND_CLASS_CONSTANT", priority)
- .addClassAndMethod(this);
+ .addClassAndMethod(this);
try {
@@ -396,21 +406,26 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
for (Map.Entry<ClassDescriptor, Set<ClassDescriptor>> e : classesWithGetClassBasedEquals.entrySet()) {
ClassAnnotation parentClass = ClassAnnotation.fromClassDescriptor(e.getKey());
XClass xParent = AnalysisContext.currentXFactory().getXClass(e.getKey());
- if (xParent == null)
+ if (xParent == null) {
continue;
+ }
EqualsKindSummary.KindOfEquals parentKind = equalsKindSummary.get(parentClass);
for (ClassDescriptor child : e.getValue()) {
- if (child.equals(e.getKey()))
+ if (child.equals(e.getKey())) {
continue;
+ }
XClass xChild = AnalysisContext.currentXFactory().getXClass(child);
- if (xChild == null)
+ if (xChild == null) {
continue;
+ }
ClassAnnotation childClass = ClassAnnotation.fromClassDescriptor(child);
EqualsKindSummary.KindOfEquals childKind = equalsKindSummary.get(childClass);
int fieldsOfInterest = 0;
- for (XField f : xChild.getXFields())
- if (!f.isStatic() && !f.isSynthetic())
+ for (XField f : xChild.getXFields()) {
+ if (!f.isStatic() && !f.isSynthetic()) {
fieldsOfInterest++;
+ }
+ }
int grandchildren = -1;
try {
@@ -422,9 +437,11 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
+ fieldsOfInterest + " " + grandchildren);
try {
if (grandchildren >= 2) {
- for (ClassDescriptor g : subtypes2.getSubtypes(child))
- if (!g.equals(child))
+ for (ClassDescriptor g : subtypes2.getSubtypes(child)) {
+ if (!g.equals(child)) {
System.out.println(" " + g);
+ }
+ }
}
} catch (ClassNotFoundException e1) {
assert true;
@@ -437,24 +454,29 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
for (Map.Entry<ClassDescriptor, Set<ClassDescriptor>> e : classesWithInstanceOfBasedEquals.entrySet()) {
ClassAnnotation parentClass = ClassAnnotation.fromClassDescriptor(e.getKey());
XClass xParent = AnalysisContext.currentXFactory().getXClass(e.getKey());
- if (xParent == null)
+ if (xParent == null) {
continue;
+ }
EqualsKindSummary.KindOfEquals parentKind = equalsKindSummary.get(parentClass);
boolean isOverridden = false;
for (ClassDescriptor child : e.getValue()) {
- if (child.equals(e.getKey()))
+ if (child.equals(e.getKey())) {
continue;
+ }
XClass xChild = AnalysisContext.currentXFactory().getXClass(child);
- if (xChild == null)
+ if (xChild == null) {
continue;
+ }
ClassAnnotation childClass = ClassAnnotation.fromClassDescriptor(child);
EqualsKindSummary.KindOfEquals childKind = equalsKindSummary.get(childClass);
- if (childKind != null)
+ if (childKind != null) {
isOverridden = true;
+ }
}
total++;
- if (isOverridden)
+ if (isOverridden) {
overridden++;
+ }
System.out.println("IS_OVERRIDDEN: " + e.getKey().getClassName());
}
System.out.println("Instance of equals: " + total + " subclassed, " + overridden + " overrridden");
@@ -471,10 +493,11 @@ public class OverridingEqualsNotSymmetrical extends OpcodeStackDetector implemen
EqualsKindSummary.KindOfEquals parentKind = equalsKindSummary.get(parentClass);
if (childKind == EqualsKindSummary.KindOfEquals.INSTANCE_OF_EQUALS
- && parentKind == EqualsKindSummary.KindOfEquals.INSTANCE_OF_EQUALS)
+ && parentKind == EqualsKindSummary.KindOfEquals.INSTANCE_OF_EQUALS) {
bugReporter.reportBug(new BugInstance(this, "EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC", NORMAL_PRIORITY)
- .add(childClass).addMethod(equalsMethod.get(childClass)).addMethod(equalsMethod.get(parentClass))
- .describe(MethodAnnotation.METHOD_OVERRIDDEN));
+ .add(childClass).addMethod(equalsMethod.get(childClass)).addMethod(equalsMethod.get(parentClass))
+ .describe(MethodAnnotation.METHOD_OVERRIDDEN));
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/PreferZeroLengthArrays.java b/src/java/edu/umd/cs/findbugs/detect/PreferZeroLengthArrays.java
index 833017a..922c09d 100644
--- a/src/java/edu/umd/cs/findbugs/detect/PreferZeroLengthArrays.java
+++ b/src/java/edu/umd/cs/findbugs/detect/PreferZeroLengthArrays.java
@@ -33,7 +33,7 @@ import edu.umd.cs.findbugs.StatelessDetector;
public class PreferZeroLengthArrays extends BytecodeScanningDetector implements StatelessDetector {
boolean nullOnTOS = false;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public PreferZeroLengthArrays(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -46,17 +46,18 @@ public class PreferZeroLengthArrays extends BytecodeScanningDetector implements
found.clear();
// Solution to sourceforge bug 1765925; returning null is the
// convention used by java.io.File.listFiles()
- if (getMethodName().equals("listFiles")) {
+ if ("listFiles".equals(getMethodName())) {
return;
}
- String returnType = getMethodSig().substring(getMethodSig().indexOf(")") + 1);
+ String returnType = getMethodSig().substring(getMethodSig().indexOf(')') + 1);
if (returnType.startsWith("[")) {
nullOnTOS = false;
super.visit(obj);
if (!found.isEmpty()) {
BugInstance bug = new BugInstance(this, "PZLA_PREFER_ZERO_LENGTH_ARRAYS", LOW_PRIORITY).addClassAndMethod(this);
- for (SourceLineAnnotation s : found)
+ for (SourceLineAnnotation s : found) {
bug.add(s);
+ }
bugReporter.reportBug(bug);
found.clear();
}
@@ -74,10 +75,12 @@ public class PreferZeroLengthArrays extends BytecodeScanningDetector implements
if (nullOnTOS) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(getClassContext(), this,
getPC());
- if (sourceLineAnnotation != null)
+ if (sourceLineAnnotation != null) {
found.add(sourceLineAnnotation);
+ }
}
-
+ break;
+ default:
break;
}
nullOnTOS = false;
diff --git a/src/java/edu/umd/cs/findbugs/detect/PublicSemaphores.java b/src/java/edu/umd/cs/findbugs/detect/PublicSemaphores.java
index 28eca7c..0e445bb 100644
--- a/src/java/edu/umd/cs/findbugs/detect/PublicSemaphores.java
+++ b/src/java/edu/umd/cs/findbugs/detect/PublicSemaphores.java
@@ -41,7 +41,7 @@ public class PublicSemaphores extends BytecodeScanningDetector implements Statel
private static final int SEEN_ALOAD_0 = 1;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private int state;
@@ -54,8 +54,9 @@ public class PublicSemaphores extends BytecodeScanningDetector implements Statel
@Override
public void visitClassContext(ClassContext classContext) {
JavaClass cls = classContext.getJavaClass();
- if ((!cls.isPublic()) || (cls.getClassName().indexOf("$") >= 0))
+ if ((!cls.isPublic()) || (cls.getClassName().indexOf('$') >= 0)) {
return;
+ }
alreadyReported = false;
super.visitClassContext(classContext);
@@ -64,8 +65,9 @@ public class PublicSemaphores extends BytecodeScanningDetector implements Statel
@Override
public void visit(Code obj) {
Method m = getMethod();
- if (m.isStatic() || alreadyReported)
+ if (m.isStatic() || alreadyReported) {
return;
+ }
state = SEEN_NOTHING;
super.visit(obj);
@@ -73,17 +75,19 @@ public class PublicSemaphores extends BytecodeScanningDetector implements Statel
@Override
public void sawOpcode(int seen) {
- if (alreadyReported)
+ if (alreadyReported) {
return;
+ }
switch (state) {
case SEEN_NOTHING:
- if (seen == ALOAD_0)
+ if (seen == ALOAD_0) {
state = SEEN_ALOAD_0;
+ }
break;
case SEEN_ALOAD_0:
- if ((seen == INVOKEVIRTUAL) && getClassConstantOperand().equals("java/lang/Object")) {
+ if ((seen == INVOKEVIRTUAL) && "java/lang/Object".equals(getClassConstantOperand())) {
String methodName = getNameConstantOperand();
if ("wait".equals(methodName) || "notify".equals(methodName) || "notifyAll".equals(methodName)) {
bugReporter.reportBug(new BugInstance(this, "PS_PUBLIC_SEMAPHORES", NORMAL_PRIORITY).addClassAndMethod(this)
@@ -93,6 +97,8 @@ public class PublicSemaphores extends BytecodeScanningDetector implements Statel
}
state = SEEN_NOTHING;
break;
+ default:
+ break;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/QuestionableBooleanAssignment.java b/src/java/edu/umd/cs/findbugs/detect/QuestionableBooleanAssignment.java
index 7a928ba..0b394be 100644
--- a/src/java/edu/umd/cs/findbugs/detect/QuestionableBooleanAssignment.java
+++ b/src/java/edu/umd/cs/findbugs/detect/QuestionableBooleanAssignment.java
@@ -39,7 +39,7 @@ public class QuestionableBooleanAssignment extends BytecodeScanningDetector impl
public static final int SEEN_IF = 5;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private int state;
@@ -60,25 +60,28 @@ public class QuestionableBooleanAssignment extends BytecodeScanningDetector impl
public void sawOpcode(int seen) {
if (seen == GOTO && getBranchOffset() == 4) {
state = SEEN_GOTO;
- } else
+ } else {
switch (state) {
case SEEN_NOTHING:
- if ((seen == ICONST_1) || (seen == ICONST_0))
+ if ((seen == ICONST_1) || (seen == ICONST_0)) {
state = SEEN_ICONST_0_OR_1;
+ }
break;
case SEEN_ICONST_0_OR_1:
- if (seen == DUP)
+ if (seen == DUP) {
state = SEEN_DUP;
- else
+ } else {
state = SEEN_NOTHING;
+ }
break;
case SEEN_DUP:
- if (((seen >= ISTORE_0) && (seen <= ISTORE_3)) || (seen == ISTORE))
+ if (((seen >= ISTORE_0) && (seen <= ISTORE_3)) || (seen == ISTORE)) {
state = SEEN_ISTORE;
- else
+ } else {
state = SEEN_NOTHING;
+ }
break;
case SEEN_ISTORE:
@@ -86,23 +89,27 @@ public class QuestionableBooleanAssignment extends BytecodeScanningDetector impl
bug = new BugInstance(this, "QBA_QUESTIONABLE_BOOLEAN_ASSIGNMENT", HIGH_PRIORITY).addClassAndMethod(this)
.addSourceLine(this);
state = SEEN_IF;
- } else
+ } else {
state = SEEN_NOTHING;
+ }
break;
case SEEN_IF:
state = SEEN_NOTHING;
if (seen == NEW) {
String cName = getClassConstantOperand();
- if (cName.equals("java/lang/AssertionError"))
+ if ("java/lang/AssertionError".equals(cName)) {
break;
+ }
}
bugReporter.reportBug(bug);
-
break;
case SEEN_GOTO:
state = SEEN_NOTHING;
break;
+ default:
+ break;
}
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass.java b/src/java/edu/umd/cs/findbugs/detect/ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass.java
index a7ca66c..196f798 100644
--- a/src/java/edu/umd/cs/findbugs/detect/ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass.java
+++ b/src/java/edu/umd/cs/findbugs/detect/ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass.java
@@ -56,8 +56,9 @@ public class ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass extends
@Override
public void visit(Code obj) {
- if (getMethod().isStatic())
+ if (getMethod().isStatic()) {
return;
+ }
initializedFields = new HashSet<XField>();
nullCheckedFields = new HashSet<XField>();
super.visit(obj);
@@ -69,42 +70,51 @@ public class ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass extends
if (opcode == PUTFIELD) {
XField f = getXFieldOperand();
OpcodeStack.Item item = stack.getStackItem(1);
- if (item.getRegisterNumber() != 0)
+ if (item.getRegisterNumber() != 0) {
return;
+ }
initializedFields.add(f);
return;
}
- if (opcode != GETFIELD)
+ if (opcode != GETFIELD) {
return;
+ }
OpcodeStack.Item item = stack.getStackItem(0);
- if (item.getRegisterNumber() != 0)
+ if (item.getRegisterNumber() != 0) {
return;
+ }
XField f = getXFieldOperand();
- if (f == null || !f.getClassDescriptor().equals(getClassDescriptor()))
+ if (f == null || !f.getClassDescriptor().equals(getClassDescriptor())) {
return;
- if (f.isSynthetic() || f.getName().startsWith("this$"))
+ }
+ if (f.isSynthetic() || f.getName().startsWith("this$")) {
return;
- if (initializedFields.contains(f))
+ }
+ if (initializedFields.contains(f)) {
return;
+ }
FieldSummary fieldSummary = AnalysisContext.currentAnalysisContext().getFieldSummary();
ClassDescriptor superClassDescriptor = DescriptorFactory.createClassDescriptor(getSuperclassName());
Set<ProgramPoint> calledFrom = fieldSummary.getCalledFromSuperConstructor(superClassDescriptor, getXMethod());
- if (calledFrom.isEmpty())
+ if (calledFrom.isEmpty()) {
return;
+ }
UnreadFieldsData unreadFields = AnalysisContext.currentAnalysisContext().getUnreadFieldsData();
int priority;
- if (!unreadFields.isWrittenInConstructor(f))
+ if (!unreadFields.isWrittenInConstructor(f)) {
return;
+ }
- if (f.isFinal())
+ if (f.isFinal()) {
priority = HIGH_PRIORITY;
- else if (unreadFields.isWrittenDuringInitialization(f) || unreadFields.isWrittenOutsideOfInitialization(f))
+ } else if (unreadFields.isWrittenDuringInitialization(f) || unreadFields.isWrittenOutsideOfInitialization(f)) {
priority = NORMAL_PRIORITY;
- else
+ } else {
priority = HIGH_PRIORITY;
+ }
int nextOpcode = getNextOpcode();
if (nullCheckedFields.contains(f) || nextOpcode == IFNULL || nextOpcode == IFNONNULL || nextOpcode == IFEQ
@@ -115,8 +125,9 @@ public class ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass extends
for (ProgramPoint p : calledFrom) {
XMethod upcall = getConstructorThatCallsSuperConstructor(p.method);
- if (upcall == null)
+ if (upcall == null) {
continue;
+ }
Method upcallMethod = null;
for (Method m : getThisClass().getMethods()) {
if (m.getName().equals(upcall.getName()) && m.getSignature().equals(upcall.getSignature())) {
@@ -124,25 +135,28 @@ public class ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass extends
break;
}
}
- if (upcallMethod == null)
+ if (upcallMethod == null) {
continue;
+ }
Map<Integer, OpcodeStack.Item> putfieldsAt = PutfieldScanner.getPutfieldsFor(getThisClass(), upcallMethod, f);
- if (putfieldsAt.isEmpty())
+ if (putfieldsAt.isEmpty()) {
continue;
+ }
Map.Entry<Integer, OpcodeStack.Item> e = putfieldsAt.entrySet().iterator().next();
int pc = e.getKey();
OpcodeStack.Item value = e.getValue();
- if (value.isNull() || value.hasConstantValue(0))
+ if (value.isNull() || value.hasConstantValue(0)) {
priority++;
+ }
SourceLineAnnotation fieldSetAt = SourceLineAnnotation.fromVisitedInstruction(getThisClass(), upcallMethod, pc);
BugInstance bug = new BugInstance(this, "UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR", priority).addClassAndMethod(
this).addField(f);
bug.addMethod(p.method).describe(MethodAnnotation.METHOD_SUPERCLASS_CONSTRUCTOR)
- .addSourceLine(p.getSourceLineAnnotation()).describe(SourceLineAnnotation.ROLE_CALLED_FROM_SUPERCLASS_AT)
- .addMethod(upcall).describe(MethodAnnotation.METHOD_CONSTRUCTOR).add(fieldSetAt)
- .describe(SourceLineAnnotation.ROLE_FIELD_SET_TOO_LATE_AT);
+ .addSourceLine(p.getSourceLineAnnotation()).describe(SourceLineAnnotation.ROLE_CALLED_FROM_SUPERCLASS_AT)
+ .addMethod(upcall).describe(MethodAnnotation.METHOD_CONSTRUCTOR).add(fieldSetAt)
+ .describe(SourceLineAnnotation.ROLE_FIELD_SET_TOO_LATE_AT);
accumulator.accumulateBug(bug, this);
}
@@ -153,12 +167,14 @@ public class ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass extends
XMethod getConstructorThatCallsSuperConstructor(XMethod superConstructor) {
FieldSummary fieldSummary = AnalysisContext.currentAnalysisContext().getFieldSummary();
- XMethod lookfor = superConstructor.getSignature().equals("()V") ? null : superConstructor;
- for (XMethod m : getXClass().getXMethods())
- if (m.getName().equals("<init>")) {
- if (fieldSummary.getSuperCall(m) == lookfor)
+ XMethod lookfor = "()V".equals(superConstructor.getSignature()) ? null : superConstructor;
+ for (XMethod m : getXClass().getXMethods()) {
+ if ("<init>".equals(m.getName())) {
+ if (fieldSummary.getSuperCall(m) == lookfor) {
return m;
+ }
}
+ }
return null;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/ReadReturnShouldBeChecked.java b/src/java/edu/umd/cs/findbugs/detect/ReadReturnShouldBeChecked.java
index b06ffdd..89ead51 100644
--- a/src/java/edu/umd/cs/findbugs/detect/ReadReturnShouldBeChecked.java
+++ b/src/java/edu/umd/cs/findbugs/detect/ReadReturnShouldBeChecked.java
@@ -63,18 +63,20 @@ public class ReadReturnShouldBeChecked extends BytecodeScanningDetector implemen
private boolean isInputStream() {
- if (lastCallClass.startsWith("["))
+ if (lastCallClass.startsWith("[")) {
return false;
+ }
return (Subtypes2.instanceOf(lastCallClass, "java.io.InputStream")
|| Subtypes2.instanceOf(lastCallClass, "java.io.DataInput") || Subtypes2.instanceOf(lastCallClass,
- "java.io.Reader")) && !Subtypes2.instanceOf(lastCallClass, "java.io.ByteArrayInputStream");
+ "java.io.Reader")) && !Subtypes2.instanceOf(lastCallClass, "java.io.ByteArrayInputStream");
}
private boolean isBufferedInputStream() {
try {
- if (lastCallClass.startsWith("["))
+ if (lastCallClass.startsWith("[")) {
return false;
+ }
return Repository.instanceOf(lastCallClass, "java.io.BufferedInputStream");
} catch (ClassNotFoundException e) {
return false;
@@ -83,8 +85,9 @@ public class ReadReturnShouldBeChecked extends BytecodeScanningDetector implemen
private boolean isImageIOInputStream() {
try {
- if (lastCallClass.startsWith("["))
+ if (lastCallClass.startsWith("[")) {
return false;
+ }
return Repository.instanceOf(lastCallClass, "javax.imageio.stream.ImageInputStream");
} catch (ClassNotFoundException e) {
return false;
@@ -100,30 +103,30 @@ public class ReadReturnShouldBeChecked extends BytecodeScanningDetector implemen
lastCallSig = getSigConstantOperand();
}
- if (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE)
- if (getNameConstantOperand().equals("available") && getSigConstantOperand().equals("()I")
+ if (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) {
+ if ("available".equals(getNameConstantOperand()) && "()I".equals(getSigConstantOperand())
|| getNameConstantOperand().startsWith("get") && getNameConstantOperand().endsWith("Length")
- && getSigConstantOperand().equals("()I") || getClassConstantOperand().equals("java/io/File")
- && getNameConstantOperand().equals("length") && getSigConstantOperand().equals("()J")) {
+ && "()I".equals(getSigConstantOperand()) || "java/io/File".equals(getClassConstantOperand())
+ && "length".equals(getNameConstantOperand()) && "()J".equals(getSigConstantOperand())) {
sawAvailable = 70;
return;
}
+ }
sawAvailable--;
if ((seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE)
- && getNameConstantOperand().equals("read")
+ && "read".equals(getNameConstantOperand())
- && (getSigConstantOperand().equals("([B)I") || getSigConstantOperand().equals("([BII)I")
- || getSigConstantOperand().equals("([C)I") || getSigConstantOperand().equals("([CII)I"))
- && isInputStream()) {
+ && ("([B)I".equals(getSigConstantOperand()) || "([BII)I".equals(getSigConstantOperand())
+ || "([C)I".equals(getSigConstantOperand()) || "([CII)I".equals(getSigConstantOperand()))
+ && isInputStream()) {
sawRead = true;
recentCallToAvailable = sawAvailable > 0;
locationOfCall = getPC();
return;
}
if ((seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE)
- && (getNameConstantOperand().equals("skip") && getSigConstantOperand().equals("(J)J") || getNameConstantOperand()
- .equals("skipBytes") && getSigConstantOperand().equals("(I)I")) && isInputStream()
- && !isImageIOInputStream()) {
+ && ("skip".equals(getNameConstantOperand()) && "(J)J".equals(getSigConstantOperand()) || "skipBytes".equals(getNameConstantOperand()) && "(I)I".equals(getSigConstantOperand())) && isInputStream()
+ && !isImageIOInputStream()) {
// if not ByteArrayInput Stream
// and either no recent calls to length
// or it is a BufferedInputStream
@@ -141,7 +144,7 @@ public class ReadReturnShouldBeChecked extends BytecodeScanningDetector implemen
if (sawRead) {
accumulator.accumulateBug(
new BugInstance(this, "RR_NOT_CHECKED", recentCallToAvailable ? LOW_PRIORITY : NORMAL_PRIORITY)
- .addClassAndMethod(this).addCalledMethod(lastCallClass, lastCallMethod, lastCallSig, false),
+ .addClassAndMethod(this).addCalledMethod(lastCallClass, lastCallMethod, lastCallSig, false),
SourceLineAnnotation.fromVisitedInstruction(getClassContext(), this, locationOfCall));
} else if (sawSkip) {
diff --git a/src/java/edu/umd/cs/findbugs/detect/RedundantConditions.java b/src/java/edu/umd/cs/findbugs/detect/RedundantConditions.java
new file mode 100644
index 0000000..87b01db
--- /dev/null
+++ b/src/java/edu/umd/cs/findbugs/detect/RedundantConditions.java
@@ -0,0 +1,236 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.detect;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.BranchInstruction;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.GOTO;
+import org.apache.bcel.generic.GotoInstruction;
+import org.apache.bcel.generic.ICONST;
+import org.apache.bcel.generic.IfInstruction;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.InvokeInstruction;
+import org.apache.bcel.generic.MethodGen;
+
+import edu.umd.cs.findbugs.BugAccumulator;
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.Detector;
+import edu.umd.cs.findbugs.SourceLineAnnotation;
+import edu.umd.cs.findbugs.StringAnnotation;
+import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.bcel.BCELUtil;
+import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
+import edu.umd.cs.findbugs.classfile.engine.bcel.ValueRangeAnalysisFactory.RedundantCondition;
+import edu.umd.cs.findbugs.classfile.engine.bcel.ValueRangeAnalysisFactory.ValueRangeAnalysis;
+
+/**
+ * @author Tagir Valeev
+ */
+public class RedundantConditions implements Detector {
+ private final BugAccumulator bugAccumulator;
+ private final BugReporter bugReporter;
+
+ public RedundantConditions(BugReporter bugReporter) {
+ this.bugReporter = bugReporter;
+ this.bugAccumulator = new BugAccumulator(bugReporter);
+ }
+
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ for(Method method : classContext.getJavaClass().getMethods()) {
+ MethodDescriptor methodDescriptor = BCELUtil.getMethodDescriptor(classContext.getJavaClass(), method);
+ ValueRangeAnalysis analysis;
+ try {
+ analysis = Global.getAnalysisCache().getMethodAnalysis(ValueRangeAnalysis.class, methodDescriptor);
+ } catch (CheckedAnalysisException e) {
+ bugReporter.logError("ValueRangeAnalysis failed for "+methodDescriptor, e);
+ continue;
+ }
+ if(analysis == null) {
+ continue;
+ }
+ for(RedundantCondition condition : analysis.getRedundantConditions()) {
+ int priority = getPriority(methodDescriptor, condition);
+ SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, method,
+ condition.getLocation().getHandle().getPosition());
+ BugInstance bug = new BugInstance(condition.isByType()?"UC_USELESS_CONDITION_TYPE":"UC_USELESS_CONDITION", priority)
+ .addClassAndMethod(methodDescriptor).add(new StringAnnotation(normalize(condition.getTrueCondition())));
+ if(condition.isByType()) {
+ bug.addType(condition.getSignature());
+ }
+ if(condition.isDeadCodeUnreachable() && condition.getDeadCodeLocation() != null && priority == HIGH_PRIORITY) {
+ bug.addSourceLine(methodDescriptor, condition.getDeadCodeLocation()).describe(SourceLineAnnotation.ROLE_UNREACHABLE_CODE);
+ }
+ bugAccumulator.accumulateBug(bug, sourceLineAnnotation);
+ }
+ bugAccumulator.reportAccumulatedBugs();
+ }
+
+ }
+
+ private String normalize(String condition) {
+ if(condition.startsWith("this.this$")) {
+ return condition.substring("this.".length());
+ }
+ if(condition.startsWith("this.val$")) {
+ return condition.substring("this.val$".length());
+ }
+ return condition;
+ }
+
+ private int getPriority(MethodDescriptor methodDescriptor, RedundantCondition condition) {
+ if(condition.isByType()) {
+ // Skip reports which should be reported by another detector
+ long number = condition.getNumber().longValue();
+ switch(condition.getSignature()) {
+ case "I":
+ if(number == Integer.MIN_VALUE || number == Integer.MAX_VALUE) {
+ // Will be reported as INT_VACUOUS_COMPARISON
+ return IGNORE_PRIORITY;
+ }
+ break;
+ case "C":
+ if(number <= 0) {
+ // Will be reported as INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE
+ return IGNORE_PRIORITY;
+ }
+ break;
+ case "B":
+ if(number < Byte.MIN_VALUE || number >= Byte.MAX_VALUE) {
+ // Will be reported as INT_BAD_COMPARISON_WITH_SIGNED_BYTE
+ return IGNORE_PRIORITY;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ int priority = condition.isDeadCodeUnreachable() ? HIGH_PRIORITY : condition.isBorder()
+ || condition.getSignature().equals("Z") ? LOW_PRIORITY : NORMAL_PRIORITY;
+ // check for boolean conversion
+ if(condition.getDeadCodeLocation() != null && condition.getLiveCodeLocation() != null && condition.isDeadCodeUnreachable()) {
+ InstructionHandle deadHandle = condition.getDeadCodeLocation().getHandle();
+ InstructionHandle liveHandle = condition.getLiveCodeLocation().getHandle();
+ int deadValue = getIntValue(deadHandle);
+ int liveValue = getIntValue(liveHandle);
+ if((deadValue == 0 && liveValue == 1) || (deadValue == 1 && liveValue == 0)) {
+ InstructionHandle deadNext = deadHandle.getNext();
+ InstructionHandle liveNext = liveHandle.getNext();
+ if(deadNext != null && liveNext != null) {
+ InstructionHandle middle, after;
+ if(deadNext.getNext() == liveHandle) {
+ middle = deadNext;
+ after = liveNext;
+ } else if(liveNext.getNext() == deadHandle) {
+ middle = liveNext;
+ after = deadNext;
+ } else {
+ return priority;
+ }
+ if(!(middle.getInstruction() instanceof GOTO) || ((GOTO)middle.getInstruction()).getTarget() != after) {
+ return priority;
+ }
+ MethodGen methodGen;
+ try {
+ methodGen = Global.getAnalysisCache().getMethodAnalysis(MethodGen.class, methodDescriptor);
+ } catch (CheckedAnalysisException e) {
+ return priority;
+ }
+ InstructionHandle consumer = getConsumer(methodGen, after);
+ Instruction consumerInst = consumer == null ? null : consumer.getInstruction();
+ if(consumerInst != null) {
+ short opcode = consumerInst.getOpcode();
+ if(opcode == Constants.IADD || opcode == Constants.ISUB || opcode == Constants.IMUL
+ || opcode == Constants.ISHR || opcode == Constants.ISHL || opcode == Constants.IUSHR) {
+ // It's actually integer expression with explicit ? 1 : 0 or ? 0 : 1 operation
+ return priority;
+ }
+ }
+ if(condition.getSignature().equals("Z")) {
+ // Ignore !flag when flag value is known
+ return IGNORE_PRIORITY;
+ }
+ priority = condition.isBorder() ? LOW_PRIORITY : NORMAL_PRIORITY;
+ if(consumerInst instanceof InvokeInstruction) {
+ ConstantPoolGen constantPool = methodGen.getConstantPool();
+ String methodName = ((InvokeInstruction)consumerInst).getMethodName(constantPool);
+ // Ignore values conditions used in assertion methods
+ if((methodName.equals("assertTrue") || methodName.equals("checkArgument") || methodName.equals("isLegal")
+ || methodName.equals("isTrue"))) {
+ return liveValue == 1 ? condition.isBorder() ? IGNORE_PRIORITY : LOW_PRIORITY : HIGH_PRIORITY;
+ }
+ if((methodName.equals("assertFalse") || methodName.equals("isFalse"))) {
+ return liveValue == 0 ? condition.isBorder() ? IGNORE_PRIORITY : LOW_PRIORITY : HIGH_PRIORITY;
+ }
+ }
+ }
+ }
+ }
+ return priority;
+ }
+
+ /**
+ * @param methodGen method
+ * @param start instruction to scan
+ * @return instruction which consumes value which was on top of stack before start instruction
+ * or null if cannot be determined
+ */
+ private InstructionHandle getConsumer(MethodGen methodGen, InstructionHandle start) {
+ int depth = 1;
+ InstructionHandle cur = start;
+ while(cur != null) {
+ Instruction inst = cur.getInstruction();
+ depth -= inst.consumeStack(methodGen.getConstantPool());
+ if(depth <= 0) {
+ return cur;
+ }
+ depth += inst.produceStack(methodGen.getConstantPool());
+ if(inst instanceof BranchInstruction) {
+ if(inst instanceof GotoInstruction) {
+ cur = ((GotoInstruction)inst).getTarget();
+ continue;
+ }
+ if(!(inst instanceof IfInstruction)) {
+ return null;
+ }
+ }
+ cur = cur.getNext();
+ }
+ return null;
+ }
+
+ private int getIntValue(InstructionHandle handle) {
+ Instruction instruction = handle.getInstruction();
+ if(instruction instanceof ICONST) {
+ return ((ICONST)instruction).getValue().intValue();
+ }
+ return -1;
+ }
+
+ @Override
+ public void report() {
+ }
+}
diff --git a/src/java/edu/umd/cs/findbugs/detect/RedundantInterfaces.java b/src/java/edu/umd/cs/findbugs/detect/RedundantInterfaces.java
index 1bb6b18..7b55a39 100644
--- a/src/java/edu/umd/cs/findbugs/detect/RedundantInterfaces.java
+++ b/src/java/edu/umd/cs/findbugs/detect/RedundantInterfaces.java
@@ -33,22 +33,25 @@ import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
public class RedundantInterfaces extends PreorderVisitor implements Detector, StatelessDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public RedundantInterfaces(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
+ @Override
public void visitClassContext(ClassContext classContext) {
JavaClass obj = classContext.getJavaClass();
String superClassName = obj.getSuperclassName();
- if (superClassName.equals("java.lang.Object"))
+ if ("java.lang.Object".equals(superClassName)) {
return;
+ }
String[] interfaceNames = obj.getInterfaceNames();
- if ((interfaceNames == null) || (interfaceNames.length == 0))
+ if ((interfaceNames == null) || (interfaceNames.length == 0)) {
return;
+ }
try {
JavaClass superObj = obj.getSuperClass();
@@ -57,15 +60,17 @@ public class RedundantInterfaces extends PreorderVisitor implements Detector, St
for (String interfaceName : interfaceNames) {
if (!"java/io/Serializable".equals(interfaceName)) {
JavaClass inf = Repository.lookupClass(interfaceName.replace('/', '.'));
- if (superObj.instanceOf(inf))
+ if (superObj.instanceOf(inf)) {
redundantInfNames.add(inf.getClassName());
+ }
}
}
if (redundantInfNames.size() > 0) {
BugInstance bug = new BugInstance(this, "RI_REDUNDANT_INTERFACES", LOW_PRIORITY).addClass(obj);
- for (String redundantInfName : redundantInfNames)
+ for (String redundantInfName : redundantInfNames) {
bug.addClass(redundantInfName).describe("INTERFACE_TYPE");
+ }
bugReporter.reportBug(bug);
}
@@ -75,6 +80,7 @@ public class RedundantInterfaces extends PreorderVisitor implements Detector, St
}
}
+ @Override
public void report() {
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/RefComparisonWarningProperty.java b/src/java/edu/umd/cs/findbugs/detect/RefComparisonWarningProperty.java
index 163292b..fb24987 100644
--- a/src/java/edu/umd/cs/findbugs/detect/RefComparisonWarningProperty.java
+++ b/src/java/edu/umd/cs/findbugs/detect/RefComparisonWarningProperty.java
@@ -23,7 +23,7 @@ import edu.umd.cs.findbugs.props.PriorityAdjustment;
/**
* Warning properties for FindRefComparison detector.
- *
+ *
* @author David Hovemeyer
*/
public class RefComparisonWarningProperty extends AbstractWarningProperty {
diff --git a/src/java/edu/umd/cs/findbugs/detect/ReflectiveClasses.java b/src/java/edu/umd/cs/findbugs/detect/ReflectiveClasses.java
index 0196730..fa4abcf 100644
--- a/src/java/edu/umd/cs/findbugs/detect/ReflectiveClasses.java
+++ b/src/java/edu/umd/cs/findbugs/detect/ReflectiveClasses.java
@@ -47,8 +47,9 @@ public class ReflectiveClasses extends BytecodeScanningDetector implements NonRe
@Override
public void sawClass() {
int opcode = getOpcode();
- if ((opcode == LDC) || (opcode == LDC_W))
+ if ((opcode == LDC) || (opcode == LDC_W)) {
process(getClassConstantOperand());
+ }
}
@Override
@@ -56,8 +57,8 @@ public class ReflectiveClasses extends BytecodeScanningDetector implements NonRe
if (seen == INVOKESTATIC) {
// System.out.println(getClassConstantOperand()+ "." +
// getNameConstantOperand());
- if (constantString != null && getClassConstantOperand().equals("java/lang/Class")
- && getNameConstantOperand().equals("forName")) {
+ if (constantString != null && "java/lang/Class".equals(getClassConstantOperand())
+ && "forName".equals(getNameConstantOperand())) {
process(ClassName.toSlashedClassName(constantString));
}
@@ -71,4 +72,3 @@ public class ReflectiveClasses extends BytecodeScanningDetector implements NonRe
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/RepeatedConditionals.java b/src/java/edu/umd/cs/findbugs/detect/RepeatedConditionals.java
index 0051bff..341cd5e 100644
--- a/src/java/edu/umd/cs/findbugs/detect/RepeatedConditionals.java
+++ b/src/java/edu/umd/cs/findbugs/detect/RepeatedConditionals.java
@@ -24,19 +24,29 @@ import java.util.LinkedList;
import java.util.Map;
import org.apache.bcel.classfile.Code;
+import org.apache.bcel.generic.BranchInstruction;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.MethodGen;
import org.objectweb.asm.Opcodes;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
+import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.detect.FindNoSideEffectMethods.MethodSideEffectStatus;
+import edu.umd.cs.findbugs.detect.FindNoSideEffectMethods.NoSideEffectMethodsDatabase;
public class RepeatedConditionals extends OpcodeStackDetector {
-
BugReporter bugReporter;
+ private final NoSideEffectMethodsDatabase noSideEffectMethods;
+
public RepeatedConditionals(BugReporter bugReporter) {
this.bugReporter = bugReporter;
+ this.noSideEffectMethods = Global.getAnalysisCache().getDatabase(NoSideEffectMethodsDatabase.class);
reset();
}
@@ -52,7 +62,7 @@ public class RepeatedConditionals extends OpcodeStackDetector {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.bcel.OpcodeStackDetector#sawOpcode(int)
*/
int oldPC;
@@ -70,73 +80,69 @@ public class RepeatedConditionals extends OpcodeStackDetector {
@Override
public void sawOpcode(int seen) {
- if (isRegisterStore() || isReturn(seen) || isSwitch(seen) || seen == INVOKEINTERFACE || seen == INVOKESPECIAL
- || seen == INVOKESTATIC || seen == INVOKEVIRTUAL || seen == PUTFIELD || seen == PUTSTATIC) {
+ if (hasSideEffect(seen)) {
reset();
} else if (stack.getStackDepth() == 0) {
- check: if (emptyStackLocations.size() > 1) {
- int first = emptyStackLocations.get(emptyStackLocations.size() - 2);
- int second = emptyStackLocations.get(emptyStackLocations.size() - 1);
- int third = getPC();
- if (third - second == second - first) {
- int endOfFirstSegment = prevOpcodeLocations.get(emptyStackLocations.size() - 1);
- int endOfSecondSegment = oldPC;
- int opcodeAtEndOfFirst = getCodeByte(endOfFirstSegment);
- int opcodeAtEndOfSecond = getCodeByte(endOfSecondSegment);
-
- if (!isBranch(opcodeAtEndOfFirst) || !isBranch(opcodeAtEndOfSecond)) {
- break check;
- }
- if (opcodeAtEndOfFirst == Opcodes.GOTO || opcodeAtEndOfSecond == Opcodes.GOTO) {
- break check;
- }
- if (opcodeAtEndOfFirst != opcodeAtEndOfSecond
- && !areOppositeBranches(opcodeAtEndOfFirst, opcodeAtEndOfSecond)) {
- break check;
- }
+ if (emptyStackLocations.size() > 1) {
+ for(int n=1; n<=emptyStackLocations.size()/2; n++) {
+ int first = emptyStackLocations.get(emptyStackLocations.size() - 2*n);
+ int second = emptyStackLocations.get(emptyStackLocations.size() - n);
+ int third = getPC();
+ if (third - second == second - first) {
+ int endOfFirstSegment = prevOpcodeLocations.get(emptyStackLocations.size() - n);
+ int endOfSecondSegment = oldPC;
+ int opcodeAtEndOfFirst = getCodeByte(endOfFirstSegment);
+ int opcodeAtEndOfSecond = getCodeByte(endOfSecondSegment);
+
+ if (!isBranch(opcodeAtEndOfFirst) || !isBranch(opcodeAtEndOfSecond)) {
+ continue;
+ }
+ if (opcodeAtEndOfFirst == Opcodes.GOTO || opcodeAtEndOfSecond == Opcodes.GOTO) {
+ continue;
+ }
+ if (opcodeAtEndOfFirst != opcodeAtEndOfSecond
+ && !areOppositeBranches(opcodeAtEndOfFirst, opcodeAtEndOfSecond)) {
+ continue;
+ }
- byte[] code = getCode().getCode();
- if (first == endOfFirstSegment) {
- break check;
- }
- for (int i = first; i < endOfFirstSegment; i++) {
- if (code[i] != code[i - first + second]) {
- break check;
+ if (first == endOfFirstSegment) {
+ continue;
+ }
+ Integer firstTarget = branchTargets.get(endOfFirstSegment);
+ Integer secondTarget = branchTargets.get(endOfSecondSegment);
+ if (firstTarget == null || secondTarget == null) {
+ continue;
+ }
+ if (firstTarget >= second && firstTarget <= endOfSecondSegment) {
+ // first jumps inside second
+ continue;
+ }
+ boolean identicalCheck = firstTarget.equals(secondTarget) && opcodeAtEndOfFirst == opcodeAtEndOfSecond
+ || (firstTarget.intValue() == getPC() && opcodeAtEndOfFirst != opcodeAtEndOfSecond);
+ if(!compareCode(first, endOfFirstSegment, second, endOfSecondSegment, !identicalCheck)) {
+ continue;
+ }
+ SourceLineAnnotation firstSourceLine = SourceLineAnnotation.fromVisitedInstructionRange(getClassContext(),
+ this, first, endOfFirstSegment - 1);
+ SourceLineAnnotation secondSourceLine = SourceLineAnnotation.fromVisitedInstructionRange(getClassContext(),
+ this, second, endOfSecondSegment - 1);
+
+ int priority = HIGH_PRIORITY;
+ if (firstSourceLine.getStartLine() == -1 || firstSourceLine.getStartLine() != secondSourceLine.getEndLine()) {
+ priority++;
+ }
+ if (stack.isJumpTarget(second)) {
+ priority++;
+ }
+ if (!identicalCheck) {
+ // opposite checks
+ priority += 2;
}
- }
- if (false) {
- System.out.println(getFullyQualifiedMethodName());
- System.out.println(first + " ... " + endOfFirstSegment + " : " + OPCODE_NAMES[opcodeAtEndOfFirst]);
- System.out.println(second + " ... " + endOfSecondSegment + " : " + OPCODE_NAMES[opcodeAtEndOfSecond]);
- }
- SourceLineAnnotation firstSourceLine = SourceLineAnnotation.fromVisitedInstructionRange(getClassContext(),
- this, first, endOfFirstSegment - 1);
- SourceLineAnnotation secondSourceLine = SourceLineAnnotation.fromVisitedInstructionRange(getClassContext(),
- this, second, endOfSecondSegment - 1);
-
- int priority = HIGH_PRIORITY;
- if (firstSourceLine.getStartLine() == -1 || firstSourceLine.getStartLine() != secondSourceLine.getEndLine()) {
- priority++;
- }
- if (stack.isJumpTarget(second)) {
- priority++;
- }
- Integer firstTarget = branchTargets.get(endOfFirstSegment);
- Integer secondTarget = branchTargets.get(endOfSecondSegment);
- if (firstTarget == null || secondTarget == null) {
- break check;
- }
- if (firstTarget.equals(secondTarget) && opcodeAtEndOfFirst == opcodeAtEndOfSecond
- || firstTarget.intValue() == getPC()) {
- // identical checks;
- } else {
- // opposite checks
- priority += 2;
- }
- BugInstance bug = new BugInstance(this, "RpC_REPEATED_CONDITIONAL_TEST", priority).addClassAndMethod(this)
- .add(firstSourceLine).add(secondSourceLine);
- bugReporter.reportBug(bug);
+ BugInstance bug = new BugInstance(this, "RpC_REPEATED_CONDITIONAL_TEST", priority).addClassAndMethod(this)
+ .add(firstSourceLine).add(secondSourceLine);
+ bugReporter.reportBug(bug);
+ }
}
}
emptyStackLocations.add(getPC());
@@ -146,6 +152,77 @@ public class RepeatedConditionals extends OpcodeStackDetector {
oldPC = getPC();
}
+ private boolean compareCode(int first, int endOfFirstSegment, int second,
+ int endOfSecondSegment, boolean oppositeChecks) {
+ if(endOfFirstSegment-first != endOfSecondSegment-second) {
+ return false;
+ }
+ MethodGen methodGen = null;
+ try {
+ methodGen = Global.getAnalysisCache().getMethodAnalysis(MethodGen.class, getMethodDescriptor());
+ } catch (CheckedAnalysisException e) {
+ // Ignore
+ }
+ if(methodGen == null) {
+ // MethodGen is absent for some reason: fallback to byte-to-byte comparison
+ byte[] code = getCode().getCode();
+ for (int i = first; i < endOfFirstSegment; i++) {
+ if (code[i] != code[i - first + second]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ InstructionHandle firstHandle = methodGen.getInstructionList().findHandle(first);
+ InstructionHandle secondHandle = methodGen.getInstructionList().findHandle(second);
+ while(true) {
+ if(firstHandle == null || secondHandle == null) {
+ return false;
+ }
+ if(firstHandle.getPosition() >= endOfFirstSegment) {
+ return secondHandle.getPosition() >= endOfSecondSegment;
+ }
+ if(secondHandle.getPosition() >= endOfSecondSegment) {
+ return firstHandle.getPosition() >= endOfFirstSegment;
+ }
+ Instruction firstInstruction = firstHandle.getInstruction();
+ Instruction secondInstruction = secondHandle.getInstruction();
+ if(firstInstruction instanceof BranchInstruction && secondInstruction instanceof BranchInstruction) {
+ int firstOpcode = firstInstruction.getOpcode();
+ int secondOpcode = secondInstruction.getOpcode();
+ if(firstOpcode != secondOpcode) {
+ return false;
+ }
+ int firstTarget = ((BranchInstruction)firstInstruction).getTarget().getPosition();
+ int secondTarget = ((BranchInstruction)secondInstruction).getTarget().getPosition();
+ if(firstTarget == second) {
+ if(oppositeChecks || secondTarget <= endOfSecondSegment) {
+ return false;
+ }
+ } else {
+ if(!((firstTarget >= first && firstTarget <= endOfFirstSegment && firstTarget - first == secondTarget - second)
+ || firstTarget == secondTarget)) {
+ return false;
+ }
+ }
+ } else {
+ if(!firstInstruction.equals(secondInstruction)) {
+ return false;
+ }
+ }
+ firstHandle = firstHandle.getNext();
+ secondHandle = secondHandle.getNext();
+ }
+ }
+
+ private boolean hasSideEffect(int seen) {
+ if(seen == INVOKEVIRTUAL || seen == INVOKESPECIAL || seen == INVOKEINTERFACE || seen == INVOKESTATIC) {
+ return noSideEffectMethods.is(getMethodDescriptorOperand(), MethodSideEffectStatus.SE, MethodSideEffectStatus.OBJ);
+ }
+ return isRegisterStore() || isReturn(seen) || isSwitch(seen) || seen == INVOKEDYNAMIC || seen == PUTFIELD
+ || seen == PUTSTATIC;
+ }
+
private void reset() {
emptyStackLocations.clear();
prevOpcodeLocations.clear();
diff --git a/src/java/edu/umd/cs/findbugs/detect/ResolveAllReferences.java b/src/java/edu/umd/cs/findbugs/detect/ResolveAllReferences.java
index fa54116..3633a76 100644
--- a/src/java/edu/umd/cs/findbugs/detect/ResolveAllReferences.java
+++ b/src/java/edu/umd/cs/findbugs/detect/ResolveAllReferences.java
@@ -34,7 +34,7 @@ import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
public class ResolveAllReferences extends PreorderVisitor implements Detector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public ResolveAllReferences(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -68,11 +68,13 @@ public class ResolveAllReferences extends PreorderVisitor implements Detector {
}
}
+ @Override
public void visitClassContext(ClassContext classContext) {
classContext.getJavaClass().accept(this);
}
+ @Override
public void report() {
}
@@ -80,16 +82,18 @@ public class ResolveAllReferences extends PreorderVisitor implements Detector {
String className2 = obj.getClassName();
defined.add(className2);
- for (Method m : obj.getMethods())
+ for (Method m : obj.getMethods()) {
if (!m.isPrivate()) {
String name = getMemberName(obj, className2, m.getNameIndex(), m.getSignatureIndex());
defined.add(name);
}
- for (Field f : obj.getFields())
+ }
+ for (Field f : obj.getFields()) {
if (!f.isPrivate()) {
String name = getMemberName(obj, className2, f.getNameIndex(), f.getSignatureIndex());
defined.add(name);
}
+ }
}
private String getClassName(JavaClass c, int classIndex) {
@@ -107,16 +111,21 @@ public class ResolveAllReferences extends PreorderVisitor implements Detector {
}
private boolean find(JavaClass target, String name, String signature) throws ClassNotFoundException {
- if (target == null)
+ if (target == null) {
return false;
+ }
String ref = getMemberName(target.getClassName(), name, signature);
- if (defined.contains(ref))
+ if (defined.contains(ref)) {
return true;
- if (find(target.getSuperClass(), name, signature))
+ }
+ if (find(target.getSuperClass(), name, signature)) {
return true;
- for (JavaClass i : target.getInterfaces())
- if (find(i, name, signature))
+ }
+ for (JavaClass i : target.getInterfaces()) {
+ if (find(i, name, signature)) {
return true;
+ }
+ }
return false;
}
@@ -127,13 +136,15 @@ public class ResolveAllReferences extends PreorderVisitor implements Detector {
Constant[] constants = cp.getConstantPool();
checkConstant: for (int i = 0; i < constants.length; i++) {
Constant co = constants[i];
- if (co instanceof ConstantDouble || co instanceof ConstantLong)
+ if (co instanceof ConstantDouble || co instanceof ConstantLong) {
i++;
+ }
if (co instanceof ConstantClass) {
String ref = getClassName(obj, i);
- if ((ref.startsWith("java") || ref.startsWith("org.w3c.dom")) && !defined.contains(ref))
+ if ((ref.startsWith("java") || ref.startsWith("org.w3c.dom")) && !defined.contains(ref)) {
bugReporter.reportBug(new BugInstance(this, "VR_UNRESOLVABLE_REFERENCE", NORMAL_PRIORITY).addClass(obj)
.addString(ref));
+ }
} else if (co instanceof ConstantFieldref) {
// do nothing until we handle static fields defined in
@@ -154,9 +165,10 @@ public class ResolveAllReferences extends PreorderVisitor implements Detector {
try {
JavaClass target = Repository.lookupClass(className);
- if (!find(target, name, signature))
+ if (!find(target, name, signature)) {
bugReporter.reportBug(new BugInstance(this, "VR_UNRESOLVABLE_REFERENCE", NORMAL_PRIORITY).addClass(obj)
.addString(getMemberName(target.getClassName(), name, signature)));
+ }
} catch (ClassNotFoundException e) {
bugReporter.reportMissingClass(e);
diff --git a/src/java/edu/umd/cs/findbugs/detect/RuntimeExceptionCapture.java b/src/java/edu/umd/cs/findbugs/detect/RuntimeExceptionCapture.java
old mode 100644
new mode 100755
index 7e7eb44..327c83c
--- a/src/java/edu/umd/cs/findbugs/detect/RuntimeExceptionCapture.java
+++ b/src/java/edu/umd/cs/findbugs/detect/RuntimeExceptionCapture.java
@@ -62,7 +62,7 @@ import edu.umd.cs.findbugs.util.ClassName;
/**
* RuntimeExceptionCapture
- *
+ *
* @author Brian Goetz
* @author Bill Pugh
* @author David Hovemeyer
@@ -70,13 +70,13 @@ import edu.umd.cs.findbugs.util.ClassName;
public class RuntimeExceptionCapture extends OpcodeStackDetector implements StatelessDetector {
private static final boolean DEBUG = SystemProperties.getBoolean("rec.debug");
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
+
+ private final List<ExceptionCaught> catchList = new ArrayList<ExceptionCaught>();
- private List<ExceptionCaught> catchList = new ArrayList<ExceptionCaught>();
-
- private List<ExceptionThrown> throwList = new ArrayList<ExceptionThrown>();
+ private final List<ExceptionThrown> throwList = new ArrayList<ExceptionThrown>();
- private BugAccumulator accumulator;
+ private final BugAccumulator accumulator;
private static class ExceptionCaught {
public String exceptionClass;
@@ -118,42 +118,48 @@ public class RuntimeExceptionCapture extends OpcodeStackDetector implements Stat
accumulator.reportAccumulatedBugs();
}
- @Override
- public void visitAfter(Code obj) {
+ @Override
+ public void visitAfter(Code obj) {
for (ExceptionCaught caughtException : catchList) {
Set<String> thrownSet = new HashSet<String>();
for (ExceptionThrown thrownException : throwList) {
if (thrownException.offset >= caughtException.startOffset && thrownException.offset < caughtException.endOffset) {
thrownSet.add(thrownException.exceptionClass);
- if (thrownException.exceptionClass.equals(caughtException.exceptionClass))
+ if (thrownException.exceptionClass.equals(caughtException.exceptionClass)) {
caughtException.seen = true;
+ }
}
}
int catchClauses = 0;
- if (caughtException.exceptionClass.equals("java.lang.Exception") && !caughtException.seen) {
+ if ("java.lang.Exception".equals(caughtException.exceptionClass) && !caughtException.seen) {
// Now we have a case where Exception is caught, but not thrown
boolean rteCaught = false;
for (ExceptionCaught otherException : catchList) {
if (otherException.startOffset == caughtException.startOffset
&& otherException.endOffset == caughtException.endOffset) {
catchClauses++;
- if (otherException.exceptionClass.equals("java.lang.RuntimeException"))
+ if ("java.lang.RuntimeException".equals(otherException.exceptionClass)) {
rteCaught = true;
+ }
}
}
int range = caughtException.endOffset - caughtException.startOffset;
if (!rteCaught) {
int priority = LOW_PRIORITY + 1;
- if (range > 300)
+ if (range > 300) {
priority--;
- else if (range < 30)
+ } else if (range < 30) {
priority++;
- if (catchClauses > 1)
+ }
+ if (catchClauses > 1) {
priority++;
- if (thrownSet.size() > 1)
+ }
+ if (thrownSet.size() > 1) {
priority--;
- if (caughtException.dead)
+ }
+ if (caughtException.dead) {
priority--;
+ }
accumulator.accumulateBug(new BugInstance(this, "REC_CATCH_EXCEPTION", priority).addClassAndMethod(this),
SourceLineAnnotation.fromVisitedInstruction(getClassContext(), this, caughtException.sourcePC));
}
@@ -168,8 +174,9 @@ public class RuntimeExceptionCapture extends OpcodeStackDetector implements Stat
try {
super.visit(obj);
int type = obj.getCatchType();
- if (type == 0)
+ if (type == 0) {
return;
+ }
String name = getConstantPool().constantToString(getConstantPool().getConstant(type));
ExceptionCaught caughtException = new ExceptionCaught(name, obj.getStartPC(), obj.getEndPC(), obj.getHandlerPC());
@@ -216,10 +223,11 @@ public class RuntimeExceptionCapture extends OpcodeStackDetector implements Stat
OpcodeStack.Item item = stack.getStackItem(0);
String signature = item.getSignature();
if (signature != null && signature.length() > 0) {
- if (signature.startsWith("L"))
+ if (signature.startsWith("L")) {
signature = SignatureConverter.convert(signature);
- else
+ } else {
signature = signature.replace('/', '.');
+ }
throwList.add(new ExceptionThrown(signature, getPC()));
}
}
@@ -229,23 +237,27 @@ public class RuntimeExceptionCapture extends OpcodeStackDetector implements Stat
case INVOKESPECIAL:
case INVOKESTATIC:
String className = getClassConstantOperand();
- if (!className.startsWith("["))
+ if (!className.startsWith("[")) {
try {
XClass c = Global.getAnalysisCache().getClassAnalysis(XClass.class,
DescriptorFactory.createClassDescriptor(className));
XMethod m = Hierarchy2.findInvocationLeastUpperBound(c, getNameConstantOperand(), getSigConstantOperand(),
seen == INVOKESTATIC, seen == INVOKEINTERFACE);
- if (m == null)
+ if (m == null) {
break;
+ }
String[] exceptions = m.getThrownExceptions();
- if (exceptions != null)
- for (String name : exceptions)
+ if (exceptions != null) {
+ for (String name : exceptions) {
throwList.add(new ExceptionThrown(ClassName.toDottedClassName(name), getPC()));
+ }
+ }
} catch (MissingClassException e) {
bugReporter.reportMissingClass(e.getClassDescriptor());
} catch (CheckedAnalysisException e) {
bugReporter.logError("Error looking up " + className, e);
}
+ }
break;
default:
break;
@@ -255,4 +267,3 @@ public class RuntimeExceptionCapture extends OpcodeStackDetector implements Stat
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/SerializableIdiom.java b/src/java/edu/umd/cs/findbugs/detect/SerializableIdiom.java
index 753a9e0..47dd3d4 100644
--- a/src/java/edu/umd/cs/findbugs/detect/SerializableIdiom.java
+++ b/src/java/edu/umd/cs/findbugs/detect/SerializableIdiom.java
@@ -74,7 +74,7 @@ public class SerializableIdiom extends OpcodeStackDetector {
boolean isGUIClass;
boolean isEjbImplClass;
-
+
boolean isJSPClass;
boolean foundSynthetic;
@@ -119,6 +119,8 @@ public class SerializableIdiom extends OpcodeStackDetector {
private boolean directlyImplementsExternalizable;
+ private final boolean testingEnabled;
+
// private JavaClass serializable;
// private JavaClass collection;
// private JavaClass map;
@@ -126,6 +128,7 @@ public class SerializableIdiom extends OpcodeStackDetector {
public SerializableIdiom(BugReporter bugReporter) {
this.bugReporter = bugReporter;
+ testingEnabled = SystemProperties.getBoolean("report_TESTING_pattern_in_standard_detectors");
}
@Override
@@ -136,8 +139,9 @@ public class SerializableIdiom extends OpcodeStackDetector {
private void flush() {
if (!isAbstract && !((sawReadExternal && sawWriteExternal) || (sawReadObject && sawWriteObject))) {
- for (BugInstance aFieldWarningList : fieldWarningList)
+ for (BugInstance aFieldWarningList : fieldWarningList) {
bugReporter.reportBug(aFieldWarningList);
+ }
}
fieldWarningList.clear();
}
@@ -155,15 +159,16 @@ public class SerializableIdiom extends OpcodeStackDetector {
String superClassname = obj.getSuperclassName();
// System.out.println("superclass of " + getClassName() + " is " +
// superClassname);
- isEnum = superClassname.equals("java.lang.Enum");
- if (isEnum)
+ isEnum = "java.lang.Enum".equals(superClassname);
+ if (isEnum) {
return;
+ }
int flags = obj.getAccessFlags();
isAbstract = (flags & ACC_ABSTRACT) != 0 || (flags & ACC_INTERFACE) != 0;
isAnonymousInnerClass = anonymousInnerClassNamePattern.matcher(getClassName()).matches();
innerClassHasOuterInstance = false;
for (Field f : obj.getFields()) {
- if (f.getName().equals("this$0")) {
+ if ("this$0".equals(f.getName())) {
innerClassHasOuterInstance = true;
break;
}
@@ -187,13 +192,13 @@ public class SerializableIdiom extends OpcodeStackDetector {
// Does this class directly implement Serializable?
String[] interface_names = obj.getInterfaceNames();
for (String interface_name : interface_names) {
- if (interface_name.equals("java.io.Externalizable")) {
+ if ("java.io.Externalizable".equals(interface_name)) {
directlyImplementsExternalizable = true;
isExternalizable = true;
if (DEBUG) {
System.out.println("Directly implements Externalizable: " + getClassName());
}
- } else if (interface_name.equals("java.io.Serializable")) {
+ } else if ("java.io.Serializable".equals(interface_name)) {
implementsSerializableDirectly = true;
isSerializable = true;
if (DEBUG) {
@@ -224,7 +229,7 @@ public class SerializableIdiom extends OpcodeStackDetector {
superClassHasReadObject = false;
superClassImplementsSerializable = isSerializable && !implementsSerializableDirectly;
ClassDescriptor superclassDescriptor = getXClass().getSuperclassDescriptor();
- if (superclassDescriptor != null)
+ if (superclassDescriptor != null) {
try {
XClass superXClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, superclassDescriptor);
if (superXClass != null) {
@@ -235,12 +240,13 @@ public class SerializableIdiom extends OpcodeStackDetector {
DescriptorFactory.createClassDescriptor(java.io.Serializable.class));
superClassHasVoidConstructor = false;
for (XMethod m : superXClass.getXMethods()) {
- if (m.getName().equals("<init>") && m.getSignature().equals("()V") && !m.isPrivate()) {
+ if ("<init>".equals(m.getName()) && "()V".equals(m.getSignature()) && !m.isPrivate()) {
superClassHasVoidConstructor = true;
}
- if (m.getName().equals("readObject") && m.getSignature().equals("(Ljava/io/ObjectInputStream;)V")
- && m.isPrivate())
+ if ("readObject".equals(m.getName()) && "(Ljava/io/ObjectInputStream;)V".equals(m.getSignature())
+ && m.isPrivate()) {
superClassHasReadObject = true;
+ }
}
}
} catch (ClassNotFoundException e) {
@@ -248,18 +254,19 @@ public class SerializableIdiom extends OpcodeStackDetector {
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("Error while analyzing " + obj.getClassName(), e);
}
+ }
// Is this a GUI or other class that is rarely serialized?
isGUIClass = false;
isEjbImplClass = false;
- if (true || !directlyImplementsExternalizable && !implementsSerializableDirectly) {
+ if (true /*|| !directlyImplementsExternalizable && !implementsSerializableDirectly*/) {
isEjbImplClass = Subtypes2.instanceOf(obj, "javax.ejb.SessionBean");
isJSPClass = Subtypes2.isJSP(obj);
isGUIClass = (Subtypes2.instanceOf(obj, "java.lang.Throwable") || Subtypes2.instanceOf(obj, "java.awt.Component")
|| Subtypes2.instanceOf(obj, "java.awt.Component$AccessibleAWTComponent")
|| Subtypes2.instanceOf(obj, "java.awt.event.ActionListener") || Subtypes2.instanceOf(obj,
- "java.util.EventListener"));
+ "java.util.EventListener"));
if (!isGUIClass) {
JavaClass o = obj;
while (o != null) {
@@ -285,18 +292,20 @@ public class SerializableIdiom extends OpcodeStackDetector {
if (isSerializable) {
for (Method m : obj.getMethods()) {
- if (m.getName().equals("readObject") && m.getSignature().equals("(Ljava/io/ObjectInputStream;)V"))
+ if ("readObject".equals(m.getName()) && "(Ljava/io/ObjectInputStream;)V".equals(m.getSignature())) {
sawReadObject = true;
- else if (m.getName().equals("readResolve") && m.getSignature().startsWith("()"))
+ } else if ("readResolve".equals(m.getName()) && m.getSignature().startsWith("()")) {
sawReadResolve = true;
- else if (m.getName().equals("readObjectNoData") && m.getSignature().equals("()V"))
+ } else if ("readObjectNoData".equals(m.getName()) && "()V".equals(m.getSignature())) {
sawReadObject = true;
- else if (m.getName().equals("writeObject") && m.getSignature().equals("(Ljava/io/ObjectOutputStream;)V"))
+ } else if ("writeObject".equals(m.getName()) && "(Ljava/io/ObjectOutputStream;)V".equals(m.getSignature())) {
sawWriteObject = true;
+ }
}
for (Field f : obj.getFields()) {
- if (f.isTransient())
+ if (f.isTransient()) {
seenTransientField = true;
+ }
}
}
}
@@ -308,13 +317,14 @@ public class SerializableIdiom extends OpcodeStackDetector {
|| sawWriteObject
|| seenTransientField
|| AnalysisContext.currentAnalysisContext().getUnreadFieldsData()
- .existsStrongEvidenceForIntendedSerialization(this.getClassDescriptor());
+ .existsStrongEvidenceForIntendedSerialization(this.getClassDescriptor());
}
@Override
public void visitAfter(JavaClass obj) {
- if (isEnum)
+ if (isEnum) {
return;
+ }
if (DEBUG) {
System.out.println(getDottedClassName());
System.out.println(" hasPublicVoidConstructor: " + hasPublicVoidConstructor);
@@ -332,29 +342,37 @@ public class SerializableIdiom extends OpcodeStackDetector {
XField fieldX = e.getKey();
int priority = NORMAL_PRIORITY;
- if (transientFieldsSetInConstructor.contains(e.getKey()))
+ if (transientFieldsSetInConstructor.contains(e.getKey())) {
priority--;
+ }
- if (isGUIClass)
+ if (isGUIClass) {
priority++;
- if (isEjbImplClass)
+ }
+ if (isEjbImplClass) {
priority++;
- if (isJSPClass)
+ }
+ if (isJSPClass) {
priority++;
- if (e.getValue() < 3)
+ }
+ if (e.getValue() < 3) {
priority++;
- if (transientFieldsSetToDefaultValueInConstructor.contains(e.getKey()))
+ }
+ if (transientFieldsSetToDefaultValueInConstructor.contains(e.getKey())) {
priority++;
+ }
if (obj.isAbstract()) {
priority++;
- if (priority < Priorities.LOW_PRIORITY)
+ if (priority < Priorities.LOW_PRIORITY) {
priority = Priorities.LOW_PRIORITY;
+ }
}
try {
double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(fieldX.getSignature());
- if (isSerializable < 0.6)
+ if (isSerializable < 0.6) {
priority++;
+ }
} catch (ClassNotFoundException e1) {
// ignore it
}
@@ -368,30 +386,37 @@ public class SerializableIdiom extends OpcodeStackDetector {
if (isSerializable && !isExternalizable && !superClassHasVoidConstructor && !superClassImplementsSerializable) {
int priority = implementsSerializableDirectly || seenTransientField ? HIGH_PRIORITY
: (sawSerialVersionUID ? NORMAL_PRIORITY : LOW_PRIORITY);
- if (isGUIClass || isEjbImplClass || isJSPClass)
+ if (isGUIClass || isEjbImplClass || isJSPClass) {
priority++;
+ }
bugReporter.reportBug(new BugInstance(this, "SE_NO_SUITABLE_CONSTRUCTOR", priority).addClass(getThisClass()
.getClassName()));
}
// Downgrade class-level warnings if it's a GUI or EJB-implementation
// class.
int priority = (isGUIClass || isEjbImplClass || isJSPClass) ? LOW_PRIORITY : NORMAL_PRIORITY;
- if (obj.getClassName().endsWith("_Stub"))
+ if (obj.getClassName().endsWith("_Stub")) {
priority++;
+ }
- if (isExternalizable && !hasPublicVoidConstructor && !isAbstract)
+ if (isExternalizable && !hasPublicVoidConstructor && !isAbstract) {
bugReporter.reportBug(new BugInstance(this, "SE_NO_SUITABLE_CONSTRUCTOR_FOR_EXTERNALIZATION",
directlyImplementsExternalizable ? HIGH_PRIORITY : NORMAL_PRIORITY).addClass(getThisClass().getClassName()));
- if (!foundSynthetic)
+ }
+ if (!foundSynthetic) {
priority++;
- if (seenTransientField)
+ }
+ if (seenTransientField) {
priority--;
+ }
if (!isAnonymousInnerClass && !isExternalizable && !isGUIClass && !obj.isAbstract() && isSerializable && !isAbstract
- && !sawSerialVersionUID && !isEjbImplClass && !isJSPClass)
+ && !sawSerialVersionUID && !isEjbImplClass && !isJSPClass) {
bugReporter.reportBug(new BugInstance(this, "SE_NO_SERIALVERSIONID", priority).addClass(this));
+ }
- if (writeObjectIsSynchronized && !foundSynchronizedMethods)
+ if (writeObjectIsSynchronized && !foundSynchronizedMethods) {
bugReporter.reportBug(new BugInstance(this, "WS_WRITEOBJECT_SYNC", LOW_PRIORITY).addClass(this));
+ }
}
@Override
@@ -399,36 +424,41 @@ public class SerializableIdiom extends OpcodeStackDetector {
int accessFlags = obj.getAccessFlags();
boolean isSynchronized = (accessFlags & ACC_SYNCHRONIZED) != 0;
- if (getMethodName().equals("<init>") && getMethodSig().equals("()V") && (accessFlags & ACC_PUBLIC) != 0)
+ if ("<init>".equals(getMethodName()) && "()V".equals(getMethodSig()) && (accessFlags & ACC_PUBLIC) != 0) {
hasPublicVoidConstructor = true;
- if (!getMethodName().equals("<init>") && isSynthetic(obj))
+ }
+ if (!"<init>".equals(getMethodName()) && isSynthetic(obj))
+ {
foundSynthetic = true;
- // System.out.println(methodName + isSynchronized);
+ // System.out.println(methodName + isSynchronized);
+ }
- if (getMethodName().equals("readExternal") && getMethodSig().equals("(Ljava/io/ObjectInput;)V")) {
+ if ("readExternal".equals(getMethodName()) && "(Ljava/io/ObjectInput;)V".equals(getMethodSig())) {
sawReadExternal = true;
- if (DEBUG && !obj.isPrivate())
+ if (DEBUG && !obj.isPrivate()) {
System.out.println("Non-private readExternal method in: " + getDottedClassName());
- } else if (getMethodName().equals("writeExternal") && getMethodSig().equals("(Ljava/io/Objectoutput;)V")) {
+ }
+ } else if ("writeExternal".equals(getMethodName()) && "(Ljava/io/Objectoutput;)V".equals(getMethodSig())) {
sawWriteExternal = true;
- if (DEBUG && !obj.isPrivate())
+ if (DEBUG && !obj.isPrivate()) {
System.out.println("Non-private writeExternal method in: " + getDottedClassName());
- } else if (getMethodName().equals("readResolve") && getMethodSig().startsWith("()") && isSerializable) {
+ }
+ } else if ("readResolve".equals(getMethodName()) && getMethodSig().startsWith("()") && isSerializable) {
sawReadResolve = true;
- if (!getMethodSig().equals("()Ljava/lang/Object;"))
+ if (!"()Ljava/lang/Object;".equals(getMethodSig())) {
bugReporter.reportBug(new BugInstance(this, "SE_READ_RESOLVE_MUST_RETURN_OBJECT", HIGH_PRIORITY)
- .addClassAndMethod(this));
- else if (obj.isStatic())
+ .addClassAndMethod(this));
+ } else if (obj.isStatic()) {
bugReporter.reportBug(new BugInstance(this, "SE_READ_RESOLVE_IS_STATIC", HIGH_PRIORITY).addClassAndMethod(this));
- else if (obj.isPrivate())
+ } else if (obj.isPrivate()) {
try {
Set<ClassDescriptor> subtypes = AnalysisContext.currentAnalysisContext().getSubtypes2()
.getSubtypes(getClassDescriptor());
if (subtypes.size() > 1) {
BugInstance bug = new BugInstance(this, "SE_PRIVATE_READ_RESOLVE_NOT_INHERITED", NORMAL_PRIORITY)
- .addClassAndMethod(this);
+ .addClassAndMethod(this);
boolean nasty = false;
- for (ClassDescriptor subclass : subtypes)
+ for (ClassDescriptor subclass : subtypes) {
if (!subclass.equals(getClassDescriptor())) {
XClass xSub = AnalysisContext.currentXFactory().getXClass(subclass);
@@ -438,43 +468,50 @@ public class SerializableIdiom extends OpcodeStackDetector {
nasty = true;
}
}
- if (nasty)
+ }
+ if (nasty) {
bug.setPriority(HIGH_PRIORITY);
- else if (!getThisClass().isPublic())
+ } else if (!getThisClass().isPublic()) {
bug.setPriority(LOW_PRIORITY);
+ }
bugReporter.reportBug(bug);
}
} catch (ClassNotFoundException e) {
bugReporter.reportMissingClass(e);
}
+ }
- } else if (getMethodName().equals("readObject") && getMethodSig().equals("(Ljava/io/ObjectInputStream;)V")
+ } else if ("readObject".equals(getMethodName()) && "(Ljava/io/ObjectInputStream;)V".equals(getMethodSig())
&& isSerializable) {
sawReadObject = true;
- if (!obj.isPrivate())
+ if (!obj.isPrivate()) {
bugReporter.reportBug(new BugInstance(this, "SE_METHOD_MUST_BE_PRIVATE", isExternalizable ? NORMAL_PRIORITY : HIGH_PRIORITY).addClassAndMethod(this));
+ }
- } else if (getMethodName().equals("readObjectNoData") && getMethodSig().equals("()V") && isSerializable) {
+ } else if ("readObjectNoData".equals(getMethodName()) && "()V".equals(getMethodSig()) && isSerializable) {
- if (!obj.isPrivate())
+ if (!obj.isPrivate()) {
bugReporter.reportBug(new BugInstance(this, "SE_METHOD_MUST_BE_PRIVATE", isExternalizable ? NORMAL_PRIORITY : HIGH_PRIORITY).addClassAndMethod(this));
+ }
- } else if (getMethodName().equals("writeObject") && getMethodSig().equals("(Ljava/io/ObjectOutputStream;)V")
+ } else if ("writeObject".equals(getMethodName()) && "(Ljava/io/ObjectOutputStream;)V".equals(getMethodSig())
&& isSerializable) {
sawWriteObject = true;
- if (!obj.isPrivate())
+ if (!obj.isPrivate()) {
bugReporter.reportBug(new BugInstance(this, "SE_METHOD_MUST_BE_PRIVATE", isExternalizable ? NORMAL_PRIORITY : HIGH_PRIORITY).addClassAndMethod(this));
+ }
}
if (isSynchronized) {
- if (getMethodName().equals("readObject") && getMethodSig().equals("(Ljava/io/ObjectInputStream;)V") && isSerializable)
+ if ("readObject".equals(getMethodName()) && "(Ljava/io/ObjectInputStream;)V".equals(getMethodSig()) && isSerializable) {
bugReporter.reportBug(new BugInstance(this, "RS_READOBJECT_SYNC",isExternalizable ? LOW_PRIORITY : NORMAL_PRIORITY).addClassAndMethod(this));
- else if (getMethodName().equals("writeObject") && getMethodSig().equals("(Ljava/io/ObjectOutputStream;)V")
- && isSerializable)
+ } else if ("writeObject".equals(getMethodName()) && "(Ljava/io/ObjectOutputStream;)V".equals(getMethodSig())
+ && isSerializable) {
writeObjectIsSynchronized = true;
- else
+ } else {
foundSynchronizedMethods = true;
+ }
}
super.visit(obj);
@@ -482,9 +519,11 @@ public class SerializableIdiom extends OpcodeStackDetector {
boolean isSynthetic(FieldOrMethod obj) {
Attribute[] a = obj.getAttributes();
- for (Attribute aA : a)
- if (aA instanceof Synthetic)
+ for (Attribute aA : a) {
+ if (aA instanceof Synthetic) {
return true;
+ }
+ }
return false;
}
@@ -501,26 +540,29 @@ public class SerializableIdiom extends OpcodeStackDetector {
XField xField = getXFieldOperand();
if (xField != null && xField.getClassDescriptor().equals(getClassDescriptor())) {
Item first = stack.getStackItem(0);
-
+
boolean isPutOfDefaultValue = first.isNull(); // huh?? ||
- // first.isInitialParameter();
- if (!isPutOfDefaultValue && first.getConstant() != null) {
+ // first.isInitialParameter();
+ if (!isPutOfDefaultValue && first.getConstant() != null && !first.isArray()) {
Object constant = first.getConstant();
- if (constant instanceof Number && ((Number) constant).intValue() == 0 || constant.equals(Boolean.FALSE))
+ if (constant instanceof Number && ((Number) constant).intValue() == 0 || constant.equals(Boolean.FALSE)) {
isPutOfDefaultValue = true;
+ }
}
if (isPutOfDefaultValue) {
- if (getMethodName().equals("<init>"))
+ if ("<init>".equals(getMethodName())) {
transientFieldsSetToDefaultValueInConstructor.add(xField);
+ }
} else {
String nameOfField = getNameConstantOperand();
if (transientFieldsUpdates.containsKey(xField)) {
- if (getMethodName().equals("<init>"))
+ if ("<init>".equals(getMethodName())) {
transientFieldsSetInConstructor.add(xField);
- else
+ } else {
transientFieldsUpdates.put(xField, transientFieldsUpdates.get(xField) + 1);
+ }
} else if (fieldsThatMightBeAProblem.containsKey(nameOfField)) {
try {
@@ -532,7 +574,7 @@ public class SerializableIdiom extends OpcodeStackDetector {
if (isSerializable <= 0.2) {
XField f = fieldsThatMightBeAProblem.get(nameOfField);
- String sig = f.getSignature();
+ String sig = f.getSignature();
// System.out.println("Field signature: " +
// sig);
// System.out.println("Class stored: " +
@@ -540,16 +582,17 @@ public class SerializableIdiom extends OpcodeStackDetector {
String genSig = "L" + classStored.getClassName().replace('.', '/') + ";";
if (!sig.equals(genSig)) {
double bias = 0.0;
- if (!getMethodName().equals("<init>"))
+ if (!"<init>".equals(getMethodName())) {
bias = 1.0;
+ }
int priority = computePriority(isSerializable, bias);
fieldWarningList.add(new BugInstance(this, "SE_BAD_FIELD_STORE", priority)
- .addClass(getThisClass().getClassName()).addField(f).addType(genSig)
- .describe("TYPE_FOUND").addSourceLine(this));
+ .addClass(getThisClass().getClassName()).addField(f).addType(genSig)
+ .describe("TYPE_FOUND").addSourceLine(this));
}
}
- } catch (Exception e) {
+ } catch (ClassNotFoundException e) {
// ignore it
}
}
@@ -564,8 +607,9 @@ public class SerializableIdiom extends OpcodeStackDetector {
public void visit(Field obj) {
int flags = obj.getAccessFlags();
String genericSignature = obj.getGenericSignature();
- if (genericSignature != null && genericSignature.startsWith("T"))
+ if (genericSignature != null && genericSignature.startsWith("T")) {
return;
+ }
FieldSummary fieldSummary = AnalysisContext.currentAnalysisContext().getFieldSummary();
Item summary = fieldSummary.getSummary(getXField());
String fieldSig = summary.getSignature();
@@ -578,10 +622,11 @@ public class SerializableIdiom extends OpcodeStackDetector {
|| Subtypes2.instanceOf(fieldType, "javax.ejb.EJBHome")
|| Subtypes2.instanceOf(fieldType, "javax.ejb.EJBObject")
|| Subtypes2.instanceOf(fieldType, "javax.naming.Context")) {
- if (obj.isTransient())
+ if (testingEnabled && obj.isTransient()) {
bugReporter.reportBug(new BugInstance(this, "TESTING", NORMAL_PRIORITY).addClass(this)
.addVisitedField(this)
.addString("EJB implementation classes should not have fields of this type"));
+ }
return;
}
}
@@ -593,80 +638,93 @@ public class SerializableIdiom extends OpcodeStackDetector {
transientFieldsUpdates.put(getXField(), 0);
} else if (reportTransientFieldOfNonSerializableClass) {
bugReporter.reportBug(new BugInstance(this, "SE_TRANSIENT_FIELD_OF_NONSERIALIZABLE_CLASS", NORMAL_PRIORITY)
- .addClass(this).addVisitedField(this));
+ .addClass(this).addVisitedField(this));
}
} else if (getClassName().indexOf("ObjectStreamClass") == -1 && isSerializable && !isExternalizable
- && fieldSig.indexOf("L") >= 0 && !obj.isTransient() && !obj.isStatic()) {
+ && fieldSig.indexOf('L') >= 0 && !obj.isTransient() && !obj.isStatic()) {
if (DEBUG) {
System.out.println("Examining non-transient field with name: " + getFieldName() + ", sig: " + fieldSig);
}
XField xfield = getXField();
Type type = TypeFrameModelingVisitor.getType(xfield);
- if (type instanceof ReferenceType)
- try {
- ReferenceType rtype = (ReferenceType) type;
-
- double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(rtype);
- if (DEBUG) {
- System.out.println(" isSerializable: " + isSerializable);
- }
- if (isSerializable < 1.0)
- fieldsThatMightBeAProblem.put(obj.getName(), xfield);
- if (isSerializable < 0.9) {
- ReferenceType problemType = DeepSubtypeAnalysis.getLeastSerializableTypeComponent(rtype);
-
- // Priority is LOW for GUI classes (unless explicitly marked
- // Serializable),
- // HIGH if the class directly implements Serializable,
- // NORMAL otherwise.
- int priority = computePriority(isSerializable, 0);
- if (!strongEvidenceForIntendedSerialization()) {
- if (obj.getName().startsWith("this$"))
+ if (type instanceof ReferenceType) {
+ try {
+ ReferenceType rtype = (ReferenceType) type;
+
+ double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(rtype);
+ if (DEBUG) {
+ System.out.println(" isSerializable: " + isSerializable);
+ }
+ if (isSerializable < 1.0) {
+ fieldsThatMightBeAProblem.put(obj.getName(), xfield);
+ }
+ if (isSerializable < 0.9) {
+ ReferenceType problemType = DeepSubtypeAnalysis.getLeastSerializableTypeComponent(rtype);
+
+ // Priority is LOW for GUI classes (unless explicitly marked
+ // Serializable),
+ // HIGH if the class directly implements Serializable,
+ // NORMAL otherwise.
+ int priority = computePriority(isSerializable, 0);
+ if (!strongEvidenceForIntendedSerialization()) {
+ if (obj.getName().startsWith("this$")) {
+ priority = Math.max(priority, NORMAL_PRIORITY);
+ }
+ if (innerClassHasOuterInstance) {
+ if (isAnonymousInnerClass) {
+ priority += 2;
+ } else {
+ priority += 1;
+ }
+ }
+ if (isGUIClass || isEjbImplClass || isJSPClass) {
+ priority++;
+ }
+ } else if (isGUIClass || isEjbImplClass || isJSPClass) {
priority = Math.max(priority, NORMAL_PRIORITY);
- if (innerClassHasOuterInstance) {
- if (isAnonymousInnerClass)
- priority += 2;
- else
- priority += 1;
}
- if (isGUIClass || isEjbImplClass || isJSPClass)
- priority++;
- } else if (isGUIClass || isEjbImplClass || isJSPClass)
- priority = Math.max(priority, NORMAL_PRIORITY);
- if (DEBUG)
- System.out.println("SE_BAD_FIELD: " + getThisClass().getClassName() + " " + obj.getName() + " "
- + isSerializable + " " + implementsSerializableDirectly + " " + sawSerialVersionUID + " "
- + isGUIClass + " " + isEjbImplClass);
- // Report is queued until after the entire class has been
- // seen.
-
- if (obj.getName().equals("this$0"))
- fieldWarningList.add(new BugInstance(this, "SE_BAD_FIELD_INNER_CLASS", priority).addClass(getThisClass()
- .getClassName()));
- else if (isSerializable < 0.9)
- fieldWarningList.add(new BugInstance(this, "SE_BAD_FIELD", priority)
- .addClass(getThisClass().getClassName())
- .addField(xfield).addType(problemType)
- .describe("TYPE_FOUND"));
- } else if (!isGUIClass && !isEjbImplClass && !isJSPClass && obj.getName().equals("this$0"))
- fieldWarningList.add(new BugInstance(this, "SE_INNER_CLASS", implementsSerializableDirectly ? NORMAL_PRIORITY
- : LOW_PRIORITY).addClass(getThisClass().getClassName()));
- } catch (ClassNotFoundException e) {
- if (DEBUG) {
- System.out.println("Caught ClassNotFoundException");
+ if (DEBUG)
+ {
+ System.out.println("SE_BAD_FIELD: " + getThisClass().getClassName() + " " + obj.getName() + " "
+ + isSerializable + " " + implementsSerializableDirectly + " " + sawSerialVersionUID + " "
+ + isGUIClass + " " + isEjbImplClass);
+ // Report is queued until after the entire class has been
+ // seen.
+ }
+
+ if ("this$0".equals(obj.getName())) {
+ fieldWarningList.add(new BugInstance(this, "SE_BAD_FIELD_INNER_CLASS", priority).addClass(getThisClass()
+ .getClassName()));
+ } else if (isSerializable < 0.9) {
+ fieldWarningList.add(new BugInstance(this, "SE_BAD_FIELD", priority)
+ .addClass(getThisClass().getClassName())
+ .addField(xfield).addType(problemType)
+ .describe("TYPE_FOUND"));
+ }
+ } else if (!isGUIClass && !isEjbImplClass && !isJSPClass && "this$0".equals(obj.getName())) {
+ fieldWarningList.add(new BugInstance(this, "SE_INNER_CLASS", implementsSerializableDirectly ? NORMAL_PRIORITY
+ : LOW_PRIORITY).addClass(getThisClass().getClassName()));
+ }
+ } catch (ClassNotFoundException e) {
+ if (DEBUG) {
+ System.out.println("Caught ClassNotFoundException");
+ }
+ bugReporter.reportMissingClass(e);
}
- bugReporter.reportMissingClass(e);
}
}
- if (!getFieldName().startsWith("this") && isSynthetic(obj))
+ if (!getFieldName().startsWith("this") && isSynthetic(obj)) {
foundSynthetic = true;
- if (!getFieldName().equals("serialVersionUID"))
+ }
+ if (!"serialVersionUID".equals(getFieldName())) {
return;
+ }
int mask = ACC_STATIC | ACC_FINAL;
- if (!fieldSig.equals("I") && !fieldSig.equals("J"))
+ if (!"I".equals(fieldSig) && !"J".equals(fieldSig)) {
return;
- if ((flags & mask) == mask && fieldSig.equals("I")) {
+ }
+ if ((flags & mask) == mask && "I".equals(fieldSig)) {
bugReporter.reportBug(new BugInstance(this, "SE_NONLONG_SERIALVERSIONID", LOW_PRIORITY).addClass(this)
.addVisitedField(this));
sawSerialVersionUID = true;
@@ -686,12 +744,13 @@ public class SerializableIdiom extends OpcodeStackDetector {
private int computePriority(double isSerializable, double bias) {
int priority = (int) (1.9 + isSerializable * 3 + bias);
- if (strongEvidenceForIntendedSerialization())
+ if (strongEvidenceForIntendedSerialization()) {
priority--;
- else if (sawSerialVersionUID && priority > NORMAL_PRIORITY)
+ } else if (sawSerialVersionUID && priority > NORMAL_PRIORITY) {
priority--;
- else
+ } else {
priority = Math.max(priority, NORMAL_PRIORITY);
+ }
return priority;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/StartInConstructor.java b/src/java/edu/umd/cs/findbugs/detect/StartInConstructor.java
index 430be80..e5bc79d 100644
--- a/src/java/edu/umd/cs/findbugs/detect/StartInConstructor.java
+++ b/src/java/edu/umd/cs/findbugs/detect/StartInConstructor.java
@@ -37,7 +37,7 @@ import edu.umd.cs.findbugs.ba.ch.Subtypes2;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
public class StartInConstructor extends BytecodeScanningDetector implements StatelessDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private final BugAccumulator bugAccumulator;
@@ -54,7 +54,7 @@ public class StartInConstructor extends BytecodeScanningDetector implements Stat
@Override
public void visit(Code obj) {
- if (getMethodName().equals("<init>") && (getMethod().isPublic() || getMethod().isProtected())) {
+ if ("<init>".equals(getMethodName()) && (getMethod().isPublic() || getMethod().isProtected())) {
super.visit(obj);
bugAccumulator.reportAccumulatedBugs();
}
@@ -62,19 +62,21 @@ public class StartInConstructor extends BytecodeScanningDetector implements Stat
@Override
public void sawOpcode(int seen) {
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("start") && getSigConstantOperand().equals("()V")) {
+ if (seen == INVOKEVIRTUAL && "start".equals(getNameConstantOperand()) && "()V".equals(getSigConstantOperand())) {
try {
if (Hierarchy.isSubtype(getDottedClassConstantOperand(), "java.lang.Thread")) {
int priority = Priorities.NORMAL_PRIORITY;
- if (getPC() + 4 >= getCode().getCode().length)
+ if (getPC() + 4 >= getCode().getCode().length) {
priority = Priorities.LOW_PRIORITY;
+ }
BugInstance bug = new BugInstance(this, "SC_START_IN_CTOR", priority).addClassAndMethod(this)
.addCalledMethod(this);
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
Set<ClassDescriptor> directSubtypes = subtypes2.getDirectSubtypes(getClassDescriptor());
if (!directSubtypes.isEmpty()) {
- for (ClassDescriptor sub : directSubtypes)
+ for (ClassDescriptor sub : directSubtypes) {
bug.addClass(sub).describe(ClassAnnotation.SUBCLASS_ROLE);
+ }
bug.setPriority(Priorities.HIGH_PRIORITY);
}
bugAccumulator.accumulateBug(bug, this);
diff --git a/src/java/edu/umd/cs/findbugs/detect/StaticCalendarDetector.java b/src/java/edu/umd/cs/findbugs/detect/StaticCalendarDetector.java
index d67dbe7..6c04abe 100644
--- a/src/java/edu/umd/cs/findbugs/detect/StaticCalendarDetector.java
+++ b/src/java/edu/umd/cs/findbugs/detect/StaticCalendarDetector.java
@@ -56,7 +56,7 @@ import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
* {@link java.util.Calendar} is unsafe for multithreaded use, static fields
* look suspicous. To work correctly, all access would need to be synchronized
* by the client which cannot be guaranteed.
- *
+ *
* @author Daniel Schneller
*/
public class StaticCalendarDetector extends OpcodeStackDetector {
@@ -102,11 +102,11 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
/** Stores current LDF */
private LockDataflow currentLockDataFlow;
- private Map<XField, BugInstance> pendingBugs = new HashMap<XField, BugInstance>();
+ private final Map<XField, BugInstance> pendingBugs = new HashMap<XField, BugInstance>();
/**
* Creates a new instance of this Detector.
- *
+ *
* @param aReporter
* {@link BugReporter} instance to report found problems to.
*/
@@ -138,22 +138,22 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
if (constant instanceof ConstantClass) {
ConstantClass cc = (ConstantClass) constant;
@SlashedClassName String className = cc.getBytes(pool);
- if (className.equals("java/util/Calendar") || className.equals("java/text/DateFormat")) {
+ if ("java/util/Calendar".equals(className) || "java/text/DateFormat".equals(className)) {
sawDateClass = true;
break;
}
try {
ClassDescriptor cDesc = DescriptorFactory.createClassDescriptor(className);
-
+
if (subtypes2.isSubtype(cDesc, calendarType) || subtypes2.isSubtype(cDesc, dateFormatType)) {
sawDateClass = true;
break;
}
} catch (ClassNotFoundException e) {
- reporter.reportMissingClass(e);
+ reporter.reportMissingClass(e);
}
-
-
+
+
}
}
}
@@ -175,15 +175,17 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
return;
}
String superclassName = getSuperclassName();
- if (!aField.isStatic() && !superclassName.equals("java/lang/Enum"))
+ if (!aField.isStatic() && !"java/lang/Enum".equals(superclassName)) {
return;
- if (!aField.isPublic() && !aField.isProtected())
+ }
+ if (!aField.isPublic() && !aField.isProtected()) {
return;
+ }
ClassDescriptor classOfField = DescriptorFactory.createClassDescriptorFromFieldSignature(aField.getSignature());
String tBugType = null;
int priority = aField.isPublic() && aField.isFinal() && aField.getName().equals(aField.getName().toUpperCase())
&& getThisClass().isPublic() ? HIGH_PRIORITY : NORMAL_PRIORITY;
- if (classOfField != null)
+ if (classOfField != null) {
try {
if (subtypes2.isSubtype(classOfField, calendarType)) {
tBugType = "STCAL_STATIC_CALENDAR_INSTANCE";
@@ -191,8 +193,9 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
} else if (subtypes2.isSubtype(classOfField, dateFormatType)) {
tBugType = "STCAL_STATIC_SIMPLE_DATE_FORMAT_INSTANCE";
}
- if (getClassContext().getXClass().usesConcurrency())
+ if (getClassContext().getXClass().usesConcurrency()) {
priority--;
+ }
if (tBugType != null) {
pendingBugs.put(getXField(), new BugInstance(this, tBugType, priority).addClass(currentClass).addField(this));
@@ -200,19 +203,20 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
} catch (ClassNotFoundException e) {
AnalysisContext.reportMissingClass(e);
}
+ }
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.visitclass.BetterVisitor#visitMethod(org.apache.bcel
* .classfile.Method)
*/
@Override
public void visitMethod(Method obj) {
- if (sawDateClass)
+ if (sawDateClass) {
try {
super.visitMethod(obj);
currentMethod = obj;
@@ -223,6 +227,7 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
} catch (DataflowAnalysisException e) {
reporter.logError("Synchronization check in Static Calendar Detector caught an error.", e);
}
+ }
}
@Override
@@ -239,7 +244,7 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
* {@link java.util.Calendar} or {@link java.text.DateFormat} fields. The
* {@link OpcodeStack} is used to determine if an invocation is done on such
* a static field.
- *
+ *
* @param seen
* An opcode to be analyzed
* @see edu.umd.cs.findbugs.visitclass.DismantleBytecode#sawOpcode(int)
@@ -290,12 +295,14 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
return;
}
- if (getMethodName().equals("<clinit>") && field.getClassName().equals(getDottedClassName()))
+ if ("<clinit>".equals(getMethodName()) && field.getClassName().equals(getDottedClassName())) {
return;
+ }
String invokedName = getNameConstantOperand();
- if (invokedName.startsWith("get"))
+ if (invokedName.startsWith("get")) {
return;
- if (invokedName.equals("equals") && numArguments == 1) {
+ }
+ if ("equals".equals(invokedName) && numArguments == 1) {
OpcodeStack.Item passedAsArgument = stack.getStackItem(0);
field = passedAsArgument.getXField();
if (field == null || !field.isStatic()) {
@@ -305,8 +312,9 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
if (!SystemProperties.getBoolean(PROP_SKIP_SYNCHRONIZED_CHECK)) {
// check synchronization
- if (isLocked())
+ if (isLocked()) {
return;
+ }
}
// if we get here, we want to generate a report, depending on the
@@ -316,19 +324,22 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
tBugType = "STCAL_INVOKE_ON_STATIC_CALENDAR_INSTANCE";
} else if (isDateFormat) {
tBugType = "STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCE";
- } else
+ } else {
throw new IllegalStateException("Not possible");
+ }
int priority;
- if (amVisitingMainMethod())
+ if (amVisitingMainMethod()) {
priority = LOW_PRIORITY;
- else {
- if (getClassContext().getXClass().usesConcurrency())
+ } else {
+ if (getClassContext().getXClass().usesConcurrency()) {
priority = NORMAL_PRIORITY;
- else
+ } else {
priority = LOW_PRIORITY;
- if (invokedName.startsWith("set") || invokedName.equals("format") || invokedName.equals("add")
- || invokedName.equals("clear") || invokedName.equals("parse") || invokedName.equals("applyPattern"))
+ }
+ if (invokedName.startsWith("set") || "format".equals(invokedName) || "add".equals(invokedName)
+ || "clear".equals(invokedName) || "parse".equals(invokedName) || "applyPattern".equals(invokedName)) {
priority--;
+ }
}
bugAccumulator.accumulateBug(new BugInstance(this, tBugType, priority).addClassAndMethod(this).addCalledMethod(this)
.addOptionalField(field), this);
@@ -338,9 +349,6 @@ public class StaticCalendarDetector extends OpcodeStackDetector {
}
}
- /**
- * @return
- */
private boolean isLocked() {
try {
if (currentMethod != null && currentLockDataFlow != null && currentCFG != null) {
diff --git a/src/java/edu/umd/cs/findbugs/detect/StaticFieldLoadStreamFactory.java b/src/java/edu/umd/cs/findbugs/detect/StaticFieldLoadStreamFactory.java
index 4adada1..2e69bb3 100644
--- a/src/java/edu/umd/cs/findbugs/detect/StaticFieldLoadStreamFactory.java
+++ b/src/java/edu/umd/cs/findbugs/detect/StaticFieldLoadStreamFactory.java
@@ -43,7 +43,7 @@ public class StaticFieldLoadStreamFactory implements StreamFactory {
/**
* Constructor. Created Stream objects will be marked as uninteresting.
- *
+ *
* @param streamBaseClass
* the base class of the stream objects created by the factory
* @param className
@@ -60,21 +60,23 @@ public class StaticFieldLoadStreamFactory implements StreamFactory {
this.fieldSig = fieldSig;
}
+ @Override
public Stream createStream(Location location, ObjectType type, ConstantPoolGen cpg,
RepositoryLookupFailureCallback lookupFailureCallback) {
Instruction ins = location.getHandle().getInstruction();
- if (ins.getOpcode() != Constants.GETSTATIC)
+ if (ins.getOpcode() != Constants.GETSTATIC) {
return null;
+ }
GETSTATIC getstatic = (GETSTATIC) ins;
if (!className.equals(getstatic.getClassName(cpg)) || !fieldName.equals(getstatic.getName(cpg))
- || !fieldSig.equals(getstatic.getSignature(cpg)))
+ || !fieldSig.equals(getstatic.getSignature(cpg))) {
return null;
+ }
return new Stream(location, type.getClassName(), streamBaseClass).setIgnoreImplicitExceptions(true).setIsOpenOnCreation(
true);
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/Stream.java b/src/java/edu/umd/cs/findbugs/detect/Stream.java
index 4a0e836..16f177f 100644
--- a/src/java/edu/umd/cs/findbugs/detect/Stream.java
+++ b/src/java/edu/umd/cs/findbugs/detect/Stream.java
@@ -50,7 +50,7 @@ import edu.umd.cs.findbugs.ba.ResourceValueFrame;
* can customize how they work for different kinds of streams
*/
public class Stream extends ResourceCreationPoint implements Comparable<Stream> {
- private String streamBase;
+ private final String streamBase;
private boolean isUninteresting;
@@ -75,7 +75,7 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
* Constructor. By default, Stream objects are marked as uninteresting.
* setInteresting("BUG_TYPE") must be called explicitly to mark the Stream
* as interesting.
- *
+ *
* @param location
* where the stream is created
* @param streamClass
@@ -93,7 +93,7 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
/**
* Mark this Stream as interesting.
- *
+ *
* @param bugType
* the bug type that should be reported if the stream is not
* closed on all paths out of the method
@@ -125,7 +125,7 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
/**
* Set the number of the parameter which passes the stream instance.
- *
+ *
* @param instanceParam
* number of the parameter passing the stream instance
*/
@@ -181,12 +181,14 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
}
public boolean isStreamOpen(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg, ResourceValueFrame frame) {
- if (isOpenOnCreation)
+ if (isOpenOnCreation) {
return false;
+ }
Instruction ins = handle.getInstruction();
- if (!(ins instanceof INVOKESPECIAL))
+ if (!(ins instanceof INVOKESPECIAL)) {
return false;
+ }
// Does this instruction open the stream?
INVOKESPECIAL inv = (INVOKESPECIAL) ins;
@@ -208,7 +210,7 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
// (Basically, we may not see the exact original stream class,
// even though it's the same instance.)
- return inv.getName(cpg).equals("close") && inv.getSignature(cpg).equals("()V");
+ return "close".equals(inv.getName(cpg)) && "()V".equals(inv.getSignature(cpg));
}
@@ -217,8 +219,9 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
public boolean isStreamClose(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg, ResourceValueFrame frame,
RepositoryLookupFailureCallback lookupFailureCallback) {
- if (!mightCloseStream(basicBlock, handle, cpg))
+ if (!mightCloseStream(basicBlock, handle, cpg)) {
return false;
+ }
Instruction ins = handle.getInstruction();
@@ -226,8 +229,9 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
// Does this instruction close the stream?
InvokeInstruction inv = (InvokeInstruction) ins;
- if (!frame.isValid() || !getInstanceValue(frame, inv, cpg).isInstance())
+ if (!frame.isValid() || !getInstanceValue(frame, inv, cpg).isInstance()) {
return false;
+ }
// It's a close if the invoked class is any subtype of the stream
// base class.
@@ -235,7 +239,16 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
// even though it's the same instance.)
try {
String classClosed = inv.getClassName(cpg);
- return Hierarchy.isSubtype(classClosed, streamBase) || Hierarchy.isSubtype(streamBase, classClosed) ;
+
+ if (relatedType(classClosed) ) {
+ return true;
+ }
+ if ("java.io.ObjectOutput".equals(classClosed)) {
+ return relatedType("java.io.ObjectOutputStream");
+ } else if ("java.io.ObjectInput".equals(classClosed)) {
+ return relatedType("java.io.ObjectInputStream");
+ }
+ return false;
} catch (ClassNotFoundException e) {
lookupFailureCallback.reportMissingClass(e);
return false;
@@ -245,10 +258,15 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
return false;
}
+ private boolean relatedType(String classClosed) throws ClassNotFoundException {
+ return Hierarchy.isSubtype(classClosed, streamBase) || Hierarchy.isSubtype(streamBase, classClosed);
+ }
+
private ResourceValue getInstanceValue(ResourceValueFrame frame, InvokeInstruction inv, ConstantPoolGen cpg) {
int numConsumed = inv.consumeStack(cpg);
- if (numConsumed == Constants.UNPREDICTABLE)
+ if (numConsumed == Constants.UNPREDICTABLE) {
throw new IllegalStateException();
+ }
return frame.getValue(frame.getNumSlots() - numConsumed);
}
@@ -263,20 +281,26 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
@Override
public boolean equals(Object o) {
- if (!(o instanceof Stream))
+ if (!(o instanceof Stream)) {
return false;
+ }
Stream other = (Stream) o;
- if (!getLocation().equals(other.getLocation()))
+ if (!getLocation().equals(other.getLocation())) {
return false;
- if (!streamBase.equals(other.streamBase))
+ }
+ if (!streamBase.equals(other.streamBase)) {
return false;
- if (!getResourceClass().equals(other.getResourceClass()))
+ }
+ if (!getResourceClass().equals(other.getResourceClass())) {
return false;
- if (instanceParam != other.instanceParam)
+ }
+ if (instanceParam != other.instanceParam) {
return false;
+ }
return true;
}
+ @Override
public int compareTo(Stream other) {
int cmp;
@@ -287,20 +311,23 @@ public class Stream extends ResourceCreationPoint implements Comparable<Stream>
// different parameters to be distinguished.
cmp = getLocation().compareTo(other.getLocation());
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
cmp = streamBase.compareTo(other.streamBase);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
cmp = getResourceClass().compareTo(other.getResourceClass());
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
cmp = instanceParam - other.instanceParam;
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return 0;
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/StreamEquivalenceClass.java b/src/java/edu/umd/cs/findbugs/detect/StreamEquivalenceClass.java
index 8907185..1d71836 100644
--- a/src/java/edu/umd/cs/findbugs/detect/StreamEquivalenceClass.java
+++ b/src/java/edu/umd/cs/findbugs/detect/StreamEquivalenceClass.java
@@ -24,11 +24,11 @@ import java.util.Iterator;
/**
* Set of streams that are in an equivalence class.
- *
+ *
* @author David Hovemeyer
*/
public class StreamEquivalenceClass {
- private HashSet<Stream> memberSet;
+ private final HashSet<Stream> memberSet;
private boolean isClosed;
@@ -42,7 +42,7 @@ public class StreamEquivalenceClass {
/**
* Add a single member to the equivalence class.
- *
+ *
* @param member
* the member Stream
*/
@@ -59,7 +59,7 @@ public class StreamEquivalenceClass {
/**
* Add all members of other StreamEquivalenceClass to this one.
- *
+ *
* @param other
* the other StreamEquivalenceClass
*/
@@ -80,4 +80,3 @@ public class StreamEquivalenceClass {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/StreamEscape.java b/src/java/edu/umd/cs/findbugs/detect/StreamEscape.java
index 7900440..278bcb4 100644
--- a/src/java/edu/umd/cs/findbugs/detect/StreamEscape.java
+++ b/src/java/edu/umd/cs/findbugs/detect/StreamEscape.java
@@ -33,7 +33,7 @@ public class StreamEscape implements Comparable<StreamEscape> {
/**
* Constructor.
- *
+ *
* @param source
* Location where stream is opened
* @param target
@@ -44,10 +44,12 @@ public class StreamEscape implements Comparable<StreamEscape> {
this.target = target;
}
+ @Override
public int compareTo(StreamEscape other) {
int cmp = source.compareTo(other.source);
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return target.compareTo(other.target);
}
@@ -58,8 +60,9 @@ public class StreamEscape implements Comparable<StreamEscape> {
@Override
public boolean equals(Object o) {
- if (!(o instanceof StreamEscape))
+ if (!(o instanceof StreamEscape)) {
return false;
+ }
StreamEscape other = (StreamEscape) o;
return source.equals(other.source) && target.equals(other.target);
}
@@ -70,4 +73,3 @@ public class StreamEscape implements Comparable<StreamEscape> {
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/StreamFactory.java b/src/java/edu/umd/cs/findbugs/detect/StreamFactory.java
index 1660266..1e10806 100644
--- a/src/java/edu/umd/cs/findbugs/detect/StreamFactory.java
+++ b/src/java/edu/umd/cs/findbugs/detect/StreamFactory.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback;
public interface StreamFactory {
/**
* Determine if a Stream is created at given location.
- *
+ *
* @param location
* the Location
* @param type
@@ -52,4 +52,3 @@ public interface StreamFactory {
RepositoryLookupFailureCallback lookupFailureCallback);
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/StreamFrameModelingVisitor.java b/src/java/edu/umd/cs/findbugs/detect/StreamFrameModelingVisitor.java
index 8da66af..31056e6 100644
--- a/src/java/edu/umd/cs/findbugs/detect/StreamFrameModelingVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/detect/StreamFrameModelingVisitor.java
@@ -37,9 +37,9 @@ import edu.umd.cs.findbugs.ba.ResourceValueFrameModelingVisitor;
* (in this case, Streams).
*/
public class StreamFrameModelingVisitor extends ResourceValueFrameModelingVisitor {
- private StreamResourceTracker resourceTracker;
+ private final StreamResourceTracker resourceTracker;
- private Stream stream;
+ private final Stream stream;
private Location location;
@@ -88,8 +88,9 @@ public class StreamFrameModelingVisitor extends ResourceValueFrameModelingVisito
// If needed, update frame status
if (status != -1) {
frame.setStatus(status);
- if (created)
+ if (created) {
frame.setValue(frame.getNumSlots() - 1, ResourceValue.instance());
+ }
}
}
@@ -106,26 +107,28 @@ public class StreamFrameModelingVisitor extends ResourceValueFrameModelingVisito
String methodName = inv.getMethodName(cpg);
String methodSig = inv.getSignature(cpg);
if (inv.getOpcode() == Constants.INVOKEVIRTUAL
- && (methodName.equals("load") || methodName.equals("loadFromXml") || methodName.equals("store") || methodName
- .equals("save")) && className.equals("java.util.Properties"))
+ && ("load".equals(methodName) || "loadFromXml".equals(methodName) || "store".equals(methodName) || "save".equals(methodName)) && "java.util.Properties".equals(className)) {
escapes = false;
- if (inv.getOpcode() == Constants.INVOKEVIRTUAL && (methodName.equals("load") || methodName.equals("store"))
- && className.equals("java.security.KeyStore"))
+ }
+ if (inv.getOpcode() == Constants.INVOKEVIRTUAL && ("load".equals(methodName) || "store".equals(methodName))
+ && "java.security.KeyStore".equals(className)) {
escapes = false;
+ }
if (inv.getOpcode() == Constants.INVOKEVIRTUAL && "getChannel".equals(methodName)
- && "()Ljava/nio/channels/FileChannel;".equals(methodSig))
+ && "()Ljava/nio/channels/FileChannel;".equals(methodSig)) {
escapes = true;
+ }
if (FindOpenStream.DEBUG && escapes) {
System.out.println("ESCAPE at " + location + " at call to " + className + "." + methodName + ":" + methodSig);
}
// Record the fact that this might be a stream escape
- if (stream.getOpenLocation() != null)
+ if (stream.getOpenLocation() != null) {
resourceTracker.addStreamEscape(stream, location);
+ }
return escapes;
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/StreamResourceTracker.java b/src/java/edu/umd/cs/findbugs/detect/StreamResourceTracker.java
index 78effb1..5778d43 100644
--- a/src/java/edu/umd/cs/findbugs/detect/StreamResourceTracker.java
+++ b/src/java/edu/umd/cs/findbugs/detect/StreamResourceTracker.java
@@ -46,31 +46,31 @@ import edu.umd.cs.findbugs.ba.ResourceValueFrameModelingVisitor;
/**
* Resource tracker which determines where streams are created, and how they are
* used within the method.
- *
+ *
* @author David Hovemeyer
*/
public class StreamResourceTracker implements ResourceTracker<Stream> {
- private StreamFactory[] streamFactoryList;
+ private final StreamFactory[] streamFactoryList;
- private RepositoryLookupFailureCallback lookupFailureCallback;
+ private final RepositoryLookupFailureCallback lookupFailureCallback;
private ResourceCollection<Stream> resourceCollection;
/**
* Map of locations where streams are opened to the actual Stream objects.
*/
- private Map<Location, Stream> streamOpenLocationMap;
+ private final Map<Location, Stream> streamOpenLocationMap;
/**
* Set of all open locations and escapes of uninteresting streams.
*/
// private HashSet<Location> uninterestingStreamEscapeSet;
- private HashSet<Stream> uninterestingStreamEscapeSet;
+ private final HashSet<Stream> uninterestingStreamEscapeSet;
/**
* Set of all (potential) stream escapes.
*/
- private TreeSet<StreamEscape> streamEscapeSet;
+ private final TreeSet<StreamEscape> streamEscapeSet;
/**
* Map of individual streams to equivalence classes. Any time a stream "A"
@@ -78,11 +78,11 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
* class. If any stream in an equivalence class is closed, then we consider
* all of the streams in the equivalence class as having been closed.
*/
- private Map<Stream, StreamEquivalenceClass> streamEquivalenceMap;
+ private final Map<Stream, StreamEquivalenceClass> streamEquivalenceMap;
/**
* Constructor.
- *
+ *
* @param streamFactoryList
* array of StreamFactory objects which determine where streams
* are created
@@ -109,7 +109,7 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
/**
* Indicate that a stream escapes at the given target Location.
- *
+ *
* @param source
* the Stream that is escaping
* @param target
@@ -118,8 +118,9 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
public void addStreamEscape(Stream source, Location target) {
StreamEscape streamEscape = new StreamEscape(source, target);
streamEscapeSet.add(streamEscape);
- if (FindOpenStream.DEBUG)
+ if (FindOpenStream.DEBUG) {
System.out.println("Adding potential stream escape " + streamEscape);
+ }
}
/**
@@ -133,8 +134,9 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
for (Iterator<StreamEscape> i = streamEscapeSet.iterator(); i.hasNext();) {
StreamEscape streamEscape = i.next();
if (!isStreamOpenLocation(streamEscape.target)) {
- if (FindOpenStream.DEBUG)
+ if (FindOpenStream.DEBUG) {
System.out.println("Eliminating false stream escape " + streamEscape);
+ }
i.remove();
}
}
@@ -159,11 +161,13 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
for (StreamEscape streamEscape : streamEscapeSet) {
if (isUninterestingStreamEscape(streamEscape.source)) {
- if (FindOpenStream.DEBUG)
+ if (FindOpenStream.DEBUG) {
System.out.println("Propagating stream escape " + streamEscape);
+ }
Stream target = streamOpenLocationMap.get(streamEscape.target);
- if (target == null)
+ if (target == null) {
throw new IllegalStateException();
+ }
uninterestingStreamEscapeSet.add(target);
// Combine equivalence classes for source and target
@@ -184,7 +188,7 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
/**
* Determine if an uninteresting stream escapes at given location.
* markTransitiveUninterestingStreamEscapes() should be called first.
- *
+ *
* @param stream
* the stream
* @return true if an uninteresting stream escapes at the location
@@ -195,24 +199,26 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
/**
* Indicate that a stream is constructed at this Location.
- *
+ *
* @param streamOpenLocation
* the Location
* @param stream
* the Stream opened at this Location
*/
public void addStreamOpenLocation(Location streamOpenLocation, Stream stream) {
- if (FindOpenStream.DEBUG)
+ if (FindOpenStream.DEBUG) {
System.out.println("Stream open location at " + streamOpenLocation);
+ }
streamOpenLocationMap.put(streamOpenLocation, stream);
- if (stream.isUninteresting())
+ if (stream.isUninteresting()) {
uninterestingStreamEscapeSet.add(stream);
+ }
}
/**
* Get the equivalence class for given stream. May only be called if
* markTransitiveUninterestingStreamEscapes() has been called.
- *
+ *
* @param stream
* the stream
* @return the set containing the equivalence class for the given stream
@@ -223,7 +229,7 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
/**
* Determine if given Location is a stream open location point.
- *
+ *
* @param location
* the Location
*/
@@ -231,21 +237,25 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
return streamOpenLocationMap.get(location) != null;
}
+ @Override
public Stream isResourceCreation(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg) {
// Use precomputed map of Locations to Stream creations,
// if present. Note that we don't care about preexisting
// resources here.
- if (resourceCollection != null)
+ if (resourceCollection != null) {
return resourceCollection.getCreatedResource(new Location(handle, basicBlock));
+ }
Instruction ins = handle.getInstruction();
- if (!(ins instanceof TypedInstruction))
+ if (!(ins instanceof TypedInstruction)) {
return null;
+ }
Type type = ((TypedInstruction) ins).getType(cpg);
- if (!(type instanceof ObjectType))
+ if (!(type instanceof ObjectType)) {
return null;
+ }
Location location = new Location(handle, basicBlock);
@@ -253,8 +263,9 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
// look at the location and possibly identify a created stream.
for (StreamFactory aStreamFactoryList : streamFactoryList) {
Stream stream = aStreamFactoryList.createStream(location, (ObjectType) type, cpg, lookupFailureCallback);
- if (stream != null)
+ if (stream != null) {
return stream;
+ }
}
return null;
@@ -265,32 +276,37 @@ public class StreamResourceTracker implements ResourceTracker<Stream> {
return resource.isStreamOpen(basicBlock, handle, cpg, frame);
}
+ @Override
public boolean isResourceClose(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg, Stream resource,
ResourceValueFrame frame) {
return resource.isStreamClose(basicBlock, handle, cpg, frame, lookupFailureCallback);
}
+ @Override
public boolean mightCloseResource(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg)
throws DataflowAnalysisException {
return Stream.mightCloseStream(basicBlock, handle, cpg);
}
+ @Override
public ResourceValueFrameModelingVisitor createVisitor(Stream resource, ConstantPoolGen cpg) {
return new StreamFrameModelingVisitor(cpg, this, resource);
}
+ @Override
public boolean ignoreImplicitExceptions(Stream resource) {
return resource.ignoreImplicitExceptions();
}
+ @Override
public boolean ignoreExceptionEdge(Edge edge, Stream resource, ConstantPoolGen cpg) {
return false;
}
+ @Override
public boolean isParamInstance(Stream resource, int slot) {
return resource.getInstanceParam() == slot;
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/detect/StringConcatenation.java b/src/java/edu/umd/cs/findbugs/detect/StringConcatenation.java
index a863f2f..f5266a3 100644
--- a/src/java/edu/umd/cs/findbugs/detect/StringConcatenation.java
+++ b/src/java/edu/umd/cs/findbugs/detect/StringConcatenation.java
@@ -22,6 +22,7 @@ package edu.umd.cs.findbugs.detect;
import java.util.HashMap;
import java.util.Map;
+import java.util.Map.Entry;
import org.apache.bcel.classfile.Method;
@@ -36,7 +37,7 @@ import edu.umd.cs.findbugs.visitclass.DismantleBytecode;
* Find occurrences of using the String "+" or "+=" operators within a loop.
* This is much less efficient than creating a dedicated StringBuffer object
* outside the loop, and then appending to it.
- *
+ *
* @author Dave Brosius
* @author William Pugh
*/
@@ -55,7 +56,7 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
static final int POSSIBLE_CASE = 5;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private boolean reportedThisMethod;
@@ -77,8 +78,9 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
@Override
public void visit(Method obj) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("------------------- Analyzing " + obj.getName() + " ----------------");
+ }
reset();
clobberedRegisters = new HashMap<Integer, Integer>();
reportedThisMethod = false;
@@ -94,8 +96,9 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
// For debugging: print what call to reset() is being invoked.
// This helps figure out why the detector is failing to
// recognize a particular idiom.
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Reset from: " + new Throwable().getStackTrace()[1]);
+ }
}
private boolean storeIntoRegister(int seen, int reg) {
@@ -117,8 +120,9 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
@Override
public void sawOpcode(int seen) {
- if (reportedThisMethod)
+ if (reportedThisMethod) {
return;
+ }
int oldState = state;
if (DEBUG) {
System.out.print("Opcode: ");
@@ -144,6 +148,8 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
case ASTORE:
storeTo = getRegisterOperand();
break;
+ default:
+ break;
}
if (storeTo >= 0 && state != CONSTRUCTED_STRING_ON_STACK) {
clobberedRegisters.put(storeTo, getPC());
@@ -159,46 +165,50 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
case SEEN_NEW:
if (seen == INVOKESPECIAL && "<init>".equals(getNameConstantOperand())
- && "(Ljava/lang/String;)V".equals(getSigConstantOperand())
- && getClassConstantOperand().startsWith("java/lang/StringBu") && registerOnStack >= 0) {
+ && "(Ljava/lang/String;)V".equals(getSigConstantOperand())
+ && getClassConstantOperand().startsWith("java/lang/StringBu") && registerOnStack >= 0) {
state = SEEN_APPEND1;
stringSource = registerOnStack;
} else if (seen == INVOKEVIRTUAL && "append".equals(getNameConstantOperand())
&& getClassConstantOperand().startsWith("java/lang/StringBu")) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Saw string being appended from register " + registerOnStack);
+ }
if (getSigConstantOperand().startsWith("(Ljava/lang/String;)") && registerOnStack >= 0) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Saw string being appended, source = " + registerOnStack);
+ }
state = SEEN_APPEND1;
stringSource = registerOnStack;
- } else
+ } else {
reset();
+ }
}
break;
case SEEN_APPEND1:
- if (storeIntoRegister(seen, stringSource))
+ if (storeIntoRegister(seen, stringSource)) {
reset();
- else if (seen == INVOKEVIRTUAL && "append".equals(getNameConstantOperand())
+ } else if (seen == INVOKEVIRTUAL && "append".equals(getNameConstantOperand())
&& getClassConstantOperand().startsWith("java/lang/StringBu")) {
state = SEEN_APPEND2;
}
break;
case SEEN_APPEND2:
- if (storeIntoRegister(seen, stringSource))
+ if (storeIntoRegister(seen, stringSource)) {
reset();
- else if (seen == INVOKEVIRTUAL && "toString".equals(getNameConstantOperand())
+ } else if (seen == INVOKEVIRTUAL && "toString".equals(getNameConstantOperand())
&& getClassConstantOperand().startsWith("java/lang/StringBu")) {
state = CONSTRUCTED_STRING_ON_STACK;
}
break;
case CONSTRUCTED_STRING_ON_STACK:
- if (storeIntoRegister(seen, stringSource))
+ if (storeIntoRegister(seen, stringSource)) {
state = POSSIBLE_CASE;
- else
+ } else {
reset();
+ }
break;
case POSSIBLE_CASE:
@@ -211,11 +221,12 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
// Next check: was the destination register clobbered
// elsewhere in this loop?
boolean clobberedInLoop = false;
- for (int reg : clobberedRegisters.keySet()) {
+ for (Entry<Integer, Integer> entry : clobberedRegisters.entrySet()) {
+ int reg = entry.getKey();
if (reg != stringSource) {
continue;
}
- int pc = clobberedRegisters.get(reg);
+ int pc = entry.getValue();
if (pc >= getBranchTarget()) {
clobberedInLoop = true;
break;
@@ -227,7 +238,7 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
}
bugReporter.reportBug(new BugInstance(this, "SBSC_USE_STRINGBUFFER_CONCATENATION", NORMAL_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this, createPC));
+ .addClassAndMethod(this).addSourceLine(this, createPC));
// System.out.println("SBSC spread: " + (getPC() -
// getBranchTarget()));
reset();
@@ -236,7 +247,7 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
state = SEEN_NEW;
createPC = getPC();
} else {
- if (DismantleBytecode.isBranch(seen) && DEBUG) {
+ if (DEBUG && DismantleBytecode.isBranch(seen)) {
System.out.println("Rejecting branch:");
System.out.println(" spread: " + (getPC() - getBranchTarget()));
System.out.println(" getBranchTarget(): " + getBranchTarget());
@@ -244,11 +255,13 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
}
}
break;
+ default:
+ break;
}
- if (seen == INVOKESTATIC && getNameConstantOperand().equals("valueOf")
- && getClassConstantOperand().equals("java/lang/String")
- && getSigConstantOperand().equals("(Ljava/lang/Object;)Ljava/lang/String;")) {
+ if (seen == INVOKESTATIC && "valueOf".equals(getNameConstantOperand())
+ && "java/lang/String".equals(getClassConstantOperand())
+ && "(Ljava/lang/Object;)Ljava/lang/String;".equals(getSigConstantOperand())) {
// leave registerOnStack unchanged
} else {
registerOnStack = -1;
@@ -268,12 +281,14 @@ public class StringConcatenation extends BytecodeScanningDetector implements Sta
case ALOAD:
registerOnStack = getRegisterOperand();
break;
+ default:
+ break;
}
}
- if (DEBUG && state != oldState)
+ if (DEBUG && state != oldState) {
System.out.println("At PC " + getPC() + " changing from state " + oldState + " to state " + state + ", regOnStack = "
+ registerOnStack);
+ }
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/SuperfluousInstanceOf.java b/src/java/edu/umd/cs/findbugs/detect/SuperfluousInstanceOf.java
index 1727829..452873f 100644
--- a/src/java/edu/umd/cs/findbugs/detect/SuperfluousInstanceOf.java
+++ b/src/java/edu/umd/cs/findbugs/detect/SuperfluousInstanceOf.java
@@ -35,7 +35,7 @@ import edu.umd.cs.findbugs.visitclass.LVTHelper;
* Find occurrences of a instanceof b where it can be determined statically
* whether this is true or false. This may signal a misunderstanding of the
* inheritance hierarchy in use, and potential bugs.
- *
+ *
* @author Dave Brosius
*/
public class SuperfluousInstanceOf extends BytecodeScanningDetector implements StatelessDetector {
@@ -44,7 +44,7 @@ public class SuperfluousInstanceOf extends BytecodeScanningDetector implements S
private static final int SEEN_ALOAD = 1;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private LocalVariableTable varTable;
@@ -60,26 +60,29 @@ public class SuperfluousInstanceOf extends BytecodeScanningDetector implements S
public void visit(Method obj) {
state = SEEN_NOTHING;
varTable = obj.getLocalVariableTable();
- if (varTable != null)
+ if (varTable != null) {
super.visit(obj);
+ }
}
@Override
public void visit(Code obj) {
- if (varTable != null)
+ if (varTable != null) {
super.visit(obj);
+ }
}
@Override
public void sawOpcode(int seen) {
switch (state) {
case SEEN_NOTHING:
- if (seen == ALOAD)
+ if (seen == ALOAD) {
register = getRegisterOperand();
- else if ((seen >= ALOAD_0) && (seen <= ALOAD_3))
+ } else if ((seen >= ALOAD_0) && (seen <= ALOAD_3)) {
register = seen - ALOAD_0;
- else
+ } else {
return;
+ }
state = SEEN_ALOAD;
break;
@@ -96,7 +99,7 @@ public class SuperfluousInstanceOf extends BytecodeScanningDetector implements S
if (clsSignature.charAt(0) != '[') {
if (org.apache.bcel.Repository.instanceOf(objSignature, clsSignature)) {
bugReporter.reportBug(new BugInstance(this, "SIO_SUPERFLUOUS_INSTANCEOF", LOW_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
}
}
}
@@ -108,9 +111,9 @@ public class SuperfluousInstanceOf extends BytecodeScanningDetector implements S
state = SEEN_NOTHING;
break;
+ default:
+ break;
}
}
}
-
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/SuspiciousThreadInterrupted.java b/src/java/edu/umd/cs/findbugs/detect/SuspiciousThreadInterrupted.java
index a4ce582..c99e2f3 100644
--- a/src/java/edu/umd/cs/findbugs/detect/SuspiciousThreadInterrupted.java
+++ b/src/java/edu/umd/cs/findbugs/detect/SuspiciousThreadInterrupted.java
@@ -21,6 +21,7 @@
package edu.umd.cs.findbugs.detect;
import java.util.BitSet;
+import java.util.Collections;
import org.apache.bcel.classfile.Method;
@@ -28,6 +29,7 @@ import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.StatelessDetector;
+import edu.umd.cs.findbugs.ba.ClassContext;
/**
* looks for calls to Thread.interrupted from a non static context, especially
@@ -44,7 +46,7 @@ public class SuspiciousThreadInterrupted extends BytecodeScanningDetector implem
public static final int SEEN_POSSIBLE_THREAD = 4;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private BitSet localsWithCurrentThreadValue;
@@ -55,6 +57,13 @@ public class SuspiciousThreadInterrupted extends BytecodeScanningDetector implem
}
@Override
+ public void visitClassContext(ClassContext classContext) {
+ if(hasInterestingClass(classContext.getJavaClass().getConstantPool(), Collections.singleton("java/lang/Thread"))) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
public void visit(Method obj) {
localsWithCurrentThreadValue = new BitSet();
state = SEEN_NOTHING;
@@ -68,29 +77,33 @@ public class SuspiciousThreadInterrupted extends BytecodeScanningDetector implem
if (seen == POP) {
state = SEEN_UNKNOWNCONTEXT_POP;
return;
- } else
+ } else {
state = SEEN_NOTHING;
+ }
}
switch (state) {
case SEEN_NOTHING:
- if ((seen == INVOKESTATIC) && getClassConstantOperand().equals("java/lang/Thread")
- && getNameConstantOperand().equals("currentThread") && getSigConstantOperand().equals("()Ljava/lang/Thread;"))
+ if ((seen == INVOKESTATIC) && "java/lang/Thread".equals(getClassConstantOperand())
+ && "currentThread".equals(getNameConstantOperand()) && "()Ljava/lang/Thread;".equals(getSigConstantOperand())) {
state = SEEN_CURRENTTHREAD;
- else if ((seen == INVOKESTATIC || seen == INVOKEINTERFACE || seen == INVOKEVIRTUAL || seen == INVOKESPECIAL)
- && getSigConstantOperand().endsWith("Ljava/lang/Thread;"))
+ } else if ((seen == INVOKESTATIC || seen == INVOKEINTERFACE || seen == INVOKEVIRTUAL || seen == INVOKESPECIAL)
+ && getSigConstantOperand().endsWith("Ljava/lang/Thread;")) {
state = SEEN_POSSIBLE_THREAD;
- else if (seen == ALOAD) {
+ } else if (seen == ALOAD) {
if (localsWithCurrentThreadValue.get(getRegisterOperand())) {
state = SEEN_CURRENTTHREAD;
- } else
+ } else {
state = SEEN_POSSIBLE_THREAD;
+ }
} else if ((seen >= ALOAD_0) && (seen <= ALOAD_3)) {
if (localsWithCurrentThreadValue.get(seen - ALOAD_0)) {
state = SEEN_CURRENTTHREAD;
- } else
+ } else {
state = SEEN_POSSIBLE_THREAD;
- } else if ((seen == GETFIELD || seen == GETSTATIC) && getSigConstantOperand().equals("Ljava/lang/Thread;"))
+ }
+ } else if ((seen == GETFIELD || seen == GETSTATIC) && "Ljava/lang/Thread;".equals(getSigConstantOperand())) {
state = SEEN_POSSIBLE_THREAD;
+ }
break;
case SEEN_CURRENTTHREAD:
@@ -108,14 +121,14 @@ public class SuspiciousThreadInterrupted extends BytecodeScanningDetector implem
break;
default:
- if ((seen == INVOKESTATIC) && getClassConstantOperand().equals("java/lang/Thread")
- && getNameConstantOperand().equals("interrupted") && getSigConstantOperand().equals("()Z")) {
+ if ((seen == INVOKESTATIC) && "java/lang/Thread".equals(getClassConstantOperand())
+ && "interrupted".equals(getNameConstantOperand()) && "()Z".equals(getSigConstantOperand())) {
if (state == SEEN_POP_AFTER_CURRENTTHREAD) {
bugReporter.reportBug(new BugInstance(this, "STI_INTERRUPTED_ON_CURRENTTHREAD", LOW_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
} else if (state == SEEN_UNKNOWNCONTEXT_POP) {
bugReporter.reportBug(new BugInstance(this, "STI_INTERRUPTED_ON_UNKNOWNTHREAD", NORMAL_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addSourceLine(this));
}
}
state = SEEN_NOTHING;
@@ -124,4 +137,3 @@ public class SuspiciousThreadInterrupted extends BytecodeScanningDetector implem
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/SwitchFallthrough.java b/src/java/edu/umd/cs/findbugs/detect/SwitchFallthrough.java
index 0986ec3..63c60cd 100644
--- a/src/java/edu/umd/cs/findbugs/detect/SwitchFallthrough.java
+++ b/src/java/edu/umd/cs/findbugs/detect/SwitchFallthrough.java
@@ -91,8 +91,9 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
@Override
public void visit(Code obj) {
- if (DEBUG)
+ if (DEBUG) {
System.out.printf("%nVisiting %s%n", getMethodDescriptor());
+ }
reachable = false;
lastPC = 0;
biggestJumpTarget = -1;
@@ -106,10 +107,12 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
super.visit(obj);
enumType = null;
if (!found.isEmpty()) {
- if (found.size() >= 4 && priority == NORMAL_PRIORITY)
+ if (found.size() >= 4 && priority == NORMAL_PRIORITY) {
priority = LOW_PRIORITY;
- for (SourceLineAnnotation s : found)
+ }
+ for (SourceLineAnnotation s : found) {
bugAccumulator.accumulateBug(new BugInstance(this, "SF_SWITCH_FALLTHROUGH", priority).addClassAndMethod(this), s);
+ }
}
bugAccumulator.reportAccumulatedBugs();
@@ -123,12 +126,14 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
int prev = Integer.MIN_VALUE;
for (LineNumber ln : table.getLineNumberTable()) {
int thisLineNumber = ln.getLineNumber();
- if (thisLineNumber < startLine && thisLineNumber > prev && ln.getStartPC() < s.getStartBytecode())
+ if (thisLineNumber < startLine && thisLineNumber > prev && ln.getStartPC() < s.getStartBytecode()) {
prev = thisLineNumber;
+ }
}
int diff = startLine - prev;
- if (diff > 5)
+ if (diff > 5) {
return;
+ }
bugAccumulator.accumulateBug(new BugInstance(this, "SF_SWITCH_NO_DEFAULT", NORMAL_PRIORITY).addClassAndMethod(this),
s);
@@ -144,13 +149,13 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
boolean isCaseOffset = switchHdlr.isOnSwitchOffset(this);
if (DEBUG) {
- if (seen == GOTO)
+ if (seen == GOTO) {
System.out.printf("%4d: goto %-7d %s %s %s %d%n", getPC(), getBranchTarget(), reachable, isCaseOffset,
isDefaultOffset, switchHdlr.stackSize());
-
- else
+ } else {
System.out.printf("%4d: %-12s %s %s %s %d%n", getPC(), OPCODE_NAMES[seen], reachable, isCaseOffset,
isDefaultOffset, switchHdlr.stackSize());
+ }
}
if (reachable && (isDefaultOffset || isCaseOffset)) {
@@ -167,8 +172,9 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
found.add(sourceLineAnnotation);
} else if ( getPC() >= biggestJumpTarget) {
SourceLineAnnotation sourceLineAnnotation = switchHdlr.getCurrentSwitchStatement(this);
- if (DEBUG)
+ if (DEBUG) {
System.out.printf("Found fallthrough to default offset at %d (BJT is %d)%n", getPC(), biggestJumpTarget);
+ }
foundSwitchNoDefault(sourceLineAnnotation);
}
@@ -183,8 +189,9 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
if (seen == GETFIELD && stack.getStackDepth() > 0) {
OpcodeStack.Item top = stack.getStackItem(0);
- if (top.getRegisterNumber() == 0)
+ if (top.getRegisterNumber() == 0) {
potentiallyDeadFields.remove(getXFieldOperand());
+ }
}
else if (seen == PUTFIELD && stack.getStackDepth() >= 2) {
@@ -195,7 +202,7 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
// killed store
priority = HIGH_PRIORITY;
bugAccumulator.accumulateBug(new BugInstance(this, "SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH", priority)
- .addClassAndMethod(this).addField(f), this);
+ .addClassAndMethod(this).addField(f), this);
}
potentiallyDeadFields.add(f);
@@ -220,53 +227,59 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
clearAllDeadStores();
}
- if (isRegisterLoad())
+ if (isRegisterLoad()) {
potentiallyDeadStores.clear(getRegisterOperand());
-
- else if (isRegisterStore() && !atCatchBlock()) {
+ } else if (isRegisterStore() && !atCatchBlock()) {
int register = getRegisterOperand();
if (potentiallyDeadStores.get(register) && (potentiallyDeadStoresFromBeforeFallthrough.get(register))) {
// killed store
priority = HIGH_PRIORITY;
deadStore = LocalVariableAnnotation.getLocalVariableAnnotation(getMethod(), register, getPC() - 1, getPC());
bugAccumulator.accumulateBug(new BugInstance(this, "SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH", priority)
- .addClassAndMethod(this).add(deadStore), this);
+ .addClassAndMethod(this).add(deadStore), this);
}
potentiallyDeadStores.set(register);
}
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("ordinal") && getSigConstantOperand().equals("()I")) {
+ if (seen == INVOKEVIRTUAL && "ordinal".equals(getNameConstantOperand()) && "()I".equals(getSigConstantOperand())) {
XClass c = getXClassOperand();
if (c != null) {
ClassDescriptor superclassDescriptor = c.getSuperclassDescriptor();
- if (superclassDescriptor != null && superclassDescriptor.getClassName().equals("java/lang/Enum"))
+ if (superclassDescriptor != null && "java/lang/Enum".equals(superclassDescriptor.getClassName())) {
enumType = c;
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("Saw " + enumType + ".ordinal()");
+ }
}
- } else if (seen != TABLESWITCH && seen != LOOKUPSWITCH && seen != IALOAD)
+ } else if (seen != TABLESWITCH && seen != LOOKUPSWITCH && seen != IALOAD) {
enumType = null;
+ }
switch (seen) {
case TABLESWITCH:
case LOOKUPSWITCH:
if (justSawHashcode)
+ {
break; // javac compiled switch statement
+ }
reachable = false;
biggestJumpTarget = -1;
switchHdlr.enterSwitch(this, enumType);
- if (DEBUG)
+ if (DEBUG) {
System.out.printf(" entered switch, default is %d%n", switchHdlr.getDefaultOffset());
+ }
break;
case GOTO_W:
case GOTO:
if (biggestJumpTarget < getBranchTarget()) {
biggestJumpTarget = getBranchTarget();
- if (DEBUG)
+ if (DEBUG) {
System.out.printf(" Setting BJT to %d%n", biggestJumpTarget);
+ }
}
reachable = false;
@@ -290,7 +303,7 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
reachable = true;
}
- justSawHashcode = seen == INVOKEVIRTUAL && getNameConstantOperand().equals("hashCode") && getSigConstantOperand().equals("()I");
+ justSawHashcode = seen == INVOKEVIRTUAL && "hashCode".equals(getNameConstantOperand()) && "()I".equals(getSigConstantOperand());
lastPC = getPC();
fallthroughDistance++;
}
@@ -316,18 +329,21 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
int startLine = srcLine.getStartLine();
int numLines = srcLine.getEndLine() - startLine - 1;
- if (numLines <= 0)
+ if (numLines <= 0) {
return false;
+ }
r = UTF8.bufferedReader(sourceFile.getInputStream());
for (int i = 0; i < startLine; i++) {
String line = r.readLine();
- if (line == null)
+ if (line == null) {
return false;
+ }
}
for (int i = 0; i < numLines; i++) {
String line = r.readLine();
- if (line == null)
+ if (line == null) {
return false;
+ }
line = line.toLowerCase();
if (line.indexOf("fall") >= 0 || line.indexOf("nobreak") >= 0) {
return true;
@@ -337,8 +353,9 @@ public class SwitchFallthrough extends OpcodeStackDetector implements StatelessD
// Problems with source file, mean report the bug
} finally {
try {
- if (r != null)
+ if (r != null) {
r.close();
+ }
} catch (IOException ioe) {
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/SynchronizationOnSharedBuiltinConstant.java b/src/java/edu/umd/cs/findbugs/detect/SynchronizationOnSharedBuiltinConstant.java
index 2e6421c..e0c853f 100644
--- a/src/java/edu/umd/cs/findbugs/detect/SynchronizationOnSharedBuiltinConstant.java
+++ b/src/java/edu/umd/cs/findbugs/detect/SynchronizationOnSharedBuiltinConstant.java
@@ -53,9 +53,10 @@ public class SynchronizationOnSharedBuiltinConstant extends OpcodeStackDetector
private static boolean newlyConstructedObject(OpcodeStack.Item item) {
XMethod method = item.getReturnValueOf();
- if (method == null)
+ if (method == null) {
return false;
- return method.getName().equals("<init>");
+ }
+ return "<init>".equals(method.getName());
}
private static final Pattern identified = Pattern.compile("\\p{Alnum}+");
@@ -89,50 +90,50 @@ public class SynchronizationOnSharedBuiltinConstant extends OpcodeStackDetector
syncSignature = top.getSignature();
isSyncOnBoolean = false;
Object constant = top.getConstant();
- if (syncSignature.equals("Ljava/lang/String;") && constant instanceof String) {
+ if ("Ljava/lang/String;".equals(syncSignature) && constant instanceof String) {
pendingBug = new BugInstance(this, "DL_SYNCHRONIZATION_ON_SHARED_CONSTANT", NORMAL_PRIORITY)
- .addClassAndMethod(this);
+ .addClassAndMethod(this);
String value = (String) constant;
- if (identified.matcher(value).matches())
+ if (identified.matcher(value).matches()) {
pendingBug.addString(value).describe(StringAnnotation.STRING_CONSTANT_ROLE);
+ }
} else if (badSignatures.contains(syncSignature)) {
- isSyncOnBoolean = syncSignature.equals("Ljava/lang/Boolean;");
+ isSyncOnBoolean = "Ljava/lang/Boolean;".equals(syncSignature);
XField field = top.getXField();
FieldSummary fieldSummary = AnalysisContext.currentAnalysisContext().getFieldSummary();
OpcodeStack.Item summary = fieldSummary.getSummary(field);
int priority = NORMAL_PRIORITY;
- if (isSyncOnBoolean)
+ if (isSyncOnBoolean) {
priority--;
- if (newlyConstructedObject(summary))
+ }
+ if (newlyConstructedObject(summary)) {
pendingBug = new BugInstance(this, "DL_SYNCHRONIZATION_ON_UNSHARED_BOXED_PRIMITIVE", NORMAL_PRIORITY)
- .addClassAndMethod(this).addType(syncSignature).addOptionalField(field)
- .addOptionalLocalVariable(this, top);
- else if (isSyncOnBoolean)
+ .addClassAndMethod(this).addType(syncSignature).addOptionalField(field)
+ .addOptionalLocalVariable(this, top);
+ } else if (isSyncOnBoolean) {
pendingBug = new BugInstance(this, "DL_SYNCHRONIZATION_ON_BOOLEAN", priority).addClassAndMethod(this)
.addOptionalField(field).addOptionalLocalVariable(this, top);
- else
+ } else {
pendingBug = new BugInstance(this, "DL_SYNCHRONIZATION_ON_BOXED_PRIMITIVE", priority).addClassAndMethod(this)
.addType(syncSignature).addOptionalField(field).addOptionalLocalVariable(this, top);
+ }
}
break;
case MONITOREXIT:
-
accumulateBug();
-
break;
-
+ default:
+ break;
}
}
- /**
- *
- */
private void accumulateBug() {
- if (pendingBug == null)
+ if (pendingBug == null) {
return;
+ }
bugAccumulator.accumulateBug(pendingBug, SourceLineAnnotation.fromVisitedInstruction(this, monitorEnterPC));
pendingBug = null;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/SynchronizeAndNullCheckField.java b/src/java/edu/umd/cs/findbugs/detect/SynchronizeAndNullCheckField.java
index 74c330b..f8486b6 100644
--- a/src/java/edu/umd/cs/findbugs/detect/SynchronizeAndNullCheckField.java
+++ b/src/java/edu/umd/cs/findbugs/detect/SynchronizeAndNullCheckField.java
@@ -69,35 +69,40 @@ public class SynchronizeAndNullCheckField extends BytecodeScanningDetector {
case 1:
if (seen == DUP) {
currState = 2;
- } else
+ } else {
currState = 0;
+ }
break;
case 2:
- if (seen == ASTORE || seen == ASTORE_0 || seen == ASTORE_1 || seen == ASTORE_2 || seen == ASTORE_3)
+ if (seen == ASTORE || seen == ASTORE_0 || seen == ASTORE_1 || seen == ASTORE_2 || seen == ASTORE_3) {
currState = 3;
- else
+ } else {
currState = 0;
+ }
break;
case 3:
if (seen == MONITORENTER) {
currState = 4;
- } else
+ } else {
currState = 0;
+ }
break;
case 4:
if (seen == GETFIELD || seen == GETSTATIC) {
gottenField = FieldAnnotation.fromReferencedField(this);
currState = 5;
- } else
+ } else {
currState = 0;
+ }
break;
case 5:
if ((seen == IFNONNULL || seen == IFNULL) && gottenField.equals(syncField)) {
BugInstance bug = new BugInstance(this, "NP_SYNC_AND_NULL_CHECK_FIELD", NORMAL_PRIORITY).addClass(this)
.addMethod(this).addField(syncField).addSourceLine(this);
bugReporter.reportBug(bug);
- } else
+ } else {
currState = 0;
+ }
break;
default:
currState = 0;
diff --git a/src/java/edu/umd/cs/findbugs/detect/SynchronizeOnClassLiteralNotGetClass.java b/src/java/edu/umd/cs/findbugs/detect/SynchronizeOnClassLiteralNotGetClass.java
index 85c8e42..9c22acf 100644
--- a/src/java/edu/umd/cs/findbugs/detect/SynchronizeOnClassLiteralNotGetClass.java
+++ b/src/java/edu/umd/cs/findbugs/detect/SynchronizeOnClassLiteralNotGetClass.java
@@ -52,12 +52,6 @@ public class SynchronizeOnClassLiteralNotGetClass extends OpcodeStackDetector {
}
/*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.bcel.OpcodeStackDetector#sawOpcode(int)
- */
-
- /*
* Looking for ALOAD 0 INVOKEVIRTUAL
* java/lang/Object.getClass()Ljava/lang/Class; DUP ASTORE 1 MONITORENTER
*/
@@ -73,17 +67,20 @@ public class SynchronizeOnClassLiteralNotGetClass extends OpcodeStackDetector {
if (seen == PUTSTATIC) {
String classConstantOperand = getClassConstantOperand();
String thisClassName = getThisClass().getClassName().replace('.', '/');
- if (classConstantOperand.equals(thisClassName))
+ if (classConstantOperand.equals(thisClassName)) {
seenPutStatic = true;
+ }
} else if (seen == GETSTATIC) {
String classConstantOperand = getClassConstantOperand();
String thisClassName = getThisClass().getClassName().replace('.', '/');
- if (classConstantOperand.equals(thisClassName))
+ if (classConstantOperand.equals(thisClassName)) {
seenGetStatic = true;
+ }
} else if (seen == MONITOREXIT) {
int priority = LOW_PRIORITY;
- if (seenPutStatic || seenGetStatic)
+ if (seenPutStatic || seenGetStatic) {
priority--;
+ }
try {
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
Set<ClassDescriptor> directSubtypes = subtypes2.getDirectSubtypes(getClassDescriptor());
@@ -104,34 +101,42 @@ public class SynchronizeOnClassLiteralNotGetClass extends OpcodeStackDetector {
}
switch (state) {
case 0:
- if (seen == ALOAD_0)
+ if (seen == ALOAD_0) {
state = 1;
+ }
break;
case 1:
- if (seen == INVOKEVIRTUAL && getNameConstantOperand().equals("getClass")
- && getSigConstantOperand().equals("()Ljava/lang/Class;"))
+ if (seen == INVOKEVIRTUAL && "getClass".equals(getNameConstantOperand())
+ && "()Ljava/lang/Class;".equals(getSigConstantOperand())) {
state = 2;
- else
+ } else {
state = 0;
+ }
break;
case 2:
- if (seen == DUP)
+ if (seen == DUP) {
state = 3;
- else
+ } else {
state = 0;
+ }
break;
case 3:
- if (isRegisterStore())
+ if (isRegisterStore()) {
state = 4;
- else
+ } else {
state = 0;
+ }
break;
case 4:
- if (seen == MONITORENTER)
+ if (seen == MONITORENTER) {
pendingBug = new BugInstance(this, "WL_USING_GETCLASS_RATHER_THAN_CLASS_LITERAL", NORMAL_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this);
+ .addClassAndMethod(this).addSourceLine(this);
+ }
state = 0;
seenGetStatic = seenPutStatic = false;
+ break;
+ default:
+ break;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/SynchronizingOnContentsOfFieldToProtectField.java b/src/java/edu/umd/cs/findbugs/detect/SynchronizingOnContentsOfFieldToProtectField.java
index 45fde37..a181bde 100644
--- a/src/java/edu/umd/cs/findbugs/detect/SynchronizingOnContentsOfFieldToProtectField.java
+++ b/src/java/edu/umd/cs/findbugs/detect/SynchronizingOnContentsOfFieldToProtectField.java
@@ -64,14 +64,16 @@ public class SynchronizingOnContentsOfFieldToProtectField extends OpcodeStackDet
// System.out.println(state + " " + getPC() + " " + OPCODE_NAMES[seen]);
if (countDown == 2 && seen == GOTO) {
CodeException tryBlock = getSurroundingTryBlock(getPC());
- if (tryBlock != null && tryBlock.getEndPC() == getPC())
+ if (tryBlock != null && tryBlock.getEndPC() == getPC()) {
pendingBug.lowerPriority();
+ }
}
if (countDown > 0) {
countDown--;
if (countDown == 0) {
- if (seen == MONITOREXIT)
+ if (seen == MONITOREXIT) {
pendingBug.lowerPriority();
+ }
bugReporter.reportBug(pendingBug);
pendingBug = null;
@@ -82,10 +84,11 @@ public class SynchronizingOnContentsOfFieldToProtectField extends OpcodeStackDet
if (syncField != null && getPrevOpcode(1) != ALOAD_0 && syncField.equals(getXFieldOperand())) {
OpcodeStack.Item value = stack.getStackItem(0);
int priority = Priorities.HIGH_PRIORITY;
- if (value.isNull())
+ if (value.isNull()) {
priority = Priorities.NORMAL_PRIORITY;
+ }
pendingBug = new BugInstance(this, "ML_SYNC_ON_FIELD_TO_GUARD_CHANGING_THAT_FIELD", priority)
- .addClassAndMethod(this).addField(syncField).addSourceLine(this);
+ .addClassAndMethod(this).addField(syncField).addSourceLine(this);
countDown = 2;
}
@@ -96,41 +99,48 @@ public class SynchronizingOnContentsOfFieldToProtectField extends OpcodeStackDet
countDown = 0;
}
- if (seen == MONITORENTER)
+ if (seen == MONITORENTER) {
syncField = null;
+ }
switch (state) {
case 0:
- if (seen == ALOAD_0)
+ if (seen == ALOAD_0) {
state = 1;
+ }
break;
case 1:
if (seen == GETFIELD) {
state = 2;
field = getXFieldOperand();
- } else
+ } else {
state = 0;
+ }
break;
case 2:
- if (seen == DUP)
+ if (seen == DUP) {
state = 3;
- else
+ } else {
state = 0;
+ }
break;
case 3:
- if (isRegisterStore())
+ if (isRegisterStore()) {
state = 4;
- else
+ } else {
state = 0;
+ }
break;
case 4:
if (seen == MONITORENTER) {
state = 0;
syncField = field;
- } else
+ } else {
state = 0;
+ }
+ break;
+ default:
break;
-
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/TestASM.java b/src/java/edu/umd/cs/findbugs/detect/TestASM.java
index d6d70c1..f555b89 100644
--- a/src/java/edu/umd/cs/findbugs/detect/TestASM.java
+++ b/src/java/edu/umd/cs/findbugs/detect/TestASM.java
@@ -19,8 +19,7 @@
package edu.umd.cs.findbugs.detect;
-import static org.apache.bcel.Constants.I2D;
-import static org.apache.bcel.Constants.INVOKESTATIC;
+import static org.apache.bcel.Constants.*;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
@@ -35,7 +34,7 @@ import edu.umd.cs.findbugs.asm.ClassNodeDetector;
/**
* Sample detector, using ASM
- *
+ *
* @author David Hovemeyer
*/
public class TestASM extends ClassNodeDetector {
@@ -64,9 +63,9 @@ public class TestASM extends ClassNodeDetector {
}
@Override
- public void visitMethodInsn(int opcode, String owner, String invokedName, String invokedDesc) {
- if (prevPC + 1 == getPC() && prevOpcode == I2D && opcode == INVOKESTATIC && owner.equals("java/lang/Math")
- && invokedName.equals("ceil") && invokedDesc.equals("(D)D")) {
+ public void visitMethodInsn(int opcode, String owner, String invokedName, String invokedDesc, boolean itf) {
+ if (prevPC + 1 == getPC() && prevOpcode == I2D && opcode == INVOKESTATIC && "java/lang/Math".equals(owner)
+ && "ceil".equals(invokedName) && "(D)D".equals(invokedDesc)) {
BugInstance bug0 = new BugInstance(TestASM.this, "ICAST_INT_CAST_TO_DOUBLE_PASSED_TO_CEIL", NORMAL_PRIORITY);
MethodAnnotation methodAnnotation = MethodAnnotation.fromForeignMethod(TestASM.this.name, name, desc, access);
bug0.addClass(TestASM.this).addMethod(methodAnnotation);
@@ -80,9 +79,10 @@ public class TestASM extends ClassNodeDetector {
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
if ((access & Opcodes.ACC_STATIC) != 0 && (access & Opcodes.ACC_FINAL) != 0 && (access & Opcodes.ACC_PUBLIC) != 0
- && !name.equals(name.toUpperCase()))
+ && !name.equals(name.toUpperCase())) {
bugReporter.reportBug(new BugInstance(this, "NM_FIELD_NAMING_CONVENTION", Priorities.LOW_PRIORITY).addClass(this)
.addField(this.name, name, desc, access));
+ }
return null;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/TestDataflowAnalysis.java b/src/java/edu/umd/cs/findbugs/detect/TestDataflowAnalysis.java
index 09baf42..5c06d8f 100644
--- a/src/java/edu/umd/cs/findbugs/detect/TestDataflowAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/detect/TestDataflowAnalysis.java
@@ -65,6 +65,7 @@ public class TestDataflowAnalysis<Fact,AnalysisType extends DataflowAnalysis<Fac
*
* @see edu.umd.cs.findbugs.Detector2#finishPass()
*/
+ @Override
public void finishPass() {
}
@@ -73,6 +74,7 @@ public class TestDataflowAnalysis<Fact,AnalysisType extends DataflowAnalysis<Fac
*
* @see edu.umd.cs.findbugs.Detector2#getDetectorClassName()
*/
+ @Override
public String getDetectorClassName() {
return getClass().getName();
}
@@ -84,6 +86,7 @@ public class TestDataflowAnalysis<Fact,AnalysisType extends DataflowAnalysis<Fac
* edu.umd.cs.findbugs.Detector2#visitClass(edu.umd.cs.findbugs.classfile
* .ClassDescriptor)
*/
+ @Override
@SuppressWarnings("unchecked")
public void visitClass(ClassDescriptor classDescriptor) throws CheckedAnalysisException {
if (dataflowClassName == null) {
@@ -119,8 +122,8 @@ public class TestDataflowAnalysis<Fact,AnalysisType extends DataflowAnalysis<Fac
System.out.println("Dataflow finished after " + dataflow.getNumIterations());
if (SystemProperties.getBoolean("dataflow.printcfg")) {
- DataflowCFGPrinter<Fact,AnalysisType> cfgPrinter
- = new DataflowCFGPrinter<Fact,AnalysisType>(dataflow);
+ DataflowCFGPrinter<Fact,AnalysisType> cfgPrinter
+ = new DataflowCFGPrinter<Fact,AnalysisType>(dataflow);
cfgPrinter.print(System.out);
}
@@ -138,7 +141,7 @@ public class TestDataflowAnalysis<Fact,AnalysisType extends DataflowAnalysis<Fac
try {
Class<?> c = getClass().getClassLoader().loadClass(dataflowClassName);
cls = asDataflowClass(c);
-
+
} catch (ClassNotFoundException e) {
assert true;
}
@@ -165,7 +168,7 @@ public class TestDataflowAnalysis<Fact,AnalysisType extends DataflowAnalysis<Fac
return;
}
-
+
dataflowClass = cls;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/TestingGround.java b/src/java/edu/umd/cs/findbugs/detect/TestingGround.java
index 50bbce0..27b456b 100644
--- a/src/java/edu/umd/cs/findbugs/detect/TestingGround.java
+++ b/src/java/edu/umd/cs/findbugs/detect/TestingGround.java
@@ -21,27 +21,26 @@ package edu.umd.cs.findbugs.detect;
import org.apache.bcel.classfile.Code;
-import edu.umd.cs.findbugs.BugAccumulator;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
public class TestingGround extends OpcodeStackDetector {
- final BugReporter bugReporter;
+ // final BugReporter bugReporter;
- final BugAccumulator accumulator;
+ // final BugAccumulator accumulator;
public TestingGround(BugReporter bugReporter) {
- this.bugReporter = bugReporter;
- this.accumulator = new BugAccumulator(bugReporter);
+ // this.bugReporter = bugReporter;
+ // this.accumulator = new BugAccumulator(bugReporter);
}
@Override
public void visit(Code code) {
- System.out.println(getFullyQualifiedMethodName());
- super.visit(code);
- System.out.println();
- }
+ System.out.println(getFullyQualifiedMethodName());
+ super.visit(code);
+ System.out.println();
+ }
@Override
public void sawOpcode(int seen) {
diff --git a/src/java/edu/umd/cs/findbugs/detect/TestingGround2.java b/src/java/edu/umd/cs/findbugs/detect/TestingGround2.java
index 2b7a4ff..0b7adf1 100644
--- a/src/java/edu/umd/cs/findbugs/detect/TestingGround2.java
+++ b/src/java/edu/umd/cs/findbugs/detect/TestingGround2.java
@@ -22,12 +22,14 @@ package edu.umd.cs.findbugs.detect;
import org.apache.bcel.classfile.Code;
import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
public class TestingGround2 extends OpcodeStackDetector {
BugReporter bugReporter;
+ @SuppressFBWarnings("URF_UNREAD_FIELD")
public TestingGround2(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
@@ -43,7 +45,7 @@ public class TestingGround2 extends OpcodeStackDetector {
@Override
public void sawOpcode(int seen) {
-
+
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/TrainFieldStoreTypes.java b/src/java/edu/umd/cs/findbugs/detect/TrainFieldStoreTypes.java
index a988c7d..cd90ce6 100644
--- a/src/java/edu/umd/cs/findbugs/detect/TrainFieldStoreTypes.java
+++ b/src/java/edu/umd/cs/findbugs/detect/TrainFieldStoreTypes.java
@@ -49,24 +49,26 @@ import edu.umd.cs.findbugs.ba.type.TypeFrame;
* Build a database of reference types stored into fields. This can be used in
* the future to improve the precision of type analysis when values are loaded
* from fields.
- *
+ *
* @author David Hovemeyer
*/
public class TrainFieldStoreTypes implements Detector, TrainingDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
- private FieldStoreTypeDatabase database;
+ private final FieldStoreTypeDatabase database;
public TrainFieldStoreTypes(BugReporter bugReporter) {
this.bugReporter = bugReporter;
this.database = new FieldStoreTypeDatabase();
}
+ @Override
public void visitClassContext(ClassContext classContext) {
Method[] methodList = classContext.getJavaClass().getMethods();
for (Method method : methodList) {
- if (method.getCode() == null)
+ if (method.getCode() == null) {
continue;
+ }
try {
analyzeMethod(classContext, method);
@@ -74,12 +76,12 @@ public class TrainFieldStoreTypes implements Detector, TrainingDetector {
bugReporter.logError("Error compting field store types", e);
} catch (DataflowAnalysisException e) {
bugReporter.logError("Error compting field store types", e);
- }
+ }
}
}
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException
- {
+ {
CFG cfg = classContext.getCFG(method);
TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
ConstantPoolGen cpg = classContext.getConstantPoolGen();
@@ -90,34 +92,40 @@ public class TrainFieldStoreTypes implements Detector, TrainingDetector {
short opcode = ins.getOpcode();
// Field store instruction?
- if (opcode != Constants.PUTFIELD && opcode != Constants.PUTSTATIC)
+ if (opcode != Constants.PUTFIELD && opcode != Constants.PUTSTATIC) {
continue;
+ }
// Check if field type is a reference type
FieldInstruction fins = (FieldInstruction) ins;
Type fieldType = fins.getType(cpg);
- if (!(fieldType instanceof ReferenceType))
+ if (!(fieldType instanceof ReferenceType)) {
continue;
+ }
// Find the exact field being stored into
XField xfield = Hierarchy.findXField(fins, cpg);
- if (xfield == null)
+ if (xfield == null) {
continue;
+ }
// Skip public and protected fields, since it is reasonable to
// assume
// we won't see every store to those fields
- if (xfield.isPublic() || xfield.isProtected())
+ if (xfield.isPublic() || xfield.isProtected()) {
continue;
+ }
// The top value on the stack is the one which will be stored
// into the field
TypeFrame frame = typeDataflow.getFactAtLocation(location);
- if (!frame.isValid())
+ if (!frame.isValid()) {
continue;
+ }
Type storeType = frame.getTopValue();
- if (!(storeType instanceof ReferenceType))
+ if (!(storeType instanceof ReferenceType)) {
continue;
+ }
// Get or create the field store type set
FieldStoreType property = database.getProperty(xfield.getFieldDescriptor());
@@ -131,6 +139,7 @@ public class TrainFieldStoreTypes implements Detector, TrainingDetector {
}
}
+ @Override
public void report() {
database.purgeBoringEntries();
AnalysisContext.currentAnalysisContext().storePropertyDatabase(database, FieldStoreTypeDatabase.DEFAULT_FILENAME,
diff --git a/src/java/edu/umd/cs/findbugs/detect/TrainLongInstantfParams.java b/src/java/edu/umd/cs/findbugs/detect/TrainLongInstantfParams.java
index 3383905..d0c9e65 100644
--- a/src/java/edu/umd/cs/findbugs/detect/TrainLongInstantfParams.java
+++ b/src/java/edu/umd/cs/findbugs/detect/TrainLongInstantfParams.java
@@ -52,7 +52,7 @@ public class TrainLongInstantfParams extends PreorderVisitor implements Detector
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.ba.interproc.MethodPropertyDatabase#encodeProperty
* (Property)
@@ -73,13 +73,15 @@ public class TrainLongInstantfParams extends PreorderVisitor implements Detector
@Override
public void visit(Code obj) {
- if (!getMethod().isPublic() && !getMethod().isProtected())
+ if (!getMethod().isPublic() && !getMethod().isProtected()) {
return;
+ }
SignatureParser p = new SignatureParser(getMethodSig());
LocalVariableTable t = obj.getLocalVariableTable();
- if (t == null)
+ if (t == null) {
return;
+ }
ParameterProperty property = new ParameterProperty();
int index = getMethod().isStatic() ? 0 : 1;
@@ -89,16 +91,17 @@ public class TrainLongInstantfParams extends PreorderVisitor implements Detector
LocalVariable localVariable = t.getLocalVariable(index, 0);
if (localVariable != null) {
String name = localVariable.getName();
- if (s.equals("J") && (name.toLowerCase().indexOf("instant") >= 0 || name.startsWith("date"))) {
+ if ("J".equals(s) && (name.toLowerCase().indexOf("instant") >= 0 || name.startsWith("date"))) {
// System.out.println(getFullyQualifiedMethodName() + " " + s + " " + index + " " + name);
property.setParamWithProperty(parameterNumber, true);
}
}
- if (s.equals("J") || s.equals("D"))
+ if ("J".equals(s) || "D".equals(s)) {
index += 2;
- else
+ } else {
index += 1;
+ }
parameterNumber++;
}
if (!property.isEmpty()) {
@@ -109,15 +112,17 @@ public class TrainLongInstantfParams extends PreorderVisitor implements Detector
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector#report()
*/
+ @Override
public void report() {
// System.out.println(database.entrySet().size() + " methods");
AnalysisContext.currentAnalysisContext().storePropertyDatabase(database, "longInstant.db", "long instant database");
}
+ @Override
public void visitClassContext(ClassContext classContext) {
classContext.getJavaClass().accept(this);
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/TrainNonNullAnnotations.java b/src/java/edu/umd/cs/findbugs/detect/TrainNonNullAnnotations.java
index 233bdae..1aa7e3c 100644
--- a/src/java/edu/umd/cs/findbugs/detect/TrainNonNullAnnotations.java
+++ b/src/java/edu/umd/cs/findbugs/detect/TrainNonNullAnnotations.java
@@ -27,9 +27,9 @@ import edu.umd.cs.findbugs.ba.ClassContext;
/**
* Training detector to store NonNull, PossiblyNull and CheckForNull annotations
* to database files.
- *
+ *
* @author David Hovemeyer
- *
+ *
* @deprecated AnnotationDatabases are being phased out, since annotations are
* now stored directly in the XClass/XMethod/XField objects.
* Resolving nullness annotations will be handled through the
@@ -44,20 +44,22 @@ public class TrainNonNullAnnotations extends BuildNonNullAnnotationDatabase impl
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.Detector#visitClassContext(edu.umd.cs.findbugs.ba
* .ClassContext)
*/
+ @Override
public void visitClassContext(ClassContext classContext) {
classContext.getJavaClass().accept(this);
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector#report()
*/
+ @Override
public void report() {
// TODO: FIX for new version of annnotations
// AnalysisContext.currentAnalysisContext().storePropertyDatabase(
diff --git a/src/java/edu/umd/cs/findbugs/detect/TrainUnconditionalDerefParams.java b/src/java/edu/umd/cs/findbugs/detect/TrainUnconditionalDerefParams.java
index 5eed317..857cbed 100644
--- a/src/java/edu/umd/cs/findbugs/detect/TrainUnconditionalDerefParams.java
+++ b/src/java/edu/umd/cs/findbugs/detect/TrainUnconditionalDerefParams.java
@@ -21,7 +21,6 @@ package edu.umd.cs.findbugs.detect;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
-import edu.umd.cs.findbugs.Detector;
import edu.umd.cs.findbugs.TrainingDetector;
import edu.umd.cs.findbugs.ba.AnalysisContext;
@@ -30,19 +29,15 @@ import edu.umd.cs.findbugs.ba.AnalysisContext;
* dereferenced. We do this by performing a backwards dataflow analysis which
* sees which params are dereferenced on all non-implicit-exception paths from
* the CFG entry.
- *
+ *
* @author David Hovemeyer
*/
-public class TrainUnconditionalDerefParams extends BuildUnconditionalParamDerefDatabase implements Detector, TrainingDetector {
-
+public class TrainUnconditionalDerefParams extends BuildUnconditionalParamDerefDatabase implements TrainingDetector {
+
public TrainUnconditionalDerefParams(BugReporter bugReporter) {
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.Detector#report()
- */
+ @Override
public void report() {
AnalysisContext.currentAnalysisContext().storePropertyDatabase(
AnalysisContext.currentAnalysisContext().getUnconditionalDerefParamDatabase(),
@@ -55,7 +50,6 @@ public class TrainUnconditionalDerefParams extends BuildUnconditionalParamDerefD
@Override
protected void reportBug(BugInstance bug) {
// Ignore it
-
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/BooleanReturnNull.java b/src/java/edu/umd/cs/findbugs/detect/TypeReturnNull.java
similarity index 68%
copy from src/java/edu/umd/cs/findbugs/detect/BooleanReturnNull.java
copy to src/java/edu/umd/cs/findbugs/detect/TypeReturnNull.java
index 85debac..e00e74b 100644
--- a/src/java/edu/umd/cs/findbugs/detect/BooleanReturnNull.java
+++ b/src/java/edu/umd/cs/findbugs/detect/TypeReturnNull.java
@@ -22,7 +22,6 @@ package edu.umd.cs.findbugs.detect;
import org.apache.bcel.classfile.Code;
import edu.umd.cs.findbugs.BugAccumulator;
-import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase;
@@ -32,31 +31,37 @@ import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
/**
+ * Base class for simple type checking detectors which tests if the method
+ * returns null references for specific types.
+ *
* @author alison
+ * @author Andrey Loskutov
*/
-public class BooleanReturnNull extends OpcodeStackDetector {
+public abstract class TypeReturnNull extends OpcodeStackDetector {
- BugAccumulator bugAccumulator;
+ protected final BugAccumulator bugAccumulator;
- public BooleanReturnNull(BugReporter bugReporter) {
+ public TypeReturnNull(BugReporter bugReporter) {
this.bugAccumulator = new BugAccumulator(bugReporter);
}
@Override
public void visit(Code code) {
- String s = getMethodSig();
- SignatureParser sp = new SignatureParser(s);
- // Check to see if the method has Boolean return type
- if (!"Ljava/lang/Boolean;".equals(sp.getReturnTypeSignature()))
+ SignatureParser sp = new SignatureParser(getMethodSig());
+ // Check to see if the method has expected return type
+ String returnSignature = sp.getReturnTypeSignature();
+ if (!matchesReturnSignature(returnSignature)){
return;
+ }
- if (isExplicitlyNullable())
+ if (isExplicitlyNullable()){
return;
+ }
super.visit(code); // make callbacks to sawOpcode for all opcodes
bugAccumulator.reportAccumulatedBugs();
-
}
+
private boolean isExplicitlyNullable() {
AnalysisContext analysisContext = AnalysisContext.currentAnalysisContext();
INullnessAnnotationDatabase nullnessAnnotationDatabase = analysisContext.getNullnessAnnotationDatabase();
@@ -64,17 +69,22 @@ public class BooleanReturnNull extends OpcodeStackDetector {
NullnessAnnotation na = nullnessAnnotationDatabase.getResolvedAnnotation(xMethod, true);
return na != null && na != NullnessAnnotation.NONNULL;
}
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.bcel.OpcodeStackDetector#sawOpcode(int)
- */
+
@Override
public void sawOpcode(int seen) {
- if (seen == ARETURN && getPrevOpcode(1) == ACONST_NULL)
- bugAccumulator.accumulateBug(new BugInstance(this, "NP_BOOLEAN_RETURN_NULL",
- getMethodName().startsWith("is") ? HIGH_PRIORITY : NORMAL_PRIORITY).addClassAndMethod(this), this);
-
+ if (seen == ARETURN && getPrevOpcode(1) == ACONST_NULL){
+ accumulateBug();
+ }
}
+ /**
+ * @return true if the given return signature matches expected type
+ */
+ protected abstract boolean matchesReturnSignature(String returnSignature);
+
+ /**
+ * creates individual bug instance on match
+ */
+ protected abstract void accumulateBug();
+
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/URLProblems.java b/src/java/edu/umd/cs/findbugs/detect/URLProblems.java
index d9340f1..f75a0ad 100644
--- a/src/java/edu/umd/cs/findbugs/detect/URLProblems.java
+++ b/src/java/edu/umd/cs/findbugs/detect/URLProblems.java
@@ -18,8 +18,10 @@
*/
package edu.umd.cs.findbugs.detect;
-import java.util.regex.Pattern;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Signature;
@@ -27,7 +29,9 @@ import edu.umd.cs.findbugs.BugAccumulator;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.OpcodeStack;
+import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* equals and hashCode are blocking methods on URL's. Warn about invoking equals
@@ -35,49 +39,87 @@ import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
*/
public class URLProblems extends OpcodeStackDetector {
+ private static final MethodDescriptor URL_EQUALS = new MethodDescriptor("java/net/URL", "equals", "(Ljava/lang/Object;)Z");
+ private static final MethodDescriptor URL_HASHCODE = new MethodDescriptor("java/net/URL", "hashCode", "()I");
+
final static String[] BAD_SIGNATURES = { "Hashtable<Ljava/net/URL", "Map<Ljava/net/URL", "Set<Ljava/net/URL" };
+ // Must be sorted
+ private static final String[] HASHSET_KEY_METHODS = {"add", "contains", "remove"};
+ private static final String[] HASHMAP_KEY_METHODS = {"containsKey", "get", "remove"};
+ private static final String[] HASHMAP_TWO_ARG_KEY_METHODS = {"put"};
+
+ private static final List<MethodDescriptor> methods = Arrays.asList(URL_EQUALS, URL_HASHCODE,
+ new MethodDescriptor("", "add", "(Ljava/lang/Object;)Z"),
+ new MethodDescriptor("", "contains", "(Ljava/lang/Object;)Z"),
+ new MethodDescriptor("", "remove", "(Ljava/lang/Object;)Z"),
+ new MethodDescriptor("", "containsKey", "(Ljava/lang/Object;)Z"),
+ new MethodDescriptor("", "get", "(Ljava/lang/Object;)Ljava/lang/Object;"),
+ new MethodDescriptor("", "remove", "(Ljava/lang/Object;)Ljava/lang/Object;"),
+ new MethodDescriptor("", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"));
+
final private BugReporter bugReporter;
final private BugAccumulator accumulator;
+ private boolean hasInterestingMethodCalls;
+
public URLProblems(BugReporter bugReporter) {
this.bugReporter = bugReporter;
this.accumulator = new BugAccumulator(bugReporter);
}
@Override
+ public void visitClassContext(ClassContext classContext) {
+ this.hasInterestingMethodCalls = hasInterestingMethod(classContext.getJavaClass().getConstantPool(), methods);
+ super.visitClassContext(classContext);
+ }
+
+ @Override
public void visitAfter(JavaClass obj) {
accumulator.reportAccumulatedBugs();
}
@Override
+ public void visit(Code obj) {
+ if(this.hasInterestingMethodCalls) {
+ super.visit(obj);
+ }
+ }
+
+ @Override
public void visit(Signature obj) {
String sig = obj.getSignature();
- for (String s : BAD_SIGNATURES)
+ for (String s : BAD_SIGNATURES) {
if (sig.indexOf(s) >= 0) {
- if (visitingField())
+ if (visitingField()) {
bugReporter.reportBug(new BugInstance(this, "DMI_COLLECTION_OF_URLS", HIGH_PRIORITY).addClass(this)
.addVisitedField(this));
- else if (visitingMethod())
+ } else if (visitingMethod()) {
bugReporter.reportBug(new BugInstance(this, "DMI_COLLECTION_OF_URLS", HIGH_PRIORITY).addClassAndMethod(this));
- else
+ } else {
bugReporter.reportBug(new BugInstance(this, "DMI_COLLECTION_OF_URLS", HIGH_PRIORITY).addClass(this).addClass(
this));
+ }
}
+ }
}
- void check(String className, Pattern name, int target, int url) {
- if (!name.matcher(getNameConstantOperand()).matches())
+ void check(String className, String[] methodNames, int target, int url) {
+ if (Arrays.binarySearch(methodNames, getNameConstantOperand()) < 0) {
return;
- if (stack.getStackDepth() <= target)
+ }
+ if (stack.getStackDepth() <= target) {
return;
+ }
OpcodeStack.Item targetItem = stack.getStackItem(target);
OpcodeStack.Item urlItem = stack.getStackItem(url);
- if (!urlItem.getSignature().equals("Ljava/net/URL;"))
+ if (!"Ljava/net/URL;".equals(urlItem.getSignature())) {
return;
- if (!targetItem.getSignature().equals(className))
+ }
+ if (!targetItem.getSignature().equals(className)) {
return;
+ }
accumulator.accumulateBug(new BugInstance(this, "DMI_COLLECTION_OF_URLS", HIGH_PRIORITY).addClassAndMethod(this)
.addCalledMethod(this), this);
}
@@ -85,21 +127,17 @@ public class URLProblems extends OpcodeStackDetector {
@Override
public void sawOpcode(int seen) {
- // System.out.println(getPC() + " " + OPCODE_NAMES[seen] + " " + stack);
if (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) {
- check("Ljava/util/HashSet;", Pattern.compile("add|remove|contains"), 1, 0);
- check("Ljava/util/HashMap;", Pattern.compile("remove|containsKey|get"), 1, 0);
- check("Ljava/util/HashMap;", Pattern.compile("put"), 2, 1);
-
+ check("Ljava/util/HashSet;", HASHSET_KEY_METHODS, 1, 0);
+ check("Ljava/util/HashMap;", HASHMAP_KEY_METHODS, 1, 0);
+ check("Ljava/util/HashMap;", HASHMAP_TWO_ARG_KEY_METHODS, 2, 1);
}
- if (seen == INVOKEVIRTUAL && getClassConstantOperand().equals("java/net/URL")) {
- if (getNameConstantOperand().equals("equals") && getSigConstantOperand().equals("(Ljava/lang/Object;)Z")
- || getNameConstantOperand().equals("hashCode") && getSigConstantOperand().equals("()I")) {
- accumulator.accumulateBug(
- new BugInstance(this, "DMI_BLOCKING_METHODS_ON_URL", HIGH_PRIORITY).addClassAndMethod(this)
- .addCalledMethod(this), this);
- }
+ if (seen == INVOKEVIRTUAL && (getMethodDescriptorOperand().equals(URL_EQUALS)
+ || getMethodDescriptorOperand().equals(URL_HASHCODE))) {
+ accumulator.accumulateBug(
+ new BugInstance(this, "DMI_BLOCKING_METHODS_ON_URL", HIGH_PRIORITY).addClassAndMethod(this)
+ .addCalledMethod(this), this);
}
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/UncallableMethodOfAnonymousClass.java b/src/java/edu/umd/cs/findbugs/detect/UncallableMethodOfAnonymousClass.java
index 45c027f..19a6047 100644
--- a/src/java/edu/umd/cs/findbugs/detect/UncallableMethodOfAnonymousClass.java
+++ b/src/java/edu/umd/cs/findbugs/detect/UncallableMethodOfAnonymousClass.java
@@ -65,22 +65,25 @@ public class UncallableMethodOfAnonymousClass extends BytecodeScanningDetector {
}
String superclassName2 = getSuperclassName();
- boolean weird = superclassName2.equals("java.lang.Object") && obj.getInterfaceIndices().length == 0;
+ boolean weird = "java.lang.Object".equals(superclassName2) && obj.getInterfaceIndices().length == 0;
boolean hasAnonymousName = ClassName.isAnonymous(obj.getClassName());
boolean isAnonymousInnerClass = hasAnonymousName && !weird;
- if (isAnonymousInnerClass)
+ if (isAnonymousInnerClass) {
super.visitJavaClass(obj);
+ }
}
boolean definedInThisClassOrSuper(JavaClass clazz, String method) throws ClassNotFoundException {
- if (clazz == null)
+ if (clazz == null) {
return false;
+ }
// System.out.println("Checking to see if " + method + " is defined in "
// + clazz.getClassName());
for (Method m : clazz.getMethods()) {
String key = m.getName() + ":" + m.getSignature();
- if (!m.isStatic() && method.equals(key))
+ if (!m.isStatic() && method.equals(key)) {
return true;
+ }
}
return definedInSuperClassOrInterface(clazz, method);
@@ -91,71 +94,90 @@ public class UncallableMethodOfAnonymousClass extends BytecodeScanningDetector {
public void sawOpcode(int seen) {
if (seen == INVOKESPECIAL) {
XMethod m = getXMethodOperand();
- if (m == null)
+ if (m == null) {
return;
+ }
XClass c = getXClass();
int nameDistance = EditDistance.editDistance(m.getName(), getMethodName());
- if (nameDistance < 4 && c.findMatchingMethod(m.getMethodDescriptor()) == null && !m.isFinal())
+ if (nameDistance < 4 && c.findMatchingMethod(m.getMethodDescriptor()) == null && !m.isFinal()) {
potentialSuperCall = m;
+ }
}
}
boolean definedInSuperClassOrInterface(JavaClass clazz, String method) throws ClassNotFoundException {
- if (clazz == null)
+ if (clazz == null) {
return false;
+ }
JavaClass superClass = clazz.getSuperClass();
- if (superClass == null)
+ if (superClass == null) {
return false;
+ }
try {
XClass xClass = Global.getAnalysisCache().getClassAnalysis(XClass.class,
DescriptorFactory.createClassDescriptorFromDottedClassName(superClass.getClassName()));
- if (xClass.hasStubs())
+ if (xClass.hasStubs()) {
return true;
+ }
} catch (CheckedAnalysisException e) {
return true;
}
-
- if (definedInThisClassOrSuper(superClass, method))
+
+ if (definedInThisClassOrSuper(superClass, method)) {
return true;
- for (JavaClass i : clazz.getInterfaces())
- if (definedInThisClassOrSuper(i, method))
+ }
+ for (JavaClass i : clazz.getInterfaces()) {
+ if (definedInThisClassOrSuper(i, method)) {
return true;
+ }
+ }
return false;
}
Set<String> definedInClass(JavaClass clazz) {
HashSet<String> result = new HashSet<String>();
for (Method m : clazz.getMethods()) {
- if (!skip(m))
+ if (!skip(m)) {
result.add(m.getName() + m.getSignature());
+ }
}
return result;
}
private boolean skip(Method obj) {
- if (BCELUtil.isSynthetic(obj))
+ if (BCELUtil.isSynthetic(obj)) {
return true;
- if (obj.isPrivate())
+ }
+ if (obj.isPrivate()) {
return true;
- if (obj.isAbstract())
+ }
+ if (obj.isAbstract()) {
return true;
+ }
String methodName = obj.getName();
String sig = obj.getSignature();
- if (methodName.equals("<init>"))
+ if ("<init>".equals(methodName)) {
return true;
- if (methodName.equals("<clinit>"))
+ }
+ if ("<clinit>".equals(methodName)) {
return true;
- if (sig.equals("()Ljava/lang/Object;") && (methodName.equals("readResolve") || methodName.equals("writeReplace")))
+ }
+ if ("()Ljava/lang/Object;".equals(sig) && ("readResolve".equals(methodName) || "writeReplace".equals(methodName))) {
return true;
- if (methodName.startsWith("access$"))
+ }
+ if (methodName.startsWith("access$")) {
return true;
- if (methodName.length() < 2 || methodName.indexOf('$') >= 0)
+ }
+ if (methodName.length() < 2 || methodName.indexOf('$') >= 0) {
return true;
+ }
XMethod m = getXMethod();
- for (ClassDescriptor c : m.getAnnotationDescriptors())
- if (c.getClassName().indexOf("inject") >= 0)
+ for (ClassDescriptor c : m.getAnnotationDescriptors()) {
+ if (c.getClassName().indexOf("inject") >= 0) {
return true;
+ }
+ }
return false;
}
@@ -169,7 +191,7 @@ public class UncallableMethodOfAnonymousClass extends BytecodeScanningDetector {
String role = ClassAnnotation.SUPERCLASS_ROLE;
@DottedClassName String superclassName = ClassName.toDottedClassName(getSuperclassName());
- if (superclassName.equals("java.lang.Object")) {
+ if ("java.lang.Object".equals(superclassName)) {
try {
JavaClass interfaces[] = getThisClass().getInterfaces();
@@ -186,19 +208,21 @@ public class UncallableMethodOfAnonymousClass extends BytecodeScanningDetector {
XClass from = Global.getAnalysisCache().getClassAnalysis(XClass.class,
DescriptorFactory.createClassDescriptorFromDottedClassName(superclassName));
XMethod potentialMatch = null;
- for(XMethod m : from.getXMethods())
+ for(XMethod m : from.getXMethods()) {
if (!m.isStatic() && !m.isPrivate() && m.getName().toLowerCase().equals(obj.getName().toLowerCase())) {
- if (potentialMatch == null)
+ if (potentialMatch == null) {
potentialMatch = m;
- else {
+ } else {
// multiple matches; ignore all
potentialMatch = null;
break;
}
+ }
+ }
+ if (potentialMatch != null) {
+ pendingBug.addMethod(potentialMatch)
+ .describe(MethodAnnotation.METHOD_DID_YOU_MEAN_TO_OVERRIDE);
}
- if (potentialMatch != null)
- pendingBug.addMethod(potentialMatch)
- .describe(MethodAnnotation.METHOD_DID_YOU_MEAN_TO_OVERRIDE);
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("Error: ", e);
@@ -216,16 +240,18 @@ public class UncallableMethodOfAnonymousClass extends BytecodeScanningDetector {
@Override
public void visit(Code obj) {
- if (pendingBug != null)
+ if (pendingBug != null) {
super.visit(obj);
+ }
}
@Override
public void visit(Method obj) {
try {
- if (skip(obj))
+ if (skip(obj)) {
return;
+ }
JavaClass clazz = getThisClass();
XMethod xmethod = XFactory.createXMethod(clazz, obj);
@@ -235,21 +261,24 @@ public class UncallableMethodOfAnonymousClass extends BytecodeScanningDetector {
int priority = NORMAL_PRIORITY;
JavaClass superClass = clazz.getSuperClass();
String superClassName = superClass.getClassName();
- if (superClassName.equals("java.lang.Object")) {
+ if ("java.lang.Object".equals(superClassName)) {
priority = NORMAL_PRIORITY;
- } else if (definedInClass(superClass).containsAll(definedInClass(clazz)))
+ } else if (definedInClass(superClass).containsAll(definedInClass(clazz))) {
priority = NORMAL_PRIORITY;
- else
+ } else {
priority = HIGH_PRIORITY;
+ }
Code code = null;
- for (Attribute a : obj.getAttributes())
+ for (Attribute a : obj.getAttributes()) {
if (a instanceof Code) {
code = (Code) a;
break;
}
- if (code != null && code.getLength() == 1)
+ }
+ if (code != null && code.getLength() == 1) {
priority++;
+ }
pendingBug = new BugInstance(this, "UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS", priority).addClassAndMethod(this);
potentialSuperCall = null;
diff --git a/src/java/edu/umd/cs/findbugs/detect/UnnecessaryMath.java b/src/java/edu/umd/cs/findbugs/detect/UnnecessaryMath.java
index b76e697..2f5bfde 100644
--- a/src/java/edu/umd/cs/findbugs/detect/UnnecessaryMath.java
+++ b/src/java/edu/umd/cs/findbugs/detect/UnnecessaryMath.java
@@ -20,6 +20,7 @@
package edu.umd.cs.findbugs.detect;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -33,6 +34,7 @@ import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.StatelessDetector;
+import edu.umd.cs.findbugs.ba.ClassContext;
/**
* Find occurrences of Math using constants, where the result of the calculation
@@ -109,11 +111,19 @@ public class UnnecessaryMath extends BytecodeScanningDetector implements Statele
}
@Override
+ public void visitClassContext(ClassContext classContext) {
+ if(hasInterestingClass(classContext.getJavaClass().getConstantPool(), Collections.singleton("java/lang/Math"))) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
public void visit(Code obj) {
// Don't complain about unnecessary math calls in class initializers,
// since they may be there to improve readability.
- if (getMethod().getName().equals("<clinit>"))
+ if ("<clinit>".equals(getMethod().getName())) {
return;
+ }
state = SEEN_NOTHING;
super.visit(obj);
@@ -128,19 +138,20 @@ public class UnnecessaryMath extends BytecodeScanningDetector implements Statele
} else if ((seen == LDC2_W) || (seen == LDC_W)) {
state = SEEN_DCONST;
Constant c = this.getConstantRefOperand();
- if (c instanceof ConstantDouble)
+ if (c instanceof ConstantDouble) {
constValue = ((ConstantDouble) c).getBytes();
- else if (c instanceof ConstantFloat)
+ } else if (c instanceof ConstantFloat) {
constValue = ((ConstantFloat) c).getBytes();
- else if (c instanceof ConstantLong)
+ } else if (c instanceof ConstantLong) {
constValue = ((ConstantLong) c).getBytes();
- else
+ } else {
state = SEEN_NOTHING;
+ }
}
} else if (state == SEEN_DCONST) {
if (seen == INVOKESTATIC) {
state = SEEN_NOTHING;
- if (getDottedClassConstantOperand().equals("java.lang.Math")) {
+ if ("java.lang.Math".equals(getDottedClassConstantOperand())) {
String methodName = getNameConstantOperand();
if (((constValue == 0.0) && zeroMethods.contains(methodName))
@@ -155,4 +166,3 @@ public class UnnecessaryMath extends BytecodeScanningDetector implements Statele
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/detect/UnreadFields.java b/src/java/edu/umd/cs/findbugs/detect/UnreadFields.java
index b29441e..5deb99a 100644
--- a/src/java/edu/umd/cs/findbugs/detect/UnreadFields.java
+++ b/src/java/edu/umd/cs/findbugs/detect/UnreadFields.java
@@ -190,12 +190,13 @@ public class UnreadFields extends OpcodeStackDetector {
data.abstractClasses.add(getDottedClassName());
} else {
String superClass = obj.getSuperclassName();
- if (superClass != null)
+ if (superClass != null) {
data.hasNonAbstractSubClass.add(superClass);
+ }
}
data.classesScanned.add(getDottedClassName());
boolean superClassIsObject = "java.lang.Object".equals(obj.getSuperclassName());
- if (getSuperclassName().indexOf("$") >= 0 || getSuperclassName().indexOf("+") >= 0
+ if (getSuperclassName().indexOf('$') >= 0 || getSuperclassName().indexOf('+') >= 0
|| withinAnonymousClass.matcher(getDottedClassName()).find()) {
// System.out.println("hicfsc: " + betterClassName);
data.innerClassCannotBeStatic.add(getDottedClassName());
@@ -205,9 +206,9 @@ public class UnreadFields extends OpcodeStackDetector {
// Does this class directly implement Serializable?
String[] interface_names = obj.getInterfaceNames();
for (String interface_name : interface_names) {
- if (interface_name.equals("java.io.Externalizable")) {
+ if ("java.io.Externalizable".equals(interface_name)) {
isSerializable = true;
- } else if (interface_name.equals("java.io.Serializable")) {
+ } else if ("java.io.Serializable".equals(interface_name)) {
isSerializable = true;
break;
}
@@ -233,11 +234,12 @@ public class UnreadFields extends OpcodeStackDetector {
}
public static boolean classHasParameter(JavaClass obj) {
- for (Attribute a : obj.getAttributes())
+ for (Attribute a : obj.getAttributes()) {
if (a instanceof Signature) {
String sig = ((Signature) a).getSignature();
return sig.charAt(0) == '<';
}
+ }
return false;
}
@@ -265,56 +267,58 @@ public class UnreadFields extends OpcodeStackDetector {
XField f = XFactory.createXField(this);
data.allMyFields.add(f);
String signature = obj.getSignature();
- if (!getFieldName().equals("serialVersionUID")) {
+ if (!"serialVersionUID".equals(getFieldName())) {
data.myFields.add(f);
- if (obj.getName().equals("_jspx_dependants"))
+ if ("_jspx_dependants".equals(obj.getName())) {
data.containerFields.add(f);
+ }
}
- if (isSeleniumWebElement(signature))
+ if (isSeleniumWebElement(signature)) {
data.containerFields.add(f);
+ }
}
- /**
- * @param signature
- * @return
- */
public static boolean isSeleniumWebElement(String signature) {
- return signature.equals("Lorg/openqa/selenium/RenderedWebElement;")
- || signature.equals("Lorg/openqa/selenium/WebElement;");
+ return "Lorg/openqa/selenium/RenderedWebElement;".equals(signature)
+ || "Lorg/openqa/selenium/WebElement;".equals(signature);
}
@Override
public void visitAnnotation(String annotationClass, Map<String, ElementValue> map, boolean runtimeVisible) {
- if (!visitingField())
+ if (!visitingField()) {
return;
+ }
if (isInjectionAttribute(annotationClass)) {
data.containerFields.add(XFactory.createXField(this));
}
- if (!annotationClass.startsWith("edu.umd.cs.findbugs") && !annotationClass.startsWith("javax.lang"))
+ if (!annotationClass.startsWith("edu.umd.cs.findbugs") && !annotationClass.startsWith("javax.lang")) {
data.unknownAnnotation.add(XFactory.createXField(this), annotationClass);
+ }
}
public static boolean isInjectionAttribute(@DottedClassName String annotationClass) {
if (annotationClass.startsWith("javax.annotation.")
|| annotationClass.startsWith("javax.ejb")
- || annotationClass.equals("org.apache.tapestry5.annotations.Persist")
- || annotationClass.equals("org.jboss.seam.annotations.In")
+ || "org.apache.tapestry5.annotations.Persist".equals(annotationClass)
+ || "org.jboss.seam.annotations.In".equals(annotationClass)
|| annotationClass.startsWith("javax.persistence")
|| annotationClass.endsWith("SpringBean")
- || annotationClass.equals("com.google.inject.Inject")
+ || "com.google.inject.Inject".equals(annotationClass)
|| annotationClass.startsWith("com.google.") && annotationClass.endsWith(".Bind")
&& annotationClass.hashCode() == -243168318
|| annotationClass.startsWith("org.nuxeo.common.xmap.annotation")
|| annotationClass.startsWith("com.google.gwt.uibinder.client")
|| annotationClass.startsWith("org.springframework.beans.factory.annotation")
- || annotationClass.equals("javax.ws.rs.core.Context"))
+ || "javax.ws.rs.core.Context".equals(annotationClass)) {
return true;
+ }
int lastDot = annotationClass.lastIndexOf('.');
String lastPart = annotationClass.substring(lastDot + 1);
- if (lastPart.startsWith("Inject"))
+ if (lastPart.startsWith("Inject")) {
return true;
+ }
return false;
}
@@ -324,6 +328,7 @@ public class UnreadFields extends OpcodeStackDetector {
// set during visitation of the Field are still valid here
XField f = XFactory.createXField(this);
data.constantFields.add(f);
+ data.writtenFields.add(f);
}
int count_aload_1;
@@ -343,7 +348,7 @@ public class UnreadFields extends OpcodeStackDetector {
seenMonitorEnter = getMethod().isSynchronized();
data.staticFieldsReadInThisMethod.clear();
super.visit(obj);
- if (getMethodName().equals("<init>") && count_aload_1 > 1
+ if ("<init>".equals(getMethodName()) && count_aload_1 > 1
&& (getClassName().indexOf('$') >= 0 || getClassName().indexOf('+') >= 0)) {
data.needsOuterObjectInConstructor.add(getDottedClassName());
// System.out.println(betterClassName +
@@ -354,16 +359,19 @@ public class UnreadFields extends OpcodeStackDetector {
@Override
public void visit(Method obj) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Checking " + getClassName() + "." + obj.getName());
- if (getMethodName().equals("<init>") && (obj.isPublic() || obj.isProtected()))
+ }
+ if ("<init>".equals(getMethodName()) && (obj.isPublic() || obj.isProtected())) {
publicOrProtectedConstructor = true;
+ }
pendingGetField = null;
saState = 0;
super.visit(obj);
int flags = obj.getAccessFlags();
- if ((flags & ACC_NATIVE) != 0)
+ if ((flags & ACC_NATIVE) != 0) {
hasNativeMethods = true;
+ }
}
boolean seenInvokeStatic;
@@ -377,49 +385,59 @@ public class UnreadFields extends OpcodeStackDetector {
@Override
public void sawOpcode(int seen) {
- if (DEBUG)
+ if (DEBUG) {
System.out.println(getPC() + ": " + OPCODE_NAMES[seen] + " " + saState);
- if (seen == MONITORENTER)
+ }
+ if (seen == MONITORENTER) {
seenMonitorEnter = true;
+ }
switch (saState) {
case 0:
- if (seen == ALOAD_0)
+ if (seen == ALOAD_0) {
saState = 1;
+ }
break;
case 1:
- if (seen == ALOAD_0)
+ if (seen == ALOAD_0) {
saState = 2;
- else
+ } else {
saState = 0;
+ }
break;
case 2:
- if (seen == GETFIELD)
+ if (seen == GETFIELD) {
saState = 3;
- else
+ } else {
saState = 0;
+ }
break;
case 3:
- if (seen == PUTFIELD)
+ if (seen == PUTFIELD) {
saState = 4;
- else
+ } else {
saState = 0;
+ }
+ break;
+ default:
break;
}
boolean selfAssignment = false;
if (pendingGetField != null) {
- if (seen != PUTFIELD && seen != PUTSTATIC)
+ if (seen != PUTFIELD && seen != PUTSTATIC) {
data.readFields.add(pendingGetField);
- else if (XFactory.createReferencedXField(this).equals(pendingGetField) && (saState == 4 || seen == PUTSTATIC))
+ } else if (XFactory.createReferencedXField(this).equals(pendingGetField) && (saState == 4 || seen == PUTSTATIC)) {
selfAssignment = true;
- else
+ } else {
data.readFields.add(pendingGetField);
+ }
pendingGetField = null;
}
- if (saState == 4)
+ if (saState == 4) {
saState = 0;
+ }
- if (seen == INVOKESTATIC && getClassConstantOperand().equals("java/util/concurrent/atomic/AtomicReferenceFieldUpdater")
- && getNameConstantOperand().equals("newUpdater")) {
+ if (seen == INVOKESTATIC && "java/util/concurrent/atomic/AtomicReferenceFieldUpdater".equals(getClassConstantOperand())
+ && "newUpdater".equals(getNameConstantOperand())) {
String fieldName = (String) stack.getStackItem(0).getConstant();
String fieldSignature = (String) stack.getStackItem(1).getConstant();
String fieldClass = (String) stack.getStackItem(2).getConstant();
@@ -430,8 +448,8 @@ public class UnreadFields extends OpcodeStackDetector {
}
}
- if (seen == INVOKESTATIC && getClassConstantOperand().equals("java/util/concurrent/atomic/AtomicIntegerFieldUpdater")
- && getNameConstantOperand().equals("newUpdater")) {
+ if (seen == INVOKESTATIC && "java/util/concurrent/atomic/AtomicIntegerFieldUpdater".equals(getClassConstantOperand())
+ && "newUpdater".equals(getNameConstantOperand())) {
String fieldName = (String) stack.getStackItem(0).getConstant();
String fieldClass = (String) stack.getStackItem(1).getConstant();
if (fieldName != null && fieldClass != null) {
@@ -440,8 +458,8 @@ public class UnreadFields extends OpcodeStackDetector {
}
}
- if (seen == INVOKESTATIC && getClassConstantOperand().equals("java/util/concurrent/atomic/AtomicLongFieldUpdater")
- && getNameConstantOperand().equals("newUpdater")) {
+ if (seen == INVOKESTATIC && "java/util/concurrent/atomic/AtomicLongFieldUpdater".equals(getClassConstantOperand())
+ && "newUpdater".equals(getNameConstantOperand())) {
String fieldName = (String) stack.getStackItem(0).getConstant();
String fieldClass = (String) stack.getStackItem(1).getConstant();
if (fieldName != null && fieldClass != null) {
@@ -462,7 +480,7 @@ public class UnreadFields extends OpcodeStackDetector {
checkWriteToStaticFromInstanceMethod: if (f.getName().indexOf("class$") != 0) {
int priority = LOW_PRIORITY;
- if (f.isReferenceType())
+ if (f.isReferenceType()) {
try {
ValueNumberDataflow vnaDataflow = getClassContext().getValueNumberDataflow(getMethod());
IsNullValueDataflow invDataflow = getClassContext().getIsNullValueDataflow(getMethod());
@@ -470,51 +488,60 @@ public class UnreadFields extends OpcodeStackDetector {
IsNullValueFrame iFrame = invDataflow.getAnalysis().getFactAtPC(invDataflow.getCFG(), getPC());
AvailableLoad l = new AvailableLoad(f);
ValueNumber[] availableLoads = vFrame.getAvailableLoad(l);
- if (availableLoads != null && iFrame.isTrackValueNumbers())
+ if (availableLoads != null && iFrame.isTrackValueNumbers()) {
for (ValueNumber v : availableLoads) {
IsNullValue knownValue = iFrame.getKnownValue(v);
- if (knownValue == null)
+ if (knownValue == null) {
continue;
+ }
if (knownValue.isDefinitelyNotNull()) {
- if (valuePut.isNull())
+ if (valuePut.isNull()) {
priority++;
- else
+ } else {
priority--;
+ }
break;
} else if (knownValue.isDefinitelyNull()) {
break checkWriteToStaticFromInstanceMethod;
}
}
+ }
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("foo", e);
}
+ }
if (!publicOrProtectedConstructor) {
priority--;
}
- if (seenMonitorEnter)
+ if (seenMonitorEnter) {
priority++;
- if (!seenInvokeStatic && data.staticFieldsReadInThisMethod.isEmpty())
+ }
+ if (!seenInvokeStatic && data.staticFieldsReadInThisMethod.isEmpty()) {
priority--;
- if (getThisClass().isPublic() && getMethod().isPublic())
+ }
+ if (getThisClass().isPublic() && getMethod().isPublic()) {
priority--;
- if (getThisClass().isPrivate() || getMethod().isPrivate())
+ }
+ if (getThisClass().isPrivate() || getMethod().isPrivate()) {
priority++;
+ }
if (getClassName().indexOf('$') != -1 || BCELUtil.isSynthetic(getMethod()) || f.isSynthetic()
- || f.getName().indexOf('$') >= 0)
+ || f.getName().indexOf('$') >= 0) {
priority++;
+ }
// Decrease priority for boolean fields used to control
// debug/test settings
- if (f.getName().indexOf("DEBUG") >= 0 || f.getName().indexOf("VERBOSE") >= 0 && f.getSignature().equals("Z")) {
+ if (f.getName().indexOf("DEBUG") >= 0 || f.getName().indexOf("VERBOSE") >= 0 && "Z".equals(f.getSignature())) {
priority++;
priority++;
}
// Eclipse bundles which implements start/stop *very* often
// assigns static instances there
- if ((getMethodName().equals("start") || getMethodName().equals("stop"))
- && getMethodSig().equals("(Lorg/osgi/framework/BundleContext;)V")) {
+ if (("start".equals(getMethodName()) || "stop".equals(getMethodName()))
+ && "(Lorg/osgi/framework/BundleContext;)V".equals(getMethodSig())) {
try {
JavaClass bundleClass = Repository.lookupClass("org.osgi.framework.BundleActivator");
if (getThisClass().instanceOf(bundleClass)) {
@@ -539,7 +566,7 @@ public class UnreadFields extends OpcodeStackDetector {
}
}
bugAccumulator.accumulateBug(new BugInstance(this, "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", priority)
- .addClassAndMethod(this).addField(f), this);
+ .addClassAndMethod(this).addField(f), this);
}
}
@@ -549,7 +576,7 @@ public class UnreadFields extends OpcodeStackDetector {
String sig = getSigConstantOperand();
String invokedClassName = getClassConstantOperand();
if (invokedClassName.equals(getClassName())
- && (getMethodName().equals("<init>") || getMethodName().equals("<clinit>"))) {
+ && ("<init>".equals(getMethodName()) || "<clinit>".equals(getMethodName()))) {
data.calledFromConstructors.add(getNameConstantOperand() + ":" + sig);
}
@@ -558,15 +585,17 @@ public class UnreadFields extends OpcodeStackDetector {
OpcodeStack.Item item = stack.getStackItem(pos);
boolean superCall = seen == INVOKESPECIAL && !invokedClassName.equals(getClassName());
- if (DEBUG)
+ if (DEBUG) {
System.out.println("In " + getFullyQualifiedMethodName() + " saw call on " + item);
+ }
boolean selfCall = item.getRegisterNumber() == 0 && !superCall;
- if (selfCall && getMethodName().equals("<init>")) {
+ if (selfCall && "<init>".equals(getMethodName())) {
sawSelfCallInConstructor = true;
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Saw self call in " + getFullyQualifiedMethodName() + " to " + invokedClassName + "."
+ getNameConstantOperand());
+ }
}
}
}
@@ -576,8 +605,9 @@ public class UnreadFields extends OpcodeStackDetector {
XField f = item.getXField();
if (f != null) {
data.nullTested.add(f);
- if (DEBUG)
+ if (DEBUG) {
System.out.println(f + " null checked in " + getFullyQualifiedMethodName());
+ }
}
}
@@ -585,12 +615,13 @@ public class UnreadFields extends OpcodeStackDetector {
OpcodeStack.Item item0 = stack.getStackItem(0);
OpcodeStack.Item item1 = stack.getStackItem(1);
XField field1 = item1.getXField();
- if (item0.isNull() && field1 != null)
+ if (item0.isNull() && field1 != null) {
data.nullTested.add(field1);
- else {
+ } else {
XField field0 = item0.getXField();
- if (item1.isNull() && field0 != null)
+ if (item1.isNull() && field0 != null) {
data.nullTested.add(field0);
+ }
}
}
@@ -640,25 +671,29 @@ public class UnreadFields extends OpcodeStackDetector {
IsNullValueDataflow invDataflow = getClassContext().getIsNullValueDataflow(getMethod());
IsNullValueFrame iFrame = invDataflow.getAnalysis().getFactBeforeExceptionCheck(invDataflow.getCFG(),
getPC());
- if (!iFrame.isValid() || iFrame.getStackValue(pos).isDefinitelyNotNull())
+ if (!iFrame.isValid() || iFrame.getStackValue(pos).isDefinitelyNotNull()) {
break computePlacesAssumedNonnull;
+ }
} catch (CheckedAnalysisException e) {
- AnalysisContext.logError("foo", e);
+ AnalysisContext.logError("INV dataflow error when analyzing "+getMethodDescriptor(), e);
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("RRR: " + f + " " + data.nullTested.contains(f) + " "
+ data.writtenInConstructorFields.contains(f) + " " + data.writtenNonNullFields.contains(f));
+ }
ProgramPoint p = new ProgramPoint(this);
Set<ProgramPoint> s = data.assumedNonNull.get(f);
- if (s == null)
+ if (s == null) {
s = Collections.singleton(p);
- else
+ } else {
s = Util.addTo(s, p);
+ }
data.assumedNonNull.put(f, s);
- if (DEBUG)
+ if (DEBUG) {
System.out.println(f + " assumed non-null in " + getFullyQualifiedMethodName());
+ }
}
}
}
@@ -668,52 +703,61 @@ public class UnreadFields extends OpcodeStackDetector {
} else if (seen == GETFIELD || seen == GETSTATIC) {
XField f = XFactory.createReferencedXField(this);
pendingGetField = f;
- if (getMethodName().equals("readResolve") && seen == GETFIELD) {
+ if ("readResolve".equals(getMethodName()) && seen == GETFIELD) {
data.writtenFields.add(f);
data.writtenNonNullFields.add(f);
}
- if (DEBUG)
+ if (DEBUG) {
System.out.println("get: " + f);
- if (data.writtenFields.contains(f))
+ }
+ if (data.writtenFields.contains(f)) {
data.fieldAccess.remove(f);
- else if (!data.fieldAccess.containsKey(f))
+ } else if (!data.fieldAccess.containsKey(f)) {
data.fieldAccess.put(f, SourceLineAnnotation.fromVisitedInstruction(this));
+ }
} else if ((seen == PUTFIELD || seen == PUTSTATIC) && !selfAssignment) {
XField f = XFactory.createReferencedXField(this);
OpcodeStack.Item item = null;
if (stack.getStackDepth() > 0) {
item = stack.getStackItem(0);
- if (!item.isNull())
+ if (!item.isNull()) {
data.nullTested.add(f);
+ }
}
data.writtenFields.add(f);
boolean writtingNonNull = previousOpcode != ACONST_NULL || previousPreviousOpcode == GOTO;
if (writtingNonNull) {
data.writtenNonNullFields.add(f);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("put nn: " + f);
- } else if (DEBUG)
+ }
+ } else if (DEBUG) {
System.out.println("put: " + f);
- if (writtingNonNull && data.readFields.contains(f))
+ }
+ if (writtingNonNull && data.readFields.contains(f)) {
data.fieldAccess.remove(f);
- else if (!data.fieldAccess.containsKey(f))
+ } else if (!data.fieldAccess.containsKey(f)) {
data.fieldAccess.put(f, SourceLineAnnotation.fromVisitedInstruction(this));
+ }
- boolean isConstructor = getMethodName().equals("<init>") || getMethodName().equals("<clinit>");
+ boolean isConstructor = "<init>".equals(getMethodName()) || "<clinit>".equals(getMethodName());
if (getMethod().isStatic() == f.isStatic()
&& (isConstructor || data.calledFromConstructors.contains(getMethodName() + ":" + getMethodSig())
- || getMethodName().equals("init") || getMethodName().equals("init")
- || getMethodName().equals("initialize") || getMethod().isPrivate())) {
+ || "init".equals(getMethodName()) || "init".equals(getMethodName())
+ || "initialize".equals(getMethodName()) || getMethod().isPrivate())) {
if (isConstructor) {
data.writtenInConstructorFields.add(f);
- if (f.getSignature().equals("Ljava/lang/ThreadLocal;") && item != null && item.isNewlyAllocated())
+ if ("Ljava/lang/ThreadLocal;".equals(f.getSignature()) && item != null && item.isNewlyAllocated()) {
data.threadLocalAssignedInConstructor.put(f, new ProgramPoint(this));
- } else
+ }
+ } else {
data.writtenInInitializationFields.add(f);
- if (writtingNonNull)
+ }
+ if (writtingNonNull) {
data.assumedNonNull.remove(f);
+ }
} else {
data.writtenOutsideOfInitializationFields.add(f);
}
@@ -738,33 +782,40 @@ public class UnreadFields extends OpcodeStackDetector {
@Override
public void report() {
Set<String> fieldNamesSet = new HashSet<String>();
- for (XField f : data.writtenNonNullFields)
+ for (XField f : data.writtenNonNullFields) {
fieldNamesSet.add(f.getName());
+ }
if (DEBUG) {
System.out.println("read fields:");
- for (XField f : data.readFields)
+ for (XField f : data.readFields) {
System.out.println(" " + f);
+ }
if (!data.containerFields.isEmpty()) {
System.out.println("ejb3 fields:");
- for (XField f : data.containerFields)
+ for (XField f : data.containerFields) {
System.out.println(" " + f);
+ }
}
if (!data.reflectiveFields.isEmpty()) {
System.out.println("reflective fields:");
- for (XField f : data.reflectiveFields)
+ for (XField f : data.reflectiveFields) {
System.out.println(" " + f);
+ }
}
System.out.println("written fields:");
- for (XField f : data.writtenFields)
+ for (XField f : data.writtenFields) {
System.out.println(" " + f);
+ }
System.out.println("written nonnull fields:");
- for (XField f : data.writtenNonNullFields)
+ for (XField f : data.writtenNonNullFields) {
System.out.println(" " + f);
+ }
System.out.println("assumed nonnull fields:");
- for (XField f : data.assumedNonNull.keySet())
+ for (XField f : data.assumedNonNull.keySet()) {
System.out.println(" " + f);
+ }
}
Set<XField> declaredFields = new HashSet<XField>();
AnalysisContext currentAnalysisContext = AnalysisContext.currentAnalysisContext();
@@ -772,8 +823,9 @@ public class UnreadFields extends OpcodeStackDetector {
for (XField f : AnalysisContext.currentXFactory().allFields()) {
ClassDescriptor classDescriptor = f.getClassDescriptor();
if (currentAnalysisContext.isApplicationClass(classDescriptor) && !currentAnalysisContext.isTooBig(classDescriptor)
- && !xFactory.isReflectiveClass(classDescriptor))
+ && !xFactory.isReflectiveClass(classDescriptor)) {
declaredFields.add(f);
+ }
}
// Don't report anything about ejb3Fields
HashSet<XField> unknownAnotationAndUnwritten = new HashSet<XField>(data.unknownAnnotation.keySet());
@@ -783,8 +835,9 @@ public class UnreadFields extends OpcodeStackDetector {
declaredFields.removeAll(data.reflectiveFields);
for (Iterator<XField> i = declaredFields.iterator(); i.hasNext();) {
XField f = i.next();
- if (f.isSynthetic() && !f.getName().startsWith("this$") || f.getName().startsWith("_"))
+ if (f.isSynthetic() && !f.getName().startsWith("this$") || f.getName().startsWith("_")) {
i.remove();
+ }
}
TreeSet<XField> notInitializedInConstructors = new TreeSet<XField>(declaredFields);
@@ -795,8 +848,9 @@ public class UnreadFields extends OpcodeStackDetector {
notInitializedInConstructors.removeAll(data.writtenInInitializationFields);
for (Iterator<XField> i = notInitializedInConstructors.iterator(); i.hasNext();) {
- if (i.next().isStatic())
+ if (i.next().isStatic()) {
i.remove();
+ }
}
TreeSet<XField> readOnlyFields = new TreeSet<XField>(declaredFields);
@@ -821,14 +875,16 @@ public class UnreadFields extends OpcodeStackDetector {
classContainingNullOnlyFields.add(f.getClassDescriptor());
int increment = 3;
Collection<ProgramPoint> assumedNonNullAt = data.assumedNonNull.get(f);
- if (assumedNonNullAt != null)
+ if (assumedNonNullAt != null) {
increment += assumedNonNullAt.size();
+ }
for (String s : data.unknownAnnotation.get(f)) {
Integer value = count.get(s);
- if (value == null)
+ if (value == null) {
count.put(s, increment);
- else
+ } else {
count.put(s, value + increment);
+ }
}
}
Map<XField, Integer> maxCount = new HashMap<XField, Integer>();
@@ -838,19 +894,22 @@ public class UnreadFields extends OpcodeStackDetector {
int myMaxCount = 0;
for (String s : data.unknownAnnotation.get(f)) {
Integer value = count.get(s);
- if (value != null && myMaxCount < value)
+ if (value != null && myMaxCount < value) {
myMaxCount = value;
+ }
}
- if (myMaxCount > 0)
+ if (myMaxCount > 0) {
maxCount.put(f, myMaxCount);
- if (myMaxCount > 15)
+ }
+ if (myMaxCount > 15) {
assumeReflective.add(f);
- else if (nullOnlyFieldNames.getCount(f.getName()) > 8)
+ } else if (nullOnlyFieldNames.getCount(f.getName()) > 8) {
assumeReflective.add(f);
- else if (classContainingNullOnlyFields.getCount(f.getClassDescriptor()) > 4)
+ } else if (classContainingNullOnlyFields.getCount(f.getClassDescriptor()) > 4) {
assumeReflective.add(f);
- else if (classContainingNullOnlyFields.getCount(f.getClassDescriptor()) > 2 && f.getName().length() == 1)
+ } else if (classContainingNullOnlyFields.getCount(f.getClassDescriptor()) > 2 && f.getName().length() == 1) {
assumeReflective.add(f);
+ }
}
@@ -866,45 +925,50 @@ public class UnreadFields extends OpcodeStackDetector {
}
for (XField f : notInitializedInConstructors) {
String className = f.getClassName();
- if (notInitializedUses.getCount(className) >= 8)
+ if (notInitializedUses.getCount(className) >= 8) {
continue;
+ }
String fieldSignature = f.getSignature();
if (f.isResolved() && !data.fieldsOfNativeClasses.contains(f)
&& (fieldSignature.charAt(0) == 'L' || fieldSignature.charAt(0) == '[')) {
int priority = LOW_PRIORITY;
Set<ProgramPoint> assumedNonnullAt = data.assumedNonNull.get(f);
- if (assumedNonnullAt.size() < 4)
+ if (assumedNonnullAt.size() < 4) {
for (ProgramPoint p : assumedNonnullAt) {
BugInstance bug = new BugInstance(this, "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", priority)
- .addClass(className).addField(f).addMethod(p.getMethodAnnotation());
+ .addClass(className).addField(f).addMethod(p.getMethodAnnotation());
bugAccumulator.accumulateBug(bug, p.getSourceLineAnnotation());
}
+ }
}
}
for (XField f : readOnlyFields) {
- String fieldName = f.getName();
- String className = f.getClassName();
+ // String fieldName = f.getName();
+ // String className = f.getClassName();
String fieldSignature = f.getSignature();
if (f.isResolved() && !data.fieldsOfNativeClasses.contains(f)) {
int priority = NORMAL_PRIORITY;
- if (!(fieldSignature.charAt(0) == 'L' || fieldSignature.charAt(0) == '['))
+ if (!(fieldSignature.charAt(0) == 'L' || fieldSignature.charAt(0) == '[')) {
priority++;
- if (maxCount.containsKey(f))
+ }
+ if (maxCount.containsKey(f)) {
priority++;
+ }
String pattern = "UWF_UNWRITTEN_FIELD";
- if (f.isProtected() || f.isPublic())
+ if (f.isProtected() || f.isPublic()) {
pattern = "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD";
+ }
bugReporter.reportBug(addClassFieldAndAccess(new BugInstance(this, pattern, priority), f));
}
}
for (XField f : nullOnlyFields) {
- String fieldName = f.getName();
- String className = f.getClassName();
- String fieldSignature = f.getSignature();
+ // String fieldName = f.getName();
+ // String className = f.getClassName();
+ // String fieldSignature = f.getSignature();
if (DEBUG) {
System.out.println("Null only: " + f);
System.out.println(" : " + data.assumedNonNull.containsKey(f));
@@ -914,20 +978,24 @@ public class UnreadFields extends OpcodeStackDetector {
System.out.println(" : " + data.hasNonAbstractSubClass.contains(f.getClassName()));
System.out.println(" : " + f.isResolved());
}
- if (!f.isResolved())
+ if (!f.isResolved()) {
continue;
- if (data.fieldsOfNativeClasses.contains(f))
+ }
+ if (data.fieldsOfNativeClasses.contains(f)) {
continue;
+ }
if (DEBUG) {
System.out.println("Ready to report");
}
int priority = NORMAL_PRIORITY;
- if (maxCount.containsKey(f))
+ if (maxCount.containsKey(f)) {
priority++;
+ }
if (data.abstractClasses.contains(f.getClassName())) {
priority++;
- if (!data.hasNonAbstractSubClass.contains(f.getClassName()))
+ if (!data.hasNonAbstractSubClass.contains(f.getClassName())) {
priority++;
+ }
}
// if (fieldNamesSet.contains(f.getName())) priority++;
if (data.assumedNonNull.containsKey(f)) {
@@ -943,22 +1011,27 @@ public class UnreadFields extends OpcodeStackDetector {
}
String pattern = (f.isPublic() || f.isProtected()) ? "NP_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD"
: "NP_UNWRITTEN_FIELD";
- for (ProgramPoint p : assumedNonNullAt)
+ for (ProgramPoint p : assumedNonNullAt) {
bugAccumulator.accumulateBug(
new BugInstance(this, pattern, npPriority).addClassAndMethod(p.method).addField(f),
p.getSourceLineAnnotation());
+ }
} else {
- if (f.isStatic())
+ if (f.isStatic()) {
priority++;
- if (f.isFinal())
+ }
+ if (f.isFinal()) {
priority++;
- if (data.fieldsOfSerializableOrNativeClassed.contains(f))
+ }
+ if (data.fieldsOfSerializableOrNativeClassed.contains(f)) {
priority++;
+ }
}
- if (!readOnlyFields.contains(f))
+ if (!readOnlyFields.contains(f)) {
bugReporter.reportBug(addClassFieldAndAccess(new BugInstance(this, "UWF_NULL_FIELD", priority), f)
.lowerPriorityIfDeprecated());
+ }
}
writeOnlyFields: for (XField f : writeOnlyFields) {
@@ -972,25 +1045,30 @@ public class UnreadFields extends OpcodeStackDetector {
System.out.println("Checking write only field " + className + "." + fieldName + "\t" + data.constantFields.contains(f)
+ "\t" + f.isStatic());
}
- if (!f.isResolved())
+ if (!f.isResolved()) {
continue;
- if (dontComplainAbout.matcher(fieldName).find())
+ }
+ if (dontComplainAbout.matcher(fieldName).find()) {
continue;
+ }
if (lastDollar >= 0 && (fieldName.startsWith("this$") || fieldName.startsWith("this+"))) {
String outerClassName = className.substring(0, lastDollar);
try {
XClass thisClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, f.getClassDescriptor());
- if (isAnonymousInnerClass)
+ if (isAnonymousInnerClass) {
for (XField f2 : thisClass.getXFields()) {
if (f2 != f && f2.isPrivate() && f2.isSynthetic() && !f2.getName().startsWith("this$")
- && f2.getName().contains("$"))
+ && f2.getName().contains("$")) {
continue writeOnlyFields;
+ }
}
+ }
JavaClass outerClass = Repository.lookupClass(outerClassName);
- if (classHasParameter(outerClass))
+ if (classHasParameter(outerClass)) {
continue;
+ }
ClassDescriptor cDesc = DescriptorFactory.createClassDescriptorFromDottedClassName(outerClassName);
@@ -1000,10 +1078,10 @@ public class UnreadFields extends OpcodeStackDetector {
Subtypes2 subtypes2 = analysisContext.getSubtypes2();
- for (XField of : outerXClass.getXFields())
+ for (XField of : outerXClass.getXFields()) {
if (!of.isStatic()) {
String sourceSignature = of.getSourceSignature();
- if (sourceSignature != null && of.getSignature().equals("Ljava/lang/ThreadLocal;")) {
+ if (sourceSignature != null && "Ljava/lang/ThreadLocal;".equals(of.getSignature())) {
Type ofType = GenericUtilities.getType(sourceSignature);
if (ofType instanceof GenericObjectType) {
GenericObjectType gType = (GenericObjectType) ofType;
@@ -1016,8 +1094,9 @@ public class UnreadFields extends OpcodeStackDetector {
int priority = p == null ? NORMAL_PRIORITY : HIGH_PRIORITY;
BugInstance bug = new BugInstance(this, "SIC_THREADLOCAL_DEADLY_EMBRACE",
priority).addClass(className).addField(of);
- if (p != null)
+ if (p != null) {
bug.addMethod(p.method).add(p.getSourceLineAnnotation());
+ }
bugReporter.reportBug(bug);
}
}
@@ -1026,13 +1105,17 @@ public class UnreadFields extends OpcodeStackDetector {
}
}
+ }
boolean outerClassIsInnerClass = false;
- for (Field field : outerClass.getFields())
- if (field.getName().equals("this$0"))
+ for (Field field : outerClass.getFields()) {
+ if ("this$0".equals(field.getName())) {
outerClassIsInnerClass = true;
- if (outerClassIsInnerClass)
+ }
+ }
+ if (outerClassIsInnerClass) {
continue;
+ }
} catch (ClassNotFoundException e) {
bugReporter.reportMissingClass(e);
} catch (CheckedAnalysisException e) {
@@ -1048,14 +1131,16 @@ public class UnreadFields extends OpcodeStackDetector {
// false true not reported
// false false low, SIC_THIS
int priority = LOW_PRIORITY;
- if (easyChange && !isAnonymousInnerClass)
+ if (easyChange && !isAnonymousInnerClass) {
priority = NORMAL_PRIORITY;
+ }
String bug = "SIC_INNER_SHOULD_BE_STATIC";
- if (isAnonymousInnerClass)
+ if (isAnonymousInnerClass) {
bug = "SIC_INNER_SHOULD_BE_STATIC_ANON";
- else if (!easyChange)
+ } else if (!easyChange) {
bug = "SIC_INNER_SHOULD_BE_STATIC_NEEDS_THIS";
+ }
bugReporter.reportBug(new BugInstance(this, bug, priority).addClass(className));
@@ -1063,41 +1148,42 @@ public class UnreadFields extends OpcodeStackDetector {
}
} else if (f.isResolved()) {
if (data.constantFields.contains(f)) {
- if (!f.isStatic())
+ if (!f.isStatic()) {
bugReporter.reportBug(addClassFieldAndAccess(
new BugInstance(this, "SS_SHOULD_BE_STATIC", NORMAL_PRIORITY), f));
+ }
} else if (data.fieldsOfSerializableOrNativeClassed.contains(f)) {
// ignore it
- } else if (!data.writtenFields.contains(f))
+ } else if (!data.writtenFields.contains(f)) {
bugReporter.reportBug(new BugInstance(this,
(f.isPublic() || f.isProtected()) ? "UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD" : "UUF_UNUSED_FIELD",
- NORMAL_PRIORITY).addClass(className).addField(f).lowerPriorityIfDeprecated());
- else if (f.getName().toLowerCase().indexOf("guardian") < 0) {
+ NORMAL_PRIORITY).addClass(className).addField(f).lowerPriorityIfDeprecated());
+ } else if (f.getName().toLowerCase().indexOf("guardian") < 0) {
int priority = NORMAL_PRIORITY;
- if (f.isStatic())
+ if (f.isStatic()) {
priority++;
- if (f.isFinal())
+ }
+ if (f.isFinal()) {
priority++;
+ }
bugReporter.reportBug(addClassFieldAndAccess(new BugInstance(this,
(f.isPublic() || f.isProtected()) ? "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD" : "URF_UNREAD_FIELD",
- priority), f));
+ priority), f));
}
}
}
bugAccumulator.reportAccumulatedBugs();
}
- /**
- * @param instance
- * @return
- */
private BugInstance addClassFieldAndAccess(BugInstance instance, XField f) {
- if (data.writtenNonNullFields.contains(f) && data.readFields.contains(f))
+ if (data.writtenNonNullFields.contains(f) && data.readFields.contains(f)) {
throw new IllegalArgumentException("No information for fields that are both read and written nonnull");
+ }
instance.addClass(f.getClassName()).addField(f);
- if (data.fieldAccess.containsKey(f))
+ if (data.fieldAccess.containsKey(f)) {
instance.add(data.fieldAccess.get(f));
+ }
return instance;
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/UselessSubclassMethod.java b/src/java/edu/umd/cs/findbugs/detect/UselessSubclassMethod.java
index df60573..511c73f 100644
--- a/src/java/edu/umd/cs/findbugs/detect/UselessSubclassMethod.java
+++ b/src/java/edu/umd/cs/findbugs/detect/UselessSubclassMethod.java
@@ -98,9 +98,10 @@ public class UselessSubclassMethod extends BytecodeScanningDetector implements S
if ((interfaceMethods != null) && ((obj.getAccessFlags() & Constants.ACC_ABSTRACT) != 0)) {
String curDetail = obj.getName() + obj.getSignature();
for (String infMethodDetail : interfaceMethods) {
- if (curDetail.equals(infMethodDetail))
+ if (curDetail.equals(infMethodDetail)) {
bugReporter.reportBug(new BugInstance(this, "USM_USELESS_ABSTRACT_METHOD", LOW_PRIORITY).addClassAndMethod(
getClassContext().getJavaClass(), obj));
+ }
}
}
super.visitMethod(obj);
@@ -111,7 +112,7 @@ public class UselessSubclassMethod extends BytecodeScanningDetector implements S
try {
String methodName = getMethodName();
- if (!methodName.equals("<init>") && !methodName.equals("clone")
+ if (!"<init>".equals(methodName) && !"clone".equals(methodName)
&& ((getMethod().getAccessFlags() & (Constants.ACC_STATIC | Constants.ACC_SYNTHETIC)) == 0)) {
/*
@@ -120,13 +121,15 @@ public class UselessSubclassMethod extends BytecodeScanningDetector implements S
*/
Attribute[] atts = getMethod().getAttributes();
for (Attribute att : atts) {
- if (att.getClass().equals(Synthetic.class))
+ if (att.getClass().equals(Synthetic.class)) {
return;
+ }
}
byte[] codeBytes = obj.getCode();
- if ((codeBytes.length == 0) || (codeBytes[0] != ALOAD_0))
+ if ((codeBytes.length == 0) || (codeBytes[0] != ALOAD_0)) {
return;
+ }
state = State.SEEN_NOTHING;
invokePC = 0;
@@ -136,8 +139,9 @@ public class UselessSubclassMethod extends BytecodeScanningDetector implements S
Method superMethod = findSuperclassMethod(superclassName, getMethod());
if ((superMethod == null) || differentAttributes(getMethod(), superMethod)
|| getMethod().isProtected()
- && !samePackage(getDottedClassName(), superclassName))
+ && !samePackage(getDottedClassName(), superclassName)) {
return;
+ }
bugReporter.reportBug(new BugInstance(this, "USM_USELESS_SUBCLASS_METHOD", LOW_PRIORITY).addClassAndMethod(
this).addSourceLine(this, invokePC));
@@ -150,13 +154,14 @@ public class UselessSubclassMethod extends BytecodeScanningDetector implements S
public String getPackage(@DottedClassName String classname) {
int i = classname.lastIndexOf('.');
- if (i < 0)
+ if (i < 0) {
return "";
+ }
return classname.substring(0,i);
}
public boolean samePackage(@DottedClassName String classname1, @DottedClassName String classname2) {
return getPackage(classname1).equals(getPackage(classname2));
-
+
}
@Override
public void sawOpcode(int seen) {
@@ -166,18 +171,20 @@ public class UselessSubclassMethod extends BytecodeScanningDetector implements S
argTypes = Type.getArgumentTypes(this.getMethodSig());
curParm = 0;
curParmOffset = 1;
- if (argTypes.length > 0)
+ if (argTypes.length > 0) {
state = State.SEEN_PARM;
- else
+ } else {
state = State.SEEN_LAST_PARM;
- } else
+ }
+ } else {
state = State.SEEN_INVALID;
+ }
break;
case SEEN_PARM:
- if (curParm >= argTypes.length)
+ if (curParm >= argTypes.length) {
state = State.SEEN_INVALID;
- else {
+ } else {
String signature = argTypes[curParm++].getSignature();
char typeChar0 = signature.charAt(0);
if ((typeChar0 == 'L') || (typeChar0 == '[')) {
@@ -190,11 +197,13 @@ public class UselessSubclassMethod extends BytecodeScanningDetector implements S
checkParm(seen, ILOAD_0, ILOAD, 1);
} else if (typeChar0 == 'J') {
checkParm(seen, LLOAD_0, LLOAD, 2);
- } else
+ } else {
state = State.SEEN_INVALID;
+ }
- if ((state != State.SEEN_INVALID) && (curParm >= argTypes.length))
+ if ((state != State.SEEN_INVALID) && (curParm >= argTypes.length)) {
state = State.SEEN_LAST_PARM;
+ }
}
break;
@@ -204,48 +213,54 @@ public class UselessSubclassMethod extends BytecodeScanningDetector implements S
&& getMethodSig().equals(getSigConstantOperand())) {
invokePC = getPC();
state = State.SEEN_INVOKE;
- } else
+ } else {
state = State.SEEN_INVALID;
+ }
break;
case SEEN_INVOKE:
Type returnType = getMethod().getReturnType();
char retSigChar0 = returnType.getSignature().charAt(0);
- if ((retSigChar0 == 'V') && (seen == RETURN))
+ if ((retSigChar0 == 'V') && (seen == RETURN)) {
state = State.SEEN_RETURN;
- else if (((retSigChar0 == 'L') || (retSigChar0 == '[')) && (seen == ARETURN))
+ } else if (((retSigChar0 == 'L') || (retSigChar0 == '[')) && (seen == ARETURN)) {
state = State.SEEN_RETURN;
- else if ((retSigChar0 == 'D') && (seen == DRETURN))
+ } else if ((retSigChar0 == 'D') && (seen == DRETURN)) {
state = State.SEEN_RETURN;
- else if ((retSigChar0 == 'F') && (seen == FRETURN))
+ } else if ((retSigChar0 == 'F') && (seen == FRETURN)) {
state = State.SEEN_RETURN;
- else if ((retSigChar0 == 'I' || retSigChar0 == 'S' || retSigChar0 == 'C' || retSigChar0 == 'B' || retSigChar0 == 'Z')
- && (seen == IRETURN))
+ } else if ((retSigChar0 == 'I' || retSigChar0 == 'S' || retSigChar0 == 'C' || retSigChar0 == 'B' || retSigChar0 == 'Z')
+ && (seen == IRETURN)) {
state = State.SEEN_RETURN;
- else if ((retSigChar0 == 'J') && (seen == LRETURN))
+ } else if ((retSigChar0 == 'J') && (seen == LRETURN)) {
state = State.SEEN_RETURN;
- else
+ } else {
state = State.SEEN_INVALID;
+ }
break;
case SEEN_RETURN:
state = State.SEEN_INVALID;
break;
+ default:
+ break;
}
}
private void checkParm(int seen, int fastOpBase, int slowOp, int parmSize) {
if ((curParmOffset >= 1) && (curParmOffset <= 3)) {
- if (seen == (fastOpBase + curParmOffset))
+ if (seen == (fastOpBase + curParmOffset)) {
curParmOffset += parmSize;
- else
+ } else {
state = State.SEEN_INVALID;
- } else if (curParmOffset == 0)
+ }
+ } else if (curParmOffset == 0) {
state = State.SEEN_INVALID;
- else if ((seen == slowOp) && (getRegisterOperand() == curParmOffset))
+ } else if ((seen == slowOp) && (getRegisterOperand() == curParmOffset)) {
curParmOffset += parmSize;
- else
+ } else {
state = State.SEEN_INVALID;
+ }
}
private Method findSuperclassMethod(@DottedClassName String superclassName, Method subclassMethod) throws ClassNotFoundException {
@@ -256,20 +271,22 @@ public class UselessSubclassMethod extends BytecodeScanningDetector implements S
Method[] methods = superClass.getMethods();
outer: for (Method m : methods) {
if (m.getName().equals(methodName)) {
- if (subArgs == null)
+ if (subArgs == null) {
subArgs = Type.getArgumentTypes(subclassMethod.getSignature());
+ }
Type[] superArgs = Type.getArgumentTypes(m.getSignature());
if (subArgs.length == superArgs.length) {
for (int j = 0; j < subArgs.length; j++) {
- if (!superArgs[j].equals(subArgs[j]))
+ if (!superArgs[j].equals(subArgs[j])) {
continue outer;
+ }
}
return m;
}
}
}
- if (!superclassName.equals("Object")) {
+ if (!"Object".equals(superclassName)) {
@DottedClassName String superSuperClassName = superClass.getSuperclassName();
if (superSuperClassName.equals(superclassName)) {
throw new ClassNotFoundException("superclass of " + superclassName + " is itself");
@@ -283,26 +300,30 @@ public class UselessSubclassMethod extends BytecodeScanningDetector implements S
HashSet<String> thrownExceptions(Method m) {
HashSet<String> result = new HashSet<String>();
ExceptionTable exceptionTable = m.getExceptionTable();
- if (exceptionTable != null)
- for (String e : exceptionTable.getExceptionNames())
+ if (exceptionTable != null) {
+ for (String e : exceptionTable.getExceptionNames()) {
result.add(e);
+ }
+ }
return result;
}
private boolean differentAttributes(Method m1, Method m2) {
- if (m1.getAnnotationEntries().length > 0 || m2.getAnnotationEntries().length > 0)
+ if (m1.getAnnotationEntries().length > 0 || m2.getAnnotationEntries().length > 0) {
return true;
+ }
int access1 = m1.getAccessFlags()
& (Constants.ACC_PRIVATE | Constants.ACC_PROTECTED | Constants.ACC_PUBLIC | Constants.ACC_FINAL);
int access2 = m2.getAccessFlags()
& (Constants.ACC_PRIVATE | Constants.ACC_PROTECTED | Constants.ACC_PUBLIC | Constants.ACC_FINAL);
-
+
m1.getAnnotationEntries();
- if (access1 != access2)
+ if (access1 != access2) {
return true;
- if (!thrownExceptions(m1).equals(thrownExceptions(m2)))
+ }
+ if (!thrownExceptions(m1).equals(thrownExceptions(m2))) {
return false;
- m1.getExceptionTable();
+ }
return false;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/VarArgsProblems.java b/src/java/edu/umd/cs/findbugs/detect/VarArgsProblems.java
index 6494292..c6959e9 100644
--- a/src/java/edu/umd/cs/findbugs/detect/VarArgsProblems.java
+++ b/src/java/edu/umd/cs/findbugs/detect/VarArgsProblems.java
@@ -41,7 +41,7 @@ import edu.umd.cs.findbugs.TypeAnnotation;
public class VarArgsProblems extends BytecodeScanningDetector implements StatelessDetector {
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
private int state;
@@ -80,11 +80,12 @@ public class VarArgsProblems extends BytecodeScanningDetector implements Statele
// System.out.println("State:" + state);
if (seen == GOTO && getBranchOffset() == 4) {
state = SEEN_GOTO;
- } else
+ } else {
switch (state) {
case SEEN_NOTHING:
- if ((seen == ICONST_1))
+ if ((seen == ICONST_1)) {
state = SEEN_ICONST_1;
+ }
break;
case SEEN_ICONST_1:
@@ -93,34 +94,39 @@ public class VarArgsProblems extends BytecodeScanningDetector implements Statele
// getClassConstantOperand());
primitiveArraySig = getClassConstantOperand();
state = SEEN_ANEWARRAY;
- } else
+ } else {
state = SEEN_NOTHING;
+ }
break;
case SEEN_ANEWARRAY:
- if (seen == DUP)
+ if (seen == DUP) {
state = SEEN_DUP;
- else
+ } else {
state = SEEN_NOTHING;
+ }
break;
case SEEN_DUP:
- if (seen == ICONST_0)
+ if (seen == ICONST_0) {
state = SEEN_ICONST_0;
- else
+ } else {
state = SEEN_NOTHING;
+ }
break;
case SEEN_ICONST_0:
- if (((seen >= ALOAD_0) && (seen < ALOAD_3)) || (seen == ALOAD))
+ if (((seen >= ALOAD_0) && (seen < ALOAD_3)) || (seen == ALOAD)) {
state = SEEN_ALOAD;
- else
+ } else {
state = SEEN_NOTHING;
+ }
break;
case SEEN_ALOAD:
- if (seen == AASTORE)
+ if (seen == AASTORE) {
state = SEEN_AASTORE;
- else
+ } else {
state = SEEN_NOTHING;
+ }
break;
case SEEN_AASTORE:
@@ -128,14 +134,16 @@ public class VarArgsProblems extends BytecodeScanningDetector implements Statele
// System.out.println(getClassConstantOperand());
// System.out.println(getNameConstantOperand());
// System.out.println(getSigConstantOperand());
- if (getSigConstantOperand().indexOf("Ljava/lang/Object;)") == -1)
+ if (getSigConstantOperand().indexOf("Ljava/lang/Object;)") == -1) {
break;
+ }
int priority = NORMAL_PRIORITY;
- if (getNameConstantOperand().equals("asList") && getClassConstantOperand().equals("java/util/Arrays"))
+ if ("asList".equals(getNameConstantOperand()) && "java/util/Arrays".equals(getClassConstantOperand())) {
priority = HIGH_PRIORITY;
+ }
bugReporter.reportBug(new BugInstance(this, "VA_PRIMITIVE_ARRAY_PASSED_TO_OBJECT_VARARG", priority)
- .addClassAndMethod(this).addType(primitiveArraySig).describe(TypeAnnotation.FOUND_ROLE)
- .addCalledMethod(this).addSourceLine(this));
+ .addClassAndMethod(this).addType(primitiveArraySig).describe(TypeAnnotation.FOUND_ROLE)
+ .addCalledMethod(this).addSourceLine(this));
}
state = SEEN_NOTHING;
break;
@@ -147,5 +155,6 @@ public class VarArgsProblems extends BytecodeScanningDetector implements Statele
throw new IllegalStateException("State " + state + " not expected");
}
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/VolatileUsage.java b/src/java/edu/umd/cs/findbugs/detect/VolatileUsage.java
index 43c3ac3..85bf74d 100644
--- a/src/java/edu/umd/cs/findbugs/detect/VolatileUsage.java
+++ b/src/java/edu/umd/cs/findbugs/detect/VolatileUsage.java
@@ -76,48 +76,57 @@ public class VolatileUsage extends BytecodeScanningDetector {
}
break;
case GETFIELD:
- if (seen == ICONST_1 || seen == LCONST_1 || seen == ICONST_M1)
+ if (seen == ICONST_1 || seen == LCONST_1 || seen == ICONST_M1) {
state = IncrementState.LOADCONSTANT;
- else
+ } else {
resetIncrementState();
+ }
break;
case LOADCONSTANT:
if (seen == IADD || seen == ISUB || seen == LADD || seen == LSUB) {
state = IncrementState.ADD;
- } else
+ } else {
resetIncrementState();
+ }
break;
case ADD:
- if (seen == PUTFIELD && incrementField.equals(getXFieldOperand()))
+ if (seen == PUTFIELD && incrementField.equals(getXFieldOperand())) {
bugReporter.reportBug(new BugInstance(this, "VO_VOLATILE_INCREMENT",
- incrementField.getSignature().equals("J") ? Priorities.HIGH_PRIORITY : Priorities.NORMAL_PRIORITY)
- .addClassAndMethod(this).addField(incrementField).addSourceLine(this));
+ "J".equals(incrementField.getSignature()) ? Priorities.HIGH_PRIORITY : Priorities.NORMAL_PRIORITY)
+ .addClassAndMethod(this).addField(incrementField).addSourceLine(this));
+ }
resetIncrementState();
break;
}
switch (seen) {
case PUTSTATIC: {
XField f = getXFieldOperand();
- if (!isVolatileArray(f))
+ if (!isVolatileArray(f)) {
return;
- if (getMethodName().equals("<clinit>"))
+ }
+ if ("<clinit>".equals(getMethodName())) {
initializationWrites.add(f);
- else
+ } else {
otherWrites.add(f);
+ }
break;
}
case PUTFIELD: {
XField f = getXFieldOperand();
- if (!isVolatileArray(f))
+ if (!isVolatileArray(f)) {
return;
+ }
- if (getMethodName().equals("<init>"))
+ if ("<init>".equals(getMethodName())) {
initializationWrites.add(f);
- else
+ } else {
otherWrites.add(f);
+ }
break;
}
+ default:
+ break;
}
}
@@ -133,20 +142,18 @@ public class VolatileUsage extends BytecodeScanningDetector {
public void report() {
Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();
- for (XField f : AnalysisContext.currentXFactory().allFields())
+ for (XField f : AnalysisContext.currentXFactory().allFields()) {
if (isVolatileArray(f) && subtypes2.isApplicationClass(f.getClassDescriptor())) {
int priority = LOW_PRIORITY;
- if (initializationWrites.contains(f) && !otherWrites.contains(f))
+ if (initializationWrites.contains(f) && !otherWrites.contains(f)) {
priority = NORMAL_PRIORITY;
+ }
bugReporter.reportBug(new BugInstance(this, "VO_VOLATILE_REFERENCE_TO_ARRAY", priority).addClass(
f.getClassDescriptor()).addField(f));
}
+ }
}
- /**
- * @param f
- * @return
- */
private boolean isVolatile(XField f) {
return f != null && f.isVolatile();
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/WaitInLoop.java b/src/java/edu/umd/cs/findbugs/detect/WaitInLoop.java
index 226db53..3df7d1d 100644
--- a/src/java/edu/umd/cs/findbugs/detect/WaitInLoop.java
+++ b/src/java/edu/umd/cs/findbugs/detect/WaitInLoop.java
@@ -42,7 +42,7 @@ public class WaitInLoop extends BytecodeScanningDetector implements StatelessDet
int waitAt = 0;
- private BugReporter bugReporter;
+ private final BugReporter bugReporter;
public WaitInLoop(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -59,36 +59,38 @@ public class WaitInLoop extends BytecodeScanningDetector implements StatelessDet
if ((sawWait || sawAwait) && waitAt < earliestJump) {
String bugType = sawWait ? "WA_NOT_IN_LOOP" : "WA_AWAIT_NOT_IN_LOOP";
bugReporter.reportBug(new BugInstance(this, bugType, waitHasTimeout ? LOW_PRIORITY : NORMAL_PRIORITY)
- .addClassAndMethod(this).addSourceLine(this, waitAt));
+ .addClassAndMethod(this).addSourceLine(this, waitAt));
}
- if (sawNotify)
+ if (sawNotify) {
bugReporter.reportBug(new BugInstance(this, "NO_NOTIFY_NOT_NOTIFYALL", LOW_PRIORITY).addClassAndMethod(this)
.addSourceLine(this, notifyPC));
+ }
}
@Override
public void sawOpcode(int seen) {
- if ((seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) && getNameConstantOperand().equals("notify")
- && getSigConstantOperand().equals("()V")) {
+ if ((seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE) && "notify".equals(getNameConstantOperand())
+ && "()V".equals(getSigConstantOperand())) {
sawNotify = true;
notifyPC = getPC();
}
if (!(sawWait || sawAwait) && (seen == INVOKEVIRTUAL || seen == INVOKEINTERFACE)
&& (isMonitorWait() || isConditionAwait())) {
- if (getNameConstantOperand().equals("wait")) {
+ if ("wait".equals(getNameConstantOperand())) {
sawWait = true;
} else {
sawAwait = true;
}
- waitHasTimeout = !getSigConstantOperand().equals("()V");
+ waitHasTimeout = !"()V".equals(getSigConstantOperand());
waitAt = getPC();
earliestJump = getPC() + 1;
return;
}
- if (seen >= IFEQ && seen <= GOTO || seen >= IFNULL && seen <= GOTO_W)
+ if (seen >= IFEQ && seen <= GOTO || seen >= IFNULL && seen <= GOTO_W) {
earliestJump = Math.min(earliestJump, getBranchTarget());
+ }
}
private boolean isConditionAwait() {
@@ -96,20 +98,26 @@ public class WaitInLoop extends BytecodeScanningDetector implements StatelessDet
String name = getNameConstantOperand();
String sig = getSigConstantOperand();
- if (!className.equals("java/util/concurrent/locks/Condition"))
+ if (!"java/util/concurrent/locks/Condition".equals(className)) {
return false;
+ }
- if (!name.startsWith("await"))
+ if (!name.startsWith("await")) {
return false;
+ }
- if (name.equals("await") && (sig.equals("()V") || sig.equals("(JLjava/util/concurrent/TimeUnit;)V")))
+ if ("await".equals(name) && ("()V".equals(sig) || "(JLjava/util/concurrent/TimeUnit;)V".equals(sig))) {
return true;
- if (name.equals("awaitNanos") && sig.equals("(J)V"))
+ }
+ if ("awaitNanos".equals(name) && "(J)V".equals(sig)) {
return true;
- if (name.equals("awaitUninterruptibly") && sig.equals("()V"))
+ }
+ if ("awaitUninterruptibly".equals(name) && "()V".equals(sig)) {
return true;
- if (name.equals("awaitUntil") && sig.equals("(Ljava/util/Date;)V"))
+ }
+ if ("awaitUntil".equals(name) && "(Ljava/util/Date;)V".equals(sig)) {
return true;
+ }
return false;
}
@@ -118,7 +126,7 @@ public class WaitInLoop extends BytecodeScanningDetector implements StatelessDet
String name = getNameConstantOperand();
String sig = getSigConstantOperand();
- return name.equals("wait") && (sig.equals("()V") || sig.equals("(J)V") || sig.equals("(JI)V"));
+ return "wait".equals(name) && ("()V".equals(sig) || "(J)V".equals(sig) || "(JI)V".equals(sig));
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/WrongMapIterator.java b/src/java/edu/umd/cs/findbugs/detect/WrongMapIterator.java
index 8afec88..6102711 100644
--- a/src/java/edu/umd/cs/findbugs/detect/WrongMapIterator.java
+++ b/src/java/edu/umd/cs/findbugs/detect/WrongMapIterator.java
@@ -20,6 +20,9 @@
package edu.umd.cs.findbugs.detect;
+import java.util.Collections;
+import java.util.Set;
+
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.Method;
@@ -29,45 +32,89 @@ import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.MethodAnnotation;
import edu.umd.cs.findbugs.StatelessDetector;
+import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.ba.XClass;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
+import edu.umd.cs.findbugs.classfile.FieldDescriptor;
import edu.umd.cs.findbugs.classfile.Global;
+import edu.umd.cs.findbugs.classfile.MethodDescriptor;
public class WrongMapIterator extends BytecodeScanningDetector implements StatelessDetector {
- private BugAccumulator bugAccumulator;
-
- private static final int SAW_NOTHING = 0;
-
- private static final int SAW_MAP_LOAD1 = 1;
+ private static final Set<MethodDescriptor> methods = Collections.singleton(new MethodDescriptor("", "keySet", "()Ljava/util/Set;"));
- private static final int SAW_KEYSET = 2;
-
- private static final int SAW_KEYSET_STORE = 3;
+ static enum LoadedVariableState {
+ NOTHING, LOCAL, FIELD
+ }
- private static final int SAW_ITERATOR = 4;
+ final LoadedVariable NONE = new LoadedVariable(LoadedVariableState.NOTHING, 0, null);
- private static final int SAW_ITERATOR_STORE = 5;
+ final class LoadedVariable {
+ private final LoadedVariableState lvState;
+ private final int num;
+ private final FieldDescriptor fd;
- private static final int SAW_ITERATOR_LOAD = 6;
+ private LoadedVariable(LoadedVariableState state, int num, FieldDescriptor fd) {
+ this.lvState = state;
+ this.num = num;
+ this.fd = fd;
+ }
- private static final int SAW_NEXT = 7;
+ public boolean none() {
+ return lvState == LoadedVariableState.NOTHING;
+ }
- private static final int SAW_CHECKCAST_ON_NEXT = 8;
+ public boolean isRegister(int register) {
+ return lvState == LoadedVariableState.LOCAL && num == register;
+ }
- private static final int SAW_KEY_STORE = 9;
+ public LoadedVariable seen(int opcode) {
+ if(isRegisterLoad() && !isRegisterStore()) {
+ return new LoadedVariable(LoadedVariableState.LOCAL, getRegisterOperand(), null);
+ }
+ switch(opcode) {
+ case GETSTATIC:
+ return new LoadedVariable(LoadedVariableState.FIELD, 0, getFieldDescriptorOperand());
+ case GETFIELD:
+ if(lvState == LoadedVariableState.LOCAL && num == 0) {
+ // Ignore fields from other classes
+ return new LoadedVariable(LoadedVariableState.FIELD, 0, getFieldDescriptorOperand());
+ }
+ return NONE;
+ default:
+ return NONE;
+ }
+ }
- private static final int NEED_KEYSET_LOAD = 10;
+ public boolean same(LoadedVariable other) {
+ if(other.lvState != lvState) {
+ return false;
+ }
+ if(lvState == LoadedVariableState.LOCAL && num != other.num) {
+ return false;
+ }
+ if ((lvState == LoadedVariableState.FIELD) && !fd.equals(other.fd)) {
+ return false;
+ }
+ return true;
+ }
- private static final int SAW_MAP_LOAD2 = 11;
+ public BugInstance annotate(BugInstance bug) {
+ if(lvState == LoadedVariableState.FIELD) {
+ bug.addField(fd);
+ }
+ return bug;
+ }
+ }
- private static final int SAW_KEY_LOAD = 12;
+ private final BugAccumulator bugAccumulator;
- private int state;
+ private static final int NOT_FOUND = -2;
+ private static final int IN_STACK = -1;
- private int loadedRegister;
+ private LoadedVariable loadedVariable = NONE;
- private int mapRegister;
+ private LoadedVariable mapVariable = NONE;
private int keySetRegister;
@@ -75,18 +122,31 @@ public class WrongMapIterator extends BytecodeScanningDetector implements Statel
private int keyRegister;
+ private boolean mapAndKeyLoaded;
+
public WrongMapIterator(BugReporter bugReporter) {
this.bugAccumulator = new BugAccumulator(bugReporter);
}
@Override
+ public void visitClassContext(ClassContext classContext) {
+ if(hasInterestingMethod(classContext.getJavaClass().getConstantPool(), methods)) {
+ super.visitClassContext(classContext);
+ }
+ }
+
+ @Override
public void visit(Method obj) {
- state = SAW_NOTHING;
- loadedRegister = -1;
- mapRegister = -1;
- keySetRegister = -1;
- iteratorRegister = -1;
- keyRegister = -1;
+ reset();
+ }
+
+ private void reset() {
+ loadedVariable = NONE;
+ mapVariable = NONE;
+ mapAndKeyLoaded = false;
+ keySetRegister = NOT_FOUND;
+ iteratorRegister = NOT_FOUND;
+ keyRegister = NOT_FOUND;
}
@Override
@@ -98,7 +158,7 @@ public class WrongMapIterator extends BytecodeScanningDetector implements Statel
/**
* Determine from the class descriptor for a variable whether that variable
* implements java.util.Map.
- *
+ *
* @param d
* class descriptor for variable we want to check implements Map
* @return true iff the descriptor corresponds to an implementor of Map
@@ -125,148 +185,96 @@ public class WrongMapIterator extends BytecodeScanningDetector implements Statel
return false;
}
- @Override
- public void sawOpcode(int seen) {
- switch (state) {
- case SAW_NOTHING:
- loadedRegister = getLoadStoreRegister(seen, true);
- if (loadedRegister >= 0)
- state = SAW_MAP_LOAD1;
- break;
-
- case SAW_MAP_LOAD1:
- // Doesn't check to see if the target object is a Map
- if (((seen == INVOKEINTERFACE) || (seen == INVOKEVIRTUAL)) && ("keySet".equals(getNameConstantOperand()))
- && ("()Ljava/util/Set;".equals(getSigConstantOperand()))
- // Following check solves sourceforge bug 1830576
- && implementsMap(getClassDescriptorOperand())) {
- mapRegister = loadedRegister;
- state = SAW_KEYSET;
- } else {
- state = SAW_NOTHING;
- }
- break;
-
- case SAW_KEYSET:
- keySetRegister = getLoadStoreRegister(seen, false);
- if (keySetRegister >= 0)
- state = SAW_KEYSET_STORE;
- else if ((seen == INVOKEINTERFACE) && ("iterator".equals(getNameConstantOperand()))
- && ("()Ljava/util/Iterator;".equals(getSigConstantOperand())))
- state = SAW_ITERATOR;
- else
- state = SAW_NOTHING;
- break;
-
- case SAW_KEYSET_STORE:
- if ((seen == INVOKEINTERFACE) && ("iterator".equals(getNameConstantOperand()))
- && ("()Ljava/util/Iterator;".equals(getSigConstantOperand())))
- state = SAW_ITERATOR;
- else
- state = NEED_KEYSET_LOAD;
- break;
-
- case NEED_KEYSET_LOAD:
- loadedRegister = getLoadStoreRegister(seen, true);
- if (loadedRegister == iteratorRegister)
- state = SAW_ITERATOR;
- break;
-
- case SAW_ITERATOR:
- iteratorRegister = getLoadStoreRegister(seen, false);
- if (iteratorRegister >= 0)
- state = SAW_ITERATOR_STORE;
- else
- state = SAW_NOTHING;
- break;
-
- case SAW_ITERATOR_STORE:
- loadedRegister = getLoadStoreRegister(seen, true);
- if (loadedRegister == iteratorRegister)
- state = SAW_ITERATOR_LOAD;
- break;
-
- case SAW_ITERATOR_LOAD:
- if ((seen == INVOKEINTERFACE) && ("next".equals(getNameConstantOperand()))
- && ("()Ljava/lang/Object;".equals(getSigConstantOperand())))
- state = SAW_NEXT;
- else
- state = SAW_ITERATOR_STORE;
- break;
-
- case SAW_NEXT:
- if (seen == CHECKCAST)
- state = SAW_CHECKCAST_ON_NEXT;
- else {
- keyRegister = getLoadStoreRegister(seen, false);
- if (keyRegister >= 0)
- state = SAW_KEY_STORE;
- else
- state = SAW_NOTHING;
- }
- break;
-
- case SAW_CHECKCAST_ON_NEXT:
- keyRegister = getLoadStoreRegister(seen, false);
- if (keyRegister >= 0)
- state = SAW_KEY_STORE;
- break;
-
- case SAW_KEY_STORE:
- loadedRegister = getLoadStoreRegister(seen, true);
- if (loadedRegister == mapRegister)
- state = SAW_MAP_LOAD2;
- break;
-
- case SAW_MAP_LOAD2:
- loadedRegister = getLoadStoreRegister(seen, true);
- if (loadedRegister == keyRegister)
- state = SAW_KEY_LOAD;
- else
- state = SAW_KEY_STORE;
- break;
-
- case SAW_KEY_LOAD:
- if (((seen == INVOKEINTERFACE) || (seen == INVOKEVIRTUAL)) && ("get".equals(getNameConstantOperand()))
- && ("(Ljava/lang/Object;)Ljava/lang/Object;".equals(getSigConstantOperand()))) {
- MethodAnnotation ma = MethodAnnotation.fromVisitedMethod(this);
- bugAccumulator.accumulateBug(new BugInstance(this, "WMI_WRONG_MAP_ITERATOR", NORMAL_PRIORITY).addClass(this)
- .addMethod(ma), this);
- state = SAW_NOTHING;
- }
- break;
+ private int handleStore(int storeRegister, int current) {
+ if(storeRegister == current) {
+ return NOT_FOUND;
}
+ if(current == IN_STACK) {
+ return storeRegister;
+ }
+ return current;
+ }
+
+ private void handleStore(int register) {
+ keySetRegister = handleStore(register, keySetRegister);
+ iteratorRegister = handleStore(register, iteratorRegister);
+ keyRegister = handleStore(register, keyRegister);
}
- private int getLoadStoreRegister(int seen, boolean doLoad) {
- switch (seen) {
- case ALOAD_0:
- case ALOAD_1:
- case ALOAD_2:
- case ALOAD_3:
- if (doLoad)
- return seen - ALOAD_0;
- break;
-
- case ALOAD:
- if (doLoad)
- return getRegisterOperand();
- break;
-
- case ASTORE_0:
- case ASTORE_1:
- case ASTORE_2:
- case ASTORE_3:
- if (!doLoad)
- return seen - ASTORE_0;
- break;
-
- case ASTORE:
- if (!doLoad)
- return getRegisterOperand();
- break;
+ private void removedFromStack(boolean includeKey) {
+ if(keySetRegister == IN_STACK) {
+ keySetRegister = NOT_FOUND;
+ }
+ if(iteratorRegister == IN_STACK) {
+ iteratorRegister = NOT_FOUND;
+ }
+ if(keyRegister == IN_STACK && includeKey) {
+ keyRegister = NOT_FOUND;
}
+ }
- return -1;
+ @Override
+ public void sawOpcode(int seen) {
+ boolean loadedPreserved = false;
+ if(isRegisterStore() && !isRegisterLoad()) {
+ handleStore(getRegisterOperand());
+ } else {
+ switch (seen) {
+ case INVOKEINTERFACE:
+ case INVOKEVIRTUAL:
+ if (!loadedVariable.none() &&
+ "keySet".equals(getNameConstantOperand()) && "()Ljava/util/Set;".equals(getSigConstantOperand())
+ // Following check solves sourceforge bug 1830576
+ && implementsMap(getClassDescriptorOperand())) {
+ mapVariable = loadedVariable;
+ removedFromStack(true);
+ keySetRegister = IN_STACK;
+ } else if ((keySetRegister == IN_STACK || loadedVariable.isRegister(keySetRegister))
+ && "iterator".equals(getNameConstantOperand()) && "()Ljava/util/Iterator;".equals(getSigConstantOperand())) {
+ removedFromStack(true);
+ iteratorRegister = IN_STACK;
+ } else if ((iteratorRegister == IN_STACK || loadedVariable.isRegister(iteratorRegister))
+ && "next".equals(getNameConstantOperand())
+ && "()Ljava/lang/Object;".equals(getSigConstantOperand())) {
+ removedFromStack(true);
+ keyRegister = IN_STACK;
+ } else if (mapAndKeyLoaded && "get".equals(getNameConstantOperand())
+ && "(Ljava/lang/Object;)Ljava/lang/Object;".equals(getSigConstantOperand())) {
+ MethodAnnotation ma = MethodAnnotation.fromVisitedMethod(this);
+ bugAccumulator.accumulateBug(mapVariable
+ .annotate(new BugInstance(this, "WMI_WRONG_MAP_ITERATOR", NORMAL_PRIORITY).addClass(this).addMethod(ma)),
+ this);
+ reset();
+ } else if(("intValue".equals(getNameConstantOperand()) && "java/lang/Integer".equals(getClassConstantOperand())) ||
+ ("longValue".equals(getNameConstantOperand()) && "java/lang/Long".equals(getClassConstantOperand())) ||
+ ("doubleValue".equals(getNameConstantOperand()) && "java/lang/Double".equals(getClassConstantOperand())) ||
+ ("floatValue".equals(getNameConstantOperand()) && "java/lang/Float".equals(getClassConstantOperand()))) {
+ removedFromStack(false);
+ } else {
+ removedFromStack(true);
+ }
+ break;
+ case INVOKESTATIC:
+ if ("valueOf".equals(getNameConstantOperand())
+ && ("java/lang/Integer".equals(getClassConstantOperand())
+ || "java/lang/Long".equals(getClassConstantOperand())
+ || "java/lang/Double".equals(getClassConstantOperand()) || "java/lang/Float"
+ .equals(getClassConstantOperand()))) {
+ loadedPreserved = true;
+ }
+ removedFromStack(true);
+ break;
+ case CHECKCAST:
+ removedFromStack(false);
+ break;
+ default:
+ removedFromStack(true);
+ }
+ }
+ if(!loadedPreserved) {
+ boolean mapLoaded = !loadedVariable.none() && loadedVariable.same(mapVariable);
+ loadedVariable = loadedVariable.seen(seen);
+ mapAndKeyLoaded = mapLoaded && loadedVariable.isRegister(keyRegister);
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/detect/XMLFactoryBypass.java b/src/java/edu/umd/cs/findbugs/detect/XMLFactoryBypass.java
index 8052190..7d443c7 100644
--- a/src/java/edu/umd/cs/findbugs/detect/XMLFactoryBypass.java
+++ b/src/java/edu/umd/cs/findbugs/detect/XMLFactoryBypass.java
@@ -71,28 +71,34 @@ public class XMLFactoryBypass extends BytecodeScanningDetector {
try {
if (seen == INVOKESPECIAL) {
String newClsName = getClassConstantOperand();
- if (rejectedXMLClasses.contains(newClsName))
+ if (rejectedXMLClasses.contains(newClsName)) {
return;
+ }
rejectedXMLClasses.add(newClsName);
- if (newClsName.startsWith("java/") || newClsName.startsWith("javax/"))
+ if (newClsName.startsWith("java/") || newClsName.startsWith("javax/")) {
return;
+ }
- if (newClsName.endsWith("Adapter"))
+ if (newClsName.endsWith("Adapter")) {
return;
+ }
- if (!getNameConstantOperand().equals("<init>"))
+ if (!"<init>".equals(getNameConstantOperand())) {
return;
+ }
String invokerClsName = this.getClassName();
- if (samePackageBase(invokerClsName, newClsName))
+ if (samePackageBase(invokerClsName, newClsName)) {
return;
+ }
JavaClass newCls = Repository.lookupClass(getDottedClassConstantOperand());
JavaClass superCls = curClass.getSuperClass();
- if (superCls.getClassName().equals(newClsName.replace('/', '.')))
+ if (superCls.getClassName().equals(newClsName.replace('/', '.'))) {
return;
+ }
JavaClass[] infs = newCls.getAllInterfaces();
for (JavaClass inf : infs) {
@@ -112,13 +118,16 @@ public class XMLFactoryBypass extends BytecodeScanningDetector {
String[] invokerParts = invokerClsName.split("/");
String[] newClsParts = newClsName.split("/");
- if (newClsParts.length < 3)
+ if (newClsParts.length < 3) {
return false;
- if (invokerParts.length < 3)
+ }
+ if (invokerParts.length < 3) {
return false;
+ }
- if (!invokerParts[0].equals(newClsParts[0]))
+ if (!invokerParts[0].equals(newClsParts[0])) {
return false;
+ }
return invokerParts[1].equals(newClsParts[1]);
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/AndMatcher.java b/src/java/edu/umd/cs/findbugs/filter/AndMatcher.java
index 33aa933..153ebdd 100644
--- a/src/java/edu/umd/cs/findbugs/filter/AndMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/AndMatcher.java
@@ -33,18 +33,21 @@ public class AndMatcher extends CompoundMatcher {
return anyMatches;
}
+ @Override
public boolean match(BugInstance bugInstance) {
Iterator<Matcher> i = childIterator();
while (i.hasNext()) {
Matcher child = i.next();
- if (!child.match(bugInstance))
+ if (!child.match(bugInstance)) {
return false;
+ }
}
anyMatches = true;
return true;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
if (numberChildren() == 1) {
// System.out.println("One child: " + this);
@@ -52,8 +55,9 @@ public class AndMatcher extends CompoundMatcher {
return;
}
xmlOutput.startTag("And");
- if (disabled)
+ if (disabled) {
xmlOutput.addAttribute("disabled", "true");
+ }
xmlOutput.stopTag(false);
super.writeChildrenXML(xmlOutput);
xmlOutput.closeTag("And");
@@ -61,11 +65,11 @@ public class AndMatcher extends CompoundMatcher {
@Override
public String toString() {
- if (numberChildren() == 1)
+ if (numberChildren() == 1) {
return super.toString();
+ }
return "And(" + super.toString() + ")";
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/filter/BugMatcher.java b/src/java/edu/umd/cs/findbugs/filter/BugMatcher.java
index 7890c9e..a188081 100644
--- a/src/java/edu/umd/cs/findbugs/filter/BugMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/BugMatcher.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* Match bug instances having one of given codes or patterns.
- *
+ *
* @author rafal at caltha.pl
*/
public class BugMatcher implements Matcher {
@@ -41,7 +41,7 @@ public class BugMatcher implements Matcher {
/**
* Constructor.
- *
+ *
* @param codes
* comma-separated list of bug codes
* @param patterns
@@ -55,14 +55,16 @@ public class BugMatcher implements Matcher {
this.categories = new StringSetMatch(categories);
}
+ @Override
public boolean match(BugInstance bugInstance) {
boolean result1 = codes.match(bugInstance.getAbbrev());
boolean result2 = patterns.match(bugInstance.getType());
boolean result3 = categories.match(bugInstance.getBugPattern().getCategory());
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Matching " + bugInstance.getAbbrev() + "/" + bugInstance.getType() + "/"
+ bugInstance.getBugPattern().getCategory() + " with " + this + ", result = " + result1 + "/" + result2 + "/"
+ result3);
+ }
return result1 || result2 || result3;
}
@@ -74,16 +76,19 @@ public class BugMatcher implements Matcher {
@Override
public boolean equals(Object o) {
- if (!(o instanceof BugMatcher))
+ if (!(o instanceof BugMatcher)) {
return false;
+ }
BugMatcher other = (BugMatcher) o;
return codes.equals(other.codes) && patterns.equals(other.patterns) && categories.equals(other.categories);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
xmlOutput.startTag("Bug");
- if (disabled)
+ if (disabled) {
xmlOutput.addAttribute("disabled", "true");
+ }
addAttribute(xmlOutput, "code", codes);
addAttribute(xmlOutput, "pattern", patterns);
@@ -93,19 +98,23 @@ public class BugMatcher implements Matcher {
public void addAttribute(XMLOutput xmlOutput, String name, StringSetMatch matches) throws IOException {
String value = matches.toString();
- if (value.length() != 0)
+ if (value.length() != 0) {
xmlOutput.addAttribute(name, value);
+ }
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder("Bug(");
- if (!codes.isEmpty())
+ if (!codes.isEmpty()) {
buf.append("code = \"").append(codes).append("\" ");
- if (!patterns.isEmpty())
+ }
+ if (!patterns.isEmpty()) {
buf.append("pattern = \"").append(patterns).append("\" ");
- if (!categories.isEmpty())
+ }
+ if (!categories.isEmpty()) {
buf.append("category = \"").append(categories).append("\" ");
+ }
buf.setLength(buf.length() - 1);
buf.append(")");
return buf.toString();
diff --git a/src/java/edu/umd/cs/findbugs/filter/ClassMatcher.java b/src/java/edu/umd/cs/findbugs/filter/ClassMatcher.java
index 274a236..28b8ce4 100644
--- a/src/java/edu/umd/cs/findbugs/filter/ClassMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/ClassMatcher.java
@@ -21,6 +21,7 @@ package edu.umd.cs.findbugs.filter;
import java.io.IOException;
+import edu.umd.cs.findbugs.BugAnnotation;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.ClassAnnotation;
import edu.umd.cs.findbugs.SystemProperties;
@@ -30,7 +31,9 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
public class ClassMatcher implements Matcher {
private static final boolean DEBUG = SystemProperties.getBoolean("filter.debug");
- private NameMatch className;
+ private final NameMatch className;
+
+ private final String role;
@Override
public String toString() {
@@ -38,24 +41,41 @@ public class ClassMatcher implements Matcher {
}
public ClassMatcher(String className) {
+ this(className, null);
+ }
+
+ public ClassMatcher(String className, String role) {
this.className = new NameMatch(className);
+ this.role = role;
}
+ @Override
public boolean match(BugInstance bugInstance) {
- ClassAnnotation primaryClassAnnotation = bugInstance.getPrimaryClass();
- String bugClassName = primaryClassAnnotation.getClassName();
+ ClassAnnotation classAnnotation = bugInstance.getPrimaryClass();
+ if (role != null && !"".equals(role)) {
+ for (BugAnnotation a : bugInstance.getAnnotations()) {
+ if (a instanceof ClassAnnotation && role.equals(a.getDescription())) {
+ classAnnotation = (ClassAnnotation) a;
+ break;
+ }
+ }
+ }
+ String bugClassName = classAnnotation.getClassName();
boolean result = className.match(bugClassName);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Matching " + bugClassName + " with " + className + ", result = " + result);
+ }
return result;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
XMLAttributeList attributes = new XMLAttributeList().addAttribute("name", className.getSpec());
- if (disabled)
+ if (disabled) {
attributes.addAttribute("disabled", "true");
+ }
+ attributes.addOptionalAttribute("role", role);
xmlOutput.openCloseTag("Class", attributes);
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/filter/CompoundMatcher.java b/src/java/edu/umd/cs/findbugs/filter/CompoundMatcher.java
index 950e7ac..6fa2bdb 100644
--- a/src/java/edu/umd/cs/findbugs/filter/CompoundMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/CompoundMatcher.java
@@ -33,17 +33,20 @@ public abstract class CompoundMatcher implements Matcher {
@Override
public int hashCode() {
int result = this.getClass().hashCode();
- for (Matcher m : children)
+ for (Matcher m : children) {
result += m.hashCode();
+ }
return result;
}
@Override
public boolean equals(Object o) {
- if (o == null)
+ if (o == null) {
return false;
- if (o.getClass() != this.getClass())
+ }
+ if (o.getClass() != this.getClass()) {
return false;
+ }
CompoundMatcher m = (CompoundMatcher) o;
return children.equals(m.children);
}
@@ -73,17 +76,20 @@ public abstract class CompoundMatcher implements Matcher {
}
public void writeChildrenXML(XMLOutput xmlOutput) throws IOException {
- for (Matcher m : children)
+ for (Matcher m : children) {
m.writeXML(xmlOutput, false);
+ }
}
@Override
public String toString() {
- if (children.isEmpty())
+ if (children.isEmpty()) {
return "";
+ }
StringBuilder buf = new StringBuilder();
- for (Matcher m : children)
+ for (Matcher m : children) {
buf.append(m).append(" ");
+ }
buf.setLength(buf.length() - 1);
return buf.toString();
}
@@ -93,4 +99,3 @@ public abstract class CompoundMatcher implements Matcher {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/filter/PriorityMatcher.java b/src/java/edu/umd/cs/findbugs/filter/ConfidenceMatcher.java
similarity index 65%
copy from src/java/edu/umd/cs/findbugs/filter/PriorityMatcher.java
copy to src/java/edu/umd/cs/findbugs/filter/ConfidenceMatcher.java
index f816407..010a4b3 100644
--- a/src/java/edu/umd/cs/findbugs/filter/PriorityMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/ConfidenceMatcher.java
@@ -25,50 +25,54 @@ import edu.umd.cs.findbugs.xml.XMLAttributeList;
import edu.umd.cs.findbugs.xml.XMLOutput;
/**
- * Matcher to select BugInstances with a particular priority.
- *
+ * Matcher to select BugInstances with a particular confidence.
+ *
* @author David Hovemeyer
*/
-public class PriorityMatcher implements Matcher {
- private int priority;
+public class ConfidenceMatcher implements Matcher {
+ private final int confidence;
@Override
public String toString() {
- return "Priority(priority=" + priority + ")";
+ return "Confidence(confidence=" + confidence + ")";
}
/**
* Constructor.
- *
- * @param priorityAsString
- * the priority, as a String
+ *
+ * @param confidenceAsString
+ * the confidence, as a String
* @throws FilterException
*/
- public PriorityMatcher(String priorityAsString) {
- this.priority = Integer.parseInt(priorityAsString);
+ public ConfidenceMatcher(String confidenceAsString) {
+ this.confidence = Integer.parseInt(confidenceAsString);
}
@Override
public int hashCode() {
- return priority;
+ return confidence;
}
@Override
public boolean equals(Object o) {
- if (!(o instanceof PriorityMatcher))
+ if (!(o instanceof ConfidenceMatcher)) {
return false;
- PriorityMatcher other = (PriorityMatcher) o;
- return priority == other.priority;
+ }
+ ConfidenceMatcher other = (ConfidenceMatcher) o;
+ return confidence == other.confidence;
}
+ @Override
public boolean match(BugInstance bugInstance) {
- return bugInstance.getPriority() == priority;
+ return bugInstance.getPriority() == confidence;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
- XMLAttributeList attributes = new XMLAttributeList().addAttribute("value", Integer.toString(priority));
- if (disabled)
+ XMLAttributeList attributes = new XMLAttributeList().addAttribute("value", Integer.toString(confidence));
+ if (disabled) {
attributes.addAttribute("disabled", "true");
- xmlOutput.openCloseTag("Priority", attributes);
+ }
+ xmlOutput.openCloseTag("Confidence", attributes);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/DesignationMatcher.java b/src/java/edu/umd/cs/findbugs/filter/DesignationMatcher.java
index 398c674..8f75fe2 100644
--- a/src/java/edu/umd/cs/findbugs/filter/DesignationMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/DesignationMatcher.java
@@ -26,15 +26,15 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* Match bug instances having one of given codes or patterns.
- *
+ *
* @author rafal at caltha.pl
*/
public class DesignationMatcher implements Matcher {
- private StringSetMatch designations;
+ private final StringSetMatch designations;
/**
* Constructor.
- *
+ *
* @param designations
* comma-separated list of designations
*/
@@ -42,6 +42,7 @@ public class DesignationMatcher implements Matcher {
this.designations = new StringSetMatch(designations);
}
+ @Override
public boolean match(BugInstance bugInstance) {
return designations.match(bugInstance.getUserDesignationKey());
}
@@ -58,24 +59,28 @@ public class DesignationMatcher implements Matcher {
@Override
public boolean equals(Object o) {
- if (!(o instanceof DesignationMatcher))
+ if (!(o instanceof DesignationMatcher)) {
return false;
+ }
DesignationMatcher other = (DesignationMatcher) o;
return designations.equals(other.designations);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
xmlOutput.startTag("Designation");
- if (disabled)
+ if (disabled) {
xmlOutput.addAttribute("disabled", "true");
+ }
addAttribute(xmlOutput, "designation", designations);
xmlOutput.stopTag(true);
}
public void addAttribute(XMLOutput xmlOutput, String name, StringSetMatch matches) throws IOException {
String value = matches.toString();
- if (value.length() != 0)
+ if (value.length() != 0) {
xmlOutput.addAttribute(name, value);
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/FieldMatcher.java b/src/java/edu/umd/cs/findbugs/filter/FieldMatcher.java
index d1577d9..0de4bd7 100644
--- a/src/java/edu/umd/cs/findbugs/filter/FieldMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/FieldMatcher.java
@@ -37,7 +37,11 @@ public class FieldMatcher extends MemberMatcher implements Matcher {
}
public FieldMatcher(String name, String type) {
- super(name, SignatureUtil.createFieldSignature(type));
+ this(name, SignatureUtil.createFieldSignature(type), null);
+ }
+
+ public FieldMatcher(String name, String type, String role) {
+ super(name, SignatureUtil.createFieldSignature(type), role);
}
@Override
@@ -45,34 +49,41 @@ public class FieldMatcher extends MemberMatcher implements Matcher {
return "Method(" + super.toString() + ")";
}
+ @Override
public boolean match(BugInstance bugInstance) {
FieldAnnotation fieldAnnotation = null;
- if (role == null || role.equals(""))
+ if (role == null || "".equals(role)) {
fieldAnnotation = bugInstance.getPrimaryField();
- else
- for (BugAnnotation a : bugInstance.getAnnotations())
+ } else {
+ for (BugAnnotation a : bugInstance.getAnnotations()) {
if (a instanceof FieldAnnotation && role.equals(a.getDescription())) {
fieldAnnotation = (FieldAnnotation) a;
break;
}
+ }
+ }
if (fieldAnnotation == null) {
return false;
}
if (!name.match(fieldAnnotation.getFieldName())) {
return false;
}
- if (signature != null && !signature.match(fieldAnnotation.getFieldSignature()))
+ if (signature != null && !signature.match(fieldAnnotation.getFieldSignature())) {
return false;
+ }
return true;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
XMLAttributeList attributes = new XMLAttributeList().addAttribute("name", name.getSpec());
- if (signature != null)
- attributes.addOptionalAttribute(
- "signature", signature.getSpec());
- if (disabled)
+ if (signature != null) {
+ attributes.addOptionalAttribute("signature", signature.getSpec());
+ }
+ attributes.addOptionalAttribute("role", role);
+ if (disabled) {
attributes.addAttribute("disabled", "true");
+ }
xmlOutput.openCloseTag("Field", attributes);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/Filter.java b/src/java/edu/umd/cs/findbugs/filter/Filter.java
index e99b070..9ef4fe9 100644
--- a/src/java/edu/umd/cs/findbugs/filter/Filter.java
+++ b/src/java/edu/umd/cs/findbugs/filter/Filter.java
@@ -19,10 +19,10 @@
package edu.umd.cs.findbugs.filter;
-import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.IdentityHashMap;
@@ -30,11 +30,6 @@ import java.util.Iterator;
import javax.annotation.WillClose;
-import org.dom4j.Attribute;
-import org.dom4j.Document;
-import org.dom4j.DocumentException;
-import org.dom4j.Element;
-import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
@@ -46,23 +41,22 @@ import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.util.Util;
import edu.umd.cs.findbugs.xml.OutputStreamXMLOutput;
import edu.umd.cs.findbugs.xml.XMLOutput;
-import edu.umd.cs.findbugs.xml.XMLUtil;
/**
* Filter to match a subset of BugInstances. The filter criteria are read from
* an XML file.
- *
+ *
* @author David Hovemeyer
*/
public class Filter extends OrMatcher {
private static final boolean DEBUG = SystemProperties.getBoolean("filter.debug");
- private IdentityHashMap<Matcher, Boolean> disabled = new IdentityHashMap<Matcher, Boolean>();
+ private final IdentityHashMap<Matcher, Boolean> disabled = new IdentityHashMap<Matcher, Boolean>();
/**
* Constructor for empty filter
- *
+ *
*/
public Filter() {
@@ -78,18 +72,23 @@ public class Filter extends OrMatcher {
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (!super.equals(obj))
+ }
+ if (!super.equals(obj)) {
return false;
- if (!(obj instanceof Filter))
+ }
+ if (!(obj instanceof Filter)) {
return false;
+ }
final Filter other = (Filter) obj;
if (disabled == null) {
- if (other.disabled != null)
+ if (other.disabled != null) {
return false;
- } else if (!disabled.equals(other.disabled))
+ }
+ } else if (!disabled.equals(other.disabled)) {
return false;
+ }
return true;
}
@@ -98,10 +97,11 @@ public class Filter extends OrMatcher {
}
public void setEnabled(Matcher m, boolean value) {
- if (value)
+ if (value) {
enable(m);
- else
+ } else {
disable(m);
+ }
}
public void disable(Matcher m) {
@@ -122,7 +122,7 @@ public class Filter extends OrMatcher {
/**
* Constructor.
- *
+ *
* @param fileName
* name of the filter file
* @throws IOException
@@ -130,8 +130,21 @@ public class Filter extends OrMatcher {
public Filter(String fileName) throws IOException {
try {
parse(fileName);
- if (false)
- System.out.println("Parsed: " + this);
+ } catch (SAXException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param stream
+ * content of the filter file
+ * @throws IOException
+ */
+ public Filter(InputStream stream) throws IOException {
+ try {
+ parse("", stream);
} catch (SAXException e) {
throw new IOException(e.getMessage());
}
@@ -143,7 +156,7 @@ public class Filter extends OrMatcher {
/**
* Add if not present, but do not enable if already present and disabled
- *
+ *
* @param child
*/
public void softAdd(Matcher child) {
@@ -173,15 +186,16 @@ public class Filter extends OrMatcher {
Iterator<Matcher> i = childIterator();
while (i.hasNext()) {
Matcher child = i.next();
- if (isEnabled(child) && child.match(bugInstance))
+ if (isEnabled(child) && child.match(bugInstance)) {
return true;
+ }
}
return false;
}
/**
* Parse and load the given filter file.
- *
+ *
* @param fileName
* name of the filter file
* @throws IOException
@@ -189,169 +203,30 @@ public class Filter extends OrMatcher {
* @throws FilterException
*/
private void parse(String fileName) throws IOException, SAXException {
-
- if (true) {
- File file = new File(fileName);
- SAXBugCollectionHandler handler = new SAXBugCollectionHandler(this, file);
- XMLReader xr = XMLReaderFactory.createXMLReader();
- xr.setContentHandler(handler);
- xr.setErrorHandler(handler);
- FileInputStream fileInputStream = new FileInputStream(file);
- try {
- Reader reader = Util.getReader(fileInputStream);
- xr.parse(new InputSource(reader));
- } finally {
- Util.closeSilently(fileInputStream);
- }
- return;
-
- }
- Document filterDoc = null;
-
- FileInputStream fileInputStream = new FileInputStream(fileName);
-
- try {
- SAXReader reader = new SAXReader();
- filterDoc = reader.read(new BufferedInputStream(fileInputStream));
- } catch (DocumentException e) {
- throw new FilterException("Couldn't parse filter file " + fileName, e);
- }
-
- int count = 1;
- // Iterate over Match elements
- for (Object matchObj : XMLUtil.selectNodes(filterDoc, "/FindBugsFilter/Match")) {
- Element matchNode = (Element) matchObj;
- AndMatcher matchMatcher = new AndMatcher();
-
- // Each match node may have either "class" or "classregex"
- // attributes
- Matcher classMatcher = null;
- String classAttr = matchNode.valueOf("@class");
- if (!classAttr.equals("")) {
- classMatcher = new ClassMatcher(classAttr);
- } else {
- String classRegex = matchNode.valueOf("@classregex");
- if (!classRegex.equals(""))
- classMatcher = new ClassMatcher("~" + classRegex);
- }
- if (classMatcher != null)
- matchMatcher.addChild(classMatcher);
-
- if (DEBUG)
- System.out.println("Match node");
-
- // Iterate over child elements of Match node.
- Iterator<?> j = matchNode.elementIterator();
- while (j.hasNext()) {
- Element child = (Element) j.next();
- Matcher matcher = getMatcher(child);
- matchMatcher.addChild(matcher);
- }
- if (matchMatcher.numberChildren() == 0)
- throw new FilterException("Match element #" + count + " (starting at 1) is invalid in filter file " + fileName);
- // Add the Match matcher to the overall Filter
- this.addChild(matchMatcher);
- count++;
- }
- if (this.numberChildren() == 0)
- throw new FilterException("Could not find any /FindBugsFilter/Match nodes in filter file " + fileName);
-
+ FileInputStream fileInputStream = new FileInputStream(new File(fileName));
+ parse(fileName, fileInputStream);
}
/**
- * Get a Matcher for given Element.
- *
- * @param element
- * the Element
- * @return a Matcher representing that element
+ * Parse and load the given filter file.
+ *
+ * @param fileName
+ * name of the filter file
+ * @throws IOException
+ * @throws SAXException
* @throws FilterException
*/
- private static Matcher getMatcher(Element element) throws FilterException {
- // These will be either BugCode, Priority, Class, Method, Field, or Or
- // elements.
- String name = element.getName();
- if (name.equals("BugCode")) {
- return new BugMatcher(element.valueOf("@name"), "", "");
- } else if (name.equals("Local")) {
- return new LocalMatcher(element.valueOf("@name"));
- } else if (name.equals("BugPattern")) {
- return new BugMatcher("", element.valueOf("@name"), "");
- } else if (name.equals("Bug")) {
- return new BugMatcher(element.valueOf("@code"), element.valueOf("@pattern"), element.valueOf("@category"));
- } else if (name.equals("Priority") || name.equals("Confidence")) {
- return new PriorityMatcher(element.valueOf("@value"));
- } else if (name.equals("Rank")) {
- return new RankMatcher(element.valueOf("@value"));
- } else if (name.equals("Class")) {
- Attribute nameAttr = element.attribute("name");
-
- if (nameAttr == null)
- throw new FilterException("Missing name attribute in Class element");
-
- return new ClassMatcher(nameAttr.getValue());
- } else if (name.equals("Package")) {
- Attribute nameAttr = element.attribute("name");
-
- if (nameAttr == null)
- throw new FilterException("Missing name attribute in Package element");
-
- String pName = nameAttr.getValue();
- pName = pName.startsWith("~") ? pName : "~" + pName.replace(".", "\\.");
- return new ClassMatcher(pName + "\\.[^.]+");
- } else if (name.equals("Method")) {
- Attribute nameAttr = element.attribute("name");
- String nameValue;
- Attribute paramsAttr = element.attribute("params");
- Attribute returnsAttr = element.attribute("returns");
- Attribute roleAttr = element.attribute("role");
-
- if (nameAttr == null)
- if (paramsAttr == null || returnsAttr == null)
- throw new FilterException("Method element must have eiter name or params and returnss attributes");
- else
- nameValue = "~.*"; // any name
- else
- nameValue = nameAttr.getValue();
-
- if ((paramsAttr != null || returnsAttr != null) && (paramsAttr == null || returnsAttr == null))
- throw new FilterException("Method element must have both params and returns attributes if either is used");
-
- if (paramsAttr == null)
- if (roleAttr == null)
- return new MethodMatcher(nameValue);
- else
- return new MethodMatcher(nameValue, roleAttr.getValue());
- else if (roleAttr == null)
- return new MethodMatcher(nameValue, paramsAttr.getValue(), returnsAttr.getValue());
- else
- return new MethodMatcher(nameValue, paramsAttr.getValue(), returnsAttr.getValue(), roleAttr.getValue());
-
- } else if (name.equals("Field")) {
- Attribute nameAttr = element.attribute("name");
- String nameValue;
- Attribute typeAttr = element.attribute("type");
-
- if (nameAttr == null)
- if (typeAttr == null)
- throw new FilterException("Field element must have either name or type attribute");
- else
- nameValue = "~.*"; // any name
- else
- nameValue = nameAttr.getValue();
-
- if (typeAttr == null)
- return new FieldMatcher(nameValue);
- else
- return new FieldMatcher(nameValue, typeAttr.getValue());
- } else if (name.equals("Or")) {
- OrMatcher orMatcher = new OrMatcher();
- Iterator<?> i = element.elementIterator();
- while (i.hasNext()) {
- orMatcher.addChild(getMatcher((Element) i.next()));
- }
- return orMatcher;
- } else
- throw new FilterException("Unknown element: " + name);
+ private void parse(String fileName, @WillClose InputStream stream) throws IOException, SAXException {
+ try {
+ SAXBugCollectionHandler handler = new SAXBugCollectionHandler(this, new File(fileName));
+ XMLReader xr = XMLReaderFactory.createXMLReader();
+ xr.setContentHandler(handler);
+ xr.setErrorHandler(handler);
+ Reader reader = Util.getReader(stream);
+ xr.parse(new InputSource(reader));
+ } finally {
+ Util.closeSilently(stream);
+ }
}
public static void main(String[] argv) {
@@ -412,4 +287,3 @@ public class Filter extends OrMatcher {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/filter/FilterException.java b/src/java/edu/umd/cs/findbugs/filter/FilterException.java
index 3943049..2f694a2 100644
--- a/src/java/edu/umd/cs/findbugs/filter/FilterException.java
+++ b/src/java/edu/umd/cs/findbugs/filter/FilterException.java
@@ -31,4 +31,3 @@ public class FilterException extends RuntimeException {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/filter/FirstVersionMatcher.java b/src/java/edu/umd/cs/findbugs/filter/FirstVersionMatcher.java
index 35813d9..53fc136 100644
--- a/src/java/edu/umd/cs/findbugs/filter/FirstVersionMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/FirstVersionMatcher.java
@@ -45,15 +45,18 @@ public class FirstVersionMatcher extends VersionMatcher implements Matcher {
return "FirstVersion(version" + relOp + version + ")";
}
+ @Override
public boolean match(BugInstance bugInstance) {
return relOp.check(bugInstance.getFirstVersion(), version);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
XMLAttributeList attributes = new XMLAttributeList().addAttribute("value", Long.toString(version)).addAttribute("relOp",
relOp.getName());
- if (disabled)
+ if (disabled) {
attributes.addAttribute("disabled", "true");
+ }
xmlOutput.openCloseTag("FirstVersion", attributes);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/LastVersionMatcher.java b/src/java/edu/umd/cs/findbugs/filter/LastVersionMatcher.java
index d52a510..cc016dc 100644
--- a/src/java/edu/umd/cs/findbugs/filter/LastVersionMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/LastVersionMatcher.java
@@ -43,24 +43,28 @@ public class LastVersionMatcher extends VersionMatcher implements Matcher {
super(version, relOp);
}
+ @Override
public boolean match(BugInstance bugInstance) {
return relOp.check(bugInstance.getLastVersion(), version);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
XMLAttributeList attributes = new XMLAttributeList().addAttribute("value", Long.toString(version)).addAttribute("relOp",
relOp.getName());
- if (disabled)
+ if (disabled) {
attributes.addAttribute("disabled", "true");
+ }
xmlOutput.openCloseTag("LastVersion", attributes);
}
@Override
public String toString() {
- if (version == -1 && relOp == RelationalOp.EQ)
+ if (version == -1 && relOp == RelationalOp.EQ) {
return "ActiveBugs";
- else if (version == -1 && relOp == RelationalOp.NEQ)
+ } else if (version == -1 && relOp == RelationalOp.NEQ) {
return "DeadBugs";
+ }
return "LastVersion(version " + relOp + version + ")";
}
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/LocalMatcher.java b/src/java/edu/umd/cs/findbugs/filter/LocalMatcher.java
index 175c28f..dac6e6b 100644
--- a/src/java/edu/umd/cs/findbugs/filter/LocalMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/LocalMatcher.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.xml.XMLAttributeList;
import edu.umd.cs.findbugs.xml.XMLOutput;
public class LocalMatcher implements Matcher {
- private NameMatch name;
+ private final NameMatch name;
public LocalMatcher(String name) {
this.name = new NameMatch(name);
@@ -42,6 +42,7 @@ public class LocalMatcher implements Matcher {
return "Local(name=" + name + ")";
}
+ @Override
public boolean match(BugInstance bugInstance) {
LocalVariableAnnotation localAnnotation = bugInstance.getPrimaryLocalVariableAnnotation();
if (localAnnotation == null) {
@@ -53,10 +54,12 @@ public class LocalMatcher implements Matcher {
return true;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
XMLAttributeList attributes = new XMLAttributeList().addAttribute("name", name.getSpec());
- if (disabled)
+ if (disabled) {
attributes.addAttribute("disabled", "true");
+ }
xmlOutput.openCloseTag("Local", attributes);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/Matcher.java b/src/java/edu/umd/cs/findbugs/filter/Matcher.java
index 02a1074..43a2fdd 100644
--- a/src/java/edu/umd/cs/findbugs/filter/Matcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/Matcher.java
@@ -26,14 +26,14 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* Match BugInstances for some feature.
- *
+ *
* @author David Hovemeyer
*/
public interface Matcher {
/**
* Determine whether or not the given BugInstance has the feature this
* Matcher tests for.
- *
+ *
* @param bugInstance
* the BugInstance
* @return true if the BugInstance matches, false if not
@@ -43,4 +43,3 @@ public interface Matcher {
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException;
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/filter/MemberMatcher.java b/src/java/edu/umd/cs/findbugs/filter/MemberMatcher.java
index 5f49a2d..f1dd9c8 100644
--- a/src/java/edu/umd/cs/findbugs/filter/MemberMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/MemberMatcher.java
@@ -47,10 +47,12 @@ public class MemberMatcher {
public MemberMatcher(String name, String signature, String role) {
if (name == null) {
- if (signature == null)
+ if (signature == null) {
throw new FilterException(this.getClass().getName() + " must have eiter name or signature attributes");
- else
+ }
+ else {
name = "~.*"; // any name
+ }
}
this.name = new NameMatch(name);
@@ -68,8 +70,9 @@ public class MemberMatcher {
buf.append("\"");
}
if (signature != null) {
- if (buf.length() > 0)
+ if (buf.length() > 0) {
buf.append(" ");
+ }
buf.append("signature=\"");
buf.append(signature);
buf.append("\"");
@@ -84,8 +87,9 @@ public class MemberMatcher {
@Override
public boolean equals(Object o) {
- if (o == null || this.getClass() != o.getClass())
+ if (o == null || this.getClass() != o.getClass()) {
return false;
+ }
MemberMatcher other = (MemberMatcher) o;
return name.equals(other.name) && Util.nullSafeEquals(signature, other.signature);
diff --git a/src/java/edu/umd/cs/findbugs/filter/MethodMatcher.java b/src/java/edu/umd/cs/findbugs/filter/MethodMatcher.java
index 50c6f65..5dadcd1 100644
--- a/src/java/edu/umd/cs/findbugs/filter/MethodMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/MethodMatcher.java
@@ -24,6 +24,7 @@ import java.io.IOException;
import edu.umd.cs.findbugs.BugAnnotation;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.MethodAnnotation;
+import edu.umd.cs.findbugs.ba.SignatureConverter;
import edu.umd.cs.findbugs.xml.XMLAttributeList;
import edu.umd.cs.findbugs.xml.XMLOutput;
@@ -45,23 +46,29 @@ public class MethodMatcher extends MemberMatcher implements Matcher {
super(name, SignatureUtil.createMethodSignature(params, returns), role);
}
+ @Override
public boolean match(BugInstance bugInstance) {
MethodAnnotation methodAnnotation = null;
- if (role == null || role.equals(""))
+ if (role == null || "".equals(role)) {
methodAnnotation = bugInstance.getPrimaryMethod();
- else
- for (BugAnnotation a : bugInstance.getAnnotations())
+ } else {
+ for (BugAnnotation a : bugInstance.getAnnotations()) {
if (a instanceof MethodAnnotation && role.equals(a.getDescription())) {
methodAnnotation = (MethodAnnotation) a;
break;
}
- if (methodAnnotation == null)
+ }
+ }
+ if (methodAnnotation == null) {
return false;
- if (!name.match(methodAnnotation.getMethodName()))
+ }
+ if (!name.match(methodAnnotation.getMethodName())) {
return false;
- if (signature != null && !signature.match(methodAnnotation.getMethodSignature()))
+ }
+ if (signature != null && !signature.match(methodAnnotation.getMethodSignature())) {
return false;
+ }
return true;
}
@@ -70,15 +77,31 @@ public class MethodMatcher extends MemberMatcher implements Matcher {
return "Method(" + super.toString() + ")";
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
XMLAttributeList attributes = new XMLAttributeList().addAttribute("name", name.getSpec());
- if (signature != null)
- attributes
- .addOptionalAttribute("signature", signature.getSpec()).addOptionalAttribute("role", role);
- if (disabled)
+ if (signature != null && signature.getSpec() != null) {
+ StringBuilder paramsBuilder = new StringBuilder();
+ SignatureConverter converter = new SignatureConverter(signature.getSpec());
+ converter.skip();
+ while (converter.getFirst() != ')') {
+ if (paramsBuilder.length() > 1) {
+ paramsBuilder.append(", ");
+ }
+ paramsBuilder.append(converter.parseNext());
+ }
+ converter.skip();
+
+ String params = paramsBuilder.toString();
+ String returns = converter.parseNext();
+ attributes.addAttribute("params", params);
+ attributes.addAttribute("returns", returns);
+ }
+ attributes.addOptionalAttribute("role", role);
+ if (disabled) {
attributes.addAttribute("disabled", "true");
+ }
xmlOutput.openCloseTag("Method", attributes);
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/filter/NameMatch.java b/src/java/edu/umd/cs/findbugs/filter/NameMatch.java
index 7ace823..e57ab21 100644
--- a/src/java/edu/umd/cs/findbugs/filter/NameMatch.java
+++ b/src/java/edu/umd/cs/findbugs/filter/NameMatch.java
@@ -27,24 +27,25 @@ import edu.umd.cs.findbugs.util.Util;
/**
* Matches a String value against a predefined specification.
- *
+ *
* Matching can be done in three modes depending on ctor matchSpec argument.
- *
+ *
* If matchSpec is null, match will succeed for any value (including empty
* String and null)
- *
+ *
* If matchSpec starts with ~ character it will be treated as
* java.util.regex.Pattern, with the ~ character omited. The pattern will be
* matched against whole value (ie Matcher.match(), not Matcher.find())
- *
+ *
* If matchSpec is a non-null String with any other initial charcter, exact
* matching using String.equals(String) will be performed.
- *
+ *
* @author rafal at caltha.pl
*/
public class NameMatch {
private @CheckForNull
+ final
String spec;
private @CheckForNull
@@ -55,29 +56,34 @@ public class NameMatch {
@Override
public int hashCode() {
- if (spec == null)
+ if (spec == null) {
return 0;
+ }
return spec.hashCode();
}
public boolean isUniversal() {
- if (spec == null)
+ if (spec == null) {
return true;
- return spec.equals("~.*");
+ }
+ return "~.*".equals(spec);
}
@Override
public boolean equals(Object o) {
- if (!(o instanceof NameMatch))
+ if (!(o instanceof NameMatch)) {
return false;
+ }
return Util.nullSafeEquals(spec, ((NameMatch) o).spec);
}
public String getValue() {
- if (exact != null)
+ if (exact != null) {
return exact;
- if (pattern != null)
+ }
+ if (pattern != null) {
return pattern.toString();
+ }
return "~.*";
}
@@ -93,19 +99,23 @@ public class NameMatch {
}
public boolean match(String value) {
- if (exact != null)
+ if (exact != null) {
return exact.equals(value);
- if (pattern != null)
+ }
+ if (pattern != null) {
return pattern.matcher(value).matches();
+ }
return true;
}
@Override
public String toString() {
- if (exact != null)
+ if (exact != null) {
return "exact(" + exact + ")";
- if (pattern != null)
+ }
+ if (pattern != null) {
return "regex(" + pattern.toString() + ")";
+ }
return "any()";
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/NotMatcher.java b/src/java/edu/umd/cs/findbugs/filter/NotMatcher.java
index da837bd..baa75a1 100644
--- a/src/java/edu/umd/cs/findbugs/filter/NotMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/NotMatcher.java
@@ -29,6 +29,7 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
public class NotMatcher extends CompoundMatcher {
+ @Override
public boolean match(BugInstance bugInstance) {
if(!childIterator().hasNext() ) {
return false;
@@ -38,10 +39,13 @@ public class NotMatcher extends CompoundMatcher {
return ! invertedMatcher.match(bugInstance);
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
if(childIterator().hasNext()) {
xmlOutput.startTag("Not");
- if (disabled) xmlOutput.addAttribute("disabled","true");
+ if (disabled) {
+ xmlOutput.addAttribute("disabled","true");
+ }
Matcher invertedMatcher = childIterator().next();
xmlOutput.stopTag(false);
@@ -50,6 +54,7 @@ public class NotMatcher extends CompoundMatcher {
xmlOutput.closeTag("Not");
}
}
+
@Override
public String toString() {
Matcher invertedMatcher = childIterator().hasNext() ? childIterator().next() : null;
@@ -62,11 +67,6 @@ public class NotMatcher extends CompoundMatcher {
return 1;
}
- @Override
- public void addChild(Matcher child) {
- super.addChild(child);
- }
-
public Matcher originalMatcher() {
Iterator<Matcher> childMatchers = childIterator();
if (childMatchers.hasNext()) {
diff --git a/src/java/edu/umd/cs/findbugs/filter/OrMatcher.java b/src/java/edu/umd/cs/findbugs/filter/OrMatcher.java
index 1166a3f..2998fde 100644
--- a/src/java/edu/umd/cs/findbugs/filter/OrMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/OrMatcher.java
@@ -27,24 +27,28 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
public class OrMatcher extends CompoundMatcher {
+ @Override
public boolean match(BugInstance bugInstance) {
Iterator<Matcher> i = childIterator();
while (i.hasNext()) {
Matcher child = i.next();
- if (child.match(bugInstance))
+ if (child.match(bugInstance)) {
return true;
+ }
}
return false;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
if (numberChildren() == 1) {
childIterator().next().writeXML(xmlOutput, false);
return;
}
xmlOutput.startTag("Or");
- if (disabled)
+ if (disabled) {
xmlOutput.addAttribute("disabled", "true");
+ }
xmlOutput.stopTag(false);
writeChildrenXML(xmlOutput);
xmlOutput.closeTag("Or");
@@ -52,11 +56,11 @@ public class OrMatcher extends CompoundMatcher {
@Override
public String toString() {
- if (numberChildren() == 1)
+ if (numberChildren() == 1) {
return super.toString();
+ }
return "Or(" + super.toString() + ")";
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/filter/PriorityMatcher.java b/src/java/edu/umd/cs/findbugs/filter/PriorityMatcher.java
index f816407..fd79b8d 100644
--- a/src/java/edu/umd/cs/findbugs/filter/PriorityMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/PriorityMatcher.java
@@ -26,11 +26,11 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* Matcher to select BugInstances with a particular priority.
- *
+ *
* @author David Hovemeyer
*/
public class PriorityMatcher implements Matcher {
- private int priority;
+ private final int priority;
@Override
public String toString() {
@@ -39,7 +39,7 @@ public class PriorityMatcher implements Matcher {
/**
* Constructor.
- *
+ *
* @param priorityAsString
* the priority, as a String
* @throws FilterException
@@ -55,20 +55,24 @@ public class PriorityMatcher implements Matcher {
@Override
public boolean equals(Object o) {
- if (!(o instanceof PriorityMatcher))
+ if (!(o instanceof PriorityMatcher)) {
return false;
+ }
PriorityMatcher other = (PriorityMatcher) o;
return priority == other.priority;
}
+ @Override
public boolean match(BugInstance bugInstance) {
return bugInstance.getPriority() == priority;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
XMLAttributeList attributes = new XMLAttributeList().addAttribute("value", Integer.toString(priority));
- if (disabled)
+ if (disabled) {
attributes.addAttribute("disabled", "true");
+ }
xmlOutput.openCloseTag("Priority", attributes);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/RankMatcher.java b/src/java/edu/umd/cs/findbugs/filter/RankMatcher.java
index 394add5..cca3cab 100644
--- a/src/java/edu/umd/cs/findbugs/filter/RankMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/RankMatcher.java
@@ -27,11 +27,11 @@ import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* Matcher to select BugInstances with a particular rank or higher.
- *
+ *
* @author William Pugh
*/
public class RankMatcher implements Matcher {
- private int rank;
+ private final int rank;
@Override
public String toString() {
@@ -40,7 +40,7 @@ public class RankMatcher implements Matcher {
/**
* Constructor.
- *
+ *
* @param rankAsString
* the rank, as a String
* @throws NumberFormatException
@@ -57,20 +57,24 @@ public class RankMatcher implements Matcher {
@Override
public boolean equals(Object o) {
- if (!(o instanceof RankMatcher))
+ if (!(o instanceof RankMatcher)) {
return false;
+ }
RankMatcher other = (RankMatcher) o;
return rank == other.rank;
}
+ @Override
public boolean match(BugInstance bugInstance) {
return BugRanker.findRank(bugInstance) >= rank;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
XMLAttributeList attributes = new XMLAttributeList().addAttribute("value", Integer.toString(rank));
- if (disabled)
+ if (disabled) {
attributes.addAttribute("disabled", "true");
+ }
xmlOutput.openCloseTag("Rank", attributes);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/RelationalOp.java b/src/java/edu/umd/cs/findbugs/filter/RelationalOp.java
index c4b6e27..644be98 100644
--- a/src/java/edu/umd/cs/findbugs/filter/RelationalOp.java
+++ b/src/java/edu/umd/cs/findbugs/filter/RelationalOp.java
@@ -41,8 +41,9 @@ public abstract class RelationalOp {
public static RelationalOp byName(String s) {
RelationalOp relationalOp = map.get(s);
- if (relationalOp == null)
+ if (relationalOp == null) {
throw new IllegalArgumentException("Could not find relOp named " + s + " in " + map.keySet());
+ }
return relationalOp;
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/SignatureUtil.java b/src/java/edu/umd/cs/findbugs/filter/SignatureUtil.java
index 315afba..eeeb920 100644
--- a/src/java/edu/umd/cs/findbugs/filter/SignatureUtil.java
+++ b/src/java/edu/umd/cs/findbugs/filter/SignatureUtil.java
@@ -28,40 +28,42 @@ import java.util.regex.Pattern;
public class SignatureUtil {
public static String createMethodSignature(String params, String returns) {
- if (params == null && returns == null)
+ if (params == null && returns == null) {
return null;
-
+ }
+
String pString, rString;
- if (params == null)
+ if (params == null) {
pString = ".*";
- else {
- StringBuilder buf = new StringBuilder();
+ } else {
+ StringBuilder buf = new StringBuilder();
- StringTokenizer tok = new StringTokenizer(params, " \t\n\r\f,");
- while (tok.hasMoreTokens()) {
- String param = typeToSignature(tok.nextToken());
- buf.append(param);
- }
- pString = buf.toString();
+ StringTokenizer tok = new StringTokenizer(params, " \t\n\r\f,");
+ while (tok.hasMoreTokens()) {
+ String param = typeToSignature(tok.nextToken());
+ buf.append(param);
+ }
+ pString = buf.toString();
}
- if (returns == null)
+ if (returns == null) {
rString = ".*";
- else
+ } else {
rString = typeToSignature(returns);
+ }
if (params == null || returns == null) {
String result = "~\\(" + pString + "\\)" + rString;
assert Pattern.compile(result.substring(1)) != null;
return result;
- }
-
- else
+ } else {
return "(" + pString + ")" + rString;
-
+ }
+
}
public static String createFieldSignature(String type) {
- if (type == null)
+ if (type == null) {
return null;
+ }
return typeToSignature(type);
}
@@ -74,25 +76,26 @@ public class SignatureUtil {
}
private static String scalarTypeToSiganture(String type) {
- if (type.equals("boolean"))
+ if ("boolean".equals(type)) {
return "Z";
- else if (type.equals("byte"))
+ } else if ("byte".equals(type)) {
return "B";
- else if (type.equals("char"))
+ } else if ("char".equals(type)) {
return "C";
- else if (type.equals("short"))
+ } else if ("short".equals(type)) {
return "S";
- else if (type.equals("int"))
+ } else if ("int".equals(type)) {
return "I";
- else if (type.equals("long"))
+ } else if ("long".equals(type)) {
return "J";
- else if (type.equals("float"))
+ } else if ("float".equals(type)) {
return "F";
- else if (type.equals("double"))
+ } else if ("double".equals(type)) {
return "D";
- else if (type.equals("void"))
+ } else if ("void".equals(type)) {
return "V";
- else
+ } else {
return "L" + type.replace('.', '/') + ";";
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/ClassMatcher.java b/src/java/edu/umd/cs/findbugs/filter/SourceMatcher.java
similarity index 65%
copy from src/java/edu/umd/cs/findbugs/filter/ClassMatcher.java
copy to src/java/edu/umd/cs/findbugs/filter/SourceMatcher.java
index 274a236..8ce4f6a 100644
--- a/src/java/edu/umd/cs/findbugs/filter/ClassMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/SourceMatcher.java
@@ -2,6 +2,8 @@
* FindBugs - Find bugs in Java programs
* Copyright (C) 2003-2005, University of Maryland
*
+ * Author: Andrey Loskutov
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -27,35 +29,44 @@ import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.xml.XMLAttributeList;
import edu.umd.cs.findbugs.xml.XMLOutput;
-public class ClassMatcher implements Matcher {
+public class SourceMatcher implements Matcher {
private static final boolean DEBUG = SystemProperties.getBoolean("filter.debug");
- private NameMatch className;
+ private final NameMatch fileName;
@Override
public String toString() {
- return "Class(class=\"" + className.getValue() + "\")";
+ return "Source(file=\"" + fileName.getValue() + "\")";
}
- public ClassMatcher(String className) {
- this.className = new NameMatch(className);
+ public SourceMatcher(String fileName) {
+ this.fileName = new NameMatch(fileName);
}
+ @Override
public boolean match(BugInstance bugInstance) {
ClassAnnotation primaryClassAnnotation = bugInstance.getPrimaryClass();
- String bugClassName = primaryClassAnnotation.getClassName();
- boolean result = className.match(bugClassName);
- if (DEBUG)
- System.out.println("Matching " + bugClassName + " with " + className + ", result = " + result);
+ if(primaryClassAnnotation == null){
+ return false;
+ }
+ String bugFileName = primaryClassAnnotation.getSourceFileName();
+ if(bugFileName == null || bugFileName.isEmpty()){
+ return false;
+ }
+ boolean result = fileName.match(bugFileName);
+ if (DEBUG) {
+ System.out.println("Matching " + bugFileName + " with " + fileName + ", result = " + result);
+ }
return result;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
- XMLAttributeList attributes = new XMLAttributeList().addAttribute("name", className.getSpec());
- if (disabled)
+ XMLAttributeList attributes = new XMLAttributeList().addAttribute("name", fileName.getSpec());
+ if (disabled) {
attributes.addAttribute("disabled", "true");
- xmlOutput.openCloseTag("Class", attributes);
+ }
+ xmlOutput.openCloseTag("Source", attributes);
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/filter/StringSetMatch.java b/src/java/edu/umd/cs/findbugs/filter/StringSetMatch.java
index 46af3fd..dd36ead 100644
--- a/src/java/edu/umd/cs/findbugs/filter/StringSetMatch.java
+++ b/src/java/edu/umd/cs/findbugs/filter/StringSetMatch.java
@@ -25,14 +25,14 @@ import java.util.StringTokenizer;
/**
* Matches a string against a set of predefined values.
- *
+ *
* Value set is defined using a String containing a comma separated value list.
* Heading an trailing whitespace on the values is ignored in matching.
- *
+ *
* @author rak
*/
public class StringSetMatch {
- private Set<String> strings = new HashSet<String>();
+ private final Set<String> strings = new HashSet<String>();
@Override
public int hashCode() {
@@ -41,14 +41,15 @@ public class StringSetMatch {
@Override
public boolean equals(Object o) {
- if (!(o instanceof StringSetMatch))
+ if (!(o instanceof StringSetMatch)) {
return false;
+ }
return strings.equals(((StringSetMatch) o).strings);
}
/**
* Constructor.
- *
+ *
* @param strings
* comma-separated list of Strings
*/
@@ -67,7 +68,7 @@ public class StringSetMatch {
/**
* Returns true if the given string is contained in the value set.
- *
+ *
* @param string
* @return true if the given string is contained in the value set
*/
@@ -77,11 +78,13 @@ public class StringSetMatch {
@Override
public String toString() {
- if (strings.isEmpty())
+ if (strings.isEmpty()) {
return "";
+ }
StringBuilder result = new StringBuilder();
- for (String s : strings)
+ for (String s : strings) {
result.append(s).append(",");
+ }
return result.substring(0, result.length() - 1);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/filter/MethodMatcher.java b/src/java/edu/umd/cs/findbugs/filter/TypeMatcher.java
similarity index 53%
copy from src/java/edu/umd/cs/findbugs/filter/MethodMatcher.java
copy to src/java/edu/umd/cs/findbugs/filter/TypeMatcher.java
index 50c6f65..2fc781b 100644
--- a/src/java/edu/umd/cs/findbugs/filter/MethodMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/TypeMatcher.java
@@ -2,6 +2,8 @@
* FindBugs - Find bugs in Java programs
* Copyright (C) 2003-2005, University of Maryland
*
+ * Author: Andrey Loskutov
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -23,62 +25,62 @@ import java.io.IOException;
import edu.umd.cs.findbugs.BugAnnotation;
import edu.umd.cs.findbugs.BugInstance;
-import edu.umd.cs.findbugs.MethodAnnotation;
+import edu.umd.cs.findbugs.TypeAnnotation;
import edu.umd.cs.findbugs.xml.XMLAttributeList;
import edu.umd.cs.findbugs.xml.XMLOutput;
-public class MethodMatcher extends MemberMatcher implements Matcher {
+public class TypeMatcher implements Matcher {
- public MethodMatcher(String name) {
- super(name);
- }
+ private final NameMatch descriptor;
- public MethodMatcher(String name, String role) {
- super(name, null, role);
- }
+ private final String role;
- public MethodMatcher(String name, String params, String returns) {
- super(name, SignatureUtil.createMethodSignature(params, returns));
+ private final String typeParameters;
+
+ @Override
+ public String toString() {
+ return "Type(descriptor=\"" + descriptor.getValue() + "\")";
}
- public MethodMatcher(String name, String params, String returns, String role) {
- super(name, SignatureUtil.createMethodSignature(params, returns), role);
+ public TypeMatcher(String descriptor, String role, String typeParameters) {
+ this.descriptor = new NameMatch(descriptor);
+ this.role = role;
+ this.typeParameters = typeParameters;
}
+ @Override
public boolean match(BugInstance bugInstance) {
-
- MethodAnnotation methodAnnotation = null;
- if (role == null || role.equals(""))
- methodAnnotation = bugInstance.getPrimaryMethod();
- else
- for (BugAnnotation a : bugInstance.getAnnotations())
- if (a instanceof MethodAnnotation && role.equals(a.getDescription())) {
- methodAnnotation = (MethodAnnotation) a;
+ TypeAnnotation typeAnnotation = bugInstance.getPrimaryType();
+ if (role != null && !"".equals(role)) {
+ for (BugAnnotation a : bugInstance.getAnnotations()) {
+ if (a instanceof TypeAnnotation && role.equals(a.getDescription())) {
+ typeAnnotation = (TypeAnnotation) a;
break;
}
- if (methodAnnotation == null)
+ }
+ }
+ if(typeAnnotation == null){
return false;
- if (!name.match(methodAnnotation.getMethodName()))
+ }
+ String typeDesctiptor = typeAnnotation.getTypeDescriptor();
+ if(!descriptor.match(typeDesctiptor)){
return false;
- if (signature != null && !signature.match(methodAnnotation.getMethodSignature()))
+ }
+ if (typeParameters != null && !typeParameters.equals(typeAnnotation.getTypeParameters())) {
return false;
+ }
return true;
}
@Override
- public String toString() {
- return "Method(" + super.toString() + ")";
- }
-
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
- XMLAttributeList attributes = new XMLAttributeList().addAttribute("name", name.getSpec());
- if (signature != null)
- attributes
- .addOptionalAttribute("signature", signature.getSpec()).addOptionalAttribute("role", role);
- if (disabled)
+ XMLAttributeList attributes = new XMLAttributeList().addAttribute("descriptor", descriptor.getSpec());
+ if (disabled) {
attributes.addAttribute("disabled", "true");
- xmlOutput.openCloseTag("Method", attributes);
+ }
+ attributes.addOptionalAttribute("typeParameters", typeParameters);
+ attributes.addOptionalAttribute("role", role);
+ xmlOutput.openCloseTag("Type", attributes);
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/filter/VersionMatcher.java b/src/java/edu/umd/cs/findbugs/filter/VersionMatcher.java
index de0e91d..90dbd14 100644
--- a/src/java/edu/umd/cs/findbugs/filter/VersionMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/filter/VersionMatcher.java
@@ -37,15 +37,17 @@ public class VersionMatcher {
@Override
public boolean equals(Object o) {
- if (o == null || this.getClass() != o.getClass())
+ if (o == null || this.getClass() != o.getClass()) {
return false;
+ }
VersionMatcher m = (VersionMatcher) o;
return version == m.version && relOp.equals(m.relOp);
}
public VersionMatcher(long version, @Nonnull RelationalOp relOp) {
- if (relOp == null)
+ if (relOp == null) {
throw new NullPointerException("relOp must be nonnull");
+ }
this.version = version;
this.relOp = relOp;
}
diff --git a/src/java/edu/umd/cs/findbugs/graph/AbstractDepthFirstSearch.java b/src/java/edu/umd/cs/findbugs/graph/AbstractDepthFirstSearch.java
index 3441468..e1621a2 100644
--- a/src/java/edu/umd/cs/findbugs/graph/AbstractDepthFirstSearch.java
+++ b/src/java/edu/umd/cs/findbugs/graph/AbstractDepthFirstSearch.java
@@ -35,34 +35,34 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
* <li>produces a topological sort of the vertices,
* <em>if and only if the graph is acyclic</em>
* </ul>
- *
+ *
* <p>
* Concrete subclasses implement forward and reverse versions of depth first
* search.
- *
+ *
* @author David Hovemeyer
* @see Graph
* @see DepthFirstSearch
* @see ReverseDepthFirstSearch
*/
public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType, VertexType>, EdgeType extends GraphEdge<EdgeType, VertexType>, VertexType extends GraphVertex<VertexType>>
- implements DFSEdgeTypes {
+implements DFSEdgeTypes {
public final static boolean DEBUG = false;
- private GraphType graph;
+ private final GraphType graph;
- private int[] colorList;
+ private final int[] colorList;
- private int[] discoveryTimeList;
+ private final int[] discoveryTimeList;
- private int[] finishTimeList;
+ private final int[] finishTimeList;
- private int[] dfsEdgeTypeList;
+ private final int[] dfsEdgeTypeList;
private int timestamp;
- private LinkedList<VertexType> topologicalSortList;
+ private final LinkedList<VertexType> topologicalSortList;
private VertexChooser<VertexType> vertexChooser;
@@ -86,7 +86,7 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
/**
* Constructor.
- *
+ *
* @param graph
* the graph to be searched
* @throws IllegalArgumentException
@@ -131,15 +131,16 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
* Choose the next search tree root. By default, this method just scans for
* a WHITE vertex. Subclasses may override this method in order to choose
* which vertices are used as search tree roots.
- *
+ *
* @return the next search tree root
*/
protected VertexType getNextSearchTreeRoot() {
// FIXME: slow linear search, should improve
for (Iterator<VertexType> i = graph.vertexIterator(); i.hasNext();) {
VertexType vertex = i.next();
- if (visitMe(vertex))
+ if (visitMe(vertex)) {
return vertex;
+ }
}
return null;
}
@@ -149,8 +150,9 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
for (Iterator<VertexType> i = graph.vertexIterator(); i.hasNext();) {
VertexType v = i.next();
- if (getColor(v) == WHITE)
+ if (getColor(v) == WHITE) {
result.add(v);
+ }
}
return result;
}
@@ -159,7 +161,7 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
* Specify a VertexChooser object to be used to selected which vertices are
* visited by the search. This is useful if you only want to search a subset
* of the vertices in the graph.
- *
+ *
* @param vertexChooser
* the VertexChooser to use
*/
@@ -169,7 +171,7 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
/**
* Set a search tree callback.
- *
+ *
* @param searchTreeCallback
* the search tree callback
*/
@@ -179,7 +181,7 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
/**
* Perform the depth first search.
- *
+ *
* @return this object
*/
public AbstractDepthFirstSearch<GraphType, EdgeType, VertexType> search() {
@@ -193,21 +195,22 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
* Return whether or not the graph contains a cycle: i.e., whether it
* contains any back edges. This should only be called after search() has
* been called (since that method actually executes the search).
- *
+ *
* @return true if the graph contains a cycle, false otherwise
*/
public boolean containsCycle() {
for (Iterator<EdgeType> i = graph.edgeIterator(); i.hasNext();) {
EdgeType edge = i.next();
- if (getDFSEdgeType(edge) == BACK_EDGE)
+ if (getDFSEdgeType(edge) == BACK_EDGE) {
return true;
+ }
}
return false;
}
/**
* Get the type of edge in the depth first search.
- *
+ *
* @param edge
* the edge
* @return the DFS type of edge: TREE_EDGE, FORWARD_EDGE, CROSS_EDGE, or
@@ -220,7 +223,7 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
/**
* Return the timestamp indicating when the given vertex was discovered.
- *
+ *
* @param vertex
* the vertex
*/
@@ -231,7 +234,7 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
/**
* Return the timestamp indicating when the given vertex was finished
* (meaning that all of its descendents were visited recursively).
- *
+ *
* @param vertex
* the vertex
*/
@@ -241,7 +244,7 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
/**
* Get array of finish times, indexed by vertex label.
- *
+ *
* @return the array of finish times
*/
@SuppressFBWarnings("EI")
@@ -258,13 +261,14 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
}
private class Visit {
- private VertexType vertex;
+ private final VertexType vertex;
- private Iterator<EdgeType> outgoingEdgeIterator;
+ private final Iterator<EdgeType> outgoingEdgeIterator;
public Visit(VertexType vertex) {
- if (vertex == null)
+ if (vertex == null) {
throw new IllegalStateException();
+ }
this.vertex = vertex;
this.outgoingEdgeIterator = outgoingEdgeIterator(graph, vertex);
@@ -289,12 +293,14 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
private void visitAll() {
for (;;) {
VertexType searchTreeRoot = getNextSearchTreeRoot();
- if (searchTreeRoot == null)
+ if (searchTreeRoot == null) {
// No more work to do
break;
+ }
- if (searchTreeCallback != null)
+ if (searchTreeCallback != null) {
searchTreeCallback.startSearchTree(searchTreeRoot);
+ }
ArrayList<Visit> stack = new ArrayList<Visit>(graph.getNumVertexLabels());
stack.add(new Visit(searchTreeRoot));
@@ -336,7 +342,7 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
case BLACK:
dfsEdgeType = UNKNOWN_EDGE;
break;// We can't distinguish between CROSS and FORWARD edges at
- // this point
+ // this point
default:
assert false;
}
@@ -345,8 +351,9 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
// If successor hasn't been visited yet, visit it
if (visitMe(succ)) {
// Add to search tree (if a search tree callback exists)
- if (searchTreeCallback != null)
+ if (searchTreeCallback != null) {
searchTreeCallback.addToSearchTree(getSource(edge), getTarget(edge));
+ }
// Add to visitation stack
stack.add(new Visit(succ));
@@ -384,7 +391,7 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
/**
* Get the current color of given vertex.
- *
+ *
* @param vertex
* the vertex
* @return the color (WHITE, BLACK, or GRAY)
@@ -397,7 +404,7 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
* Predicate to determine which vertices should be visited as the search
* progresses. Takes both vertex color and the vertex chooser (if any) into
* account.
- *
+ *
* @param vertex
* the vertex to possibly be visited
* @return true if the vertex should be visited, false if not
@@ -419,4 +426,3 @@ public abstract class AbstractDepthFirstSearch<GraphType extends Graph<EdgeType,
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/AbstractEdge.java b/src/java/edu/umd/cs/findbugs/graph/AbstractEdge.java
index a6554ef..f0a75b7 100644
--- a/src/java/edu/umd/cs/findbugs/graph/AbstractEdge.java
+++ b/src/java/edu/umd/cs/findbugs/graph/AbstractEdge.java
@@ -21,18 +21,18 @@ package edu.umd.cs.findbugs.graph;
/**
* GraphEdge implementation for use with AbstractGraph.
- *
+ *
* @see GraphEdge
* @see AbstractGraph
* @see AbstractVertex
* @author David Hovemeyer
*/
public class AbstractEdge<ActualEdgeType extends AbstractEdge<ActualEdgeType, VertexType>, VertexType extends AbstractVertex<ActualEdgeType, VertexType>>
- implements GraphEdge<ActualEdgeType, VertexType> {
+implements GraphEdge<ActualEdgeType, VertexType> {
- private VertexType source;
+ private final VertexType source;
- private VertexType target;
+ private final VertexType target;
private int label;
@@ -42,7 +42,7 @@ public class AbstractEdge<ActualEdgeType extends AbstractEdge<ActualEdgeType, Ve
/**
* Constructor.
- *
+ *
* @param source
* the source vertex of the edge
* @param target
@@ -53,18 +53,22 @@ public class AbstractEdge<ActualEdgeType extends AbstractEdge<ActualEdgeType, Ve
this.target = target;
}
+ @Override
public VertexType getSource() {
return source;
}
+ @Override
public VertexType getTarget() {
return target;
}
+ @Override
public int getLabel() {
return label;
}
+ @Override
public void setLabel(int label) {
this.label = label;
}
@@ -76,16 +80,19 @@ public class AbstractEdge<ActualEdgeType extends AbstractEdge<ActualEdgeType, Ve
@Override
public boolean equals(Object o) {
- if (!(o instanceof AbstractEdge))
+ if (!(o instanceof AbstractEdge)) {
return false;
+ }
AbstractEdge<?,?> other = (AbstractEdge<?,?>) o;
return source.equals(other.source) && target.equals(other.target);
}
+ @Override
public int compareTo(ActualEdgeType other) {
int cmp = source.compareTo(other.getSource());
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return target.compareTo(other.getTarget());
}
@@ -107,4 +114,3 @@ public class AbstractEdge<ActualEdgeType extends AbstractEdge<ActualEdgeType, Ve
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/AbstractGraph.java b/src/java/edu/umd/cs/findbugs/graph/AbstractGraph.java
index aaed6ba..f7dcbfd 100644
--- a/src/java/edu/umd/cs/findbugs/graph/AbstractGraph.java
+++ b/src/java/edu/umd/cs/findbugs/graph/AbstractGraph.java
@@ -27,17 +27,17 @@ import java.util.NoSuchElementException;
* A simple Graph implementation where the vertex objects store a list of
* incoming and outgoing edges. The edge link fields are stored in the edge
* objects, which means a fairly low space overhead.
- *
+ *
* <p>
* The abstract allocateEdge() method must be implemented.
- *
+ *
* @see Graph
* @see AbstractEdge
* @see AbstractVertex
* @author David Hovemeyer
*/
public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, VertexType>, VertexType extends AbstractVertex<EdgeType, VertexType>>
- implements Graph<EdgeType, VertexType> {
+implements Graph<EdgeType, VertexType> {
/*
* ----------------------------------------------------------------------
@@ -49,7 +49,7 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
* Iterator over outgoing edges.
*/
private static class OutgoingEdgeIterator<EdgeType extends AbstractEdge<EdgeType, VertexType>, VertexType extends AbstractVertex<EdgeType, VertexType>>
- implements Iterator<EdgeType> {
+ implements Iterator<EdgeType> {
private EdgeType edge;
@@ -57,18 +57,22 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
this.edge = source.getFirstOutgoingEdge();
}
+ @Override
public boolean hasNext() {
return edge != null;
}
+ @Override
public EdgeType next() {
- if (!hasNext())
+ if (!hasNext()) {
throw new NoSuchElementException();
+ }
EdgeType result = edge;
edge = edge.getNextOutgoingEdge();
return result;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -78,7 +82,7 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
* Iterator over incoming edges.
*/
private static class IncomingEdgeIterator<EdgeType extends AbstractEdge<EdgeType, VertexType>, VertexType extends AbstractVertex<EdgeType, VertexType>>
- implements Iterator<EdgeType> {
+ implements Iterator<EdgeType> {
private EdgeType edge;
@@ -86,18 +90,22 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
this.edge = target.getFirstIncomingEdge();
}
+ @Override
public boolean hasNext() {
return edge != null;
}
+ @Override
public EdgeType next() {
- if (!hasNext())
+ if (!hasNext()) {
throw new NoSuchElementException();
+ }
EdgeType result = edge;
edge = edge.getNextIncomingEdge();
return result;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -109,9 +117,9 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
* ----------------------------------------------------------------------
*/
- private ArrayList<VertexType> vertexList;
+ private final ArrayList<VertexType> vertexList;
- private ArrayList<EdgeType> edgeList;
+ private final ArrayList<EdgeType> edgeList;
private int maxVertexLabel;
@@ -131,18 +139,22 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
this.maxEdgeLabel = 0;
}
+ @Override
public int getNumEdges() {
return edgeList.size();
}
+ @Override
public int getNumVertices() {
return vertexList.size();
}
+ @Override
public Iterator<EdgeType> edgeIterator() {
return edgeList.iterator();
}
+ @Override
public Iterator<VertexType> vertexIterator() {
return vertexList.iterator();
}
@@ -151,19 +163,23 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
return vertexList;
}
+ @Override
public void addVertex(VertexType v) {
vertexList.add(v);
v.setLabel(maxVertexLabel++);
}
+ @Override
public boolean containsVertex(VertexType v) {
for (VertexType existingVertex : vertexList) {
- if (v == existingVertex)
+ if (v == existingVertex) {
return true;
+ }
}
return false;
}
+ @Override
public EdgeType createEdge(VertexType source, VertexType target) {
EdgeType edge = allocateEdge(source, target);
edgeList.add(edge);
@@ -173,58 +189,73 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
return edge;
}
+ @Override
public EdgeType lookupEdge(VertexType source, VertexType target) {
Iterator<EdgeType> i = outgoingEdgeIterator(source);
while (i.hasNext()) {
EdgeType edge = i.next();
- if (edge.getTarget() == target)
+ if (edge.getTarget() == target) {
return edge;
+ }
}
return null;
}
+ @Override
public int getNumVertexLabels() {
return maxVertexLabel;
}
+ @Override
public void setNumVertexLabels(int numLabels) {
this.maxVertexLabel = numLabels;
}
+ @Override
public int getNumEdgeLabels() {
return maxEdgeLabel;
}
+ @Override
public void setNumEdgeLabels(int numLabels) {
maxEdgeLabel = numLabels;
}
+ @Override
public void removeEdge(EdgeType edge) {
- if (!edgeList.remove(edge))
+ if (!edgeList.remove(edge)) {
throw new IllegalArgumentException("removing nonexistent edge!");
+ }
edge.getSource().removeOutgoingEdge(edge);
edge.getTarget().removeIncomingEdge(edge);
}
+ @Override
public void removeVertex(VertexType v) {
- if (!vertexList.remove(v))
+ if (!vertexList.remove(v)) {
throw new IllegalArgumentException("removing nonexistent vertex!");
+ }
- for (Iterator<EdgeType> i = incomingEdgeIterator(v); i.hasNext();)
+ for (Iterator<EdgeType> i = incomingEdgeIterator(v); i.hasNext();) {
removeEdge(i.next());
+ }
- for (Iterator<EdgeType> i = outgoingEdgeIterator(v); i.hasNext();)
+ for (Iterator<EdgeType> i = outgoingEdgeIterator(v); i.hasNext();) {
removeEdge(i.next());
+ }
}
+ @Override
public Iterator<EdgeType> outgoingEdgeIterator(VertexType source) {
return new OutgoingEdgeIterator<EdgeType, VertexType>(source);
}
+ @Override
public Iterator<EdgeType> incomingEdgeIterator(VertexType target) {
return new IncomingEdgeIterator<EdgeType, VertexType>(target);
}
+ @Override
public int getNumIncomingEdges(VertexType vertex) {
int count = 0;
EdgeType e = vertex.firstIncomingEdge;
@@ -235,6 +266,7 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
return count;
}
+ @Override
public int getNumOutgoingEdges(VertexType vertex) {
int count = 0;
EdgeType e = vertex.firstOutgoingEdge;
@@ -245,36 +277,44 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
return count;
}
+ @Override
public Iterator<VertexType> successorIterator(final VertexType source) {
return new Iterator<VertexType>() {
- private Iterator<EdgeType> iter = outgoingEdgeIterator(source);
+ private final Iterator<EdgeType> iter = outgoingEdgeIterator(source);
+ @Override
public boolean hasNext() {
return iter.hasNext();
}
+ @Override
public VertexType next() {
return iter.next().getTarget();
}
+ @Override
public void remove() {
iter.remove();
}
};
}
+ @Override
public Iterator<VertexType> predecessorIterator(final VertexType target) {
return new Iterator<VertexType>() {
- private Iterator<EdgeType> iter = incomingEdgeIterator(target);
+ private final Iterator<EdgeType> iter = incomingEdgeIterator(target);
+ @Override
public boolean hasNext() {
return iter.hasNext();
}
+ @Override
public VertexType next() {
return iter.next().getSource();
}
+ @Override
public void remove() {
iter.remove();
}
@@ -291,4 +331,3 @@ public abstract class AbstractGraph<EdgeType extends AbstractEdge<EdgeType, Vert
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/AbstractVertex.java b/src/java/edu/umd/cs/findbugs/graph/AbstractVertex.java
index 75a2bc9..d06ddea 100644
--- a/src/java/edu/umd/cs/findbugs/graph/AbstractVertex.java
+++ b/src/java/edu/umd/cs/findbugs/graph/AbstractVertex.java
@@ -21,14 +21,14 @@ package edu.umd.cs.findbugs.graph;
/**
* GraphVertex implementation for use with AbstractGraph.
- *
+ *
* @see GraphVertex
* @see AbstractGraph
* @see AbstractEdge
* @author David Hovemeyer
*/
public class AbstractVertex<EdgeType extends AbstractEdge<EdgeType, ActualVertexType>, ActualVertexType extends AbstractVertex<EdgeType, ActualVertexType>>
- implements GraphVertex<ActualVertexType> {
+implements GraphVertex<ActualVertexType> {
private int label;
@@ -36,10 +36,12 @@ public class AbstractVertex<EdgeType extends AbstractEdge<EdgeType, ActualVertex
EdgeType firstOutgoingEdge, lastOutgoingEdge;
+ @Override
public int getLabel() {
return label;
}
+ @Override
public void setLabel(int label) {
this.label = label;
}
@@ -58,6 +60,7 @@ public class AbstractVertex<EdgeType extends AbstractEdge<EdgeType, ActualVertex
return other.getLabel() == this.getLabel();
}
+ @Override
public int compareTo(ActualVertexType other) {
if (this.getLabel() < other.getLabel()) {
return -1;
@@ -99,10 +102,11 @@ public class AbstractVertex<EdgeType extends AbstractEdge<EdgeType, ActualVertex
while (cur != null) {
EdgeType next = cur.getNextIncomingEdge();
if (cur.equals(edge)) {
- if (prev != null)
+ if (prev != null) {
prev.setNextIncomingEdge(next);
- else
+ } else {
firstIncomingEdge = next;
+ }
return;
}
prev = cur;
@@ -116,10 +120,11 @@ public class AbstractVertex<EdgeType extends AbstractEdge<EdgeType, ActualVertex
while (cur != null) {
EdgeType next = cur.getNextOutgoingEdge();
if (cur.equals(edge)) {
- if (prev != null)
+ if (prev != null) {
prev.setNextOutgoingEdge(next);
- else
+ } else {
firstOutgoingEdge = next;
+ }
return;
}
prev = cur;
@@ -130,4 +135,3 @@ public class AbstractVertex<EdgeType extends AbstractEdge<EdgeType, ActualVertex
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/DFSEdgeTypes.java b/src/java/edu/umd/cs/findbugs/graph/DFSEdgeTypes.java
index 91930fa..4fb459b 100644
--- a/src/java/edu/umd/cs/findbugs/graph/DFSEdgeTypes.java
+++ b/src/java/edu/umd/cs/findbugs/graph/DFSEdgeTypes.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.graph;
/**
* Edge types in a depth first search.
- *
+ *
* @see DepthFirstSearch
*/
public interface DFSEdgeTypes {
@@ -53,4 +53,3 @@ public interface DFSEdgeTypes {
public static final int CROSS_EDGE = 3;
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/DepthFirstSearch.java b/src/java/edu/umd/cs/findbugs/graph/DepthFirstSearch.java
index e545454..8ba103a 100644
--- a/src/java/edu/umd/cs/findbugs/graph/DepthFirstSearch.java
+++ b/src/java/edu/umd/cs/findbugs/graph/DepthFirstSearch.java
@@ -23,17 +23,17 @@ import java.util.Iterator;
/**
* Perform a forward depth first search of a graph.
- *
+ *
* @author David Hovemeyer
* @see Graph
* @see AbstractDepthFirstSearch
*/
public class DepthFirstSearch<GraphType extends Graph<EdgeType, VertexType>, EdgeType extends GraphEdge<EdgeType, VertexType>, VertexType extends GraphVertex<VertexType>>
- extends AbstractDepthFirstSearch<GraphType, EdgeType, VertexType> {
+extends AbstractDepthFirstSearch<GraphType, EdgeType, VertexType> {
/**
* Constructor.
- *
+ *
* @param graph
* the graph to perform a depth first search of
*/
@@ -58,4 +58,3 @@ public class DepthFirstSearch<GraphType extends Graph<EdgeType, VertexType>, Edg
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/Graph.java b/src/java/edu/umd/cs/findbugs/graph/Graph.java
index da5f8d6..04de234 100644
--- a/src/java/edu/umd/cs/findbugs/graph/Graph.java
+++ b/src/java/edu/umd/cs/findbugs/graph/Graph.java
@@ -52,7 +52,7 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
/**
* Add given vertex to the graph. The vertex should not be part of any other
* graph.
- *
+ *
* @param v
* the vertex to add
*/
@@ -60,7 +60,7 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
/**
* Determine if the graph contains the given vertex.
- *
+ *
* @param v
* the vertex
* @return true if the vertex is part of the graph, false if not
@@ -70,7 +70,7 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
/**
* Add a new edge to the graph. Duplicate edges (with same source and target
* vertices) are allowed.
- *
+ *
* @param source
* the source vertex
* @param target
@@ -82,7 +82,7 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
/**
* Look up an edge by source and target vertex. If multiple edges with same
* source and target vertex exist, one is selected arbitrarily.
- *
+ *
* @param source
* the source vertex
* @param target
@@ -127,7 +127,7 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
/**
* Get an Iterator over outgoing edges from given vertex.
- *
+ *
* @param source
* the source vertex
* @return an Iterator over outgoing edges
@@ -136,7 +136,7 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
/**
* Get an Iterator over incoming edges to a given vertex.
- *
+ *
* @param target
* the target vertex
* @return an Iterator over incoming edges
@@ -145,7 +145,7 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
/**
* Get number of edges going into given vertex.
- *
+ *
* @param vertex
* the vertex
* @return number of edges going into the vertex
@@ -154,7 +154,7 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
/**
* Get number of edges going out of given vertex.
- *
+ *
* @param vertex
* the vertex
* @return number of edges going out of the vertex
@@ -164,7 +164,7 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
/**
* Get an iterator over the successors of this vertex; i.e., the targets of
* the vertex's outgoing edges.
- *
+ *
* @param source
* the source vertex
* @return an Iterator over the successors of the vertex
@@ -174,7 +174,7 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
/**
* Get an iterator over the predecessors of this vertex; i.e., the sources
* of the vertex's incoming edges.
- *
+ *
* @param target
* the target vertex
* @return an Iterator over the predecessors of the vertex
@@ -183,4 +183,3 @@ public interface Graph<EdgeType extends GraphEdge<EdgeType, VertexType>, VertexT
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/GraphEdge.java b/src/java/edu/umd/cs/findbugs/graph/GraphEdge.java
index a743256..b923d70 100644
--- a/src/java/edu/umd/cs/findbugs/graph/GraphEdge.java
+++ b/src/java/edu/umd/cs/findbugs/graph/GraphEdge.java
@@ -25,7 +25,7 @@ package edu.umd.cs.findbugs.graph;
* GraphEdge interface; represents an edge in a graph.
*/
public interface GraphEdge<ActualEdgeType extends GraphEdge<ActualEdgeType, VertexType>, VertexType extends GraphVertex<VertexType>>
- extends Comparable<ActualEdgeType> {
+extends Comparable<ActualEdgeType> {
/**
* Get the source vertex.
@@ -49,4 +49,3 @@ public interface GraphEdge<ActualEdgeType extends GraphEdge<ActualEdgeType, Vert
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/GraphToolkit.java b/src/java/edu/umd/cs/findbugs/graph/GraphToolkit.java
index 1068013..d7a644e 100644
--- a/src/java/edu/umd/cs/findbugs/graph/GraphToolkit.java
+++ b/src/java/edu/umd/cs/findbugs/graph/GraphToolkit.java
@@ -27,14 +27,14 @@ public interface GraphToolkit<GraphType extends Graph<EdgeType, VertexType>, Edg
/**
* Create a new empty graph (no vertices or edges).
- *
+ *
* @return the new graph
*/
public GraphType createGraph();
/**
* Make a copy of given vertex.
- *
+ *
* @param original
* the vertex to copy
* @return an exact duplicate of the vertex
@@ -43,7 +43,7 @@ public interface GraphToolkit<GraphType extends Graph<EdgeType, VertexType>, Edg
/**
* Copy auxiliary information from one edge to another.
- *
+ *
* @param source
* the source edge
* @param dest
@@ -53,4 +53,3 @@ public interface GraphToolkit<GraphType extends Graph<EdgeType, VertexType>, Edg
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/GraphVertex.java b/src/java/edu/umd/cs/findbugs/graph/GraphVertex.java
index 165fa2b..21a1e6f 100644
--- a/src/java/edu/umd/cs/findbugs/graph/GraphVertex.java
+++ b/src/java/edu/umd/cs/findbugs/graph/GraphVertex.java
@@ -38,4 +38,3 @@ public interface GraphVertex<ActualVertexType> extends Comparable<ActualVertexTy
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/MergeVertices.java b/src/java/edu/umd/cs/findbugs/graph/MergeVertices.java
index d686d97..94ba782 100644
--- a/src/java/edu/umd/cs/findbugs/graph/MergeVertices.java
+++ b/src/java/edu/umd/cs/findbugs/graph/MergeVertices.java
@@ -39,7 +39,7 @@ public class MergeVertices<GraphType extends Graph<EdgeType, VertexType>, EdgeTy
/**
* Merge the specified set of vertices into a single vertex.
- *
+ *
* @param vertexSet
* the set of vertices to be merged
* @param g
@@ -54,8 +54,9 @@ public class MergeVertices<GraphType extends Graph<EdgeType, VertexType>, EdgeTy
// Special case: if the vertex set contains a single vertex
// or is empty, there is nothing to do
- if (vertexSet.size() <= 1)
+ if (vertexSet.size() <= 1) {
return;
+ }
// Get all vertices to which we have outgoing edges
// or from which we have incoming edges, since they'll need
@@ -63,8 +64,9 @@ public class MergeVertices<GraphType extends Graph<EdgeType, VertexType>, EdgeTy
TreeSet<EdgeType> edgeSet = new TreeSet<EdgeType>();
for (Iterator<EdgeType> i = g.edgeIterator(); i.hasNext();) {
EdgeType e = i.next();
- if (vertexSet.contains(e.getSource()) || vertexSet.contains(e.getTarget()))
+ if (vertexSet.contains(e.getSource()) || vertexSet.contains(e.getTarget())) {
edgeSet.add(e);
+ }
}
// Combine all of the vertices into a single composite vertex
@@ -83,12 +85,14 @@ public class MergeVertices<GraphType extends Graph<EdgeType, VertexType>, EdgeTy
// Don't create a self edge for the composite vertex
// unless one of the vertices in the vertex set
// had a self edge
- if (source == compositeVertex && target == compositeVertex && e.getSource() != e.getTarget())
+ if (source == compositeVertex && target == compositeVertex && e.getSource() != e.getTarget()) {
continue;
+ }
// Don't create duplicate edges.
- if (g.lookupEdge(source, target) != null)
+ if (g.lookupEdge(source, target) != null) {
continue;
+ }
EdgeType compositeEdge = g.createEdge(source, target);
// FIXME: we really should have an EdgeCombinator here
@@ -106,4 +110,3 @@ public class MergeVertices<GraphType extends Graph<EdgeType, VertexType>, EdgeTy
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/ReverseDepthFirstSearch.java b/src/java/edu/umd/cs/findbugs/graph/ReverseDepthFirstSearch.java
index f004b6e..8e2a15a 100644
--- a/src/java/edu/umd/cs/findbugs/graph/ReverseDepthFirstSearch.java
+++ b/src/java/edu/umd/cs/findbugs/graph/ReverseDepthFirstSearch.java
@@ -24,17 +24,17 @@ import java.util.Iterator;
/**
* Perform a reverse depth first search of a graph. (I.e., depth first search of
* reversed graph.)
- *
+ *
* @author David Hovemeyer
* @see Graph
* @see AbstractDepthFirstSearch
*/
public class ReverseDepthFirstSearch<GraphType extends Graph<EdgeType, VertexType>, EdgeType extends GraphEdge<EdgeType, VertexType>, VertexType extends GraphVertex<VertexType>>
- extends AbstractDepthFirstSearch<GraphType, EdgeType, VertexType> {
+extends AbstractDepthFirstSearch<GraphType, EdgeType, VertexType> {
/**
* Constructor.
- *
+ *
* @param graph
* the graph to perform a reverse depth first search of
*/
@@ -59,4 +59,3 @@ public class ReverseDepthFirstSearch<GraphType extends Graph<EdgeType, VertexTyp
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/SearchTree.java b/src/java/edu/umd/cs/findbugs/graph/SearchTree.java
index 8ec55d6..ba6f806 100644
--- a/src/java/edu/umd/cs/findbugs/graph/SearchTree.java
+++ b/src/java/edu/umd/cs/findbugs/graph/SearchTree.java
@@ -31,9 +31,9 @@ import java.util.Set;
*/
public class SearchTree<VertexType extends GraphVertex<VertexType>> {
- private VertexType m_vertex;
+ private final VertexType m_vertex;
- private ArrayList<SearchTree<VertexType>> m_childList;
+ private final ArrayList<SearchTree<VertexType>> m_childList;
/**
* Create a new search tree.
@@ -82,4 +82,3 @@ public class SearchTree<VertexType extends GraphVertex<VertexType>> {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/SearchTreeBuilder.java b/src/java/edu/umd/cs/findbugs/graph/SearchTreeBuilder.java
index 7893938..603b3ca 100644
--- a/src/java/edu/umd/cs/findbugs/graph/SearchTreeBuilder.java
+++ b/src/java/edu/umd/cs/findbugs/graph/SearchTreeBuilder.java
@@ -26,24 +26,27 @@ import java.util.LinkedList;
/**
* A search tree callback implementation that builds a list of SearchTrees
* recording a graph search.
- *
+ *
* @see SearchTreeCallback
* @author David Hovemeyer
*/
public class SearchTreeBuilder<VertexType extends GraphVertex<VertexType>> implements SearchTreeCallback<VertexType> {
- private HashMap<VertexType, SearchTree<VertexType>> searchTreeMap = new HashMap<VertexType, SearchTree<VertexType>>();
+ private final HashMap<VertexType, SearchTree<VertexType>> searchTreeMap = new HashMap<VertexType, SearchTree<VertexType>>();
- private LinkedList<SearchTree<VertexType>> searchTreeList = new LinkedList<SearchTree<VertexType>>();
+ private final LinkedList<SearchTree<VertexType>> searchTreeList = new LinkedList<SearchTree<VertexType>>();
+ @Override
public void startSearchTree(VertexType vertex) {
searchTreeList.add(createSearchTree(vertex));
}
+ @Override
public void addToSearchTree(VertexType parent, VertexType child) {
SearchTree<VertexType> parentTree = searchTreeMap.get(parent);
- if (parentTree == null)
+ if (parentTree == null) {
throw new IllegalStateException();
+ }
SearchTree<VertexType> childTree = createSearchTree(child);
parentTree.addChild(childTree);
}
@@ -62,4 +65,3 @@ public class SearchTreeBuilder<VertexType extends GraphVertex<VertexType>> imple
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/SearchTreeCallback.java b/src/java/edu/umd/cs/findbugs/graph/SearchTreeCallback.java
index b626d8b..ee911db 100644
--- a/src/java/edu/umd/cs/findbugs/graph/SearchTreeCallback.java
+++ b/src/java/edu/umd/cs/findbugs/graph/SearchTreeCallback.java
@@ -25,7 +25,7 @@ package edu.umd.cs.findbugs.graph;
public interface SearchTreeCallback<VertexType extends GraphVertex<VertexType>> {
/**
* Start a search tree.
- *
+ *
* @param vertex
* the root of the search tree
*/
@@ -33,7 +33,7 @@ public interface SearchTreeCallback<VertexType extends GraphVertex<VertexType>>
/**
* Add an edge to the current search tree.
- *
+ *
* @param parent
* the parent vertex
* @param child
@@ -42,4 +42,3 @@ public interface SearchTreeCallback<VertexType extends GraphVertex<VertexType>>
public void addToSearchTree(VertexType parent, VertexType child);
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/StronglyConnectedComponents.java b/src/java/edu/umd/cs/findbugs/graph/StronglyConnectedComponents.java
index 1fb86e4..a45b1c1 100644
--- a/src/java/edu/umd/cs/findbugs/graph/StronglyConnectedComponents.java
+++ b/src/java/edu/umd/cs/findbugs/graph/StronglyConnectedComponents.java
@@ -32,7 +32,7 @@ import java.util.TreeSet;
*/
public class StronglyConnectedComponents<GraphType extends Graph<EdgeType, VertexType>, EdgeType extends GraphEdge<EdgeType, VertexType>, VertexType extends GraphVertex<VertexType>> {
- private ArrayList<SearchTree<VertexType>> m_stronglyConnectedSearchTreeList;
+ private final ArrayList<SearchTree<VertexType>> m_stronglyConnectedSearchTreeList;
private VertexChooser<VertexType> m_vertexChooser;
@@ -55,7 +55,7 @@ public class StronglyConnectedComponents<GraphType extends Graph<EdgeType, Verte
/**
* Find the strongly connected components in given graph.
- *
+ *
* @param g
* the graph
* @param toolkit
@@ -66,8 +66,9 @@ public class StronglyConnectedComponents<GraphType extends Graph<EdgeType, Verte
// Perform the initial depth first search
DepthFirstSearch<GraphType, EdgeType, VertexType> initialDFS = new DepthFirstSearch<GraphType, EdgeType, VertexType>(g);
- if (m_vertexChooser != null)
+ if (m_vertexChooser != null) {
initialDFS.setVertexChooser(m_vertexChooser);
+ }
initialDFS.search();
// Create a transposed graph
@@ -97,14 +98,16 @@ public class StronglyConnectedComponents<GraphType extends Graph<EdgeType, Verte
protected VertexType getNextSearchTreeRoot() {
while (vertexIter.hasNext()) {
VertexType vertex = vertexIter.next();
- if (visitMe(vertex))
+ if (visitMe(vertex)) {
return vertex;
+ }
}
return null;
}
};
- if (m_vertexChooser != null)
+ if (m_vertexChooser != null) {
transposeDFS.setVertexChooser(m_vertexChooser);
+ }
transposeDFS.setSearchTreeCallback(searchTreeBuilder);
transposeDFS.search();
@@ -121,7 +124,7 @@ public class StronglyConnectedComponents<GraphType extends Graph<EdgeType, Verte
/**
* Make a copy of given search tree (in the transposed graph) using vertices
* of the original graph.
- *
+ *
* @param tree
* a search tree in the transposed graph
* @param t
@@ -145,7 +148,7 @@ public class StronglyConnectedComponents<GraphType extends Graph<EdgeType, Verte
/**
* Returns an iterator over the search trees containing the vertices of each
* strongly connected component.
- *
+ *
* @return an Iterator over a sequence of SearchTree objects
*/
public Iterator<SearchTree<VertexType>> searchTreeIterator() {
@@ -157,16 +160,18 @@ public class StronglyConnectedComponents<GraphType extends Graph<EdgeType, Verte
* components.
*/
private class SCCSetIterator implements Iterator<Set<VertexType>> {
- private Iterator<SearchTree<VertexType>> m_searchTreeIterator;
+ private final Iterator<SearchTree<VertexType>> m_searchTreeIterator;
public SCCSetIterator() {
m_searchTreeIterator = searchTreeIterator();
}
+ @Override
public boolean hasNext() {
return m_searchTreeIterator.hasNext();
}
+ @Override
public Set<VertexType> next() {
SearchTree<VertexType> tree = m_searchTreeIterator.next();
TreeSet<VertexType> set = new TreeSet<VertexType>();
@@ -174,6 +179,7 @@ public class StronglyConnectedComponents<GraphType extends Graph<EdgeType, Verte
return set;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -182,7 +188,7 @@ public class StronglyConnectedComponents<GraphType extends Graph<EdgeType, Verte
/**
* Returns an iterator over the sets of vertices of each strongly connected
* component.
- *
+ *
* @return an Iterator over a sequence of Set objects
*/
public Iterator<Set<VertexType>> setIterator() {
@@ -191,4 +197,3 @@ public class StronglyConnectedComponents<GraphType extends Graph<EdgeType, Verte
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/Transpose.java b/src/java/edu/umd/cs/findbugs/graph/Transpose.java
index 92924a1..3b4e245 100644
--- a/src/java/edu/umd/cs/findbugs/graph/Transpose.java
+++ b/src/java/edu/umd/cs/findbugs/graph/Transpose.java
@@ -29,9 +29,9 @@ import java.util.Iterator;
*/
public class Transpose<GraphType extends Graph<EdgeType, VertexType>, EdgeType extends GraphEdge<EdgeType, VertexType>, VertexType extends GraphVertex<VertexType>> {
- private IdentityHashMap<VertexType, VertexType> m_origToTransposeMap;
+ private final IdentityHashMap<VertexType, VertexType> m_origToTransposeMap;
- private IdentityHashMap<VertexType, VertexType> m_transposeToOrigMap;
+ private final IdentityHashMap<VertexType, VertexType> m_transposeToOrigMap;
/**
* Constructor.
@@ -44,7 +44,7 @@ public class Transpose<GraphType extends Graph<EdgeType, VertexType>, EdgeType e
/**
* Transpose a graph. Note that the original graph is not modified; the new
* graph and its vertices and edges are new objects.
- *
+ *
* @param orig
* the graph to transpose
* @param toolkit
@@ -97,7 +97,7 @@ public class Transpose<GraphType extends Graph<EdgeType, VertexType>, EdgeType e
/**
* Get the vertex in the transposed graph which corresponds to the given
* vertex in the original graph.
- *
+ *
* @param v
* the vertex in the original graph
* @return the equivalent vertex in the transposed graph
@@ -109,7 +109,7 @@ public class Transpose<GraphType extends Graph<EdgeType, VertexType>, EdgeType e
/**
* Get the vertex in the original graph which corresponds to the given
* vertex in the transposed graph.
- *
+ *
* @param v
* the vertex in the transposed graph
* @return the equivalent vertex in the original graph
@@ -120,4 +120,3 @@ public class Transpose<GraphType extends Graph<EdgeType, VertexType>, EdgeType e
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/VertexChooser.java b/src/java/edu/umd/cs/findbugs/graph/VertexChooser.java
index f239036..4c0dc88 100644
--- a/src/java/edu/umd/cs/findbugs/graph/VertexChooser.java
+++ b/src/java/edu/umd/cs/findbugs/graph/VertexChooser.java
@@ -36,4 +36,3 @@ public interface VertexChooser<VertexType extends GraphVertex<VertexType>> {
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/VertexCombinator.java b/src/java/edu/umd/cs/findbugs/graph/VertexCombinator.java
index 9b648e4..b03b247 100644
--- a/src/java/edu/umd/cs/findbugs/graph/VertexCombinator.java
+++ b/src/java/edu/umd/cs/findbugs/graph/VertexCombinator.java
@@ -30,7 +30,7 @@ import java.util.Set;
public interface VertexCombinator<VertexType extends GraphVertex<VertexType>> {
/**
* Combine given vertices into a single vertex.
- *
+ *
* @param vertexSet
* set of vertices to be combined
* @return the result of combining the vertices in the set
@@ -38,4 +38,3 @@ public interface VertexCombinator<VertexType extends GraphVertex<VertexType>> {
public VertexType combineVertices(Set<VertexType> vertexSet);
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/graph/VisitationTimeComparator.java b/src/java/edu/umd/cs/findbugs/graph/VisitationTimeComparator.java
index dcf979f..d9e9c93 100644
--- a/src/java/edu/umd/cs/findbugs/graph/VisitationTimeComparator.java
+++ b/src/java/edu/umd/cs/findbugs/graph/VisitationTimeComparator.java
@@ -44,13 +44,13 @@ public class VisitationTimeComparator<VertexType extends GraphVertex<VertexType>
*/
public static final int DESCENDING = 1;
- private int[] m_visitationTimeList;
+ private final int[] m_visitationTimeList;
- private int m_direction;
+ private final int m_direction;
/**
* Constructor.
- *
+ *
* @param visitationTimeList
* array of visitation times indexed by vertex label
* @param direction
@@ -61,20 +61,22 @@ public class VisitationTimeComparator<VertexType extends GraphVertex<VertexType>
m_visitationTimeList = visitationTimeList;
m_direction = direction;
- if (direction != ASCENDING && direction != DESCENDING)
+ if (direction != ASCENDING && direction != DESCENDING) {
throw new IllegalArgumentException();
+ }
}
+ @Override
public int compare(VertexType v1, VertexType v2) {
int f1 = m_visitationTimeList[v1.getLabel()];
int f2 = m_visitationTimeList[v2.getLabel()];
- if (m_direction == ASCENDING)
+ if (m_direction == ASCENDING) {
return f1 - f2;
- else
+ } else {
return f2 - f1;
+ }
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/gui/bundle/findbugs_ja.properties b/src/java/edu/umd/cs/findbugs/gui/bundle/findbugs_ja.properties
index c8a7faa..23246a0 100644
--- a/src/java/edu/umd/cs/findbugs/gui/bundle/findbugs_ja.properties
+++ b/src/java/edu/umd/cs/findbugs/gui/bundle/findbugs_ja.properties
@@ -1,288 +1,273 @@
-# Japanese translation provided by Shisei Hanai
-
-
-menu.file_menu=\u30d5\u30a1\u30a4\u30eb(&F)
-menu.new_item=\u65b0\u898f\u30d7\u30ed\u30b8\u30a7\u30af\u30c8(&N)...
-menu.open_item=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u958b\u304f(&O)...
-menu.recent_menu=\u6700\u8fd1\u4f7f\u7528\u3057\u305f\u30d7\u30ed\u30b8\u30a7\u30af\u30c8(&E)
-menu.save_item=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u4fdd\u5b58(&S)
-menu.saveas_item=\u540d\u524d\u3092\u4ed8\u3051\u3066\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u4fdd\u5b58(&A)...
-menu.reload_item=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u518d\u8aad\u307f\u8fbc\u307f(&R)
-menu.close_item=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u9589\u3058\u308b(&C)
-menu.loadbugs_item=\u30d0\u30b0\u306e\u8aad\u307f\u8fbc\u307f(&L)...
-menu.savebugs_item=\u30d0\u30b0\u306e\u4fdd\u5b58(&A)...
-menu.exit_item=\u7d42\u4e86(&X)
-menu.reconfig=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u518d\u69cb\u6210
-
-menu.edit_menu=\u7de8\u96c6(&E)
-menu.selectall_item=\u3059\u3079\u3066\u9078\u629e(&A)
-
-menu.navigation=\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3(&N)
-menu.designation=\u30d0\u30b0\u5206\u985e\u6307\u5b9a(&D)
-menu.view_menu=\u8868\u793a(&V)
-menu.console_item=\u30b3\u30f3\u30bd\u30fc\u30eb(&C)
-menu.bugdetails_item=\u30d0\u30b0\u306e\u8a73\u7d30(&D)
-menu.fulldescriptions_item=\u8a73\u7d30\u8aac\u660e(&F)
-menu.viewprojectdetails_item=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u8a73\u7d30\u306e\u8868\u793a
-menu.viewbugs_item=\u30d0\u30b0\u306e\u8868\u793a
-menu.exit=\u7d42\u4e86
-menu.filtersAndSupressions=\u30d5\u30a3\u30eb\u30bf\u30fc/\u6291\u6b62
-menu.sortConfiguration=\u30bd\u30fc\u30c8\u8a2d\u5b9a...
-menu.gotoLine=\u6307\u5b9a\u884c\u3078\u79fb\u52d5...
-menu.changeDesignation=\u30d0\u30b0\u5206\u985e\u6307\u5b9a\u306e\u5909\u66f4
-menu.filterBugsLikeThis=\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u8a2d\u5b9a...
-menu.filterTheseBugs=\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0\u3059\u308b
-menu.mergeAnalysis=\u30d0\u30b0\u3092\u30de\u30fc\u30b8...
-menu.filterwarnings_menu=\u8b66\u544a\u30d5\u30a3\u30eb\u30bf\u30fc(&W)
-menu.suppress=\u3053\u306e\u30d0\u30b0\u3092\u6291\u6b62
-menu.expand=\u5c55\u958b\u3059\u308b
-menu.collapse=\u6298\u308a\u305f\u305f\u3080
-menu.up=\u4e0a\u3078
-menu.down=\u4e0b\u3078
-
-menu.filterwarnings_menu=\u8b66\u544a\u30d5\u30a3\u30eb\u30bf\u30fc
-menu.exppriority_item=\u512a\u5148\u5ea6(\u5b9f\u9a13\u6bb5\u968e)
-menu.lowpriority_item=\u512a\u5148\u5ea6(\u4f4e)
-menu.mediumpriority_item=\u512a\u5148\u5ea6(\u4e2d)
-menu.highpriority_item=\u512a\u5148\u5ea6(\u9ad8)
-
-menu.preferences_menu=\u8a2d\u5b9a(&P)...
-menu.settings_menu=\u8a2d\u5b9a(&S)
-menu.configure_item=\u30c7\u30a3\u30c6\u30af\u30bf\u306e\u8a2d\u5b9a(&C)...
-menu.effort_menu=Effort
-menu.mineffort_item=\u6700\u5c0f
-menu.normaleffort_item=\u6a19\u6e96
-menu.maxeffort_item=\u6700\u5927
-
-menu.help_menu=\u30d8\u30eb\u30d7(&H)
-menu.about_item=FindBug\u306b\u3064\u3044\u3066(&A)
-
-menu.empty_item=\u7a7a
-menu.rerunAnalysis=\u5206\u6790\u306e\u518d\u5b9f\u884c
-
-dlg.noproject_lbl=FindBugs - \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\u3042\u308a\u307e\u305b\u3093
-dlg.new_item=\u65b0\u898f\u30d7\u30ed\u30b8\u30a7\u30af\u30c8
-dlg.reconfig=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u518d\u69cb\u6210
-dlg.unnamed_lbl=<<\u7121\u540d\u30d7\u30ed\u30b8\u30a7\u30af\u30c8>>
-dlg.project_lbl=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8
-dlg.jarfile_lbl=\u30a2\u30fc\u30ab\u30a4\u30d6\u307e\u305f\u306f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc
-dlg.jarlist_lbl=\u30a2\u30fc\u30ab\u30a4\u30d6/\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc:
-dlg.srcfile_lbl=\u30bd\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc:
-dlg.srclist_lbl=\u30bd\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc:
-dlg.classpathfile_lbl=\u30af\u30e9\u30b9\u30d1\u30b9\u30fb\u30a8\u30f3\u30c8\u30ea\u30fc:
-dlg.classpathlist_lbl=\u30af\u30e9\u30b9\u30d1\u30b9\u30fb\u30a8\u30f3\u30c8\u30ea\u30fc:
-dlg.add_btn=\u8ffd\u52a0...
-dlg.remove_btn=\u524a\u9664
-dlg.browse_btn=\u53c2\u7167
-dlg.up_btn=\u4e0a\u3078
-dlg.down_btn=\u4e0b\u3078
-
-dlg.byclass_tab=\u30af\u30e9\u30b9\u5225
-dlg.bypackage_tab=\u30d1\u30c3\u30b1\u30fc\u30b8\u5225
-dlg.bybugtype_tab=\u30d0\u30b0\u30bf\u30a4\u30d7\u5225
-dlg.bybugcategory_tab=\u30d0\u30b0\u30ab\u30c6\u30b4\u30ea\u30fc\u5225
-dlg.summary_tab=\u30b5\u30de\u30ea\u30fc
-dlg.details_tab=\u8a73\u7d30
-dlg.sourcecode_tab=\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9
-dlg.annotations_tab=\u6ce8\u91c8
-
-dlg.analysiserror_lbl=\u5206\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f:
-dlg.ok_btn=\u4e86\u89e3
-
-dlg.stage_lbl=Stage:
-dlg.count_lbl=Count:
-dlg.progress_lbl=Progress:
-dlg.cancel_btn=\u30ad\u30e3\u30f3\u30bb\u30eb
-
-dlg.restoredefaults_btn=\u30c7\u30d5\u30a9\u30eb\u30c8\u306b\u623b\u3059
-
-dlg.bugdetector_lbl=Bug Detector
-dlg.speed_lbl=Speed
-dlg.enabled_lbl=Enabled
-
-dlg.about_tab=FindBug\u306b\u3064\u3044\u3066
-dlg.license_tab=\u30e9\u30a4\u30bb\u30f3\u30b9
-dlg.acknowledgements_tab=\u8b1d\u8f9e
-
-dlg.findbugsprojects_lbl=FindBugs \u30d7\u30ed\u30b8\u30a7\u30af\u30c8 (*.fb)
-dlg.jarsanddirectories_lbl=\u30a2\u30fc\u30ab\u30a4\u30d6\u30d5\u30a1\u30a4\u30eb\u304a\u3088\u3073\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc
-
-dlg.runanalysis_ttl=\u5206\u6790\u306e\u5b9f\u884c
-dlg.aboutfindbugs_ttl=FindBugs {0} \u306b\u3064\u3044\u3066
-dlg.analysiserrors_ttl=\u5206\u6790\u30a8\u30e9\u30fc
-dlg.configuredetectors_ttl=\u30c7\u30a3\u30c6\u30af\u30bf\u306e\u8a2d\u5b9a
-dlg.xmlsavedbugs_lbl=\u30d0\u30b0\u4fdd\u5b58 XML \u30d5\u30a1\u30a4\u30eb
-dlg.javaarchives_lbl=Java \u30a2\u30fc\u30ab\u30a4\u30d6 (*.class,*.jar,*.zip,*.ear,*.war,*.sar)
-dlg.closeproject_lbl=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u9589\u3058\u308b
-dlg.saveprojectas_ttl=\u540d\u524d\u3092\u4ed8\u3051\u3066\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u4fdd\u5b58
-dlg.loadbugs_ttl=\u30d0\u30b0\u306e\u8aad\u307f\u8fbc\u307f
-dlg.savebugs_ttl=\u30d0\u30b0\u306e\u4fdd\u5b58
-dlg.rerunAnalysis=\u5206\u6790\u306e\u518d\u5b9f\u884c
-
-msg.scanningarchives_txt=\u30a2\u30fc\u30ab\u30a4\u30d6\u3092\u30b9\u30ad\u30e3\u30f3\u4e2d
-msg.analysingclasses_txt=\u30af\u30e9\u30b9\u3092\u5206\u6790\u4e2d
-msg.finishedanalysis_txt=\u5206\u6790\u7d42\u4e86
-msg.cancelanalysis_txt=\u5206\u6790\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3059\u304b?
-msg.analyze_txt=\u5206\u6790
-msg.couldntload_txt={0} \u304c\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093
-msg.failedtotransform_txt=\u30b5\u30de\u30ea\u30fc\u306e\u5909\u63db\u306b\u5931\u6557: {0}
-msg.error_txt=\u30a8\u30e9\u30fc:
-msg.warning_txt=\u8b66\u544a:
-msg.exp_txt=\u5b9f\u9a13\u6bb5\u968e:
-msg.errorformatting_txt=\u30d0\u30b0\u306b\u5bfe\u3059\u308b\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u51e6\u7406\u3067\u30a8\u30e9\u30fc: {0}
-msg.couldnotopenproject_txt=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\u958b\u3051\u306a\u304b\u3063\u305f: {0}
-msg.saveproject_txt=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u4fdd\u5b58
-msg.saveprojectas_txt=\u540d\u524d\u3092\u4ed8\u3051\u3066\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u4fdd\u5b58
-msg.saveprojectquery_txt=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u4fdd\u5b58\u3057\u307e\u3059\u304b?
-msg.projectnojars_txt=Project {0} \u306f\u30a2\u30fc\u30ab\u30a4\u30d6\u30d5\u30a1\u30a4\u30eb\u304c\u672a\u9078\u629e\u3067\u3059
-msg.beginninganalysis_txt={0} \u306e\u5206\u6790\u3092\u958b\u59cb\u3057\u307e\u3059
-msg.analysiscompleted_txt={0} \u306e\u5206\u6790\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f
-msg.fatalanalysisexception_txt=\u5206\u6790\u306b\u304a\u3044\u3066\u81f4\u547d\u7684\u306a\u4f8b\u5916\u304c\u767a\u751f: {0}
-msg.analysiscancelled_txt={0} \u306e\u5206\u6790\u306f\u30e6\u30fc\u30b6\u30fc\u306b\u3088\u308a\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f
-msg_addsource_lbl=\u30bd\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u307e\u305f\u306f\u30a2\u30fc\u30ab\u30a4\u30d6\u3092\u8ffd\u52a0
-msg.addarchiveordirectory_txt=\u30a2\u30fc\u30ab\u30a4\u30d6\u307e\u305f\u306f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u8ffd\u52a0
-msg.newproject_txt=\u65b0\u898f\u30d7\u30ed\u30b8\u30a7\u30af\u30c8
-msg.openproject_txt=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u958b\u304f...
-msg.addRemoveFiles=\u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0/\u524a\u9664...
-msg.userelativepaths_txt=\u76f8\u5bfe\u30d1\u30b9\u3092\u4f7f\u7528
-msg.bugpatternsreported_txt=\u5831\u544a\u3055\u308c\u305f\u30d0\u30b0\u30d1\u30bf\u30fc\u30f3
-
-msg.nosource_txt=\u30bd\u30fc\u30b9\u304c\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
-msg.loading_bugs_over_network_txt=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u4e0a\u304b\u3089\u30d0\u30b0\u3092\u8aad\u307f\u8fbc\u3080...
-
-# The following three properties are not needed any more.
-msg.you_are_loading_txt=\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059
-msg.you_are_closing_txt=You are closing
-msg.without_saving_txt=without saving. \u4fdd\u5b58\u3057\u307e\u3059\u304b?
-# instead, the following two are used
-msg.you_are_loading_without_saving_txt=\u4fdd\u5b58\u305b\u305a\u306b\u8aad\u307f\u8fbc\u307f\u3092\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059\u3002\u4fdd\u5b58\u3057\u307e\u3059\u304b?
-msg.you_are_closing_without_saving_txt=\u4fdd\u5b58\u305b\u305a\u306b\u9589\u3058\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059\u3002\u4fdd\u5b58\u3057\u307e\u3059\u304b?
-
-msg.confirm_save_txt=\u4fdd\u5b58\u3057\u307e\u3059\u304b?
-dlg.create_new_filter_ttl=\u30d5\u30a3\u30eb\u30bf\u30fc\u306e\u65b0\u898f\u4f5c\u6210
-dlg.changing_text_lbl=\u3053\u306e\u30c6\u30ad\u30b9\u30c8\u30fb\u30dc\u30c3\u30af\u30b9\u3092\u5909\u66f4\u3059\u308b\u3068\u3001\u9078\u629e\u3055\u308c\u305f\u30d5\u30a9\u30eb\u30c0\u30fc\u304a\u3088\u3073\u30b5\u30d6\u30d5\u30a9\u30eb\u30c0\u30fc\u306b\u3042\u308b\u3059\u3079\u3066\u306e\u30d0\u30b0\u306e\u6ce8\u91c8\u304c\u4e0a\u66f8\u304d\u3055\u308c\u307e\u3059\u3002\u3088\u308d\u3057\u3044\u3067\u3059\u304b?
-dlg.annotation_change_ttl=\u6ce8\u91c8\u306e\u5909\u66f4
-dlg.yes_btn=\u306f\u3044
-dlg.no_btn=\u3044\u3044\u3048
-dlg.find_btn=\u691c\u7d22
-dlg.find_next_btn=\u6b21\u3092\u691c\u7d22
-dlg.find_prev_btn=\u524d\u3092\u691c\u7d22
-dlg.save_dont_ask_btn=\u306f\u3044\u3002\u307e\u305f\u3001\u4eca\u5f8c\u3053\u306e\u78ba\u8a8d\u306f\u5fc5\u8981\u3042\u308a\u307e\u305b\u3093\u3002
-dlg.proj_not_found=\u3053\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306f\u3082\u306f\u3084\u5b58\u5728\u3057\u307e\u305b\u3093\u3002
-dlg.save_current_changes=\u73fe\u5728\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306f\u5909\u66f4\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u73fe\u5728\u306e\u5909\u66f4\u3092\u4fdd\u5b58\u3057\u307e\u3059\u304b?
-dlg.save_changes=\u4fdd\u5b58\u3057\u307e\u3059\u304b?
-dlg.go_to_line_lbl=\u6307\u5b9a\u884c\u3078\u79fb\u52d5
-dlg.no_proj_save_lbl=\u4fdd\u5b58\u3059\u308b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306f\u5b58\u5728\u3057\u307e\u305b\u3093
-dlg.saveas_ttl=\u540d\u524d\u3092\u4ed8\u3051\u3066\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u4fdd\u5b58
-dlg.proj_already_exists_lbl=\u3053\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\u7f6e\u304d\u63db\u3048\u307e\u3059\u304b?
-dlg.analysis_exists_lbl=\u3053\u306e\u30d0\u30b0\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\u7f6e\u304d\u63db\u3048\u307e\u3059\u304b?
-dlg.file_does_not_exist_lbl=\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
-dlg.not_dir_warning_lbl=\u8b66\u544a!\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3067\u306f\u3042\u308a\u307e\u305b\u3093
-dlg.proj_not_dir_warning_lbl=\u8b66\u544a!\u3053\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3067\u306f\u3042\u308a\u307e\u305b\u3093
-dlg.no_xml_data_lbl=\u3053\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u306f\u30d0\u30b0\u4fdd\u5b58XML\u3092\u542b\u3093\u3067\u3044\u307e\u305b\u3093\u3002\u5225\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002
-dlg.not_xml_data_lbl=\u3053\u308c\u306f\u30d0\u30b0\u4fdd\u5b58XML\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
-dlg.filter_settings_not_found_lbl=\u30d5\u30a3\u30eb\u30bf\u30fc\u8a2d\u5b9a\u304c\u307f\u3064\u304b\u308a\u307e\u305b\u3093\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u8a2d\u5b9a\u3092\u4f7f\u7528\u3057\u307e\u3059\u3002
-dlg.saving_error_lbl=\u4fdd\u5b58\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f
-dlg.warning_ttl=\u8b66\u544a!
-dlg.finish_btn=\u7d42\u4e86
-dlg.class_jars_dirs_lbl=\u5206\u6790\u3059\u308b\u30a2\u30fc\u30ab\u30a4\u30d6\u304a\u3088\u3073\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc
-dlg.aux_class_lbl=\u88dc\u52a9\u30af\u30e9\u30b9\u30d1\u30b9(\u53c2\u7167\u3055\u308c\u308b\u304c\u5206\u6790\u306e\u5bfe\u8c61\u5916)
-dlg.source_dirs_lbl=\u30bd\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc:
-dlg.invalid_txt= \u307f\u3064\u304b\u308a\u307e\u305b\u3093\u3002\u7d9a\u884c\u3057\u3066\u3044\u3044\u3067\u3059\u304b?
-dlg.error_ttl=\u30d5\u30a1\u30a4\u30eb\u3092\u307f\u3064\u3051\u3089\u308c\u307e\u305b\u3093
-dlg.project_settings_changed_lbl=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u8a2d\u5b9a\u304c\u5909\u66f4\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u5909\u66f4\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3067\u65b0\u305f\u306a\u5206\u6790\u3092\u5b9f\u884c\u3057\u307e\u3059\u304b?
-dlg.redo_analysis_question_lbl=\u5206\u6790\u306e\u518d\u5b9f\u884c?
-dlg.apply_btn=\u9069\u7528
-dlg.unsuppress_btn=\u6291\u6b62\u89e3\u9664
-dlg.remove_all_btn=\u3059\u3079\u3066\u524a\u9664
-dlg.add_dot_btn=\u8ffd\u52a0...
-dlg.fil_sup_ttl=\u30d5\u30a3\u30eb\u30bf\u30fc/\u6291\u6b62
-dlg.choose_xmls_ttl=\u7d50\u5408\u3059\u308bXML\u3092\u3059\u3079\u3066\u9078\u629e
-dlg.filter_bugs_lbl=\u6b21\u306e\u6761\u4ef6\u306e\u30d0\u30b0\u3092\u30d5\u30a3\u30eb\u30bf\u30fc\u3067\u9664\u53bb\u3059\u308b
-dlg.is=\u304c
-button.find=\u691c\u7d22
-button.findNext=\u6b21\u3092\u691c\u7d22
-button.findPrev=\u524d\u3092\u691c\u7d22
-tree.bugs=\u30d0\u30b0
-view.bugs=\u30d0\u30b0
-view.bug_summary=\u30d0\u30b0\u30b5\u30de\u30ea\u30fc
-view.comments=\u30b3\u30e1\u30f3\u30c8
-view.source=\u30bd\u30fc\u30b9
-mode.not_equal_to=\u7b49\u3057\u304f\u306a\u3044
-mode.equal_to=\u7b49\u3057\u3044
-mode.at_or_after=\u4ee5\u964d
-mode.at_or_before=\u4ee5\u524d
-menu.addRemoveFiles=\u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0/\u524a\u9664...
-menu.suppress_bug=\u3053\u306e\u30d0\u30b0\u3092\u6291\u6b62
-menu.filter_bugs=\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u8a2d\u5b9a
-menu.filter_these_bugs=\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0\u3059\u308b
-menu.change_designation=\u30d0\u30b0\u5206\u985e\u6307\u5b9a\u306e\u5909\u66f4
-menu.go_to_line=\u6307\u5b9a\u884c\u3078\u79fb\u52d5...
-menu.about_fb=FindBugs \u306b\u3064\u3044\u3066...
-menu.recent_projects_menu=\u6700\u8fd1\u4f7f\u7528\u3057\u305f\u30d7\u30ed\u30b8\u30a7\u30af\u30c8
-tooltip.reorder_message=\u30c9\u30e9\u30c3\u30b0\u3059\u308b\u3068\u30d5\u30a9\u30eb\u30c0\u30fc\u306e\u30c4\u30ea\u30fc\u69cb\u6210\u3092\u518d\u914d\u7f6e\u3057\u3066\u30bd\u30fc\u30c8\u3057\u307e\u3059
-tooltip.longer_description=\u691c\u51fa\u3055\u308c\u305f\u30d0\u30b0\u30d1\u30bf\u30fc\u30f3\u306e\u8a73\u7d30\u306a\u8aac\u660e \u3067\u3059
-tooltip.click_to_go_to=\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u79fb\u52d5\u3057\u307e\u3059\u3002\u79fb\u52d5\u5148
-tooltip.enter_comments=\u3053\u306e\u30d0\u30b0\u306b\u5bfe\u3059\u308b\u30b3\u30e1\u30f3\u30c8\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044
-tooltip.reuse_comments=\u3053\u306e\u30d0\u30b0\u306b\u5bfe\u3059\u308b\u4ee5\u524d\u306e\u30b3\u30e1\u30f3\u30c8\u3092\u518d\u4f7f\u7528\u3057\u307e\u3059
-tooltip.select_designation=\u3053\u306e\u30d0\u30b0\u306b\u5bfe\u3059\u308b\u30d0\u30b0\u5206\u985e\u6307\u5b9a\u3092\u9078\u629e\u3057\u307e\u3059
-summary.null=null
-summary.source_code=\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9
-summary_line=\u884c
-summary_lines=\u884c
-sort.priority_high=\u512a\u5148\u5ea6(\u9ad8)
-sort.priority_normal=\u512a\u5148\u5ea6(\u4e2d)
-sort.priority_low=\u512a\u5148\u5ea6(\u4f4e)
-sort.priority_experimental=\u512a\u5148\u5ea6(\u5b9f\u9a13\u6bb5\u968e)
-sort.priority_ignore=\u7121\u8996
-sort.priority=\u512a\u5148\u5ea6
-sort.class=\u30af\u30e9\u30b9
-sort.package=\u30d1\u30c3\u30b1\u30fc\u30b8
-sort.category=\u30ab\u30c6\u30b4\u30ea\u30fc
-sort.designation=\u30d0\u30b0\u5206\u985e\u6307\u5b9a
-sort.bug_kind=\u30d0\u30b0\u7a2e\u5225
-sort.bug_pattern=\u30d0\u30b0\u30d1\u30bf\u30fc\u30f3
-sort.divider=[\u4ed5\u5207\u308a]
-sort.first_version=\u521d\u56de\u30d0\u30fc\u30b8\u30e7\u30f3
-sort.last_version=\u6700\u7d42\u30d0\u30fc\u30b8\u30e7\u30f3
-sort.first_version_not_defined=\u521d\u56de\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u672a\u5b9a\u7fa9
-sort.last_version_not_defined=\u6700\u7d42\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u672a\u5b9a\u7fa9
-txt.source_listing=<\u30bd\u30fc\u30b9\u30ea\u30b9\u30c8>
-txt.source=\u30bd\u30fc\u30b9
-txt.cut=\u5207\u308a\u53d6\u308a
-txt.copy=\u30b3\u30d4\u30fc
-txt.paste=\u8cbc\u308a\u4ed8\u3051
-file.accepted_extensions=\u30af\u30e9\u30b9\u30a2\u30fc\u30ab\u30a4\u30d6\u30d5\u30a1\u30a4\u30eb (*.jar, *.war, *.ear, *.zip, *.sar)
-pref.filters=\u30d5\u30a3\u30eb\u30bf\u30fc
-pref.close=\u9589\u3058\u308b
-pref.name=\u540d\u524d
-pref.type=\u30bf\u30a4\u30d7
-pref.description=\u8aac\u660e
-pref.comments=\u30b3\u30e1\u30f3\u30c8
-pref.suppressions=\u30d0\u30b0\u6291\u6b62
-pref.suppressions_tab=\u6291\u6b62
-progress.finishing_analysis=\u5206\u6790\u3092\u7d42\u4e86\u4e2d...
-progress.analyzing_classes=\u30af\u30e9\u30b9\u3092\u5206\u6790\u4e2d...
-progress.scanning_archives=\u30a2\u30fc\u30ab\u30a4\u30d6\u3092\u30b9\u30ad\u30e3\u30f3\u4e2d...
-err.missing_pattern=\u30a8\u30e9\u30fc: \u30ad\u30fc\u306b\u5bfe\u3059\u308b\u30d0\u30b0\u30d1\u30bf\u30fc\u30f3\u304c\u6b20\u843d
-err.missing_code=\u30a8\u30e9\u30fc: \u30ad\u30fc\u306b\u5bfe\u3059\u308b\u30d0\u30b0\u30b3\u30fc\u30c9\u304c\u6b20\u843d
-statusbar.bug_hidden=\u96a0\u3055\u308c\u305f\u30d0\u30b0
-statusbar.bugs_hidden=\u96a0\u3055\u308c\u305f\u30d0\u30b0
-
-menu.addRemoveFiles=\u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0/\u524a\u9664...
-summary.line=\u884c
-summary.lines=\u884c
-
-
-# missing in findbugs_en.properties
-menu.recent=\u6700\u8fd1\u4f7f\u3063\u305f\u30d5\u30a1\u30a4\u30eb
-menu.importFilter_item=\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u30a4\u30f3\u30dd\u30fc\u30c8...
-menu.exportFilter_item=\u30d5\u30a3\u30eb\u30bf\u30fc\u306e\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
-pref.dead_bugs=Dead Bugs
-msg.proj_not_found=\u3053\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306f\u3082\u306f\u3084\u5b58\u5728\u3057\u307e\u305b\u3093
-dlg.no_filter=\u30d5\u30a3\u30eb\u30bf\u30fc\u304c\u3042\u308a\u307e\u305b\u3093
-dlg.importFilter_ttl=\u30d5\u30a3\u30eb\u30bf\u30fc\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u304a\u3088\u3073\u30de\u30fc\u30b8
-dlg.exportFilter_ttl=\u30d5\u30a3\u30eb\u30bf\u30fc\u306e\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
-dlg.file_exists_lbl=\u3053\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\u7f6e\u304d\u63db\u3048\u307e\u3059\u304b?
-FB\ Project\ File\ already\ exists=\u3053\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\u7f6e\u304d\u63db\u3048\u307e\u3059\u304b?
-FB\ Analysis\ File\ already\ exists=\u3053\u306e\u30d0\u30b0\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\u7f6e\u304d\u63db\u3048\u307e\u3059\u304b?
+#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
+# Japanese translation provided by Shisei Hanai
+
+button.find = \u691C\u7D22
+button.findNext = \u6B21\u3092\u691C\u7D22
+button.findPrev = \u524D\u3092\u691C\u7D22
+
+dlg.about_tab = FindBug \u306B\u3064\u3044\u3066
+dlg.aboutfindbugs_ttl = FindBugs {0} \u306B\u3064\u3044\u3066
+dlg.acknowledgements_tab = \u8B1D\u8F9E
+dlg.add_btn = \u8FFD\u52A0
+dlg.add_dot_btn = \u8FFD\u52A0...
+dlg.analysis_exists_lbl = \u3053\u306E\u5206\u6790\u306F\u3059\u3067\u306B\u5B58\u5728\u3057\u307E\u3059\u3002\u7F6E\u304D\u63DB\u3048\u307E\u3059\u304B?
+dlg.analysiserror_lbl = \u5206\u6790\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u305F:
+dlg.analysiserrors_ttl = \u5206\u6790\u30A8\u30E9\u30FC
+dlg.analyze_btn = \u5206\u6790
+dlg.annotation_change_ttl = \u3088\u308D\u3057\u3044\u3067\u3059\u304B?
+dlg.annotations_tab = \u6CE8\u91C8
+dlg.apply_btn = \u9069\u7528
+dlg.aux_class_lbl = \u88DC\u52A9\u30AF\u30E9\u30B9\u30D1\u30B9 (\u30AA\u30D7\u30B7\u30E7\u30CA\u30EB; \u30AF\u30E9\u30B9\u30D1\u30B9\u5206\u6790\u3067\u53C2\u7167\u3055\u308C\u308B)
+dlg.browse_btn = \u30D6\u30E9\u30A6\u30BA
+dlg.bugdetector_lbl = \u30D0\u30B0\u30FB\u30C7\u30A3\u30C6\u30AF\u30BF\u30FC
+dlg.bybugcategory_tab = \u30D0\u30B0\u30FB\u30AB\u30C6\u30B4\u30EA\u30FC\u5225
+dlg.bybugtype_tab = \u30D0\u30B0\u30FB\u30BF\u30A4\u30D7\u5225
+dlg.byclass_tab = \u30AF\u30E9\u30B9\u5225
+dlg.bypackage_tab = \u30D1\u30C3\u30B1\u30FC\u30B8\u5225
+dlg.cancel_btn = \u30AD\u30E3\u30F3\u30BB\u30EB
+dlg.changing_text_lbl = \u3053\u306E\u30D5\u30A9\u30EB\u30C0\u30FC\u304A\u3088\u3073\u30B5\u30D6\u30D5\u30A9\u30EB\u30C0\u30FC\u306B\u3042\u308B\u3059\u3079\u3066\u306E\u30D0\u30B0\u306E\u30EC\u30D3\u30E5\u30FC\u304C\u4E0A\u66F8\u304D\u3055\u308C\u307E\u3059\u3002\u3088\u308D\u3057\u3044\u3067\u3059\u304B?
+dlg.choose_xmls_ttl = \u7D50\u5408\u3059\u308B XML \u3092\u3059\u3079\u3066\u9078\u629E
+dlg.class_jars_dirs_lbl = \u5206\u6790\u30AF\u30E9\u30B9\u30D1\u30B9 (\u30A2\u30FC\u30AB\u30A4\u30D6\u304A\u3088\u3073\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC)
+dlg.classpathfile_lbl = \u30AF\u30E9\u30B9\u30D1\u30B9\u30FB\u30A8\u30F3\u30C8\u30EA\u30FC:
+dlg.classpathlist_lbl = \u30AF\u30E9\u30B9\u30D1\u30B9\u30FB\u30A8\u30F3\u30C8\u30EA\u30FC:
+dlg.closeproject_lbl = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u9589\u3058\u308B
+dlg.cloud.add_review = \u30EC\u30D3\u30E5\u30FC\u3092\u8FFD\u52A0...
+dlg.cloud.add_review_multi = \u30D0\u30B0\u306B\u30EC\u30D3\u30E5\u30FC\u3092\u8FFD\u52A0...
+dlg.cloud.ovwrt_review_multi = \u30EC\u30D3\u30E5\u30FC\u3092\u4E0A\u66F8\u304D\u3059\u308B...
+dlg.configuredetectors_ttl = \u30C7\u30A3\u30C6\u30AF\u30BF\u30FC\u306E\u8A2D\u5B9A
+dlg.count_lbl = \u30AB\u30A6\u30F3\u30C8:
+dlg.create_new_filter_ttl = \u65B0\u898F\u30D5\u30A3\u30EB\u30BF\u30FC\u306E\u4F5C\u6210
+dlg.details_tab = \u8A73\u7D30
+dlg.dontsave_btn = \u4FDD\u5B58\u3057\u306A\u3044
+dlg.down_btn = \u4E0B\u3078
+dlg.enabled_lbl = \u4F7F\u7528\u53EF\u80FD
+dlg.error_ttl = \u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
+dlg.fil_sup_ttl = \u8A2D\u5B9A
+dlg.file_does_not_exist_lbl = \u305D\u306E\u30D5\u30A1\u30A4\u30EB\u306F\u5B58\u5728\u3057\u307E\u305B\u3093
+dlg.filter_bugs_lbl = \u3059\u3079\u3066\u306E\u30D0\u30B0\u3092\u30D5\u30A3\u30EB\u30BF\u30FC\u3059\u308B
+dlg.filter_settings_not_found_lbl = \u30D5\u30A3\u30EB\u30BF\u30FC\u8A2D\u5B9A\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u8A2D\u5B9A\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+dlg.find_btn = \u691C\u7D22
+dlg.find_next_btn = \u6B21\u3092\u691C\u7D22
+dlg.find_prev_btn = \u524D\u3092\u691C\u7D22
+dlg.findbugsprojects_lbl = FindBugs \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8 (*.fb)
+dlg.go_to_line_lbl = \u6307\u5B9A\u884C\u3078\u79FB\u52D5
+dlg.invalid_txt = \u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u7D9A\u884C\u3057\u307E\u3059\u304B?
+dlg.is = \u304C
+dlg.jarfile_lbl = \u30A2\u30FC\u30AB\u30A4\u30D6\u307E\u305F\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC
+dlg.jarlist_lbl = \u30A2\u30FC\u30AB\u30A4\u30D6/\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC:
+dlg.jarsanddirectories_lbl = \u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u304A\u3088\u3073\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC
+dlg.javaarchives_lbl = Java \u30A2\u30FC\u30AB\u30A4\u30D6 (*.class,*.jar,*.zip,*.ear,*.war,*.sar)
+dlg.license_tab = \u30E9\u30A4\u30BB\u30F3\u30B9
+dlg.loadbugs_ttl = \u30D0\u30B0\u306E\u30ED\u30FC\u30C9...
+dlg.new_item = \u65B0\u898F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8
+dlg.no_btn = \u3044\u3044\u3048
+dlg.no_proj_save_lbl = \u4FDD\u5B58\u3059\u308B\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C\u3042\u308A\u307E\u305B\u3093
+dlg.no_xml_data_lbl = \u3053\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC\u306F\u30D0\u30B0\u4FDD\u5B58 XML \u30C7\u30FC\u30BF\u3092\u542B\u3093\u3067\u3044\u307E\u305B\u3093\u3002\u5225\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+dlg.noproject_lbl = FindBugs - \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C\u3042\u308A\u307E\u305B\u3093
+dlg.not_dir_warning_lbl = \u8B66\u544A! \u30D5\u30A1\u30A4\u30EB\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC\u3067\u306F\u3042\u308A\u307E\u305B\u3093
+dlg.not_xml_data_lbl = \u3053\u308C\u306F\u30D0\u30B0\u4FDD\u5B58 XML \u30C7\u30FC\u30BF\u30FB\u30D5\u30A1\u30A4\u30EB\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002
+dlg.ok_btn = OK
+dlg.progress_lbl = \u9032\u884C\u72B6\u6CC1:
+dlg.proj_already_exists_lbl = \u3053\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306F\u3059\u3067\u306B\u5B58\u5728\u3057\u307E\u3059\u3002\u7F6E\u304D\u63DB\u3048\u307E\u3059\u304B?
+dlg.proj_not_dir_warning_lbl = \u8B66\u544A! \u3053\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC\u3067\u306F\u3042\u308A\u307E\u305B\u3093
+dlg.proj_not_found = \u3053\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306F\u3082\u3046\u3042\u308A\u307E\u305B\u3093\u3002
+dlg.project_lbl = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8
+dlg.project_settings_changed_lbl = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u8A2D\u5B9A\u304C\u5909\u66F4\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u5909\u66F4\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u3067\u65B0\u305F\u306A\u5206\u6790\u3092\u5B9F\u884C\u3057\u307E\u3059\u304B?
+dlg.reconfig = \u518D\u69CB\u6210
+dlg.redo_analysis_question_lbl = \u5206\u6790\u306E\u3084\u308A\u76F4\u3057?
+dlg.remove_all_btn = \u3059\u3079\u3066\u9664\u53BB
+dlg.remove_btn = \u9664\u53BB
+dlg.rerunAnalysis = \u5206\u6790\u306E\u518D\u5B9F\u884C
+dlg.restoredefaults_btn = \u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u5FA9\u5143
+dlg.runanalysis_ttl = \u5206\u6790\u306E\u5B9F\u884C
+dlg.save_btn = \u4FDD\u5B58
+dlg.save_changes = \u5909\u66F4\u3092\u4FDD\u5B58\u3057\u307E\u3059\u304B?
+dlg.save_current_changes = \u73FE\u5728\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306F\u5909\u66F4\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u73FE\u5728\u306E\u5909\u66F4\u3092\u4FDD\u5B58\u3057\u307E\u3059\u304B?
+dlg.save_dont_ask_btn = \u5E38\u306B\u4FDD\u5B58
+dlg.saveas_ttl = \u5225\u540D\u3067\u4FDD\u5B58
+dlg.savebugs_ttl = \u30D0\u30B0\u306E\u4FDD\u5B58
+dlg.saved_btn = \u4FDD\u5B58
+dlg.saveprojectas_ttl = \u5225\u540D\u3067\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58
+dlg.saving_error_lbl = \u4FDD\u5B58\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u305F
+dlg.source_dirs_lbl = \u30BD\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC (\u30AA\u30D7\u30B7\u30E7\u30CA\u30EB: \u767A\u898B\u3057\u305F\u30D0\u30B0\u3092\u30D6\u30E9\u30A6\u30BA\u3059\u308B\u3068\u304D\u306B\u4F7F\u308F\u308C\u308B)
+dlg.sourcecode_tab = \u30BD\u30FC\u30B9\u30FB\u30B3\u30FC\u30C9
+dlg.speed_lbl = \u901F\u5EA6
+dlg.srcfile_lbl = \u30BD\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC:
+dlg.srclist_lbl = \u30BD\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC:
+dlg.stage_lbl = \u6BB5\u968E:
+dlg.summary_tab = \u8981\u7D04
+dlg.unnamed_lbl = <<\u7121\u540D\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8>>
+dlg.unsuppress_btn = \u6291\u6B62\u89E3\u9664
+dlg.up_btn = \u4E0A\u3078
+dlg.warning_ttl = \u8B66\u544A!
+dlg.xmlsavedbugs_lbl = \u30D0\u30B0\u4FDD\u5B58 XML \u30D5\u30A1\u30A4\u30EB
+dlg.yes_btn = \u306F\u3044
+
+err.missing_code = \u30A8\u30E9\u30FC: \u30AD\u30FC\u306B\u5BFE\u3059\u308B\u30D0\u30B0\u30FB\u30B3\u30FC\u30C9\u304C\u6B20\u843D
+err.missing_pattern = \u30A8\u30E9\u30FC: \u30AD\u30FC\u306B\u5BFE\u3059\u308B\u30D0\u30B0\u30FB\u30D1\u30BF\u30FC\u30F3\u304C\u6B20\u843D
+
+file.accepted_extensions = \u30AF\u30E9\u30B9\u30FB\u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB (*.jar, *.war, *.ear, *.zip, *.sar)
+
+menu.about_fb = FindBugs \u306B\u3064\u3044\u3066...
+menu.about_item = FindBug\u306B\u3064\u3044\u3066(&A)...
+menu.addRemoveFiles = \u30D5\u30A1\u30A4\u30EB\u306E\u8FFD\u52A0/\u9664\u53BB...
+menu.bugdetails_item = \u30D0\u30B0\u306E\u8A73\u7D30(&D)
+menu.changeDesignation = \u6307\u5B9A\u306E\u5909\u66F4
+menu.change_designation = \u30D0\u30B0\u540D\u79F0\u306E\u5909\u66F4
+menu.check_for_updates = \u66F4\u65B0\u306E\u78BA\u8A8D(&U)...
+menu.closeProject = \u9589\u3058\u308B(&C)
+menu.close_item = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u9589\u3058\u308B(&C)
+menu.collapse = \u7E2E\u5C0F
+menu.configure_item = \u30C7\u30A3\u30C6\u30AF\u30BF\u30FC\u306E\u69CB\u6210(&C)
+menu.console_item = \u30B3\u30F3\u30BD\u30FC\u30EB(&C)
+menu.designation = \u540D\u79F0(&D)
+menu.down = \u4E0B\u3078
+menu.edit_menu = \u7DE8\u96C6(&E)
+menu.effort_menu = \u8A66\u884C
+menu.empty_item = \u7A7A
+menu.exit = \u7D42\u4E86
+menu.exit_item = \u7D42\u4E86(&X)
+menu.expand = \u5C55\u958B
+menu.exppriority_item = \u512A\u5148\u5EA6 (\u5B9F\u9A13\u7684)
+menu.file_menu = \u30D5\u30A1\u30A4\u30EB(&F)
+menu.filterBugsLikeThis = \u3053\u306E\u3088\u3046\u306A\u30D0\u30B0\u3092\u30D5\u30A3\u30EB\u30BF\u30FC\u3059\u308B...
+menu.filterTheseBugs = \u30D0\u30B0\u3092\u30D5\u30A3\u30EB\u30BF\u30FC\u3059\u308B
+menu.filter_bugs = \u3053\u306E\u3088\u3046\u306A\u30D0\u30B0\u3092\u30D5\u30A3\u30EB\u30BF\u30FC\u3059\u308B
+menu.filter_these_bugs = \u30D0\u30B0\u3092\u30D5\u30A3\u30EB\u30BF\u30FC\u3059\u308B
+menu.filtersAndSupressions = \u30D5\u30A3\u30EB\u30BF\u30FC/\u6291\u6B62
+menu.filterwarnings_menu = \u8B66\u544A\u3092\u30D5\u30A3\u30EB\u30BF\u30FC\u3059\u308B
+menu.fulldescriptions_item = \u5B8C\u5168\u306A\u8AAC\u660E(&F)
+menu.go_to_line = \u6307\u5B9A\u884C\u3078\u79FB\u52D5...
+menu.gotoLine = \u6307\u5B9A\u884C\u3078\u79FB\u52D5...
+menu.help_menu = \u30D8\u30EB\u30D7(&H)
+menu.highpriority_item = \u512A\u5148\u5EA6 (\u9AD8)
+menu.loadbugs_item = \u5206\u6790\u306E\u30ED\u30FC\u30C9(&L)...
+menu.lowpriority_item = \u512A\u5148\u5EA6 (\u4F4E)
+menu.maxeffort_item = \u6700\u5927
+menu.mediumpriority_item = \u512A\u5148\u5EA6 (\u4E2D)
+menu.mergeAnalysis = \u5206\u6790\u3092\u30DE\u30FC\u30B8...
+menu.mineffort_item = \u6700\u5C0F
+menu.navigation = \u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3(&N)
+menu.new_item = \u65B0\u898F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8(&N)...
+menu.normaleffort_item = \u6A19\u6E96
+menu.open_item = \u958B\u304F(&O)...
+menu.preferences_menu = \u8A2D\u5B9A(&P)...
+menu.recent_menu = \u6700\u8FD1\u4F7F\u7528\u3057\u305F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8(&E)
+menu.recent_projects_menu = \u6700\u8FD1\u4F7F\u7528\u3057\u305F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8
+menu.reconfig = \u518D\u69CB\u6210...
+menu.reload_item = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u518D\u30ED\u30FC\u30C9(&R)
+menu.rerunAnalysis = \u5206\u6790\u306E\u3084\u308A\u76F4\u3057
+menu.save_item = \u4FDD\u5B58(&S)
+menu.saveas_item = \u5225\u540D\u3067\u4FDD\u5B58(&A)...
+menu.savebugs_item = \u5206\u6790\u306E\u4FDD\u5B58(&A)...
+menu.selectall_item = \u3059\u3079\u3066\u9078\u629E(&A)
+menu.settings_menu = \u8A2D\u5B9A(&S)
+menu.sortConfiguration = \u30D0\u30B0\u3092\u30B0\u30EB\u30FC\u30D7\u5316...
+menu.suppress = \u3053\u306E\u30D0\u30B0\u3092\u6291\u6B62
+menu.suppress_bug = \u3053\u306E\u30D0\u30B0\u3092\u6291\u6B62
+menu.up = \u4E0A\u3078
+menu.view_menu = \u8868\u793A(&V)
+menu.viewbugs_item = \u30D0\u30B0\u306E\u8868\u793A
+menu.viewprojectdetails_item = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u8A73\u7D30\u306E\u8868\u793A
+
+mode.at_or_after = \u4EE5\u964D
+mode.at_or_before = \u4EE5\u524D
+mode.equal_to = \u7B49\u3057\u3044
+mode.not_equal_to = \u7B49\u3057\u304F\u306A\u3044
+
+msg.addRemoveFiles = \u30D5\u30A1\u30A4\u30EB\u306E\u8FFD\u52A0/\u524A\u9664...
+msg.addarchiveordirectory_txt = \u30A2\u30FC\u30AB\u30A4\u30D6\u307E\u305F\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC\u3092\u8FFD\u52A0
+msg.analysingclasses_txt = \u30AF\u30E9\u30B9\u3092\u5206\u6790\u4E2D
+msg.analysiscancelled_txt = {0} \u306E\u5206\u6790\u306F\u30E6\u30FC\u30B6\u30FC\u306B\u3088\u308A\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F
+msg.analysiscompleted_txt = {0} \u306E\u5206\u6790\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F
+msg.analyze_txt = \u5206\u6790
+msg.beginninganalysis_txt = {0} \u306E\u5206\u6790\u3092\u958B\u59CB\u3057\u307E\u3059
+msg.bugpatternsreported_txt = \u5831\u544A\u3055\u308C\u305F\u30D0\u30B0\u30FB\u30D1\u30BF\u30FC\u30F3
+msg.cancelanalysis_txt = \u5206\u6790\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3059\u304B?
+msg.confirm_save_txt = \u4FDD\u5B58\u3057\u307E\u3059\u304B?
+msg.couldnotopenproject_txt = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C\u958B\u3051\u306A\u304B\u3063\u305F: {0}
+msg.couldntload_txt = {0} \u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
+msg.error_txt = \u30A8\u30E9\u30FC:
+msg.errorformatting_txt = \u30D0\u30B0\u306B\u5BFE\u3059\u308B\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u51E6\u7406\u3067\u30A8\u30E9\u30FC: {0}
+msg.exp_txt = \u5B9F\u9A13\u6BB5\u968E:
+msg.failedtotransform_txt = \u8981\u7D04\u306E\u5909\u63DB\u306B\u5931\u6557: {0}
+msg.fatalanalysisexception_txt = \u81F4\u547D\u7684\u306A\u5206\u6790\u4F8B\u5916: {0}
+msg.finishedanalysis_txt = \u5206\u6790\u7D42\u4E86
+msg.loading_bugs_over_network_txt = \u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u4E0A\u304B\u3089\u30D0\u30B0\u3092\u30ED\u30FC\u30C9\u3059\u308B...
+msg.newproject_txt = \u65B0\u898F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8
+msg.nosource_txt = \u5229\u7528\u3067\u304D\u306A\u3044\u30BD\u30FC\u30B9
+msg.openproject_txt = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u958B\u304F...
+msg.projectnojars_txt = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8 {0} \u306F\u3001\u9078\u629E\u3055\u308C\u305F\u30AF\u30E9\u30B9\u30FB\u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093
+msg.saveproject_txt = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u4FDD\u5B58
+msg.saveprojectas_txt = \u5225\u540D\u3067\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58
+msg.saveprojectquery_txt = \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58\u3057\u307E\u3059\u304B?
+msg.scanningarchives_txt = \u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u30B9\u30AD\u30E3\u30F3\u4E2D
+msg.userelativepaths_txt = \u76F8\u5BFE\u30D1\u30B9\u3092\u4F7F\u7528
+msg.warning_txt = \u8B66\u544A:
+msg.without_saving_txt = \u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u4FDD\u5B58\u3057\u307E\u3059\u304B?
+msg.you_are_closing_txt = \u9589\u3058\u3066\u3044\u307E\u3059
+msg.you_are_closing_without_saving_txt = \u4FDD\u5B58\u305B\u305A\u306B\u9589\u3058\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059\u3002\u4FDD\u5B58\u3057\u307E\u3059\u304B?
+# The following three properties are not needed any more.
+msg.you_are_loading_txt = \u30ED\u30FC\u30C9\u4E2D\u3067\u3059
+# instead, the following two are used
+msg.you_are_loading_without_saving_txt = \u4FDD\u5B58\u305B\u305A\u306B\u30ED\u30FC\u30C9\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059\u3002\u4FDD\u5B58\u3057\u307E\u3059\u304B?
+
+msg_addsource_lbl = \u30BD\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FC\u307E\u305F\u306F\u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u8FFD\u52A0
+
+pref.close = \u9589\u3058\u308B
+pref.comments = \u30EC\u30D3\u30E5\u30FC
+pref.description = \u8AAC\u660E
+pref.filters = \u30D5\u30A3\u30EB\u30BF\u30FC
+pref.name = \u540D\u524D
+pref.suppressions = \u30D0\u30B0\u6291\u6B62
+pref.suppressions_tab = \u6291\u6B62
+pref.type = \u30BF\u30A4\u30D7
+
+progress.analyzing_classes = \u30AF\u30E9\u30B9\u3092\u5206\u6790\u4E2D...
+progress.finishing_analysis = \u5206\u6790\u3092\u7D42\u4E86\u4E2D...
+progress.scanning_archives = \u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u30B9\u30AD\u30E3\u30F3\u4E2D...
+
+sort.bug_kind = \u30D0\u30B0\u7A2E\u985E
+sort.bug_pattern = \u30D0\u30B0\u30FB\u30D1\u30BF\u30FC\u30F3
+sort.category = \u30AB\u30C6\u30B4\u30EA\u30FC
+sort.class = \u30AF\u30E9\u30B9
+sort.designation = \u540D\u79F0
+sort.divider = [\u4ED5\u5207\u308A]
+sort.first_version = \u521D\u56DE\u30D0\u30FC\u30B8\u30E7\u30F3
+sort.first_version_not_defined = \u521D\u56DE\u30D0\u30FC\u30B8\u30E7\u30F3\u304C\u672A\u5B9A\u7FA9
+sort.last_version = \u6700\u7D42\u30D0\u30FC\u30B8\u30E7\u30F3
+sort.last_version_not_defined = \u6700\u7D42\u30D0\u30FC\u30B8\u30E7\u30F3\u304C\u672A\u5B9A\u7FA9
+sort.package = \u30D1\u30C3\u30B1\u30FC\u30B8
+sort.priority = \u4FE1\u983C\u6027
+sort.priority_experimental = \u512A\u5148\u5EA6 (\u5B9F\u9A13\u7684)
+sort.priority_high = \u512A\u5148\u5EA6 (\u9AD8)
+sort.priority_ignore = \u7121\u8996
+sort.priority_low = \u512A\u5148\u5EA6 (\u4F4E)
+sort.priority_normal = \u512A\u5148\u5EA6 (\u4E2D)
+
+statusbar.bug_hidden = \u96A0\u3055\u308C\u305F\u30D0\u30B0 (\u30D3\u30E5\u30FC\u30FB\u30E1\u30CB\u30E5\u30FC\u53C2\u7167)
+statusbar.bugs_hidden = \u96A0\u3055\u308C\u305F\u30D0\u30B0 (\u30D3\u30E5\u30FC\u30FB\u30E1\u30CB\u30E5\u30FC\u53C2\u7167)
+
+summary.line = \u884C
+summary.lines = \u884C
+summary.null = null
+summary.source_code = \u30BD\u30FC\u30B9\u30FB\u30B3\u30FC\u30C9\u3002
+
+summary_line = \u884C
+
+summary_lines = \u884C
+
+tooltip.click_to_go_to = \u30AF\u30EA\u30C3\u30AF\u3057\u3066\u79FB\u52D5
+tooltip.enter_comments = \u3053\u306E\u30D0\u30B0\u306B\u3064\u3044\u3066\u306E\u30B3\u30E1\u30F3\u30C8\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+tooltip.reorder_message = \u30C9\u30E9\u30C3\u30B0\u3059\u308B\u3068\u30D5\u30A9\u30EB\u30C0\u30FC\u30FB\u30C4\u30EA\u30FC\u3068\u30BD\u30FC\u30C8\u9806\u3092\u4E26\u3079\u66FF\u3048\u307E\u3059
+
+tree.bugs = \u30D0\u30B0
+
+txt.copy = \u30B3\u30D4\u30FC
+txt.cut = \u5207\u308A\u53D6\u308A
+txt.paste = \u8CBC\u308A\u4ED8\u3051
+
+view.bug_summary = \u30D0\u30B0\u8981\u7D04
+view.bugs = \u30D0\u30B0
+view.comments = \u30EC\u30D3\u30E5\u30FC
+view.source = \u30BD\u30FC\u30B9
diff --git a/src/java/edu/umd/cs/findbugs/gui2/CloudCommentsPaneSwing.java b/src/java/edu/umd/cs/findbugs/gui2/CloudCommentsPaneSwing.java
index 5135276..9887192 100644
--- a/src/java/edu/umd/cs/findbugs/gui2/CloudCommentsPaneSwing.java
+++ b/src/java/edu/umd/cs/findbugs/gui2/CloudCommentsPaneSwing.java
@@ -1,71 +1,74 @@
-package edu.umd.cs.findbugs.gui2;
-
-import java.awt.Dimension;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.List;
-
-import javax.swing.JButton;
-import javax.swing.JPopupMenu;
-import javax.swing.JRadioButtonMenuItem;
-
-import org.apache.commons.lang.StringUtils;
-
-import edu.umd.cs.findbugs.cloud.CloudPlugin;
-
-public class CloudCommentsPaneSwing extends CloudCommentsPane {
-
-
- @Override
- public Dimension getPreferredSize() {
- return super.getMinimumSize();
-
- }
-
- @Override
- protected void setupLinksOrButtons() {
- signInOutLink = new JButton("Sign in");
- ((JButton)signInOutLink).addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- signInOrOutClicked();
- }
- });
- cancelLink = new JButton("Cancel");
- ((JButton) cancelLink).addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- cancelClicked();
- }
- });
- }
-
- @Override
- protected boolean isDisabled(CloudPlugin plugin) {
- return false;
- }
-
- @Override
- protected void showCloudChooser(List<CloudPlugin> plugins, List<String> descriptions) {
- JPopupMenu popup = new JPopupMenu();
- for (int i = 0; i < plugins.size(); i++) {
- final CloudPlugin plugin = plugins.get(i);
- String id = _bugCollection.getCloud().getPlugin().getId();
- String thisid = plugin.getId();
- boolean selected = id.equals(thisid);
- JRadioButtonMenuItem item = new JRadioButtonMenuItem(descriptions.get(i), selected);
- item.setToolTipText(plugin.getDetails());
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- changeCloud(plugin.getId());
- }
- });
- popup.add(item);
- }
- popup.show(signInOutLink, 0, signInOutLink.getHeight() + 5);
- }
-
- @Override
- protected void setSignInOutText(String buttonText) {
- ((JButton) signInOutLink).setText(StringUtils.capitalize(buttonText));
- }
-
-}
+package edu.umd.cs.findbugs.gui2;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JPopupMenu;
+import javax.swing.JRadioButtonMenuItem;
+
+import org.apache.commons.lang.StringUtils;
+
+import edu.umd.cs.findbugs.cloud.CloudPlugin;
+
+public class CloudCommentsPaneSwing extends CloudCommentsPane {
+
+
+ @Override
+ public Dimension getPreferredSize() {
+ return super.getMinimumSize();
+
+ }
+
+ @Override
+ protected void setupLinksOrButtons() {
+ signInOutLink = new JButton("Sign in");
+ ((JButton)signInOutLink).addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ signInOrOutClicked();
+ }
+ });
+ cancelLink = new JButton("Cancel");
+ ((JButton) cancelLink).addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ cancelClicked();
+ }
+ });
+ }
+
+ @Override
+ protected boolean isDisabled(CloudPlugin plugin) {
+ return false;
+ }
+
+ @Override
+ protected void showCloudChooser(List<CloudPlugin> plugins, List<String> descriptions) {
+ JPopupMenu popup = new JPopupMenu();
+ for (int i = 0; i < plugins.size(); i++) {
+ final CloudPlugin plugin = plugins.get(i);
+ String id = _bugCollection.getCloud().getPlugin().getId();
+ String thisid = plugin.getId();
+ boolean selected = id.equals(thisid);
+ JRadioButtonMenuItem item = new JRadioButtonMenuItem(descriptions.get(i), selected);
+ item.setToolTipText(plugin.getDetails());
+ item.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ changeCloud(plugin.getId());
+ }
+ });
+ popup.add(item);
+ }
+ popup.show(signInOutLink, 0, signInOutLink.getHeight() + 5);
+ }
+
+ @Override
+ protected void setSignInOutText(String buttonText) {
+ ((JButton) signInOutLink).setText(StringUtils.capitalize(buttonText));
+ }
+
+}
diff --git a/src/java/edu/umd/cs/findbugs/internalAnnotations/DottedClassName.java b/src/java/edu/umd/cs/findbugs/internalAnnotations/DottedClassName.java
index 0c154fc..f348d61 100644
--- a/src/java/edu/umd/cs/findbugs/internalAnnotations/DottedClassName.java
+++ b/src/java/edu/umd/cs/findbugs/internalAnnotations/DottedClassName.java
@@ -29,7 +29,7 @@ import javax.annotation.meta.When;
/**
* Denotes a class name or package name where the . character is used to
* separate package/class name components.
- *
+ *
* @author pugh
*/
@Documented
diff --git a/src/java/edu/umd/cs/findbugs/internalAnnotations/SlashedClassName.java b/src/java/edu/umd/cs/findbugs/internalAnnotations/SlashedClassName.java
index a10b44b..1295a6d 100644
--- a/src/java/edu/umd/cs/findbugs/internalAnnotations/SlashedClassName.java
+++ b/src/java/edu/umd/cs/findbugs/internalAnnotations/SlashedClassName.java
@@ -53,16 +53,20 @@ public @interface SlashedClassName {
final static Pattern pattern = Pattern.compile(slashedClassName);
+ @Override
@Nonnull
public When forConstantValue(@Nonnull SlashedClassName annotation, Object value) {
- if (!(value instanceof String))
+ if (!(value instanceof String)) {
return When.UNKNOWN;
+ }
- if (pattern.matcher((String) value).matches())
+ if (pattern.matcher((String) value).matches()) {
return When.ALWAYS;
+ }
- if (value.equals(NOT_AVAILABLE))
+ if (value.equals(NOT_AVAILABLE)) {
return When.MAYBE;
+ }
return When.NEVER;
diff --git a/src/java/edu/umd/cs/findbugs/io/IO.java b/src/java/edu/umd/cs/findbugs/io/IO.java
index ef1e1ea..a2ec357 100644
--- a/src/java/edu/umd/cs/findbugs/io/IO.java
+++ b/src/java/edu/umd/cs/findbugs/io/IO.java
@@ -80,15 +80,16 @@ public class IO {
static byte[] copyOf(byte[] original, int newLength) {
byte[] copy = new byte[newLength];
System.arraycopy(original, 0, copy, 0,
- Math.min(original.length, newLength));
+ Math.min(original.length, newLength));
return copy;
}
public static byte[] readAll(@WillClose InputStream in, int size) throws IOException {
try {
- if (size == 0)
+ if (size == 0) {
throw new IllegalArgumentException();
+ }
byte[] result = new byte[size];
int pos = 0;
while (true) {
@@ -97,11 +98,13 @@ public class IO {
pos += sz;
}
- if (pos < size)
+ if (pos < size) {
return copyOf(result, pos);
+ }
int nextByte = in.read();
- if (nextByte == -1)
+ if (nextByte == -1) {
return result;
+ }
size = size * 2 + 500;
result = copyOf(result, size);
result[pos++] = (byte) nextByte;
@@ -128,7 +131,7 @@ public class IO {
public static long copy(@WillNotClose InputStream in, @WillNotClose OutputStream out, long maxBytes)
- throws IOException {
+ throws IOException {
long total = 0;
int sz = 0;
@@ -146,7 +149,7 @@ public class IO {
public static long copy(Reader in, Writer out, long maxChars)
- throws IOException {
+ throws IOException {
long total = 0;
int sz;
@@ -165,7 +168,7 @@ public class IO {
* Close given InputStream, ignoring any resulting exception.
*
*/
- public static void close(@CheckForNull Closeable c) {
+ public static void close(@CheckForNull Closeable c) {
if (c == null) {
return;
}
@@ -229,21 +232,24 @@ public class IO {
* if in.skip throws an IOException
*/
public static void skipFully(InputStream in, long bytes) throws IOException {
- if (bytes < 0)
+ if (bytes < 0) {
throw new IllegalArgumentException("Can't skip " + bytes + " bytes");
+ }
long remaining = bytes;
while (remaining > 0) {
long skipped = in.skip(remaining);
- if (skipped <= 0)
+ if (skipped <= 0) {
throw new EOFException("Reached EOF while trying to skip a total of " + bytes);
+ }
remaining -= skipped;
}
}
public static boolean verifyURL(URL u) {
- if (u == null)
+ if (u == null) {
return false;
+ }
InputStream i = null;
diff --git a/src/java/edu/umd/cs/findbugs/io/SlowInputStream.java b/src/java/edu/umd/cs/findbugs/io/SlowInputStream.java
index a0b79de..47fbcf1 100644
--- a/src/java/edu/umd/cs/findbugs/io/SlowInputStream.java
+++ b/src/java/edu/umd/cs/findbugs/io/SlowInputStream.java
@@ -24,11 +24,11 @@ import java.io.IOException;
import java.io.InputStream;
public class SlowInputStream extends FilterInputStream {
- private long started = System.currentTimeMillis();
+ private final long started = System.currentTimeMillis();
private long length = 0;
- private int bytesPerSecond;
+ private final int bytesPerSecond;
public SlowInputStream(InputStream in, int baudRate) {
super(in);
@@ -49,8 +49,9 @@ public class SlowInputStream extends FilterInputStream {
@Override
public int read() throws IOException {
int b = in.read();
- if (b >= 0)
+ if (b >= 0) {
length++;
+ }
delay();
return b;
}
@@ -62,8 +63,9 @@ public class SlowInputStream extends FilterInputStream {
@Override
public int read(byte[] b, int off, int len) throws IOException {
- if (len > bytesPerSecond / 10)
+ if (len > bytesPerSecond / 10) {
len = bytesPerSecond / 10;
+ }
int tmp = in.read(b, off, len);
if (tmp >= 0) {
length += tmp;
@@ -75,8 +77,9 @@ public class SlowInputStream extends FilterInputStream {
@Override
public long skip(long n) throws IOException {
n = in.skip(n);
- if (n >= 0)
+ if (n >= 0) {
length += n;
+ }
delay();
return n;
}
diff --git a/src/java/edu/umd/cs/findbugs/jaif/JAIFEnumConstant.java b/src/java/edu/umd/cs/findbugs/jaif/JAIFEnumConstant.java
index 506c1d6..8495fd3 100644
--- a/src/java/edu/umd/cs/findbugs/jaif/JAIFEnumConstant.java
+++ b/src/java/edu/umd/cs/findbugs/jaif/JAIFEnumConstant.java
@@ -23,7 +23,7 @@ package edu.umd.cs.findbugs.jaif;
* @author David Hovemeyer
*/
public class JAIFEnumConstant {
- private String name;
+ private final String name;
public JAIFEnumConstant(String name) {
this.name = name;
@@ -38,7 +38,7 @@ public class JAIFEnumConstant {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/jaif/JAIFEvents.java b/src/java/edu/umd/cs/findbugs/jaif/JAIFEvents.java
index 30b34cc..ec769d4 100644
--- a/src/java/edu/umd/cs/findbugs/jaif/JAIFEvents.java
+++ b/src/java/edu/umd/cs/findbugs/jaif/JAIFEvents.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.jaif;
/**
* Callbacks for parsing an extenal annotation file.
- *
+ *
* @author David Hovemeyer
* @see <a
* href="http://groups.csail.mit.edu/pag/jsr308/annotation-file-utilities/">Annotation
@@ -31,7 +31,7 @@ public interface JAIFEvents {
/**
* Called to indicate the start of a package definition.
- *
+ *
* @param pkgName
* package name
*/
@@ -39,14 +39,14 @@ public interface JAIFEvents {
/**
* Called to indicate the end of a package definition.
- *
+ *
* @param pkgName
*/
void endPackageDefinition(String pkgName);
/**
* Called to indicate the start of an annotation.
- *
+ *
* @param annotationName
* annotation name
*/
@@ -54,7 +54,7 @@ public interface JAIFEvents {
/**
* Called to indicate the end of an annotation.
- *
+ *
* @param annotationName
* annotation name
*/
@@ -62,7 +62,7 @@ public interface JAIFEvents {
/**
* Called to visit an annotation field.
- *
+ *
* @param fieldName
* annotation field name
* @param constant
@@ -73,7 +73,7 @@ public interface JAIFEvents {
/**
* Called to indicate the start of an annotation definition.
- *
+ *
* @param annotationName
* name of the annotation
* @param retention
@@ -83,7 +83,7 @@ public interface JAIFEvents {
/**
* Called to indicate the end of an annotation definition.
- *
+ *
* @param annotationName
* name of the annotation
*/
@@ -91,7 +91,7 @@ public interface JAIFEvents {
/**
* Called to visit an annotation field definition.
- *
+ *
* @param type
* type of the annotation field (in JVM signature format)
* @param fieldName
diff --git a/src/java/edu/umd/cs/findbugs/jaif/JAIFParser.java b/src/java/edu/umd/cs/findbugs/jaif/JAIFParser.java
index 14d7a91..41baf85 100644
--- a/src/java/edu/umd/cs/findbugs/jaif/JAIFParser.java
+++ b/src/java/edu/umd/cs/findbugs/jaif/JAIFParser.java
@@ -27,16 +27,16 @@ import edu.umd.cs.findbugs.charsets.UTF8;
/**
* Parse an external annotation file.
- *
+ *
* @author David Hovemeyer
* @see <a
* href="http://groups.csail.mit.edu/pag/jsr308/annotation-file-utilities/">Annotation
* File Utilities/</a>
*/
public class JAIFParser {
- private JAIFScanner scanner;
+ private final JAIFScanner scanner;
- private JAIFEvents callback;
+ private final JAIFEvents callback;
public JAIFParser(Reader reader, JAIFEvents callback) {
this.scanner = new JAIFScanner(reader);
@@ -128,11 +128,11 @@ public class JAIFParser {
private String readType() throws IOException, JAIFSyntaxException {
StringBuilder buf = new StringBuilder();
- JAIFToken t = expect(JAIFTokenKind.IDENTIFIER_OR_KEYWORD);
-
- if (t.lexeme.equals("enum")) {
+ /*JAIFToken t = */expect(JAIFTokenKind.IDENTIFIER_OR_KEYWORD);
- }
+ // if (t.lexeme.equals("enum")) {
+ //
+ // }
return buf.toString();
}
@@ -173,7 +173,7 @@ public class JAIFParser {
while (!scanner.atEOF()) {
t = scanner.peekToken();
- if (t.lexeme.equals("package")) {
+ if ("package".equals(t.lexeme)) {
break;
}
@@ -322,9 +322,9 @@ public class JAIFParser {
private void parseAnnotationDefinitionOrClassDefinition() throws IOException, JAIFSyntaxException {
JAIFToken t = scanner.peekToken();
- if (t.lexeme.equals("annotation")) {
+ if ("annotation".equals(t.lexeme)) {
parseAnnotationDefinition();
- } else if (t.lexeme.equals("class")) {
+ } else if ("class".equals(t.lexeme)) {
parseClassDefinition();
} else {
throw new JAIFSyntaxException(this, "Unexpected token " + t + " (expected `annotation' or `class')");
@@ -337,7 +337,7 @@ public class JAIFParser {
String retention = null;
JAIFToken t = scanner.peekToken();
- if (t.lexeme.equals("visible") || t.lexeme.equals("invisible") || t.lexeme.equals("source")) {
+ if ("visible".equals(t.lexeme) || "invisible".equals(t.lexeme) || "source".equals(t.lexeme)) {
retention = t.lexeme;
scanner.nextToken();
}
@@ -373,31 +373,39 @@ public class JAIFParser {
}
JAIFEvents callback = new JAIFEvents() {
+ @Override
public void annotationField(String fieldName, Object constant) {
System.out.println(" " + fieldName + "=" + constant);
}
+ @Override
public void endAnnotation(String annotationName) {
}
+ @Override
public void endPackageDefinition(String pkgName) {
}
+ @Override
public void startAnnotation(String annotationName) {
System.out.println(" annotation " + annotationName);
}
+ @Override
public void startPackageDefinition(String pkgName) {
System.out.println("package " + pkgName);
}
+ @Override
public void startAnnotationDefinition(String annotationName, String retention) {
System.out.println(" annotation " + annotationName + " " + retention);
}
+ @Override
public void endAnnotationDefinition(String annotationName) {
}
+ @Override
public void annotationFieldDefinition(String type, String fieldName) {
System.out.println(" " + type + " " + fieldName);
}
diff --git a/src/java/edu/umd/cs/findbugs/jaif/JAIFScanner.java b/src/java/edu/umd/cs/findbugs/jaif/JAIFScanner.java
index 7027cb0..35f420e 100644
--- a/src/java/edu/umd/cs/findbugs/jaif/JAIFScanner.java
+++ b/src/java/edu/umd/cs/findbugs/jaif/JAIFScanner.java
@@ -27,7 +27,7 @@ import java.util.regex.Pattern;
/**
* Lexical scanner for external annotation files.
- *
+ *
* @author David Hovemeyer
* @see <a
* href="http://groups.csail.mit.edu/pag/jsr308/annotation-file-utilities/">Annotation
@@ -36,9 +36,9 @@ import java.util.regex.Pattern;
public class JAIFScanner {
static class TokenPattern {
- private Pattern pattern;
+ private final Pattern pattern;
- private JAIFTokenKind kind;
+ private final JAIFTokenKind kind;
public TokenPattern(String regex, JAIFTokenKind kind) {
this.pattern = Pattern.compile("^" + regex);
@@ -90,9 +90,9 @@ public class JAIFScanner {
private static final String INT_TYPE_SUFFIX_OPT = "[Ll]?";
private static final String INPUT_CHAR = "[^\\\\\\\"]";// anything other
- // than backslash or
- // double-quote
- // character
+ // than backslash or
+ // double-quote
+ // character
private static final String OCT_ESCAPE = "([0-7]|[0-3]?[0-7][0-7])";
@@ -101,35 +101,35 @@ public class JAIFScanner {
private static final String STRING_CHARS_OPT = "(" + INPUT_CHAR + "|" + ESCAPE_SEQ + ")*";
private static final TokenPattern[] TOKEN_PATTERNS = {
- // Misc. syntax
- new TokenPattern(":", JAIFTokenKind.COLON),
- new TokenPattern("\\(", JAIFTokenKind.LPAREN),
- new TokenPattern("\\)", JAIFTokenKind.RPAREN),
- new TokenPattern(",", JAIFTokenKind.COMMA),
- new TokenPattern("=", JAIFTokenKind.EQUALS),
+ // Misc. syntax
+ new TokenPattern(":", JAIFTokenKind.COLON),
+ new TokenPattern("\\(", JAIFTokenKind.LPAREN),
+ new TokenPattern("\\)", JAIFTokenKind.RPAREN),
+ new TokenPattern(",", JAIFTokenKind.COMMA),
+ new TokenPattern("=", JAIFTokenKind.EQUALS),
- // Identifiers and keywords
- new TokenPattern(ID_START + "(" + ID_REST + ")*", JAIFTokenKind.IDENTIFIER_OR_KEYWORD),
+ // Identifiers and keywords
+ new TokenPattern(ID_START + "(" + ID_REST + ")*", JAIFTokenKind.IDENTIFIER_OR_KEYWORD),
- // FP literals
- new TokenPattern(DIGITS + DOT + DIGITS_OPT + EXP_PART_OPT + FLOAT_TYPE_SUFFIX_OPT,
- JAIFTokenKind.FLOATING_POINT_LITERAL),
- new TokenPattern(DOT + DIGITS + EXP_PART_OPT + FLOAT_TYPE_SUFFIX_OPT, JAIFTokenKind.FLOATING_POINT_LITERAL),
- new TokenPattern(DIGITS + EXP_PART + FLOAT_TYPE_SUFFIX_OPT, JAIFTokenKind.FLOATING_POINT_LITERAL),
- new TokenPattern(DIGITS + EXP_PART_OPT + FLOAT_TYPE_SUFFIX, JAIFTokenKind.FLOATING_POINT_LITERAL),
+ // FP literals
+ new TokenPattern(DIGITS + DOT + DIGITS_OPT + EXP_PART_OPT + FLOAT_TYPE_SUFFIX_OPT,
+ JAIFTokenKind.FLOATING_POINT_LITERAL),
+ new TokenPattern(DOT + DIGITS + EXP_PART_OPT + FLOAT_TYPE_SUFFIX_OPT, JAIFTokenKind.FLOATING_POINT_LITERAL),
+ new TokenPattern(DIGITS + EXP_PART + FLOAT_TYPE_SUFFIX_OPT, JAIFTokenKind.FLOATING_POINT_LITERAL),
+ new TokenPattern(DIGITS + EXP_PART_OPT + FLOAT_TYPE_SUFFIX, JAIFTokenKind.FLOATING_POINT_LITERAL),
- // This must come after the FP literal patterns
- new TokenPattern(DOT, JAIFTokenKind.DOT),
+ // This must come after the FP literal patterns
+ new TokenPattern(DOT, JAIFTokenKind.DOT),
- // Integer literals
- new TokenPattern("0" + OCTAL_DIGITS + INT_TYPE_SUFFIX_OPT, JAIFTokenKind.OCTAL_LITERAL),
- new TokenPattern(HEX_SIGNIFIER + HEX_DIGITS + INT_TYPE_SUFFIX_OPT, JAIFTokenKind.HEX_LITERAL),
- new TokenPattern(DIGITS + INT_TYPE_SUFFIX_OPT, JAIFTokenKind.DECIMAL_LITERAL),
+ // Integer literals
+ new TokenPattern("0" + OCTAL_DIGITS + INT_TYPE_SUFFIX_OPT, JAIFTokenKind.OCTAL_LITERAL),
+ new TokenPattern(HEX_SIGNIFIER + HEX_DIGITS + INT_TYPE_SUFFIX_OPT, JAIFTokenKind.HEX_LITERAL),
+ new TokenPattern(DIGITS + INT_TYPE_SUFFIX_OPT, JAIFTokenKind.DECIMAL_LITERAL),
- // String literals
- new TokenPattern("\"" + STRING_CHARS_OPT + "\"", JAIFTokenKind.STRING_LITERAL), };
+ // String literals
+ new TokenPattern("\"" + STRING_CHARS_OPT + "\"", JAIFTokenKind.STRING_LITERAL), };
- private BufferedReader reader;
+ private final BufferedReader reader;
private JAIFToken next;
@@ -202,7 +202,7 @@ public class JAIFScanner {
// System.out.println("Consumed " + wsCount +
// " characters of horizontal whitespace");
- if (lineBuf.equals("")) {
+ if ("".equals(lineBuf)) {
// Reached end of line.
next = new JAIFToken(JAIFTokenKind.NEWLINE, "\n", lineNum);
lineBuf = null;
diff --git a/src/java/edu/umd/cs/findbugs/jaif/JAIFToken.java b/src/java/edu/umd/cs/findbugs/jaif/JAIFToken.java
index 01773f9..6902053 100644
--- a/src/java/edu/umd/cs/findbugs/jaif/JAIFToken.java
+++ b/src/java/edu/umd/cs/findbugs/jaif/JAIFToken.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.jaif;
/**
* One lexical token of an external annotations file.
- *
+ *
* @author David Hovemeyer
* @see <a href="http://pag.csail.mit.edu/jsr308/annotation-file-utilities/">
* http://pag.csail.mit.edu/jsr308/annotation-file-utilities/</a>
@@ -31,12 +31,12 @@ class JAIFToken {
String lexeme;
- int lineNum;
+ // int lineNum;
public JAIFToken(JAIFTokenKind kind, String lexeme, int lineNum) {
this.kind = kind;
this.lexeme = lexeme;
- this.lineNum = lineNum;
+ // this.lineNum = lineNum;
// System.out.println("token: " + this);
}
@@ -46,12 +46,12 @@ class JAIFToken {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
- if (lexeme.equals("\n")) {
+ if ("\n".equals(lexeme)) {
return "<newline>";
} else {
return lexeme;
diff --git a/src/java/edu/umd/cs/findbugs/jaif/JAIFTokenKind.java b/src/java/edu/umd/cs/findbugs/jaif/JAIFTokenKind.java
index 166dd93..530d430 100644
--- a/src/java/edu/umd/cs/findbugs/jaif/JAIFTokenKind.java
+++ b/src/java/edu/umd/cs/findbugs/jaif/JAIFTokenKind.java
@@ -22,7 +22,7 @@ package edu.umd.cs.findbugs.jaif;
public enum JAIFTokenKind {
NEWLINE("<newline>"), COLON(":"), DOT("."), IDENTIFIER_OR_KEYWORD("<identifier or keyword>"), LPAREN("("), RPAREN(")"), COMMA(
","), EQUALS("="), OCTAL_LITERAL("<octal literal>"), DECIMAL_LITERAL("<decimal literal>"), HEX_LITERAL(
- "<hex literal>"), FLOATING_POINT_LITERAL("<floating point literal>"), STRING_LITERAL("<string literal>");
+ "<hex literal>"), FLOATING_POINT_LITERAL("<floating point literal>"), STRING_LITERAL("<string literal>");
private String stringRep;
@@ -32,7 +32,7 @@ public enum JAIFTokenKind {
/*
* (non-Javadoc)
- *
+ *
* @see java.lang.Enum#toString()
*/
@Override
diff --git a/src/java/edu/umd/cs/findbugs/log/ConsoleLogger.java b/src/java/edu/umd/cs/findbugs/log/ConsoleLogger.java
index 1089a9e..889df9b 100644
--- a/src/java/edu/umd/cs/findbugs/log/ConsoleLogger.java
+++ b/src/java/edu/umd/cs/findbugs/log/ConsoleLogger.java
@@ -34,7 +34,7 @@ import edu.umd.cs.findbugs.L10N;
*/
public class ConsoleLogger implements Logger {
- private LogSync logSync;
+ private final LogSync logSync;
/**
* Creates a new instance of ConsoleLogger
@@ -43,10 +43,12 @@ public class ConsoleLogger implements Logger {
this.logSync = logSync;
}
+ @Override
public void logMessage(int severity, String message) {
// If this is an error, pass it to the GUI
- if (severity == ERROR)
+ if (severity == ERROR) {
logSync.error(message);
+ }
// Format a message for the console window
Date date = new Date();
@@ -54,10 +56,11 @@ public class ConsoleLogger implements Logger {
buf.append('[');
buf.append(date.toString());
buf.append("] ");
- if (severity == ERROR)
+ if (severity == ERROR) {
buf.append(L10N.getLocalString("msg.error_txt", "ERROR: "));
- else if (severity == WARNING)
+ } else if (severity == WARNING) {
buf.append(L10N.getLocalString("msg.warning_txt", "WARNING: "));
+ }
buf.append(message);
logSync.writeToLog(buf.toString());
}
diff --git a/src/java/edu/umd/cs/findbugs/log/Profiler.java b/src/java/edu/umd/cs/findbugs/log/Profiler.java
index 58779c1..e9f39eb 100644
--- a/src/java/edu/umd/cs/findbugs/log/Profiler.java
+++ b/src/java/edu/umd/cs/findbugs/log/Profiler.java
@@ -27,6 +27,7 @@ import java.util.EmptyStackException;
import java.util.Stack;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@@ -48,8 +49,9 @@ public class Profiler implements XMLWriteable {
public Profiler() {
startTimes = new Stack<Clock>();
profile = new ConcurrentHashMap<Class<?>, Profile>();
- if (REPORT)
+ if (REPORT) {
System.err.println("Profiling activated");
+ }
}
public static interface Filter {
@@ -63,6 +65,7 @@ public class Profiler implements XMLWriteable {
this.minNanoSeconds = minNanoSeconds;
}
+ @Override
public boolean accepts(Profile p) {
long time = p.totalTime.get();
if (time < minNanoSeconds) {
@@ -79,6 +82,7 @@ public class Profiler implements XMLWriteable {
this.minNanoSeconds = minNanoSeconds;
}
+ @Override
public boolean accepts(Profile p) {
int totalCalls = p.totalCalls.get();
long time = p.totalTime.get();
@@ -96,6 +100,7 @@ public class Profiler implements XMLWriteable {
this.minCalls = minCalls;
}
+ @Override
public boolean accepts(Profile p) {
int totalCalls = p.totalCalls.get();
if (totalCalls < minCalls) {
@@ -117,7 +122,7 @@ public class Profiler implements XMLWriteable {
final AtomicLong totalSquareMicroseconds = new AtomicLong();
private final String className;
-
+
Object maxContext;
/**
@@ -134,8 +139,9 @@ public class Profiler implements XMLWriteable {
long oldMax = maxTime.get();
if (nanoTime > oldMax) {
maxTime.compareAndSet(oldMax, nanoTime);
- if (MAX_CONTEXT)
+ if (MAX_CONTEXT) {
maxContext = context;
+ }
}
long microseconds = TimeUnit.MICROSECONDS.convert(nanoTime, TimeUnit.NANOSECONDS);
totalSquareMicroseconds.addAndGet(microseconds * microseconds);
@@ -150,6 +156,7 @@ public class Profiler implements XMLWriteable {
* @throws IOException
*/
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
long time = totalTime.get();
int callCount = totalCalls.get();
@@ -170,8 +177,9 @@ public class Profiler implements XMLWriteable {
xmlOutput.addAttribute("invocations", String.valueOf(callCount));
xmlOutput.addAttribute("avgMicrosecondsPerInvocation", String.valueOf(averageTimeMicros));
xmlOutput.addAttribute("maxMicrosecondsPerInvocation", String.valueOf(maxTimeMicros));
- if (maxContext != null)
- xmlOutput.addAttribute("maxContext", String.valueOf(maxContext));
+ if (maxContext != null) {
+ xmlOutput.addAttribute("maxContext", String.valueOf(maxContext));
+ }
xmlOutput.addAttribute("standardDeviationMircosecondsPerInvocation", String.valueOf(timeStandardDeviation));
xmlOutput.stopTag(true);
}
@@ -202,22 +210,23 @@ public class Profiler implements XMLWriteable {
final Stack<Clock> startTimes;
- final ConcurrentHashMap<Class<?>, Profile> profile;
-
+ final ConcurrentMap<Class<?>, Profile> profile;
+
final Stack<Object> context = new Stack<Object>();
-
+
public void startContext(Object context) {
this.context.push(context);
}
-
+
public void endContext(Object context) {
Object o = this.context.pop();
assert o == context;
}
private Object getContext() {
- if (context.size() == 0)
+ if (context.size() == 0) {
return "";
+ }
try {
return context.peek();
} catch (EmptyStackException e) {
@@ -274,6 +283,7 @@ public class Profiler implements XMLWriteable {
this.profiler = p;
}
+ @Override
public int compare(Class<?> c1, Class<?> c2) {
try {
return c1.getSimpleName().compareTo(c2.getSimpleName());
@@ -281,10 +291,12 @@ public class Profiler implements XMLWriteable {
AnalysisContext.logError("Error comparing " + c1 + " and " + c2, e);
int i1 = System.identityHashCode(c1);
int i2 = System.identityHashCode(c2);
- if (i1 < i2)
+ if (i1 < i2) {
return -1;
- if (i1 > i2)
+ }
+ if (i1 > i2) {
return 1;
+ }
return 0;
}
}
@@ -414,8 +426,9 @@ public class Profiler implements XMLWriteable {
AnalysisContext.logError("Unexpected null profile for " + c.getName(), new NullPointerException());
result = new Profile(c.getName());
Profile tmp = profile.putIfAbsent(c, result);
- if (tmp != null)
+ if (tmp != null) {
return tmp;
+ }
}
return result;
}
@@ -427,25 +440,29 @@ public class Profiler implements XMLWriteable {
* edu.umd.cs.findbugs.xml.XMLWriteable#writeXML(edu.umd.cs.findbugs.xml
* .XMLOutput)
*/
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
xmlOutput.startTag("FindBugsProfile");
xmlOutput.stopTag(false);
TreeSet<Class<?>> treeSet = new TreeSet<Class<?>>(new TotalTimeComparator(this));
treeSet.addAll(profile.keySet());
long totalTime = 0;
- for (Profile p : profile.values())
+ for (Profile p : profile.values()) {
totalTime += p.totalTime.get();
+ }
long accumulatedTime = 0;
for (Class<?> c : treeSet) {
Profile p = getProfile(c);
- if (p == null)
+ if (p == null) {
continue;
+ }
p.writeXML(xmlOutput);
accumulatedTime += p.totalTime.get();
- if (accumulatedTime > 3 * totalTime / 4)
+ if (accumulatedTime > 3 * totalTime / 4) {
break;
+ }
}
xmlOutput.closeTag("FindBugsProfile");
}
diff --git a/src/java/edu/umd/cs/findbugs/log/YourKitController.java b/src/java/edu/umd/cs/findbugs/log/YourKitController.java
index 7fe31ed..5cdbf6a 100644
--- a/src/java/edu/umd/cs/findbugs/log/YourKitController.java
+++ b/src/java/edu/umd/cs/findbugs/log/YourKitController.java
@@ -21,18 +21,26 @@ package edu.umd.cs.findbugs.log;
import java.lang.reflect.Method;
+import edu.umd.cs.findbugs.SystemProperties;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
/**
* @author pugh
*/
public class YourKitController {
+ private static final boolean ENABLED = SystemProperties.getBoolean("findbugs.yourkit.enabled");
+
Object controller;
Method advanceGeneration, captureMemorySnapshot, getStatus;
-
- public static final long ALLOCATION_RECORDING = 2L;
+
+ public static final long ALLOCATION_RECORDING = 2L;
public YourKitController() {
+ if(!ENABLED){
+ return;
+ }
try {
Class<?> c = Class.forName("com.yourkit.api.Controller");
controller = c.newInstance();
@@ -49,18 +57,20 @@ public class YourKitController {
}
public void advanceGeneration(String name) {
- if (controller == null)
+ if (controller == null) {
return;
+ }
try {
advanceGeneration.invoke(controller, name);
- } catch (Exception e) {
+ } catch (Throwable e) {
assert true;
}
}
-
+
public long getStatus() {
- if (getStatus == null)
+ if (getStatus == null) {
return 0;
+ }
try {
return (Long) getStatus.invoke(controller);
} catch (RuntimeException e) {
@@ -70,15 +80,17 @@ public class YourKitController {
}
}
+ @SuppressFBWarnings("DM_GC")
public void captureMemorySnapshot() {
- if (controller == null)
+ if (controller == null) {
return;
+ }
try {
System.gc();
captureMemorySnapshot.invoke(controller);
} catch (RuntimeException e) {
throw e;
- } catch (Exception e) {
+ } catch (Throwable e) {
assert true;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/model/ClassFeatureSet.java b/src/java/edu/umd/cs/findbugs/model/ClassFeatureSet.java
index 44f2c69..7713822 100644
--- a/src/java/edu/umd/cs/findbugs/model/ClassFeatureSet.java
+++ b/src/java/edu/umd/cs/findbugs/model/ClassFeatureSet.java
@@ -42,7 +42,7 @@ import edu.umd.cs.findbugs.xml.XMLWriteable;
/**
* Features of a class which may be used to identify it if it is renamed or
* modified.
- *
+ *
* @author David Hovemeyer
*/
public class ClassFeatureSet implements XMLWriteable {
@@ -58,7 +58,7 @@ public class ClassFeatureSet implements XMLWriteable {
private boolean isInterface;
- private Set<String> featureSet;
+ private final Set<String> featureSet;
/**
* Constructor. Creates an empty feature set.
@@ -74,7 +74,7 @@ public class ClassFeatureSet implements XMLWriteable {
/**
* Initialize from given JavaClass.
- *
+ *
* @param javaClass
* the JavaClass
* @return this object
@@ -113,7 +113,7 @@ public class ClassFeatureSet implements XMLWriteable {
/**
* Determine if given method overrides a superclass or superinterface
* method.
- *
+ *
* @param javaClass
* class defining the method
* @param method
@@ -122,24 +122,27 @@ public class ClassFeatureSet implements XMLWriteable {
* false if not
*/
private boolean overridesSuperclassMethod(JavaClass javaClass, Method method) {
- if (method.isStatic())
+ if (method.isStatic()) {
return false;
+ }
try {
JavaClass[] superclassList = javaClass.getSuperClasses();
if (superclassList != null) {
JavaClassAndMethod match = Hierarchy.findMethod(superclassList, method.getName(), method.getSignature(),
Hierarchy.INSTANCE_METHOD);
- if (match != null)
+ if (match != null) {
return true;
+ }
}
JavaClass[] interfaceList = javaClass.getAllInterfaces();
if (interfaceList != null) {
JavaClassAndMethod match = Hierarchy.findMethod(interfaceList, method.getName(), method.getSignature(),
Hierarchy.INSTANCE_METHOD);
- if (match != null)
+ if (match != null) {
return true;
+ }
}
return false;
@@ -150,22 +153,25 @@ public class ClassFeatureSet implements XMLWriteable {
/**
* Figure out if a class member (field or method) is synthetic.
- *
+ *
* @param member
* a field or method
* @return true if the member is synthetic
*/
private boolean isSynthetic(FieldOrMethod member) {
- if (BCELUtil.isSynthetic(member)) // this never works, but worth a try
+ if (BCELUtil.isSynthetic(member)) {
return true;
+ }
String name = member.getName();
- if (name.startsWith("class$"))
+ if (name.startsWith("class$")) {
return true;
+ }
- if (name.startsWith("access$"))
+ if (name.startsWith("access$")) {
return true;
+ }
return false;
}
@@ -218,7 +224,7 @@ public class ClassFeatureSet implements XMLWriteable {
/**
* Transform a class name by stripping its package name.
- *
+ *
* @param className
* a class name
* @return the transformed class name
@@ -237,7 +243,7 @@ public class ClassFeatureSet implements XMLWriteable {
/**
* Return true if classes in the given package is unlikely to be renamed:
* e.g., because they are part of a public API.
- *
+ *
* @param pkg
* the package name
* @return true if classes in the package is unlikely to be renamed
@@ -249,7 +255,7 @@ public class ClassFeatureSet implements XMLWriteable {
/**
* Transform a method signature to allow it to be compared even if any of
* its parameter types are moved to another package.
- *
+ *
* @param signature
* a method signature
* @return the transformed signature
@@ -274,7 +280,7 @@ public class ClassFeatureSet implements XMLWriteable {
/**
* Transform a field or method parameter signature to allow it to be
* compared even if it is moved to another package.
- *
+ *
* @param signature
* the signature
* @return the transformed signature
@@ -317,11 +323,13 @@ public class ClassFeatureSet implements XMLWriteable {
public static double similarity(ClassFeatureSet a, ClassFeatureSet b) {
// Some features must match exactly
- if (a.isInterface() != b.isInterface())
+ if (a.isInterface() != b.isInterface()) {
return 0.0;
+ }
- if (a.getNumFeatures() < MIN_FEATURES || b.getNumFeatures() < MIN_FEATURES)
+ if (a.getNumFeatures() < MIN_FEATURES || b.getNumFeatures() < MIN_FEATURES) {
return a.getClassName().equals(b.getClassName()) ? EXACT_CLASS_NAME_MATCH : 0.0;
+ }
int numMatch = 0;
int max = Math.max(a.getNumFeatures(), b.getNumFeatures());
@@ -363,11 +371,12 @@ public class ClassFeatureSet implements XMLWriteable {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.xml.XMLWriteable#writeXML(edu.umd.cs.findbugs.xml
* .XMLOutput)
*/
+ @Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
xmlOutput.openTag(ELEMENT_NAME, new XMLAttributeList().addAttribute("class", className));
for (Iterator<String> i = featureIterator(); i.hasNext();) {
diff --git a/src/java/edu/umd/cs/findbugs/model/ClassNameRewriter.java b/src/java/edu/umd/cs/findbugs/model/ClassNameRewriter.java
index 6410948..e11a4a5 100644
--- a/src/java/edu/umd/cs/findbugs/model/ClassNameRewriter.java
+++ b/src/java/edu/umd/cs/findbugs/model/ClassNameRewriter.java
@@ -21,13 +21,13 @@ package edu.umd.cs.findbugs.model;
/**
* Rewrite class names. This is needed for comparing warnings across versions.
- *
+ *
* @author David Hovemeyer
*/
public interface ClassNameRewriter {
/**
* Rewrite a class name.
- *
+ *
* @param className
* a class name
* @return the rewritten class name
diff --git a/src/java/edu/umd/cs/findbugs/model/ClassNameRewriterUtil.java b/src/java/edu/umd/cs/findbugs/model/ClassNameRewriterUtil.java
index 51482a0..86e2aef 100644
--- a/src/java/edu/umd/cs/findbugs/model/ClassNameRewriterUtil.java
+++ b/src/java/edu/umd/cs/findbugs/model/ClassNameRewriterUtil.java
@@ -27,14 +27,14 @@ import edu.umd.cs.findbugs.ba.SignatureParser;
/**
* Utility methods for using a ClassNameRewriter.
- *
+ *
* @author David Hovemeyer
*/
public abstract class ClassNameRewriterUtil {
/**
* Rewrite a method signature.
- *
+ *
* @param classNameRewriter
* a ClassNameRewriter
* @param methodSignature
@@ -63,7 +63,7 @@ public abstract class ClassNameRewriterUtil {
/**
* Rewrite a signature.
- *
+ *
* @param classNameRewriter
* a ClassNameRewriter
* @param signature
@@ -85,7 +85,7 @@ public abstract class ClassNameRewriterUtil {
/**
* Rewrite a MethodAnnotation to update the class name, and any class names
* mentioned in the method signature.
- *
+ *
* @param classNameRewriter
* a ClassNameRewriter
* @param annotation
@@ -105,7 +105,7 @@ public abstract class ClassNameRewriterUtil {
/**
* Rewrite a FieldAnnotation to update the class name and field signature,
* if needed.
- *
+ *
* @param classNameRewriter
* a ClassNameRewriter
* @param annotation
diff --git a/src/java/edu/umd/cs/findbugs/model/IdentityClassNameRewriter.java b/src/java/edu/umd/cs/findbugs/model/IdentityClassNameRewriter.java
index 8997d42..34248d2 100644
--- a/src/java/edu/umd/cs/findbugs/model/IdentityClassNameRewriter.java
+++ b/src/java/edu/umd/cs/findbugs/model/IdentityClassNameRewriter.java
@@ -23,7 +23,7 @@ import java.io.Serializable;
/**
* ClassNameRewriter that leaves classe names unchanged.
- *
+ *
* @author David Hovemeyer
*/
public class IdentityClassNameRewriter implements ClassNameRewriter, Serializable {
@@ -34,7 +34,7 @@ public class IdentityClassNameRewriter implements ClassNameRewriter, Serializabl
/**
* Get the single instance.
- *
+ *
* @return the instance
*/
public static IdentityClassNameRewriter instance() {
@@ -44,9 +44,11 @@ public class IdentityClassNameRewriter implements ClassNameRewriter, Serializabl
/**
* @see edu.umd.cs.findbugs.model.ClassNameRewriter#rewriteClassName(java.lang.String)
*/
+ @Override
public String rewriteClassName(String className) {
- if (className.indexOf('+') >= 0)
+ if (className.indexOf('+') >= 0) {
className = className.replace('+', '$');
+ }
return className;
}
diff --git a/src/java/edu/umd/cs/findbugs/model/MovedClassMap.java b/src/java/edu/umd/cs/findbugs/model/MovedClassMap.java
index d192018..cbf32b4 100644
--- a/src/java/edu/umd/cs/findbugs/model/MovedClassMap.java
+++ b/src/java/edu/umd/cs/findbugs/model/MovedClassMap.java
@@ -35,18 +35,18 @@ import edu.umd.cs.findbugs.SystemProperties;
/**
* Build a map of added class names to removed class names. Serves as a
* ClassNameRewriter that can match up renamed classes in two BugCollections.
- *
+ *
* @author David Hovemeyer
*/
public class MovedClassMap implements ClassNameRewriter {
private static final boolean DEBUG = SystemProperties.getBoolean("movedClasses.debug");
- private BugCollection before;
+ private final BugCollection before;
- private BugCollection after;
+ private final BugCollection after;
- private Map<String, String> rewriteMap;
+ private final Map<String, String> rewriteMap;
public MovedClassMap(BugCollection before, BugCollection after) {
this.before = before;
@@ -76,8 +76,9 @@ public class MovedClassMap implements ClassNameRewriter {
String shortAddedName = getShortClassName(fullAddedName);
String fullRemovedName = removedShortNameToFullNameMap.get(shortAddedName);
if (fullRemovedName != null) {
- if (DEBUG)
+ if (DEBUG) {
System.err.println(fullAddedName + " --> " + fullRemovedName);
+ }
rewriteMap.put(fullAddedName, fullRemovedName);
}
@@ -90,6 +91,7 @@ public class MovedClassMap implements ClassNameRewriter {
return rewriteMap.isEmpty();
}
+ @Override
public String rewriteClassName(String className) {
String rewrittenClassName = rewriteMap.get(className);
if (rewrittenClassName != null) {
@@ -100,7 +102,7 @@ public class MovedClassMap implements ClassNameRewriter {
/**
* Find set of classes referenced in given BugCollection.
- *
+ *
* @param bugCollection
* @return set of classes referenced in the BugCollection
*/
@@ -111,8 +113,9 @@ public class MovedClassMap implements ClassNameRewriter {
BugInstance warning = i.next();
for (Iterator<BugAnnotation> j = warning.annotationIterator(); j.hasNext();) {
BugAnnotation annotation = j.next();
- if (!(annotation instanceof ClassAnnotation))
+ if (!(annotation instanceof ClassAnnotation)) {
continue;
+ }
classSet.add(((ClassAnnotation) annotation).getClassName());
}
}
@@ -122,7 +125,7 @@ public class MovedClassMap implements ClassNameRewriter {
/**
* Build a map of short class names (without package) to full class names.
- *
+ *
* @param classSet
* set of fully-qualified class names
* @return map of short class names to fully-qualified class names
@@ -138,7 +141,7 @@ public class MovedClassMap implements ClassNameRewriter {
/**
* Get a short class name (no package part).
- *
+ *
* @param className
* a class name
* @return short class name
diff --git a/src/java/edu/umd/cs/findbugs/model/RegenerateClassFeatures.java b/src/java/edu/umd/cs/findbugs/model/RegenerateClassFeatures.java
index 679ef1c..9972ede 100644
--- a/src/java/edu/umd/cs/findbugs/model/RegenerateClassFeatures.java
+++ b/src/java/edu/umd/cs/findbugs/model/RegenerateClassFeatures.java
@@ -35,13 +35,13 @@ import edu.umd.cs.findbugs.SortedBugCollection;
/**
* Repopulate a BugCollection with class features from the classes in a
* specified jar file.
- *
+ *
* @author David Hovemeyer
*/
public class RegenerateClassFeatures {
- private BugCollection bugCollection;
+ private final BugCollection bugCollection;
- private String jarFile;
+ private final String jarFile;
public RegenerateClassFeatures(BugCollection bugCollection, String jarFile) {
this.bugCollection = bugCollection;
@@ -51,25 +51,27 @@ public class RegenerateClassFeatures {
public RegenerateClassFeatures execute() throws IOException {
bugCollection.clearClassFeatures();
- ZipFile zipFile = new ZipFile(jarFile);
ArrayList<JavaClass> classList = new ArrayList<JavaClass>();
- // Add all classes to repository (for hierarchy queries)
- Enumeration<? extends ZipEntry> entries = zipFile.entries();
- while (entries.hasMoreElements()) {
- ZipEntry entry = entries.nextElement();
+ try (ZipFile zipFile = new ZipFile(jarFile)){
+
+ // Add all classes to repository (for hierarchy queries)
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
- if (!entry.getName().endsWith(".class"))
- continue;
+ if (!entry.getName().endsWith(".class")) {
+ continue;
+ }
- ClassParser parser = new ClassParser(zipFile.getInputStream(entry), entry.getName());
- JavaClass javaClass = parser.parse();
+ ClassParser parser = new ClassParser(zipFile.getInputStream(entry), entry.getName());
+ JavaClass javaClass = parser.parse();
- Repository.addClass(javaClass);
- classList.add(javaClass);
+ Repository.addClass(javaClass);
+ classList.add(javaClass);
+ }
}
- zipFile.close();
for (JavaClass javaClass : classList) {
ClassFeatureSet classFeatureSet = new ClassFeatureSet().initialize(javaClass);
diff --git a/src/java/edu/umd/cs/findbugs/model/SimilarClassFinder.java b/src/java/edu/umd/cs/findbugs/model/SimilarClassFinder.java
index d3a325c..b944537 100644
--- a/src/java/edu/umd/cs/findbugs/model/SimilarClassFinder.java
+++ b/src/java/edu/umd/cs/findbugs/model/SimilarClassFinder.java
@@ -27,7 +27,7 @@ import java.util.List;
* @author David Hovemeyer
*/
public class SimilarClassFinder {
- private List<SimilarClassSet> similarClassSetList;
+ private final List<SimilarClassSet> similarClassSetList;
public SimilarClassFinder() {
this.similarClassSetList = new LinkedList<SimilarClassSet>();
diff --git a/src/java/edu/umd/cs/findbugs/model/SimilarClassSet.java b/src/java/edu/umd/cs/findbugs/model/SimilarClassSet.java
index f979b34..58998ae 100644
--- a/src/java/edu/umd/cs/findbugs/model/SimilarClassSet.java
+++ b/src/java/edu/umd/cs/findbugs/model/SimilarClassSet.java
@@ -24,11 +24,11 @@ import java.util.List;
/**
* A set of classes considered similar because of their features.
- *
+ *
* @author David Hovemeyer
*/
public class SimilarClassSet {
- private List<ClassFeatureSet> memberList;
+ private final List<ClassFeatureSet> memberList;
public SimilarClassSet() {
this.memberList = new LinkedList<ClassFeatureSet>();
@@ -36,8 +36,9 @@ public class SimilarClassSet {
public boolean shouldContain(ClassFeatureSet candidate) {
for (ClassFeatureSet member : memberList) {
- if (candidate.similarTo(member))
+ if (candidate.similarTo(member)) {
return true;
+ }
}
return false;
}
@@ -47,8 +48,9 @@ public class SimilarClassSet {
}
public String getRepresentativeClassName() {
- if (memberList.isEmpty())
+ if (memberList.isEmpty()) {
throw new IllegalStateException();
+ }
return memberList.get(0).getClassName();
}
diff --git a/src/java/edu/umd/cs/findbugs/plan/AnalysisPass.java b/src/java/edu/umd/cs/findbugs/plan/AnalysisPass.java
index 066ffe8..bf3bacb 100644
--- a/src/java/edu/umd/cs/findbugs/plan/AnalysisPass.java
+++ b/src/java/edu/umd/cs/findbugs/plan/AnalysisPass.java
@@ -33,20 +33,20 @@ import edu.umd.cs.findbugs.DetectorFactory;
/**
* An analysis pass in the overall ExecutionPlan. This is a list of Detectors to
* be applied to analyzed classes.
- *
+ *
* @see ExecutionPlan
* @author David Hovemeyer
*/
public class AnalysisPass {
- private LinkedList<DetectorFactory> orderedFactoryList;
+ private final LinkedList<DetectorFactory> orderedFactoryList;
- private HashSet<DetectorFactory> memberSet;
+ private final HashSet<DetectorFactory> memberSet;
// private Detector2[] detectorList;
/**
* Constructor.
- *
+ *
* Creates an empty analysis pass.
*/
public AnalysisPass() {
@@ -57,7 +57,7 @@ public class AnalysisPass {
/**
* Make given DetectorFactory a member of this pass. Does not position the
* factory within the overall list of detectors.
- *
+ *
* @param factory
* a DetectorFactory
*/
@@ -68,19 +68,20 @@ public class AnalysisPass {
/**
* Append the given DetectorFactory to the end of the ordered detector list.
* The factory must be a member of the pass.
- *
+ *
* @param factory
* a DetectorFactory
*/
public void append(DetectorFactory factory) {
- if (!memberSet.contains(factory))
+ if (!memberSet.contains(factory)) {
throw new IllegalArgumentException("Detector " + factory.getFullName() + " appended to pass it doesn't belong to");
+ }
this.orderedFactoryList.addLast(factory);
}
/**
* Get the members of this pass.
- *
+ *
* @return members of this pass
*/
public Collection<DetectorFactory> getMembers() {
@@ -107,7 +108,7 @@ public class AnalysisPass {
/**
* Return whether or not this pass contains the given DetectorFactory.
- *
+ *
* @param factory
* the DetectorFactory
* @return true if this pass contains the DetectorFactory, false if not
@@ -119,7 +120,7 @@ public class AnalysisPass {
/**
* Instantiate all of the Detector2s in this pass and return them in a
* (correctly-ordered) array.
- *
+ *
* @param bugReporter
* the BugReporter
* @return array of Detector2s
@@ -138,7 +139,7 @@ public class AnalysisPass {
* BCEL-only Detector interface. Detectors that do not support this
* interface will not be created. Therefore, new code should use the
* instantiateDetector2sInPass() method, which can support all detectors.
- *
+ *
* @param bugReporter
* the BugReporter
* @return array of Detectors
@@ -168,4 +169,3 @@ public class AnalysisPass {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/plan/ByInterfaceDetectorFactorySelector.java b/src/java/edu/umd/cs/findbugs/plan/ByInterfaceDetectorFactorySelector.java
index 2f550d1..0dd3048 100644
--- a/src/java/edu/umd/cs/findbugs/plan/ByInterfaceDetectorFactorySelector.java
+++ b/src/java/edu/umd/cs/findbugs/plan/ByInterfaceDetectorFactorySelector.java
@@ -25,22 +25,24 @@ import edu.umd.cs.findbugs.Plugin;
/**
* DetectorFactorySelector implementation that chooses detectors based on an
* implemented interface or extended superclass.
- *
+ *
* @author David Hovemeyer
*/
public class ByInterfaceDetectorFactorySelector implements DetectorFactorySelector {
- private Plugin plugin;
+ private final Plugin plugin;
- private Class<?> detectorInterface;
+ private final Class<?> detectorInterface;
public ByInterfaceDetectorFactorySelector(Plugin plugin, Class<?> detectorInterface) {
this.plugin = plugin;
this.detectorInterface = detectorInterface;
}
+ @Override
public boolean selectFactory(DetectorFactory factory) {
- if (plugin != null && factory.getPlugin() != plugin)
+ if (plugin != null && factory.getPlugin() != plugin) {
return false;
+ }
return factory.isDetectorClassSubtypeOf(detectorInterface);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/plan/ConstraintEdge.java b/src/java/edu/umd/cs/findbugs/plan/ConstraintEdge.java
index 24ffb51..259eb54 100644
--- a/src/java/edu/umd/cs/findbugs/plan/ConstraintEdge.java
+++ b/src/java/edu/umd/cs/findbugs/plan/ConstraintEdge.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.graph.AbstractEdge;
/**
* Edge in a ConstraintGraph. Edges flow from earlier detectors to later
* detectors.
- *
+ *
* @see ConstraintGraph
* @see DetectorNode
* @see ExecutionPlan
@@ -35,7 +35,7 @@ public class ConstraintEdge extends AbstractEdge<ConstraintEdge, DetectorNode> {
/**
* Constructor.
- *
+ *
* @param source
* the source vertex (earlier Detector)
* @param target
@@ -47,7 +47,7 @@ public class ConstraintEdge extends AbstractEdge<ConstraintEdge, DetectorNode> {
/**
* Set the DetectorOrderingConstraint that created this edge.
- *
+ *
* @param constraint
* the DetectorOrderingConstraint that created this edge
*/
@@ -60,7 +60,7 @@ public class ConstraintEdge extends AbstractEdge<ConstraintEdge, DetectorNode> {
* constraint having a single detector as its source (ealier detector). Such
* constraints automatically enable the source (earlier) detector if the
* target (later) detector is enabled.
- *
+ *
* @return true if this edge has a single detector as its source (earlier
* detector)
*/
@@ -69,4 +69,3 @@ public class ConstraintEdge extends AbstractEdge<ConstraintEdge, DetectorNode> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/plan/ConstraintGraph.java b/src/java/edu/umd/cs/findbugs/plan/ConstraintGraph.java
index 126f70a..9be9b27 100644
--- a/src/java/edu/umd/cs/findbugs/plan/ConstraintGraph.java
+++ b/src/java/edu/umd/cs/findbugs/plan/ConstraintGraph.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.graph.AbstractGraph;
* Graph of Detector ordering constraints. It may represent ordering constraints
* between analysis passes, or ordering constraints within a single pass. Edges
* flow from earlier detectors to later detectors.
- *
+ *
* @see DetectorNode
* @see ConstraintEdge
* @see ExecutionPlan
@@ -43,4 +43,3 @@ public class ConstraintGraph extends AbstractGraph<ConstraintEdge, DetectorNode>
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/plan/DetectorFactorySelector.java b/src/java/edu/umd/cs/findbugs/plan/DetectorFactorySelector.java
index a7a9327..29d7dd4 100644
--- a/src/java/edu/umd/cs/findbugs/plan/DetectorFactorySelector.java
+++ b/src/java/edu/umd/cs/findbugs/plan/DetectorFactorySelector.java
@@ -24,13 +24,13 @@ import edu.umd.cs.findbugs.DetectorFactory;
/**
* Select one or more DetectorFactories as part of satisfying a Detector
* ordering constraint.
- *
+ *
* @author David Hovemeyer
*/
public interface DetectorFactorySelector {
/**
* Is given DetectorFactory selected (as part of an ordering constraint)?
- *
+ *
* @param factory
* a DetectorFactory
* @return true if the factory is selected, false otherwise
diff --git a/src/java/edu/umd/cs/findbugs/plan/DetectorNode.java b/src/java/edu/umd/cs/findbugs/plan/DetectorNode.java
index 4d28a42..8918c28 100644
--- a/src/java/edu/umd/cs/findbugs/plan/DetectorNode.java
+++ b/src/java/edu/umd/cs/findbugs/plan/DetectorNode.java
@@ -25,18 +25,18 @@ import edu.umd.cs.findbugs.graph.AbstractVertex;
/**
* Node in a ConstraintGraph. It represents a single Detector which must be
* ordered before or after some other Detector(s).
- *
+ *
* @see ConstraintGraph
* @see ConstraintEdge
* @see ExecutionPlan
* @author David Hovemeyer
*/
public class DetectorNode extends AbstractVertex<ConstraintEdge, DetectorNode> {
- private DetectorFactory factory;
+ private final DetectorFactory factory;
/**
* Constructor.
- *
+ *
* @param factory
* the DetectorFactory for the Detector this node represents
*/
@@ -60,4 +60,3 @@ public class DetectorNode extends AbstractVertex<ConstraintEdge, DetectorNode> {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/plan/DetectorOrderingConstraint.java b/src/java/edu/umd/cs/findbugs/plan/DetectorOrderingConstraint.java
index 022ca8c..5d97b6b 100644
--- a/src/java/edu/umd/cs/findbugs/plan/DetectorOrderingConstraint.java
+++ b/src/java/edu/umd/cs/findbugs/plan/DetectorOrderingConstraint.java
@@ -22,15 +22,15 @@ package edu.umd.cs.findbugs.plan;
/**
* An ordering constraint which must be taken into account when Detectors are
* run.
- *
+ *
* @see edu.umd.cs.findbugs.Plugin
* @see edu.umd.cs.findbugs.plan.ExecutionPlan
* @author David Hovemeyer
*/
public class DetectorOrderingConstraint {
- private DetectorFactorySelector earlier;
+ private final DetectorFactorySelector earlier;
- private DetectorFactorySelector later;
+ private final DetectorFactorySelector later;
private boolean singleSource;
@@ -54,7 +54,7 @@ public class DetectorOrderingConstraint {
* ordering constraint having a single detector as its source (ealier
* detector). Such constraints automatically enable the source (earlier)
* detector if the target (later) detector is enabled.
- *
+ *
* @return true if this edge has a single detector as its source (earlier
* detector)
*/
@@ -76,4 +76,3 @@ public class DetectorOrderingConstraint {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/plan/ExecutionPlan.java b/src/java/edu/umd/cs/findbugs/plan/ExecutionPlan.java
index 21679ca..1ccf537 100644
--- a/src/java/edu/umd/cs/findbugs/plan/ExecutionPlan.java
+++ b/src/java/edu/umd/cs/findbugs/plan/ExecutionPlan.java
@@ -45,7 +45,7 @@ import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
* A plan for executing Detectors on an application. Automatically assigns
* Detectors to passes and orders Detectors within each pass based on ordering
* constraints specified in the plugin descriptor(s).
- *
+ *
* @author David Hovemeyer
*/
public class ExecutionPlan {
@@ -72,10 +72,12 @@ public class ExecutionPlan {
public ExecutionPlan() {
this.pluginList = new LinkedList<Plugin>();
this.factoryChooser = new DetectorFactoryChooser() {
+ @Override
public boolean choose(DetectorFactory factory) {
return true;
}
+ @Override
public void enable(DetectorFactory factory) {
// OK...
}
@@ -232,8 +234,9 @@ public class ExecutionPlan {
}
appendDetectorsToPass(unassignedSet, lastPass);
}
- if (DEBUG)
+ if (DEBUG) {
print();
+ }
}
/**
@@ -245,7 +248,7 @@ public class ExecutionPlan {
/**
* Get the number of passes in the execution plan.
- *
+ *
* @return the number of passes in the execution plan
*/
public int getNumPasses() {
@@ -264,7 +267,7 @@ public class ExecutionPlan {
* correct ordering of the detectors (which may mean either passes or an
* ordering within a single pass, depending on whether the constraints are
* inter-pass or intra-pass).
- *
+ *
* @param nodeMap
* map to be populated with detector class names to constraint
* graph nodes for those detectors
@@ -359,7 +362,7 @@ public class ExecutionPlan {
while (incomingEdgeIterator.hasNext()) {
ConstraintEdge edge = incomingEdgeIterator.next();
System.out.println(" requires " + edge.getSource().getFactory().getShortName());
-
+
}
}
@@ -484,9 +487,10 @@ public class ExecutionPlan {
}
private void appendDetectorsToPass(Collection<DetectorFactory> detectorSet, AnalysisPass pass)
- {
+ {
DetectorFactory[] unassignedList = detectorSet.toArray(new DetectorFactory[detectorSet.size()]);
Arrays.sort(unassignedList, new Comparator<DetectorFactory>() {
+ @Override
public int compare(DetectorFactory a, DetectorFactory b) {
// Sort first by plugin id...
int cmp = a.getPlugin().getPluginId().compareTo(b.getPlugin().getPluginId());
@@ -543,4 +547,3 @@ public class ExecutionPlan {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/plan/OrderingConstraintException.java b/src/java/edu/umd/cs/findbugs/plan/OrderingConstraintException.java
index 5cdbb8e..9a79d6a 100644
--- a/src/java/edu/umd/cs/findbugs/plan/OrderingConstraintException.java
+++ b/src/java/edu/umd/cs/findbugs/plan/OrderingConstraintException.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
/**
* An exception indicating that the detector ordering constraints specified by a
* plugin are invalid.
- *
+ *
* @see DetectorOrderingConstraint
* @see ExecutionPlan
* @author David Hovemeyer
@@ -37,7 +37,7 @@ public class OrderingConstraintException extends CheckedAnalysisException {
/**
* Constructor.
- *
+ *
* @param msg
* the message describing the exception
*/
@@ -46,4 +46,3 @@ public class OrderingConstraintException extends CheckedAnalysisException {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/plan/ReportingDetectorFactorySelector.java b/src/java/edu/umd/cs/findbugs/plan/ReportingDetectorFactorySelector.java
index 2c42d6a..84c1325 100644
--- a/src/java/edu/umd/cs/findbugs/plan/ReportingDetectorFactorySelector.java
+++ b/src/java/edu/umd/cs/findbugs/plan/ReportingDetectorFactorySelector.java
@@ -24,15 +24,15 @@ import edu.umd.cs.findbugs.Plugin;
/**
* Select all detector factories for reporting detectors.
- *
+ *
* @author David Hovemeyer
*/
public class ReportingDetectorFactorySelector implements DetectorFactorySelector {
- private Plugin plugin;
+ private final Plugin plugin;
/**
* Constructor.
- *
+ *
* @param plugin
* Plugin containing detector factories to be selected; if null,
* factories from any Plugin may be selected
@@ -43,11 +43,12 @@ public class ReportingDetectorFactorySelector implements DetectorFactorySelector
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.plan.DetectorFactorySelector#selectFactory(edu.umd
* .cs.findbugs.DetectorFactory)
*/
+ @Override
public boolean selectFactory(DetectorFactory factory) {
return (plugin == null || plugin == factory.getPlugin()) && factory.isReportingDetector();
}
diff --git a/src/java/edu/umd/cs/findbugs/plan/SingleDetectorFactorySelector.java b/src/java/edu/umd/cs/findbugs/plan/SingleDetectorFactorySelector.java
index f8f5fc2..a953928 100644
--- a/src/java/edu/umd/cs/findbugs/plan/SingleDetectorFactorySelector.java
+++ b/src/java/edu/umd/cs/findbugs/plan/SingleDetectorFactorySelector.java
@@ -24,19 +24,20 @@ import edu.umd.cs.findbugs.Plugin;
/**
* Select a detector factory for a specific detector class.
- *
+ *
* @author David Hovemeyer
*/
public class SingleDetectorFactorySelector implements DetectorFactorySelector {
- private Plugin plugin;
+ private final Plugin plugin;
- private String className;
+ private final String className;
public SingleDetectorFactorySelector(Plugin plugin, String className) {
this.plugin = plugin;
this.className = className;
}
+ @Override
public boolean selectFactory(DetectorFactory factory) {
return plugin == factory.getPlugin()
&& (factory.getFullName().equals(className) || factory.getShortName().equals(className));
diff --git a/src/java/edu/umd/cs/findbugs/props/AbstractWarningProperty.java b/src/java/edu/umd/cs/findbugs/props/AbstractWarningProperty.java
index 71f280b..b7d3640 100644
--- a/src/java/edu/umd/cs/findbugs/props/AbstractWarningProperty.java
+++ b/src/java/edu/umd/cs/findbugs/props/AbstractWarningProperty.java
@@ -21,17 +21,17 @@ package edu.umd.cs.findbugs.props;
/**
* Abstract base class for implementing warning properties.
- *
+ *
* @author David Hovemeyer
*/
public abstract class AbstractWarningProperty implements WarningProperty {
- private String shortName;
+ private final String shortName;
- private PriorityAdjustment priorityAdjustment;
+ private final PriorityAdjustment priorityAdjustment;
/**
* Constructor.
- *
+ *
* @param shortName
* the short name of the property; will be qualified with the
* full name of the warning property class
@@ -45,18 +45,20 @@ public abstract class AbstractWarningProperty implements WarningProperty {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.props.WarningProperty#getPriorityAdjustment()
*/
+ @Override
public PriorityAdjustment getPriorityAdjustment() {
return priorityAdjustment;
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.props.WarningProperty#getName()
*/
+ @Override
public String getName() {
return this.getClass().getName() + "." + shortName;
}
diff --git a/src/java/edu/umd/cs/findbugs/props/GeneralWarningProperty.java b/src/java/edu/umd/cs/findbugs/props/GeneralWarningProperty.java
index f077398..5ac31c5 100644
--- a/src/java/edu/umd/cs/findbugs/props/GeneralWarningProperty.java
+++ b/src/java/edu/umd/cs/findbugs/props/GeneralWarningProperty.java
@@ -23,7 +23,7 @@ package edu.umd.cs.findbugs.props;
* any warning to provide information which might be useful in determining
* whether or not the bug is a false positive, and/or the severity of the
* warning.
- *
+ *
* @author David Hovemeyer
*/
public class GeneralWarningProperty extends AbstractWarningProperty {
diff --git a/src/java/edu/umd/cs/findbugs/props/PriorityAdjustment.java b/src/java/edu/umd/cs/findbugs/props/PriorityAdjustment.java
index f6baa13..6e98c93 100644
--- a/src/java/edu/umd/cs/findbugs/props/PriorityAdjustment.java
+++ b/src/java/edu/umd/cs/findbugs/props/PriorityAdjustment.java
@@ -21,11 +21,11 @@ package edu.umd.cs.findbugs.props;
/**
* Enum representing how a particular warning property is expected to affect its
* likelihood of being serious, benign, or a false positive.
- *
+ *
* @author David Hovemeyer
*/
public class PriorityAdjustment {
- private String value;
+ private final String value;
private PriorityAdjustment(String value) {
this.value = value;
diff --git a/src/java/edu/umd/cs/findbugs/props/WarningProperty.java b/src/java/edu/umd/cs/findbugs/props/WarningProperty.java
index c37ca03..58acd3a 100644
--- a/src/java/edu/umd/cs/findbugs/props/WarningProperty.java
+++ b/src/java/edu/umd/cs/findbugs/props/WarningProperty.java
@@ -20,7 +20,7 @@ package edu.umd.cs.findbugs.props;
/**
* Interface that all warning property enumerations are expected to implement.
- *
+ *
* @author David Hovemeyer
*/
public interface WarningProperty {
@@ -28,7 +28,7 @@ public interface WarningProperty {
* Get the priority adjustment: i.e., the effect that this warning property
* is expected to have on the likelihood that the warning is real, benign,
* or a false positive.
- *
+ *
* @return the priority adjustment
*/
public abstract PriorityAdjustment getPriorityAdjustment();
@@ -36,7 +36,7 @@ public interface WarningProperty {
/**
* Get the fully qualified name of the property. Should be full class name,
* ".", followed by the descriptive name of the property.
- *
+ *
* @return fully qualified name of the property
*/
public abstract String getName();
diff --git a/src/java/edu/umd/cs/findbugs/props/WarningPropertySet.java b/src/java/edu/umd/cs/findbugs/props/WarningPropertySet.java
index 8a571ea..1783911 100644
--- a/src/java/edu/umd/cs/findbugs/props/WarningPropertySet.java
+++ b/src/java/edu/umd/cs/findbugs/props/WarningPropertySet.java
@@ -191,13 +191,13 @@ public class WarningPropertySet<T extends WarningProperty> implements Cloneable
} else if (adj == PriorityAdjustment.FALSE_POSITIVE) {
falsePositive = true;
atMostLow = true;
- } else if (adj == PriorityAdjustment.A_LITTLE_BIT_LOWER_PRIORITY)
+ } else if (adj == PriorityAdjustment.A_LITTLE_BIT_LOWER_PRIORITY) {
aLittleBitLower++;
- else if (adj == PriorityAdjustment.A_LITTLE_BIT_HIGHER_PRIORITY)
+ } else if (adj == PriorityAdjustment.A_LITTLE_BIT_HIGHER_PRIORITY) {
aLittleBitLower--;
- else if (adj == PriorityAdjustment.RAISE_PRIORITY)
+ } else if (adj == PriorityAdjustment.RAISE_PRIORITY) {
--priority;
- else if (adj == PriorityAdjustment.RAISE_PRIORITY_TO_AT_LEAST_NORMAL) {
+ } else if (adj == PriorityAdjustment.RAISE_PRIORITY_TO_AT_LEAST_NORMAL) {
--priority;
atLeastMedium = true;
} else if (adj == PriorityAdjustment.LOWER_PRIORITY_TO_AT_MOST_NORMAL) {
@@ -215,31 +215,38 @@ public class WarningPropertySet<T extends WarningProperty> implements Cloneable
atMostMedium = true;
} else if (adj == PriorityAdjustment.NO_ADJUSTMENT) {
assert true; // do nothing
- } else
+ } else {
throw new IllegalStateException("Unknown priority " + adj);
+ }
}
- if (peggedHigh && !falsePositive)
+ if (peggedHigh && !falsePositive) {
return Priorities.HIGH_PRIORITY;
- if (aLittleBitLower >= 3 || priority == 1 && aLittleBitLower == 2)
+ }
+ if (aLittleBitLower >= 3 || priority == 1 && aLittleBitLower == 2) {
priority++;
- else if (aLittleBitLower <= -2)
+ } else if (aLittleBitLower <= -2) {
priority--;
- if (atMostMedium)
+ }
+ if (atMostMedium) {
priority = Math.max(Priorities.NORMAL_PRIORITY, priority);
+ }
- if (falsePositive && !atLeastMedium)
+ if (falsePositive && !atLeastMedium) {
return Priorities.EXP_PRIORITY + 1;
- else if (atMostLow)
+ } else if (atMostLow) {
return Math.min(Math.max(Priorities.LOW_PRIORITY, priority), Priorities.EXP_PRIORITY);
- if (atLeastMedium && priority > Priorities.NORMAL_PRIORITY)
+ }
+ if (atLeastMedium && priority > Priorities.NORMAL_PRIORITY) {
priority = Priorities.NORMAL_PRIORITY;
+ }
- if (priority < Priorities.HIGH_PRIORITY)
+ if (priority < Priorities.HIGH_PRIORITY) {
priority = Priorities.HIGH_PRIORITY;
- else if (priority > Priorities.EXP_PRIORITY)
+ } else if (priority > Priorities.EXP_PRIORITY) {
priority = Priorities.EXP_PRIORITY;
+ }
}
return priority;
@@ -270,8 +277,9 @@ public class WarningPropertySet<T extends WarningProperty> implements Cloneable
for (Map.Entry<T, Object> entry : map.entrySet()) {
WarningProperty prop = entry.getKey();
Object attribute = entry.getValue();
- if (attribute == null)
+ if (attribute == null) {
attribute = "";
+ }
bugInstance.setProperty(prop.getName(), attribute.toString());
}
}
diff --git a/src/java/edu/umd/cs/findbugs/props/WarningPropertyUtil.java b/src/java/edu/umd/cs/findbugs/props/WarningPropertyUtil.java
index ef6ea07..b4a3bc0 100644
--- a/src/java/edu/umd/cs/findbugs/props/WarningPropertyUtil.java
+++ b/src/java/edu/umd/cs/findbugs/props/WarningPropertyUtil.java
@@ -40,7 +40,7 @@ import edu.umd.cs.findbugs.ba.type.TypeFrame;
/**
* Utility methods for creating general warning properties.
- *
+ *
* @author David Hovemeyer
*/
public abstract class WarningPropertyUtil {
@@ -61,7 +61,7 @@ public abstract class WarningPropertyUtil {
* Get a Location matching the given PC value. Because of JSR subroutines,
* there may be multiple Locations referring to the given instruction. This
* method simply returns one of them arbitrarily.
- *
+ *
* @param classContext
* the ClassContext containing the method
* @param method
@@ -76,8 +76,9 @@ public abstract class WarningPropertyUtil {
CFG cfg = classContext.getCFG(method);
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
- if (location.getHandle().getPosition() == pc)
+ if (location.getHandle().getPosition() == pc) {
return location;
+ }
}
return null;
}
@@ -85,7 +86,7 @@ public abstract class WarningPropertyUtil {
/**
* Add a RECEIVER_OBJECT_TYPE warning property for a particular location in
* a method to given warning property set.
- *
+ *
* @param propertySet
* the property set
* @param classContext
@@ -100,8 +101,9 @@ public abstract class WarningPropertyUtil {
try {
Instruction ins = location.getHandle().getInstruction();
- if (!receiverObjectInstructionSet.get(ins.getOpcode()))
+ if (!receiverObjectInstructionSet.get(ins.getOpcode())) {
return;
+ }
TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
TypeFrame frame = typeDataflow.getFactAtLocation(location);
@@ -121,7 +123,7 @@ public abstract class WarningPropertyUtil {
/**
* Add CALLED_METHOD_<i>n</i> warning properties based on methods which have
* been called and returned normally at given Location.
- *
+ *
* @param propertySet
* the WarningPropertySet
* @param classContext
@@ -136,8 +138,9 @@ public abstract class WarningPropertyUtil {
try {
CallListDataflow dataflow = classContext.getCallListDataflow(method);
CallList callList = dataflow.getFactAtLocation(location);
- if (!callList.isValid())
+ if (!callList.isValid()) {
return;
+ }
int count = 0;
for (Iterator<Call> i = callList.callIterator(); count < 4 && i.hasNext(); ++count) {
Call call = i.next();
@@ -170,7 +173,7 @@ public abstract class WarningPropertyUtil {
/**
* Add all relevant general warning properties to the given property set for
* the given Location.
- *
+ *
* @param propertySet
* the WarningPropertySet
* @param classContext
@@ -189,7 +192,7 @@ public abstract class WarningPropertyUtil {
/**
* Add all relevant general warning properties to the given property set for
* the given Location.
- *
+ *
* @param propertySet
* the WarningPropertySet
* @param classContext
diff --git a/src/java/edu/umd/cs/findbugs/updates/UpdateChecker.java b/src/java/edu/umd/cs/findbugs/updates/UpdateChecker.java
index eaf4ba0..fcc9f7a 100644
--- a/src/java/edu/umd/cs/findbugs/updates/UpdateChecker.java
+++ b/src/java/edu/umd/cs/findbugs/updates/UpdateChecker.java
@@ -39,6 +39,7 @@ import edu.umd.cs.findbugs.FindBugs;
import edu.umd.cs.findbugs.Plugin;
import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.Version;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import edu.umd.cs.findbugs.util.MultiMap;
import edu.umd.cs.findbugs.util.Util;
import edu.umd.cs.findbugs.xml.OutputStreamXMLOutput;
@@ -87,27 +88,24 @@ public class UpdateChecker {
startUpdateCheckThread(uri, pluginsByUrl.get(uri), latch);
}
}
-
+
waitForCompletion(latch, force);
}
- /**
- * @param force
- * @return
- */
public @CheckForNull URI getRedirectURL(final boolean force) {
String redirect = dfc.getGlobalOption(KEY_REDIRECT_ALL_UPDATE_CHECKS);
String sysprop = System.getProperty("findbugs.redirectUpdateChecks");
- if (sysprop != null)
+ if (sysprop != null) {
redirect = sysprop;
+ }
Plugin setter = dfc.getGlobalOptionSetter(KEY_REDIRECT_ALL_UPDATE_CHECKS);
URI redirectUri = null;
String pluginName = setter == null ? "<unknown plugin>" : setter.getShortDescription();
- if (redirect != null && !redirect.trim().equals("")) {
+ if (redirect != null && !"".equals(redirect.trim())) {
try {
redirectUri = new URI(redirect);
logError(Level.INFO, "Redirecting all plugin update checks to " + redirectUri + " (" + pluginName + ")");
-
+
} catch (URISyntaxException e) {
String error = "Invalid update check redirect URI in " + pluginName + ": " + redirect;
logError(Level.SEVERE, error);
@@ -120,12 +118,13 @@ public class UpdateChecker {
private long dontWarnAgainUntil() {
Preferences prefs = Preferences.userNodeForPackage(UpdateChecker.class);
-
+
String oldSeen = prefs.get("last-plugin-update-seen", "");
- if (oldSeen == null || oldSeen.equals(""))
+ if (oldSeen == null || "".equals(oldSeen)) {
return 0;
+ }
try {
- return Long.parseLong(oldSeen) + DONT_REMIND_WINDOW;
+ return Long.parseLong(oldSeen) + DONT_REMIND_WINDOW;
} catch (Exception e) {
return 0;
}
@@ -135,7 +134,7 @@ public class UpdateChecker {
long now = System.currentTimeMillis();
Preferences prefs = Preferences.userNodeForPackage(UpdateChecker.class);
String oldHash = prefs.get("last-plugin-update-hash", "");
-
+
String newHash = Integer.toString(buildPluginUpdateHash(updates));
if (oldHash.equals(newHash) && dontWarnAgainUntil() > now) {
LOGGER.fine("Skipping update dialog because these updates have been seen before");
@@ -153,12 +152,14 @@ public class UpdateChecker {
}
return builder.hashCode();
}
-
+
private void waitForCompletion(final CountDownLatch latch, final boolean force) {
Util.runInDameonThread(new Runnable() {
+ @Override
public void run() {
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Checking for version updates");
+ }
try {
if (! latch.await(15, TimeUnit.SECONDS)) {
logError(Level.INFO, "Update check timed out");
@@ -201,36 +202,40 @@ public class UpdateChecker {
final String entryPoint = getEntryPoint();
if ((entryPoint.contains("edu.umd.cs.findbugs.FindBugsTestCase")
|| entryPoint.contains("edu.umd.cs.findbugs.cloud.appEngine.AbstractWebCloudTest"))
- && (url.getScheme().equals("http") || url.getScheme().equals("https"))) {
+ && ("http".equals(url.getScheme()) || "https".equals(url.getScheme()))) {
LOGGER.fine("Skipping update check because we're running in FindBugsTestCase and using "
+ url.getScheme());
return;
}
Runnable r = new Runnable() {
+ @Override
public void run() {
try {
actuallyCheckforUpdates(url, plugins, entryPoint);
} catch (Exception e) {
- if (e instanceof IllegalStateException && e.getMessage().contains("Shutdown in progress"))
+ if (e instanceof IllegalStateException && e.getMessage().contains("Shutdown in progress")) {
return;
+ }
logError(e, "Error doing update check at " + url);
} finally {
latch.countDown();
}
}
};
- if (DEBUG)
+ if (DEBUG) {
r.run();
- else
+ } else {
Util.runInDameonThread(r, "Check for updates");
+ }
}
static final boolean DEBUG = SystemProperties.getBoolean("findbugs.updatecheck.debug");
/** protected for testing */
protected void actuallyCheckforUpdates(URI url, Collection<Plugin> plugins, String entryPoint) throws IOException {
LOGGER.fine("Checking for updates at " + url + " for " + getPluginNames(plugins));
- if (DEBUG)
+ if (DEBUG) {
System.out.println(url);
+ }
HttpURLConnection conn = (HttpURLConnection) url.toURL().openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
@@ -247,7 +252,7 @@ public class UpdateChecker {
if (responseCode != 200) {
logError(SystemProperties.ASSERTIONS_ENABLED ? Level.WARNING : Level.FINE,
"Error checking for updates at " + url + ": "
- + responseCode + " - " + conn.getResponseMessage());
+ + responseCode + " - " + conn.getResponseMessage());
} else {
parseUpdateXml(url, plugins, conn.getInputStream());
}
@@ -255,6 +260,7 @@ public class UpdateChecker {
}
/** protected for testing */
+ @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION")
protected final void writeXml(OutputStream out, Collection<Plugin> plugins, String entryPoint,
boolean finish) throws IOException {
OutputStreamXMLOutput xmlOutput = new OutputStreamXMLOutput(out);
@@ -264,17 +270,19 @@ public class UpdateChecker {
xmlOutput.startTag("findbugs-invocation");
xmlOutput.addAttribute("version", Version.RELEASE);
String applicationName = Version.getApplicationName();
- if (applicationName == null || applicationName.equals("")) {
+ if (applicationName == null || "".equals(applicationName)) {
int lastDot = entryPoint.lastIndexOf('.');
- if (lastDot == -1)
+ if (lastDot == -1) {
applicationName = entryPoint;
- else
+ } else {
applicationName = entryPoint.substring(lastDot + 1);
+ }
}
xmlOutput.addAttribute("app-name", applicationName);
String applicationVersion = Version.getApplicationVersion();
- if (applicationVersion == null)
+ if (applicationVersion == null) {
applicationVersion = "";
+ }
xmlOutput.addAttribute("app-version", applicationVersion);
xmlOutput.addAttribute("entry-point", entryPoint);
xmlOutput.addAttribute("os", SystemProperties.getProperty("os.name", ""));
@@ -290,23 +298,25 @@ public class UpdateChecker {
xmlOutput.addAttribute("name", plugin.getShortDescription());
xmlOutput.addAttribute("version", plugin.getVersion());
Date date = plugin.getReleaseDate();
- if (date != null)
+ if (date != null) {
xmlOutput.addAttribute("release-date", Long.toString(date.getTime()));
+ }
xmlOutput.stopTag(true);
}
xmlOutput.closeTag("findbugs-invocation");
xmlOutput.flush();
} finally {
- if (finish)
+ if (finish) {
xmlOutput.finish();
+ }
}
}
// package-private for testing
@SuppressWarnings({ "unchecked" })
void parseUpdateXml(URI url, Collection<Plugin> plugins, @WillClose
- InputStream inputStream) {
+ InputStream inputStream) {
try {
Document doc = new SAXReader().read(inputStream);
if (DEBUG) {
@@ -318,8 +328,9 @@ public class UpdateChecker {
}
List<Element> pluginEls = XMLUtil.selectNodes(doc, "fb-plugin-updates/plugin");
Map<String, Plugin> map = new HashMap<String, Plugin>();
- for (Plugin p : plugins)
+ for (Plugin p : plugins) {
map.put(p.getPluginId(), p);
+ }
for (Element pluginEl : pluginEls) {
String id = pluginEl.attributeValue("id");
Plugin plugin = map.get(id);
@@ -345,11 +356,13 @@ public class UpdateChecker {
private void checkPluginRelease(Plugin plugin, Element maxEl) {
@CheckForNull Date updateDate = parseReleaseDate(maxEl);
@CheckForNull Date installedDate = plugin.getReleaseDate();
- if (updateDate != null && installedDate != null && updateDate.before(installedDate))
+ if (updateDate != null && installedDate != null && updateDate.before(installedDate)) {
return;
+ }
String version = maxEl.attributeValue("version");
- if (version.equals(plugin.getVersion()))
+ if (version.equals(plugin.getVersion())) {
return;
+ }
String url = maxEl.attributeValue("url");
String message = maxEl.element("message").getTextTrim();
@@ -370,12 +383,13 @@ public class UpdateChecker {
private @CheckForNull Date parseReleaseDate(Element releaseEl) {
SimpleDateFormat format = new SimpleDateFormat(PLUGIN_RELEASE_DATE_FMT);
String dateStr = releaseEl.attributeValue("date");
- if (dateStr == null)
+ if (dateStr == null) {
return null;
+ }
try {
return format.parse(dateStr);
- } catch (Exception e) {
- throw new IllegalArgumentException("Error parsing " + dateStr, e);
+ } catch (java.text.ParseException e) {
+ throw new IllegalArgumentException("Error parsing " + dateStr + " using " + PLUGIN_RELEASE_DATE_FMT, e);
}
}
@@ -399,7 +413,7 @@ public class UpdateChecker {
}
return lastFbClass;
}
-
+
/** Should only be used once */
private static Random random = new Random();
@@ -421,7 +435,7 @@ public class UpdateChecker {
String ver = SystemProperties.getProperty("java.version", "");
Matcher m = Pattern.compile("^\\d+\\.\\d+").matcher(ver);
if (m.find()) {
- return m.group();
+ return m.group();
}
return "";
}
@@ -460,17 +474,18 @@ public class UpdateChecker {
public @Nonnull String getMessage() {
return message;
}
-
+
@Override
public String toString() {
SimpleDateFormat format = new SimpleDateFormat(PLUGIN_RELEASE_DATE_FMT);
StringBuilder buf = new StringBuilder();
String name = getPlugin().isCorePlugin() ? "FindBugs" : "FindBugs plugin " + getPlugin().getShortDescription();
buf.append( name + " " + getVersion() );
- if (date == null)
+ if (date == null) {
buf.append(" has been released");
- else
+ } else {
buf.append(" was released " + format.format(date));
+ }
buf.append(
" (you have " + getPlugin().getVersion()
+ ")");
@@ -478,23 +493,26 @@ public class UpdateChecker {
buf.append(" " + message.replaceAll("\n", "\n "));
- if (url != null)
+ if (url != null) {
buf.append("\nVisit " + url + " for details.");
+ }
return buf.toString();
}
}
-
+
public static void main(String args[]) throws Exception {
FindBugs.setNoAnalysis();
DetectorFactoryCollection dfc = DetectorFactoryCollection.instance();
UpdateChecker checker = dfc.getUpdateChecker();
- if (checker.updateChecksGloballyDisabled())
+ if (checker.updateChecksGloballyDisabled()) {
System.out.println("Update checkes are globally disabled");
+ }
URI redirect = checker.getRedirectURL(false);
- if (redirect != null)
+ if (redirect != null) {
System.out.println("All update checks redirected to " + redirect);
+ }
checker.writeXml(System.out, dfc.plugins(), "UpdateChecker", true);
-
-
+
+
}
}
diff --git a/src/java/edu/umd/cs/findbugs/util/AnyTypeMatcher.java b/src/java/edu/umd/cs/findbugs/util/AnyTypeMatcher.java
index 19ae1c8..5300b12 100644
--- a/src/java/edu/umd/cs/findbugs/util/AnyTypeMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/util/AnyTypeMatcher.java
@@ -23,11 +23,12 @@ import org.apache.bcel.generic.Type;
/**
* A TypeMatcher that matches all types.
- *
+ *
* @author David Hovemeyer
*/
public class AnyTypeMatcher implements TypeMatcher {
+ @Override
public boolean matches(Type t) {
return true;
}
diff --git a/src/java/edu/umd/cs/findbugs/util/Archive.java b/src/java/edu/umd/cs/findbugs/util/Archive.java
index 4413030..fc5dd94 100644
--- a/src/java/edu/umd/cs/findbugs/util/Archive.java
+++ b/src/java/edu/umd/cs/findbugs/util/Archive.java
@@ -59,10 +59,6 @@ public class Archive {
return ARCHIVE_EXTENSION_SET.contains(extension);
}
- /**
- * @param fileName
- * @return
- */
private static String getExtension(String fileName) {
int lastDot = fileName.lastIndexOf('.');
if (lastDot < 0) {
@@ -71,9 +67,9 @@ public class Archive {
String extension = fileName.substring(lastDot).toLowerCase(Locale.ENGLISH);
return extension;
}
-
+
public static boolean isLibraryFileName(String fileName) {
String extension = getExtension(fileName);
- return extension.equals(".jar");
+ return ".jar".equals(extension);
}
}
diff --git a/src/java/edu/umd/cs/findbugs/util/Bag.java b/src/java/edu/umd/cs/findbugs/util/Bag.java
index 6fa06a1..ca96610 100644
--- a/src/java/edu/umd/cs/findbugs/util/Bag.java
+++ b/src/java/edu/umd/cs/findbugs/util/Bag.java
@@ -26,7 +26,7 @@ import java.util.Set;
/**
* Simple implementation of a Bag
- *
+ *
* @author pugh
*/
public class Bag<E> {
@@ -42,19 +42,21 @@ public class Bag<E> {
public boolean add(E e) {
Integer v = map.get(e);
- if (v == null)
+ if (v == null) {
map.put(e, 1);
- else
+ } else {
map.put(e, v + 1);
+ }
return true;
}
public boolean add(E e, int count) {
Integer v = map.get(e);
- if (v == null)
+ if (v == null) {
map.put(e, count);
- else
+ } else {
map.put(e, v + count);
+ }
return true;
}
@@ -68,10 +70,11 @@ public class Bag<E> {
public int getCount(E e) {
Integer v = map.get(e);
- if (v == null)
+ if (v == null) {
return 0;
- else
+ } else {
return v;
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/util/ClassName.java b/src/java/edu/umd/cs/findbugs/util/ClassName.java
index 1b92a4e..7bef67e 100644
--- a/src/java/edu/umd/cs/findbugs/util/ClassName.java
+++ b/src/java/edu/umd/cs/findbugs/util/ClassName.java
@@ -22,6 +22,7 @@ package edu.umd.cs.findbugs.util;
import javax.annotation.CheckForNull;
import javax.annotation.meta.When;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import edu.umd.cs.findbugs.classfile.DescriptorFactory;
import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
@@ -34,7 +35,7 @@ import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
public abstract class ClassName {
public static boolean isMathClass(@SlashedClassName String className) {
- return className.equals("java/lang/Math") || className.equals("java/lang/StrictMath");
+ return "java/lang/Math".equals(className) || "java/lang/StrictMath".equals(className);
}
public static @DottedClassName String assertIsDotted(@DottedClassName String className) {
@@ -46,27 +47,47 @@ public abstract class ClassName {
return className;
}
public static String toSignature(@SlashedClassName String className) {
- if (className.length() == 0)
+ if (className.length() == 0) {
throw new IllegalArgumentException("classname can't be empty");
- if (className.charAt(0) == '[' || className.endsWith(";"))
+ }
+ if (className.charAt(0) == '[' || className.endsWith(";")) {
return className;
+ }
return "L" + className + ";";
}
public static @CheckForNull String getPrimitiveType(@SlashedClassName String cls) {
- if (!cls.startsWith("java/lang/")) return null;
+ if (!cls.startsWith("java/lang/")) {
+ return null;
+ }
cls = cls.substring(10);
- if (cls.equals("Integer")) return "I";
- if (cls.equals("Float")) return "F";
- if (cls.equals("Double")) return "D";
- if (cls.equals("Long")) return "J";
- if (cls.equals("Byte")) return "B";
- if (cls.equals("Character")) return "C";
- if (cls.equals("Short")) return "S";
- if (cls.equals("Boolean")) return "Z";
+ if ("Integer".equals(cls)) {
+ return "I";
+ }
+ if ("Float".equals(cls)) {
+ return "F";
+ }
+ if ("Double".equals(cls)) {
+ return "D";
+ }
+ if ("Long".equals(cls)) {
+ return "J";
+ }
+ if ("Byte".equals(cls)) {
+ return "B";
+ }
+ if ("Character".equals(cls)) {
+ return "C";
+ }
+ if ("Short".equals(cls)) {
+ return "S";
+ }
+ if ("Boolean".equals(cls)) {
+ return "Z";
+ }
return null;
}
-
+
/**
* Converts from signature to slashed class name
* (e.g., from Ljava/lang/String; to java/lang/String).
@@ -82,7 +103,6 @@ public abstract class ClassName {
return signature.substring(1, signature.length() - 1);
}
-
/**
* Convert class name to slashed format. If the class name is already in
* slashed format, it is returned unmodified.
@@ -91,8 +111,9 @@ public abstract class ClassName {
* a class name
* @return the same class name in slashed format
*/
- public static @SlashedClassName
- String toSlashedClassName(@SlashedClassName(when = When.UNKNOWN) String className) {
+ @SlashedClassName
+ @SuppressFBWarnings("TQ_EXPLICIT_UNKNOWN_SOURCE_VALUE_REACHES_ALWAYS_SINK")
+ public static String toSlashedClassName(@SlashedClassName(when = When.UNKNOWN) String className) {
if (className.indexOf('.') >= 0) {
return DescriptorFactory.canonicalizeString(className.replace('.', '/'));
}
@@ -107,8 +128,9 @@ public abstract class ClassName {
* a class name
* @return the same class name in dotted format
*/
- public static @DottedClassName
- String toDottedClassName(@SlashedClassName(when = When.UNKNOWN) String className) {
+ @DottedClassName
+ @SuppressFBWarnings("TQ_EXPLICIT_UNKNOWN_SOURCE_VALUE_REACHES_NEVER_SINK")
+ public static String toDottedClassName(@SlashedClassName(when = When.UNKNOWN) String className) {
if (className.indexOf('/') >= 0) {
return DescriptorFactory.canonicalizeString(className.replace('/', '.'));
}
@@ -126,16 +148,24 @@ public abstract class ClassName {
public static @DottedClassName
String extractPackageName(@DottedClassName String className) {
int i = className.lastIndexOf('.');
- if (i < 0)
+ if (i < 0) {
return "";
+ }
return className.substring(0, i);
}
public static String extractSimpleName(@DottedClassName String className) {
int i = className.lastIndexOf('.');
- if (i > 0)
+ if (i > 0) {
className = className.substring(i + 1);
- className = className.replace('$', '.');
+ }
+ // to be consistent with the Class.getSimpleName(),
+ // simple class name does not! contain the enclosing class name
+ i = className.lastIndexOf('$');
+ if (i > 0) {
+ className = className.substring(i + 1);
+ }
+ // can be empty!
return className;
}
@@ -181,14 +211,18 @@ public abstract class ClassName {
public static @SlashedClassName
String extractClassName(String originalName) {
String name = originalName;
- if (name.charAt(0) != '[' && name.charAt(name.length() - 1) != ';')
+ if (name.charAt(0) != '[' && name.charAt(name.length() - 1) != ';') {
return name;
- while (name.charAt(0) == '[')
+ }
+ while (name.charAt(0) == '[') {
name = name.substring(1);
- if (name.charAt(0) == 'L' && name.charAt(name.length() - 1) == ';')
+ }
+ if (name.charAt(0) == 'L' && name.charAt(name.length() - 1) == ';') {
name = name.substring(1, name.length() - 1);
- if (name.charAt(0) == '[')
+ }
+ if (name.charAt(0) == '[') {
throw new IllegalArgumentException("Bad class name: " + originalName);
+ }
return name;
}
@@ -197,24 +231,29 @@ public abstract class ClassName {
int prefixLength = 0;
while (dotsSeen < count) {
int p = packageName.indexOf('.', prefixLength);
- if (p < 0)
+ if (p < 0) {
return packageName;
+ }
prefixLength = p + 1;
dotsSeen++;
}
- if (prefixLength == 0)
+ if (prefixLength == 0) {
return "";
+ }
return packageName.substring(0, prefixLength - 1);
}
public static boolean matchedPrefixes(String[] classSearchStrings, @DottedClassName String className) {
String[] pp = classSearchStrings;
- if (pp == null || pp.length == 0)
+ if (pp == null || pp.length == 0) {
return true;
+ }
- for (String p : pp)
- if (p.length() > 0 && className.indexOf(p) >= 0)
+ for (String p : pp) {
+ if (p.length() > 0 && className.indexOf(p) >= 0) {
return true;
+ }
+ }
return false;
diff --git a/src/java/edu/umd/cs/findbugs/util/ClassPathUtil.java b/src/java/edu/umd/cs/findbugs/util/ClassPathUtil.java
index 02f37c7..6a51f02 100644
--- a/src/java/edu/umd/cs/findbugs/util/ClassPathUtil.java
+++ b/src/java/edu/umd/cs/findbugs/util/ClassPathUtil.java
@@ -28,14 +28,14 @@ import javax.annotation.Nonnull;
/**
* Some utility methods for working with the Java class path.
- *
+ *
* @author David Hovemeyer
*/
public class ClassPathUtil {
/**
* Try to find a codebase with the given name in the given class path
* string.
- *
+ *
* @param codeBaseName
* name of a codebase (e.g., "findbugs.jar")
* @param classPath
@@ -63,7 +63,7 @@ public class ClassPathUtil {
/**
* Try to find a codebase matching the given pattern in the given class path
* string.
- *
+ *
* @param codeBaseNamePattern
* pattern describing a codebase (e.g., compiled from the regex
* "findbugs\\.jar$")
diff --git a/src/java/edu/umd/cs/findbugs/util/ContainsCamelCaseWordStringMatcher.java b/src/java/edu/umd/cs/findbugs/util/ContainsCamelCaseWordStringMatcher.java
index 67640f6..d1885b6 100644
--- a/src/java/edu/umd/cs/findbugs/util/ContainsCamelCaseWordStringMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/util/ContainsCamelCaseWordStringMatcher.java
@@ -26,17 +26,17 @@ import java.util.Locale;
/**
* A StringMatcher that checks to see if a candidate string (assumed to be a
* camel-case word), when broken into components, contains a given word.
- *
+ *
* @author David Hovemeyer
*/
public class ContainsCamelCaseWordStringMatcher implements StringMatcher {
- private String expected;
+ private final String expected;
/**
* Constructor. This StringMatcher will match any string which, when broken
* into camel-case identifier components, has a component which matches the
* (lower-cased) expected string value.
- *
+ *
* @param expected
* the expected string value
*/
@@ -44,6 +44,7 @@ public class ContainsCamelCaseWordStringMatcher implements StringMatcher {
this.expected = expected.toLowerCase(Locale.ENGLISH);
}
+ @Override
public boolean matches(String s) {
SplitCamelCaseIdentifier splitter = new SplitCamelCaseIdentifier(s);
Collection<String> components = splitter.split();
diff --git a/src/java/edu/umd/cs/findbugs/util/DualKeyHashMap.java b/src/java/edu/umd/cs/findbugs/util/DualKeyHashMap.java
index a919dfd..6cb3258 100644
--- a/src/java/edu/umd/cs/findbugs/util/DualKeyHashMap.java
+++ b/src/java/edu/umd/cs/findbugs/util/DualKeyHashMap.java
@@ -32,22 +32,25 @@ public class DualKeyHashMap<K1, K2, V> {
public V get(K1 k1, K2 k2) {
Map<K2, V> m = map.get(k1);
- if (m == null)
+ if (m == null) {
return null;
+ }
return m.get(k2);
}
public boolean containsKey(K1 k1, K2 k2) {
Map<K2, V> m = map.get(k1);
- if (m == null)
+ if (m == null) {
return false;
+ }
return m.containsKey(k2);
}
public Map<K2, V> get(K1 k1) {
Map<K2, V> m = map.get(k1);
- if (m == null)
+ if (m == null) {
return Collections.<K2, V> emptyMap();
+ }
return m;
}
@@ -61,9 +64,9 @@ public class DualKeyHashMap<K1, K2, V> {
m = Collections.singletonMap(k2, v);
map.put(k1, m);
return null;
- } else if (m instanceof HashMap)
+ } else if (m instanceof HashMap) {
return m.put(k2, v);
- else {
+ } else {
m = Util.makeSmallHashMap(m);
map.put(k1, m);
return m.put(k2, v);
diff --git a/src/java/edu/umd/cs/findbugs/util/EditDistance.java b/src/java/edu/umd/cs/findbugs/util/EditDistance.java
index 91ff789..3a0d118 100644
--- a/src/java/edu/umd/cs/findbugs/util/EditDistance.java
+++ b/src/java/edu/umd/cs/findbugs/util/EditDistance.java
@@ -29,16 +29,19 @@ public class EditDistance {
private static final int INSERT_OR_DELETE_COST = 2;
private static int minimum(int a, int b, int c) {
- if (a > b)
+ if (a > b) {
return Math.min(b, c);
+ }
return Math.min(a, c);
}
private static int distance(char a, char b) {
- if (a == b)
+ if (a == b) {
return 0;
- if (Character.toLowerCase(a) == Character.toLowerCase(b))
+ }
+ if (Character.toLowerCase(a) == Character.toLowerCase(b)) {
return 1;
+ }
return 2;
}
@@ -52,8 +55,9 @@ public class EditDistance {
int n1 = str1.length();
int n2 = str2.length();
int diff = Math.abs(n1 - n2);
- if (diff > 6)
+ if (diff > 6) {
return INSERT_OR_DELETE_COST * Math.max(n1, n2);
+ }
return editDistance1(str1, str2);
}
@@ -68,13 +72,16 @@ public class EditDistance {
distance[i] = new int[n2 + 1];
distance[i][0] = INSERT_OR_DELETE_COST * i;
}
- for (int j = 1; j <= n2; j++)
+ for (int j = 1; j <= n2; j++) {
distance[0][j] = INSERT_OR_DELETE_COST * j;
+ }
- for (int i = 1; i <= n1; i++)
- for (int j = 1; j <= n2; j++)
+ for (int i = 1; i <= n1; i++) {
+ for (int j = 1; j <= n2; j++) {
distance[i][j] = minimum(distance[i - 1][j] + INSERT_OR_DELETE_COST, distance[i][j - 1] + INSERT_OR_DELETE_COST,
distance[i - 1][j - 1] + distance(str1.charAt(i - 1), str2.charAt(j - 1)));
+ }
+ }
return distance[n1][n2];
}
@@ -86,14 +93,16 @@ public class EditDistance {
int[] distance = new int[n2 + 1];
int[] oldDistance = new int[n2 + 1];
- for (int j = 1; j <= n2; j++)
+ for (int j = 1; j <= n2; j++) {
oldDistance[j] = INSERT_OR_DELETE_COST * j;
+ }
for (int i = 1; i <= n1; i++) {
distance[0] = INSERT_OR_DELETE_COST * i;
- for (int j = 1; j <= n2; j++)
+ for (int j = 1; j <= n2; j++) {
distance[j] = minimum(oldDistance[j] + INSERT_OR_DELETE_COST, distance[j - 1] + INSERT_OR_DELETE_COST,
oldDistance[j - 1] + distance(str1.charAt(i - 1), str2.charAt(j - 1)));
+ }
int[] tmp = oldDistance;
oldDistance = distance;
distance = tmp;
diff --git a/src/java/edu/umd/cs/findbugs/util/ExactStringMatcher.java b/src/java/edu/umd/cs/findbugs/util/ExactStringMatcher.java
index 2478827..424db20 100644
--- a/src/java/edu/umd/cs/findbugs/util/ExactStringMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/util/ExactStringMatcher.java
@@ -21,7 +21,7 @@ package edu.umd.cs.findbugs.util;
/**
* Exact String-matching predicate.
- *
+ *
* @author David Hovemeyer
*/
public class ExactStringMatcher implements StringMatcher {
@@ -29,7 +29,7 @@ public class ExactStringMatcher implements StringMatcher {
/**
* Constructor.
- *
+ *
* @param expected
* the expected string value
*/
@@ -37,6 +37,7 @@ public class ExactStringMatcher implements StringMatcher {
this.expected = expected;
}
+ @Override
public boolean matches(String s) {
return this.expected.equals(s);
}
diff --git a/src/java/edu/umd/cs/findbugs/util/FractionalMultiset.java b/src/java/edu/umd/cs/findbugs/util/FractionalMultiset.java
index 6fbea1a..943b1fa 100644
--- a/src/java/edu/umd/cs/findbugs/util/FractionalMultiset.java
+++ b/src/java/edu/umd/cs/findbugs/util/FractionalMultiset.java
@@ -26,6 +26,8 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeSet;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
/**
* @author pwilliam
*/
@@ -50,26 +52,29 @@ public class FractionalMultiset<K> {
public void add(K k, double val) {
Double v = map.get(k);
- if (v == null)
+ if (v == null) {
map.put(k, val);
- else
+ } else {
map.put(k, v + val);
+ }
}
public double getValue(K k) {
Double v = map.get(k);
- if (v == null)
+ if (v == null) {
return 0;
+ }
return v;
}
public void turnTotalIntoAverage(Multiset<K> counts) {
for (Map.Entry<K, Double> e : map.entrySet()) {
int count = counts.getCount(e.getKey());
- if (count == 0)
+ if (count == 0) {
e.setValue(Double.NaN);
- else
+ } else {
e.setValue(e.getValue() / count);
+ }
}
}
@@ -78,43 +83,50 @@ public class FractionalMultiset<K> {
return map.entrySet();
}
+ @SuppressFBWarnings("DMI_ENTRY_SETS_MAY_REUSE_ENTRY_OBJECTS")
public Iterable<Map.Entry<K, Double>> entriesInDecreasingOrder() {
TreeSet<Map.Entry<K, Double>> result = new TreeSet<Map.Entry<K, Double>>(new DecreasingOrderEntryComparator<K>());
result.addAll(map.entrySet());
- if (result.size() != map.size())
- throw new IllegalStateException("Map " + map.getClass().getSimpleName()
+ if (result.size() != map.size()) {
+ throw new IllegalStateException("Map " + map.getClass().getSimpleName()
+ " reuses Map.Entry objects; entrySet can't be passed to addAll");
+ }
return result;
}
-
-
+
+ @SuppressFBWarnings("DMI_ENTRY_SETS_MAY_REUSE_ENTRY_OBJECTS")
public Iterable<Map.Entry<K, Double>> entriesInIncreasingOrder() {
TreeSet<Map.Entry<K, Double>> result = new TreeSet<Map.Entry<K, Double>>(new DecreasingOrderEntryComparator<K>());
result.addAll(map.entrySet());
- if (result.size() != map.size())
- throw new IllegalStateException("Map " + map.getClass().getSimpleName()
+ if (result.size() != map.size()) {
+ throw new IllegalStateException("Map " + map.getClass().getSimpleName()
+ " reuses Map.Entry objects; entrySet can't be passed to addAll");
+ }
return result;
}
-
+
private static <E> int compareValues(Entry<E, Double> o1, Entry<E, Double> o2) {
double c1 = o1.getValue();
double c2 = o2.getValue();
- if (c1 < c2)
+ if (c1 < c2) {
return 1;
- if (c1 > c2)
+ }
+ if (c1 > c2) {
return -1;
+ }
return System.identityHashCode(o1.getKey()) - System.identityHashCode(o2.getKey());
}
static class DecreasingOrderEntryComparator<E> implements Comparator<Map.Entry<E, Double>>, Serializable {
+ @Override
public int compare(Entry<E, Double> o1, Entry<E, Double> o2) {
return compareValues(o1, o2);
}
}
static class IncreasingOrderEntryComparator<E> implements Comparator<Map.Entry<E, Double>>, Serializable {
+ @Override
public int compare(Entry<E, Double> o1, Entry<E, Double> o2) {
return -compareValues(o1, o2);
}
diff --git a/src/java/edu/umd/cs/findbugs/util/FutureValue.java b/src/java/edu/umd/cs/findbugs/util/FutureValue.java
index 7c6ef53..84ef88a 100644
--- a/src/java/edu/umd/cs/findbugs/util/FutureValue.java
+++ b/src/java/edu/umd/cs/findbugs/util/FutureValue.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -35,76 +35,64 @@ public class FutureValue<V> implements Future<V> {
volatile boolean canceled;
+ @Override
public synchronized boolean cancel(boolean arg0) {
- if (latch.getCount() == 0)
+ if (latch.getCount() == 0) {
return false;
+ }
canceled = true;
latch.countDown();
return true;
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.concurrent.Future#get()
- */
- public V get() throws InterruptedException {
+ @Override
+ public synchronized V get() throws InterruptedException {
latch.await();
- if (canceled)
+ if (canceled) {
throw new RuntimeException("Canceled");
+ }
return value;
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.concurrent.Future#get(long, java.util.concurrent.TimeUnit)
- */
- public V get(long arg0, TimeUnit arg1) throws InterruptedException, TimeoutException {
- if (!latch.await(arg0, arg1))
+ @Override
+ public synchronized V get(long arg0, TimeUnit arg1) throws InterruptedException, TimeoutException {
+ if (!latch.await(arg0, arg1)) {
throw new TimeoutException();
- if (canceled)
+ }
+ if (canceled) {
throw new RuntimeException("Canceled");
+ }
return value;
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.concurrent.Future#get(long, java.util.concurrent.TimeUnit)
- */
- public V get(long arg0, TimeUnit arg1, V valueOnTimeout) throws InterruptedException {
- if (!latch.await(arg0, arg1))
+ public synchronized V get(long arg0, TimeUnit arg1, V valueOnTimeout) throws InterruptedException {
+ if (!latch.await(arg0, arg1)) {
return valueOnTimeout;
-
- if (canceled)
+ }
+
+ if (canceled) {
throw new RuntimeException("Canceled");
+ }
return value;
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.concurrent.Future#isCancelled()
- */
+ @Override
public boolean isCancelled() {
return canceled;
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.concurrent.Future#isDone()
- */
+ @Override
public boolean isDone() {
return !canceled && latch.getCount() == 0;
}
public synchronized void set(V value) {
- if (canceled)
+ if (canceled) {
throw new IllegalStateException("Already cancelled");
- if (latch.getCount() == 0)
+ }
+ if (latch.getCount() == 0) {
throw new IllegalStateException("Already set");
+ }
this.value = value;
latch.countDown();
}
diff --git a/src/java/edu/umd/cs/findbugs/util/HTML.java b/src/java/edu/umd/cs/findbugs/util/HTML.java
index 22b8622..53810fb 100644
--- a/src/java/edu/umd/cs/findbugs/util/HTML.java
+++ b/src/java/edu/umd/cs/findbugs/util/HTML.java
@@ -41,10 +41,6 @@ public class HTML {
boolean startingParagraph = false;
- /**
- * @param w
- * @param doc
- */
public HTMLtoPlainTextWriter2(Writer w, HTMLDocument doc) {
super(w, doc);
setLineLength(80);
@@ -55,17 +51,17 @@ public class HTML {
protected void startTag(Element elem) throws IOException {
String name = elem.getName();
startingParagraph = true;
- if (name.equals("ul")) {
+ if ("ul".equals(name)) {
super.incrIndent();
write(" ");
- } else if (name.equals("pre")) {
+ } else if ("pre".equals(name)) {
inPre = true;
- } else if (name.equals("li")) {
+ } else if ("li".equals(name)) {
super.incrIndent();
write("* ");
- } else if (name.equals("p")) {
+ } /*else if (name.equals("p")) {
- }
+ }*/
}
@Override
@@ -76,16 +72,16 @@ public class HTML {
@Override
protected void endTag(Element elem) throws IOException {
String name = elem.getName();
- if (name.equals("p")) {
+ if ("p".equals(name)) {
writeLineSeparator();
indent();
- } else if (name.equals("pre")) {
+ } else if ("pre".equals(name)) {
inPre = false;
- } else if (name.equals("ul")) {
+ } else if ("ul".equals(name)) {
super.decrIndent();
writeLineSeparator();
indent();
- } else if (name.equals("li")) {
+ } else if ("li".equals(name)) {
super.decrIndent();
writeLineSeparator();
indent();
@@ -102,8 +98,9 @@ public class HTML {
@Override
protected void emptyTag(Element elem) throws IOException, BadLocationException {
- if (elem.getName().equals("content"))
+ if ("content".equals(elem.getName())) {
super.emptyTag(elem);
+ }
}
@Override
@@ -113,8 +110,9 @@ public class HTML {
contentStr = contentStr.replaceAll("\\s+", " ");
if (startingParagraph) {
- while (contentStr.length() > 0 && contentStr.charAt(0) == ' ')
+ while (contentStr.length() > 0 && contentStr.charAt(0) == ' ') {
contentStr = contentStr.substring(1);
+ }
}
startingParagraph = false;
diff --git a/src/java/edu/umd/cs/findbugs/util/JavaWebStart.java b/src/java/edu/umd/cs/findbugs/util/JavaWebStart.java
index 1ae208f..fc4942f 100644
--- a/src/java/edu/umd/cs/findbugs/util/JavaWebStart.java
+++ b/src/java/edu/umd/cs/findbugs/util/JavaWebStart.java
@@ -40,7 +40,7 @@ public class JavaWebStart {
Method jnlpGetCodeBaseMethod;
static final Object jnlpBasicService; // will not be null if
- // jnlpShowMethod!=null
+ // jnlpShowMethod!=null
static {
// attempt to set the JNLP BasicService object and its showDocument(URL)
@@ -79,8 +79,9 @@ public class JavaWebStart {
if (JavaWebStart.jnlpGetCodeBaseMethod != null) {
try {
URL base = (URL) JavaWebStart.jnlpGetCodeBaseMethod.invoke(JavaWebStart.jnlpBasicService);
- if (base != null)
+ if (base != null) {
return new URL(base, s);
+ }
} catch (RuntimeException e) {
assert true;
} catch (Exception e) {
@@ -91,22 +92,25 @@ public class JavaWebStart {
}
static Boolean viaWebStart(URL url) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
- if (JavaWebStart.jnlpShowDocumentMethod == null)
+ if (JavaWebStart.jnlpShowDocumentMethod == null) {
throw new UnsupportedOperationException("Launch via web start not available");
+ }
return (Boolean) JavaWebStart.jnlpShowDocumentMethod.invoke(JavaWebStart.jnlpBasicService, url);
}
static boolean showViaWebStart(URL url) {
- if (JavaWebStart.jnlpShowDocumentMethod != null)
+ if (JavaWebStart.jnlpShowDocumentMethod != null) {
try {
- if (LaunchBrowser.DEBUG)
+ if (LaunchBrowser.DEBUG) {
JOptionPane.showMessageDialog(null, "Trying browse via webstart");
+ }
Boolean b = viaWebStart(url);
boolean success = b != null && b.booleanValue();
- if (LaunchBrowser.DEBUG)
+ if (LaunchBrowser.DEBUG) {
JOptionPane.showMessageDialog(null, " browse via webstart: " + success);
+ }
return success;
} catch (InvocationTargetException ite) {
@@ -114,6 +118,7 @@ public class JavaWebStart {
} catch (IllegalAccessException iae) {
assert true;
}
+ }
return false;
}
diff --git a/src/java/edu/umd/cs/findbugs/util/LaunchBrowser.java b/src/java/edu/umd/cs/findbugs/util/LaunchBrowser.java
index 0867f7b..4749134 100644
--- a/src/java/edu/umd/cs/findbugs/util/LaunchBrowser.java
+++ b/src/java/edu/umd/cs/findbugs/util/LaunchBrowser.java
@@ -75,13 +75,15 @@ public class LaunchBrowser {
static boolean showDocumentViaDesktop(URL u) {
- if (desktopObject != null && desktopBrowseMethod != null)
+ if (desktopObject != null && desktopBrowseMethod != null) {
try {
- if (DEBUG)
+ if (DEBUG) {
JOptionPane.showMessageDialog(null, "Trying desktop browse");
+ }
viaDesktop(u.toURI());
- if (DEBUG)
+ if (DEBUG) {
JOptionPane.showMessageDialog(null, "desktop browse succeeded");
+ }
return true;
} catch (InvocationTargetException ite) {
assert true;
@@ -92,19 +94,22 @@ public class LaunchBrowser {
} catch (URISyntaxException e) {
assert true;
}
+ }
return false;
}
static void viaDesktop(URI u) throws IllegalAccessException, InvocationTargetException {
- if (desktopBrowseMethod == null)
+ if (desktopBrowseMethod == null) {
throw new UnsupportedOperationException("Launch via desktop not available");
+ }
desktopBrowseMethod.invoke(desktopObject, u);
}
static boolean showDocumentViaExec(URL url) {
if (launchViaExec && !launchViaExecFailed) {
- if (DEBUG)
+ if (DEBUG) {
JOptionPane.showMessageDialog(null, "Trying exec browse");
+ }
try {
Process p = launchViaExec(url);
@@ -113,20 +118,24 @@ public class LaunchBrowser {
int exitValue = p.exitValue();
if (exitValue != 0) {
launchViaExecFailed = true;
- if (DEBUG)
+ if (DEBUG) {
JOptionPane.showMessageDialog(null, "exec browse launch failed with exit code " + exitValue);
+ }
return false;
}
- if (DEBUG)
+ if (DEBUG) {
JOptionPane.showMessageDialog(null, "exec browse succeeded");
+ }
return true;
} catch (IllegalThreadStateException e) {
- if (DEBUG)
+ if (DEBUG) {
JOptionPane.showMessageDialog(null, "exec browse succeeded but not done");
+ }
return true;
} catch (Exception e) {
- if (DEBUG)
+ if (DEBUG) {
JOptionPane.showMessageDialog(null, "exec browse failed" + e.getMessage());
+ }
launchViaExecFailed = true;
}
}
@@ -143,19 +152,22 @@ public class LaunchBrowser {
/**
* attempt to show the given URL. will first attempt via the JNLP api, then
* will try showViaExec().
- *
+ *
* @param url
* the URL
* @return true on success
*/
public static boolean showDocument(URL url) {
- if (showDocumentViaDesktop(url))
+ if (showDocumentViaDesktop(url)) {
return true;
- if (showDocumentViaExec(url))
+ }
+ if (showDocumentViaExec(url)) {
return true;
- if (JavaWebStart.showViaWebStart(url))
+ }
+ if (JavaWebStart.showViaWebStart(url)) {
return true;
+ }
return false;
diff --git a/src/java/edu/umd/cs/findbugs/util/MapCache.java b/src/java/edu/umd/cs/findbugs/util/MapCache.java
index ebf3722..e185e4d 100644
--- a/src/java/edu/umd/cs/findbugs/util/MapCache.java
+++ b/src/java/edu/umd/cs/findbugs/util/MapCache.java
@@ -28,7 +28,7 @@ import org.apache.bcel.classfile.JavaClass;
* Provide a HashMap that can only grow to a specified maximum capacity, with
* entries discarded using a LRU policy to keep the size of the HashMap within
* that bound.
- *
+ *
* @author pugh
*/
public class MapCache<K, V> extends LinkedHashMap<K, V> {
@@ -38,7 +38,7 @@ public class MapCache<K, V> extends LinkedHashMap<K, V> {
/**
* Create a new MapCache
- *
+ *
* @param maxCapacity
* - maximum number of entries in the map
*/
@@ -51,8 +51,9 @@ public class MapCache<K, V> extends LinkedHashMap<K, V> {
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
boolean result = size() > maxCapacity;
- if (false && result && eldest.getKey() instanceof JavaClass)
+ if (false && result && eldest.getKey() instanceof JavaClass) {
System.out.println("Dropping " + ((JavaClass) eldest.getKey()).getClassName());
+ }
return result;
}
diff --git a/src/java/edu/umd/cs/findbugs/util/MergeMap.java b/src/java/edu/umd/cs/findbugs/util/MergeMap.java
index 5c85067..9f8bc3e 100644
--- a/src/java/edu/umd/cs/findbugs/util/MergeMap.java
+++ b/src/java/edu/umd/cs/findbugs/util/MergeMap.java
@@ -32,8 +32,9 @@ public abstract class MergeMap<K, V> {
@Override
protected V mergeValues(V oldValue, V newValue) {
- if (oldValue.compareTo(newValue) > 0)
+ if (oldValue.compareTo(newValue) > 0) {
return newValue;
+ }
return oldValue;
}
}
@@ -43,8 +44,9 @@ public abstract class MergeMap<K, V> {
@Override
protected V mergeValues(V oldValue, V newValue) {
- if (oldValue.compareTo(newValue) < 0)
+ if (oldValue.compareTo(newValue) < 0) {
return newValue;
+ }
return oldValue;
}
}
@@ -68,8 +70,9 @@ public abstract class MergeMap<K, V> {
return v;
}
V result = mergeValues(currentValue, v);
- if (currentValue != result)
+ if (currentValue != result) {
map.put(k, v);
+ }
return result;
}
diff --git a/src/java/edu/umd/cs/findbugs/util/MultiMap.java b/src/java/edu/umd/cs/findbugs/util/MultiMap.java
index d73c1ee..68d9848 100644
--- a/src/java/edu/umd/cs/findbugs/util/MultiMap.java
+++ b/src/java/edu/umd/cs/findbugs/util/MultiMap.java
@@ -71,8 +71,9 @@ public class MultiMap<K, V> {
Collection<V> s = map.get(k);
if (s != null) {
s.remove(v);
- if (s.isEmpty())
+ if (s.isEmpty()) {
map.remove(k);
+ }
}
}
@@ -82,8 +83,9 @@ public class MultiMap<K, V> {
public Collection<V> get(K k) {
Collection<V> s = map.get(k);
- if (s != null)
+ if (s != null) {
return s;
+ }
return Collections.<V> emptySet();
}
diff --git a/src/java/edu/umd/cs/findbugs/util/Multiset.java b/src/java/edu/umd/cs/findbugs/util/Multiset.java
index 1932af8..564e706 100644
--- a/src/java/edu/umd/cs/findbugs/util/Multiset.java
+++ b/src/java/edu/umd/cs/findbugs/util/Multiset.java
@@ -27,6 +27,8 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
/**
* @author pwilliam
*/
@@ -63,8 +65,9 @@ public class Multiset<K> {
public boolean remove(K k) {
Integer v = map.get(k);
- if (v == null || v.intValue() == 0)
+ if (v == null || v.intValue() == 0) {
return false;
+ }
if (v.intValue() == 1) {
map.remove(k);
return true;
@@ -75,21 +78,24 @@ public class Multiset<K> {
public void add(K k, int val) {
Integer v = map.get(k);
- if (v == null)
+ if (v == null) {
map.put(k, val);
- else
+ } else {
map.put(k, v + val);
+ }
}
public void addAll(Iterable<K> c) {
- for (K k : c)
+ for (K k : c) {
add(k);
+ }
}
public int getCount(K k) {
Integer v = map.get(k);
- if (v == null)
+ if (v == null) {
return 0;
+ }
return v;
}
@@ -101,24 +107,29 @@ public class Multiset<K> {
return map.keySet();
}
+ @SuppressFBWarnings("DMI_ENTRY_SETS_MAY_REUSE_ENTRY_OBJECTS")
public Iterable<Map.Entry<K, Integer>> entriesInDecreasingFrequency() {
TreeSet<Map.Entry<K, Integer>> result = new TreeSet<Map.Entry<K, Integer>>(new EntryComparator<K>());
result.addAll(map.entrySet());
- if (result.size() != map.size())
- throw new IllegalStateException("Map " + map.getClass().getSimpleName()
+ if (result.size() != map.size()) {
+ throw new IllegalStateException("Map " + map.getClass().getSimpleName()
+ " reuses Map.Entry objects; entrySet can't be passed to addAll");
+ }
return result;
}
static class EntryComparator<E> implements Comparator<Map.Entry<E, Integer>>, Serializable {
+ @Override
public int compare(Entry<E, Integer> o1, Entry<E, Integer> o2) {
int c1 = o1.getValue();
int c2 = o2.getValue();
- if (c1 < c2)
+ if (c1 < c2) {
return 1;
- if (c1 > c2)
+ }
+ if (c1 > c2) {
return -1;
+ }
return System.identityHashCode(o1.getKey()) - System.identityHashCode(o2.getKey());
}
diff --git a/src/java/edu/umd/cs/findbugs/util/NullIterator.java b/src/java/edu/umd/cs/findbugs/util/NullIterator.java
index 75f74a5..a32005d 100644
--- a/src/java/edu/umd/cs/findbugs/util/NullIterator.java
+++ b/src/java/edu/umd/cs/findbugs/util/NullIterator.java
@@ -24,34 +24,37 @@ import java.util.NoSuchElementException;
/**
* An Iterator that returns no elements.
- *
+ *
* @author David Hovemeyer
*/
public class NullIterator<E> implements Iterator<E> {
/*
* (non-Javadoc)
- *
+ *
* @see java.util.Iterator#hasNext()
*/
+ @Override
public boolean hasNext() {
return false;
}
/*
* (non-Javadoc)
- *
+ *
* @see java.util.Iterator#next()
*/
+ @Override
public E next() {
throw new NoSuchElementException();
}
/*
* (non-Javadoc)
- *
+ *
* @see java.util.Iterator#remove()
*/
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
diff --git a/src/java/edu/umd/cs/findbugs/util/ProfilingMapCache.java b/src/java/edu/umd/cs/findbugs/util/ProfilingMapCache.java
index 73dceb1..b1d1e79 100644
--- a/src/java/edu/umd/cs/findbugs/util/ProfilingMapCache.java
+++ b/src/java/edu/umd/cs/findbugs/util/ProfilingMapCache.java
@@ -36,8 +36,9 @@ public class ProfilingMapCache<K, V> extends MapCache<K, V> {
@Override
public void run() {
System.out.println("Profile for map cache " + ProfilingMapCache.this.name);
- for (int i = 0; i < count.length; i++)
+ for (int i = 0; i < count.length; i++) {
System.out.printf("%4d %5d%n", i, count[i]);
+ }
}
});
}
@@ -63,8 +64,9 @@ public class ProfilingMapCache<K, V> extends MapCache<K, V> {
public String getStatistics() {
StringBuilder b = new StringBuilder();
- for (int c : count)
+ for (int c : count) {
b.append(c).append(" ");
+ }
return b.toString();
}
}
diff --git a/src/java/edu/umd/cs/findbugs/util/RegexStringMatcher.java b/src/java/edu/umd/cs/findbugs/util/RegexStringMatcher.java
index 11cb2a1..c986fe3 100644
--- a/src/java/edu/umd/cs/findbugs/util/RegexStringMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/util/RegexStringMatcher.java
@@ -24,16 +24,16 @@ import java.util.regex.Pattern;
/**
* StringMatcher that matches based on a regular expression.
- *
+ *
* @author David Hovemeyer
*/
public class RegexStringMatcher implements StringMatcher {
- private Pattern pattern;
+ private final Pattern pattern;
/**
* Constructor.
- *
+ *
* @param patStr
* a String defining the regular expression pattern to match
*/
@@ -41,6 +41,7 @@ public class RegexStringMatcher implements StringMatcher {
pattern = Pattern.compile(patStr);
}
+ @Override
public boolean matches(String s) {
Matcher m = pattern.matcher(s);
return m.matches();
diff --git a/src/java/edu/umd/cs/findbugs/util/SplitCamelCaseIdentifier.java b/src/java/edu/umd/cs/findbugs/util/SplitCamelCaseIdentifier.java
index cf2c136..719e45a 100644
--- a/src/java/edu/umd/cs/findbugs/util/SplitCamelCaseIdentifier.java
+++ b/src/java/edu/umd/cs/findbugs/util/SplitCamelCaseIdentifier.java
@@ -25,15 +25,15 @@ import java.util.Set;
/**
* Split a camel case identifier into individual words.
- *
+ *
* @author David Hovemeyer
*/
public class SplitCamelCaseIdentifier {
- private String ident;
+ private final String ident;
/**
* Constructor.
- *
+ *
* @param ident
* the identifier to split into words
*/
@@ -43,7 +43,7 @@ public class SplitCamelCaseIdentifier {
/**
* Split the identifier into words.
- *
+ *
* @return Collection of words in the identifier
*/
public Collection<String> split() {
@@ -70,8 +70,9 @@ public class SplitCamelCaseIdentifier {
while (i < s.length()) {
char c = s.charAt(i);
if (Character.isUpperCase(c)) {
- if (camelWord)
+ if (camelWord) {
break;
+ }
} else if (!camelWord) {
break;
}
diff --git a/src/java/edu/umd/cs/findbugs/util/StringMatcher.java b/src/java/edu/umd/cs/findbugs/util/StringMatcher.java
index 452adb1..31428d8 100644
--- a/src/java/edu/umd/cs/findbugs/util/StringMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/util/StringMatcher.java
@@ -21,13 +21,13 @@ package edu.umd.cs.findbugs.util;
/**
* A boolean predicate for matching String values.
- *
+ *
* @author David Hovemeyer
*/
public interface StringMatcher {
/**
* Return whether or not the given String matches.
- *
+ *
* @param s
* a String
* @return true if the String matches, false if it does not match
diff --git a/src/java/edu/umd/cs/findbugs/util/Strings.java b/src/java/edu/umd/cs/findbugs/util/Strings.java
index 91846fa..4723959 100644
--- a/src/java/edu/umd/cs/findbugs/util/Strings.java
+++ b/src/java/edu/umd/cs/findbugs/util/Strings.java
@@ -28,7 +28,7 @@ import org.apache.commons.lang.StringEscapeUtils;
/**
* A class for static String utility methods.
- *
+ *
* @author Brian Cole
*/
public class Strings {
@@ -36,7 +36,7 @@ public class Strings {
/**
* This is intended to be semantically equivalent to
* <code>source.replace(find, repl)</code> but also compatible with JDK 1.4.
- *
+ *
* @param source
* The String on which to operate
* @param find
@@ -61,7 +61,7 @@ public class Strings {
* also compatible with JDK 1.4. This concatenates the results of calling
* String.valueOf() on each element of the array, so this won't work well
* for multi-dimensional arrays.
- *
+ *
* @see java.lang.String#valueOf(Object)
* @see java.util.Arrays#toString(Object[])
* @see java.util.Arrays#deepToString(Object[])
@@ -73,7 +73,7 @@ public class Strings {
/**
* Trim trailing comma from given string.
- *
+ *
* @param s
* a string
* @return the same string with trailing comma trimmed (if any)
@@ -94,10 +94,12 @@ public class Strings {
private static final int xmlAllowedLowCharacterBound = 0x20;
private static boolean isInvalidXMLCharacter(int c) {
- if (c < xmlAllowedLowCharacterBound && c >= 0x0 &&
- // low-value characters allowed by XML 1.0 spec
- c != 0x9 && c != 0xA && c != 0xD)
+ if ((c < xmlAllowedLowCharacterBound && c >= 0x0 &&
+ // low-value characters allowed by XML 1.0 spec
+ // '\uFFFE' () cannot be deserialized by SAX reader.
+ c != 0x9 && c != 0xA && c != 0xD) || c == 0xFFFE) {
return true;
+ }
return false;
}
@@ -111,13 +113,14 @@ public class Strings {
* Initializes the map of characters to be escaped and their corresponding
* escape sequences. This method will be invoked automatically the first
* time a string is escaped/unescaped.
- *
+ *
* @see <a href="http://www.w3.org/TR/REC-xml/#charsets">Extensible Markup
* Language (XML) 1.0 (Fifth Edition)</a>
*/
public static void initializeEscapeMap() {
- if (xmlLowValueEscapeStringsInitialized == true)
+ if (xmlLowValueEscapeStringsInitialized == true) {
return;
+ }
/*
* synchronize the lazy initialization so things don't break if FindBugs
@@ -125,8 +128,9 @@ public class Strings {
* warning about the thread safety of this operation)
*/
synchronized (escapeInitLockObject) {
- if (xmlLowValueEscapeStringsInitialized == true)
+ if (xmlLowValueEscapeStringsInitialized == true) {
return;
+ }
for (int i = 0; i < xmlAllowedLowCharacterBound; i++) {
if (isInvalidXMLCharacter(i)) {
@@ -146,7 +150,7 @@ public class Strings {
* org.apache.commons.lang.StringEscapeUtils.escapeXml by escaping
* low-valued unprintable characters, which are not permitted by the W3C XML
* 1.0 specification.
- *
+ *
* @param s
* a string
* @return the same string with characters not permitted by the XML
@@ -160,8 +164,9 @@ public class Strings {
public static String escapeXml(String s) {
initializeEscapeMap();
- if (s == null || s.length() == 0)
+ if (s == null || s.length() == 0) {
return s;
+ }
char[] sChars = s.toCharArray();
StringBuilder sb = new StringBuilder();
@@ -171,13 +176,14 @@ public class Strings {
// append intermediate string to string builder
sb.append(sChars, lastReplacement, i - lastReplacement);
// substitute control character with escape sequence
- sb.append(xmlLowValueEscapeStrings[sChars[i]]);
+ sb.append(sChars[i] == 0xFFFE ? "\\ufffe" : xmlLowValueEscapeStrings[sChars[i]]);
// advance last pointer past this character
lastReplacement = i + 1;
}
}
- if (lastReplacement < sChars.length)
+ if (lastReplacement < sChars.length) {
sb.append(sChars, lastReplacement, sChars.length - lastReplacement);
+ }
return StringEscapeUtils.escapeXml(sb.toString());
}
@@ -195,12 +201,14 @@ public class Strings {
* invoked automatically the first time a string is unescaped.
*/
public static boolean initializeUnescapePattern() {
- if (paternIsInitialized == true)
+ if (paternIsInitialized == true) {
return true;
+ }
synchronized (unescapeInitLockObject) {
- if (paternIsInitialized == true)
+ if (paternIsInitialized == true) {
return true;
+ }
try {
unescapePattern = Pattern.compile(unicodeUnescapeMatchExpression);
@@ -224,7 +232,7 @@ public class Strings {
* org.apache.commons.lang.StringEscapeUtils.unescapeXml by unescaping
* low-valued unprintable characters, which are not permitted by the W3C XML
* 1.0 specification.
- *
+ *
* @param s
* a string
* @return the same string with XML entities/escape sequences unescaped
@@ -242,11 +250,13 @@ public class Strings {
* we can't escape the string if the pattern doesn't compile! (but that
* should never happen since the pattern is static)
*/
- if (!initializeUnescapePattern())
+ if (!initializeUnescapePattern()) {
return s;
+ }
- if (s == null || s.length() == 0)
+ if (s == null || s.length() == 0) {
return s;
+ }
/*
* skip this expensive check entirely if there are no substrings
diff --git a/src/java/edu/umd/cs/findbugs/util/SubtypeTypeMatcher.java b/src/java/edu/umd/cs/findbugs/util/SubtypeTypeMatcher.java
index 89a3c21..3826871 100644
--- a/src/java/edu/umd/cs/findbugs/util/SubtypeTypeMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/util/SubtypeTypeMatcher.java
@@ -31,15 +31,15 @@ import edu.umd.cs.findbugs.classfile.IAnalysisCache;
/**
* Type matcher that determines if a candidate Type is a subtype of a given
* Type.
- *
+ *
* @author David Hovemeyer
*/
public class SubtypeTypeMatcher implements TypeMatcher {
- private ReferenceType supertype;
+ private final ReferenceType supertype;
/**
* Constructor.
- *
+ *
* @param supertype
* a ReferenceType: this TypeMatcher will test whether or not
* candidate Types are subtypes of this Type
@@ -50,7 +50,7 @@ public class SubtypeTypeMatcher implements TypeMatcher {
/**
* Constructor.
- *
+ *
* @param classDescriptor
* a ClassDescriptor naming a class: this TypeMatcher will test
* whether or not candidate Types are subtypes of the class
@@ -59,6 +59,7 @@ public class SubtypeTypeMatcher implements TypeMatcher {
this(BCELUtil.getObjectTypeInstance(classDescriptor.toDottedClassName()));
}
+ @Override
public boolean matches(Type t) {
if (!(t instanceof ReferenceType)) {
return false;
diff --git a/src/java/edu/umd/cs/findbugs/util/TestDesktopIntegration.java b/src/java/edu/umd/cs/findbugs/util/TestDesktopIntegration.java
index f464fae..ab98c8d 100644
--- a/src/java/edu/umd/cs/findbugs/util/TestDesktopIntegration.java
+++ b/src/java/edu/umd/cs/findbugs/util/TestDesktopIntegration.java
@@ -51,17 +51,18 @@ import edu.umd.cs.findbugs.SystemProperties;
public class TestDesktopIntegration extends JPanel {
private static String[] propertyNames = { "java.version", "java.vendor", "java.vendor.url", "java.home",
- "java.vm.specification.version", "java.vm.specification.vendor", "java.vm.specification.name", "java.vm.version",
- "java.vm.vendor", "java.vm.name", "java.specification.version", "java.specification.vendor",
- "java.specification.name", "java.class.version", "java.class.path", "java.library.path", "java.io.tmpdir",
- "java.compiler", "java.ext.dirs", "os.name", "os.arch", "os.version", "file.separator", "path.separator",
- "line.separator", "user.name", "user.home", "user.dir" };
+ "java.vm.specification.version", "java.vm.specification.vendor", "java.vm.specification.name", "java.vm.version",
+ "java.vm.vendor", "java.vm.name", "java.specification.version", "java.specification.vendor",
+ "java.specification.name", "java.class.version", "java.class.path", "java.library.path", "java.io.tmpdir",
+ "java.compiler", "java.ext.dirs", "os.name", "os.arch", "os.version", "file.separator", "path.separator",
+ "line.separator", "user.name", "user.home", "user.dir" };
public static void main(String args[]) throws Exception {
String u = SystemProperties.getProperty("findbugs.browserTestURL", "http://findbugs.sourceforge.net/");
url = new URL(u);
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
createAndShowGUI();
}
@@ -95,7 +96,7 @@ public class TestDesktopIntegration extends JPanel {
/*
* (non-Javadoc)
- *
+ *
* @see java.io.Writer#flush()
*/
@Override
@@ -105,7 +106,7 @@ public class TestDesktopIntegration extends JPanel {
/*
* (non-Javadoc)
- *
+ *
* @see java.io.Writer#write(char[], int, int)
*/
@Override
@@ -132,12 +133,14 @@ public class TestDesktopIntegration extends JPanel {
console.setEditable(false);
console.setLineWrap(true);
add(scrollPane);
- } else
+ } else {
add(new JLabel("These buttons should view " + url), BorderLayout.NORTH);
+ }
if (LaunchBrowser.desktopFeasible()) {
JButton desktop = new JButton("Use java.awt.Desktop");
desktop.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
try {
@@ -161,6 +164,7 @@ public class TestDesktopIntegration extends JPanel {
if (LaunchBrowser.webstartFeasible()) {
JButton jnlp = new JButton("Use jnlp");
jnlp.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
try {
@@ -183,6 +187,7 @@ public class TestDesktopIntegration extends JPanel {
top.add(exec);
if (LaunchBrowser.launchViaExec) {
exec.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
try {
writer.println("Launch via exec " + LaunchBrowser.execCommand);
@@ -210,6 +215,7 @@ public class TestDesktopIntegration extends JPanel {
top.add(chooseFile);
chooseFile.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
final JFileChooser fc = new JFileChooser();
int retvel = fc.showOpenDialog(TestDesktopIntegration.this);
@@ -236,8 +242,9 @@ public class TestDesktopIntegration extends JPanel {
writer.println("System properties:");
TreeSet<String> props = new TreeSet<String>();
for (Object o : System.getProperties().keySet()) {
- if (o instanceof String)
+ if (o instanceof String) {
props.add((String) o);
+ }
}
props.addAll(Arrays.asList(propertyNames));
diff --git a/src/java/edu/umd/cs/findbugs/util/TopologicalSort.java b/src/java/edu/umd/cs/findbugs/util/TopologicalSort.java
index 2d52a9f..2e35e25 100644
--- a/src/java/edu/umd/cs/findbugs/util/TopologicalSort.java
+++ b/src/java/edu/umd/cs/findbugs/util/TopologicalSort.java
@@ -59,6 +59,7 @@ public class TopologicalSort {
this.base = base;
}
+ @Override
public Collection<E> getOutEdges(E e) {
Collection<E> result = map.get(e);
if (result == null) {
@@ -82,19 +83,22 @@ public class TopologicalSort {
}
public static <E> void countBadEdges(List<E> elements, OutEdges<E> outEdges) {
- if (!DEBUG)
+ if (!DEBUG) {
return;
+ }
HashSet<E> seen = new HashSet<E>();
HashSet<E> all = new HashSet<E>(elements);
int result = 0;
int total = 0;
for (E e : elements) {
- for (E e2 : outEdges.getOutEdges(e))
+ for (E e2 : outEdges.getOutEdges(e)) {
if (e != e2 && all.contains(e2) && !outEdges.getOutEdges(e2).contains(e)) {
total++;
- if (!seen.contains(e2))
+ if (!seen.contains(e2)) {
result++;
+ }
}
+ }
seen.add(e);
}
System.out.println(" bad edges are " + result + "/" + total);
@@ -120,19 +124,24 @@ public class TopologicalSort {
Set<E> consider = new HashSet<E>();
+ @Override
public List<E> compute() {
- for (E e : consider)
+ for (E e : consider) {
visit(e);
+ }
return result;
}
void visit(E e) {
- if (!consider.contains(e))
+ if (!consider.contains(e)) {
return;
- if (!visited.add(e))
+ }
+ if (!visited.add(e)) {
return;
- for (E e2 : outEdges.getOutEdges(e))
+ }
+ for (E e2 : outEdges.getOutEdges(e)) {
visit(e2);
+ }
result.add(e);
}
@@ -140,8 +149,9 @@ public class TopologicalSort {
static class Worker2<E> implements SortAlgorithm<E> {
Worker2(Collection<E> consider, OutEdges<E> outEdges) {
- if (outEdges == null)
+ if (outEdges == null) {
throw new IllegalArgumentException("outEdges must not be null");
+ }
this.consider = new LinkedHashSet<E>(consider);
this.outEdges = outEdges;
@@ -167,6 +177,7 @@ public class TopologicalSort {
oEdges.removeAll(e);
}
+ @Override
public List<E> compute() {
ArrayList<E> doFirst = new ArrayList<E>(consider.size());
ArrayList<E> doLast = new ArrayList<E>(consider.size());
@@ -175,12 +186,14 @@ public class TopologicalSort {
iEdges = new MultiMap<E, E>(LinkedList.class);
oEdges = new MultiMap<E, E>(LinkedList.class);
- for (E e : consider)
- for (E e2 : outEdges.getOutEdges(e))
+ for (E e : consider) {
+ for (E e2 : outEdges.getOutEdges(e)) {
if (e != e2 && consider.contains(e2)) {
iEdges.add(e2, e);
oEdges.add(e, e2);
}
+ }
+ }
for (E e : consider) {
HashSet<E> both = new HashSet<E>(iEdges.get(e));
both.retainAll(oEdges.get(e));
@@ -198,15 +211,17 @@ public class TopologicalSort {
if (oEdges.get(e).isEmpty()) {
doFirst.add(e);
removeVertex(e);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("do " + e + " first");
+ }
i.remove();
foundSomething = true;
} else if (iEdges.get(e).isEmpty()) {
doLast.add(e);
removeVertex(e);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("do " + e + " last");
+ }
i.remove();
foundSomething = true;
} else {
@@ -250,8 +265,9 @@ public class TopologicalSort {
int myScore = score(e);
if (outEdges instanceof OutEdges2) {
int score2 = ((OutEdges2<E>) outEdges).score(e);
- if (score2 > 1)
+ if (score2 > 1) {
score2 += 11;
+ }
myScore = 5 * myScore + score2;
}
return myScore;
@@ -263,16 +279,20 @@ public class TopologicalSort {
*/
private int score(E e) {
int myScore = 0;
- for (E e2 : oEdges.get(e))
- if (iEdges.get(e2).size() == 1)
+ for (E e2 : oEdges.get(e)) {
+ if (iEdges.get(e2).size() == 1) {
myScore -= 2;
- else
+ } else {
myScore -= 1;
- for (E e2 : iEdges.get(e))
- if (oEdges.get(e2).size() == 1)
+ }
+ }
+ for (E e2 : iEdges.get(e)) {
+ if (oEdges.get(e2).size() == 1) {
myScore += 2;
- else
+ } else {
myScore += 1;
+ }
+ }
return myScore;
}
diff --git a/src/java/edu/umd/cs/findbugs/util/TripleKeyHashMap.java b/src/java/edu/umd/cs/findbugs/util/TripleKeyHashMap.java
index 3762d8f..410676e 100644
--- a/src/java/edu/umd/cs/findbugs/util/TripleKeyHashMap.java
+++ b/src/java/edu/umd/cs/findbugs/util/TripleKeyHashMap.java
@@ -30,8 +30,9 @@ public class TripleKeyHashMap<K1, K2, K3, V> {
public V get(K1 k1, K2 k2, K3 k3) {
DualKeyHashMap<K2, K3, V> m = map.get(k1);
- if (m == null)
+ if (m == null) {
return null;
+ }
return m.get(k2, k3);
}
diff --git a/src/java/edu/umd/cs/findbugs/util/TypeMatcher.java b/src/java/edu/umd/cs/findbugs/util/TypeMatcher.java
index 137b4a9..dac0d21 100644
--- a/src/java/edu/umd/cs/findbugs/util/TypeMatcher.java
+++ b/src/java/edu/umd/cs/findbugs/util/TypeMatcher.java
@@ -23,13 +23,13 @@ import org.apache.bcel.generic.Type;
/**
* Predicate for matching types.
- *
+ *
* @author David Hovemeyer
*/
public interface TypeMatcher {
/**
* Determine whether given type matches this predicate.
- *
+ *
* @param t
* a Type
* @return true if the Type matches, false otherwise
diff --git a/src/java/edu/umd/cs/findbugs/util/Util.java b/src/java/edu/umd/cs/findbugs/util/Util.java
index ae52825..35a5a49 100644
--- a/src/java/edu/umd/cs/findbugs/util/Util.java
+++ b/src/java/edu/umd/cs/findbugs/util/Util.java
@@ -60,69 +60,69 @@ import javax.annotation.WillCloseWhenClosed;
import javax.annotation.WillNotClose;
import edu.umd.cs.findbugs.SystemProperties;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import edu.umd.cs.findbugs.charsets.UTF8;
/**
* @author William Pugh
*/
public class Util {
-
+
public static Thread startDameonThread(Thread t) {
t.setDaemon(true);
t.start();
return t;
}
-
+
public static Thread runInDameonThread(Runnable r, String name) {
Thread t = new Thread(r, name);
return startDameonThread(t);
-
+
}
public static Thread runInDameonThread(Runnable r) {
Thread t = new Thread(r);
return startDameonThread(t);
-
+
}
-
+
public static int sign(int x) {
- if (x < 0)
+ if (x < 0) {
return -1;
- if (x > 0)
+ }
+ if (x > 0) {
return 1;
+ }
return 0;
}
/**
* return sign of x - y
- *
- * @param x
- * @param y
- * @return
*/
public static int compare(int x, int y) {
- if (x > y)
+ if (x > y) {
return 1;
- if (x < y)
+ }
+ if (x < y) {
return -1;
+ }
return 0;
}
/**
* return sign of x - y
- *
- * @param x
- * @param y
- * @return
*/
public static int compare(long x, long y) {
- if (x > y)
+ if (x > y) {
return 1;
- if (x < y)
+ }
+ if (x < y) {
return -1;
+ }
return 0;
}
public static Iterable<Integer> setBitIteratable(final BitSet b) {
return new Iterable<Integer>() {
+ @Override
public Iterator<Integer> iterator() {
return setBitIterator(b);
}
@@ -133,16 +133,19 @@ public class Util {
return new Iterator<Integer>() {
int nextBit = b.nextSetBit(0);
+ @Override
public boolean hasNext() {
return nextBit >= 0;
}
+ @Override
public Integer next() {
int result = nextBit;
nextBit = b.nextSetBit(nextBit + 1);
return result;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -151,21 +154,23 @@ public class Util {
public static String repeat(String s, int number) {
StringBuilder b = new StringBuilder(s.length() * number);
- for (int i = 0; i < number; i++)
+ for (int i = 0; i < number; i++) {
b.append(s);
+ }
return b.toString();
}
static Collection<Runnable> runAtShutdown;
public static String getNetworkErrorMessage(Throwable e) {
- if (e.getClass().getSimpleName().equals("InvalidProtocolBufferException")) {
- return "Your Internet provider may require you to log in via your web browser.";
+ if ("InvalidProtocolBufferException".equals(e.getClass().getSimpleName())) {
+ return "Your Internet provider may require you to log in via your web browser.";
}
if (e instanceof UnknownHostException) {
return "You may not be connected to the Internet.";
- } else
+ } else {
return e.getClass().getSimpleName() + ": " + e.getMessage();
+ }
}
static class ShutdownLogging {
@@ -195,38 +200,46 @@ public class Util {
}
public static <T> Set<T> emptyOrNonnullSingleton(T t) {
- if (t == null)
+ if (t == null) {
return Collections.<T> emptySet();
+ }
return Collections.<T> singleton(t);
}
public static <K, V> Map<K, V> immutableMap(Map<K, V> map) {
- if (map.size() == 0)
+ if (map.size() == 0) {
return Collections.<K, V> emptyMap();
+ }
return Collections.<K, V> unmodifiableMap(map);
}
public static int nullSafeHashcode(@CheckForNull Object o) {
- if (o == null)
+ if (o == null) {
return 0;
+ }
return o.hashCode();
}
public static <T> boolean nullSafeEquals(@CheckForNull T o1, @CheckForNull T o2) {
- if (o1 == o2)
+ if (o1 == o2) {
return true;
- if (o1 == null || o2 == null)
+ }
+ if (o1 == null || o2 == null) {
return false;
+ }
return o1.equals(o2);
}
public static <T extends Comparable<? super T>> int nullSafeCompareTo(@CheckForNull T o1, @CheckForNull T o2) {
- if (o1 == o2)
+ if (o1 == o2) {
return 0;
- if (o1 == null)
+ }
+ if (o1 == null) {
return -1;
- if (o2 == null)
+ }
+ if (o2 == null) {
return 1;
+ }
return o1.compareTo(o2);
}
@@ -252,8 +265,9 @@ public class Util {
public static void closeSilently(@WillClose Connection c) {
try {
- if (c != null)
+ if (c != null) {
c.close();
+ }
} catch (SQLException e) {
assert true;
}
@@ -261,8 +275,9 @@ public class Util {
public static void closeSilently(@WillClose PreparedStatement c) {
try {
- if (c != null)
+ if (c != null) {
c.close();
+ }
} catch (SQLException e) {
assert true;
}
@@ -270,8 +285,9 @@ public class Util {
public static void closeSilently(@WillClose ResultSet c) {
try {
- if (c != null)
+ if (c != null) {
c.close();
+ }
} catch (SQLException e) {
assert true;
}
@@ -279,8 +295,9 @@ public class Util {
public static void closeSilently(@WillClose InputStream in) {
try {
- if (in != null)
+ if (in != null) {
in.close();
+ }
} catch (IOException e) {
assert true;
}
@@ -288,8 +305,9 @@ public class Util {
public static void closeSilently(@WillClose Reader in) {
try {
- if (in != null)
+ if (in != null) {
in.close();
+ }
} catch (IOException e) {
assert true;
}
@@ -297,8 +315,9 @@ public class Util {
public static void closeSilently(@WillClose OutputStream out) {
try {
- if (out != null)
+ if (out != null) {
out.close();
+ }
} catch (IOException e) {
assert true;
}
@@ -306,17 +325,19 @@ public class Util {
public static void closeSilently(@WillClose Closeable out) {
try {
- if (out != null)
+ if (out != null) {
out.close();
+ }
} catch (IOException e) {
assert true;
}
}
-
+
public static void closeSilently(@WillClose ZipFile zip) {
try {
- if (zip != null)
+ if (zip != null) {
zip.close();
+ }
} catch (IOException e) {
assert true;
}
@@ -324,9 +345,11 @@ public class Util {
static final Pattern tag = Pattern.compile("^\\s*<(\\w+)");
+ @SuppressFBWarnings("OS_OPEN_STREAM")
public static String getXMLType(@WillNotClose InputStream in) throws IOException {
- if (!in.markSupported())
+ if (!in.markSupported()) {
throw new IllegalArgumentException("Input stream does not support mark");
+ }
in.mark(5000);
BufferedReader r = null;
@@ -337,11 +360,13 @@ public class Util {
int count = 0;
while (count < 4) {
s = r.readLine();
- if (s == null)
+ if (s == null) {
break;
+ }
Matcher m = tag.matcher(s);
- if (m.find())
+ if (m.find()) {
return m.group(1);
+ }
}
throw new IOException("Didn't find xml tag");
} finally {
@@ -357,8 +382,9 @@ public class Util {
}
private static String getFileExtension(String name) {
int lastDot = name.lastIndexOf('.');
- if (lastDot == -1)
+ if (lastDot == -1) {
return "";
+ }
return name.substring(lastDot + 1);
}
@@ -368,9 +394,10 @@ public class Util {
public static String getFileExtensionIgnoringGz(File f) {
String name = f.getName().toLowerCase();
- if (name.endsWith(".gz"))
+ if (name.endsWith(".gz")) {
name = name.substring(0,name.length()-3);
- return getFileExtension(name);
+ }
+ return getFileExtension(name);
}
public static void throwIOException(String msg, Throwable cause) throws IOException {
@@ -386,22 +413,28 @@ public class Util {
*/
public static <E> E first(Iterable<E> i) {
Iterator<E> iterator = i.iterator();
- if (!iterator.hasNext())
+ if (!iterator.hasNext()) {
throw new IllegalArgumentException("iterator has no elements");
+ }
return iterator.next();
}
public static String commonPrefix(String s1, String s2) {
- if (s1 == null)
+ if (s1 == null) {
return s2;
- if (s2 == null)
+ }
+ if (s2 == null) {
return s1;
+ }
int minLength = Math.min(s1.length(), s2.length());
- for (int i = 0; i < minLength; i++)
- if (s1.charAt(i) != s2.charAt(i))
+ for (int i = 0; i < minLength; i++) {
+ if (s1.charAt(i) != s2.charAt(i)) {
return s1.substring(0, i);
- if (s1.length() == minLength)
+ }
+ }
+ if (s1.length() == minLength) {
return s1;
+ }
assert s2.length() == minLength;
return s2;
@@ -523,10 +556,12 @@ public class Util {
}
public static <K> Set<K> addTo(Set<K> s, K k) {
- if (s.isEmpty())
+ if (s.isEmpty()) {
return Collections.singleton(k);
- if (s.contains(k))
+ }
+ if (s.contains(k)) {
return s;
+ }
if (s instanceof HashSet) {
s.add(k);
return s;
@@ -538,10 +573,12 @@ public class Util {
}
public static <K> List<K> addTo(List<K> s, K k) {
- if (s.isEmpty())
+ if (s.isEmpty()) {
return Collections.singletonList(k);
- if (!(s instanceof ArrayList))
+ }
+ if (!(s instanceof ArrayList)) {
s = makeSmallArrayList(s);
+ }
s.add(k);
return s;
}
diff --git a/src/java/edu/umd/cs/findbugs/util/WriteOnceProperties.java b/src/java/edu/umd/cs/findbugs/util/WriteOnceProperties.java
index 3943c47..ed7d275 100644
--- a/src/java/edu/umd/cs/findbugs/util/WriteOnceProperties.java
+++ b/src/java/edu/umd/cs/findbugs/util/WriteOnceProperties.java
@@ -7,50 +7,51 @@ import java.util.Properties;
public class WriteOnceProperties extends Properties {
private static final long serialVersionUID = 1L;
+ private final Map<String, PropertyReadAt> propertReadAt = new HashMap<String, PropertyReadAt>();
static class PropertyReadAt extends Exception {
private static final long serialVersionUID = 1L;
}
- private final Map<String, PropertyReadAt> propertReadAt = new HashMap<String, PropertyReadAt>();
-
private WriteOnceProperties(Properties initialValue) {
super.putAll(initialValue);
}
@Override
- public boolean equals(Object o) {
- return super.equals(o);
+ public final synchronized int hashCode() {
+ return super.hashCode();
}
+ /* overridden to avoid EQ_DOESNT_OVERRIDE_EQUALS */
@Override
- public int hashCode() {
- return super.hashCode();
+ public final synchronized boolean equals(Object o) {
+ return super.equals(o);
}
@Override
- public String getProperty(String key) {
+ public synchronized String getProperty(String key) {
String result = super.getProperty(key);
- if (result != null && result.length() > 0 && !propertReadAt.containsKey(key))
+ if (result != null && result.length() > 0 && !propertReadAt.containsKey(key)) {
propertReadAt.put(key, new PropertyReadAt());
+ }
return result;
}
@Override
- public String getProperty(String key, String defaultValue) {
+ public synchronized String getProperty(String key, String defaultValue) {
String result = super.getProperty(key, defaultValue);
- if (result != null && result.length() > 0 && !propertReadAt.containsKey(key))
+ if (result != null && result.length() > 0 && !propertReadAt.containsKey(key)) {
propertReadAt.put(key, new PropertyReadAt());
+ }
return result;
}
@Override
- public Object setProperty(String key, String value) {
+ public synchronized Object setProperty(String key, String value) {
if (propertReadAt.containsKey(key) && !value.equals(super.getProperty(key))) {
IllegalStateException e = new IllegalStateException("Changing property '" + key + "' to '" + value
+ "' after it has already been read as '" + super.getProperty(key) + "'");
e.initCause(propertReadAt.get(key));
-
throw e;
}
return super.setProperty(key, value);
@@ -58,8 +59,9 @@ public class WriteOnceProperties extends Properties {
public static void makeSystemPropertiesWriteOnce() {
Properties properties = System.getProperties();
- if (properties instanceof WriteOnceProperties)
+ if (properties instanceof WriteOnceProperties) {
return;
+ }
System.setProperties(new WriteOnceProperties(properties));
}
@@ -76,9 +78,6 @@ public class WriteOnceProperties extends Properties {
}
- /**
- *
- */
private static void dumpProperties() {
Properties properties = System.getProperties();
diff --git a/src/java/edu/umd/cs/findbugs/visitclass/AnnotationVisitor.java b/src/java/edu/umd/cs/findbugs/visitclass/AnnotationVisitor.java
index 426f482..9782d75 100644
--- a/src/java/edu/umd/cs/findbugs/visitclass/AnnotationVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/visitclass/AnnotationVisitor.java
@@ -18,20 +18,14 @@
*/
package edu.umd.cs.findbugs.visitclass;
-import java.io.DataInputStream;
-import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
+import javax.annotation.CheckForNull;
+
import org.apache.bcel.classfile.AnnotationEntry;
import org.apache.bcel.classfile.Annotations;
import org.apache.bcel.classfile.ArrayElementValue;
-import org.apache.bcel.classfile.Constant;
-import org.apache.bcel.classfile.ConstantDouble;
-import org.apache.bcel.classfile.ConstantFloat;
-import org.apache.bcel.classfile.ConstantInteger;
-import org.apache.bcel.classfile.ConstantLong;
-import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.ElementValue;
import org.apache.bcel.classfile.ElementValuePair;
import org.apache.bcel.classfile.ParameterAnnotationEntry;
@@ -39,33 +33,23 @@ import org.apache.bcel.classfile.ParameterAnnotations;
import org.apache.bcel.classfile.SimpleElementValue;
import edu.umd.cs.findbugs.SystemProperties;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
import edu.umd.cs.findbugs.util.ClassName;
/**
* Subclass of PreorderVisitor that visits annotations on classes, fields,
* methods, and method parameters.
- *
+ *
* @author William Pugh
*/
public class AnnotationVisitor extends PreorderVisitor {
-
- private static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations";
-
-
- private static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
-
-
- private static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
-
- private static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
-
static final boolean DEBUG = SystemProperties.getBoolean("annotation.visitor");
/**
* Visit annotation on a class, field or method
- *
+ *
* @param annotationClass
* class of annotation
* @param map
@@ -87,8 +71,9 @@ public class AnnotationVisitor extends PreorderVisitor {
try {
ElementValue ev = map.get(parameter);
- if (ev instanceof SimpleElementValue)
+ if (ev instanceof SimpleElementValue) {
return ((SimpleElementValue) ev).getValueString();
+ }
return null;
} catch (Exception e) {
return null;
@@ -96,24 +81,27 @@ public class AnnotationVisitor extends PreorderVisitor {
}
}
+ @CheckForNull
+ @SuppressFBWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS")
protected static String[] getAnnotationParameterAsStringArray(Map<String, ElementValue> map, String parameter) {
try {
ElementValue e = map.get(parameter);
ArrayElementValue a = (ArrayElementValue) e;
int size = a.getElementValuesArraySize();
String[] result = new String[size];
- for (int i = 0; i < size; i++)
- result[i] = ((SimpleElementValue) a.getElementValuesArray()[i]).getValueString();
+ ElementValue[] elementValuesArray = a.getElementValuesArray();
+ for (int i = 0; i < size; i++) {
+ result[i] = ((SimpleElementValue) elementValuesArray[i]).getValueString();
+ }
return result;
} catch (Exception e) {
return null;
-
}
}
/**
* Visit annotation on a method parameter
- *
+ *
* @param p
* parameter number, starting at zero ("this" parameter is not
* counted)
@@ -132,45 +120,59 @@ public class AnnotationVisitor extends PreorderVisitor {
public void visitSyntheticParameterAnnotation(int p, boolean runtimeVisible) {
}
-
+ /*
+
+ private static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations";
+ private static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
+ private static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
+ private static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
+
private Map<String, Object> readAnnotationValues(DataInputStream bytes, int numPairs) throws IOException {
Map<String, Object> values = new HashMap<String, Object>();
for (int j = 0; j < numPairs; j++) {
int memberNameIndex = bytes.readUnsignedShort();
String memberName = ((ConstantUtf8) getConstantPool().getConstant(memberNameIndex)).getBytes();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("memberName: " + memberName);
+ }
Object value = readAnnotationValue(bytes);
- if (DEBUG)
+ if (DEBUG) {
System.out.println(memberName + ":" + value);
+ }
values.put(memberName, value);
}
return values;
}
+
private @DottedClassName
String getAnnotationName(DataInputStream bytes) throws IOException {
int annotationNameIndex = bytes.readUnsignedShort();
String annotationName = ((ConstantUtf8) getConstantPool().getConstant(annotationNameIndex)).getBytes().replace('/', '.');
annotationName = annotationName.substring(1, annotationName.length() - 1);
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Annotation name: " + annotationName);
+ }
return annotationName;
}
+
private Object readAnnotationValue(DataInputStream bytes) throws IOException {
try {
char tag = (char) bytes.readUnsignedByte();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("tag: " + tag);
+ }
switch (tag) {
case '[': {
int sz = bytes.readUnsignedShort();
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Array of " + sz + " entries");
+ }
Object[] result = new Object[sz];
- for (int i = 0; i < sz; i++)
+ for (int i = 0; i < sz; i++) {
result[i] = readAnnotationValue(bytes);
+ }
return result;
}
case 'B':
@@ -206,14 +208,17 @@ public class AnnotationVisitor extends PreorderVisitor {
return ((ConstantUtf8) c).getBytes();
case 'c':
String cName = ((ConstantUtf8) c).getBytes().replace('/', '.');
- if (cName.startsWith("L") && cName.endsWith(";"))
+ if (cName.startsWith("L") && cName.endsWith(";")) {
cName = cName.substring(1, cName.length() - 1);
- if (DEBUG)
+ }
+ if (DEBUG) {
System.out.println("cName: " + cName);
+ }
return cName;
default:
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Impossible");
+ }
throw new IllegalStateException("Impossible");
}
case '@':
@@ -222,8 +227,9 @@ public class AnnotationVisitor extends PreorderVisitor {
int cp1 = bytes.readUnsignedShort();
ConstantUtf8 c1 = (ConstantUtf8) getConstantPool().getConstant(cp1);
String cName = c1.getBytes().replace('/', '.');
- if (cName.startsWith("L") && cName.endsWith(";"))
+ if (cName.startsWith("L") && cName.endsWith(";")) {
cName = cName.substring(1, cName.length() - 1);
+ }
int cp2 = bytes.readUnsignedShort();
ConstantUtf8 c2 = (ConstantUtf8) getConstantPool().getConstant(cp2);
String result = cName + "." + c2.getBytes();
@@ -231,8 +237,9 @@ public class AnnotationVisitor extends PreorderVisitor {
return result;
}
default:
- if (DEBUG)
+ if (DEBUG) {
System.out.println("Unexpected tag of " + tag);
+ }
throw new IllegalArgumentException("Unexpected tag of " + tag);
}
} catch (RuntimeException e) {
@@ -243,6 +250,7 @@ public class AnnotationVisitor extends PreorderVisitor {
throw e;
}
}
+ */
@Override
public void visitParameterAnnotation(ParameterAnnotations arg0) {
@@ -258,8 +266,9 @@ public class AnnotationVisitor extends PreorderVisitor {
boolean runtimeVisible = ae.isRuntimeVisible();
String name = ClassName.fromFieldSignature(ae.getAnnotationType());
- if (name == null)
+ if (name == null) {
continue;
+ }
name = ClassName.toDottedClassName(name);
Map<String, ElementValue> map = new HashMap<String, ElementValue>();
for (ElementValuePair ev : ae.getElementValuePairs()) {
@@ -273,7 +282,7 @@ public class AnnotationVisitor extends PreorderVisitor {
/*
* (non-Javadoc)
- *
+ *
* @see
* org.apache.bcel.classfile.Visitor#visitAnnotation(org.apache.bcel.classfile
* .Annotations)
@@ -283,8 +292,9 @@ public class AnnotationVisitor extends PreorderVisitor {
for (AnnotationEntry ae : arg0.getAnnotationEntries()) {
boolean runtimeVisible = ae.isRuntimeVisible();
String name = ClassName.fromFieldSignature(ae.getAnnotationType());
- if (name == null)
+ if (name == null) {
continue;
+ }
name = ClassName.toDottedClassName(name);
Map<String, ElementValue> map = new HashMap<String, ElementValue>();
for (ElementValuePair ev : ae.getElementValuePairs()) {
diff --git a/src/java/edu/umd/cs/findbugs/visitclass/BetterVisitor.java b/src/java/edu/umd/cs/findbugs/visitclass/BetterVisitor.java
index bafb9a8..5d62092 100644
--- a/src/java/edu/umd/cs/findbugs/visitclass/BetterVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/visitclass/BetterVisitor.java
@@ -60,7 +60,7 @@ import org.apache.bcel.classfile.Visitor;
/**
* Fixedup of from org.apache.bcel.classfile.Visitor
- *
+ *
* @author <A HREF="http://www.cs.umd.edu/~pugh">William Pugh</A>
* @version 980818
*/
@@ -213,137 +213,170 @@ public abstract class BetterVisitor implements Visitor {
}
// Attributes
+ @Override
public void visitCode(Code obj) {
visit(obj);
}
+ @Override
public void visitCodeException(CodeException obj) {
visit(obj);
}
// Constants
+ @Override
public void visitConstantClass(ConstantClass obj) {
visit(obj);
}
+ @Override
public void visitConstantDouble(ConstantDouble obj) {
visit(obj);
}
+ @Override
public void visitConstantFieldref(ConstantFieldref obj) {
visit(obj);
}
+ @Override
public void visitConstantFloat(ConstantFloat obj) {
visit(obj);
}
+ @Override
public void visitConstantInteger(ConstantInteger obj) {
visit(obj);
}
+ @Override
public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj) {
visit(obj);
}
+ @Override
public void visitConstantLong(ConstantLong obj) {
visit(obj);
}
+ @Override
public void visitConstantMethodref(ConstantMethodref obj) {
visit(obj);
}
+ @Override
public void visitConstantNameAndType(ConstantNameAndType obj) {
visit(obj);
}
+ @Override
public void visitConstantPool(ConstantPool obj) {
visit(obj);
}
+ @Override
public void visitConstantString(ConstantString obj) {
visit(obj);
}
+ @Override
public void visitConstantUtf8(ConstantUtf8 obj) {
visit(obj);
}
+ @Override
public void visitConstantValue(ConstantValue obj) {
visit(obj);
}
+ @Override
public void visitDeprecated(org.apache.bcel.classfile.Deprecated obj) {
visit(obj);
}
+ @Override
public void visitExceptionTable(ExceptionTable obj) {
visit(obj);
}
+ @Override
public void visitField(Field obj) {
visit(obj);
}
// Extra classes (i.e. leaves in this context)
+ @Override
public void visitInnerClass(InnerClass obj) {
visit(obj);
}
+ @Override
public void visitInnerClasses(InnerClasses obj) {
visit(obj);
}
// General classes
+ @Override
public void visitJavaClass(JavaClass obj) {
visit(obj);
}
+ @Override
public void visitLineNumber(LineNumber obj) {
visit(obj);
}
+ @Override
public void visitLineNumberTable(LineNumberTable obj) {
visit(obj);
}
+ @Override
public void visitLocalVariable(LocalVariable obj) {
visit(obj);
}
+ @Override
public void visitLocalVariableTable(LocalVariableTable obj) {
visit(obj);
}
+ @Override
public void visitLocalVariableTypeTable(LocalVariableTypeTable obj) {
visit(obj);
}
+ @Override
public void visitMethod(Method obj) {
visit(obj);
}
+ @Override
public void visitSignature(Signature obj) {
visit(obj);
}
+ @Override
public void visitSourceFile(SourceFile obj) {
visit(obj);
}
+ @Override
public void visitSynthetic(Synthetic obj) {
visit(obj);
}
+ @Override
public void visitUnknown(Unknown obj) {
visit(obj);
}
+ @Override
public void visitStackMapEntry(StackMapEntry obj) {
visit(obj);
}
+ @Override
public void visitStackMap(StackMap obj) {
visit(obj);
}
diff --git a/src/java/edu/umd/cs/findbugs/visitclass/DismantleBytecode.java b/src/java/edu/umd/cs/findbugs/visitclass/DismantleBytecode.java
index c374b15..891aba0 100644
--- a/src/java/edu/umd/cs/findbugs/visitclass/DismantleBytecode.java
+++ b/src/java/edu/umd/cs/findbugs/visitclass/DismantleBytecode.java
@@ -36,6 +36,7 @@ import org.apache.bcel.classfile.ConstantFieldref;
import org.apache.bcel.classfile.ConstantFloat;
import org.apache.bcel.classfile.ConstantInteger;
import org.apache.bcel.classfile.ConstantInterfaceMethodref;
+import org.apache.bcel.classfile.ConstantInvokeDynamic;
import org.apache.bcel.classfile.ConstantLong;
import org.apache.bcel.classfile.ConstantMethodref;
import org.apache.bcel.classfile.ConstantNameAndType;
@@ -153,31 +154,31 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
* Meaning of bytecode operands
*/
static final byte[][] MEANING_OF_OPERANDS = {
- // 0 1 2 3 4 5 6 7 8 9
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, { M_INT }, { M_INT }, { M_CP }, { M_CP }, { M_CP },
- { M_R }, { M_R }, { M_R }, { M_R }, { M_R }, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, { M_R }, { M_R }, { M_R }, { M_R }, { M_R }, {}, {}, {}, {}, {}, {}, {}, {},
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
- {},
- {},
- {},
- {},
- {},
- // 130 1 2 3 4 5 6 7 8 9
- {}, {}, { M_R, M_INT }, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, { M_BR },
- { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR },
- { M_BR }, { M_BR }, { M_BR },
- { M_BR },
- { M_R },
- // 170 1 2 3 4 5 6 7 8 9
- {}, {}, {}, {}, {}, {}, {}, {}, { M_CP }, { M_CP }, { M_CP }, { M_CP }, { M_CP }, { M_CP }, { M_CP },
- { M_CP, M_PAD, M_PAD }, {}, { M_CP }, { M_UINT },
- { M_CP },
- // 190 1 2 3 4 5 6 7 8 9
- {}, {}, { M_CP }, { M_CP }, {}, {}, { M_PAD }, { M_CP, M_UINT }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, {}, {}, {},
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
- {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} };
+ // 0 1 2 3 4 5 6 7 8 9
+ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, { M_INT }, { M_INT }, { M_CP }, { M_CP }, { M_CP },
+ { M_R }, { M_R }, { M_R }, { M_R }, { M_R }, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, { M_R }, { M_R }, { M_R }, { M_R }, { M_R }, {}, {}, {}, {}, {}, {}, {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ // 130 1 2 3 4 5 6 7 8 9
+ {}, {}, { M_R, M_INT }, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, { M_BR },
+ { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, { M_BR },
+ { M_BR }, { M_BR }, { M_BR },
+ { M_BR },
+ { M_R },
+ // 170 1 2 3 4 5 6 7 8 9
+ {}, {}, {}, {}, {}, {}, {}, {}, { M_CP }, { M_CP }, { M_CP }, { M_CP }, { M_CP }, { M_CP }, { M_CP },
+ { M_CP, M_PAD, M_PAD }, { M_CP, M_PAD, M_PAD }, { M_CP }, { M_UINT },
+ { M_CP },
+ // 190 1 2 3 4 5 6 7 8 9
+ {}, {}, { M_CP }, { M_CP }, {}, {}, { M_PAD }, { M_CP, M_UINT }, { M_BR }, { M_BR }, { M_BR }, { M_BR }, {}, {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} };
protected byte[] codeBytes;
@@ -186,8 +187,9 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
// Accessors
public ClassDescriptor getClassDescriptorOperand() {
- if (referencedClass == null)
+ if (referencedClass == null) {
throw new IllegalStateException("getClassDescriptorOperand called but value not available");
+ }
return referencedClass;
}
@@ -199,7 +201,6 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
public boolean isMethodCall() {
switch(opcode) {
default: return false;
- case INVOKEDYNAMIC:
case INVOKEINTERFACE:
case INVOKESPECIAL:
case INVOKEVIRTUAL:
@@ -208,9 +209,12 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
}
}
+
+ @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ")
public MethodDescriptor getMethodDescriptorOperand() {
- if (nameConstantOperand == NOT_AVAILABLE)
+ if (nameConstantOperand == NOT_AVAILABLE || classConstantOperand == NOT_AVAILABLE) {
throw new IllegalStateException("getMethodDescriptorOperand called but value not available");
+ }
if (referencedMethod == null) {
referencedMethod = DescriptorFactory.instance().getMethodDescriptor(classConstantOperand, nameConstantOperand,
@@ -220,7 +224,12 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
}
public @CheckForNull
+ @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ")
XMethod getXMethodOperand() {
+ if (nameConstantOperand == NOT_AVAILABLE || classConstantOperand == NOT_AVAILABLE) {
+ throw new IllegalStateException("getXMethodOperand called but value not available");
+ }
+
if (getReferencedXClass() != null && referencedXMethod == null) {
referencedXMethod = Hierarchy2.findInvocationLeastUpperBound(getReferencedXClass(), nameConstantOperand,
sigConstantOperand, opcode == INVOKESTATIC, opcode == INVOKEINTERFACE);
@@ -229,9 +238,11 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
return referencedXMethod;
}
+ @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ")
public FieldDescriptor getFieldDescriptorOperand() {
- if (nameConstantOperand == NOT_AVAILABLE)
+ if (nameConstantOperand == NOT_AVAILABLE) {
throw new IllegalStateException("getFieldDescriptorOperand called but value not available");
+ }
if (referencedField == null) {
referencedField = DescriptorFactory.instance().getFieldDescriptor(classConstantOperand, nameConstantOperand,
@@ -242,9 +253,10 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
public @CheckForNull
XField getXFieldOperand() {
- if (getReferencedXClass() != null && referencedXField == null)
+ if (getReferencedXClass() != null && referencedXField == null) {
referencedXField = getReferencedXClass().findField(nameConstantOperand, sigConstantOperand,
opcode == GETSTATIC || opcode == PUTSTATIC);
+ }
return referencedXField;
}
@@ -253,13 +265,15 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
* If the current opcode has a class operand, get the associated class
* constant, dot-formatted
*/
+ @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ")
public String getDottedClassConstantOperand() {
if (dottedClassConstantOperand != null) {
assert dottedClassConstantOperand != NOT_AVAILABLE;
return dottedClassConstantOperand;
}
- if (classConstantOperand == NOT_AVAILABLE)
+ if (classConstantOperand == NOT_AVAILABLE) {
throw new IllegalStateException("getDottedClassConstantOperand called but value not available");
+ }
dottedClassConstantOperand = ClassName.toDottedClassName(classConstantOperand);
return dottedClassConstantOperand;
}
@@ -269,24 +283,28 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
* representation
*/
@Deprecated
+ @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ")
public String getRefConstantOperand() {
- if (refConstantOperand == NOT_AVAILABLE)
+ if (refConstantOperand == NOT_AVAILABLE) {
throw new IllegalStateException("getRefConstantOperand called but value not available");
+ }
if (refConstantOperand == null) {
String dottedClassConstantOperand = getDottedClassConstantOperand();
StringBuilder ref = new StringBuilder(dottedClassConstantOperand.length() + nameConstantOperand.length()
+ sigConstantOperand.length() + 5);
ref.append(dottedClassConstantOperand).append(".").append(nameConstantOperand).append(" : ")
- .append(replaceSlashesWithDots(sigConstantOperand));
+ .append(replaceSlashesWithDots(sigConstantOperand));
refConstantOperand = ref.toString();
}
return refConstantOperand;
}
/** If the current opcode has a reference constant operand, get its name */
+ @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ")
public String getNameConstantOperand() {
- if (nameConstantOperand == NOT_AVAILABLE)
+ if (nameConstantOperand == NOT_AVAILABLE) {
throw new IllegalStateException("getNameConstantOperand called but value not available");
+ }
return nameConstantOperand;
}
@@ -294,9 +312,11 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
* If the current opcode has a reference constant operand, get its
* signature, slash-formatted
*/
+ @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ")
public String getSigConstantOperand() {
- if (sigConstantOperand == NOT_AVAILABLE)
+ if (sigConstantOperand == NOT_AVAILABLE) {
throw new IllegalStateException("getSigConstantOperand called but value not available");
+ }
return sigConstantOperand;
}
@@ -305,22 +325,27 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
* slash-formatted.
*/
public @SlashedClassName
+ @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ")
String getClassConstantOperand() {
- if (classConstantOperand == NOT_AVAILABLE)
+ if (classConstantOperand == NOT_AVAILABLE) {
throw new IllegalStateException("getClassConstantOperand called but value not available");
+ }
return classConstantOperand;
}
/** If the current opcode has a string constant operand, get its name */
+ @SuppressFBWarnings("ES_COMPARING_STRINGS_WITH_EQ")
public String getStringConstantOperand() {
- if (stringConstantOperand == NOT_AVAILABLE)
+ if (stringConstantOperand == NOT_AVAILABLE) {
throw new IllegalStateException("getStringConstantOperand called but value not available");
+ }
return stringConstantOperand;
}
public Constant getConstantRefOperand() {
- if (constantRefOperand == null)
+ if (constantRefOperand == null) {
throw new IllegalStateException("getConstantRefOperand called but value not available");
+ }
return constantRefOperand;
}
@@ -333,8 +358,9 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
}
public int getRegisterOperand() {
- if (registerOperand == -1)
+ if (registerOperand == -1) {
throw new IllegalStateException("getRegisterOperand called but value not available");
+ }
return registerOperand;
}
@@ -347,26 +373,30 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
return longConstant;
}
public int getBranchOffset() {
- if (branchOffset == INVALID_OFFSET)
+ if (branchOffset == INVALID_OFFSET) {
throw new IllegalStateException("getBranchOffset called but value not available");
+ }
return branchOffset;
}
public int getBranchTarget() {
- if (branchTarget == INVALID_OFFSET)
+ if (branchTarget == INVALID_OFFSET) {
throw new IllegalStateException("getBranchTarget called but value not available");
+ }
return branchTarget;
}
public int getBranchFallThrough() {
- if (branchFallThrough == INVALID_OFFSET)
+ if (branchFallThrough == INVALID_OFFSET) {
throw new IllegalStateException("getBranchFallThrough called but value not available");
+ }
return branchFallThrough;
}
public int getDefaultSwitchOffset() {
- if (defaultSwitchOffset == INVALID_OFFSET)
+ if (defaultSwitchOffset == INVALID_OFFSET) {
throw new IllegalStateException("getDefaultSwitchOffset called but value not available");
+ }
return defaultSwitchOffset;
}
@@ -385,13 +415,16 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
* 0 for current opcode, 1 for one before that, etc.
*/
public int getPrevOpcode(int offset) {
- if (offset < 0)
+ if (offset < 0) {
throw new IllegalArgumentException("offset (" + offset + ") must be nonnegative");
- if (offset >= prevOpcode.length || offset > sizePrevOpcodeBuffer)
+ }
+ if (offset >= prevOpcode.length || offset > sizePrevOpcodeBuffer) {
return NOP;
+ }
int pos = currentPosInPrevOpcodeBuffer - offset;
- if (pos < 0)
+ if (pos < 0) {
pos += prevOpcode.length;
+ }
return prevOpcode[pos];
}
@@ -424,15 +457,17 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
@SuppressFBWarnings("EI")
public int[] getSwitchOffsets() {
- if (switchOffsets == null)
+ if (switchOffsets == null) {
throw new IllegalStateException("getSwitchOffsets called but value not available");
+ }
return switchOffsets;
}
@SuppressFBWarnings("EI")
public int[] getSwitchLabels() {
- if (switchLabels == null)
+ if (switchLabels == null) {
throw new IllegalStateException("getSwitchLabels called but value not available");
+ }
return switchLabels;
}
@@ -459,9 +494,11 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
// Sort by offset
for (int j = 0; j < npairs; j++) {
int min = j;
- for (int k = j + 1; k < npairs; k++)
- if (switchOffsets[min] > switchOffsets[k])
+ for (int k = j + 1; k < npairs; k++) {
+ if (switchOffsets[min] > switchOffsets[k]) {
min = k;
+ }
+ }
if (min > j) {
int tmp = switchOffsets[min];
switchOffsets[min] = switchOffsets[j];
@@ -486,14 +523,20 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
}
public boolean atCatchBlock() {
- for (CodeException e : getCode().getExceptionTable())
- if (e.getHandlerPC() == getPC())
+ for (CodeException e : getCode().getExceptionTable()) {
+ if (e.getHandlerPC() == getPC()) {
return true;
+ }
+ }
return false;
}
@Override
public void visit(Code obj) {
+ // if (getXMethod().usesInvokeDynamic()) {
+ // AnalysisContext.currentAnalysisContext().analysisSkippedDueToInvokeDynamic(getXMethod());
+ // return;
+ // }
sizePrevOpcodeBuffer = 0;
currentPosInPrevOpcodeBuffer = prevOpcode.length - 1;
@@ -513,8 +556,9 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
sizePrevOpcodeBuffer++;
currentPosInPrevOpcodeBuffer++;
- if (currentPosInPrevOpcodeBuffer >= prevOpcode.length)
+ if (currentPosInPrevOpcodeBuffer >= prevOpcode.length) {
currentPosInPrevOpcodeBuffer = 0;
+ }
prevOpcode[currentPosInPrevOpcodeBuffer] = opcode;
i++;
// System.out.println(OPCODE_NAMES[opCode]);
@@ -523,11 +567,13 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
if (opcode == LOOKUPSWITCH) {
int pad = 4 - (i & 3);
- if (pad == 4)
+ if (pad == 4) {
pad = 0;
+ }
int count = pad;
- while (count > 0)
+ while (count > 0) {
count -= byteStream.skipBytes(count);
+ }
i += pad;
defaultSwitchOffset = byteStream.readInt();
branchOffset = defaultSwitchOffset;
@@ -545,11 +591,13 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
sortByOffset(switchOffsets, switchLabels);
} else if (opcode == TABLESWITCH) {
int pad = 4 - (i & 3);
- if (pad == 4)
+ if (pad == 4) {
pad = 0;
+ }
int count = pad;
- while (count > 0)
+ while (count > 0) {
count -= byteStream.skipBytes(count);
+ }
i += pad;
defaultSwitchOffset = byteStream.readInt();
branchOffset = defaultSwitchOffset;
@@ -594,13 +642,15 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
i += 2;
break;
default:
- throw new IllegalStateException("bad wide bytecode: " + OPCODE_NAMES[opcode]);
+ throw new IllegalStateException(String.format("bad wide bytecode %d: %s" , opcode, OPCODE_NAMES[opcode]));
}
- } else
- throw new IllegalStateException("bad unpredicatable bytecode: " + OPCODE_NAMES[opcode]);
+ } else {
+ throw new IllegalStateException(String.format("bad unpredicatable bytecode %d: %s" , opcode, OPCODE_NAMES[opcode]));
+ }
} else {
- if (byteStreamArgCount < 0)
- throw new IllegalStateException("bad length for bytecode: " + OPCODE_NAMES[opcode]);
+ if (byteStreamArgCount < 0) {
+ throw new IllegalStateException(String.format("bad length for bytecode %d: %s" , opcode, OPCODE_NAMES[opcode]));
+ }
for (int k = 0; k < TYPE_OF_OPERANDS[opcode].length; k++) {
int v;
@@ -609,10 +659,11 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
boolean unsigned = (m == M_CP || m == M_R || m == M_UINT);
switch (t) {
case T_BYTE:
- if (unsigned)
+ if (unsigned) {
v = byteStream.readUnsignedByte();
- else
+ } else {
v = byteStream.readByte();
+ }
/*
* System.out.print("Read byte " + v);
* System.out.println(" with meaning" + m);
@@ -620,10 +671,11 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
i++;
break;
case T_SHORT:
- if (unsigned)
+ if (unsigned) {
v = byteStream.readUnsignedShort();
- else
+ } else {
v = byteStream.readShort();
+ }
i += 2;
break;
case T_INT:
@@ -646,15 +698,15 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
classConstantOperand = getStringFromIndex(clazz.getNameIndex());
referencedClass = DescriptorFactory.createClassDescriptor(classConstantOperand);
- } else if (constantRefOperand instanceof ConstantInteger)
+ } else if (constantRefOperand instanceof ConstantInteger) {
intConstant = ((ConstantInteger) constantRefOperand).getBytes();
- else if (constantRefOperand instanceof ConstantLong)
+ } else if (constantRefOperand instanceof ConstantLong) {
longConstant = ((ConstantLong) constantRefOperand).getBytes();
- else if (constantRefOperand instanceof ConstantFloat)
+ } else if (constantRefOperand instanceof ConstantFloat) {
floatConstant = ((ConstantFloat) constantRefOperand).getBytes();
- else if (constantRefOperand instanceof ConstantDouble)
+ } else if (constantRefOperand instanceof ConstantDouble) {
doubleConstant = ((ConstantDouble) constantRefOperand).getBytes();
- else if (constantRefOperand instanceof ConstantString) {
+ } else if (constantRefOperand instanceof ConstantString) {
int s = ((ConstantString) constantRefOperand).getStringIndex();
stringConstantOperand = getStringFromIndex(s);
@@ -669,6 +721,14 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
nameConstantOperand = getStringFromIndex(sig.getNameIndex());
sigConstantOperand = getStringFromIndex(sig.getSignatureIndex());
refConstantOperand = null;
+ } else if (constantRefOperand instanceof ConstantInvokeDynamic) {
+ ConstantInvokeDynamic id = (ConstantInvokeDynamic) constantRefOperand;
+ ConstantNameAndType sig = (ConstantNameAndType) getConstantPool().getConstant(
+ id.getNameAndTypeIndex());
+ nameConstantOperand = getStringFromIndex(sig.getNameIndex());
+ sigConstantOperand = getStringFromIndex(sig.getSignatureIndex());
+
+
}
break;
case M_R:
@@ -784,7 +844,8 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
case DSTORE:
isRegisterStore = true;
break;
-
+ default:
+ break;
}
switch (opcode) {
@@ -813,32 +874,35 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
case PUTFIELD:
refFieldIsStatic = false;
break;
+ default:
+ break;
}
nextPC = i;
- if (beforeOpcode(opcode))
+ if (beforeOpcode(opcode)) {
sawOpcode(opcode);
+ }
afterOpcode(opcode);
if (opcode == TABLESWITCH) {
sawInt(switchLow);
sawInt(switchHigh);
- int prevOffset = i - PC;
+ // int prevOffset = i - PC;
for (int o = 0; o <= switchHigh - switchLow; o++) {
sawBranchTo(switchOffsets[o] + PC);
- prevOffset = switchOffsets[o];
+ // prevOffset = switchOffsets[o];
}
sawBranchTo(defaultSwitchOffset + PC);
} else if (opcode == LOOKUPSWITCH) {
sawInt(switchOffsets.length);
- int prevOffset = i - PC;
+ // int prevOffset = i - PC;
for (int o = 0; o < switchOffsets.length; o++) {
sawBranchTo(switchOffsets[o] + PC);
- prevOffset = switchOffsets[o];
+ // prevOffset = switchOffsets[o];
sawInt(switchLabels[o]);
}
sawBranchTo(defaultSwitchOffset + PC);
- } else
+ } else {
for (int k = 0; k < TYPE_OF_OPERANDS[opcode].length; k++) {
int m = MEANING_OF_OPERANDS[opcode][k];
switch (m) {
@@ -846,24 +910,25 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
sawBranchTo(branchOffset + PC);
break;
case M_CP:
- if (constantRefOperand instanceof ConstantInteger)
+ if (constantRefOperand instanceof ConstantInteger) {
sawInt(intConstant);
- else if (constantRefOperand instanceof ConstantLong)
+ } else if (constantRefOperand instanceof ConstantLong) {
sawLong(longConstant);
- else if (constantRefOperand instanceof ConstantFloat)
+ } else if (constantRefOperand instanceof ConstantFloat) {
sawFloat(floatConstant);
- else if (constantRefOperand instanceof ConstantDouble)
+ } else if (constantRefOperand instanceof ConstantDouble) {
sawDouble(doubleConstant);
- else if (constantRefOperand instanceof ConstantString)
+ } else if (constantRefOperand instanceof ConstantString) {
sawString(stringConstantOperand);
- else if (constantRefOperand instanceof ConstantFieldref)
+ } else if (constantRefOperand instanceof ConstantFieldref) {
sawField();
- else if (constantRefOperand instanceof ConstantMethodref)
+ } else if (constantRefOperand instanceof ConstantMethodref) {
sawMethod();
- else if (constantRefOperand instanceof ConstantInterfaceMethodref)
+ } else if (constantRefOperand instanceof ConstantInterfaceMethodref) {
sawIMethod();
- else if (constantRefOperand instanceof ConstantClass)
+ } else if (constantRefOperand instanceof ConstantClass) {
sawClass();
+ }
break;
case M_R:
sawRegister(registerOperand);
@@ -871,8 +936,11 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
case M_INT:
sawInt(intConstant);
break;
+ default:
+ break;
}
}
+ }
}
} catch (IOException e) {
AnalysisContext.logError("Error while dismantling bytecode", e);
@@ -938,26 +1006,27 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
public void printOpCode(int seen) {
System.out.print(" " + this.getClass().getSimpleName() + ": [" + formatter.format(getPC()) + "] " + OPCODE_NAMES[seen]);
- if ((seen == INVOKEVIRTUAL) || (seen == INVOKESPECIAL) || (seen == INVOKEINTERFACE) || (seen == INVOKESTATIC))
+ if ((seen == INVOKEVIRTUAL) || (seen == INVOKESPECIAL) || (seen == INVOKEINTERFACE) || (seen == INVOKESTATIC)) {
System.out.print(" " + getClassConstantOperand() + "." + getNameConstantOperand() + " " + getSigConstantOperand());
- else if (seen == LDC || seen == LDC_W || seen == LDC2_W) {
+ } else if (seen == LDC || seen == LDC_W || seen == LDC2_W) {
Constant c = getConstantRefOperand();
- if (c instanceof ConstantString)
+ if (c instanceof ConstantString) {
System.out.print(" \"" + getStringConstantOperand() + "\"");
- else if (c instanceof ConstantClass)
+ } else if (c instanceof ConstantClass) {
System.out.print(" " + getClassConstantOperand());
- else
+ } else {
System.out.print(" " + c);
- } else if ((seen == ALOAD) || (seen == ASTORE))
+ }
+ } else if ((seen == ALOAD) || (seen == ASTORE)) {
System.out.print(" " + getRegisterOperand());
- else if ((seen == GOTO) || (seen == GOTO_W) || (seen == IF_ACMPEQ) || (seen == IF_ACMPNE) || (seen == IF_ICMPEQ)
+ } else if ((seen == GOTO) || (seen == GOTO_W) || (seen == IF_ACMPEQ) || (seen == IF_ACMPNE) || (seen == IF_ICMPEQ)
|| (seen == IF_ICMPGE) || (seen == IF_ICMPGT) || (seen == IF_ICMPLE) || (seen == IF_ICMPLT)
|| (seen == IF_ICMPNE) || (seen == IFEQ) || (seen == IFGE) || (seen == IFGT) || (seen == IFLE) || (seen == IFLT)
- || (seen == IFNE) || (seen == IFNONNULL) || (seen == IFNULL))
+ || (seen == IFNE) || (seen == IFNONNULL) || (seen == IFNULL)) {
System.out.print(" " + getBranchTarget());
- else if ((seen == NEW) || (seen == INSTANCEOF))
+ } else if ((seen == NEW) || (seen == INSTANCEOF)) {
System.out.print(" " + getClassConstantOperand());
- else if ((seen == TABLESWITCH) || (seen == LOOKUPSWITCH)) {
+ } else if ((seen == TABLESWITCH) || (seen == LOOKUPSWITCH)) {
System.out.print(" [");
int switchPC = getPC();
int[] offsets = getSwitchOffsets();
@@ -981,6 +1050,9 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
return codeBytes[nextPC] & 0xff;
}
+ public int getNextCodeByte(int offset) {
+ return codeBytes[nextPC + offset] & 0xff;
+ }
public boolean isReturn(int opcode) {
switch (opcode) {
case IRETURN:
@@ -994,12 +1066,27 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
return false;
}
}
+ public boolean isShift(int opcode) {
+ switch (opcode) {
+ case IUSHR:
+ case ISHR:
+ case ISHL:
+ case LUSHR:
+ case LSHR:
+ case LSHL:
+ return true;
+ default:
+ return false;
+ }
+ }
public static boolean areOppositeBranches(int opcode1, int opcode2) {
- if (!isBranch(opcode1))
+ if (!isBranch(opcode1)) {
throw new IllegalArgumentException(OPCODE_NAMES[opcode1] + " isn't a branch");
- if (!isBranch(opcode2))
+ }
+ if (!isBranch(opcode2)) {
throw new IllegalArgumentException(OPCODE_NAMES[opcode2] + " isn't a branch");
+ }
switch (opcode1) {
case IF_ACMPEQ:
case IF_ACMPNE:
@@ -1076,12 +1163,13 @@ abstract public class DismantleBytecode extends AnnotationVisitor {
* @return Returns the referencedXClass.
*/
private XClass getReferencedXClass() {
- if (referencedXClass == null && referencedClass != null)
+ if (referencedXClass == null && referencedClass != null) {
try {
referencedXClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, referencedClass);
} catch (CheckedAnalysisException e) {
assert true;
}
+ }
return referencedXClass;
}
}
diff --git a/src/java/edu/umd/cs/findbugs/visitclass/LVTHelper.java b/src/java/edu/umd/cs/findbugs/visitclass/LVTHelper.java
index 17a8d28..a77991d 100644
--- a/src/java/edu/umd/cs/findbugs/visitclass/LVTHelper.java
+++ b/src/java/edu/umd/cs/findbugs/visitclass/LVTHelper.java
@@ -32,7 +32,7 @@ import org.apache.bcel.classfile.LocalVariableTable;
public class LVTHelper {
/**
* returns the local variable at an index int the scope of PC
- *
+ *
* @param lvt
* the local variable table
* @param index
@@ -47,8 +47,9 @@ public class LVTHelper {
for (int i = 0; i < length; i++) {
if (lvs[i].getIndex() == index) {
int startPC = lvs[i].getStartPC();
- if ((pc >= startPC) && (pc < (startPC + lvs[i].getLength())))
+ if ((pc >= startPC) && (pc < (startPC + lvs[i].getLength()))) {
return lvs[i];
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/visitclass/PreorderVisitor.java b/src/java/edu/umd/cs/findbugs/visitclass/PreorderVisitor.java
index 06664ea..53c0623 100644
--- a/src/java/edu/umd/cs/findbugs/visitclass/PreorderVisitor.java
+++ b/src/java/edu/umd/cs/findbugs/visitclass/PreorderVisitor.java
@@ -20,6 +20,7 @@
package edu.umd.cs.findbugs.visitclass;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
@@ -31,7 +32,11 @@ import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.CodeException;
import org.apache.bcel.classfile.Constant;
+import org.apache.bcel.classfile.ConstantCP;
import org.apache.bcel.classfile.ConstantClass;
+import org.apache.bcel.classfile.ConstantInterfaceMethodref;
+import org.apache.bcel.classfile.ConstantMethodref;
+import org.apache.bcel.classfile.ConstantNameAndType;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.EnclosingMethod;
@@ -58,6 +63,7 @@ import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.DescriptorFactory;
import edu.umd.cs.findbugs.classfile.FieldDescriptor;
+import edu.umd.cs.findbugs.classfile.FieldOrMethodDescriptor;
import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.classfile.IAnalysisCache;
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
@@ -151,8 +157,9 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
* @return current code attribute
*/
public Code getCode() {
- if (code == null)
+ if (code == null) {
throw new IllegalStateException("Not visiting Code");
+ }
return code;
}
@@ -162,11 +169,13 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
public Set<String> getSurroundingCaughtExceptions(int pc, int maxTryBlockSize) {
HashSet<String> result = new HashSet<String>();
- if (code == null)
+ if (code == null) {
throw new IllegalStateException("Not visiting Code");
+ }
int size = maxTryBlockSize;
- if (code.getExceptionTable() == null)
+ if (code.getExceptionTable() == null) {
return result;
+ }
for (CodeException catchBlock : code.getExceptionTable()) {
int startPC = catchBlock.getStartPC();
int endPC = catchBlock.getEndPC();
@@ -177,8 +186,9 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
size = thisSize;
Constant kind = constantPool.getConstant(catchBlock.getCatchType());
result.add("C" + catchBlock.getCatchType());
- } else if (size == thisSize)
+ } else if (size == thisSize) {
result.add("C" + catchBlock.getCatchType());
+ }
}
}
return result;
@@ -201,8 +211,9 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
* @return number of lines of code in try block
*/
public int getSizeOfSurroundingTryBlock(String vmNameOfExceptionClass, int pc) {
- if (code == null)
+ if (code == null) {
throw new IllegalStateException("Not visiting Code");
+ }
return Util.getSizeOfSurroundingTryBlock(constantPool, code, vmNameOfExceptionClass, pc);
}
@@ -211,8 +222,9 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
}
public CodeException getSurroundingTryBlock(String vmNameOfExceptionClass, int pc) {
- if (code == null)
+ if (code == null) {
throw new IllegalStateException("Not visiting Code");
+ }
return Util.getSurroundingTryBlock(constantPool, code, vmNameOfExceptionClass, pc);
}
@@ -222,11 +234,13 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
code = obj;
super.visitCode(obj);
CodeException[] exceptions = obj.getExceptionTable();
- for (CodeException exception : exceptions)
+ for (CodeException exception : exceptions) {
exception.accept(this);
+ }
Attribute[] attributes = obj.getAttributes();
- for (Attribute attribute : attributes)
+ for (Attribute attribute : attributes) {
attribute.accept(this);
+ }
visitAfter(obj);
code = null;
}
@@ -248,14 +262,16 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
for (int i = 1; i < constant_pool.length; i++) {
constant_pool[i].accept(this);
byte tag = constant_pool[i].getTag();
- if ((tag == CONSTANT_Double) || (tag == CONSTANT_Long))
+ if ((tag == CONSTANT_Double) || (tag == CONSTANT_Long)) {
i++;
+ }
}
}
private void doVisitField(Field field) {
- if (visitingField)
+ if (visitingField) {
throw new IllegalStateException("visitField called when already visiting a field");
+ }
visitingField = true;
this.field = field;
try {
@@ -265,8 +281,9 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
fieldIsStatic = field.isStatic();
field.accept(this);
Attribute[] attributes = field.getAttributes();
- for (Attribute attribute : attributes)
+ for (Attribute attribute : attributes) {
attribute.accept(this);
+ }
} finally {
visitingField = false;
this.field = null;
@@ -275,8 +292,9 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
}
public void doVisitMethod(Method method) {
- if (visitingMethod)
+ if (visitingMethod) {
throw new IllegalStateException("doVisitMethod called when already visiting a method");
+ }
visitingMethod = true;
try {
this.method = method;
@@ -285,8 +303,9 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
assert thisMethodInfo != null : "Can't get method info for " + getFullyQualifiedMethodName();
this.method.accept(this);
Attribute[] attributes = method.getAttributes();
- for (Attribute attribute : attributes)
+ for (Attribute attribute : attributes) {
attribute.accept(this);
+ }
} finally {
visitingMethod = false;
this.method = null;
@@ -295,14 +314,18 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
}
public boolean amVisitingMainMethod() {
- if (!visitingMethod)
+ if (!visitingMethod) {
throw new IllegalStateException("Not visiting a method");
- if (!method.isStatic())
+ }
+ if (!method.isStatic()) {
return false;
- if (!getMethodName().equals("main"))
+ }
+ if (!"main".equals(getMethodName())) {
return false;
- if (!getMethodSig().equals("([Ljava/lang/String;)V"))
+ }
+ if (!"([Ljava/lang/String;)V".equals(getMethodSig())) {
return false;
+ }
return true;
}
@@ -312,8 +335,9 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
public void visitInnerClasses(InnerClasses obj) {
super.visitInnerClasses(obj);
InnerClass[] inner_classes = obj.getInnerClasses();
- for (InnerClass inner_class : inner_classes)
+ for (InnerClass inner_class : inner_classes) {
inner_class.accept(this);
+ }
}
public void visitAfter(JavaClass obj) {
@@ -326,7 +350,7 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
boolean visitMethodsInCallOrder;
- protected boolean isVisitMethodsInCallOrder() {
+ protected boolean isVisitMethodsInCallOrder() {
return visitMethodsInCallOrder;
}
@@ -345,8 +369,9 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
constantPool.accept(this);
Field[] fields = obj.getFields();
Attribute[] attributes = obj.getAttributes();
- for (Field field : fields)
+ for (Field field : fields) {
doVisitField(field);
+ }
boolean didInCallOrder = false;
if (visitMethodsInCallOrder) {
@@ -357,18 +382,22 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
ClassContext classContext = analysisCache.getClassAnalysis(ClassContext.class, c);
didInCallOrder = true;
- for (Method m : classContext.getMethodsInCallOrder())
+ for (Method m : classContext.getMethodsInCallOrder()) {
doVisitMethod(m);
+ }
} catch (CheckedAnalysisException e) {
- AnalysisContext.logError("Error trying to visit methods in order", e);
+ AnalysisContext.logError("Error trying to visit methods in order", e);
}
}
- if (!didInCallOrder)
- for (Method m : getMethodVisitOrder(obj))
+ if (!didInCallOrder) {
+ for (Method m : getMethodVisitOrder(obj)) {
doVisitMethod(m);
- for (Attribute attribute : attributes)
+ }
+ }
+ for (Attribute attribute : attributes) {
attribute.accept(this);
+ }
visitAfter(obj);
}
}
@@ -385,11 +414,12 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
superclassName = dottedSuperclassName.replace('.', '/');
ClassDescriptor cDesc = DescriptorFactory.createClassDescriptor(className);
- if (!FindBugs.isNoAnalysis())
- try {
- thisClassInfo = (ClassInfo) Global.getAnalysisCache().getClassAnalysis(XClass.class, cDesc);
- } catch (CheckedAnalysisException e) {
- throw new AssertionError("Can't find ClassInfo for " + cDesc);
+ if (!FindBugs.isNoAnalysis()) {
+ try {
+ thisClassInfo = (ClassInfo) Global.getAnalysisCache().getClassAnalysis(XClass.class, cDesc);
+ } catch (CheckedAnalysisException e) {
+ throw new AssertionError("Can't find ClassInfo for " + cDesc);
+ }
}
super.visitJavaClass(obj);
@@ -399,23 +429,26 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
public void visitLineNumberTable(LineNumberTable obj) {
super.visitLineNumberTable(obj);
LineNumber[] line_number_table = obj.getLineNumberTable();
- for (LineNumber aLine_number_table : line_number_table)
+ for (LineNumber aLine_number_table : line_number_table) {
aLine_number_table.accept(this);
+ }
}
@Override
public void visitLocalVariableTable(LocalVariableTable obj) {
super.visitLocalVariableTable(obj);
LocalVariable[] local_variable_table = obj.getLocalVariableTable();
- for (LocalVariable aLocal_variable_table : local_variable_table)
+ for (LocalVariable aLocal_variable_table : local_variable_table) {
aLocal_variable_table.accept(this);
+ }
}
// Accessors
public XClass getXClass() {
- if (thisClassInfo == null)
+ if (thisClassInfo == null) {
throw new AssertionError("XClass information not set");
+ }
return thisClassInfo;
}
@@ -497,10 +530,10 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
/** If currently visiting a method, get the method's fully qualified name */
public String getFullyQualifiedMethodName() {
- if (!visitingMethod)
+ if (!visitingMethod) {
throw new IllegalStateException("getFullyQualifiedMethodName called while not visiting method");
+ }
if (fullyQualifiedMethodName == null) {
- getDottedSuperclassName();
getMethodName();
getDottedMethodSig();
StringBuilder ref = new StringBuilder(5 + dottedClassName.length() + methodName.length() + dottedMethodSig.length());
@@ -527,24 +560,28 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
/** If currently visiting a field, get the field's Field object */
public Field getField() {
- if (!visitingField)
+ if (!visitingField) {
throw new IllegalStateException("getField called while not visiting field");
+ }
return field;
}
/** If currently visiting a method, get the method's Method object */
public Method getMethod() {
- if (!visitingMethod)
+ if (!visitingMethod) {
throw new IllegalStateException("getMethod called while not visiting method");
+ }
return method;
}
/** If currently visiting a method, get the method's name */
public String getMethodName() {
- if (!visitingMethod)
+ if (!visitingMethod) {
throw new IllegalStateException("getMethodName called while not visiting method");
- if (methodName == null)
+ }
+ if (methodName == null) {
methodName = getStringFromIndex(method.getNameIndex());
+ }
return methodName;
}
@@ -561,21 +598,25 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
case ')':
return count;
case '[':
- if (!inArray)
+ if (!inArray) {
count++;
+ }
inArray = true;
break;
case 'L':
- if (!inArray)
+ if (!inArray) {
count++;
- while (signature.charAt(pos) != ';')
+ }
+ while (signature.charAt(pos) != ';') {
pos++;
+ }
pos++;
inArray = false;
break;
default:
- if (!inArray)
+ if (!inArray) {
count++;
+ }
inArray = false;
break;
}
@@ -583,6 +624,47 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
}
+ /**
+ * Returns true if given constant pool probably has a reference to any of supplied methods
+ * Useful to exclude from analysis uninteresting classes
+ * @param cp constant pool
+ * @param methods methods collection
+ * @return true if method is found
+ */
+ public static boolean hasInterestingMethod(ConstantPool cp, Collection<MethodDescriptor> methods) {
+ for(Constant c : cp.getConstantPool()) {
+ if(c instanceof ConstantMethodref || c instanceof ConstantInterfaceMethodref) {
+ ConstantCP desc = (ConstantCP)c;
+ ConstantNameAndType nameAndType = (ConstantNameAndType) cp.getConstant(desc.getNameAndTypeIndex());
+ String className = cp.getConstantString(desc.getClassIndex(), CONSTANT_Class);
+ String name = ((ConstantUtf8)cp.getConstant(nameAndType.getNameIndex())).getBytes();
+ String signature = ((ConstantUtf8)cp.getConstant(nameAndType.getSignatureIndex())).getBytes();
+ // We don't know whether method is static thus cannot use equals
+ int hash = FieldOrMethodDescriptor.getNameSigHashCode(name, signature);
+ for(MethodDescriptor method : methods) {
+ if (method.getNameSigHashCode() == hash
+ && (method.getSlashedClassName().isEmpty() || method.getSlashedClassName().equals(className))
+ && method.getName().equals(name) && method.getSignature().equals(signature)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public static boolean hasInterestingClass(ConstantPool cp, Collection<String> classes) {
+ for(Constant c : cp.getConstantPool()) {
+ if(c instanceof ConstantClass) {
+ String className = ((ConstantUtf8)cp.getConstant(((ConstantClass)c).getNameIndex())).getBytes();
+ if(classes.contains(className)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public int getNumberMethodArguments() {
return getNumberArguments(getMethodSig());
}
@@ -592,73 +674,87 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
* signature
*/
public String getMethodSig() {
- if (!visitingMethod)
+ if (!visitingMethod) {
throw new IllegalStateException("getMethodSig called while not visiting method");
- if (methodSig == null)
+ }
+ if (methodSig == null) {
methodSig = getStringFromIndex(method.getSignatureIndex());
+ }
return methodSig;
}
/** If currently visiting a method, get the method's dotted method signature */
public String getDottedMethodSig() {
- if (!visitingMethod)
+ if (!visitingMethod) {
throw new IllegalStateException("getDottedMethodSig called while not visiting method");
- if (dottedMethodSig == null)
+ }
+ if (dottedMethodSig == null) {
dottedMethodSig = getMethodSig().replace('/', '.');
+ }
return dottedMethodSig;
}
/** If currently visiting a field, get the field's name */
public String getFieldName() {
- if (!visitingField)
+ if (!visitingField) {
throw new IllegalStateException("getFieldName called while not visiting field");
- if (fieldName == null)
+ }
+ if (fieldName == null) {
fieldName = getStringFromIndex(field.getNameIndex());
+ }
return fieldName;
}
/** If currently visiting a field, get the field's slash-formatted signature */
public String getFieldSig() {
- if (!visitingField)
+ if (!visitingField) {
throw new IllegalStateException("getFieldSig called while not visiting field");
- if (fieldSig == null)
+ }
+ if (fieldSig == null) {
fieldSig = getStringFromIndex(field.getSignatureIndex());
+ }
return fieldSig;
}
/** If currently visiting a field, return whether or not the field is static */
public boolean getFieldIsStatic() {
- if (!visitingField)
+ if (!visitingField) {
throw new IllegalStateException("getFieldIsStatic called while not visiting field");
+ }
return fieldIsStatic;
}
/** If currently visiting a field, get the field's fully qualified name */
public String getFullyQualifiedFieldName() {
- if (!visitingField)
+ if (!visitingField) {
throw new IllegalStateException("getFullyQualifiedFieldName called while not visiting field");
- if (fullyQualifiedFieldName == null)
+ }
+ if (fullyQualifiedFieldName == null) {
fullyQualifiedFieldName = getDottedClassName() + "." + getFieldName() + " : " + getFieldSig();
+ }
return fullyQualifiedFieldName;
}
/** If currently visiting a field, get the field's dot-formatted signature */
@Deprecated
public String getDottedFieldSig() {
- if (!visitingField)
+ if (!visitingField) {
throw new IllegalStateException("getDottedFieldSig called while not visiting field");
- if (dottedFieldSig == null)
+ }
+ if (dottedFieldSig == null) {
dottedFieldSig = fieldSig.replace('/', '.');
+ }
return dottedFieldSig;
}
@Override
public String toString() {
- if (visitingMethod)
+ if (visitingMethod) {
return this.getClass().getSimpleName() + " analyzing " + getClassName() + "." + getMethodName() + getMethodSig();
- else if (visitingField)
+ } else if (visitingField) {
return this.getClass().getSimpleName() + " analyzing " + getClassName() + "." + getFieldName();
+ }
return this.getClass().getSimpleName() + " analyzing " + getClassName();
}
@@ -669,6 +765,7 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
* org.apache.bcel.classfile.Visitor#visitAnnotation(org.apache.bcel.classfile
* .Annotations)
*/
+ @Override
public void visitAnnotation(Annotations arg0) {
// TODO Auto-generated method stub
@@ -681,6 +778,7 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
* org.apache.bcel.classfile.Visitor#visitAnnotationDefault(org.apache.bcel
* .classfile.AnnotationDefault)
*/
+ @Override
public void visitAnnotationDefault(AnnotationDefault arg0) {
// TODO Auto-generated method stub
@@ -693,6 +791,7 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
* org.apache.bcel.classfile.Visitor#visitAnnotationEntry(org.apache.bcel
* .classfile.AnnotationEntry)
*/
+ @Override
public void visitAnnotationEntry(AnnotationEntry arg0) {
// TODO Auto-generated method stub
@@ -705,6 +804,7 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
* org.apache.bcel.classfile.Visitor#visitEnclosingMethod(org.apache.bcel
* .classfile.EnclosingMethod)
*/
+ @Override
public void visitEnclosingMethod(EnclosingMethod arg0) {
// TODO Auto-generated method stub
@@ -717,6 +817,7 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
* org.apache.bcel.classfile.Visitor#visitParameterAnnotation(org.apache
* .bcel.classfile.ParameterAnnotations)
*/
+ @Override
public void visitParameterAnnotation(ParameterAnnotations arg0) {
}
@@ -727,6 +828,7 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
* org.apache.bcel.classfile.Visitor#visitStackMapTable(org.apache.bcel.
* classfile.StackMapTable)
*/
+ @Override
public void visitStackMapTable(StackMapTable arg0) {
// TODO Auto-generated method stub
@@ -739,6 +841,7 @@ public class PreorderVisitor extends BetterVisitor implements Constants2 {
* org.apache.bcel.classfile.Visitor#visitStackMapTableEntry(org.apache.
* bcel.classfile.StackMapTableEntry)
*/
+ @Override
public void visitStackMapTableEntry(StackMapTableEntry arg0) {
// TODO Auto-generated method stub
diff --git a/src/java/edu/umd/cs/findbugs/visitclass/PrintClass.java b/src/java/edu/umd/cs/findbugs/visitclass/PrintClass.java
index e3c5c84..443d3c4 100644
--- a/src/java/edu/umd/cs/findbugs/visitclass/PrintClass.java
+++ b/src/java/edu/umd/cs/findbugs/visitclass/PrintClass.java
@@ -43,21 +43,25 @@ public class PrintClass {
static final class ZipEntryComparator implements Comparator<ZipEntry>, Serializable {
private static final long serialVersionUID = 1L;
+ @Override
public int compare(ZipEntry e1, ZipEntry e2) {
String s1 = e1.getName();
int pos1 = s1.lastIndexOf('/');
String p1 = "-";
- if (pos1 >= 0)
+ if (pos1 >= 0) {
p1 = s1.substring(0, pos1);
+ }
String s2 = e2.getName();
int pos2 = s2.lastIndexOf('/');
String p2 = "-";
- if (pos2 >= 0)
+ if (pos2 >= 0) {
p2 = s2.substring(0, pos2);
+ }
int r = p1.compareTo(p2);
- if (r != 0)
+ if (r != 0) {
return r;
+ }
return s1.compareTo(s2);
}
}
@@ -69,7 +73,6 @@ public class PrintClass {
public static void main(String argv[]) throws IOException {
String[] file_name = new String[argv.length];
int files = 0;
- ClassParser parser = null;
String zip_file = null;
/*
@@ -77,51 +80,61 @@ public class PrintClass {
*/
for (int i = 0; i < argv.length; i++) {
if (argv[i].charAt(0) == '-') { // command line switch
- if (argv[i].equals("-constants"))
+ if ("-constants".equals(argv[i])) {
constants = true;
- else if (argv[i].equals("-code"))
+ } else if ("-code".equals(argv[i])) {
code = true;
- else if (argv[i].equals("-super"))
+ } else if ("-super".equals(argv[i])) {
superClasses = true;
- else if (argv[i].equals("-zip"))
+ } else if ("-zip".equals(argv[i])) {
zip_file = argv[++i];
- } else if (argv[i].endsWith(".zip") || argv[i].endsWith(".jar"))
+ }
+ } else if (argv[i].endsWith(".zip") || argv[i].endsWith(".jar")) {
zip_file = argv[i];
- else { // add file name to list
+ } else { // add file name to list
file_name[files++] = argv[i];
}
}
- if (!constants)
+ if (!constants) {
code = true;
+ }
if (files == 0 && zip_file == null) {
System.err.println("list: No input files specified");
} else if (zip_file != null) {
- for (int i = 0; i < files; i++)
+ for (int i = 0; i < files; i++) {
file_name[i] = file_name[i].replace('.', '/');
- ZipFile z = new ZipFile(zip_file);
- TreeSet<ZipEntry> zipEntries = new TreeSet<ZipEntry>(new ZipEntryComparator());
- for (Enumeration<? extends ZipEntry> e = z.entries(); e.hasMoreElements();)
- zipEntries.add(e.nextElement());
-
- for (ZipEntry ze : zipEntries) {
- String name = ze.getName();
- if (!name.endsWith(".class"))
- continue;
- checkMatch: if (files > 0) {
- for (int i = 0; i < files; i++)
- if (name.indexOf(file_name[i]) >= 0)
- break checkMatch;
- continue;
+ }
+ try(ZipFile z = new ZipFile(zip_file)){
+ TreeSet<ZipEntry> zipEntries = new TreeSet<ZipEntry>(new ZipEntryComparator());
+ for (Enumeration<? extends ZipEntry> e = z.entries(); e.hasMoreElements();) {
+ zipEntries.add(e.nextElement());
}
- printClass(new ClassParser(z.getInputStream(ze), name));
+ for (ZipEntry ze : zipEntries) {
+ String name = ze.getName();
+ if (!name.endsWith(".class")) {
+ continue;
+ }
+ checkMatch: if (files > 0) {
+ for (int i = 0; i < files; i++) {
+ if (name.indexOf(file_name[i]) >= 0) {
+ break checkMatch;
+ }
+ }
+ continue;
+ }
+ printClass(new ClassParser(z.getInputStream(ze), name));
+
+ }
}
- z.close();
- } else
- for (int i = 0; i < files; i++)
- if (file_name[i].endsWith(".class"))
+ } else {
+ for (int i = 0; i < files; i++) {
+ if (file_name[i].endsWith(".class")) {
printClass(new ClassParser(file_name[i]));
+ }
+ }
+ }
}
@@ -142,13 +155,16 @@ public class PrintClass {
System.out.println();
return;
}
- if (constants || code)
+ if (constants || code) {
System.out.println(java_class); // Dump the contents
- if (constants) // Dump the constant pool ?
+ }
+ if (constants) {
System.out.println(java_class.getConstantPool());
+ }
- if (code) // Dump the method code ?
+ if (code) {
printCode(java_class.getMethods());
+ }
}
/**
@@ -158,8 +174,9 @@ public class PrintClass {
for (Method m : methods) {
System.out.println(m);
Code code = m.getCode();
- if (code != null)
+ if (code != null) {
System.out.println(code);
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/visitclass/Util.java b/src/java/edu/umd/cs/findbugs/visitclass/Util.java
index 3ef9d9d..b8b7123 100644
--- a/src/java/edu/umd/cs/findbugs/visitclass/Util.java
+++ b/src/java/edu/umd/cs/findbugs/visitclass/Util.java
@@ -53,7 +53,7 @@ public class Util {
@CheckForNull
public static JavaClass getOuterClass(JavaClass obj) throws ClassNotFoundException {
- for (Attribute a : obj.getAttributes())
+ for (Attribute a : obj.getAttributes()) {
if (a instanceof InnerClasses) {
for (InnerClass ic : ((InnerClasses) a).getInnerClasses()) {
if (obj.getClassNameIndex() == ic.getInnerClassIndex()) {
@@ -65,33 +65,38 @@ public class Util {
}
}
}
+ }
return null;
}
public static int getSizeOfSurroundingTryBlock(@CheckForNull Method method, Class<? extends Throwable> exceptionClass, int pc) {
- if (method == null)
+ if (method == null) {
return Integer.MAX_VALUE;
+ }
return getSizeOfSurroundingTryBlock(method, ClassName.toSlashedClassName(exceptionClass), pc);
}
- public static int getSizeOfSurroundingTryBlock(@CheckForNull Method method, String vmNameOfExceptionClass, int pc) {
- if (method == null)
+ public static int getSizeOfSurroundingTryBlock(@CheckForNull Method method, @CheckForNull String vmNameOfExceptionClass, int pc) {
+ if (method == null) {
return Integer.MAX_VALUE;
+ }
return getSizeOfSurroundingTryBlock(method.getConstantPool(), method.getCode(), vmNameOfExceptionClass, pc);
}
public static @CheckForNull
CodeException getSurroundingTryBlock(ConstantPool constantPool, Code code, @CheckForNull String vmNameOfExceptionClass, int pc) {
int size = Integer.MAX_VALUE;
- if (code.getExceptionTable() == null)
+ if (code.getExceptionTable() == null) {
return null;
+ }
CodeException result = null;
for (CodeException catchBlock : code.getExceptionTable()) {
if (vmNameOfExceptionClass != null) {
Constant catchType = constantPool.getConstant(catchBlock.getCatchType());
- if (catchType == null || catchType instanceof ConstantClass
- && !((ConstantClass) catchType).getBytes(constantPool).equals(vmNameOfExceptionClass))
+ if (catchType == null && !vmNameOfExceptionClass.isEmpty() || catchType instanceof ConstantClass
+ && !((ConstantClass) catchType).getBytes(constantPool).equals(vmNameOfExceptionClass)) {
continue;
+ }
}
int startPC = catchBlock.getStartPC();
int endPC = catchBlock.getEndPC();
@@ -111,16 +116,15 @@ public class Util {
int size = Integer.MAX_VALUE;
int tightStartPC = 0;
int tightEndPC = Integer.MAX_VALUE;
- if (code.getExceptionTable() == null)
+ if (code.getExceptionTable() == null) {
return size;
+ }
for (CodeException catchBlock : code.getExceptionTable()) {
if (vmNameOfExceptionClass != null) {
Constant catchType = constantPool.getConstant(catchBlock.getCatchType());
- if (catchType == null) continue;
- if (catchType instanceof ConstantClass) {
- String name = ((ConstantClass) catchType).getBytes(constantPool);
- if (!name.equals(vmNameOfExceptionClass))
- continue;
+ if (catchType == null && !vmNameOfExceptionClass.isEmpty() || catchType instanceof ConstantClass
+ && !((ConstantClass) catchType).getBytes(constantPool).equals(vmNameOfExceptionClass)) {
+ continue;
}
}
int startPC = catchBlock.getStartPC();
@@ -134,21 +138,25 @@ public class Util {
}
}
}
- if (size == Integer.MAX_VALUE)
+ if (size == Integer.MAX_VALUE) {
return size;
+ }
// try to guestimate number of lines that correspond
size = (size + 7) / 8;
LineNumberTable lineNumberTable = code.getLineNumberTable();
- if (lineNumberTable == null)
+ if (lineNumberTable == null) {
return size;
+ }
int count = 0;
for (LineNumber line : lineNumberTable.getLineNumberTable()) {
- if (line.getStartPC() > tightEndPC)
+ if (line.getStartPC() > tightEndPC) {
break;
- if (line.getStartPC() >= tightStartPC)
+ }
+ if (line.getStartPC() >= tightStartPC) {
count++;
+ }
}
return count;
diff --git a/src/java/edu/umd/cs/findbugs/workflow/BackdateHistoryUsingSource.java b/src/java/edu/umd/cs/findbugs/workflow/BackdateHistoryUsingSource.java
index 0e030d7..bf7121b 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/BackdateHistoryUsingSource.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/BackdateHistoryUsingSource.java
@@ -56,10 +56,12 @@ public class BackdateHistoryUsingSource {
for (BugInstance b : origCollection) {
SourceLineAnnotation s = b.getPrimarySourceLineAnnotation();
- if (!s.isSourceFileKnown())
+ if (!s.isSourceFileKnown()) {
continue;
- if (!sourceFinder.hasSourceFile(s))
+ }
+ if (!sourceFinder.hasSourceFile(s)) {
continue;
+ }
SourceFile sourceFile = sourceFinder.findSourceFile(s);
long when = sourceFile.getLastModified();
if (when > 0) {
@@ -81,8 +83,9 @@ public class BackdateHistoryUsingSource {
cloud.waitUntilIssueDataDownloaded();
- if (args.length > 1)
+ if (args.length > 1) {
origCollection.writeXML(args[1]);
+ }
cloud.waitUntilNewIssuesUploaded();
cloud.shutdown();
diff --git a/src/java/edu/umd/cs/findbugs/workflow/Churn.java b/src/java/edu/umd/cs/findbugs/workflow/Churn.java
index 25ac134..5903171 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/Churn.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/Churn.java
@@ -53,11 +53,13 @@ public class Churn {
}
String getKey(BugInstance b) {
- if (false)
+ if (false) {
return b.getType();
+ }
String result = b.getCategoryAbbrev();
- if (result.equals("C") || result.equals("N"))
+ if ("C".equals(result) || "N".equals(result)) {
return result;
+ }
return "O";
// return b.getPriorityAbbreviation() + "-" + b.getType();
@@ -68,26 +70,30 @@ public class Churn {
int maxRemovedAtOnce() {
int count = 0;
- for (int c : lastCount.values())
- if (count < c)
+ for (int c : lastCount.values()) {
+ if (count < c) {
count = c;
+ }
+ }
return count;
}
Map<Long, Integer> lastCount = new HashMap<Long, Integer>();
void update(BugInstance bug) {
- if (bug.isDead())
+ if (bug.isDead()) {
fixed++;
- else
+ } else {
persist++;
+ }
final long lastVersion = bug.getLastVersion();
if (lastVersion != -1) {
Integer v = lastCount.get(lastVersion);
- if (v == null)
+ if (v == null) {
lastCount.put(lastVersion, 0);
- else
+ } else {
lastCount.put(lastVersion, v + 1);
+ }
}
}
}
@@ -111,8 +117,9 @@ public class Churn {
String key = getKey(bugInstance);
Data d = data.get(key);
- if (d == null)
+ if (d == null) {
data.put(key, d = new Data());
+ }
d.update(bugInstance);
all.update(bugInstance);
@@ -128,12 +135,14 @@ public class Churn {
System.out.printf("%3d #age %s%n", lifespan, key);
System.out.printf("%3d %3d #spread %s%n", first, last, key);
diedAfter[lifespan]++;
- for (int t = 1; t < lifespan; t++)
+ for (int t = 1; t < lifespan; t++) {
aliveAt[t]++;
+ }
} else if (first != 0) {
int lifespan = (int) (bugCollection.getSequenceNumber() - first + 1);
- for (int t = 1; t < lifespan; t++)
+ for (int t = 1; t < lifespan; t++) {
aliveAt[t]++;
+ }
}
}
return this;
@@ -141,22 +150,25 @@ public class Churn {
public void dump(PrintStream out) {
for (int t = 1; t < aliveAt.length; t++) {
- if (aliveAt[t] != 0)
+ if (aliveAt[t] != 0) {
System.out.printf("%3d%% %4d %5d %3d #decay%n", diedAfter[t] * 100 / aliveAt[t], diedAfter[t], aliveAt[t], t);
+ }
}
System.out.printf("%7s %3s %5s %5s %5s %s%n", "chi", "%", "const", "fix", "max", "kind");
double fixRate;
- if (this.fixRate == -1)
+ if (this.fixRate == -1) {
fixRate = ((double) all.fixed) / (all.fixed + all.persist);
- else
+ } else {
fixRate = this.fixRate / 100.0;
+ }
double highFixRate = fixRate + 0.05;
double lowFixRate = fixRate - 0.05;
for (Map.Entry<String, Data> e : data.entrySet()) {
Data d = e.getValue();
int total = d.persist + d.fixed;
- if (total < 2)
+ if (total < 2) {
continue;
+ }
double rawFixRate = ((double) d.fixed) / total;
@@ -166,16 +178,18 @@ public class Churn {
} else {
double baseFixRate;
- if (rawFixRate < lowFixRate)
+ if (rawFixRate < lowFixRate) {
baseFixRate = lowFixRate;
- else
+ } else {
baseFixRate = highFixRate;
+ }
double expectedFixed = baseFixRate * total;
double expectedPersist = (1 - baseFixRate) * total;
chiValue = (d.fixed - expectedFixed) * (d.fixed - expectedFixed) / expectedFixed + (d.persist - expectedPersist)
* (d.persist - expectedPersist) / expectedPersist;
- if (rawFixRate < lowFixRate)
+ if (rawFixRate < lowFixRate) {
chiValue = -chiValue;
+ }
}
System.out.printf("%7d %3d %5d %5d %5d %s%n", (int) chiValue, d.fixed * 100 / total, d.persist, d.fixed,
@@ -197,10 +211,11 @@ public class Churn {
@Override
public void handleOptionWithArgument(String option, String argument) {
- if (option.equals("-fixRate"))
+ if ("-fixRate".equals(option)) {
fixRate = Integer.parseInt(argument);
- else
+ } else {
throw new IllegalArgumentException("unknown option: " + option);
+ }
}
}
@@ -213,10 +228,11 @@ public class Churn {
.parse(args, 0, 2, "Usage: " + Churn.class.getName() + " [options] [<xml results> [<history]] ");
SortedBugCollection bugCollection = new SortedBugCollection();
- if (argCount < args.length)
+ if (argCount < args.length) {
bugCollection.readXML(args[argCount++]);
- else
+ } else {
bugCollection.readXML(System.in);
+ }
churn.setBugCollection(bugCollection);
churn.execute();
PrintStream out = System.out;
diff --git a/src/java/edu/umd/cs/findbugs/workflow/CloudReport.java b/src/java/edu/umd/cs/findbugs/workflow/CloudReport.java
index 18d03a5..3075b37 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/CloudReport.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/CloudReport.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.charsets.UTF8;
/**
* Java main application to compute update a historical bug collection with
* results from another build/analysis.
- *
+ *
* @author William Pugh
*/
@@ -52,10 +52,11 @@ public class CloudReport {
}
BugCollection bugs = new SortedBugCollection();
- if (args.length == 0)
+ if (args.length == 0) {
bugs.readXML(System.in);
- else
+ } else {
bugs.readXML(args[0]);
+ }
bugs.getCloud().waitUntilIssueDataDownloaded();
PrintWriter out = UTF8.printWriter(System.out);
bugs.getCloud().printCloudSummary(out, bugs, new String[0]);
diff --git a/src/java/edu/umd/cs/findbugs/workflow/CloudSyncAndReport.java b/src/java/edu/umd/cs/findbugs/workflow/CloudSyncAndReport.java
index 44d2177..6540c38 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/CloudSyncAndReport.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/CloudSyncAndReport.java
@@ -87,14 +87,15 @@ public class CloudSyncAndReport {
*/
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-cloud")) {
+ if ("-cloud".equals(option)) {
options.cloudId = argument;
- } else if (option.equals("-recent")) {
+ } else if ("-recent".equals(option)) {
options.ageInHours = Integer.parseInt(argument);
- } else if (option.equals("-cloudSummary")) {
+ } else if ("-cloudSummary".equals(option)) {
options.cloudSummary = argument;
- } else
+ } else {
throw new IllegalArgumentException("Unknown option : " + option);
+ }
}
}
@@ -106,8 +107,9 @@ public class CloudSyncAndReport {
int argCount = commandLine.parse(argv, 0, 1, "Usage: " + CloudSyncAndReport.class.getName()
+ " [options] [<results1> <results2> ... <resultsn>] ");
- if (argCount < argv.length)
+ if (argCount < argv.length) {
options.analysisFile = argv[argCount];
+ }
CloudSyncAndReport csr = new CloudSyncAndReport(options);
csr.load();
@@ -133,10 +135,11 @@ public class CloudSyncAndReport {
}
public void load() throws IOException, DocumentException {
- if (options.analysisFile == null)
+ if (options.analysisFile == null) {
bugCollection.readXML(UTF8.bufferedReader(System.in));
- else
+ } else {
bugCollection.readXML(options.analysisFile);
+ }
if (options.cloudId != null && !options.cloudId.equals(bugCollection.getProject().getCloudId())) {
bugCollection.getProject().setCloudId(options.cloudId);
bugCollection.reinitializeCloud();
@@ -193,8 +196,9 @@ public class CloudSyncAndReport {
cs.printf("%6s %6s %s%n", "recent", "total", "Rank category");
for (Entry<BugRankCategory, Stats> e : stats.entrySet()) {
Stats s = e.getValue();
- if (s.total > 0)
+ if (s.total > 0) {
cs.printf("%6d %6d %s%n", s.recent, s.total, e.getKey());
+ }
}
cs.println();
cloud.printCloudSummary(cs, bugs, null);
diff --git a/src/java/edu/umd/cs/findbugs/workflow/CopyBuggySource.java b/src/java/edu/umd/cs/findbugs/workflow/CopyBuggySource.java
index 3ff596a..53f61eb 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/CopyBuggySource.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/CopyBuggySource.java
@@ -38,13 +38,14 @@ import edu.umd.cs.findbugs.FindBugs;
import edu.umd.cs.findbugs.Project;
import edu.umd.cs.findbugs.SortedBugCollection;
import edu.umd.cs.findbugs.SourceLineAnnotation;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import edu.umd.cs.findbugs.ba.SourceFile;
import edu.umd.cs.findbugs.ba.SourceFinder;
/**
* Java main application to compute update a historical bug collection with
* results from another build/analysis.
- *
+ *
* @author William Pugh
*/
@@ -52,13 +53,16 @@ public class CopyBuggySource {
enum SrcKind {
DIR, ZIP, Z0P_GZ;
static SrcKind get(File f) {
- if (f.exists() && f.isDirectory() && f.canWrite())
+ if (f.exists() && f.isDirectory() && f.canWrite()) {
return DIR;
+ }
if (!f.exists()) {
- if (f.getName().endsWith(".zip"))
+ if (f.getName().endsWith(".zip")) {
return ZIP;
- if (f.getName().endsWith(".z0p.gz"))
+ }
+ if (f.getName().endsWith(".z0p.gz")) {
return Z0P_GZ;
+ }
}
throw new IllegalArgumentException("Invalid src destination: " + f);
}
@@ -70,7 +74,7 @@ public class CopyBuggySource {
*/
private static final String USAGE = "Usage: <cmd> " + " <bugs.xml> <destinationSrc>";
-
+
public static void main(String[] args) throws Exception {
FindBugs.setNoAnalysis();
DetectorFactoryCollection.instance();
@@ -117,6 +121,7 @@ public class CopyBuggySource {
}
+ @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_BAD_PRACTICE")
private void copySourceFile(String fullName, SourceFile sourceFile) {
InputStream in = null;
OutputStream out = null;
@@ -124,16 +129,19 @@ public class CopyBuggySource {
long lastModified = sourceFile.getLastModified();
in = sourceFile.getInputStream();
out = getOutputStream(fullName, 0);
- if (out == null)
+ if (out == null) {
return;
+ }
while (true) {
int sz = in.read(buf);
- if (sz < 0)
+ if (sz < 0) {
break;
+ }
out.write(buf, 0, sz);
}
- if (dstFile != null)
+ if (dstFile != null) {
dstFile.setLastModified(lastModified);
+ }
System.out.println("Copied " + fullName);
copyCount++;
} catch (IOException e) {
@@ -149,16 +157,19 @@ public class CopyBuggySource {
private void copySourceForAnnotation(BugAnnotation ann) {
SourceLineAnnotation sourceAnnotation;
- if (ann instanceof BugAnnotationWithSourceLines)
+ if (ann instanceof BugAnnotationWithSourceLines) {
sourceAnnotation = ((BugAnnotationWithSourceLines) ann).getSourceLines();
- else if (ann instanceof SourceLineAnnotation)
+ } else if (ann instanceof SourceLineAnnotation) {
sourceAnnotation = (SourceLineAnnotation) ann;
- else
+ } else {
return;
- if (sourceAnnotation == null)
+ }
+ if (sourceAnnotation == null) {
return;
- if (sourceAnnotation.isUnknown())
+ }
+ if (sourceAnnotation.isUnknown()) {
return;
+ }
String fullName = SourceFinder.getPlatformName(sourceAnnotation);
@@ -167,8 +178,9 @@ public class CopyBuggySource {
sourceFile = sourceFinder.findSourceFile(sourceAnnotation);
} catch (IOException e) {
- if (couldNotFind.add(fullName))
+ if (couldNotFind.add(fullName)) {
System.out.println("Did not find " + fullName);
+ }
return;
}
@@ -184,8 +196,9 @@ public class CopyBuggySource {
copySourceForAnnotation(i.next());
}
}
- if (zOut != null)
+ if (zOut != null) {
zOut.close();
+ }
System.out.printf("All done. %d files not found, %d files copied%n", couldNotFind.size(), copyCount);
}
@@ -205,8 +218,9 @@ public class CopyBuggySource {
if (!parent.mkdirs() && !parent.isDirectory()) {
String path = parent.getPath();
- if (couldNotCreate.add(path))
+ if (couldNotCreate.add(path)) {
System.out.println("Can't create directory for " + path);
+ }
return null;
}
@@ -219,11 +233,12 @@ public class CopyBuggySource {
}
}
-
+
public static void close(InputStream in) {
try {
- if (in != null)
+ if (in != null) {
in.close();
+ }
} catch (IOException e) {
}
@@ -231,10 +246,11 @@ public class CopyBuggySource {
public static void close(OutputStream out) {
try {
- if (out instanceof ZipOutputStream)
+ if (out instanceof ZipOutputStream) {
((ZipOutputStream) out).closeEntry();
- else if (out != null)
+ } else if (out != null) {
out.close();
+ }
} catch (IOException e) {
}
diff --git a/src/java/edu/umd/cs/findbugs/workflow/CountByPackagePrefix.java b/src/java/edu/umd/cs/findbugs/workflow/CountByPackagePrefix.java
index 91bc8e8..5e23910 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/CountByPackagePrefix.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/CountByPackagePrefix.java
@@ -33,7 +33,7 @@ import edu.umd.cs.findbugs.util.ClassName;
/**
* Java main application to compute update a historical bug collection with
* results from another build/analysis.
- *
+ *
* @author William Pugh
*/
@@ -54,45 +54,51 @@ public class CountByPackagePrefix {
int prefixLength = Integer.parseInt(args[0]);
BugCollection origCollection = new SortedBugCollection();
- if (args.length == 1)
+ if (args.length == 1) {
origCollection.readXML(System.in);
- else
+ } else {
origCollection.readXML(args[1]);
+ }
Map<String, Integer> map = new TreeMap<String, Integer>();
Map<String, Integer> ncss = new TreeMap<String, Integer>();
for (BugInstance b : origCollection.getCollection()) {
String prefix = ClassName.extractPackagePrefix(b.getPrimaryClass().getPackageName(), prefixLength);
Integer v = map.get(prefix);
- if (v == null)
+ if (v == null) {
map.put(prefix, 1);
- else
+ } else {
map.put(prefix, v + 1);
+ }
}
for (PackageStats ps : origCollection.getProjectStats().getPackageStats()) {
String prefix = ClassName.extractPackagePrefix(ps.getPackageName(), prefixLength);
Integer v = ncss.get(prefix);
- if (v == null)
+ if (v == null) {
ncss.put(prefix, ps.size());
- else
+ } else {
ncss.put(prefix, v + ps.size());
+ }
}
for (Map.Entry<String, Integer> e : map.entrySet()) {
String prefix = e.getKey();
int warnings = e.getValue();
- if (warnings == 0)
+ if (warnings == 0) {
continue;
+ }
Integer v = ncss.get(prefix);
- if (v == null || v.intValue() == 0)
+ if (v == null || v.intValue() == 0) {
v = 1;
+ }
int density = warnings * 1000000 / v;
- if (warnings < 3 || v < 2000)
+ if (warnings < 3 || v < 2000) {
System.out.printf("%4s %4d %4d %s%n", " ", warnings, v / 1000, prefix);
- else
+ } else {
System.out.printf("%4d %4d %4d %s%n", density, warnings, v / 1000, prefix);
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/workflow/CountClassVersions.java b/src/java/edu/umd/cs/findbugs/workflow/CountClassVersions.java
index 64c167b..14df77f 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/CountClassVersions.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/CountClassVersions.java
@@ -56,8 +56,9 @@ public class CountClassVersions {
List<String> lst = new LinkedList<String>();
while (true) {
String s = in.readLine();
- if (s == null)
+ if (s == null) {
return lst;
+ }
lst.add(s);
}
}
@@ -76,35 +77,22 @@ public class CountClassVersions {
addOption("-prefix", "class name prefix", "prefix of class names that should be analyzed e.g., edu.umd.cs.)");
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.config.CommandLine#handleOption(java.lang.String,
- * java.lang.String)
- */
@Override
protected void handleOption(String option, String optionExtraPart) throws IOException {
throw new IllegalArgumentException("Unknown option : " + option);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.config.CommandLine#handleOptionWithArgument(java
- * .lang.String, java.lang.String)
- */
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-prefix"))
+ if ("-prefix".equals(option)) {
prefix = argument;
- else if (option.equals("-inputFileList"))
+ } else if ("-inputFileList".equals(option)) {
inputFileList = argument;
- else if (option.equals("-maxAge"))
+ } else if ("-maxAge".equals(option)) {
maxAge = System.currentTimeMillis() - (24 * 60 * 60 * 1000L) * Integer.parseInt(argument);
- else
+ } else {
throw new IllegalArgumentException("Unknown option : " + option);
+ }
}
}
@@ -115,15 +103,15 @@ public class CountClassVersions {
int argCount = commandLine.parse(args, 0, Integer.MAX_VALUE, "Usage: " + CountClassVersions.class.getName()
+ " [options] [<jarFile>+] ");
- int analysisClassCount = 0;
List<String> fileList;
- if (commandLine.inputFileList != null)
+ if (commandLine.inputFileList != null) {
fileList = readFrom(UTF8.fileReader(commandLine.inputFileList));
- else if (argCount == args.length)
+ } else if (argCount == args.length) {
fileList = readFromStandardInput();
- else
+ } else {
fileList = Arrays.asList(args).subList(argCount, args.length - 1);
+ }
byte buffer[] = new byte[8192];
MessageDigest digest = Util.getMD5Digest();
DualKeyHashMap<String, String, String> map = new DualKeyHashMap<String, String, String>();
@@ -135,41 +123,43 @@ public class CountClassVersions {
continue;
}
System.err.println("Opening " + f);
- ZipFile zipInputFile;
- try {
- zipInputFile = new ZipFile(f);
- } catch (IOException e) {
- e.printStackTrace();
- continue;
- }
- for (Enumeration<? extends ZipEntry> e = zipInputFile.entries(); e.hasMoreElements();) {
- ZipEntry ze = e.nextElement();
+ try (ZipFile zipInputFile = new ZipFile(f)){
+ for (Enumeration<? extends ZipEntry> e = zipInputFile.entries(); e.hasMoreElements();) {
+ ZipEntry ze = e.nextElement();
- if (ze == null)
- break;
- if (ze.isDirectory())
- continue;
-
- String name = ze.getName();
- if (!name.endsWith(".class"))
- continue;
- if (!name.replace('/', '.').startsWith(commandLine.prefix))
- continue;
-
- InputStream zipIn = zipInputFile.getInputStream(ze);
-
- while (true) {
- int bytesRead = zipIn.read(buffer);
- if (bytesRead < 0)
+ if (ze == null) {
break;
- digest.update(buffer, 0, bytesRead);
-
+ }
+ if (ze.isDirectory()) {
+ continue;
+ }
+
+ String name = ze.getName();
+ if (!name.endsWith(".class")) {
+ continue;
+ }
+ if (!name.replace('/', '.').startsWith(commandLine.prefix)) {
+ continue;
+ }
+
+ InputStream zipIn = zipInputFile.getInputStream(ze);
+
+ while (true) {
+ int bytesRead = zipIn.read(buffer);
+ if (bytesRead < 0) {
+ break;
+ }
+ digest.update(buffer, 0, bytesRead);
+
+ }
+ String hash = new BigInteger(1, digest.digest()).toString(16);
+ map.put(name, hash, fInName);
}
- String hash = new BigInteger(1, digest.digest()).toString(16);
- map.put(name, hash, fInName);
+ } catch (IOException e) {
+ e.printStackTrace();
+ continue;
}
- zipInputFile.close();
}
for (String s : map.keySet()) {
Map<String, String> values = map.get(s);
diff --git a/src/java/edu/umd/cs/findbugs/workflow/DefectDensity.java b/src/java/edu/umd/cs/findbugs/workflow/DefectDensity.java
index f938750..fbfda41 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/DefectDensity.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/DefectDensity.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.SortedBugCollection;
/**
* Java main application to compute defect density for a bug collection (stored
* as an XML collection)
- *
+ *
* @author William Pugh
*/
public class DefectDensity {
@@ -41,8 +41,9 @@ public class DefectDensity {
}
public static double density(int bugs, int ncss) {
- if (ncss == 0)
+ if (ncss == 0) {
return Double.NaN;
+ }
long bugsPer10KNCSS = Math.round(10000.0 * bugs / ncss);
return bugsPer10KNCSS / 10.0;
}
@@ -56,30 +57,35 @@ public class DefectDensity {
FindBugs.setNoAnalysis();
BugCollection origCollection = new SortedBugCollection();
int argCount = 0;
- if (argCount == args.length)
+ if (argCount == args.length) {
origCollection.readXML(System.in);
- else
+ } else {
origCollection.readXML(args[argCount]);
+ }
ProjectStats stats = origCollection.getProjectStats();
printRow("kind", "name", "density/KNCSS", "bugs", "NCSS");
double projectDensity = density(stats.getTotalBugs(), stats.getCodeSize());
printRow("project", origCollection.getCurrentAppVersion().getReleaseName(), projectDensity, stats.getTotalBugs(),
stats.getCodeSize());
- for (PackageStats p : stats.getPackageStats())
+ for (PackageStats p : stats.getPackageStats()) {
if (p.getTotalBugs() > 4) {
double packageDensity = density(p.getTotalBugs(), p.size());
- if (Double.isNaN(packageDensity) || packageDensity < projectDensity)
+ if (Double.isNaN(packageDensity) || packageDensity < projectDensity) {
continue;
+ }
printRow("package", p.getPackageName(), packageDensity, p.getTotalBugs(), p.size());
- for (ClassStats c : p.getSortedClassStats())
+ for (ClassStats c : p.getSortedClassStats()) {
if (c.getTotalBugs() > 4) {
double density = density(c.getTotalBugs(), c.size());
- if (Double.isNaN(density) || density < packageDensity)
+ if (Double.isNaN(density) || density < packageDensity) {
continue;
+ }
printRow("class", c.getName(), density, c.getTotalBugs(), c.size());
}
+ }
}
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/workflow/FB.java b/src/java/edu/umd/cs/findbugs/workflow/FB.java
index 92dee1a..62c09c8 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/FB.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/FB.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -38,8 +38,9 @@ public class FB {
} else {
cmd = args[0];
a = new String[args.length - 1];
- for (int i = 1; i < args.length; i++)
+ for (int i = 1; i < args.length; i++) {
a[i - 1] = args[i];
+ }
}
DetectorFactoryCollection.instance();
@@ -53,9 +54,9 @@ public class FB {
}
return;
}
-
+
}
-
+
throw new IllegalArgumentException("Unable to find FindBugs main for " + cmd);
}
diff --git a/src/java/edu/umd/cs/findbugs/workflow/FileBugHash.java b/src/java/edu/umd/cs/findbugs/workflow/FileBugHash.java
index d13ddf8..824486f 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/FileBugHash.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/FileBugHash.java
@@ -39,7 +39,7 @@ import edu.umd.cs.findbugs.util.Util;
* For each source file that has reported bugs, compute a hash of all the issues
* reported for that file. These hashes use line numbers, so a change that only
* changes the line number of an issue will cause the hash to be different.
- *
+ *
* @author William Pugh
*/
public class FileBugHash {
@@ -54,40 +54,45 @@ public class FileBugHash {
FileBugHash(BugCollection bugs) {
- for (PackageStats pStat : bugs.getProjectStats().getPackageStats())
+ for (PackageStats pStat : bugs.getProjectStats().getPackageStats()) {
for (ClassStats cStat : pStat.getSortedClassStats()) {
String path = cStat.getName();
- if (path.indexOf('.') == -1)
+ if (path.indexOf('.') == -1) {
path = cStat.getSourceFile();
- else
+ } else {
path = path.substring(0, path.lastIndexOf('.') + 1).replace('.', '/') + cStat.getSourceFile();
+ }
counts.put(path, 0);
Integer size = sizes.get(path);
- if (size == null)
+ if (size == null) {
size = 0;
+ }
sizes.put(path, size + cStat.size());
}
+ }
for (BugInstance bug : bugs.getCollection()) {
SourceLineAnnotation source = bug.getPrimarySourceLineAnnotation();
String packagePath = source.getPackageName().replace('.', '/');
String key;
- if (packagePath.length() == 0)
+ if (packagePath.length() == 0) {
key = source.getSourceFile();
- else
+ } else {
key = packagePath + "/" + source.getSourceFile();
+ }
StringBuilder buf = hashes.get(key);
if (buf == null) {
buf = new StringBuilder();
hashes.put(key, buf);
}
buf.append(bug.getInstanceKey()).append("-").append(source.getStartLine()).append(".")
- .append(source.getStartBytecode()).append(" ");
+ .append(source.getStartBytecode()).append(" ");
Integer count = counts.get(key);
- if (count == null)
+ if (count == null) {
counts.put(key, 1);
- else
+ } else {
counts.put(key, 1 + count);
+ }
}
}
@@ -98,26 +103,30 @@ public class FileBugHash {
public @CheckForNull
String getHash(String sourceFile) {
StringBuilder rawHash = hashes.get(sourceFile);
- if (rawHash == null || digest == null)
+ if (rawHash == null || digest == null) {
return null;
+ }
byte[] data = digest.digest(UTF8.getBytes(rawHash.toString()));
String tmp = new BigInteger(1, data).toString(16);
- if (tmp.length() < 32)
+ if (tmp.length() < 32) {
tmp = "000000000000000000000000000000000".substring(0, 32 - tmp.length()) + tmp;
+ }
return tmp;
}
public int getBugCount(String sourceFile) {
Integer count = counts.get(sourceFile);
- if (count == null)
+ if (count == null) {
return 0;
+ }
return count;
}
public int getSize(String sourceFile) {
Integer size = sizes.get(sourceFile);
- if (size == null)
+ if (size == null) {
return 0;
+ }
return size;
}
@@ -129,10 +138,11 @@ public class FileBugHash {
}
BugCollection origCollection = new SortedBugCollection();
int argCount = 0;
- if (argCount == args.length)
+ if (argCount == args.length) {
origCollection.readXML(System.in);
- else
+ } else {
origCollection.readXML(args[argCount]);
+ }
FileBugHash result = compute(origCollection);
for (String sourceFile : result.getSourceFiles()) {
System.out.println(result.getHash(sourceFile) + "\t" + sourceFile);
@@ -140,10 +150,6 @@ public class FileBugHash {
}
- /**
- * @param origCollection
- * @return
- */
public static FileBugHash compute(BugCollection origCollection) {
return new FileBugHash(origCollection);
}
diff --git a/src/java/edu/umd/cs/findbugs/workflow/Filter.java b/src/java/edu/umd/cs/findbugs/workflow/Filter.java
index bcd79eb..c5e23d2 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/Filter.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/Filter.java
@@ -131,7 +131,7 @@ public class Filter {
public boolean purgeHistorySpecified = false;
public boolean purgeHistory = false;
-
+
public boolean activeSpecified = false;
public boolean active = false;
@@ -205,7 +205,7 @@ public class Filter {
Set<String> designationKey = new HashSet<String>();
Set<String> categoryKey = new HashSet<String>();
-
+
SortedSet<BugInstance> uniqueSloppy;
int priority = 3;
@@ -258,21 +258,22 @@ public class Filter {
addOption("-class", "pattern", "allow only bugs whose primary class name matches this pattern");
addOption("-calls", "pattern", "allow only bugs that involve a call to a method that matches this pattern (matches with method class or name)");
-
+
addOption("-bugPattern", "pattern", "allow only bugs whose type matches this pattern");
addOption("-category", "category", "allow only warnings with a category that starts with this string");
addOption("-designation", "designation",
"allow only warnings with this designation (e.g., -designation SHOULD_FIX,MUST_FIX)");
- addSwitch("-dontUpdateStats",
+ addSwitch("-dontUpdateStats",
"used when withSource is specified to only update bugs, not the class and package stats");
addOption("-hashes", "hash file", "only bugs with instance hashes contained in the hash file");
}
public static long getVersionNum(BugCollection collection, String val,
- boolean roundToLaterVersion) {
- if (val == null)
+ boolean roundToLaterVersion) {
+ if (val == null) {
return -1;
+ }
Map<String, AppVersion> versions = new HashMap<String, AppVersion>();
SortedMap<Long, AppVersion> timeStamps = new TreeMap<Long, AppVersion>();
@@ -287,28 +288,32 @@ public class Filter {
timeStamps.put(v.getTimestamp(), v);
return getVersionNum(versions, timeStamps, val,
- roundToLaterVersion, v.getSequenceNumber());
+ roundToLaterVersion, v.getSequenceNumber());
}
public static long getVersionNum(Map<String, AppVersion> versions, SortedMap<Long, AppVersion> timeStamps, String val,
boolean roundToLaterVersion, long currentSeqNum) {
- if (val == null)
+ if (val == null) {
return -1;
+ }
long numVersions = currentSeqNum + 1;
- if (val.equals("last") || val.equals("lastVersion"))
+ if ("last".equals(val) || "lastVersion".equals(val)) {
return numVersions - 1;
+ }
AppVersion v = versions.get(val);
- if (v != null)
+ if (v != null) {
return v.getSequenceNumber();
+ }
try {
long time = 0;
- if (val.endsWith("daysAgo"))
+ if (val.endsWith("daysAgo")) {
time = System.currentTimeMillis() - MILLISECONDS_PER_DAY
* Integer.parseInt(val.substring(0, val.length() - 7));
- else
+ } else {
time = Date.parse(val);
+ }
return getAppropriateSeq(timeStamps, time, roundToLaterVersion);
} catch (Exception e) {
try {
@@ -331,13 +336,15 @@ public class Filter {
static private long getAppropriateSeq(SortedMap<Long, AppVersion> timeStamps, long when, boolean roundToLaterVersion) {
if (roundToLaterVersion) {
SortedMap<Long, AppVersion> geq = timeStamps.tailMap(when);
- if (geq.isEmpty())
+ if (geq.isEmpty()) {
return Long.MAX_VALUE;
+ }
return geq.get(geq.firstKey()).getSequenceNumber();
} else {
SortedMap<Long, AppVersion> leq = timeStamps.headMap(when);
- if (leq.isEmpty())
+ if (leq.isEmpty()) {
return Long.MIN_VALUE;
+ }
return leq.get(leq.lastKey()).getSequenceNumber();
}
}
@@ -361,132 +368,176 @@ public class Filter {
present = getVersionNum(collection, presentAsString, true);
absent = getVersionNum(collection, absentAsString, true);
- if (sloppyUniqueSpecified)
+ if (sloppyUniqueSpecified) {
uniqueSloppy = new TreeSet<BugInstance>(new SloppyBugComparator());
+ }
long fixed = getVersionNum(collection, fixedAsString, true);
if (fixed >= 0)
+ {
last = fixed - 1; // fixed means last on previous sequence (ok
- // if -1)
+ // if -1)
+ }
}
boolean accept(BugCollection collection, BugInstance bug) {
boolean result = evaluate(collection, bug);
- if (not)
+ if (not) {
return !result;
+ }
return result;
}
boolean evaluate(BugCollection collection, BugInstance bug) {
- for (Matcher m : includeFilter)
- if (!m.match(bug))
+ for (Matcher m : includeFilter) {
+ if (!m.match(bug)) {
return false;
- for (Matcher m : excludeFilter)
- if (m.match(bug))
+ }
+ }
+ for (Matcher m : excludeFilter) {
+ if (m.match(bug)) {
return false;
- if (excludedInstanceHashes.contains(bug.getInstanceHash()))
+ }
+ }
+ if (excludedInstanceHashes.contains(bug.getInstanceHash())) {
return false;
- if (annotation != null && bug.getAnnotationText().indexOf(annotation) == -1)
+ }
+ if (annotation != null && bug.getAnnotationText().indexOf(annotation) == -1) {
return false;
- if (bug.getPriority() > priority)
+ }
+ if (bug.getPriority() > priority) {
return false;
- if (firstAsString != null && bug.getFirstVersion() != first)
+ }
+ if (firstAsString != null && bug.getFirstVersion() != first) {
return false;
- if (afterAsString != null && bug.getFirstVersion() <= after)
+ }
+ if (afterAsString != null && bug.getFirstVersion() <= after) {
return false;
- if (beforeAsString != null && bug.getFirstVersion() >= before)
+ }
+ if (beforeAsString != null && bug.getFirstVersion() >= before) {
return false;
- if (hashesFromFile != null && !hashesFromFile.contains(bug.getInstanceHash()))
+ }
+ if (hashesFromFile != null && !hashesFromFile.contains(bug.getInstanceHash())) {
return false;
+ }
long lastSeen = bug.getLastVersion();
- if (lastSeen < 0)
+ if (lastSeen < 0) {
lastSeen = collection.getSequenceNumber();
+ }
long thisDuration = lastSeen - bug.getFirstVersion();
- if (duration > 0 && thisDuration > duration)
+ if (duration > 0 && thisDuration > duration) {
return false;
- if ((lastAsString != null || fixedAsString != null) && (last < 0 || bug.getLastVersion() != last))
+ }
+ if ((lastAsString != null || fixedAsString != null) && (last < 0 || bug.getLastVersion() != last)) {
return false;
- if (presentAsString != null && !bugLiveAt(bug, present))
+ }
+ if (presentAsString != null && !bugLiveAt(bug, present)) {
return false;
- if (absentAsString != null && bugLiveAt(bug, absent))
+ }
+ if (absentAsString != null && bugLiveAt(bug, absent)) {
return false;
+ }
- if (hasFieldSpecified && (hasField != (bug.getPrimaryField() != null)))
+ if (hasFieldSpecified && (hasField != (bug.getPrimaryField() != null))) {
return false;
- if (hasLocalSpecified && (hasLocal != (bug.getPrimaryLocalVariableAnnotation() != null)))
+ }
+ if (hasLocalSpecified && (hasLocal != (bug.getPrimaryLocalVariableAnnotation() != null))) {
return false;
+ }
- if (maxRank < Integer.MAX_VALUE && BugRanker.findRank(bug) > maxRank)
+ if (maxRank < Integer.MAX_VALUE && BugRanker.findRank(bug) > maxRank) {
return false;
+ }
- if (activeSpecified && active == bug.isDead())
+ if (activeSpecified && active == bug.isDead()) {
return false;
- if (removedByChangeSpecified && bug.isRemovedByChangeOfPersistingClass() != removedByChange)
+ }
+ if (removedByChangeSpecified && bug.isRemovedByChangeOfPersistingClass() != removedByChange) {
return false;
- if (introducedByChangeSpecified && bug.isIntroducedByChangeOfExistingClass() != introducedByChange)
+ }
+ if (introducedByChangeSpecified && bug.isIntroducedByChangeOfExistingClass() != introducedByChange) {
return false;
- if (newCodeSpecified && newCode != (!bug.isIntroducedByChangeOfExistingClass() && bug.getFirstVersion() != 0))
+ }
+ if (newCodeSpecified && newCode != (!bug.isIntroducedByChangeOfExistingClass() && bug.getFirstVersion() != 0)) {
return false;
- if (removedCodeSpecified && removedCode != (!bug.isRemovedByChangeOfPersistingClass() && bug.isDead()))
+ }
+ if (removedCodeSpecified && removedCode != (!bug.isRemovedByChangeOfPersistingClass() && bug.isDead())) {
return false;
+ }
- if (bugPattern != null && !bugPattern.matcher(bug.getType()).find())
+ if (bugPattern != null && !bugPattern.matcher(bug.getType()).find()) {
return false;
- if (classPattern != null && !classPattern.matcher(bug.getPrimaryClass().getClassName()).find())
+ }
+ if (classPattern != null && !classPattern.matcher(bug.getPrimaryClass().getClassName()).find()) {
return false;
+ }
if (callsPattern != null) {
MethodAnnotation m = bug.getAnnotationWithRole(MethodAnnotation.class, MethodAnnotation.METHOD_CALLED);
- if (m == null)
+ if (m == null) {
return false;
- if (!callsPattern.matcher(m.getClassName()).find() && !callsPattern.matcher(m.getMethodName()).find())
+ }
+ if (!callsPattern.matcher(m.getClassName()).find() && !callsPattern.matcher(m.getMethodName()).find()) {
return false;
+ }
}
- if (maybeMutatedAsString != null && !(atMutationPoint(bug) && mutationPoints.contains(getBugLocation(bug))))
+ if (maybeMutatedAsString != null && !(atMutationPoint(bug) && mutationPoints.contains(getBugLocation(bug)))) {
return false;
+ }
BugPattern thisBugPattern = bug.getBugPattern();
- if (!categoryKey.isEmpty() && thisBugPattern != null && !categoryKey.contains(thisBugPattern.getCategory()))
+ if (!categoryKey.isEmpty() && thisBugPattern != null && !categoryKey.contains(thisBugPattern.getCategory())) {
return false;
- if (!designationKey.isEmpty() && !designationKey.contains(bug.getUserDesignationKey()))
+ }
+ if (!designationKey.isEmpty() && !designationKey.contains(bug.getUserDesignationKey())) {
return false;
+ }
if (hashChangedSpecified) {
- if (bug.isInstanceHashConsistent() == hashChanged)
+ if (bug.isInstanceHashConsistent() == hashChanged) {
return false;
+ }
}
- if (applySuppressionSpecified && applySuppression && suppressionFilter.match(bug))
+ if (applySuppressionSpecified && applySuppression && suppressionFilter.match(bug)) {
return false;
+ }
SourceLineAnnotation primarySourceLineAnnotation = bug.getPrimarySourceLineAnnotation();
if (knownSourceSpecified) {
- if (primarySourceLineAnnotation.isUnknown() == knownSource)
+ if (primarySourceLineAnnotation.isUnknown() == knownSource) {
return false;
+ }
}
if (withSourceSpecified) {
- if (sourceSearcher.findSource(primarySourceLineAnnotation) != withSource)
+ if (sourceSearcher.findSource(primarySourceLineAnnotation) != withSource) {
return false;
+ }
}
Cloud cloud = collection.getCloud();
if (maxAgeSpecified) {
long firstSeen = cloud.getFirstSeen(bug);
- if (!cloud.isInCloud(bug))
+ if (!cloud.isInCloud(bug)) {
return false;
- if (firstSeen < minFirstSeen)
+ }
+ if (firstSeen < minFirstSeen) {
return false;
+ }
}
- if (notAProblemSpecified && notAProblem != (cloud.getConsensusDesignation(bug).score() < 0))
+ if (notAProblemSpecified && notAProblem != (cloud.getConsensusDesignation(bug).score() < 0)) {
return false;
- if (shouldFixSpecified && shouldFix != (cloud.getConsensusDesignation(bug).score() > 0))
+ }
+ if (shouldFixSpecified && shouldFix != (cloud.getConsensusDesignation(bug).score() > 0)) {
return false;
-
+ }
+
if (sloppyUniqueSpecified) {
boolean unique = uniqueSloppy.add(bug);
- if (unique != sloppyUnique)
+ if (unique != sloppyUnique) {
return false;
+ }
}
return true;
@@ -520,20 +571,23 @@ public class Filter {
}
private boolean bugLiveAt(BugInstance bug, long now) {
- if (now < bug.getFirstVersion())
+ if (now < bug.getFirstVersion()) {
return false;
- if (bug.isDead() && bug.getLastVersion() < now)
+ }
+ if (bug.isDead() && bug.getLastVersion() < now) {
return false;
+ }
return true;
}
@Override
protected void handleOption(String option, String optionExtraPart) throws IOException {
option = option.substring(1);
- if (optionExtraPart.length() == 0)
+ if (optionExtraPart.length() == 0) {
setField(option, true);
- else
+ } else {
setField(option, Boolean.parseBoolean(optionExtraPart));
+ }
setField(option + "Specified", true);
}
@@ -552,76 +606,75 @@ public class Filter {
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-priority") || option.equals("-confidence")) {
+ if ("-priority".equals(option) || "-confidence".equals(option)) {
priority = parsePriority(argument);
}
- else if (option.equals("-maxRank"))
+ else if ("-maxRank".equals(option)) {
maxRank = Integer.parseInt(argument);
-
- else if (option.equals("-first"))
+ } else if ("-first".equals(option)) {
firstAsString = argument;
- else if (option.equals("-maybeMutated"))
+ } else if ("-maybeMutated".equals(option)) {
maybeMutatedAsString = argument;
- else if (option.equals("-last"))
+ } else if ("-last".equals(option)) {
lastAsString = argument;
- else if (option.equals("-trimToVersion"))
+ } else if ("-trimToVersion".equals(option)) {
trimToVersionAsString = argument;
- else if (option.equals("-maxDuration"))
+ } else if ("-maxDuration".equals(option)) {
duration = Integer.parseInt(argument);
- else if (option.equals("-fixed"))
+ } else if ("-fixed".equals(option)) {
fixedAsString = argument;
- else if (option.equals("-after"))
+ } else if ("-after".equals(option)) {
afterAsString = argument;
- else if (option.equals("-before"))
+ } else if ("-before".equals(option)) {
beforeAsString = argument;
- else if (option.equals("-present"))
+ } else if ("-present".equals(option)) {
presentAsString = argument;
- else if (option.equals("-absent"))
+ } else if ("-absent".equals(option)) {
absentAsString = argument;
-
- else if (option.equals("-category"))
+ } else if ("-category".equals(option)) {
addCategoryKey(argument);
- else if (option.equals("-designation"))
+ } else if ("-designation".equals(option)) {
addDesignationKey(argument);
- else if (option.equals("-class"))
+ } else if ("-class".equals(option)) {
classPattern = Pattern.compile(argument.replace(',', '|'));
- else if (option.equals("-calls"))
+ } else if ("-calls".equals(option)) {
callsPattern = Pattern.compile(argument.replace(',', '|'));
- else if (option.equals("-bugPattern"))
+ } else if ("-bugPattern".equals(option)) {
bugPattern = Pattern.compile(argument);
- else if (option.equals("-annotation"))
+ } else if ("-annotation".equals(option)) {
annotation = argument;
- else if (option.equals("-excludeBugs")) {
+ } else if ("-excludeBugs".equals(option)) {
try {
ExcludingHashesBugReporter.addToExcludedInstanceHashes(excludedInstanceHashes, argument);
} catch (DocumentException e) {
throw new IllegalArgumentException("Error processing include file: " + argument, e);
}
- } else if (option.equals("-include")) {
+ } else if ("-include".equals(option)) {
try {
includeFilter.add(new edu.umd.cs.findbugs.filter.Filter(argument));
} catch (FilterException e) {
throw new IllegalArgumentException("Error processing include file: " + argument, e);
}
- } else if (option.equals("-exclude")) {
+ } else if ("-exclude".equals(option)) {
try {
excludeFilter.add(new edu.umd.cs.findbugs.filter.Filter(argument));
} catch (FilterException e) {
throw new IllegalArgumentException("Error processing include file: " + argument, e);
}
- } else if (option.equals("-maxAge")) {
+ } else if ("-maxAge".equals(option)) {
maxAge = Integer.parseInt(argument);
maxAgeSpecified = true;
- } else if (option.equals("-hashes")) {
+ } else if ("-hashes".equals(option)) {
hashesFromFile = new HashSet<String>();
BufferedReader in = null;
try {
in = new BufferedReader(UTF8.fileReader(argument));
while (true) {
String h = in.readLine();
- if (h == null)
+ if (h == null) {
break;
+ }
hashesFromFile.add(h);
}
} catch (IOException e) {
@@ -629,8 +682,9 @@ public class Filter {
} finally {
Util.closeSilently(in);
}
- } else
+ } else {
throw new IllegalArgumentException("can't handle command line argument of " + option);
+ }
}
@@ -645,11 +699,13 @@ public class Filter {
if (maybeMutatedAsString != null) {
HashSet<String> addedIssues = new HashSet<String>();
HashSet<String> removedIssues = new HashSet<String>();
- for (BugInstance b : origCollection)
- if (b.getFirstVersion() == maybeMutated)
+ for (BugInstance b : origCollection) {
+ if (b.getFirstVersion() == maybeMutated) {
addedIssues.add(getBugLocation(b));
- else if (b.getLastVersion() == maybeMutated - 1)
+ } else if (b.getLastVersion() == maybeMutated - 1) {
removedIssues.add(getBugLocation(b));
+ }
+ }
addedIssues.remove(null);
addedIssues.retainAll(removedIssues);
mutationPoints = addedIssues;
@@ -673,12 +729,13 @@ public class Filter {
String point;
MethodAnnotation m = b.getPrimaryMethod();
FieldAnnotation f = b.getPrimaryField();
- if (m != null)
+ if (m != null) {
point = m.toString();
- else if (f != null)
+ } else if (f != null) {
point = f.toString();
- else
+ } else {
point = null;
+ }
return point;
}
@@ -686,16 +743,18 @@ public class Filter {
public static int parsePriority(String argument) {
int i = " HMLE".indexOf(argument);
- if (i == -1)
+ if (i == -1) {
i = " 1234".indexOf(argument);
- if (i == -1)
+ }
+ if (i == -1) {
throw new IllegalArgumentException("Bad priority: " + argument);
+ }
return i;
}
static SourceSearcher sourceSearcher;
-
+
public static void main(String[] args) throws Exception {
FindBugs.setNoAnalysis();
DetectorFactoryCollection.instance();
@@ -706,18 +765,20 @@ public class Filter {
+ " [options] [<orig results> [<new results]] ");
SortedBugCollection origCollection = new SortedBugCollection();
- if (argCount == args.length)
+ if (argCount == args.length) {
origCollection.readXML(System.in);
- else
+ } else {
origCollection.readXML(args[argCount++]);
+ }
boolean verbose = argCount < args.length;
SortedBugCollection resultCollection = origCollection.createEmptyCollectionWithMetadata();
Project project = resultCollection.getProject();
int passed = 0;
int dropped = 0;
resultCollection.setWithMessages(commandLine.withMessages);
- if (commandLine.hashChangedSpecified)
+ if (commandLine.hashChangedSpecified) {
origCollection.computeBugHashes();
+ }
commandLine.adjustFilter(project, resultCollection);
ProjectStats projectStats = resultCollection.getProjectStats();
projectStats.clearBugCounts();
@@ -762,17 +823,19 @@ public class Filter {
+ "; ignoring filtering options that require cloud access");
} else if (!cloud.waitUntilIssueDataDownloaded(20, TimeUnit.SECONDS)) {
- if (verbose)
+ if (verbose) {
System.out.println("Waiting for cloud information required for filtering");
- if (!cloud.waitUntilIssueDataDownloaded(60, TimeUnit.SECONDS))
+ }
+ if (!cloud.waitUntilIssueDataDownloaded(60, TimeUnit.SECONDS)) {
disconnect(verbose, commandLine, resultCollection,
"Unable to connect to cloud; ignoring filtering options that require cloud access");
+ }
}
}
commandLine.getReady(origCollection);
- for (BugInstance bug : origCollection.getCollection())
+ for (BugInstance bug : origCollection.getCollection()) {
if (commandLine.accept(origCollection, bug)) {
if (trimToVersion >= 0) {
if (bug.getFirstVersion() > trimToVersion) {
@@ -785,19 +848,22 @@ public class Filter {
}
resultCollection.add(bug, false);
passed++;
- } else
+ } else {
dropped++;
+ }
+ }
if (commandLine.purgeHistorySpecified && commandLine.purgeHistory) {
resultCollection.clearAppVersions();
for (BugInstance bug : resultCollection.getCollection()) {
bug.clearHistory();
}
-
-
+
+
}
- if (verbose)
+ if (verbose) {
System.out.println(passed + " warnings passed through, " + dropped + " warnings dropped");
+ }
if (commandLine.withSourceSpecified && commandLine.withSource && !commandLine.dontUpdateStats
&& projectStats.hasClassStats()) {
for (PackageStats stats : projectStats.getPackageStats()) {
@@ -805,8 +871,9 @@ public class Filter {
while (i.hasNext()) {
String className = i.next().getName();
if (sourceSearcher.sourceNotFound.contains(className) || !sourceSearcher.sourceFound.contains(className)
- && !sourceSearcher.findSource(SourceLineAnnotation.createReallyUnknown(className)))
+ && !sourceSearcher.findSource(SourceLineAnnotation.createReallyUnknown(className))) {
i.remove();
+ }
}
}
@@ -825,13 +892,13 @@ public class Filter {
private static void disconnect(boolean verbose, final FilterCommandLine commandLine, SortedBugCollection resultCollection,
- String msg) {
- if (verbose)
+ String msg) {
+ if (verbose) {
System.out.println(msg);
+ }
resultCollection.addError(msg);
commandLine.maxAgeSpecified = commandLine.notAProblemSpecified = commandLine.shouldFixSpecified = false;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/workflow/ListBugDatabaseInfo.java b/src/java/edu/umd/cs/findbugs/workflow/ListBugDatabaseInfo.java
index 7899dc5..f3656ae 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/ListBugDatabaseInfo.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/ListBugDatabaseInfo.java
@@ -56,10 +56,11 @@ public class ListBugDatabaseInfo {
@Override
public void handleOption(String option, String optionalExtraPart) {
- if (option.equals("-formatDates"))
+ if ("-formatDates".equals(option)) {
formatDates = true;
- else
+ } else {
throw new IllegalArgumentException("unknown option: " + option);
+ }
}
@Override
@@ -76,9 +77,9 @@ public class ListBugDatabaseInfo {
int argCount = commandLine.parse(args, 0, Integer.MAX_VALUE, USAGE);
PrintWriter out = UTF8.printWriter(System.out, true);
- if (argCount == args.length)
+ if (argCount == args.length) {
listVersion(out, null, commandLine.formatDates);
- else {
+ } else {
out.println("version\ttime\tclasses\tNCSS\terrors\ttotal\thigh\tmedium\tlow\tfile");
while (argCount < args.length) {
String fileName = args[argCount++];
@@ -89,22 +90,24 @@ public class ListBugDatabaseInfo {
}
private static void listVersion(PrintWriter out, @CheckForNull String fileName, boolean formatDates) throws IOException,
- DocumentException {
+ DocumentException {
SortedBugCollection origCollection;
origCollection = new SortedBugCollection();
- if (fileName == null)
+ if (fileName == null) {
origCollection.readXML(System.in);
- else
+ } else {
origCollection.readXML(fileName);
+ }
AppVersion appVersion = origCollection.getCurrentAppVersion();
ProjectStats stats = origCollection.getProjectStats();
out.print(appVersion.getReleaseName());
out.print('\t');
- if (formatDates)
+ if (formatDates) {
out.print("\"" + new Date(appVersion.getTimestamp()) + "\"");
- else
+ } else {
out.print(appVersion.getTimestamp());
+ }
out.print('\t');
out.print(appVersion.getNumClasses());
diff --git a/src/java/edu/umd/cs/findbugs/workflow/ListErrors.java b/src/java/edu/umd/cs/findbugs/workflow/ListErrors.java
index 326a29c..e7bc618 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/ListErrors.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/ListErrors.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.SortedBugCollection;
/**
* List the analysis errors in a bug collection
- *
+ *
* @author Bill Pugh
*/
public class ListErrors {
@@ -39,11 +39,11 @@ public class ListErrors {
bugCollection.readXML(args[0]);
for (AnalysisError e : bugCollection.getErrors()) {
String msg = e.getExceptionMessage();
- if (msg != null && msg.trim().length() > 0)
+ if (msg != null && msg.trim().length() > 0) {
System.out.println(e.getMessage() + " : " + msg);
-
- else
+ } else {
System.out.println(e.getMessage());
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/workflow/MergeSummarizeAndView.java b/src/java/edu/umd/cs/findbugs/workflow/MergeSummarizeAndView.java
index 465c245..ebe7b6f 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/MergeSummarizeAndView.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/MergeSummarizeAndView.java
@@ -102,10 +102,11 @@ public class MergeSummarizeAndView {
*/
@Override
protected void handleOption(String option, String optionExtraPart) throws IOException {
- if (option.equals("-gui"))
+ if ("-gui".equals(option)) {
options.alwaysShowGui = true;
- else
+ } else {
throw new IllegalArgumentException("Unknown option : " + option);
+ }
}
/*
@@ -117,24 +118,25 @@ public class MergeSummarizeAndView {
*/
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-workingDir"))
+ if ("-workingDir".equals(option)) {
options.workingDirList = Arrays.asList(argument.split(","));
- else if (option.equals("-srcDir"))
+ } else if ("-srcDir".equals(option)) {
options.srcDirList = Arrays.asList(argument.split(","));
- else if (option.equals("-maxRank"))
+ } else if ("-maxRank".equals(option)) {
options.maxRank = Integer.parseInt(argument);
- else if (option.equals("-maxAge"))
+ } else if ("-maxAge".equals(option)) {
options.maxAge = Integer.parseInt(argument);
- else if (option.equals("-cloud"))
+ } else if ("-cloud".equals(option)) {
options.cloudId = argument;
- else if (option.equals("-baseline"))
+ } else if ("-baseline".equals(option)) {
try {
options.baselineDate = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse(argument);
} catch (ParseException e) {
System.err.println("Date " + argument + " not in MM/dd/yyyy format (e.g., 05/13/2009)");
}
- else
+ } else {
throw new IllegalArgumentException("Unknown option : " + option);
+ }
}
}
@@ -171,8 +173,9 @@ public class MergeSummarizeAndView {
int argCount = commandLine.parse(argv, 1, Integer.MAX_VALUE, "Usage: " + MergeSummarizeAndView.class.getName()
+ " [options] [<results1> <results2> ... <resultsn>] ");
- for (int i = argCount; i < argv.length; i++)
+ for (int i = argCount; i < argv.length; i++) {
options.analysisFiles.add(argv[i]);
+ }
MergeSummarizeAndView msv = new MergeSummarizeAndView(options);
boolean isCloudManagedByGui = false;
try {
@@ -318,16 +321,18 @@ public class MergeSummarizeAndView {
long old = System.currentTimeMillis() - options.maxAge * (24 * 3600 * 1000L);
if (options.baselineDate != null) {
long old2 = options.baselineDate.getTime();
- if (old2 > old)
+ if (old2 > old) {
old = old2;
+ }
}
scaryBugs = results.createEmptyCollectionWithMetadata();
- for (BugInstance warning : results.getCollection())
+ for (BugInstance warning : results.getCollection()) {
if (!project.getSuppressionFilter().match(warning)) {
int rank = BugRanker.findRank(warning);
- if (rank > BugRanker.VISIBLE_RANK_MAX)
+ if (rank > BugRanker.VISIBLE_RANK_MAX) {
continue;
+ }
if (cloud.getConsensusDesignation(warning).score() < 0) {
harmless++;
continue;
@@ -336,13 +341,15 @@ public class MergeSummarizeAndView {
long firstSeen = cloud.getFirstSeen(warning);
boolean isOld = FindBugs.validTimestamp(firstSeen) && firstSeen < old;
boolean highRank = rank > options.maxRank;
- if (highRank)
+ if (highRank) {
numLowConfidence++;
- else if (isOld)
+ } else if (isOld) {
tooOld++;
- else
+ } else {
scaryBugs.add(warning);
+ }
}
+ }
}
private boolean report() {
@@ -365,12 +372,15 @@ public class MergeSummarizeAndView {
if (hasScaryBugs) {
System.out.println();
System.out.print("plus ");
- if (numLowConfidence > 0)
+ if (numLowConfidence > 0) {
System.out.printf("%d less scary recent issues", numLowConfidence);
- if (numLowConfidence > 0 && tooOld > 0)
+ }
+ if (numLowConfidence > 0 && tooOld > 0) {
System.out.printf(" and ");
- if (tooOld > 0)
+ }
+ if (tooOld > 0) {
System.out.printf("%d older issues", tooOld);
+ }
System.out.println();
}
}
@@ -410,4 +420,3 @@ public class MergeSummarizeAndView {
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/workflow/MineBugHistory.java b/src/java/edu/umd/cs/findbugs/workflow/MineBugHistory.java
index 358100a..6597127 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/MineBugHistory.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/MineBugHistory.java
@@ -40,13 +40,13 @@ import edu.umd.cs.findbugs.config.CommandLine;
* Mine historical information from a BugCollection. The BugCollection should be
* built using UpdateBugCollection to record the history of analyzing all
* versions over time.
- *
+ *
* @author David Hovemeyer
* @author William Pugh
*/
public class MineBugHistory {
/**
- *
+ *
*/
private static final int WIDTH = 12;
@@ -86,8 +86,9 @@ public class MineBugHistory {
void increment(int key) {
tuple[key]++;
- if (key == ADDED || key == RETAINED || key == NEWCODE)
+ if (key == ADDED || key == RETAINED || key == NEWCODE) {
tuple[ACTIVE_NOW]++;
+ }
}
int get(int key) {
@@ -163,17 +164,19 @@ public class MineBugHistory {
BugInstance bugInstance = j.next();
for (int i = 0; i <= maxSequence; ++i) {
- if (bugInstance.getFirstVersion() > i)
+ if (bugInstance.getFirstVersion() > i) {
continue;
+ }
boolean activePrevious = bugInstance.getFirstVersion() < i
&& (!bugInstance.isDead() || bugInstance.getLastVersion() >= i - 1);
boolean activeCurrent = !bugInstance.isDead() || bugInstance.getLastVersion() >= i;
int key = getKey(activePrevious, activeCurrent);
- if (key == REMOVED && !bugInstance.isRemovedByChangeOfPersistingClass())
+ if (key == REMOVED && !bugInstance.isRemovedByChangeOfPersistingClass()) {
key = REMOVEDCODE;
- else if (key == ADDED && !bugInstance.isIntroducedByChangeOfExistingClass())
+ } else if (key == ADDED && !bugInstance.isIntroducedByChangeOfExistingClass()) {
key = NEWCODE;
+ }
versionList[i].increment(key);
}
}
@@ -182,14 +185,15 @@ public class MineBugHistory {
}
public void dump(PrintStream out) {
- if (xml)
+ if (xml) {
dumpXml(out);
- else if (noTabs)
+ } else if (noTabs) {
dumpNoTabs(out);
- else if (summary)
+ } else if (summary) {
dumpSummary(out);
- else
+ } else {
dumpOriginal(out);
+ }
}
public void dumpSummary(PrintStream out) {
@@ -209,16 +213,19 @@ public class MineBugHistory {
b.append('-');
b.append(removed);
}
- if (added == 0 && removed == 0)
+ if (added == 0 && removed == 0) {
b.append('0');
+ }
int paddingNeeded = WIDTH - b.length() % WIDTH;
- if (paddingNeeded > 0)
+ if (paddingNeeded > 0) {
b.append(" ".substring(0, paddingNeeded));
+ }
}
int errors = bugCollection.getErrors().size();
- if (errors > 0)
+ if (errors > 0) {
b.append(" ").append(errors).append(" errors");
+ }
out.println(b.toString());
}
@@ -233,18 +240,20 @@ public class MineBugHistory {
out.print('\t');
out.print(appVersion != null ? appVersion.getReleaseName() : "");
out.print('\t');
- if (formatDates)
+ if (formatDates) {
out.print("\"" + (appVersion != null ? dateFormat.format(new Date(appVersion.getTimestamp())) : "") + "\"");
- else
+ } else {
out.print(appVersion != null ? appVersion.getTimestamp() / 1000 : 0L);
+ }
out.print('\t');
if (appVersion != null) {
out.print(appVersion.getNumClasses());
out.print('\t');
out.print(appVersion.getCodeSize());
- } else
+ } else {
out.print("\t0\t0");
+ }
for (int j = 0; j < TUPLE_SIZE; ++j) {
out.print('\t');
@@ -256,13 +265,14 @@ public class MineBugHistory {
/** emit <code>width</code> space characters to <code>out</code> */
private static void pad(int width, PrintStream out) {
- while (width-- > 0)
+ while (width-- > 0) {
out.print(' ');
+ }
}
/**
* equivalent to out.print(obj) except it may be padded on the left or right
- *
+ *
* @param width
* padding will occur if the stringified oxj is shorter than this
* @param alignRight
@@ -275,11 +285,13 @@ public class MineBugHistory {
private static void print(int width, boolean alignRight, PrintStream out, Object obj) {
String s = String.valueOf(obj);
int padLen = width - s.length();
- if (alignRight)
+ if (alignRight) {
pad(padLen, out);
+ }
out.print(s); // doesn't truncate if (s.length() > width)
- if (!alignRight)
+ if (!alignRight) {
pad(padLen, out);
+ }
}
/**
@@ -287,7 +299,7 @@ public class MineBugHistory {
* with a fixed-width font) by padding with spaces instead of using tabs.
* Also, timestamps are formatted more tersely (-formatDates option). The
* bad news is that it requires a minimum of 112 columns.
- *
+ *
* @see #dumpOriginal(PrintStream)
*/
public void dumpNoTabs(PrintStream out) {
@@ -323,10 +335,11 @@ public class MineBugHistory {
out.print(' ');
long ts = (appVersion != null ? appVersion.getTimestamp() : 0L);
- if (formatDates)
+ if (formatDates) {
print(12, false, out, dateFormat.format(ts));
- else
+ } else {
print(10, false, out, ts / 1000);
+ }
out.print(' ');
print(7, true, out, appVersion != null ? appVersion.getNumClasses() : 0);
@@ -358,10 +371,11 @@ public class MineBugHistory {
out.print(appVersion != null ? appVersion.getReleaseName() : "");
out.print("\" ");
out.print("time=\"");
- if (formatDates)
+ if (formatDates) {
out.print((appVersion != null ? new Date(appVersion.getTimestamp()).toString() : ""));
- else
+ } else {
out.print(appVersion != null ? appVersion.getTimestamp() : 0L);
+ }
out.print("\"");
out.println(">");
@@ -392,7 +406,7 @@ public class MineBugHistory {
/**
* Get key used to classify the presence and/or abscence of a BugInstance in
* successive versions in the history.
- *
+ *
* @param activePrevious
* true if the bug was active in the previous version, false if
* not
@@ -401,11 +415,12 @@ public class MineBugHistory {
* @return the key: one of ADDED, RETAINED, REMOVED, and DEAD
*/
private int getKey(boolean activePrevious, boolean activeCurrent) {
- if (activePrevious)
+ if (activePrevious) {
return activeCurrent ? RETAINED : REMOVED;
- else
+ } else {
// !activePrevious
return activeCurrent ? ADDED : DEAD;
+ }
}
class MineBugHistoryCommandLine extends CommandLine {
@@ -419,16 +434,17 @@ public class MineBugHistory {
@Override
public void handleOption(String option, String optionalExtraPart) {
- if (option.equals("-formatDates"))
+ if ("-formatDates".equals(option)) {
setFormatDates(true);
- else if (option.equals("-noTabs"))
+ } else if ("-noTabs".equals(option)) {
setNoTabs();
- else if (option.equals("-xml"))
+ } else if ("-xml".equals(option)) {
setXml();
- else if (option.equals("-summary"))
+ } else if ("-summary".equals(option)) {
setSummary();
- else
+ } else {
throw new IllegalArgumentException("unknown option: " + option);
+ }
}
@Override
@@ -448,10 +464,11 @@ public class MineBugHistory {
+ " [options] [<xml results> [<history]] ");
SortedBugCollection bugCollection = new SortedBugCollection();
- if (argCount < args.length)
+ if (argCount < args.length) {
bugCollection.readXML(args[argCount++]);
- else
+ } else {
bugCollection.readXML(System.in);
+ }
mineBugHistory.setBugCollection(bugCollection);
mineBugHistory.execute();
diff --git a/src/java/edu/umd/cs/findbugs/workflow/ObfuscateBugs.java b/src/java/edu/umd/cs/findbugs/workflow/ObfuscateBugs.java
index 2041c1a..37a2d16 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/ObfuscateBugs.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/ObfuscateBugs.java
@@ -46,8 +46,9 @@ public class ObfuscateBugs {
public ObfuscateBugs execute() {
ProjectPackagePrefixes foo = new ProjectPackagePrefixes();
- for (BugInstance b : bugCollection.getCollection())
+ for (BugInstance b : bugCollection.getCollection()) {
foo.countBug(b);
+ }
foo.report();
return this;
@@ -62,7 +63,7 @@ public class ObfuscateBugs {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.config.CommandLine#handleOptionWithArgument(java
* .lang.String, java.lang.String)
@@ -81,10 +82,11 @@ public class ObfuscateBugs {
int argCount = commandLine.parse(args, 0, 2, "Usage: " + ObfuscateBugs.class.getName() + " [options] [<xml results>] ");
SortedBugCollection bugCollection = new SortedBugCollection();
- if (argCount < args.length)
+ if (argCount < args.length) {
bugCollection.readXML(args[argCount++]);
- else
+ } else {
bugCollection.readXML(System.in);
+ }
SortedBugCollection results = bugCollection.createEmptyCollectionWithMetadata();
Project project = results.getProject();
diff --git a/src/java/edu/umd/cs/findbugs/workflow/PrintAppVersion.java b/src/java/edu/umd/cs/findbugs/workflow/PrintAppVersion.java
index cac1076..d460430 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/PrintAppVersion.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/PrintAppVersion.java
@@ -24,7 +24,7 @@ import edu.umd.cs.findbugs.SortedBugCollection;
/**
* Print the AppVersion information from a BugCollection.
- *
+ *
* @author David Hovemeyer
*/
public class PrintAppVersion {
diff --git a/src/java/edu/umd/cs/findbugs/workflow/RebornIssues.java b/src/java/edu/umd/cs/findbugs/workflow/RebornIssues.java
index d7e2a06..12920e4 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/RebornIssues.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/RebornIssues.java
@@ -36,7 +36,7 @@ import edu.umd.cs.findbugs.SortedBugCollection;
* Mine historical information from a BugCollection. The BugCollection should be
* built using UpdateBugCollection to record the history of analyzing all
* versions over time.
- *
+ *
* @author David Hovemeyer
* @author William Pugh
*/
@@ -57,7 +57,7 @@ public class RebornIssues {
public RebornIssues execute() {
Map<String, List<BugInstance>> map = new HashMap<String, List<BugInstance>>();
- for (BugInstance b : bugCollection.getCollection())
+ for (BugInstance b : bugCollection.getCollection()) {
if (b.getFirstVersion() != 0 || b.getLastVersion() != -1) {
List<BugInstance> lst = map.get(b.getInstanceHash());
if (lst == null) {
@@ -66,6 +66,7 @@ public class RebornIssues {
}
lst.add(b);
}
+ }
for (List<BugInstance> lst : map.values()) {
if (lst.size() > 1) {
TreeSet<Long> removalTimes = new TreeSet<Long>();
@@ -74,19 +75,23 @@ public class RebornIssues {
String bugPattern = "XXX";
for (BugInstance b : lst) {
bugPattern = b.getBugPattern().getType();
- if (b.getFirstVersion() > 0)
+ if (b.getFirstVersion() > 0) {
additionTimes.add(b.getFirstVersion());
- if (b.getLastVersion() != -1)
+ }
+ if (b.getLastVersion() != -1) {
removalTimes.add(b.getLastVersion());
+ }
}
Iterator<Long> aI = additionTimes.iterator();
- if (!aI.hasNext())
+ if (!aI.hasNext()) {
continue;
+ }
long a = aI.next();
loop: for (Long removed : removalTimes) {
while (a <= removed) {
- if (!aI.hasNext())
+ if (!aI.hasNext()) {
break loop;
+ }
a = aI.next();
}
System.out.printf("%5d %5d %s%n", removed, a, bugPattern);
@@ -120,10 +125,11 @@ public class RebornIssues {
+ " [options] [<xml results> [<history]] ");
SortedBugCollection bugCollection = new SortedBugCollection();
- if (argCount < args.length)
+ if (argCount < args.length) {
bugCollection.readXML(args[argCount++]);
- else
+ } else {
bugCollection.readXML(System.in);
+ }
reborn.setBugCollection(bugCollection);
reborn.execute();
diff --git a/src/java/edu/umd/cs/findbugs/workflow/RecursiveSearchForJavaFiles.java b/src/java/edu/umd/cs/findbugs/workflow/RecursiveSearchForJavaFiles.java
index 8fcebe2..fea65a4 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/RecursiveSearchForJavaFiles.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/RecursiveSearchForJavaFiles.java
@@ -27,8 +27,9 @@ import java.util.Set;
public class RecursiveSearchForJavaFiles {
public static void main(String args[]) {
- for (File f : search(new File(args[0])))
+ for (File f : search(new File(args[0]))) {
System.out.println(f.getPath());
+ }
}
public static Set<File> search(File root) {
@@ -40,15 +41,16 @@ public class RecursiveSearchForJavaFiles {
while (!worklist.isEmpty()) {
File next = worklist.removeFirst();
File[] files = next.listFiles();
- if (files != null)
+ if (files != null) {
for (File f : files) {
- if (f.getName().endsWith(".java"))
+ if (f.getName().endsWith(".java")) {
result.add(f);
- else if (f.isDirectory() && directories.add(f)) {
+ } else if (f.isDirectory() && directories.add(f)) {
worklist.add(f);
}
}
+ }
}
return result;
diff --git a/src/java/edu/umd/cs/findbugs/workflow/RejarClassesForAnalysis.java b/src/java/edu/umd/cs/findbugs/workflow/RejarClassesForAnalysis.java
index 443aaa8..dd2ea4d 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/RejarClassesForAnalysis.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/RejarClassesForAnalysis.java
@@ -69,14 +69,17 @@ public class RejarClassesForAnalysis {
PatternMatcher(String arg) {
String[] p = arg.split(",");
this.pattern = new Pattern[p.length];
- for (int i = 0; i < p.length; i++)
+ for (int i = 0; i < p.length; i++) {
pattern[i] = Pattern.compile(p[i]);
+ }
}
public boolean matches(String arg) {
- for (Pattern p : pattern)
- if (p.matcher(arg).find())
+ for (Pattern p : pattern) {
+ if (p.matcher(arg).find()) {
return true;
+ }
+ }
return false;
}
@@ -94,17 +97,21 @@ public class RejarClassesForAnalysis {
}
public boolean matches(String arg) {
- for (String p : prefixes)
- if (arg.startsWith(p))
+ for (String p : prefixes) {
+ if (arg.startsWith(p)) {
return true;
+ }
+ }
return false;
}
public boolean matchesEverything() {
- for (String p : prefixes)
- if (p.length() == 0)
+ for (String p : prefixes) {
+ if (p.length() == 0) {
return true;
+ }
+ }
return false;
}
}
@@ -136,7 +143,7 @@ public class RejarClassesForAnalysis {
addOption("-maxClasses", "num", "maximum number of classes per analysis*.jar file");
addOption("-outputDir", "dir", "directory for the generated jar files");
addSwitch("-ignoreTimestamps", "ignore timestamps on zip entries; use first version found");
-
+
addOption("-prefix", "class name prefix",
"comma separated list of class name prefixes that should be analyzed (e.g., edu.umd.cs.)");
addOption("-exclude", "class name prefix",
@@ -157,12 +164,13 @@ public class RejarClassesForAnalysis {
*/
@Override
protected void handleOption(String option, String optionExtraPart) throws IOException {
- if (option.equals("-analyzeOnly")) {
+ if ("-analyzeOnly".equals(option)) {
onlyAnalyze = true;
- } else if (option.equals("-ignoreTimestamps")) {
+ } else if ("-ignoreTimestamps".equals(option)) {
ignoreTimestamps = true;
- }else
+ } else {
throw new IllegalArgumentException("Unknown option : " + option);
+ }
}
/*
@@ -174,24 +182,25 @@ public class RejarClassesForAnalysis {
*/
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-prefix"))
+ if ("-prefix".equals(option)) {
prefix = new PrefixMatcher(argument);
- else if (option.equals("-exclude"))
+ } else if ("-exclude".equals(option)) {
exclude = new PrefixMatcher(argument);
- else if (option.equals("-inputFileList"))
+ } else if ("-inputFileList".equals(option)) {
inputFileList = argument;
- else if (option.equals("-auxFileList"))
+ } else if ("-auxFileList".equals(option)) {
auxFileList = argument;
- else if (option.equals("-maxClasses"))
+ } else if ("-maxClasses".equals(option)) {
maxClasses = Integer.parseInt(argument);
- else if (option.equals("-maxAge"))
+ } else if ("-maxAge".equals(option)) {
maxAge = System.currentTimeMillis() - (24 * 60 * 60 * 1000L) * Integer.parseInt(argument);
- else if (option.equals("-outputDir"))
+ } else if ("-outputDir".equals(option)) {
outputDir = new File(argument);
- else if (option.equals("-excludePattern"))
+ } else if ("-excludePattern".equals(option)) {
excludePatterns = new PatternMatcher(argument);
- else
+ } else {
throw new IllegalArgumentException("Unknown option : " + option);
+ }
}
boolean skip(ZipEntry ze) {
@@ -212,7 +221,7 @@ public class RejarClassesForAnalysis {
}
public static void readFromStandardInput(Collection<String> result) throws IOException {
- readFrom(result, UserTextFile.bufferedReader(System.in));
+ readFrom(result, UserTextFile.bufferedReader(System.in));
}
SortedMap<String, ZipOutputStream> analysisOutputFiles = new TreeMap<String, ZipOutputStream>();
@@ -220,13 +229,15 @@ public class RejarClassesForAnalysis {
public @Nonnull
ZipOutputStream getZipOutputFile(String path) {
ZipOutputStream result = analysisOutputFiles.get(path);
- if (result != null)
+ if (result != null) {
return result;
+ }
SortedMap<String, ZipOutputStream> head = analysisOutputFiles.headMap(path);
String matchingPath = head.lastKey();
result = analysisOutputFiles.get(matchingPath);
- if (result == null)
+ if (result == null) {
throw new IllegalArgumentException("No zip output file for " + path);
+ }
return result;
}
@@ -249,10 +260,11 @@ public class RejarClassesForAnalysis {
String getNextAuxilaryFileOutput() {
String result;
- if (auxilaryCount == 1)
+ if (auxilaryCount == 1) {
result = "auxilary.jar";
- else
+ } else {
result = "auxilary" + (auxilaryCount) + ".jar";
+ }
auxilaryCount++;
System.out.println("Starting " + result);
return result;
@@ -260,10 +272,11 @@ public class RejarClassesForAnalysis {
String getNextAnalyzeFileOutput() {
String result;
- if (analysisCount == 1)
+ if (analysisCount == 1) {
result = "analyze.jar";
- else
+ } else {
result = "analyze" + (analysisCount) + ".jar";
+ }
analysisCount++;
System.out.println("Starting " + result);
return result;
@@ -296,8 +309,9 @@ public class RejarClassesForAnalysis {
final byte buffer[] = new byte[8192];
private boolean exclude(String dottedName) {
- if (!Character.isJavaIdentifierStart(dottedName.charAt(0)))
- return true;
+ if (!Character.isJavaIdentifierStart(dottedName.charAt(0))) {
+ return true;
+ }
if (commandLine.excludePatterns != null && commandLine.excludePatterns.matches(dottedName)
|| commandLine.exclude.matches(dottedName)) {
excluded.add(dottedName);
@@ -311,12 +325,13 @@ public class RejarClassesForAnalysis {
ArrayList<String> fileList = new ArrayList<String>();
- if (commandLine.inputFileList != null)
+ if (commandLine.inputFileList != null) {
readFrom(fileList, UTF8.fileReader(commandLine.inputFileList));
- else if (argCount == args.length)
- readFromStandardInput(fileList);
- else
+ } else if (argCount == args.length) {
+ readFromStandardInput(fileList);
+ } else {
fileList.addAll(Arrays.asList(args).subList(argCount, args.length));
+ }
ArrayList<String> auxFileList = new ArrayList<String>();
if (commandLine.auxFileList != null) {
readFrom(auxFileList, UTF8.fileReader(commandLine.auxFileList));
@@ -331,30 +346,34 @@ public class RejarClassesForAnalysis {
System.err.println("Skipping " + fInName + ", too old (" + new Date(f.lastModified()) + ")");
continue;
}
-
+
int oldSize = copied.size();
classFileFound = false;
if (processZipEntries(f, new ZipElementHandler() {
boolean checked = false;
+ @Override
public void handle(ZipFile file, ZipEntry ze) throws IOException {
- if (commandLine.skip(ze))
+ if (commandLine.skip(ze)) {
return;
+ }
String name = ze.getName();
String dottedName = name.replace('/', '.');
- if (exclude(dottedName))
+ if (exclude(dottedName)) {
return;
+ }
if (!checked) {
- checked = true;
+ checked = true;
if (embeddedNameMismatch(file, ze)) {
System.out.println("Class name mismatch for " + name + " in " + file.getName());
throw new ClassFileNameMismatch();
}
}
- if (!commandLine.prefix.matches(dottedName))
+ if (!commandLine.prefix.matches(dottedName)) {
return;
+ }
classFileFound = true;
long timestamp = ze.getTime();
Long oldTimestamp = copied.get(name);
@@ -375,12 +394,13 @@ public class RejarClassesForAnalysis {
* @return
*/
- }) && oldSize < copied.size())
+ }) && oldSize < copied.size()) {
inputZipFiles.add(f);
- else if (classFileFound)
+ } else if (classFileFound) {
System.err.println("Skipping " + fInName + ", no new classes found");
- else
+ } else {
System.err.println("Skipping " + fInName + ", no classes found");
+ }
}
for (String fInName : auxFileList) {
final File f = new File(fInName);
@@ -391,9 +411,11 @@ public class RejarClassesForAnalysis {
int oldSize = copied.size();
classFileFound = false;
if (processZipEntries(f, new ZipElementHandler() {
+ @Override
public void handle(ZipFile file, ZipEntry ze) {
- if (commandLine.skip(ze))
+ if (commandLine.skip(ze)) {
return;
+ }
String name = ze.getName();
String dottedName = name.replace('/', '.');
@@ -410,28 +432,33 @@ public class RejarClassesForAnalysis {
}
}
}
- }) && oldSize < copied.size())
+ }) && oldSize < copied.size()) {
auxZipFiles.add(f);
- else if (classFileFound)
+ } else if (classFileFound) {
System.err.println("Skipping aux file " + fInName + ", no new classes found");
- else
+ } else {
System.err.println("Skipping aux file" + fInName + ", no classes found");
+ }
}
System.out.printf(" # Zip/jar files: %2d%n", inputZipFiles.size());
System.out.printf("# aux Zip/jar files: %2d%n", auxZipFiles.size());
System.out.printf("Unique class files: %6d%n", copied.size());
- if (numFilesToAnalyze != copied.size())
+ if (numFilesToAnalyze != copied.size()) {
System.out.printf(" files to analyze: %6d%n", numFilesToAnalyze);
+ }
- if (!excluded.isEmpty())
+ if (!excluded.isEmpty()) {
System.out.printf(" excluded files: %6d%n", excluded.size());
+ }
- if (commandLine.onlyAnalyze)
+ if (commandLine.onlyAnalyze) {
return;
+ }
- if (numFilesToAnalyze < copied.size() || numFilesToAnalyze > commandLine.maxClasses)
+ if (numFilesToAnalyze < copied.size() || numFilesToAnalyze > commandLine.maxClasses) {
auxilaryOut = createZipFile(getNextAuxilaryFileOutput());
+ }
int count = Integer.MAX_VALUE;
String oldBaseClass = "x x";
@@ -442,14 +469,15 @@ public class RejarClassesForAnalysis {
int firstDollar = path.indexOf('$', lastSlash);
String baseClass = firstDollar < 0 ? path : path.substring(0, firstDollar - 1);
boolean switchOutput;
- if (count > commandLine.maxClasses)
+ if (count > commandLine.maxClasses) {
switchOutput = true;
- else if (count + 50 > commandLine.maxClasses && !baseClass.equals(oldBaseClass))
+ } else if (count + 50 > commandLine.maxClasses && !baseClass.equals(oldBaseClass)) {
switchOutput = true;
- else if (count + 250 > commandLine.maxClasses && !packageName.equals(oldPackage))
+ } else if (count + 250 > commandLine.maxClasses && !packageName.equals(oldPackage)) {
switchOutput = true;
- else
+ } else {
switchOutput = false;
+ }
if (switchOutput) {
// advance
@@ -468,29 +496,35 @@ public class RejarClassesForAnalysis {
final File ff = f;
processZipEntries(f, new ZipElementHandler() {
+ @Override
public void handle(ZipFile zipInputFile, ZipEntry ze) throws IOException {
- if (commandLine.skip(ze))
+ if (commandLine.skip(ze)) {
return;
+ }
+
-
String name = ze.getName();
String dottedName = name.replace('/', '.');
- if (exclude(dottedName))
+ if (exclude(dottedName)) {
return;
+ }
if (!ff.equals(copyFrom.get(name))) {
return;
}
- if (name.contains("DefaultProblem.class"))
+ if (name.contains("DefaultProblem.class")) {
System.out.printf("%40s %40s%n", name, ff);
-
+ }
+
boolean writeToAnalyzeOut = false;
boolean writeToAuxilaryOut = false;
if (commandLine.prefix.matches(dottedName)) {
writeToAnalyzeOut = true;
- if (numFilesToAnalyze > commandLine.maxClasses)
+ if (numFilesToAnalyze > commandLine.maxClasses) {
writeToAuxilaryOut = true;
- } else
+ }
+ } else {
writeToAuxilaryOut = auxilaryOut != null;
+ }
ZipOutputStream out = null;
if (writeToAnalyzeOut) {
out = getZipOutputFile(name);
@@ -517,15 +551,18 @@ public class RejarClassesForAnalysis {
System.err.println("Opening aux file " + f);
processZipEntries(f, new ZipElementHandler() {
+ @Override
public void handle(ZipFile zipInputFile, ZipEntry ze) throws IOException {
- if (commandLine.skip(ze))
+ if (commandLine.skip(ze)) {
return;
+ }
String name = ze.getName();
String dottedName = name.replace('/', '.');
- if (exclude(dottedName))
+ if (exclude(dottedName)) {
return;
+ }
if (!ff.equals(copyFrom.get(name))) {
return;
}
@@ -543,19 +580,16 @@ public class RejarClassesForAnalysis {
});
}
- if (auxilaryOut != null)
+ if (auxilaryOut != null) {
auxilaryOut.close();
- for (ZipOutputStream out : analysisOutputFiles.values())
+ }
+ for (ZipOutputStream out : analysisOutputFiles.values()) {
out.close();
+ }
System.out.println("All done");
}
- /**
- * @param fileName
- * @return
- * @throws FileNotFoundException
- */
private ZipOutputStream createZipFile(String fileName) throws FileNotFoundException {
File newFile = new File(commandLine.outputDir, fileName);
return new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(newFile)));
@@ -573,8 +607,9 @@ public class RejarClassesForAnalysis {
System.out.println(name);
System.out.println(" " + className);
}
- if (computedFileName.equals(name))
+ if (computedFileName.equals(name)) {
return false;
+ }
System.out.println("In " + name + " found " + className);
return true;
}
@@ -585,17 +620,22 @@ public class RejarClassesForAnalysis {
while (true) {
int bytesRead = zipIn.read(buffer);
- if (bytesRead < 0)
+ if (bytesRead < 0) {
break;
- if (writeToAnalyzeOut)
+ }
+ if (writeToAnalyzeOut) {
analyzeOut1.write(buffer, 0, bytesRead);
- if (writeToAuxilaryOut)
+ }
+ if (writeToAuxilaryOut) {
auxilaryOut1.write(buffer, 0, bytesRead);
+ }
}
- if (writeToAnalyzeOut)
+ if (writeToAnalyzeOut) {
analyzeOut1.closeEntry();
- if (writeToAuxilaryOut)
+ }
+ if (writeToAuxilaryOut) {
auxilaryOut1.closeEntry();
+ }
zipIn.close();
}
@@ -626,8 +666,9 @@ public class RejarClassesForAnalysis {
zipInputFile = new ZipFile(f);
for (Enumeration<? extends ZipEntry> e = zipInputFile.entries(); e.hasMoreElements();) {
ZipEntry ze = e.nextElement();
- if (!ze.isDirectory() && ze.getName().endsWith(".class") && ze.getSize() != 0)
+ if (!ze.isDirectory() && ze.getName().endsWith(".class") && ze.getSize() != 0) {
handler.handle(zipInputFile, ze);
+ }
}
zipInputFile.close();
@@ -642,10 +683,6 @@ public class RejarClassesForAnalysis {
}
- /**
- * @param ze
- * @return
- */
public ZipEntry newZipEntry(ZipEntry ze) {
ZipEntry ze2 = new ZipEntry(ze.getName());
ze2.setComment(ze.getComment());
diff --git a/src/java/edu/umd/cs/findbugs/workflow/SetBugDatabaseInfo.java b/src/java/edu/umd/cs/findbugs/workflow/SetBugDatabaseInfo.java
index 0dc16d8..8952abe 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/SetBugDatabaseInfo.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/SetBugDatabaseInfo.java
@@ -109,54 +109,56 @@ public class SetBugDatabaseInfo {
@Override
protected void handleOption(String option, String optionExtraPart) throws IOException {
- if (option.equals("-withMessages"))
+ if ("-withMessages".equals(option)) {
withMessages = true;
- else if (option.equals("-resetSource"))
+ } else if ("-resetSource".equals(option)) {
resetSource = true;
- else if (option.equals("-resetProject"))
+ } else if ("-resetProject".equals(option)) {
resetProject = true;
- else if (option.equals("-purgeStats"))
+ } else if ("-purgeStats".equals(option)) {
purgeStats = true;
- else if (option.equals("-purgeDesignations"))
+ } else if ("-purgeDesignations".equals(option)) {
purgeDesignations = true;
- else if (option.equals("-purgeClassStats"))
+ } else if ("-purgeClassStats".equals(option)) {
purgeClassStats = true;
- else if (option.equals("-purgeMissingClasses"))
+ } else if ("-purgeMissingClasses".equals(option)) {
purgeMissingClasses = true;
- else
+ } else {
throw new IllegalArgumentException("no option " + option);
+ }
}
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-name"))
+ if ("-name".equals(option)) {
revisionName = argument;
- else if (option.equals("-cloud"))
+ } else if ("-cloud".equals(option)) {
cloudId = argument;
- else if (option.equals("-cloudProperty")) {
+ } else if ("-cloudProperty".equals(option)) {
int e = argument.indexOf('=');
- if (e == -1)
+ if (e == -1) {
throw new IllegalArgumentException("Bad cloud property: " + argument);
+ }
String key = argument.substring(0, e);
String value = argument.substring(e + 1);
cloudProperties.put(key, value);
- } else if (option.equals("-projectName"))
+ } else if ("-projectName".equals(option)) {
projectName = argument;
- else if (option.equals("-suppress"))
+ } else if ("-suppress".equals(option)) {
exclusionFilterFile = argument;
- else if (option.equals("-timestamp"))
+ } else if ("-timestamp".equals(option)) {
revisionTimestamp = Date.parse(argument);
-
- else if (option.equals("-source"))
+ } else if ("-source".equals(option)) {
sourcePaths.add(argument);
- else if (option.equals("-lastVersion")) {
+ } else if ("-lastVersion".equals(option)) {
lastVersion = argument;
- } else if (option.equals("-findSource"))
+ } else if ("-findSource".equals(option)) {
searchSourcePaths.add(argument);
- else
+ } else {
throw new IllegalArgumentException("Can't handle option " + option);
+ }
}
@@ -170,24 +172,29 @@ public class SetBugDatabaseInfo {
SortedBugCollection origCollection = new SortedBugCollection();
- if (argCount < args.length)
+ if (argCount < args.length) {
origCollection.readXML(args[argCount++]);
- else
+ } else {
origCollection.readXML(System.in);
+ }
Project project = origCollection.getProject();
- if (commandLine.revisionName != null)
+ if (commandLine.revisionName != null) {
origCollection.setReleaseName(commandLine.revisionName);
- if (commandLine.projectName != null)
+ }
+ if (commandLine.projectName != null) {
origCollection.getProject().setProjectName(commandLine.projectName);
- if (commandLine.revisionTimestamp != 0)
+ }
+ if (commandLine.revisionTimestamp != 0) {
origCollection.setTimestamp(commandLine.revisionTimestamp);
+ }
origCollection.setWithMessages(commandLine.withMessages);
- if (commandLine.purgeDesignations)
+ if (commandLine.purgeDesignations) {
for (BugInstance b : origCollection) {
b.setUserDesignation(null);
}
+ }
if (commandLine.exclusionFilterFile != null) {
project.setSuppressionFilter(Filter.parseFilter(commandLine.exclusionFilterFile));
}
@@ -205,19 +212,24 @@ public class SetBugDatabaseInfo {
project.getCloudProperties().setProperty(e.getKey(), e.getValue());
reinitializeCloud = true;
}
-
- if (commandLine.resetSource)
+
+ if (commandLine.resetSource) {
project.getSourceDirList().clear();
- for (String source : commandLine.sourcePaths)
+ }
+ for (String source : commandLine.sourcePaths) {
project.addSourceDir(source);
- if (commandLine.purgeStats)
+ }
+ if (commandLine.purgeStats) {
origCollection.getProjectStats().getPackageStats().clear();
- if (commandLine.purgeClassStats)
+ }
+ if (commandLine.purgeClassStats) {
for (PackageStats ps : origCollection.getProjectStats().getPackageStats()) {
ps.getClassStats().clear();
}
- if (commandLine.purgeMissingClasses)
+ }
+ if (commandLine.purgeMissingClasses) {
origCollection.clearMissingClasses();
+ }
if (commandLine.lastVersion != null) {
long last = edu.umd.cs.findbugs.workflow.Filter.FilterCommandLine.getVersionNum(origCollection,
commandLine.lastVersion, true);
@@ -248,12 +260,12 @@ public class SetBugDatabaseInfo {
}
}
Set<String> foundPaths = new HashSet<String>();
- for (String f : commandLine.searchSourcePaths)
+ for (String f : commandLine.searchSourcePaths) {
for (File javaFile : RecursiveSearchForJavaFiles.search(new File(f))) {
Set<String> matchingMissingClasses = missingFiles.get(javaFile.getName());
if (matchingMissingClasses == null) {
// System.out.println("Nothing for " + javaFile);
- } else
+ } else {
for (String sourcePath : matchingMissingClasses) {
String path = javaFile.getAbsolutePath();
if (path.endsWith(sourcePath)) {
@@ -262,36 +274,44 @@ public class SetBugDatabaseInfo {
}
}
+ }
}
+ }
Set<String> toRemove = new HashSet<String>();
- for (String p1 : foundPaths)
- for (String p2 : foundPaths)
+ for (String p1 : foundPaths) {
+ for (String p2 : foundPaths) {
if (!p1.equals(p2) && p1.startsWith(p2)) {
toRemove.add(p1);
break;
}
+ }
+ }
foundPaths.removeAll(toRemove);
for (String dir : foundPaths) {
project.addSourceDir(dir);
- if (argCount < args.length)
+ if (argCount < args.length) {
System.out.println("Found " + dir);
+ }
}
}
-
+
if (reinitializeCloud)
+ {
origCollection.clearCloud();
- // OK, now we know all the missing source files
- // we also know all the .java files in the directories we were pointed
- // to
+ // OK, now we know all the missing source files
+ // we also know all the .java files in the directories we were pointed
+ // to
+ }
- if (argCount < args.length)
+ if (argCount < args.length) {
origCollection.writeXML(args[argCount++]);
- else
+ } else {
origCollection.writeXML(System.out);
+ }
}
diff --git a/src/java/edu/umd/cs/findbugs/workflow/SourceSearcher.java b/src/java/edu/umd/cs/findbugs/workflow/SourceSearcher.java
index 5024afc..49a551b 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/SourceSearcher.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/SourceSearcher.java
@@ -42,26 +42,32 @@ public class SourceSearcher {
}
public boolean findSource(SourceLineAnnotation srcLine) {
- if (srcLine == null)
+ if (srcLine == null) {
return false;
+ }
String cName = srcLine.getClassName();
- if (sourceFound.contains(cName))
+ if (sourceFound.contains(cName)) {
return true;
- if (sourceNotFound.contains(cName))
+ }
+ if (sourceNotFound.contains(cName)) {
return false;
+ }
boolean result = sourceFinder.hasSourceFile(srcLine);
return result;
}
public boolean findSource0(SourceLineAnnotation srcLine) {
- if (srcLine == null)
+ if (srcLine == null) {
return false;
+ }
String cName = srcLine.getClassName();
- if (sourceFound.contains(cName))
+ if (sourceFound.contains(cName)) {
return true;
- if (sourceNotFound.contains(cName))
+ }
+ if (sourceNotFound.contains(cName)) {
return false;
+ }
try {
InputStream in = sourceFinder.openSource(srcLine);
diff --git a/src/java/edu/umd/cs/findbugs/workflow/TestingGround.java b/src/java/edu/umd/cs/findbugs/workflow/TestingGround.java
index c2b9c90..b331b48 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/TestingGround.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/TestingGround.java
@@ -46,8 +46,9 @@ public class TestingGround {
public TestingGround execute() {
ProjectPackagePrefixes foo = new ProjectPackagePrefixes();
- for (BugInstance b : bugCollection.getCollection())
+ for (BugInstance b : bugCollection.getCollection()) {
foo.countBug(b);
+ }
foo.report();
return this;
@@ -73,10 +74,11 @@ public class TestingGround {
int argCount = commandLine.parse(args, 0, 2, "Usage: " + TestingGround.class.getName() + " [options] [<xml results>] ");
SortedBugCollection bugCollection = new SortedBugCollection();
- if (argCount < args.length)
+ if (argCount < args.length) {
bugCollection.readXML(args[argCount++]);
- else
+ } else {
bugCollection.readXML(System.in);
+ }
ArrayList<Bag<String>> live = new ArrayList<Bag<String>>();
ArrayList<Bag<String>> died = new ArrayList<Bag<String>>();
Bag<String> allBugs = new Bag<String>();
@@ -88,16 +90,19 @@ public class TestingGround {
int first = (int) b.getFirstVersion();
int buried = (int) b.getLastVersion() + 1;
int finish = buried;
- if (finish == 0)
+ if (finish == 0) {
finish = (int) bugCollection.getSequenceNumber();
+ }
String bugPattern = b.getBugPattern().getType();
allBugs.add(bugPattern);
- for (int i = first; i <= finish; i++)
+ for (int i = first; i <= finish; i++) {
live.get(i).add(bugPattern);
- if (buried > 0)
+ }
+ if (buried > 0) {
died.get(buried).add(bugPattern);
+ }
}
for (int i = 0; i < bugCollection.getSequenceNumber(); i++) {
for (Map.Entry<String, Integer> e : died.get(i).entrySet()) {
@@ -117,12 +122,14 @@ public class TestingGround {
if (buried > 0) {
int buriedCount = died.get(buried).getCount(bugPattern);
int total = live.get(buried).getCount(bugPattern);
- if (buriedCount > 30 && buriedCount * 3 > total)
+ if (buriedCount > 30 && buriedCount * 3 > total) {
continue;
+ }
}
int survied = live.get((int) bugCollection.getSequenceNumber()).getCount(bugPattern);
- if (survied == 0 && allBugs.getCount(bugPattern) > 100)
+ if (survied == 0 && allBugs.getCount(bugPattern) > 100) {
continue;
+ }
results.add(b, false);
}
diff --git a/src/java/edu/umd/cs/findbugs/workflow/TreemapVisualization.java b/src/java/edu/umd/cs/findbugs/workflow/TreemapVisualization.java
index b19dca1..0cdc861 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/TreemapVisualization.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/TreemapVisualization.java
@@ -49,14 +49,11 @@ public class TreemapVisualization {
}
}
- /**
- * @param packageName
- * @return
- */
private static String superpackage(String packageName) {
int i = packageName.lastIndexOf('.');
- if (i == -1)
+ if (i == -1) {
return "";
+ }
String p = packageName.substring(0, i);
return p;
}
@@ -70,37 +67,43 @@ public class TreemapVisualization {
if (buggyPackages.contains(superpackage) || interiorPackages.contains(superpackage) || superpackage.length() == 0) {
goodCodeCount.add(packageName, classes);
goodCodeSize.add(packageName, loc);
- if (superpackage.length() > 0)
+ if (superpackage.length() > 0) {
interiorPackages.add(superpackage);
+ }
- } else
+ } else {
cleanCode(superpackage, loc, classes);
+ }
}
public void generateTreeMap(BugCollection bugCollection) {
- for (PackageStats p : bugCollection.getProjectStats().getPackageStats())
+ for (PackageStats p : bugCollection.getProjectStats().getPackageStats()) {
if (p.getTotalBugs() > 0) {
buggyPackages.add(p.getPackageName());
addInteriorPackages(p.getPackageName());
}
+ }
- for (PackageStats p : bugCollection.getProjectStats().getPackageStats())
+ for (PackageStats p : bugCollection.getProjectStats().getPackageStats()) {
if (p.getTotalBugs() == 0) {
cleanCode(p.getPackageName(), p.size(), p.getClassStats().size());
}
+ }
System.out.println("LOC\tTypes\tH\tHM\tDensity");
System.out.println("INTEGER\tINTEGER\tINTEGER\tINTEGER\tFLOAT");
- for (PackageStats p : bugCollection.getProjectStats().getPackageStats())
+ for (PackageStats p : bugCollection.getProjectStats().getPackageStats()) {
if (p.getTotalBugs() > 0) {
int high = p.getBugsAtPriority(Priorities.HIGH_PRIORITY);
int normal = p.getBugsAtPriority(Priorities.NORMAL_PRIORITY);
System.out.printf("%d\t%d\t%d\t%d\t%g\t\t%s", p.size(), p.getClassStats().size(), high, high + normal,
(high + normal) * 1000.0 / p.size(), p.getPackageName().substring(11).replace('.', '\t'));
- if (isInteriorPackage(p.getPackageName()))
+ if (isInteriorPackage(p.getPackageName())) {
System.out.print("\t*");
+ }
System.out.println();
}
+ }
for (Map.Entry<String, Integer> e : goodCodeSize.entrySet()) {
System.out.printf("%d\t%d\t%d\t%d\t%g\t\t%s%n", e.getValue(), goodCodeCount.getCount(e.getKey()), 0, 0, 0.0, e
.getKey().substring(11).replace('.', '\t'));
@@ -115,10 +118,11 @@ public class TreemapVisualization {
SortedBugCollection bugCollection = new SortedBugCollection();
int argCount = 0;
- if (argCount < args.length)
+ if (argCount < args.length) {
bugCollection.readXML(args[argCount++]);
- else
+ } else {
bugCollection.readXML(System.in);
+ }
new TreemapVisualization().generateTreeMap(bugCollection);
diff --git a/src/java/edu/umd/cs/findbugs/workflow/UnionResults.java b/src/java/edu/umd/cs/findbugs/workflow/UnionResults.java
index d0b8e1e..974c7cc 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/UnionResults.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/UnionResults.java
@@ -57,10 +57,11 @@ public class UnionResults {
*/
@Override
protected void handleOption(String option, String optionExtraPart) throws IOException {
- if (option.equals("-withMessages"))
+ if ("-withMessages".equals(option)) {
withMessages = true;
- else
+ } else {
throw new IllegalArgumentException("Unknown option : " + option);
+ }
}
/*
@@ -72,17 +73,18 @@ public class UnionResults {
*/
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-output"))
+ if ("-output".equals(option)) {
outputFile = argument;
- else
+ } else {
throw new IllegalArgumentException("Unknown option : " + option);
+ }
}
}
static {
DetectorFactoryCollection.instance(); // as a side effect, loads
- // detector plugins
+ // detector plugins
}
static public SortedBugCollection union(SortedBugCollection origCollection, SortedBugCollection newCollection) {
@@ -93,8 +95,9 @@ public class UnionResults {
static public void merge(HashSet<String> hashes, SortedBugCollection into, SortedBugCollection from) {
for (BugInstance bugInstance : from.getCollection()) {
- if (hashes == null || hashes.add(bugInstance.getInstanceHash()))
+ if (hashes == null || hashes.add(bugInstance.getInstanceHash())) {
into.add(bugInstance);
+ }
}
ProjectStats stats = into.getProjectStats();
ProjectStats stats2 = from.getProjectStats();
@@ -104,8 +107,9 @@ public class UnionResults {
Project project2 = from.getProject();
project.add(project2);
- for(AnalysisError error : from.getErrors())
+ for(AnalysisError error : from.getErrors()) {
into.addError(error);
+ }
return;
}
@@ -126,8 +130,9 @@ public class UnionResults {
SortedBugCollection more = new SortedBugCollection();
more.readXML(argv[i]);
- if (results == null)
+ if (results == null) {
results = more.createEmptyCollectionWithMetadata();
+ }
merge(hashes, results, more);
@@ -144,12 +149,12 @@ public class UnionResults {
return;
}
results.setWithMessages(commandLine.withMessages);
- if (commandLine.outputFile == null)
+ if (commandLine.outputFile == null) {
results.writeXML(System.out);
- else
+ } else {
results.writeXML(commandLine.outputFile);
+ }
}
}
-// vim:ts=3
diff --git a/src/java/edu/umd/cs/findbugs/workflow/Update.java b/src/java/edu/umd/cs/findbugs/workflow/Update.java
index 5b4f999..9b02901 100644
--- a/src/java/edu/umd/cs/findbugs/workflow/Update.java
+++ b/src/java/edu/umd/cs/findbugs/workflow/Update.java
@@ -60,9 +60,6 @@ public class Update {
static final int maxResurrection = SystemProperties.getInt("findbugs.maxResurrection", 90);
- /**
- *
- */
private static final String USAGE = "Usage: " + Update.class.getName() + " [options] data1File data2File data3File ... ";
private final Map<BugInstance, BugInstance> mapFromNewToOldBug = new IdentityHashMap<BugInstance, BugInstance>();
@@ -109,55 +106,59 @@ public class Update {
addSwitch("-useAnalysisTimes", "use analysis timestamp rather than code timestamp in history");
addSwitch("-withMessages", "Add bug description");
addOption("-onlyMostRecent", "number", "only use the last # input files");
-
}
@Override
protected void handleOption(String option, String optionExtraPart) throws IOException {
- if (option.equals("-overrideRevisionNames")) {
- if (optionExtraPart.length() == 0)
+ if ("-overrideRevisionNames".equals(option)) {
+ if (optionExtraPart.length() == 0) {
overrideRevisionNames = true;
- else
+ } else {
overrideRevisionNames = Boolean.parseBoolean(optionExtraPart);
- } else if (option.equals("-noPackageMoves")) {
- if (optionExtraPart.length() == 0)
+ }
+ } else if ("-noPackageMoves".equals(option)) {
+ if (optionExtraPart.length() == 0) {
noPackageMoves = true;
- else
+ } else {
noPackageMoves = Boolean.parseBoolean(optionExtraPart);
- } else if (option.equals("-noResurrections")) {
- if (optionExtraPart.length() == 0)
+ }
+ } else if ("-noResurrections".equals(option)) {
+ if (optionExtraPart.length() == 0) {
noResurrections = true;
- else
+ } else {
noResurrections = Boolean.parseBoolean(optionExtraPart);
- } else if (option.equals("-preciseMatch")) {
+ }
+ } else if ("-preciseMatch".equals(option)) {
preciseMatch = true;
- } else if (option.equals("-sloppyMatch")) {
+ } else if ("-sloppyMatch".equals(option)) {
sloppyMatch = true;
- } else if (option.equals("-precisePriorityMatch")) {
+ } else if ("-precisePriorityMatch".equals(option)) {
versionInsensitiveBugComparator.setComparePriorities(true);
fuzzyBugPatternMatcher.setComparePriorities(true);
precisePriorityMatch = true;
- } else if (option.equals("-quiet"))
+ } else if ("-quiet".equals(option)) {
verbose = false;
- else if (option.equals("-useAnalysisTimes"))
+ } else if ("-useAnalysisTimes".equals(option)) {
useAnalysisTimes = true;
- else if (option.equals("-withMessages"))
+ } else if ("-withMessages".equals(option)) {
withMessages = true;
- else
+ } else {
throw new IllegalArgumentException("no option " + option);
+ }
}
@Override
protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-output"))
+ if ("-output".equals(option)) {
outputFilename = argument;
- else if (option.equals("-maxRank")) {
+ } else if ("-maxRank".equals(option)) {
maxRank = Integer.parseInt(argument);
- } else if (option.equals("-onlyMostRecent")) {
+ } else if ("-onlyMostRecent".equals(option)) {
mostRecent = Integer.parseInt(argument);
- } else
+ } else {
throw new IllegalArgumentException("Can't handle option " + option);
+ }
}
@@ -187,8 +188,9 @@ public class Update {
matchBugs(versionInsensitiveBugComparator, baselineCollection, bugCollection);
for (Iterator<BugInstance> i = bugCollection.getCollection().iterator(); i.hasNext();) {
BugInstance bug = i.next();
- if (matchedOldBugs.containsKey(bug))
+ if (matchedOldBugs.containsKey(bug)) {
i.remove();
+ }
}
}
@@ -196,9 +198,11 @@ public class Update {
public BugCollection mergeCollections(BugCollection origCollection, BugCollection newCollection, boolean copyDeadBugs,
boolean incrementalAnalysis) {
- for (BugInstance b : newCollection)
- if (b.isDead())
+ for (BugInstance b : newCollection) {
+ if (b.isDead()) {
throw new IllegalArgumentException("Can't merge bug collections if the newer collection contains dead bugs: " + b);
+ }
+ }
mapFromNewToOldBug.clear();
@@ -228,29 +232,30 @@ public class Update {
long currentSequence = origCollection.getSequenceNumber() + 1;
resultCollection.setSequenceNumber(currentSequence);
- int oldBugs = 0;
+ // int oldBugs = 0;
matchBugs(origCollection, newCollection);
- if (sloppyMatch)
+ if (sloppyMatch) {
matchBugs(new SloppyBugComparator(), origCollection, newCollection);
+ }
- int newlyDeadBugs = 0;
- int persistantBugs = 0;
- int addedBugs = 0;
- int addedInNewCode = 0;
- int deadBugInDeadCode = 0;
+ // int newlyDeadBugs = 0;
+ // int persistantBugs = 0;
+ // int addedBugs = 0;
+ // int addedInNewCode = 0;
+ // int deadBugInDeadCode = 0;
HashSet<String> analyzedSourceFiles = sourceFilesInCollection(newCollection);
// Copy unmatched bugs
- if (copyDeadBugs || incrementalAnalysis)
- for (BugInstance bug : origCollection.getCollection())
- if (!matchedOldBugs.containsKey(bug))
+ if (copyDeadBugs || incrementalAnalysis) {
+ for (BugInstance bug : origCollection.getCollection()) {
+ if (!matchedOldBugs.containsKey(bug)) {
if (bug.isDead()) {
- oldBugs++;
+ // oldBugs++;
BugInstance newBug = (BugInstance) bug.clone();
resultCollection.add(newBug, false);
} else {
- newlyDeadBugs++;
+ // newlyDeadBugs++;
BugInstance newBug = (BugInstance) bug.clone();
@@ -260,21 +265,27 @@ public class Update {
boolean fixed = sourceFile != null && analyzedSourceFiles.contains(sourceFile)
|| newCollection.getProjectStats().getClassStats(className) != null;
if (fixed) {
- if (!copyDeadBugs)
+ if (!copyDeadBugs) {
continue;
+ }
newBug.setRemovedByChangeOfPersistingClass(true);
newBug.setLastVersion(lastSequence);
} else {
- deadBugInDeadCode++;
- if (!incrementalAnalysis)
+ // deadBugInDeadCode++;
+ if (!incrementalAnalysis) {
newBug.setLastVersion(lastSequence);
+ }
}
- if (newBug.isDead() && newBug.getFirstVersion() > newBug.getLastVersion())
+ if (newBug.isDead() && newBug.getFirstVersion() > newBug.getLastVersion()) {
throw new IllegalStateException("Illegal Version range: " + newBug.getFirstVersion() + ".."
+ newBug.getLastVersion());
+ }
resultCollection.add(newBug, false);
}
+ }
+ }
+ }
// Copy matched bugs
for (BugInstance bug : newCollection.getCollection()) {
BugInstance newBug = (BugInstance) bug.clone();
@@ -285,15 +296,17 @@ public class Update {
// handle getAnnotationText()/setAnnotationText() and
// designation key
BugDesignation designation = newBug.getUserDesignation();
- if (designation != null)
+ if (designation != null) {
designation.merge(origWarning.getUserDesignation());
- else
+ }
+ else {
newBug.setUserDesignation(origWarning.getUserDesignation()); // clone??
+ }
- persistantBugs++;
+ // persistantBugs++;
} else {
newBug.setFirstVersion(lastSequence + 1);
- addedBugs++;
+ // addedBugs++;
ClassAnnotation classBugFoundIn = bug.getPrimaryClass();
@@ -303,12 +316,14 @@ public class Update {
// System.out.println("added bug to existing code " +
// newBug.getUniqueId() + " : " + newBug.getAbbrev() + " in
// " + classBugFoundIn);
- } else
- addedInNewCode++;
+ } else {
+ // addedInNewCode++;
+ }
}
- if (newBug.isDead())
+ if (newBug.isDead()) {
throw new IllegalStateException("Illegal Version range: " + newBug.getFirstVersion() + ".."
+ newBug.getLastVersion());
+ }
int oldSize = resultCollection.getCollection().size();
resultCollection.add(newBug, false);
int newSize = resultCollection.getCollection().size();
@@ -316,6 +331,7 @@ public class Update {
System.out.println("Failed to add bug" + newBug.getMessage());
}
}
+ /*
if (false && verbose) {
System.out.println(origCollection.getCollection().size() + " orig bugs, " + newCollection.getCollection().size()
+ " new bugs");
@@ -324,6 +340,7 @@ public class Update {
+ " in new code, " + (addedBugs - addedInNewCode) + " added");
System.out.println(resultCollection.getCollection().size() + " resulting bugs");
}
+ */
return resultCollection;
}
@@ -335,12 +352,15 @@ public class Update {
BugRanker.trimToMaxRank(newCollection, maxRank);
if (sloppyMatch) {
TreeSet<BugInstance> sloppyUnique = new TreeSet<BugInstance>(new SloppyBugComparator());
- for(Iterator<BugInstance> i = newCollection.iterator(); i.hasNext(); )
- if (!sloppyUnique.add(i.next()))
+ for(Iterator<BugInstance> i = newCollection.iterator(); i.hasNext(); ) {
+ if (!sloppyUnique.add(i.next())) {
i.remove();
+ }
+ }
}
}
+ /*
private static int size(BugCollection b) {
int count = 0;
for (Iterator<BugInstance> i = b.iterator(); i.hasNext();) {
@@ -349,11 +369,8 @@ public class Update {
}
return count;
}
-
- /**
- * @param origCollection
- * @param newCollection
*/
+
private void matchBugs(BugCollection origCollection, BugCollection newCollection) {
matchBugs(SortedBugCollection.BugInstanceComparator.instance, origCollection, newCollection);
@@ -362,11 +379,13 @@ public class Update {
matchBugs(versionInsensitiveBugComparator, origCollection, newCollection);
matchBugs(versionInsensitiveBugComparator, origCollection, newCollection, MatchOldBugs.IF_CLASS_NOT_SEEN_UNTIL_NOW);
- if (doMatchFixedBugs)
+ if (doMatchFixedBugs) {
matchBugs(versionInsensitiveBugComparator, origCollection, newCollection, MatchOldBugs.ALWAYS);
+ }
- if (!preciseMatch)
+ if (!preciseMatch) {
matchBugs(fuzzyBugPatternMatcher, origCollection, newCollection);
+ }
if (!noPackageMoves) {
VersionInsensitiveBugComparator movedBugComparator = new VersionInsensitiveBugComparator();
@@ -380,8 +399,11 @@ public class Update {
matchBugs(movedBugComparator, origCollection, newCollection);
}
}
- if (false)
+ /*
+ if (false) {
System.out.println("Matched old bugs: " + matchedOldBugs.size());
+ }
+ */
}
}
@@ -404,8 +426,9 @@ public class Update {
UpdateCommandLine commandLine = new UpdateCommandLine();
int argCount = commandLine.parse(args, 1, Integer.MAX_VALUE, USAGE);
- if (commandLine.outputFilename == null)
+ if (commandLine.outputFilename == null) {
verbose = false;
+ }
if (mostRecent > 0) {
argCount = Math.max(argCount, args.length - mostRecent);
}
@@ -417,20 +440,23 @@ public class Update {
commonPrefix = Math.min(commonPrefix, lengthCommonPrefix(firstPathParts, getFilePathParts(args[i])));
}
- String origFilename = args[argCount++];
+ String origFilename = args[argCount++];
BugCollection origCollection;
origCollection = new SortedBugCollection();
- if (verbose)
+ if (verbose) {
System.out.println("Starting with " + origFilename);
+ }
- while (true)
+ while (true) {
try {
while (true) {
File f = new File(origFilename);
- if (f.length() > 0)
+ if (f.length() > 0) {
break;
- if (verbose)
+ }
+ if (verbose) {
System.out.println("Empty input file: " + f);
+ }
origFilename = args[argCount++];
}
origCollection.readXML(origFilename);
@@ -442,6 +468,7 @@ public class Update {
}
origFilename = args[argCount++];
}
+ }
if (commandLine.overrideRevisionNames || origCollection.getReleaseName() == null
|| origCollection.getReleaseName().length() == 0) {
@@ -458,13 +485,16 @@ public class Update {
}
origCollection.setReleaseName(firstPathParts[commonPrefix]);
- if (useAnalysisTimes)
+ if (useAnalysisTimes) {
origCollection.setTimestamp(origCollection.getAnalysisTimestamp());
+ }
}
- for (BugInstance bug : origCollection.getCollection())
- if (bug.getLastVersion() >= 0 && bug.getFirstVersion() > bug.getLastVersion())
+ for (BugInstance bug : origCollection.getCollection()) {
+ if (bug.getLastVersion() >= 0 && bug.getFirstVersion() > bug.getLastVersion()) {
throw new IllegalStateException("Illegal Version range: " + bug.getFirstVersion() + ".." + bug.getLastVersion());
+ }
+ }
discardUnwantedBugs(origCollection);
@@ -473,60 +503,73 @@ public class Update {
BugCollection newCollection = new SortedBugCollection();
String newFilename = args[argCount++];
- if (verbose)
+ if (verbose) {
System.out.println("Merging " + newFilename);
+ }
try {
File f = new File(newFilename);
if (f.length() == 0) {
- if (verbose)
+ if (verbose) {
System.out.println("Empty input file: " + f);
+ }
continue;
}
newCollection.readXML(newFilename);
if (commandLine.overrideRevisionNames || newCollection.getReleaseName() == null
- || newCollection.getReleaseName().length() == 0)
+ || newCollection.getReleaseName().length() == 0) {
newCollection.setReleaseName(getFilePathParts(newFilename)[commonPrefix]);
- if (useAnalysisTimes)
+ }
+ if (useAnalysisTimes) {
newCollection.setTimestamp(newCollection.getAnalysisTimestamp());
+ }
discardUnwantedBugs(newCollection);
origCollection = mergeCollections(origCollection, newCollection, true, false);
} catch (IOException e) {
IOException e2 = new IOException("Error parsing " + newFilename);
e2.initCause(e);
- if (verbose)
+ if (verbose) {
e2.printStackTrace();
+ }
throw e2;
} catch (DocumentException e) {
DocumentException e2 = new DocumentException("Error parsing " + newFilename);
e2.initCause(e);
- if (verbose)
+ if (verbose) {
e2.printStackTrace();
+ }
throw e2;
}
}
-
- if (false)
+ /*
+ if (false) {
for (Iterator<BugInstance> i = origCollection.iterator(); i.hasNext();) {
- if (!resurrected.contains(i.next().getInstanceKey()))
+ if (!resurrected.contains(i.next().getInstanceKey())) {
i.remove();
+ }
}
+ }
+ */
origCollection.setWithMessages(commandLine.withMessages);
if (commandLine.outputFilename != null) {
- if (verbose)
+ if (verbose) {
System.out.println("Writing " + commandLine.outputFilename);
+ }
origCollection.writeXML(commandLine.outputFilename);
- } else
+ } else {
origCollection.writeXML(System.out);
+ }
}
private static int lengthCommonPrefix(String[] string, String[] string2) {
int maxLength = Math.min(string.length, string2.length);
- for (int result = 0; result < maxLength; result++)
- if (!string[result].equals(string2[result]))
+ for (int result = 0; result < maxLength; result++) {
+ if (!string[result].equals(string2[result])) {
return result;
+ }
+ }
return maxLength;
}
@@ -563,13 +606,13 @@ public class Update {
TreeMap<BugInstance, LinkedList<BugInstance>> set = new TreeMap<BugInstance, LinkedList<BugInstance>>(
bugInstanceComparator);
- int oldBugs = 0;
- int newBugs = 0;
- int matchedBugs = 0;
- for (BugInstance bug : origCollection.getCollection())
+ // int oldBugs = 0;
+ // int newBugs = 0;
+ // int matchedBugs = 0;
+ for (BugInstance bug : origCollection.getCollection()) {
if (!matchedOldBugs.containsKey(bug)) {
if (matchOld.match(bug)) {
- oldBugs++;
+ // oldBugs++;
LinkedList<BugInstance> q = set.get(bug);
if (q == null) {
q = new LinkedList<BugInstance>();
@@ -579,20 +622,23 @@ public class Update {
}
}
+ }
long newVersion = origCollection.getCurrentAppVersion().getSequenceNumber() + 1;
- for (BugInstance bug : newCollection.getCollection())
+ for (BugInstance bug : newCollection.getCollection()) {
if (!mapFromNewToOldBug.containsKey(bug)) {
- newBugs++;
+ // newBugs++;
LinkedList<BugInstance> q = set.get(bug);
- if (q == null)
+ if (q == null) {
continue;
+ }
for (Iterator<BugInstance> i = q.iterator(); i.hasNext();) {
BugInstance matchedBug = i.next();
if (matchedBug.isDead()) {
if (noResurrections || matchedBug.isRemovedByChangeOfPersistingClass()
- && newVersion - matchedBug.getLastVersion() > maxResurrection)
+ && newVersion - matchedBug.getLastVersion() > maxResurrection) {
continue;
+ }
resurrected.add(bug.getInstanceKey());
// System.out.println("in version " +
// newCollection.getReleaseName());
@@ -600,15 +646,17 @@ public class Update {
// bug.getMessageWithoutPrefix());
}
- matchedBugs++;
+ // matchedBugs++;
mapFromNewToOldBug.put(bug, matchedBug);
matchedOldBugs.put(matchedBug, null);
i.remove();
- if (q.isEmpty())
+ if (q.isEmpty()) {
set.remove(bug);
+ }
break;
}
}
+ }
}
}
diff --git a/src/java/edu/umd/cs/findbugs/xml/Dom4JXMLOutput.java b/src/java/edu/umd/cs/findbugs/xml/Dom4JXMLOutput.java
index 9343416..d3e5fea 100644
--- a/src/java/edu/umd/cs/findbugs/xml/Dom4JXMLOutput.java
+++ b/src/java/edu/umd/cs/findbugs/xml/Dom4JXMLOutput.java
@@ -28,16 +28,16 @@ import org.dom4j.Element;
/**
* XMLOutput class to build all or part of a dom4j tree.
- *
+ *
* @see XMLOutput
* @author David Hovemeyer
*/
public class Dom4JXMLOutput implements XMLOutput {
- private LinkedList<Branch> stack;
+ private final LinkedList<Branch> stack;
/**
* Constructor.
- *
+ *
* @param topLevel
* the Document or Element that is the root of the tree to be
* built
@@ -47,15 +47,18 @@ public class Dom4JXMLOutput implements XMLOutput {
stack.addLast(topLevel);
}
+ @Override
public void beginDocument() {
}
+ @Override
public void openTag(String tagName) {
Branch top = stack.getLast();
Element element = top.addElement(tagName);
stack.addLast(element);
}
+ @Override
public void openTag(String tagName, XMLAttributeList attributeList) {
Branch top = stack.getLast();
Element element = top.addElement(tagName);
@@ -67,42 +70,50 @@ public class Dom4JXMLOutput implements XMLOutput {
}
}
+ @Override
public void openCloseTag(String tagName) {
openTag(tagName);
closeTag(tagName);
}
+ @Override
public void openCloseTag(String tagName, XMLAttributeList attributeList) {
openTag(tagName, attributeList);
closeTag(tagName);
}
+ @Override
public void startTag(String tagName) {
Branch top = stack.getLast();
Element element = top.addElement(tagName);
stack.addLast(element);
}
+ @Override
public void addAttribute(String name, String value) {
Element element = (Element) stack.getLast();
element.addAttribute(name, value);
}
+ @Override
public void stopTag(boolean close) {
if (close) {
closeTag(null);
}
}
+ @Override
public void closeTag(String tagName) {
stack.removeLast();
}
+ @Override
public void writeText(String text) {
Element top = (Element) stack.getLast();
top.addText(text);
}
+ @Override
public void writeCDATA(String cdata) {
Element top = (Element) stack.getLast();
top.addCDATA(cdata);
@@ -111,7 +122,7 @@ public class Dom4JXMLOutput implements XMLOutput {
/**
* Add a list of Strings to document as elements with given tag name to the
* tree.
- *
+ *
* @param tagName
* the tag name
* @param listValues
@@ -127,7 +138,7 @@ public class Dom4JXMLOutput implements XMLOutput {
/**
* Add given object to the tree.
- *
+ *
* @param obj
* the object
*/
@@ -141,7 +152,7 @@ public class Dom4JXMLOutput implements XMLOutput {
/**
* Add a Collection of XMLWriteable objects to the tree.
- *
+ *
* @param collection
* Collection of XMLWriteable objects
*/
@@ -151,8 +162,8 @@ public class Dom4JXMLOutput implements XMLOutput {
}
}
+ @Override
public void finish() {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/xml/MetaCharacterMap.java b/src/java/edu/umd/cs/findbugs/xml/MetaCharacterMap.java
index b04f1f9..e3e8b51 100644
--- a/src/java/edu/umd/cs/findbugs/xml/MetaCharacterMap.java
+++ b/src/java/edu/umd/cs/findbugs/xml/MetaCharacterMap.java
@@ -25,14 +25,14 @@ import java.util.Map;
/**
* Map of metacharacters that need to be escaped, and what to replace them with.
- *
+ *
* @see QuoteMetaCharacters
* @author David Hovemeyer
*/
public class MetaCharacterMap {
- private BitSet metaCharacterSet;
+ private final BitSet metaCharacterSet;
- private Map<String, String> replacementMap;
+ private final Map<String, String> replacementMap;
/**
* Constructor. Creates an empty object.
@@ -44,7 +44,7 @@ public class MetaCharacterMap {
/**
* Add a metacharacter and its replacement.
- *
+ *
* @param meta
* the metacharacter
* @param replacement
@@ -64,7 +64,7 @@ public class MetaCharacterMap {
/**
* Get the replacement for a metacharacter.
- *
+ *
* @param c
* a String containing the metacharacter
*/
@@ -73,4 +73,3 @@ public class MetaCharacterMap {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/xml/OutputStreamXMLOutput.java b/src/java/edu/umd/cs/findbugs/xml/OutputStreamXMLOutput.java
index 9a83451..e846cbb 100644
--- a/src/java/edu/umd/cs/findbugs/xml/OutputStreamXMLOutput.java
+++ b/src/java/edu/umd/cs/findbugs/xml/OutputStreamXMLOutput.java
@@ -28,6 +28,7 @@ import java.nio.charset.Charset;
import javax.annotation.WillCloseWhenClosed;
import edu.umd.cs.findbugs.annotations.DischargesObligation;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import edu.umd.cs.findbugs.util.Strings;
/**
@@ -39,18 +40,19 @@ public class OutputStreamXMLOutput implements XMLOutput {
private static final String OPENING = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
private static String getStylesheetCode(String stylesheet) {
- if (stylesheet == null)
+ if (stylesheet == null) {
return "";
+ }
return "<?xml-stylesheet type=\"text/xsl\" href=\"" + stylesheet + "\"?>\n";
}
- private Writer out;
+ private final Writer out;
private int nestingLevel;
private boolean newLine;
- private String stylesheet;
+ private final String stylesheet;
/**
* Constructor.
@@ -58,15 +60,17 @@ public class OutputStreamXMLOutput implements XMLOutput {
* @param os
* OutputStream to write XML output to
*/
+ @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION")
public OutputStreamXMLOutput(@WillCloseWhenClosed OutputStream os) {
this(os, null);
}
/**
* Constructor.
*
- * @param os
- * OutputStream to write XML output to
+ * @param writer
+ * Writer to write XML output to
*/
+ @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION")
public OutputStreamXMLOutput(@WillCloseWhenClosed Writer writer) {
this(writer, null);
}
@@ -86,17 +90,18 @@ public class OutputStreamXMLOutput implements XMLOutput {
}
/*
- * @param os
- * Writer to write XML output to
- * @param stylesheet
- * name of stylesheet
- */
- public OutputStreamXMLOutput(@WillCloseWhenClosed Writer writer, String stylesheet) {
- this.out = writer;
- this.nestingLevel = 0;
- this.newLine = true;
- this.stylesheet = stylesheet;
- }
+ * @param os
+ * Writer to write XML output to
+ * @param stylesheet
+ * name of stylesheet
+ */
+ public OutputStreamXMLOutput(@WillCloseWhenClosed Writer writer, String stylesheet) {
+ this.out = writer;
+ this.nestingLevel = 0;
+ this.newLine = true;
+ this.stylesheet = stylesheet;
+ }
+ @Override
public void beginDocument() throws IOException {
out.write(OPENING);
out.write(getStylesheetCode(stylesheet));
@@ -104,28 +109,34 @@ public class OutputStreamXMLOutput implements XMLOutput {
newLine = true;
}
+ @Override
public void openTag(String tagName) throws IOException {
emitTag(tagName, false);
}
+ @Override
public void openTag(String tagName, XMLAttributeList attributeList) throws IOException {
emitTag(tagName, attributeList.toString(), false);
}
+ @Override
public void openCloseTag(String tagName) throws IOException {
emitTag(tagName, true);
}
+ @Override
public void openCloseTag(String tagName, XMLAttributeList attributeList) throws IOException {
emitTag(tagName, attributeList.toString(), true);
}
+ @Override
public void startTag(String tagName) throws IOException {
indent();
++nestingLevel;
out.write("<" + tagName);
}
+ @Override
public void addAttribute(String name, String value) throws IOException {
out.write(' ');
out.write(name);
@@ -135,6 +146,7 @@ public class OutputStreamXMLOutput implements XMLOutput {
out.write('"');
}
+ @Override
public void stopTag(boolean close) throws IOException {
if (close) {
out.write("/>\n");
@@ -161,18 +173,22 @@ public class OutputStreamXMLOutput implements XMLOutput {
stopTag(close);
}
+ @Override
public void closeTag(String tagName) throws IOException {
--nestingLevel;
- if (newLine)
+ if (newLine) {
indent();
+ }
out.write("</" + tagName + ">\n");
newLine = true;
}
+ @Override
public void writeText(String text) throws IOException {
out.write(Strings.escapeXml(text));
}
+ @Override
public void writeCDATA(String cdata) throws IOException {
// FIXME: We just trust fate that the characters being written
// don't contain the string "]]>"
@@ -186,18 +202,19 @@ public class OutputStreamXMLOutput implements XMLOutput {
public void flush() throws IOException {
out.flush();
}
+ @Override
@DischargesObligation
public void finish() throws IOException {
out.close();
}
private void indent() throws IOException {
- if (!newLine)
+ if (!newLine) {
out.write("\n");
+ }
for (int i = 0; i < nestingLevel; ++i) {
out.write(" ");
}
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/xml/QuoteMetaCharacters.java b/src/java/edu/umd/cs/findbugs/xml/QuoteMetaCharacters.java
index e6b70d2..5a5a64c 100644
--- a/src/java/edu/umd/cs/findbugs/xml/QuoteMetaCharacters.java
+++ b/src/java/edu/umd/cs/findbugs/xml/QuoteMetaCharacters.java
@@ -26,28 +26,30 @@ import javax.annotation.Nonnull;
/**
* Quote metacharacters in a String.
- *
+ *
* @see MetaCharacterMap
* @author David Hovemeyer
*/
public abstract class QuoteMetaCharacters {
- private String text;
+ private final String text;
- private MetaCharacterMap map;
+ private final MetaCharacterMap map;
/**
* Constructor.
- *
+ *
* @param text
* the text in which we want to quote metacharacters
* @param map
* the MetaCharacterMap
*/
public QuoteMetaCharacters(@Nonnull String text, @Nonnull MetaCharacterMap map) {
- if (text == null)
+ if (text == null) {
throw new NullPointerException("text must be nonnull");
- if (map == null)
+ }
+ if (map == null) {
throw new NullPointerException("map must be nonnull");
+ }
this.text = text;
this.map = map;
}
@@ -73,7 +75,7 @@ public abstract class QuoteMetaCharacters {
/**
* Downcall method to emit literal text, in which any occurrences of the
* metacharacters are quoted.
- *
+ *
* @param s
* the literal text to emit
*/
@@ -82,11 +84,11 @@ public abstract class QuoteMetaCharacters {
private int findNextMeta(String s, int start) {
for (int i = start; i < s.length(); ++i) {
char c = s.charAt(i);
- if (map.isMeta(c))
+ if (map.isMeta(c)) {
return i;
+ }
}
return -1;
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/xml/XMLAttributeList.java b/src/java/edu/umd/cs/findbugs/xml/XMLAttributeList.java
index 2f53a48..ecbbfdb 100644
--- a/src/java/edu/umd/cs/findbugs/xml/XMLAttributeList.java
+++ b/src/java/edu/umd/cs/findbugs/xml/XMLAttributeList.java
@@ -30,14 +30,14 @@ import edu.umd.cs.findbugs.util.Strings;
/**
* Helper class to format attributes in an XML tag.
- *
+ *
* @author David Hovemeyer
*/
public class XMLAttributeList {
public static class NameValuePair {
- private String name;
+ private final String name;
- private String value;
+ private final String value;
public NameValuePair(String name, String value) {
this.name = name;
@@ -54,7 +54,7 @@ public class XMLAttributeList {
}
// Fields
- private List<NameValuePair> nameValuePairList;
+ private final List<NameValuePair> nameValuePairList;
/**
* Constructor. Creates an empty object.
@@ -65,7 +65,7 @@ public class XMLAttributeList {
/**
* Add a single attribute name and value.
- *
+ *
* @param name
* the attribute name
* @param value
@@ -73,17 +73,19 @@ public class XMLAttributeList {
* @return this object (so calls to addAttribute() can be chained)
*/
public XMLAttributeList addAttribute(@Nonnull String name, @Nonnull String value) {
- if (name == null)
+ if (name == null) {
throw new NullPointerException("name must be nonnull");
- if (value == null)
+ }
+ if (value == null) {
throw new NullPointerException("value must be nonnull");
+ }
nameValuePairList.add(new NameValuePair(name, value));
return this;
}
/**
* Add a single attribute name and value.
- *
+ *
* @param name
* the attribute name
* @param value
@@ -91,8 +93,9 @@ public class XMLAttributeList {
* @return this object (so calls to addAttribute() can be chained)
*/
public XMLAttributeList addOptionalAttribute(@Nonnull String name, @CheckForNull String value) {
- if (value == null)
+ if (value == null) {
return this;
+ }
return addAttribute(name, value);
}
@@ -123,7 +126,7 @@ public class XMLAttributeList {
/**
* Return a properly quoted form for an attribute value.
- *
+ *
* @param rawValue
* the raw value of the attribute
* @return a properly quoted representation of the value
@@ -133,4 +136,3 @@ public class XMLAttributeList {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/xml/XMLOutput.java b/src/java/edu/umd/cs/findbugs/xml/XMLOutput.java
index 1efc1a0..7cae1cf 100644
--- a/src/java/edu/umd/cs/findbugs/xml/XMLOutput.java
+++ b/src/java/edu/umd/cs/findbugs/xml/XMLOutput.java
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.annotations.DischargesObligation;
/**
* Interface to generate an XML document in some form. E.g., writing it to a
* stream, generating SAX events, etc.
- *
+ *
* @author David Hovemeyer
*/
@CleanupObligation
@@ -39,7 +39,7 @@ public interface XMLOutput {
/**
* Open a tag with given name.
- *
+ *
* @param tagName
* the tag name
*/
@@ -47,7 +47,7 @@ public interface XMLOutput {
/**
* Open a tag with given name and given attributes.
- *
+ *
* @param tagName
* the tag name
* @param attributeList
@@ -58,7 +58,7 @@ public interface XMLOutput {
/**
* Start a tag, with the intention of adding attributes. Must be followed by
* stopTag after zero or more addAttribute calls.
- *
+ *
* @param tagName
* the tag name
*/
@@ -66,7 +66,7 @@ public interface XMLOutput {
/**
* Add an attribute to a started tag. Must follow a call to startTag.
- *
+ *
* @param name
* the attribute name.
* @param value
@@ -76,7 +76,7 @@ public interface XMLOutput {
/**
* End a started tag. Must follow a call to startTag.
- *
+ *
* @param close
* true if the element has no content.
*/
@@ -84,7 +84,7 @@ public interface XMLOutput {
/**
* Open and close tag with given name.
- *
+ *
* @param tagName
* the tag name
*/
@@ -92,7 +92,7 @@ public interface XMLOutput {
/**
* Open and close tag with given name and given attributes.
- *
+ *
* @param tagName
* the tag name
* @param attributeList
@@ -102,7 +102,7 @@ public interface XMLOutput {
/**
* Close tag with given name.
- *
+ *
* @param tagName
* the tag name
*/
@@ -111,7 +111,7 @@ public interface XMLOutput {
/**
* Write text to the XML document. XML metacharacters are automatically
* escaped.
- *
+ *
* @param text
* the text to write
*/
@@ -120,7 +120,7 @@ public interface XMLOutput {
/**
* Write a CDATA section to the XML document. The characters are not escaped
* in any way.
- *
+ *
* @param cdata
* the character data to write
*/
@@ -136,4 +136,3 @@ public interface XMLOutput {
public void finish() throws IOException;
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/xml/XMLOutputUtil.java b/src/java/edu/umd/cs/findbugs/xml/XMLOutputUtil.java
index 224d6c3..fdf961e 100644
--- a/src/java/edu/umd/cs/findbugs/xml/XMLOutputUtil.java
+++ b/src/java/edu/umd/cs/findbugs/xml/XMLOutputUtil.java
@@ -26,14 +26,14 @@ import java.util.Iterator;
/**
* Utility routines for writing to XMLOutput.
- *
+ *
* @see XMLOutput
* @author David Hovemeyer
*/
public abstract class XMLOutputUtil {
/**
* Write a list of Strings to document as elements with given tag name.
- *
+ *
* @param xmlOutput
* the XMLOutput object to write to
* @param tagName
@@ -47,7 +47,7 @@ public abstract class XMLOutputUtil {
/**
* Write a list of Strings to document as elements with given tag name.
- *
+ *
* @param xmlOutput
* the XMLOutput object to write to
* @param tagName
@@ -66,7 +66,7 @@ public abstract class XMLOutputUtil {
/**
* Write a list of Strings to document as elements with given tag name.
- *
+ *
* @param xmlOutput
* the XMLOutput object to write to
* @param tagName
@@ -75,13 +75,14 @@ public abstract class XMLOutputUtil {
* Collection of String values to write
*/
public static void writeFileList(XMLOutput xmlOutput, String tagName, Iterable<File> listValues) throws IOException {
- if (listValues != null)
+ if (listValues != null) {
writeFileList(xmlOutput, tagName, listValues.iterator());
+ }
}
/**
* Write a list of Strings to document as elements with given tag name.
- *
+ *
* @param xmlOutput
* the XMLOutput object to write to
* @param tagName
@@ -99,7 +100,7 @@ public abstract class XMLOutputUtil {
/**
* Write a Collection of XMLWriteable objects.
- *
+ *
* @param xmlOutput
* the XMLOutput object to write to
* @param collection
@@ -112,4 +113,3 @@ public abstract class XMLOutputUtil {
}
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/xml/XMLUtil.java b/src/java/edu/umd/cs/findbugs/xml/XMLUtil.java
index c484dfd..0fa40f9 100644
--- a/src/java/edu/umd/cs/findbugs/xml/XMLUtil.java
+++ b/src/java/edu/umd/cs/findbugs/xml/XMLUtil.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -28,11 +28,6 @@ import org.dom4j.Node;
*/
public class XMLUtil {
- /**
- * @param node
- * @param arg0
- * @return
- */
@SuppressWarnings("unchecked")
public static <T> List<T> selectNodes(Node node, String arg0) {
return node.selectNodes(arg0);
diff --git a/src/java/edu/umd/cs/findbugs/xml/XMLWriteable.java b/src/java/edu/umd/cs/findbugs/xml/XMLWriteable.java
index 6ac09cb..681a7a2 100644
--- a/src/java/edu/umd/cs/findbugs/xml/XMLWriteable.java
+++ b/src/java/edu/umd/cs/findbugs/xml/XMLWriteable.java
@@ -23,18 +23,17 @@ import java.io.IOException;
/**
* Interface indicating that an object can write itself to an XML document.
- *
+ *
* @see XMLOutput
* @author David Hovemeyer
*/
public interface XMLWriteable {
/**
* Write this object to given XMLOutput.
- *
+ *
* @param xmlOutput
* the XMLOutput for the document
*/
public void writeXML(XMLOutput xmlOutput) throws IOException;
}
-// vim:ts=4
diff --git a/src/java/edu/umd/cs/findbugs/xml/XPathFind.java b/src/java/edu/umd/cs/findbugs/xml/XPathFind.java
index 121883a..2c077ba 100644
--- a/src/java/edu/umd/cs/findbugs/xml/XPathFind.java
+++ b/src/java/edu/umd/cs/findbugs/xml/XPathFind.java
@@ -32,17 +32,17 @@ import org.dom4j.io.SAXReader;
/**
* Find nodes in a dom4j tree that match a particular XPath expression. The
* main() driver prints out information about matching nodes in an XML document.
- *
+ *
* <p>
* For example, to find the list of non-disabled detectors in a FindBugs plugin
* descriptor, you can use the expression <blockquote>
* <code>/FindbugsPlugin/Detector[boolean(@disabled)=false()]/@class</code>
* </blockquote>
- *
+ *
* @author David Hovemeyer
*/
public abstract class XPathFind {
- private Document document;
+ private final Document document;
public XPathFind(Document document) {
this.document = document;
@@ -94,4 +94,3 @@ public abstract class XPathFind {
}
}
-// vim:ts=4
diff --git a/src/junit/edu/umd/cs/findbugs/BugInstanceTest.java b/src/junit/edu/umd/cs/findbugs/BugInstanceTest.java
index 4e27dbb..57c0347 100644
--- a/src/junit/edu/umd/cs/findbugs/BugInstanceTest.java
+++ b/src/junit/edu/umd/cs/findbugs/BugInstanceTest.java
@@ -96,7 +96,7 @@ public class BugInstanceTest extends TestCase {
SortedBugCollection bc = new SortedBugCollection();
bc.setWithMessages(false);
-
+
String output = writeXML(inst, bc);
System.err.println(output);
@@ -155,8 +155,9 @@ public class BugInstanceTest extends TestCase {
}
private void checkPropertyIterator(Iterator<BugProperty> iter, String[] names, String[] values) {
- if (names.length != values.length)
+ if (names.length != values.length) {
throw new IllegalArgumentException();
+ }
for (int i = 0; i < names.length; ++i) {
Assert.assertTrue(iter.hasNext());
String name = names[i];
@@ -174,8 +175,9 @@ public class BugInstanceTest extends TestCase {
private void removeThroughIterator(Iterator<BugProperty> iter, String name) {
while (iter.hasNext()) {
BugProperty prop = iter.next();
- if (prop.getName().equals(name))
+ if (prop.getName().equals(name)) {
iter.remove();
+ }
}
}
}
diff --git a/src/junit/edu/umd/cs/findbugs/ClassScreenerTest.java b/src/junit/edu/umd/cs/findbugs/ClassScreenerTest.java
index 082b6a9..801e358 100644
--- a/src/junit/edu/umd/cs/findbugs/ClassScreenerTest.java
+++ b/src/junit/edu/umd/cs/findbugs/ClassScreenerTest.java
@@ -112,4 +112,3 @@ public class ClassScreenerTest extends TestCase {
}
}
-// vim:ts=4
diff --git a/src/junit/edu/umd/cs/findbugs/DetectorsTest.java b/src/junit/edu/umd/cs/findbugs/DetectorsTest.java
index ed822a0..2f74d72 100644
--- a/src/junit/edu/umd/cs/findbugs/DetectorsTest.java
+++ b/src/junit/edu/umd/cs/findbugs/DetectorsTest.java
@@ -27,6 +27,7 @@ import java.util.List;
import org.junit.After;
import org.junit.Assert;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
@@ -58,22 +59,28 @@ public class DetectorsTest {
private File findbugsTestCases;
- public File getFindbugsTestCases() throws IOException {
- if (findbugsTestCases != null)
+ /** detectors which are disabled by default but which must be used in test */
+ private final String[] enabledDetectors = {"CheckExpectedWarnings","InefficientMemberAccess","EmptyZipFileEntry"};
+
+ public File getFindbugsTestCases() {
+ if (findbugsTestCases != null) {
return findbugsTestCases;
- File f = new File(SystemProperties.getProperty("findbugsTestCases.home", "../findbugsTestCases"));
- if (f.exists() && f.isDirectory() && f.canRead()) {
- findbugsTestCases = f;
- return f;
}
- throw new IOException("FindBugs test cases not available at " + f.getCanonicalPath());
+ File f = new File(SystemProperties.getProperty("findbugsTestCases.home", "../findbugsTestCases"));
+ Assume.assumeTrue(f.exists());
+ Assume.assumeTrue(f.isDirectory());
+ Assume.assumeTrue(f.canRead());
+
+ findbugsTestCases = f;
+ return f;
}
- public File getFindbugsTestCasesFile(String path) throws IOException {
+ public File getFindbugsTestCasesFile(String path) {
File f = new File(getFindbugsTestCases(), path);
- if (f.exists() && f.canRead())
- return f;
- throw new IOException("FindBugs test cases file " + path + " not available at " + f.getCanonicalPath());
+ Assume.assumeTrue(f.exists());
+ Assume.assumeTrue(f.canRead());
+
+ return f;
}
@Before
@@ -126,8 +133,9 @@ public class DetectorsTest {
}
}
- if (!unexpectedBugs.isEmpty())
+ if (!unexpectedBugs.isEmpty()) {
Assert.fail("Unexpected bugs (" + unexpectedBugs.size() + "):" + getBugsLocations(unexpectedBugs));
+ }
}
/**
@@ -186,8 +194,10 @@ public class DetectorsTest {
engine.setBugReporter(this.bugReporter);
UserPreferences preferences = UserPreferences.createDefaultUserPreferences();
- DetectorFactory checkExpectedWarnings = detectorFactoryCollection.getFactory("CheckExpectedWarnings");
- preferences.enableDetector(checkExpectedWarnings, true);
+ for (String factory : enabledDetectors) {
+ DetectorFactory detFactory = detectorFactoryCollection.getFactory(factory);
+ preferences.enableDetector(detFactory, true);
+ }
preferences.getFilterSettings().clearAllCategories();
this.engine.setUserPreferences(preferences);
@@ -201,12 +211,12 @@ public class DetectorsTest {
project.addAuxClasspathEntry("lib/junit.jar");
File lib = getFindbugsTestCasesFile("lib");
- for(File f : lib.listFiles()) {
- String path = f.getPath();
- if (f.canRead() && path.endsWith(".jar")) {
+ for(File f : lib.listFiles()) {
+ String path = f.getPath();
+ if (f.canRead() && path.endsWith(".jar")) {
project.addAuxClasspathEntry(path);
}
- }
+ }
}
}
diff --git a/src/junit/edu/umd/cs/findbugs/FindBugsTestCase.java b/src/junit/edu/umd/cs/findbugs/FindBugsTestCase.java
index 685a119..ca22d2c 100644
--- a/src/junit/edu/umd/cs/findbugs/FindBugsTestCase.java
+++ b/src/junit/edu/umd/cs/findbugs/FindBugsTestCase.java
@@ -42,26 +42,26 @@ public abstract class FindBugsTestCase extends TestCase {
* Data of an empty class in the default package called "Empty".
*/
public static final byte[] EMPTY_CLASS_DATA = { (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x32, (byte) 0x00, (byte) 0x0d, (byte) 0x0a, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x0a,
- (byte) 0x07, (byte) 0x00, (byte) 0x0b, (byte) 0x07, (byte) 0x00, (byte) 0x0c, (byte) 0x01, (byte) 0x00, (byte) 0x06,
- (byte) 0x3c, (byte) 0x69, (byte) 0x6e, (byte) 0x69, (byte) 0x74, (byte) 0x3e, (byte) 0x01, (byte) 0x00, (byte) 0x03,
- (byte) 0x28, (byte) 0x29, (byte) 0x56, (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x43, (byte) 0x6f, (byte) 0x64,
- (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x0f, (byte) 0x4c, (byte) 0x69, (byte) 0x6e, (byte) 0x65, (byte) 0x4e,
- (byte) 0x75, (byte) 0x6d, (byte) 0x62, (byte) 0x65, (byte) 0x72, (byte) 0x54, (byte) 0x61, (byte) 0x62, (byte) 0x6c,
- (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x75, (byte) 0x72, (byte) 0x63,
- (byte) 0x65, (byte) 0x46, (byte) 0x69, (byte) 0x6c, (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x0a, (byte) 0x45,
- (byte) 0x6d, (byte) 0x70, (byte) 0x74, (byte) 0x79, (byte) 0x2e, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61,
- (byte) 0x0c, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x05, (byte) 0x01, (byte) 0x00, (byte) 0x05, (byte) 0x45,
- (byte) 0x6d, (byte) 0x70, (byte) 0x74, (byte) 0x79, (byte) 0x01, (byte) 0x00, (byte) 0x10, (byte) 0x6a, (byte) 0x61,
- (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x4f,
- (byte) 0x62, (byte) 0x6a, (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x00, (byte) 0x21, (byte) 0x00, (byte) 0x02,
- (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00,
- (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x06,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1d, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x05, (byte) 0x2a, (byte) 0xb7, (byte) 0x00, (byte) 0x01, (byte) 0xb1, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00,
- (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x09, };
+ (byte) 0x00, (byte) 0x32, (byte) 0x00, (byte) 0x0d, (byte) 0x0a, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x0a,
+ (byte) 0x07, (byte) 0x00, (byte) 0x0b, (byte) 0x07, (byte) 0x00, (byte) 0x0c, (byte) 0x01, (byte) 0x00, (byte) 0x06,
+ (byte) 0x3c, (byte) 0x69, (byte) 0x6e, (byte) 0x69, (byte) 0x74, (byte) 0x3e, (byte) 0x01, (byte) 0x00, (byte) 0x03,
+ (byte) 0x28, (byte) 0x29, (byte) 0x56, (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x43, (byte) 0x6f, (byte) 0x64,
+ (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x0f, (byte) 0x4c, (byte) 0x69, (byte) 0x6e, (byte) 0x65, (byte) 0x4e,
+ (byte) 0x75, (byte) 0x6d, (byte) 0x62, (byte) 0x65, (byte) 0x72, (byte) 0x54, (byte) 0x61, (byte) 0x62, (byte) 0x6c,
+ (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x75, (byte) 0x72, (byte) 0x63,
+ (byte) 0x65, (byte) 0x46, (byte) 0x69, (byte) 0x6c, (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x0a, (byte) 0x45,
+ (byte) 0x6d, (byte) 0x70, (byte) 0x74, (byte) 0x79, (byte) 0x2e, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61,
+ (byte) 0x0c, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x05, (byte) 0x01, (byte) 0x00, (byte) 0x05, (byte) 0x45,
+ (byte) 0x6d, (byte) 0x70, (byte) 0x74, (byte) 0x79, (byte) 0x01, (byte) 0x00, (byte) 0x10, (byte) 0x6a, (byte) 0x61,
+ (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x4f,
+ (byte) 0x62, (byte) 0x6a, (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x00, (byte) 0x21, (byte) 0x00, (byte) 0x02,
+ (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x06,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1d, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x05, (byte) 0x2a, (byte) 0xb7, (byte) 0x00, (byte) 0x01, (byte) 0xb1, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00,
+ (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x09, };
private static final class TestRunnerThread extends Thread {
private final RunnableWithExceptions runnable;
@@ -160,8 +160,9 @@ public abstract class FindBugsTestCase extends TestCase {
}
void deleteAndLog(File f) {
- if (!f.delete())
+ if (!f.delete()) {
System.err.println("Could not delete " + f);
+ }
}
/**
diff --git a/src/junit/edu/umd/cs/findbugs/IntAnnotationTest.java b/src/junit/edu/umd/cs/findbugs/IntAnnotationTest.java
index 1ca8845..82263ed 100644
--- a/src/junit/edu/umd/cs/findbugs/IntAnnotationTest.java
+++ b/src/junit/edu/umd/cs/findbugs/IntAnnotationTest.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -33,7 +33,7 @@ public class IntAnnotationTest {
assertEquals("0xffff", IntAnnotation.getShortInteger(0xffff));
assertEquals("0x1ffff", IntAnnotation.getShortInteger(0x1ffff));
assertEquals("0x1fffffff", IntAnnotation.getShortInteger(0x1fffffff));
- assertEquals("0x7fffffff", IntAnnotation.getShortInteger(0x7fffffff));
+ assertEquals("0x7fffffff", IntAnnotation.getShortInteger(0x7fffffff));
assertEquals("15", IntAnnotation.getShortInteger(15));
assertEquals("255", IntAnnotation.getShortInteger(255));
assertEquals("-1", IntAnnotation.getShortInteger(-1));
@@ -41,7 +41,7 @@ public class IntAnnotationTest {
assertEquals( "0xffffffff", IntAnnotation.getShortInteger(0xffffffffL));
assertEquals("0x1ffffffff", IntAnnotation.getShortInteger(0x1ffffffffL));
assertEquals("0xfffffffff", IntAnnotation.getShortInteger(0xfffffffffL));
-
+
}
}
diff --git a/src/junit/edu/umd/cs/findbugs/JUnitDetectorAdapter.java b/src/junit/edu/umd/cs/findbugs/JUnitDetectorAdapter.java
index e0810c7..9e95806 100644
--- a/src/junit/edu/umd/cs/findbugs/JUnitDetectorAdapter.java
+++ b/src/junit/edu/umd/cs/findbugs/JUnitDetectorAdapter.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.classfile.ClassDescriptor;
/**
* A special Detector2 class designed to run some JUnit test code. Only used by
* FindBugsTestCase.
- *
+ *
* @author David Hovemeyer
* @see FindBugsTestCase
*/
@@ -56,39 +56,45 @@ public class JUnitDetectorAdapter implements Detector2 {
}
public void finishTest() throws Exception {
- if (throwable instanceof Exception)
+ if (throwable instanceof Exception) {
throw (Exception) throwable;
- if (throwable instanceof Error)
+ }
+ if (throwable instanceof Error) {
throw (Error) throwable;
- if (throwable != null)
+ }
+ if (throwable != null) {
throw new Error(throwable);
+ }
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector2#finishPass()
*/
+ @Override
public void finishPass() {
}
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.Detector2#getDetectorClassName()
*/
+ @Override
public String getDetectorClassName() {
return this.getClass().getName();
}
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.Detector2#visitClass(edu.umd.cs.findbugs.classfile
* .ClassDescriptor)
*/
+ @Override
public void visitClass(ClassDescriptor classDescriptor) throws CheckedAnalysisException {
// Only execute the test once
if (testExecuted) {
diff --git a/src/junit/edu/umd/cs/findbugs/OpcodeStackItemTest.java b/src/junit/edu/umd/cs/findbugs/OpcodeStackItemTest.java
index ced9e19..4170207 100644
--- a/src/junit/edu/umd/cs/findbugs/OpcodeStackItemTest.java
+++ b/src/junit/edu/umd/cs/findbugs/OpcodeStackItemTest.java
@@ -30,11 +30,11 @@ public class OpcodeStackItemTest extends TestCase {
OpcodeStack.Item m2 = OpcodeStack.Item.merge(zeroItem, intItem);
assertNull(m2.getConstant());
}
-
+
public void testMergeTypeOnly() {
OpcodeStack.Item intOnly = OpcodeStack.Item.typeOnly("I");
OpcodeStack.Item zeroItem = new OpcodeStack.Item("I", 0);
-
+
OpcodeStack.Item m1 = OpcodeStack.Item.merge(intOnly, zeroItem);
assertEquals(0,m1.getConstant());
OpcodeStack.Item m2 = OpcodeStack.Item.merge(zeroItem, intOnly);
diff --git a/src/junit/edu/umd/cs/findbugs/SAXBugCollectionHandlerTest.java b/src/junit/edu/umd/cs/findbugs/SAXBugCollectionHandlerTest.java
index ea9b970..cc8c48e 100644
--- a/src/junit/edu/umd/cs/findbugs/SAXBugCollectionHandlerTest.java
+++ b/src/junit/edu/umd/cs/findbugs/SAXBugCollectionHandlerTest.java
@@ -70,7 +70,7 @@ public class SAXBugCollectionHandlerTest extends TestCase {
+ "</BugCollection>"));
assertEquals(1, bc.getCollection().size());
BugInstance bug = bc.getCollection().iterator().next();
- assertEquals("MS_MUTABLE_ARRAY", bug.getBugPattern().getType());
+ assertEquals("MS_MUTABLE_ARRAY", bug.getBugPattern().getType());
assertEquals("1acc5c5b9b7ab9efacede805afe1e53a", bug.getInstanceHash());
assertEquals(16, bug.getBugRank());
assertEquals("4/11/10 11:24 AM", BugInstance.firstSeenXMLFormat().format(bug.getXmlProps().getFirstSeen()));
diff --git a/src/junit/edu/umd/cs/findbugs/ba/MethodHashTest.java b/src/junit/edu/umd/cs/findbugs/ba/MethodHashTest.java
index 72c8c56..dd3c2fd 100644
--- a/src/junit/edu/umd/cs/findbugs/ba/MethodHashTest.java
+++ b/src/junit/edu/umd/cs/findbugs/ba/MethodHashTest.java
@@ -45,7 +45,7 @@ public class MethodHashTest extends TestCase {
/*
* (non-Javadoc)
- *
+ *
* @see junit.framework.TestCase#setUp()
*/
diff --git a/src/junit/edu/umd/cs/findbugs/ba/SignatureParserTest.java b/src/junit/edu/umd/cs/findbugs/ba/SignatureParserTest.java
index fcacb80..b588155 100644
--- a/src/junit/edu/umd/cs/findbugs/ba/SignatureParserTest.java
+++ b/src/junit/edu/umd/cs/findbugs/ba/SignatureParserTest.java
@@ -41,4 +41,3 @@ public class SignatureParserTest extends TestCase {
}
}
-// vim:ts=4
diff --git a/src/junit/edu/umd/cs/findbugs/ba/ch/Subtypes2Test.java b/src/junit/edu/umd/cs/findbugs/ba/ch/Subtypes2Test.java
index f43ce2e..c3d5299 100644
--- a/src/junit/edu/umd/cs/findbugs/ba/ch/Subtypes2Test.java
+++ b/src/junit/edu/umd/cs/findbugs/ba/ch/Subtypes2Test.java
@@ -31,7 +31,7 @@ import edu.umd.cs.findbugs.detect.FindRefComparison;
/**
* Tests for Subtypes2.
- *
+ *
* @author Bill Pugh
* @author David Hovemeyer
*/
@@ -91,7 +91,7 @@ public class Subtypes2Test extends FindBugsTestCase {
/*
* (non-Javadoc)
- *
+ *
* @see junit.framework.TestCase#setUp()
*/
@Override
@@ -134,9 +134,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -149,9 +150,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -164,9 +166,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -179,6 +182,7 @@ public class Subtypes2Test extends FindBugsTestCase {
public void testInterfaceIsSubtypeOfObject() throws Throwable {
executeFindBugsTest(new RunnableWithExceptions() {
+ @Override
public void run() throws ClassNotFoundException {
Subtypes2 test = getSubtypes2();
@@ -191,9 +195,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -207,9 +212,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -222,9 +228,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -237,9 +244,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -254,9 +262,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Exception {
Subtypes2 test = getSubtypes2();
@@ -269,9 +278,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Exception {
Subtypes2 test = getSubtypes2();
@@ -286,9 +296,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -307,9 +318,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -326,9 +338,10 @@ public class Subtypes2Test extends FindBugsTestCase {
executeFindBugsTest(new RunnableWithExceptions() {
/*
* (non-Javadoc)
- *
+ *
* @see edu.umd.cs.findbugs.RunnableWithExceptions#run()
*/
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -352,6 +365,7 @@ public class Subtypes2Test extends FindBugsTestCase {
public void testArrayFirstCommonSuperclassTricky() throws Exception {
executeFindBugsTest(new RunnableWithExceptions() {
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
@@ -369,6 +383,7 @@ public class Subtypes2Test extends FindBugsTestCase {
public void testInterfaces() throws Exception {
executeFindBugsTest(new RunnableWithExceptions() {
+ @Override
public void run() throws Throwable {
Subtypes2 test = getSubtypes2();
assertEquals(typeCollection, test.getFirstCommonSuperclass(typeCollection, typeHashSet));
diff --git a/src/junit/edu/umd/cs/findbugs/ba/generic/GenericUtilitiesTest.java b/src/junit/edu/umd/cs/findbugs/ba/generic/GenericUtilitiesTest.java
index 7955204..99ee3d2 100644
--- a/src/junit/edu/umd/cs/findbugs/ba/generic/GenericUtilitiesTest.java
+++ b/src/junit/edu/umd/cs/findbugs/ba/generic/GenericUtilitiesTest.java
@@ -70,5 +70,5 @@ public class GenericUtilitiesTest extends TestCase {
GenericUtilities.getType("[Ljava/util/Map<Ljava/lang/String;[Ljava/lang/String;>;");
GenericUtilities.getType("Lcom/palantir/finance/commons/service/calculator/Call<-Ljava/util/List<!*>;+Ljava/util/List<Ljava/lang/String;>;>;");
}
-
+
}
diff --git a/src/junit/edu/umd/cs/findbugs/ba/generic/TestGenericObjectType.java b/src/junit/edu/umd/cs/findbugs/ba/generic/TestGenericObjectType.java
index 9559c6b..3b144c8 100644
--- a/src/junit/edu/umd/cs/findbugs/ba/generic/TestGenericObjectType.java
+++ b/src/junit/edu/umd/cs/findbugs/ba/generic/TestGenericObjectType.java
@@ -70,8 +70,9 @@ public class TestGenericObjectType extends TestCase {
if (typeCategory == TypeCategory.PARAMETERIZED) {
assertTrue(obj.hasParameters());
assertTrue(obj.getNumParameters() == parameters.size());
- for (int i = 0; i < obj.getNumParameters(); i++)
+ for (int i = 0; i < obj.getNumParameters(); i++) {
compareTypes(obj.getParameterAt(i), parameters.get(i));
+ }
assertNull(obj.getVariable());
assertNull(obj.getExtension());
} else if (typeCategory == TypeCategory.TYPE_VARIABLE) {
diff --git a/src/junit/edu/umd/cs/findbugs/ba/jsr305/ValidationSecurityManagerTest.java b/src/junit/edu/umd/cs/findbugs/ba/jsr305/ValidationSecurityManagerTest.java
index e8ce227..47020c0 100644
--- a/src/junit/edu/umd/cs/findbugs/ba/jsr305/ValidationSecurityManagerTest.java
+++ b/src/junit/edu/umd/cs/findbugs/ba/jsr305/ValidationSecurityManagerTest.java
@@ -19,8 +19,7 @@
package edu.umd.cs.findbugs.ba.jsr305;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
import java.io.File;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -42,9 +41,10 @@ public class ValidationSecurityManagerTest {
private static final SlashedClassName ANNOTATION = AnnotationTemplate.class.getAnnotation(SlashedClassName.class);
static class BadValidator implements TypeQualifierValidator<SlashedClassName> {
+ @Override
public @Nonnull
When forConstantValue(@Nonnull
- SlashedClassName annotation, Object value) {
+ SlashedClassName annotation, Object value) {
Thread t = new Thread() {
@Override
public void run() {
@@ -73,8 +73,9 @@ public class ValidationSecurityManagerTest {
t.start();
t.join();
assertEquals(true, b.get());
- for (File f : File.listRoots())
+ for (File f : File.listRoots()) {
f.listFiles();
+ }
}
@SlashedClassName static class AnnotationTemplate {}
diff --git a/src/junit/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeTest.java b/src/junit/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeTest.java
index 3cb55d1..c48deac 100644
--- a/src/junit/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeTest.java
+++ b/src/junit/edu/umd/cs/findbugs/ba/npe/ReturnPathTypeTest.java
@@ -25,7 +25,7 @@ import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
/**
* Test cases for ReturnPathType class.
- *
+ *
* @author David Hovemeyer
*/
public class ReturnPathTypeTest extends TestCase {
@@ -37,7 +37,7 @@ public class ReturnPathTypeTest extends TestCase {
/*
* (non-Javadoc)
- *
+ *
* @see junit.framework.TestCase#setUp()
*/
@Override
diff --git a/src/junit/edu/umd/cs/findbugs/ba/type/TypeFrameModelingVisitorTest.java b/src/junit/edu/umd/cs/findbugs/ba/type/TypeFrameModelingVisitorTest.java
index b40954c..e89e637 100644
--- a/src/junit/edu/umd/cs/findbugs/ba/type/TypeFrameModelingVisitorTest.java
+++ b/src/junit/edu/umd/cs/findbugs/ba/type/TypeFrameModelingVisitorTest.java
@@ -28,7 +28,7 @@ public class TypeFrameModelingVisitorTest {
@Test
public void testMapSignaturePattern() {
-// assertTrue(TypeFrameModelingVisitor.mapSignaturePattern.matcher("<") && !sourceSignature.contains("Map<TK;TV;>"))
+ // assertTrue(TypeFrameModelingVisitor.mapSignaturePattern.matcher("<") && !sourceSignature.contains("Map<TK;TV;>"))
}
}
diff --git a/src/junit/edu/umd/cs/findbugs/classfile/TestClassDescriptor.java b/src/junit/edu/umd/cs/findbugs/classfile/TestClassDescriptor.java
new file mode 100644
index 0000000..deb4280
--- /dev/null
+++ b/src/junit/edu/umd/cs/findbugs/classfile/TestClassDescriptor.java
@@ -0,0 +1,55 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.classfile;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+/**
+ * @author andrei
+ */
+public class TestClassDescriptor {
+
+ @Test
+ public void testSimpleName() {
+ ClassDescriptor p = DescriptorFactory.createClassDescriptor("com/bla/Parent");
+ assertEquals("com/bla/Parent", p.getClassName());
+ assertEquals("com.bla.Parent", p.getDottedClassName());
+ assertEquals("Lcom/bla/Parent;", p.getSignature());
+ assertEquals("com.bla", p.getPackageName());
+ assertEquals("Parent", p.getSimpleName());
+
+ ClassDescriptor c = DescriptorFactory.createClassDescriptor("com/bla/Parent$Child");
+ assertEquals("com/bla/Parent$Child", c.getClassName());
+ assertEquals("com.bla.Parent$Child", c.getDottedClassName());
+ assertEquals("Lcom/bla/Parent$Child;", c.getSignature());
+ assertEquals("com.bla", c.getPackageName());
+ assertEquals("Child", c.getSimpleName());
+
+ ClassDescriptor a = DescriptorFactory.createClassDescriptor("com/bla/Parent$Child$1");
+ assertEquals("com/bla/Parent$Child$1", a.getClassName());
+ assertEquals("com.bla.Parent$Child$1", a.getDottedClassName());
+ assertEquals("Lcom/bla/Parent$Child$1;", a.getSignature());
+ assertEquals("com.bla", a.getPackageName());
+ assertEquals("1", a.getSimpleName());
+ }
+
+}
diff --git a/src/junit/edu/umd/cs/findbugs/cloud/AbstractCloudTest.java b/src/junit/edu/umd/cs/findbugs/cloud/AbstractCloudTest.java
index 3191e6b..7a6bc44 100644
--- a/src/junit/edu/umd/cs/findbugs/cloud/AbstractCloudTest.java
+++ b/src/junit/edu/umd/cs/findbugs/cloud/AbstractCloudTest.java
@@ -134,11 +134,12 @@ public class AbstractCloudTest extends TestCase {
assertEquals("line " + (i + 1), expectedLines[i].trim(), actualLines[i].trim());
}
int diff = actualLines.length - expectedLines.length;
- if (diff < 0)
+ if (diff < 0) {
fail((-diff) + " more lines than expected "
+ Arrays.asList(actualLines).subList(expectedLines.length, actualLines.length));
- else if (diff > 0)
+ } else if (diff > 0) {
fail((diff) + " missing lines " + Arrays.asList(expectedLines).subList(actualLines.length, expectedLines.length));
+ }
}
public void testPrintSummaryOneBugNoEvals() {
@@ -163,7 +164,7 @@ public class AbstractCloudTest extends TestCase {
"Distribution of reviews", " num designation", " 2 I will fix", " 1 not a bug", "",
"Distribution of number of reviews", " 3 with 1 review" },
- printSummary(bug1, bug2, bug3));
+ printSummary(bug1, bug2, bug3));
}
public void testPrintSummaryWithMoreThan9Reviewers() {
@@ -182,7 +183,7 @@ public class AbstractCloudTest extends TestCase {
" 3 9 user9", " 4 8 user8", " 5 7 user7", " 6 6 user6", " 7 5 user5", " 8 4 user4",
" 9 3 user3", " 11 1 user", "Total of 12 reviewers", "", "Distribution of reviews",
" num designation", " 66 I will fix", " 1 not a bug", "", "Distribution of number of reviews",
- " 67 with 1 review" },
+ " 67 with 1 review" },
printSummary(bugs.toArray(new BugInstance[0])));
}
@@ -200,7 +201,7 @@ public class AbstractCloudTest extends TestCase {
" 1 mostly harmless", "", "Distribution of number of reviews", " 1 with 1 review",
" 1 with 2 reviews", " 1 with 3 reviews" },
- printSummary(bugs.toArray(new BugInstance[0])));
+ printSummary(bugs.toArray(new BugInstance[0])));
}
public void testVotingModePropertyNull() throws Exception {
@@ -272,10 +273,11 @@ public class AbstractCloudTest extends TestCase {
}
private void checkVotingMode(Mode expectedMode, String modeString) throws IOException {
- if (modeString == null)
+ if (modeString == null) {
plugin.getProperties().getProperties().remove("findbugs.cloud.votingmode");
- else
+ } else {
plugin.getProperties().setProperty("findbugs.cloud.votingmode", modeString);
+ }
cloud = new MyAbstractCloud(plugin, bugCollection, new Properties());
cloud.initialize();
assertEquals(expectedMode, cloud.getMode());
@@ -283,10 +285,12 @@ public class AbstractCloudTest extends TestCase {
private void initializeSourceLinks(String pattern, String format, String formatWithLine) throws IOException {
plugin.getProperties().setProperty("findbugs.sourcelink.pattern", pattern);
- if (format != null)
+ if (format != null) {
plugin.getProperties().setProperty("findbugs.sourcelink.format", format);
- if (formatWithLine != null)
+ }
+ if (formatWithLine != null) {
plugin.getProperties().setProperty("findbugs.sourcelink.formatWithLine", formatWithLine);
+ }
cloud = new MyAbstractCloud(plugin, bugCollection, new Properties());
cloud.initialize();
}
@@ -311,8 +315,9 @@ public class AbstractCloudTest extends TestCase {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (String string : lines) {
- if (!first)
+ if (!first) {
builder.append("\n");
+ }
builder.append(string);
first = false;
}
@@ -341,10 +346,12 @@ public class AbstractCloudTest extends TestCase {
super(plugin, bugs, properties);
}
+ @Override
public void storeUserAnnotation(BugInstance bugInstance) {
throw new UnsupportedOperationException();
}
+ @Override
public String getUser() {
return "user";
}
@@ -354,19 +361,24 @@ public class AbstractCloudTest extends TestCase {
return SigninState.NO_SIGNIN_REQUIRED;
}
+ @Override
public void setSaveSignInInformation(boolean save) {
}
+ @Override
public boolean isSavingSignInInformationEnabled() {
return false;
}
+ @Override
public void signIn() {
}
+ @Override
public void signOut() {
}
+ @Override
public BugDesignation getPrimaryDesignation(BugInstance b) {
throw new UnsupportedOperationException();
}
@@ -376,39 +388,49 @@ public class AbstractCloudTest extends TestCase {
throw new UnsupportedOperationException();
}
+ @Override
public void initiateCommunication() {
}
+ @Override
public void bugFiled(BugInstance b, Object bugLink) {
throw new UnsupportedOperationException();
}
+ @Override
public boolean availableForInitialization() {
throw new UnsupportedOperationException();
}
+ @Override
public void waitUntilIssueDataDownloaded() {
}
+ @Override
public boolean waitUntilNewIssuesUploaded(long timeout, TimeUnit unit) throws InterruptedException {
return true;
}
+ @Override
public void waitUntilNewIssuesUploaded() {
}
+ @Override
public boolean waitUntilIssueDataDownloaded(long timeout, TimeUnit unit) throws InterruptedException {
return true;
}
+ @Override
public Collection<String> getProjects(String className) {
return Collections.emptyList();
}
+ @Override
public boolean isInCloud(BugInstance b) {
return true;
}
+ @Override
public boolean isOnlineCloud() {
return false;
}
@@ -424,7 +446,7 @@ public class AbstractCloudTest extends TestCase {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.cloud.Cloud#fileBug(edu.umd.cs.findbugs.BugInstance
* , ProtoClasses.BugLinkType)
@@ -436,7 +458,7 @@ public class AbstractCloudTest extends TestCase {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.cloud.Cloud#getBugIsUnassigned(edu.umd.cs.findbugs
* .BugInstance)
@@ -448,7 +470,7 @@ public class AbstractCloudTest extends TestCase {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.cloud.Cloud#getReviewers(edu.umd.cs.findbugs.
* BugInstance)
@@ -460,7 +482,7 @@ public class AbstractCloudTest extends TestCase {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.cloud.Cloud#getWillNotBeFixed(edu.umd.cs.findbugs
* .BugInstance)
@@ -472,7 +494,7 @@ public class AbstractCloudTest extends TestCase {
/*
* (non-Javadoc)
- *
+ *
* @see
* edu.umd.cs.findbugs.cloud.AbstractCloud#getLatestDesignationFromEachUser
* (edu.umd.cs.findbugs.BugInstance)
@@ -481,17 +503,19 @@ public class AbstractCloudTest extends TestCase {
protected Iterable<BugDesignation> getLatestDesignationFromEachUser(BugInstance b) {
Map<String, BugDesignation> map = new HashMap<String, BugDesignation>();
List<BugDesignation> list = designations.get(b);
- if (list == null)
+ if (list == null) {
return Collections.emptyList();
+ }
for (BugDesignation bd : list) {
BugDesignation old = map.get(bd.getUser());
- if (old == null || old.getTimestamp() < bd.getTimestamp())
+ if (old == null || old.getTimestamp() < bd.getTimestamp()) {
map.put(bd.getUser(), bd);
+ }
}
return map.values();
}
-
+
}
}
diff --git a/src/junit/edu/umd/cs/findbugs/config/ProjectFilterSettingsTest.java b/src/junit/edu/umd/cs/findbugs/config/ProjectFilterSettingsTest.java
index fcf44d0..3afe8b7 100644
--- a/src/junit/edu/umd/cs/findbugs/config/ProjectFilterSettingsTest.java
+++ b/src/junit/edu/umd/cs/findbugs/config/ProjectFilterSettingsTest.java
@@ -65,21 +65,22 @@ public class ProjectFilterSettingsTest extends TestCase {
public void testPlainCategories() {
int count = 0;
- for (String category : DetectorFactoryCollection.instance().getBugCategories())
+ for (String category : DetectorFactoryCollection.instance().getBugCategories()) {
if (!category.equals("NOISE")) {
Assert.assertTrue(plain.containsCategory(category));
++count;
}
+ }
Assert.assertEquals(count, plain.getActiveCategorySet().size());
}
public void testAddCategory() {
Assert.assertTrue(plain.containsCategory("FAKE_CATEGORY")); // unknown
- // categories
- // should be
- // unhidden
- // by
- // default
+ // categories
+ // should be
+ // unhidden
+ // by
+ // default
plain.addCategory("FAKE_CATEGORY");
Assert.assertTrue(plain.containsCategory("FAKE_CATEGORY"));
}
@@ -147,4 +148,3 @@ public class ProjectFilterSettingsTest extends TestCase {
}
}
-// vim:ts=4
diff --git a/src/junit/edu/umd/cs/findbugs/filter/NotMatcherTest.java b/src/junit/edu/umd/cs/findbugs/filter/NotMatcherTest.java
index 8af46a6..617d7e4 100644
--- a/src/junit/edu/umd/cs/findbugs/filter/NotMatcherTest.java
+++ b/src/junit/edu/umd/cs/findbugs/filter/NotMatcherTest.java
@@ -21,9 +21,7 @@
package edu.umd.cs.findbugs.filter;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import static org.junit.matchers.JUnitMatchers.containsString;
import java.io.ByteArrayOutputStream;
@@ -76,15 +74,15 @@ public class NotMatcherTest {
Matcher wrappedMatcher = new TestMatcher(true);
NotMatcher notMatcher = new NotMatcher();
notMatcher.addChild(wrappedMatcher);
-
+
assertSame("Should return child matcher.", wrappedMatcher, notMatcher.originalMatcher());
}
-
+
@Test(expected=IllegalStateException.class)
public void throwsExceptionWhenTryingToGetNonExistentChildMatcher() {
new NotMatcher().originalMatcher();
}
-
+
private String writeXMLAndGetStringOutput(NotMatcher notMatcher) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
XMLOutput xmlOutput = new OutputStreamXMLOutput(outputStream);
@@ -105,10 +103,12 @@ public class NotMatcherTest {
this.alwaysMatches = alwaysMatches;
}
+ @Override
public boolean match(BugInstance bugInstance) {
return alwaysMatches;
}
+ @Override
public void writeXML(XMLOutput xmlOutput, boolean disabled) throws IOException {
xmlOutput.openTag("TestMatch");
xmlOutput.closeTag("TestMatch");
diff --git a/src/junit/edu/umd/cs/findbugs/filter/SourceMatcherTest.java b/src/junit/edu/umd/cs/findbugs/filter/SourceMatcherTest.java
new file mode 100644
index 0000000..d62dcb2
--- /dev/null
+++ b/src/junit/edu/umd/cs/findbugs/filter/SourceMatcherTest.java
@@ -0,0 +1,129 @@
+/*
+ * FindBugs - Find Bugs in Java programs
+ * Copyright (C) 2003-2008 University of Maryland
+ *
+ * Author: Andrey Loskutov
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package edu.umd.cs.findbugs.filter;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.apache.tools.ant.filters.StringInputStream;
+import org.junit.Before;
+import org.junit.Test;
+
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.ClassAnnotation;
+import edu.umd.cs.findbugs.SourceLineAnnotation;
+import edu.umd.cs.findbugs.xml.OutputStreamXMLOutput;
+import edu.umd.cs.findbugs.xml.XMLOutput;
+
+public class SourceMatcherTest {
+
+ private BugInstance bug;
+ private String fileName;
+
+ @Before
+ public void setup() {
+ bug = new BugInstance("UUF_UNUSED_FIELD", 0);
+ fileName = "bla.groovy";
+ }
+
+ @Test
+ public void writeXML() throws Exception {
+ SourceMatcher sm = new SourceMatcher(fileName);
+
+ String xmlOutput = writeXMLAndGetStringOutput(sm, false);
+ assertEquals("<Source name=\"" + fileName + "\"/>", xmlOutput);
+
+ sm = new SourceMatcher(fileName);
+ xmlOutput = writeXMLAndGetStringOutput(sm, true);
+ assertEquals("<Source name=\"" + fileName + "\" disabled=\"true\"/>", xmlOutput);
+ }
+
+ @Test
+ public void readXML() throws Exception {
+ SourceMatcher sm = new SourceMatcher(fileName);
+
+ String xml = writeXMLAndGetStringOutput(sm, false);
+ xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ + "\n<FindBugsFilter>"
+ + "\n<Match>"
+ + "\n" + xml
+ + "\n</Match>"
+ + "\n</FindBugsFilter>\n";
+
+ Filter filter = new Filter(new StringInputStream(xml));
+
+ assertFalse(filter.match(bug));
+
+ bug.addClass("bla", fileName);
+ assertTrue(filter.match(bug));
+ }
+
+
+ @Test
+ public void match() throws Exception {
+ SourceMatcher sm = new SourceMatcher(fileName);
+
+ // no source set: test incomplete data
+ assertFalse(sm.match(bug));
+
+ bug.addClass("bla", null);
+ assertFalse(sm.match(bug));
+
+ ClassAnnotation primaryClass = bug.getPrimaryClass();
+ primaryClass.setSourceLines(SourceLineAnnotation.createUnknown("bla", ""));
+ assertFalse(sm.match(bug));
+
+ // set right source file
+ primaryClass.setSourceLines(SourceLineAnnotation.createUnknown("bla", fileName));
+
+ // exact match
+ assertTrue(sm.match(bug));
+
+ // regexp first part
+ sm = new SourceMatcher("~bla.*");
+ assertTrue(sm.match(bug));
+
+ sm = new SourceMatcher("~blup.*");
+ assertFalse(sm.match(bug));
+
+ // regexp second part
+ sm = new SourceMatcher("~.*\\.groovy");
+ assertTrue(sm.match(bug));
+
+ sm = new SourceMatcher("~.*\\.java");
+ assertFalse(sm.match(bug));
+ }
+
+ private String writeXMLAndGetStringOutput(SourceMatcher matcher, boolean disabled) throws IOException {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ XMLOutput xmlOutput = new OutputStreamXMLOutput(outputStream);
+
+ matcher.writeXML(xmlOutput, disabled);
+ xmlOutput.finish();
+
+ return outputStream.toString().trim();
+ }
+
+
+}
diff --git a/src/junit/edu/umd/cs/findbugs/gui2/FilterFactoryTest.java b/src/junit/edu/umd/cs/findbugs/gui2/FilterFactoryTest.java
index 0b25fdc..802f029 100644
--- a/src/junit/edu/umd/cs/findbugs/gui2/FilterFactoryTest.java
+++ b/src/junit/edu/umd/cs/findbugs/gui2/FilterFactoryTest.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -20,9 +20,7 @@
package edu.umd.cs.findbugs.gui2;
import static java.util.Arrays.asList;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertSame;
-import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.*;
import org.junit.Test;
@@ -34,26 +32,26 @@ import edu.umd.cs.findbugs.filter.NotMatcher;
* @author Graham Allan (grundlefleck at gmail.com)
*/
public class FilterFactoryTest {
-
+
@Test
public void invertMatcherShouldNegateTheOriginalMatchingResult() {
BugInstance bug = new BugInstance("UUF_UNUSED_FIELD", 0);
Matcher originalMatcher = FilterFactory.makeMatcher(asList(Sortables.BUGCODE), bug);
-
+
assertTrue("Original matcher should match bug.", originalMatcher.match(bug));
-
+
Matcher notMatcher = FilterFactory.invertMatcher(originalMatcher);
assertTrue("Should return an instance of NotMatcher.", notMatcher instanceof NotMatcher);
assertFalse("Inverted matcher should now not match.", notMatcher.match(bug));
}
-
+
@Test
public void shouldReturnTheOriginalMatcherWhenAskedToInvertANotMatcher() {
BugInstance bug = new BugInstance("UUF_UNUSED_FIELD", 0);
Matcher originalMatcher = FilterFactory.makeMatcher(asList(Sortables.BUGCODE), bug);
Matcher notMatcher = FilterFactory.invertMatcher(originalMatcher);
Matcher notNotMatcher = FilterFactory.invertMatcher(notMatcher);
-
+
assertSame("Should return the originally wrapped matcher.", originalMatcher, notNotMatcher);
assertTrue("Original matcher should now not match.", notNotMatcher.match(bug));
}
diff --git a/src/junit/edu/umd/cs/findbugs/updates/UpdateCheckerTest.java b/src/junit/edu/umd/cs/findbugs/updates/UpdateCheckerTest.java
index dd0b938..71bbd53 100644
--- a/src/junit/edu/umd/cs/findbugs/updates/UpdateCheckerTest.java
+++ b/src/junit/edu/umd/cs/findbugs/updates/UpdateCheckerTest.java
@@ -1,287 +1,296 @@
-package edu.umd.cs.findbugs.updates;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.logging.Level;
-import java.util.regex.Pattern;
-
-import junit.framework.TestCase;
-import edu.umd.cs.findbugs.Plugin;
-import edu.umd.cs.findbugs.PluginException;
-import edu.umd.cs.findbugs.PluginLoader;
-import edu.umd.cs.findbugs.Version;
-
-public class UpdateCheckerTest extends TestCase {
- private static final Date KEITHS_BIRTHDAY_2011;
-
- static {
- try {
- KEITHS_BIRTHDAY_2011 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z", Locale.ENGLISH).parse("2011-03-20 02:00:00 EST");
- } catch (ParseException e) {
- throw new IllegalStateException(e);
- }
- }
-
- private List<UpdateChecker.PluginUpdate> updateCollector;
- private StringBuilder errors;
- private String responseXml;
- private CountDownLatch latch;
- private UpdateChecker checker;
- private Map<String, Collection<Plugin>> checked;
- private Map<String, String> globalOptions;
- private String uploadedXml;
-
- @Override
- protected void setUp() throws Exception {
- updateCollector = new ArrayList<UpdateChecker.PluginUpdate>();
- errors = new StringBuilder();
- latch = new CountDownLatch(1);
- checked = new HashMap<String, Collection<Plugin>>();
- globalOptions = new HashMap<String, String>();
- uploadedXml = null;
- checker = new UpdateChecker(new TestingUpdateCheckCallback(latch)) {
- @Override
- protected void actuallyCheckforUpdates(URI url, Collection<Plugin> plugins, String entryPoint)
- throws IOException {
- String urlStr = url.toString();
- assertFalse(checked.containsKey(urlStr));
- checked.put(urlStr, plugins);
- ByteArrayInputStream stream = new ByteArrayInputStream(responseXml.getBytes("UTF-8"));
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- writeXml(out, plugins, "x.y.z", true);
- uploadedXml = new String(out.toByteArray(), "UTF-8");
- parseUpdateXml(url, plugins, stream);
- }
-
- @Override
- protected void logError(Exception e, String msg) {
- errors.append(msg).append("\n");
- System.err.println(msg);
- e.printStackTrace();
- }
-
- @Override
- protected void logError(Level level, String msg) {
- errors.append(msg).append("\n");
- System.err.println(msg);
- }
- };
- }
-
- public void testSimplePluginUpdate() throws Exception {
- // setup
- setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.1");
-
- // execute
- checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
-
- // verify
- assertEquals(1, updateCollector.size());
- UpdateChecker.PluginUpdate update = updateCollector.get(0);
- assertEquals("UPDATE ME", update.getMessage());
- assertEquals("http://example.com/update", update.getUrl());
- assertEquals("2.1", update.getVersion());
- assertEquals("my.id", update.getPlugin().getPluginId());
- }
-
- public void testPluginSameVersionDifferentDate() throws Exception {
- // setup
- setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.0");
-
- // execute
- checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
-
- // verify
- assertEquals(0, updateCollector.size());
- }
-
- public void testPluginSameVersionSameDate() throws Exception {
- // setup
- setResponseXml("my.id", "2011-03-20 02:00:00 EST", "2.0");
-
- // execute
- checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
-
- // verify
- assertEquals(0, updateCollector.size());
- }
-
- public void testPluginDifferentVersionSameDate() throws Exception {
- // setup
- setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.0");
-
- // execute
- checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
-
- // verify
- assertEquals(0, updateCollector.size());
- }
-
- public void testPluginNotPresent() throws Exception {
- // setup
- setResponseXml("SOME.OTHER.PLUGIN", "09/01/2011 02:00 PM EST", "2.0");
-
- // execute
- checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
-
- // verify
- assertEquals(0, updateCollector.size());
- }
-
- public void testRedirectUpdateChecks() throws Exception {
- // setup
- setResponseXml("SOME.OTHER.PLUGIN", "09/01/2011 02:00 PM EST", "2.0");
- globalOptions.put("redirectUpdateChecks", "http://redirect.com");
-
- // execute
- checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
-
- // verify
- assertEquals(1, checked.size());
- assertTrue(checked.containsKey("http://redirect.com"));
- assertEquals(0, updateCollector.size());
- }
-
- public void testDisableUpdateChecks() throws Exception {
- // setup
- setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.1");
- globalOptions.put("noUpdateChecks", "true");
-
- // execute
- checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
-
- // verify
- assertEquals(0, checked.size());
- assertEquals(0, updateCollector.size());
- }
-
- public void testDisableUpdateChecksFalse() throws Exception {
- // setup
- setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.1");
- globalOptions.put("noUpdateChecks", "false");
-
- // execute
- checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
-
- // verify
- assertEquals(1, checked.size());
- assertEquals(1, updateCollector.size());
- }
-
- public void testDisableUpdateChecksInvalid() throws Exception {
- // setup
- setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.1");
- globalOptions.put("noUpdateChecks", "BLAH");
-
- // execute
- try {
- checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
- fail();
- } catch (Throwable e) {
- }
-
- // verify
- assertEquals(0, checked.size());
- assertEquals(0, updateCollector.size());
- }
-
- public void testSubmittedXml() throws Exception {
- // setup
- setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.1");
- Version.registerApplication("MyApp", "2.x");
-
- // execute
- checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
-
- // verify
- String pattern = "<?xml version='1.0' encoding='UTF-8'?>\n" +
- "\n" +
- "<findbugs-invocation version='*' app-name='MyApp' app-version='2.x' " +
- "entry-point='x.y.z' os='*' java-version='*' language='*' country='*' " +
- "uuid='*'>\n" +
- " <plugin id='my.id' name='My Plugin' version='2.0' release-date='1300604400000'/>\n" +
- "</findbugs-invocation>\n";
- String patternRE = convertGlobToRE(pattern);
- assertTrue(uploadedXml + " did not match " + patternRE, uploadedXml.matches(patternRE));
- }
-
- // ================ end of tests =============
-
- private void checkForUpdates(Plugin plugin) throws InterruptedException {
- checker.checkForUpdates(Arrays.asList(plugin), true);
- latch.await();
- }
-
- private String convertGlobToRE(String pattern) {
- StringBuilder builder = new StringBuilder();
- boolean first = true;
- for (String blah : pattern.split("\\*")) {
- if (first) first = false;
- else builder.append(".*");
- builder.append(Pattern.quote(blah.replaceAll("'", "\"")));
- }
- return builder.toString();
- }
-
- private void setResponseXml(String pluginid, String releaseDate, String v) {
- responseXml =
- "<fb-plugin-updates>" +
- " <plugin id='" + pluginid + "'>" +
- " <release date='" + releaseDate + "' version='" + v + "' url='http://example.com/update'>" +
- " <message>UPDATE ME</message>" +
- " </release>" +
- " </plugin>" +
- "</fb-plugin-updates>";
- }
-
- @SuppressWarnings({"deprecation"})
- private Plugin createPlugin(String pluginId, Date releaseDate, String version) throws URISyntaxException, PluginException {
- PluginLoader fakeLoader;
- try {
- fakeLoader = new PluginLoader(true, new URL("http://" + pluginId + ".findbugs.cs.umd.edu"));
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
- Plugin plugin = new Plugin(pluginId, version, releaseDate, fakeLoader, true, false);
- plugin.setShortDescription("My Plugin");
- plugin.setUpdateUrl("http://example.com/update");
- return plugin;
- }
-
- private class TestingUpdateCheckCallback implements UpdateCheckCallback {
- private final CountDownLatch latch;
-
- public TestingUpdateCheckCallback(CountDownLatch latch) {
- this.latch = latch;
- }
-
- public void pluginUpdateCheckComplete(List<UpdateChecker.PluginUpdate> updates, boolean force) {
- updateCollector.addAll(updates);
- latch.countDown();
- }
-
- public String getGlobalOption(String key) {
- return globalOptions.get(key);
- }
-
- public Plugin getGlobalOptionSetter(String key) {
- return null;
- }
- }
-}
+package edu.umd.cs.findbugs.updates;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.logging.Level;
+import java.util.regex.Pattern;
+
+import junit.framework.TestCase;
+import edu.umd.cs.findbugs.Plugin;
+import edu.umd.cs.findbugs.PluginException;
+import edu.umd.cs.findbugs.PluginLoader;
+import edu.umd.cs.findbugs.Version;
+
+public class UpdateCheckerTest extends TestCase {
+ private static final Date KEITHS_BIRTHDAY_2011;
+
+ static {
+ try {
+ KEITHS_BIRTHDAY_2011 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z", Locale.ENGLISH).parse("2011-03-20 02:00:00 EST");
+ } catch (ParseException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private List<UpdateChecker.PluginUpdate> updateCollector;
+ private StringBuilder errors;
+ private String responseXml;
+ private CountDownLatch latch;
+ private UpdateChecker checker;
+ private Map<String, Collection<Plugin>> checked;
+ private Map<String, String> globalOptions;
+ private String uploadedXml;
+
+ @Override
+ protected void setUp() throws Exception {
+ updateCollector = new ArrayList<UpdateChecker.PluginUpdate>();
+ errors = new StringBuilder();
+ latch = new CountDownLatch(1);
+ checked = new HashMap<String, Collection<Plugin>>();
+ globalOptions = new HashMap<String, String>();
+ uploadedXml = null;
+ checker = new UpdateChecker(new TestingUpdateCheckCallback(latch)) {
+ @Override
+ protected void actuallyCheckforUpdates(URI url, Collection<Plugin> plugins, String entryPoint)
+ throws IOException {
+ String urlStr = url.toString();
+ assertFalse(checked.containsKey(urlStr));
+ checked.put(urlStr, plugins);
+ ByteArrayInputStream stream = new ByteArrayInputStream(responseXml.getBytes("UTF-8"));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writeXml(out, plugins, "x.y.z", true);
+ uploadedXml = new String(out.toByteArray(), "UTF-8");
+ parseUpdateXml(url, plugins, stream);
+ }
+
+ @Override
+ protected void logError(Exception e, String msg) {
+ errors.append(msg).append("\n");
+ System.err.println(msg);
+ e.printStackTrace();
+ }
+
+ @Override
+ protected void logError(Level level, String msg) {
+ errors.append(msg).append("\n");
+ System.err.println(msg);
+ }
+ };
+ org.junit.Assume.assumeTrue(!checker.updateChecksGloballyDisabled());
+ }
+
+
+ public void testSimplePluginUpdate() throws Exception {
+ // setup
+ setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.1");
+
+ // execute
+ checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
+
+ // verify
+ assertEquals(1, updateCollector.size());
+ UpdateChecker.PluginUpdate update = updateCollector.get(0);
+ assertEquals("UPDATE ME", update.getMessage());
+ assertEquals("http://example.com/update", update.getUrl());
+ assertEquals("2.1", update.getVersion());
+ assertEquals("my.id", update.getPlugin().getPluginId());
+ }
+
+ public void testPluginSameVersionDifferentDate() throws Exception {
+ // setup
+ setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.0");
+
+ // execute
+ checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
+
+ // verify
+ assertEquals(0, updateCollector.size());
+ }
+
+ public void testPluginSameVersionSameDate() throws Exception {
+ // setup
+ setResponseXml("my.id", "03/20/2011 03:00 AM EDT", "2.0");
+
+ // execute
+ checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
+
+ // verify
+ assertEquals(0, updateCollector.size());
+ }
+
+ public void testPluginDifferentVersionSameDate() throws Exception {
+ // setup
+ setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.0");
+
+ // execute
+ checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
+
+ // verify
+ assertEquals(0, updateCollector.size());
+ }
+
+ public void testPluginNotPresent() throws Exception {
+ // setup
+ setResponseXml("SOME.OTHER.PLUGIN", "09/01/2011 02:00 PM EST", "2.0");
+
+ // execute
+ checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
+
+ // verify
+ assertEquals(0, updateCollector.size());
+ }
+
+ public void testRedirectUpdateChecks() throws Exception {
+ // setup
+ setResponseXml("SOME.OTHER.PLUGIN", "09/01/2011 02:00 PM EST", "2.0");
+ globalOptions.put("redirectUpdateChecks", "http://redirect.com");
+
+ // execute
+ checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
+
+ // verify
+ assertEquals(1, checked.size());
+ assertTrue(checked.containsKey("http://redirect.com"));
+ assertEquals(0, updateCollector.size());
+ }
+
+ public void testDisableUpdateChecks() throws Exception {
+ // setup
+ setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.1");
+ globalOptions.put("noUpdateChecks", "true");
+
+ // execute
+ checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
+
+ // verify
+ assertEquals(0, checked.size());
+ assertEquals(0, updateCollector.size());
+ }
+
+ public void testDisableUpdateChecksFalse() throws Exception {
+ // setup
+ setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.1");
+ globalOptions.put("noUpdateChecks", "false");
+
+ // execute
+ checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
+
+ // verify
+ assertEquals(1, checked.size());
+ assertEquals(1, updateCollector.size());
+ }
+
+ public void testDisableUpdateChecksInvalid() throws Exception {
+ // setup
+ setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.1");
+ globalOptions.put("noUpdateChecks", "BLAH");
+
+ // execute
+ try {
+ checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
+ fail();
+ } catch (Throwable e) {
+ }
+
+ // verify
+ assertEquals(0, checked.size());
+ assertEquals(0, updateCollector.size());
+ }
+
+ public void testSubmittedXml() throws Exception {
+ // setup
+ setResponseXml("my.id", "09/01/2011 02:00 PM EST", "2.1");
+ Version.registerApplication("MyApp", "2.x");
+
+ // execute
+ checkForUpdates(createPlugin("my.id", KEITHS_BIRTHDAY_2011, "2.0"));
+
+ // verify
+ String pattern = "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "\n" +
+ "<findbugs-invocation version='*' app-name='MyApp' app-version='2.x' " +
+ "entry-point='x.y.z' os='*' java-version='*' language='*' country='*' " +
+ "uuid='*'>\n" +
+ " <plugin id='my.id' name='My Plugin' version='2.0' release-date='1300604400000'/>\n" +
+ "</findbugs-invocation>\n";
+ String patternRE = convertGlobToRE(pattern);
+ assertTrue(uploadedXml + " did not match " + patternRE, uploadedXml.matches(patternRE));
+ }
+
+ // ================ end of tests =============
+
+ private void checkForUpdates(Plugin plugin) throws InterruptedException {
+
+ checker.checkForUpdates(Arrays.asList(plugin), true);
+ latch.await();
+ }
+
+ private String convertGlobToRE(String pattern) {
+ StringBuilder builder = new StringBuilder();
+ boolean first = true;
+ for (String blah : pattern.split("\\*")) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(".*");
+ }
+ builder.append(Pattern.quote(blah.replaceAll("'", "\"")));
+ }
+ return builder.toString();
+ }
+
+ private void setResponseXml(String pluginid, String releaseDate, String v) {
+ responseXml =
+ "<fb-plugin-updates>" +
+ " <plugin id='" + pluginid + "'>" +
+ " <release date='" + releaseDate + "' version='" + v + "' url='http://example.com/update'>" +
+ " <message>UPDATE ME</message>" +
+ " </release>" +
+ " </plugin>" +
+ "</fb-plugin-updates>";
+ }
+
+ @SuppressWarnings({"deprecation"})
+ private Plugin createPlugin(String pluginId, Date releaseDate, String version) throws URISyntaxException, PluginException {
+ PluginLoader fakeLoader;
+ try {
+ fakeLoader = new PluginLoader(true, new URL("http://" + pluginId + ".findbugs.cs.umd.edu"));
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ Plugin plugin = new Plugin(pluginId, version, releaseDate, fakeLoader, true, false);
+ plugin.setShortDescription("My Plugin");
+ plugin.setUpdateUrl("http://example.com/update");
+ return plugin;
+ }
+
+ private class TestingUpdateCheckCallback implements UpdateCheckCallback {
+ private final CountDownLatch latch;
+
+ public TestingUpdateCheckCallback(CountDownLatch latch) {
+ this.latch = latch;
+ }
+
+ @Override
+ public void pluginUpdateCheckComplete(List<UpdateChecker.PluginUpdate> updates, boolean force) {
+ updateCollector.addAll(updates);
+ latch.countDown();
+ }
+
+ @Override
+ public String getGlobalOption(String key) {
+ return globalOptions.get(key);
+ }
+
+ @Override
+ public Plugin getGlobalOptionSetter(String key) {
+ return null;
+ }
+ }
+}
diff --git a/src/junit/edu/umd/cs/findbugs/util/ClassNameTest.java b/src/junit/edu/umd/cs/findbugs/util/ClassNameTest.java
index 6a85953..3fdc70e 100644
--- a/src/junit/edu/umd/cs/findbugs/util/ClassNameTest.java
+++ b/src/junit/edu/umd/cs/findbugs/util/ClassNameTest.java
@@ -41,7 +41,7 @@ public class ClassNameTest extends TestCase {
assertEquals("java/lang/Integer", ClassName.extractClassName("[[[Ljava/lang/Integer;"));
assertEquals("java/lang/Integer", ClassName.extractClassName("java/lang/Integer"));
}
-
+
public void testGetPrimitiveType() {
assertEquals("I", ClassName.getPrimitiveType("java/lang/Integer"));
assertEquals("F", ClassName.getPrimitiveType("java/lang/Float"));
diff --git a/src/junit/edu/umd/cs/findbugs/util/StringsTest.java b/src/junit/edu/umd/cs/findbugs/util/StringsTest.java
index cf11b7e..8cc3a22 100644
--- a/src/junit/edu/umd/cs/findbugs/util/StringsTest.java
+++ b/src/junit/edu/umd/cs/findbugs/util/StringsTest.java
@@ -24,27 +24,27 @@ import junit.framework.TestCase;
public class StringsTest extends TestCase {
public static String[] escapedStrings = {
- // mixed entities/unicode escape sequences
- "a b c 1 2 3 & < > " ' \\u0005 \\u0013 λ \\\\u0007",
- // *even* series of prefixed slashes + \\u -> do escape
- "a b c \\\\\\u0005",
- // *odd* series of prefixed slashes + \\u -> don't escape
- "a b c \\\\\\\\u0005",
- // mixed even/odd prefixed slashes
- "a b c \\\\\\u0005 \\\\\\\\u0013",
- // make sure slashes work on their own (no double un/escaping)
- "\\\\\\",
- // make sure that normal characters are handled correctly if they
- // appear after escapes
- "a b c 1 2 3 & < > " ' \\u0005 \\u0013 λ \\\\u0007 a b c 1 2 3",
- // escaping a null string should be safe
- null,
- // an empty string should be safe too
- "", };
+ // mixed entities/unicode escape sequences
+ "a b c 1 2 3 & < > " ' \\u0005 \\u0013 λ \\\\u0007",
+ // *even* series of prefixed slashes + \\u -> do escape
+ "a b c \\\\\\u0005",
+ // *odd* series of prefixed slashes + \\u -> don't escape
+ "a b c \\\\\\\\u0005",
+ // mixed even/odd prefixed slashes
+ "a b c \\\\\\u0005 \\\\\\\\u0013",
+ // make sure slashes work on their own (no double un/escaping)
+ "\\\\\\",
+ // make sure that normal characters are handled correctly if they
+ // appear after escapes
+ "a b c 1 2 3 & < > " ' \\u0005 \\u0013 λ \\\\u0007 a b c 1 2 3",
+ // escaping a null string should be safe
+ null,
+ // an empty string should be safe too
+ "", };
public static String[] unescapedStrings = { "a b c 1 2 3 & < > \" ' \u0005 \u0013 \u03BB \\\\u0007", "a b c \\\\\u0005",
- "a b c \\\\\\\\u0005", "a b c \\\\\u0005 \\\\\\\\u0013", "\\\\\\",
- "a b c 1 2 3 & < > \" ' \u0005 \u0013 \u03BB \\\\u0007 a b c 1 2 3", null, "", };
+ "a b c \\\\\\\\u0005", "a b c \\\\\u0005 \\\\\\\\u0013", "\\\\\\",
+ "a b c 1 2 3 & < > \" ' \u0005 \u0013 \u03BB \\\\u0007 a b c 1 2 3", null, "", };
public void testEscapeXml() {
assert (escapedStrings.length == unescapedStrings.length);
diff --git a/src/junit/edu/umd/cs/findbugs/visitclass/GetNumberArgumentsTest.java b/src/junit/edu/umd/cs/findbugs/visitclass/GetNumberArgumentsTest.java
index 84a5e11..97725f8 100644
--- a/src/junit/edu/umd/cs/findbugs/visitclass/GetNumberArgumentsTest.java
+++ b/src/junit/edu/umd/cs/findbugs/visitclass/GetNumberArgumentsTest.java
@@ -30,13 +30,15 @@ public class GetNumberArgumentsTest extends TestCase {
static String[] simpleTypes = "I J B C D F I S Z".split(" ");
public void testSimpleWithVoidReturnType() {
- for (String s : simpleTypes)
+ for (String s : simpleTypes) {
assertEquals(1, PreorderVisitor.getNumberArguments("(" + s + ")V"));
+ }
}
public void testSimpleWithVoidIntegerType() {
- for (String s : simpleTypes)
+ for (String s : simpleTypes) {
assertEquals(1, PreorderVisitor.getNumberArguments("(" + s + ")I"));
+ }
}
public void testArrays() {
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/AcmpCondition.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/AcmpCondition.java
deleted file mode 100644
index 40dc311..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/AcmpCondition.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2006, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ba.npe2;
-
-import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
-import edu.umd.cs.findbugs.ba.Edge;
-import edu.umd.cs.findbugs.ba.Location;
-import edu.umd.cs.findbugs.ba.vna.ValueNumber;
-import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
-
-/**
- * @author David Hovemeyer
- */
- at Deprecated
-public class AcmpCondition extends Condition {
-
- public AcmpCondition(Location location) {
- super(location);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.npe2.Condition#getDecision(edu.umd.cs.findbugs
- * .ba.Edge)
- */
- @Override
- public Decision getDecision(Edge edge) {
- // TODO Auto-generated method stub
- return null;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.npe2.Condition#getValueNumber()
- */
- @Override
- public ValueNumber getValueNumber() {
- // TODO Auto-generated method stub
- return null;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.npe2.Condition#refresh(edu.umd.cs.findbugs.ba.
- * vna.ValueNumberFrame, edu.umd.cs.findbugs.ba.npe2.DefinitelyNullSet)
- */
- @Override
- public void refresh(ValueNumberFrame vnaFrame, DefinitelyNullSet definitelyNullSet) throws DataflowAnalysisException {
-
- // // Get top two stack values
- // ValueNumber a = vnaFrame.getStackValue(0);
- // ValueNumber b = vnaFrame.getStackValue(1);
- //
- // boolean acmpEqOpcode =
- // getLocation().getHandle().getInstruction().getOpcode() ==
- // Constants.IF_ACMPEQ;
- //
- // if (a.equals(b)
- // || (definitelyNullSet.isValueNull(a) &&
- // definitelyNullSet.isValueNull(b))) {
- // // Definitely the same value.
- // // We don't learn anything about the nullness,
- // // but one of the edges of the branch is
- // // infeasible.
- //
- // ifcmpDecision = new Decision(
- // acmpEqOpcode,
- // false,
- // false
- // );
- //
- // fallThroughDecision = new Decision(
- // !acmpEqOpcode,
- // false,
- // false
- // );
- //
- // return;
- // }
-
- }
-
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/Condition.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/Condition.java
deleted file mode 100644
index e9af3a1..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/Condition.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2006, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ba.npe2;
-
-import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
-import edu.umd.cs.findbugs.ba.Edge;
-import edu.umd.cs.findbugs.ba.Location;
-import edu.umd.cs.findbugs.ba.vna.ValueNumber;
-import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
-
-/**
- * @author David Hovemeyer
- */
-public abstract class Condition {
- private Location location;
-
- public Condition(Location location) {
- this.location = location;
- }
-
- public Location getLocation() {
- return location;
- }
-
- public abstract void refresh(ValueNumberFrame vnaFrame, DefinitelyNullSet definitelyNullSet) throws DataflowAnalysisException;
-
- public abstract ValueNumber getValueNumber();
-
- public abstract Decision getDecision(Edge edge);
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/Decision.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/Decision.java
deleted file mode 100644
index 5402e56..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/Decision.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2006, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ba.npe2;
-
-/**
- * @author David Hovemeyer
- */
-public class Decision {
- private boolean feasible;
-
- private NullnessValue nullnessValue;
-
- public Decision(boolean feasible, NullnessValue nullnessValue) {
- this.feasible = feasible;
- this.nullnessValue = nullnessValue;
- }
-
- public boolean isFeasible() {
- return feasible;
- }
-
- public NullnessValue getNullnessValue() {
- return nullnessValue;
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSet.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSet.java
deleted file mode 100644
index f5fa12e..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSet.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2006, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ba.npe2;
-
-import java.util.BitSet;
-
-import edu.umd.cs.findbugs.ba.vna.ValueNumber;
-
-/**
- * Set of values that is definitely known to be null.
- *
- * @author David Hovemeyer
- */
-public class DefinitelyNullSet /* extends BitSet */{
- private BitSet contents;
-
- private int numValueNumbers;
-
- public DefinitelyNullSet(int numValueNumbers) {
- this.contents = new BitSet();
- this.numValueNumbers = numValueNumbers;
- }
-
- public NullnessValue getNulllessValue(ValueNumber valueNumber) {
- return getNullnessValue(valueNumber.getNumber());
- }
-
- private NullnessValue getNullnessValue(int vn) {
- int flags = 0;
-
- int start = getStartIndex(vn);
- for (int i = 0; i < NullnessValue.FLAGS_MAX; i++) {
- if (contents.get(start + i)) {
- flags |= (1 << i);
- }
- }
-
- return NullnessValue.fromFlags(flags);
- }
-
- public void setNullnessValue(ValueNumber valueNumber, NullnessValue nullnessValue) {
- int flags = nullnessValue.getFlags();
-
- int start = getStartIndex(valueNumber.getNumber());
- for (int i = 0; i < NullnessValue.FLAGS_MAX; i++) {
- contents.set(start + i, (flags & (1 << i)) != 0);
- }
- }
-
- public void clear() {
- contents.clear();
- }
-
- public void setTop() {
- contents.clear();
- contents.set(lastUsedBit());
- }
-
- public boolean isTop() {
- return contents.get(lastUsedBit());
- }
-
- public void setBottom() {
- contents.clear();
- contents.set(lastUsedBit() + 1);
- }
-
- public boolean isBottom() {
- return contents.get(lastUsedBit() + 1);
- }
-
- public boolean isValid() {
- return !(isTop() || isBottom());
- }
-
- public void makeSameAs(DefinitelyNullSet other) {
- contents.clear();
- contents.or(other.contents);
- }
-
- public void mergeWith(DefinitelyNullSet other) {
- if (this.isBottom() || other.isTop()) {
- return;
- }
-
- if (this.isTop() || other.isBottom()) {
- this.makeSameAs(other);
- return;
- }
-
- // Result is intersection of sets
- this.contents.and(other.contents);
- }
-
- public BitSet getAssignedNullLocationSet(ValueNumber vn) {
- throw new UnsupportedOperationException();
- }
-
- public void addAssignedNullLocation(int valueNumber, int locationNumber) {
- // Base class does not maintain this information.
- }
-
- public void clearAssignNullLocations(int valueNumber) {
- // Base class does not maintain this information.
- }
-
- private int getStartIndex(int vn) {
- return vn * (1 << NullnessValue.FLAGS_MAX);
- }
-
- private int lastUsedBit() {
- return numValueNumbers * NullnessValue.FLAGS_MAX;
- }
-
- private int topBit() {
- return lastUsedBit();
- }
-
- private int bottomBit() {
- return lastUsedBit() + 1;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return contents.hashCode();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object obj) {
- if (obj == null || obj.getClass() != this.getClass()) {
- return false;
- }
-
- DefinitelyNullSet other = (DefinitelyNullSet) obj;
- return this.contents.equals(other.contents);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- if (isTop()) {
- return "[TOP]";
- } else if (isBottom()) {
- return "[BOTTOM]";
- } else {
- StringBuilder buf = new StringBuilder();
- boolean first = true;
-
- buf.append("{");
-
- for (int i = 0; i < numValueNumbers; i++) {
- NullnessValue val = getNullnessValue(i);
- if (val.isDefinitelyNull() || val.isDefinitelyNotNull()) {
- if (first) {
- first = false;
- } else {
- buf.append(", ");
- }
- buf.append(i);
- buf.append("->");
- buf.append(val.toString());
- }
- }
-
- buf.append("}");
-
- return buf.toString();
- }
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSetAnalysis.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSetAnalysis.java
deleted file mode 100644
index ebdb9e7..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSetAnalysis.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2006, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ba.npe2;
-
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.bcel.Constants;
-import org.apache.bcel.generic.InstructionHandle;
-
-import edu.umd.cs.findbugs.ba.BasicBlock;
-import edu.umd.cs.findbugs.ba.CompactLocationNumbering;
-import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
-import edu.umd.cs.findbugs.ba.DepthFirstSearch;
-import edu.umd.cs.findbugs.ba.Edge;
-import edu.umd.cs.findbugs.ba.ForwardDataflowAnalysis;
-import edu.umd.cs.findbugs.ba.Location;
-import edu.umd.cs.findbugs.ba.vna.ValueNumber;
-import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
-import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
-
-/**
- * A simple null-pointer analysis that keeps track of which value numbers are
- * definitely known to be null.
- *
- * @author David Hovemeyer
- */
-public class DefinitelyNullSetAnalysis extends ForwardDataflowAnalysis<DefinitelyNullSet> {
- private ValueNumberDataflow vnaDataflow;
-
- private Map<BasicBlock, Condition> conditionMap;
-
- private static final BitSet IFNULL_OPCODE_SET = new BitSet();
-
- private static final BitSet IFACMP_OPCODE_SET = new BitSet();
-
- private static final BitSet REFCMP_OPCODE_SET = new BitSet();
- static {
- IFNULL_OPCODE_SET.set(Constants.IFNULL);
- IFNULL_OPCODE_SET.set(Constants.IFNONNULL);
-
- IFACMP_OPCODE_SET.set(Constants.IF_ACMPEQ);
- IFACMP_OPCODE_SET.set(Constants.IF_ACMPNE);
-
- REFCMP_OPCODE_SET.or(IFNULL_OPCODE_SET);
- REFCMP_OPCODE_SET.or(IFACMP_OPCODE_SET);
- }
-
- /**
- * Constructor.
- *
- * @param dfs
- * DepthFirstSearch for the method
- * @param vnaDataflow
- * value number dataflow for the method
- * @param compactLocationNumbering
- * CompactLocationNumbering for the method
- */
-
- // TODO: compactLocationNumbering is ignored. Why?
- public DefinitelyNullSetAnalysis(DepthFirstSearch dfs, ValueNumberDataflow vnaDataflow,
- CompactLocationNumbering compactLocationNumbering) {
- super(dfs);
- this.vnaDataflow = vnaDataflow;
- this.conditionMap = new HashMap<BasicBlock, Condition>();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#isFactValid(java.lang
- * .Object)
- */
- @Override
- public boolean isFactValid(DefinitelyNullSet fact) {
- return fact.isValid();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#transferInstruction(org
- * .apache.bcel.generic.InstructionHandle,
- * edu.umd.cs.findbugs.ba.BasicBlock, java.lang.Object)
- */
- @Override
- public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, DefinitelyNullSet fact)
- throws DataflowAnalysisException {
- Location location = new Location(handle, basicBlock);
- ValueNumberFrame vnaFrame = vnaDataflow.getFactAfterLocation(location);
-
- if (!vnaFrame.isValid()) {
- fact.setTop();
- return;
- }
-
- // ACONST_NULL obviously produces a value that is DEFINITELY NULL.
- // LDC produces values that are NOT NULL.
- // NEW produces values that are NOT NULL.
-
- short opcode = handle.getInstruction().getOpcode();
-
- if (opcode == Constants.ACONST_NULL) {
- setTOS(vnaFrame, location, fact, NullnessValue.definitelyNullValue());
- } else if (opcode == Constants.LDC || opcode == Constants.NEW) {
- setTOS(vnaFrame, location, fact, NullnessValue.definitelyNotNullValue());
- }
-
- // TODO: for method invocations, check return annotation
-
- // Refresh condition/decision information
- if (handle == basicBlock.getLastInstruction() && REFCMP_OPCODE_SET.get(opcode)) {
- Condition condition = getCondition(basicBlock);
- if (condition != null) {
- // System.out.println("handle: " + handle);
- condition.refresh(vnaDataflow.getFactAtLocation(location), fact);
- }
- }
- }
-
- /**
- * Get the ConditionDecision providing information about the branch at the
- * end of the given basic block.
- *
- * @param basicBlock
- * @return the ConditionDecision, or null if the basic block does not end in
- * a reference comparison
- */
- private Condition getCondition(BasicBlock basicBlock) throws DataflowAnalysisException {
- Condition condition = conditionMap.get(basicBlock);
- if (condition == null) {
- Location location = new Location(basicBlock.getLastInstruction(), basicBlock);
- short opcode = basicBlock.getLastInstruction().getInstruction().getOpcode();
- if (IFNULL_OPCODE_SET.get(opcode)) {
- condition = new IfNullCondition(location);
- } else if (IFACMP_OPCODE_SET.get(opcode)) {
- // condition = new AcmpCondition(location);
- return null;
- } else {
- return null;
- }
- conditionMap.put(basicBlock, condition);
- }
- return condition;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.BasicAbstractDataflowAnalysis#edgeTransfer(edu
- * .umd.cs.findbugs.ba.Edge, java.lang.Object)
- */
- @Override
- public void edgeTransfer(Edge edge, DefinitelyNullSet fact) throws DataflowAnalysisException {
- if (!fact.isValid()) {
- return;
- }
-
- if (edge.getSource().isEmpty()) {
- return;
- }
-
- Condition condition = getCondition(edge.getSource());
- if (condition == null) {
- return;
- }
-
- Decision decision = condition.getDecision(edge);
- if (!decision.isFeasible()) {
- // This edge is not feasible.
- // Set fact to TOP to avoid polluting dataflow information
- // at a future control merge.
- fact.setTop();
- return;
- }
-
- // System.out.println("Setting " + condition.getValueNumber() + " to " +
- // decision.getNullnessValue() + " on edge " + edge);
-
- changeNullnessOfValue(condition.getValueNumber(), condition.getLocation(), fact, decision.getNullnessValue());
- }
-
- /**
- * Set the value on top of the stack as either null or unknown.
- *
- * @param vnaFrame
- * ValueNumberFrame at Location
- * @param location
- * the Location
- * @param fact
- * DefinitelyNullSet to modify
- * @param nullnessValue
- * the nullness of the value number
- * @throws DataflowAnalysisException
- */
- private void setTOS(ValueNumberFrame vnaFrame, Location location, DefinitelyNullSet fact, NullnessValue nullnessValue)
- throws DataflowAnalysisException {
- ValueNumber valueNumber = vnaFrame.getTopValue();
- changeNullnessOfValue(valueNumber, location, fact, nullnessValue);
- }
-
- /**
- * Change the nullness of a value number.
- *
- * @param valueNumber
- * the ValueNumber
- * @param location
- * Location where information is gained
- * @param fact
- * the DefinitelyNullSet to modify
- * @param nullnessValue
- * the nullness of the value number
- * @throws DataflowAnalysisException
- */
- private void changeNullnessOfValue(ValueNumber valueNumber, Location location, DefinitelyNullSet fact,
- NullnessValue nullnessValue) throws DataflowAnalysisException {
- // fact.setValue(valueNumber, isNull);
- // if (isNull) {
- // fact.addAssignedNullLocation(valueNumber.getNumber(),
- // compactLocationNumbering.getNumber(location));
- // } else {
- // fact.clearAssignNullLocations(valueNumber.getNumber());
- // }
-
- fact.setNullnessValue(valueNumber, nullnessValue);
-
- if (fact.getNulllessValue(valueNumber) != nullnessValue) {
- throw new IllegalStateException();
- }
-
- // TODO: set location where value becomes null or non-null
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#copy(java.lang.Object,
- * java.lang.Object)
- */
- public void copy(DefinitelyNullSet source, DefinitelyNullSet dest) {
- dest.makeSameAs(source);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#createFact()
- */
- public DefinitelyNullSet createFact() {
- // TODO: optionally create one with null locations
- return new DefinitelyNullSet(vnaDataflow.getAnalysis().getNumValuesAllocated());
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#initEntryFact(java.lang.Object)
- */
- public void initEntryFact(DefinitelyNullSet result) throws DataflowAnalysisException {
- // TODO: parameter annotations?
- result.clear();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.DataflowAnalysis#makeFactTop(java.lang.Object)
- */
- public void makeFactTop(DefinitelyNullSet fact) {
- fact.setTop();
- }
-
- public boolean isTop(DefinitelyNullSet fact) {
- return fact.isTop();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#meetInto(java.lang.Object,
- * edu.umd.cs.findbugs.ba.Edge, java.lang.Object)
- */
- public void meetInto(DefinitelyNullSet fact, Edge edge, DefinitelyNullSet result) throws DataflowAnalysisException {
- // TODO: use edge information (ifnull, ifnonnull, etc.)
-
- result.mergeWith(fact);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#same(java.lang.Object,
- * java.lang.Object)
- */
- public boolean same(DefinitelyNullSet fact1, DefinitelyNullSet fact2) {
- return fact1.equals(fact2);
- }
-
- // public static void main(String[] args) throws Exception {
- // if (args.length != 1) {
- // System.err.println("Usage: " + DefinitelyNullSetAnalysis.class.getName()
- // + " <classfile>");
- // System.exit(1);
- // }
- //
- // DataflowTestDriver<DefinitelyNullSet, DefinitelyNullSetAnalysis> driver =
- // new DataflowTestDriver<DefinitelyNullSet, DefinitelyNullSetAnalysis>() {
- // /* (non-Javadoc)
- // * @see
- // edu.umd.cs.findbugs.ba.DataflowTestDriver#createDataflow(edu.umd.cs.findbugs.ba.ClassContext,
- // org.apache.bcel.classfile.Method)
- // */
- // @Override
- // public Dataflow<DefinitelyNullSet, DefinitelyNullSetAnalysis>
- // createDataflow(ClassContext classContext, Method method) throws
- // CFGBuilderException, DataflowAnalysisException {
- // return classContext.getDefinitelyNullSetDataflow(method);
- // }
- // };
- //
- // driver.execute(args[0]);
- // }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSetDataflow.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSetDataflow.java
deleted file mode 100644
index 1909b3f..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSetDataflow.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2006, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ba.npe2;
-
-import edu.umd.cs.findbugs.ba.AbstractDataflow;
-import edu.umd.cs.findbugs.ba.CFG;
-
-public class DefinitelyNullSetDataflow extends AbstractDataflow<DefinitelyNullSet, DefinitelyNullSetAnalysis> {
- public DefinitelyNullSetDataflow(CFG cfg, DefinitelyNullSetAnalysis analysis) {
- super(cfg, analysis);
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSetDataflowFactory.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSetDataflowFactory.java
deleted file mode 100644
index 5d9d94f..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/DefinitelyNullSetDataflowFactory.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2003-2007 University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package edu.umd.cs.findbugs.ba.npe2;
-
-import edu.umd.cs.findbugs.ba.CFG;
-import edu.umd.cs.findbugs.ba.CompactLocationNumbering;
-import edu.umd.cs.findbugs.ba.DepthFirstSearch;
-import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
-import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
-import edu.umd.cs.findbugs.classfile.IAnalysisCache;
-import edu.umd.cs.findbugs.classfile.MethodDescriptor;
-import edu.umd.cs.findbugs.classfile.engine.bcel.AnalysisFactory;
-
-/**
- * Analysis engine to produce DefinitelyNullSetDataflow objects for analyzed
- * methods.
- *
- * @author David Hovemeyer
- */
-public class DefinitelyNullSetDataflowFactory extends AnalysisFactory<DefinitelyNullSetDataflow> {
- public DefinitelyNullSetDataflowFactory() {
- super("definitely null set dataflow", DefinitelyNullSetDataflow.class);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
- * .classfile.IAnalysisCache, java.lang.Object)
- */
- public DefinitelyNullSetDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
- throws CheckedAnalysisException {
- CFG cfg = getCFG(analysisCache, descriptor);
- DepthFirstSearch dfs = getDepthFirstSearch(analysisCache, descriptor);
- ValueNumberDataflow vnaDataflow = getValueNumberDataflow(analysisCache, descriptor);
- CompactLocationNumbering compactLocationNumbering = getCompactLocationNumbering(analysisCache, descriptor);
-
- DefinitelyNullSetAnalysis analysis = new DefinitelyNullSetAnalysis(dfs, vnaDataflow, compactLocationNumbering);
- DefinitelyNullSetDataflow dataflow = new DefinitelyNullSetDataflow(cfg, analysis);
-
- dataflow.execute();
-
- return dataflow;
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/IfNullCondition.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/IfNullCondition.java
deleted file mode 100644
index 19447f0..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/IfNullCondition.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2006, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ba.npe2;
-
-import org.apache.bcel.Constants;
-
-import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
-import edu.umd.cs.findbugs.ba.Edge;
-import edu.umd.cs.findbugs.ba.EdgeTypes;
-import edu.umd.cs.findbugs.ba.Location;
-import edu.umd.cs.findbugs.ba.vna.ValueNumber;
-import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
-
-/**
- * @author David Hovemeyer
- */
-public class IfNullCondition extends Condition {
- private ValueNumber valueNumber;
-
- private Decision ifcmpDecision;
-
- private Decision fallThroughDecision;
-
- public IfNullCondition(Location location) {
- super(location);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.npe2.Condition#getDecision(edu.umd.cs.findbugs
- * .ba.Edge)
- */
- @Override
- public Decision getDecision(Edge edge) {
- return edge.getType() == EdgeTypes.IFCMP_EDGE ? ifcmpDecision : fallThroughDecision;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ba.npe2.Condition#getValueNumber()
- */
- @Override
- public ValueNumber getValueNumber() {
- return valueNumber;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ba.npe2.Condition#refresh(edu.umd.cs.findbugs.ba.
- * vna.ValueNumberFrame, edu.umd.cs.findbugs.ba.npe2.DefinitelyNullSet)
- */
- @Override
- public void refresh(ValueNumberFrame vnaFrame, DefinitelyNullSet definitelyNullSet) throws DataflowAnalysisException {
- valueNumber = vnaFrame.getTopValue();
-
- NullnessValue nullnessValue = definitelyNullSet.getNulllessValue(valueNumber);
- short opcode = getLocation().getHandle().getInstruction().getOpcode();
-
- if (nullnessValue.isDefinitelyNull() || nullnessValue.isDefinitelyNotNull()) {
- // Comparison is redundant.
-
- boolean ifcmpFeasible = nullnessValue.isDefinitelyNull() == (opcode == Constants.IFNULL);
- ifcmpDecision = new Decision(ifcmpFeasible, ifcmpFeasible ? nullnessValue.toCheckedValue() : null);
-
- boolean fallThroughFeasible = nullnessValue.isDefinitelyNull() != (opcode == Constants.IFNONNULL);
- fallThroughDecision = new Decision(fallThroughFeasible, fallThroughFeasible ? nullnessValue.toCheckedValue() : null);
-
- return;
- }
-
- NullnessValue definitelyNull = NullnessValue.definitelyNullValue().toCheckedValue();
- NullnessValue definitelyNotNull = NullnessValue.definitelyNotNullValue().toCheckedValue();
-
- // Nullness is unknown, assume both branches are feasible.
- ifcmpDecision = new Decision(true, (opcode == Constants.IFNULL) ? definitelyNull : definitelyNotNull);
- fallThroughDecision = new Decision(true, (opcode == Constants.IFNULL) ? definitelyNotNull : definitelyNull);
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/NullnessValue.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/NullnessValue.java
deleted file mode 100644
index f31be2c..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/NullnessValue.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2006, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ba.npe2;
-
-/**
- * Symbolic values representing the nullness of a runtime value.
- *
- * @author David Hovemeyer
- */
-public class NullnessValue {
- static final int DEFINITELY_NULL = 0;
-
- static final int DEFINITELY_NOT_NULL = 1;
-
- static final int CHECKED = 2;
-
- static final int NO_KABOOM = 3;
-
- static final int FLAGS_MAX = 4;
-
- private static final NullnessValue[] instanceList = new NullnessValue[1 << FLAGS_MAX];
- static {
- for (int i = 0; i < instanceList.length; i++) {
- instanceList[i] = new NullnessValue(i);
- }
- }
-
- private final int flags;
-
- private NullnessValue(int flags) {
- this.flags = flags;
- }
-
- int getFlags() {
- return flags;
- }
-
- public boolean isDefinitelyNull() {
- return isFlagSet(DEFINITELY_NULL);
- }
-
- public boolean isDefinitelyNotNull() {
- return isFlagSet(DEFINITELY_NOT_NULL);
- }
-
- public boolean isChecked() {
- return isFlagSet(CHECKED);
- }
-
- public boolean isNoKaboom() {
- return isFlagSet(NO_KABOOM);
- }
-
- public NullnessValue toCheckedValue() {
- return instanceList[flags | (1 << CHECKED)];
- }
-
- public NullnessValue toNoKaboomValue() {
- return instanceList[flags | (1 << NO_KABOOM)];
- }
-
- // public NullnessValue toCheckedNullValue() {
- // if (isDefinitelyNull() || isDefinitelyNotNull()) {
- // throw new IllegalStateException();
- // }
- //
- // return fromFlags(flags | DEFINITELY_NULL | CHECKED);
- // }
- //
- // public NullnessValue toCheckedNotNullValue() {
- // if (isDefinitelyNull() || isDefinitelyNotNull()) {
- // throw new IllegalStateException();
- // }
- //
- // return fromFlags(flags | DEFINITELY_NOT_NULL | CHECKED);
- // }
-
- private boolean isFlagSet(int flag) {
- return (flags & (1 << flag)) != 0;
- }
-
- static NullnessValue fromFlags(int flags) {
- return instanceList[flags];
- }
-
- public static NullnessValue definitelyNullValue() {
- return fromFlags(1 << DEFINITELY_NULL);
- }
-
- public static NullnessValue definitelyNotNullValue() {
- return fromFlags(1 << DEFINITELY_NOT_NULL);
- }
-
- public static NullnessValue unknownValue() {
- return fromFlags(0);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- String pfx = "";
-
- if (isChecked()) {
- pfx += "c";
- }
-
- if (isNoKaboom()) {
- pfx += "k";
- }
-
- String val;
-
- if (isDefinitelyNull()) {
- val = "n";
- } else if (isDefinitelyNotNull()) {
- val = "N";
- } else {
- val = "-";
- }
-
- return pfx + val;
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/TestDefinitelyNullSet.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/TestDefinitelyNullSet.java
deleted file mode 100644
index 2f2a291..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/TestDefinitelyNullSet.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2006, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ba.npe2;
-
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
-/**
- * @author David Hovemeyer
- */
-public class TestDefinitelyNullSet extends TestCase {
- DefinitelyNullSet s;
-
- /*
- * (non-Javadoc)
- *
- * @see junit.framework.TestCase#setUp()
- */
- @Override
- protected void setUp() throws Exception {
- s = new DefinitelyNullSet(10);
- }
-
- public void testEmptyToString() {
- Assert.assertEquals("{}", s.toString());
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/TestNullnessValue.java b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/TestNullnessValue.java
deleted file mode 100644
index 033b987..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/TestNullnessValue.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * FindBugs - Find Bugs in Java programs
- * Copyright (C) 2006, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ba.npe2;
-
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
-/**
- * @author David Hovemeyer
- */
-public class TestNullnessValue extends TestCase {
- NullnessValue definitelyNull;
-
- @Override
- protected void setUp() {
- definitelyNull = NullnessValue.definitelyNullValue();
- }
-
- public void testDefinitelyNullToString() {
- Assert.assertEquals("n", definitelyNull.toString());
- }
-
- public void testDefinitelyNullToCheckedString() {
- Assert.assertEquals("cn", definitelyNull.toCheckedValue().toString());
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/package.html b/src/obsolete/edu/umd/cs/findbugs/ba/npe2/package.html
deleted file mode 100644
index aeaa79a..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ba/npe2/package.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-</head>
-
-<body bgcolor="white">
-<p>
- This package is a rewrite of the null-pointer analysis to use
- sets of value numbers rather than frames. The main advantage
- of this approach is that it requires no special code to handle
- the case where a value is stored in the heap and re-appears
- in a subsequent field load.
-</p>
-
-<p>
- This isn't ready for prime time, but may be in the future.
- Or maybe we'll rewrite the entire dataflow analysis package
- to use a different bytecode framework, and it will never
- be used. Hard to say for sure.
-</p>
-</body>
-
-</html>
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/AboutDialog.form b/src/obsolete/edu/umd/cs/findbugs/gui/AboutDialog.form
deleted file mode 100644
index 3cd6bfc..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/AboutDialog.form
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.0" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
- <SyntheticProperties>
- <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
- </SyntheticProperties>
- <Events>
- <EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="closeDialog"/>
- </Events>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
- <SubComponents>
- <Container class="javax.swing.JTabbedPane" name="aboutTabPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
- <SubComponents>
- <Container class="javax.swing.JScrollPane" name="aboutScrollPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="About">
- <Property name="tabTitle" type="java.lang.String" value="About"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JEditorPane" name="aboutEditorPane">
- <Properties>
- <Property name="editable" type="boolean" value="false"/>
- </Properties>
- <Events>
- <EventHandler event="hyperlinkUpdate" listener="javax.swing.event.HyperlinkListener" parameters="javax.swing.event.HyperlinkEvent" handler="editorPaneHyperlinkUpdate"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="licenseScrollPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="License">
- <Property name="tabTitle" type="java.lang.String" value="License"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JEditorPane" name="licenseEditorPane">
- <Properties>
- <Property name="editable" type="boolean" value="false"/>
- </Properties>
- <Events>
- <EventHandler event="hyperlinkUpdate" listener="javax.swing.event.HyperlinkListener" parameters="javax.swing.event.HyperlinkEvent" handler="editorPaneHyperlinkUpdate"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="acknowledgmentsScrollPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="Acknowledgments">
- <Property name="tabTitle" type="java.lang.String" value="Acknowledgments"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JEditorPane" name="acknowldgementsEditorPane">
- <Properties>
- <Property name="editable" type="boolean" value="false"/>
- </Properties>
- <Events>
- <EventHandler event="hyperlinkUpdate" listener="javax.swing.event.HyperlinkListener" parameters="javax.swing.event.HyperlinkEvent" handler="editorPaneHyperlinkUpdate"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- </SubComponents>
- </Container>
- <Component class="javax.swing.JSeparator" name="jSeparator1">
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePre" type="java.lang.String" value="{
 aboutTabPane.setTitleAt(0, L10N.getLocalString("dlg.about_tab", "About"));
 aboutTabPane.setTitleAt(1, L10N.getLocalString("dlg.license_tab", "License"));
 aboutTabPane.setTitleAt(2, L10N.getLocalString("dlg.acknowledgements_tab", "Acknowledgements")); 
}"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="okButton">
- <Properties>
- <Property name="mnemonic" type="int" value="79"/>
- <Property name="text" type="java.lang.String" value="OK"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="okButton.setText(L10N.getLocalString("dlg.ok_btn", "OK"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- </SubComponents>
-</Form>
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/AboutDialog.java b/src/obsolete/edu/umd/cs/findbugs/gui/AboutDialog.java
deleted file mode 100644
index d2e9425..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/AboutDialog.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2003,2004 University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * AboutDialog.java
- *
- * Created on April 6, 2003, 7:05 PM
- */
-
-package edu.umd.cs.findbugs.gui;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.text.MessageFormat;
-import java.util.regex.Pattern;
-
-import javax.swing.JFrame;
-import javax.swing.event.HyperlinkEvent;
-
-import edu.umd.cs.findbugs.L10N;
-import edu.umd.cs.findbugs.Version;
-import edu.umd.cs.findbugs.log.ConsoleLogger;
-import edu.umd.cs.findbugs.log.Logger;
-import edu.umd.cs.findbugs.util.LaunchBrowser;
-import edu.umd.cs.findbugs.util.Util;
-
-/**
- * The Help:About dialog.
- *
- * @author David Hovemeyer
- */
-public class AboutDialog extends javax.swing.JDialog {
- private static final long serialVersionUID = 3546076956480385584L;
-
- //private JFrame parent;
-
- /**
- * Creates new form AboutDialog
- */
- public AboutDialog(JFrame parent, Logger l, boolean modal) {
- super(parent, modal);
- //this.parent = parent;
-
- initComponents();
-
- try {
- aboutEditorPane.setPage(getClass().getClassLoader().getResource("edu/umd/cs/findbugs/gui/help/About.html"));
- licenseEditorPane.setPage(getClass().getClassLoader().getResource("edu/umd/cs/findbugs/gui/help/License.html"));
- acknowldgementsEditorPane.setPage(getClass().getClassLoader().getResource("edu/umd/cs/findbugs/gui/help/Acknowledgements.html"));
- } catch (IOException e) {
- l.logMessage(ConsoleLogger.ERROR, e.toString());
- }
-
- setTitle(MessageFormat.format(L10N.getLocalString("dlg.aboutfindbugs_ttl", "About FindBugs {0}"), new Object[]{Version.RELEASE}));
- }
-
- static Pattern pattern = Pattern.compile("@VERSION@");
- /**
- * Process an HTML page to replace certain substitution patterns.
- * Right now, we just expand @VERSION at .
- */
- @edu.umd.cs.findbugs.annotations.SuppressWarnings("OS_OPEN_STREAM")
- private void processPage(javax.swing.JEditorPane pane, String fileName) throws IOException {
- InputStream in = null;
- BufferedReader reader = null;
- try {
- StringBuilder buf = new StringBuilder();
-
- // Open the file as a stream
- in = getClass().getClassLoader().getResourceAsStream(fileName);
- if (in == null)
- throw new IOException(MessageFormat.format(L10N.getLocalString("msg.couldntload_txt", "Couldn't load {0}"), new Object[]{fileName}));
- reader = new BufferedReader(Util.getReader(in));
-
- // Replace instances of @VERSION@ with actual version number
-
- String line;
- while ((line = reader.readLine()) != null) {
- line = pattern.matcher(line).replaceAll(Version.RELEASE);
- buf.append(line);
- buf.append('\n');
- }
-
- // Load the page into the editor pane
- String text = buf.toString();
- pane.setContentType("text/html");
- pane.setText(text);
- } finally {
- try {
- if (reader != null)
- reader.close();
- else if (in != null)
- in.close();
- } catch (IOException e) {
- }
- }
- }
-
- /**
- * This method is called from within the constructor to
- * initialize the form.
- * WARNING: Do NOT modify this code. The content of this method is
- * always regenerated by the Form Editor.
- */
- private void initComponents() {//GEN-BEGIN:initComponents
- java.awt.GridBagConstraints gridBagConstraints;
-
- aboutTabPane = new javax.swing.JTabbedPane();
- aboutScrollPane = new javax.swing.JScrollPane();
- aboutEditorPane = new javax.swing.JEditorPane();
- licenseScrollPane = new javax.swing.JScrollPane();
- licenseEditorPane = new javax.swing.JEditorPane();
- acknowledgmentsScrollPane = new javax.swing.JScrollPane();
- acknowldgementsEditorPane = new javax.swing.JEditorPane();
- jSeparator1 = new javax.swing.JSeparator();
- okButton = new javax.swing.JButton();
-
- getContentPane().setLayout(new java.awt.GridBagLayout());
-
- addWindowListener(new java.awt.event.WindowAdapter() {
- @Override
- public void windowClosing(java.awt.event.WindowEvent evt) {
- closeDialog(evt);
- }
- });
-
- aboutEditorPane.setEditable(false);
- aboutEditorPane.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
- public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
- editorPaneHyperlinkUpdate(evt);
- }
- });
-
- aboutScrollPane.setViewportView(aboutEditorPane);
-
- aboutTabPane.addTab("About", aboutScrollPane);
-
- licenseEditorPane.setEditable(false);
- licenseEditorPane.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
- public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
- editorPaneHyperlinkUpdate(evt);
- }
- });
-
- licenseScrollPane.setViewportView(licenseEditorPane);
-
- aboutTabPane.addTab("License", licenseScrollPane);
-
- acknowldgementsEditorPane.setEditable(false);
- acknowldgementsEditorPane.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
- public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
- editorPaneHyperlinkUpdate(evt);
- }
- });
-
- acknowledgmentsScrollPane.setViewportView(acknowldgementsEditorPane);
-
- aboutTabPane.addTab("Acknowledgments", acknowledgmentsScrollPane);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.weightx = 1.0;
- gridBagConstraints.weighty = 1.0;
- getContentPane().add(aboutTabPane, gridBagConstraints);
-
- {
- aboutTabPane.setTitleAt(0, L10N.getLocalString("dlg.about_tab", "About"));
- aboutTabPane.setTitleAt(1, L10N.getLocalString("dlg.license_tab", "License"));
- aboutTabPane.setTitleAt(2, L10N.getLocalString("dlg.acknowledgements_tab", "Acknowledgements"));
- }
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 1;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- getContentPane().add(jSeparator1, gridBagConstraints);
-
- okButton.setMnemonic('O');
- okButton.setText("OK");
- okButton.setText(L10N.getLocalString("dlg.ok_btn", "OK"));
- okButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- okButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 2;
- gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 0);
- getContentPane().add(okButton, gridBagConstraints);
-
- pack();
- }//GEN-END:initComponents
-
- private void editorPaneHyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {//GEN-FIRST:event_editorPaneHyperlinkUpdate
- try {
- if (evt.getEventType().equals( HyperlinkEvent.EventType.ACTIVATED)) {
- URL url = evt.getURL();
- LaunchBrowser.showDocument(url);
- }
- }
- catch (Exception e) {
- }
- }//GEN-LAST:event_editorPaneHyperlinkUpdate
-
-
- private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
- closeDialog();
- }//GEN-LAST:event_okButtonActionPerformed
-
- /**
- * Closes the dialog
- */
- private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
- closeDialog();
- }//GEN-LAST:event_closeDialog
-
- private void closeDialog() {
- setVisible(false);
- dispose();
- }
-
- // Variables declaration - do not modify//GEN-BEGIN:variables
- private javax.swing.JEditorPane aboutEditorPane;
- private javax.swing.JScrollPane aboutScrollPane;
- private javax.swing.JTabbedPane aboutTabPane;
- private javax.swing.JEditorPane acknowldgementsEditorPane;
- private javax.swing.JScrollPane acknowledgmentsScrollPane;
- private javax.swing.JSeparator jSeparator1;
- private javax.swing.JEditorPane licenseEditorPane;
- private javax.swing.JScrollPane licenseScrollPane;
- private javax.swing.JButton okButton;
- // End of variables declaration//GEN-END:variables
-
-}
-
-// vim:ts=4
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/AnalysisErrorDialog.form b/src/obsolete/edu/umd/cs/findbugs/gui/AnalysisErrorDialog.form
deleted file mode 100644
index aab3172..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/AnalysisErrorDialog.form
+++ /dev/null
@@ -1,154 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.0" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
- <NonVisualComponents>
- <Menu class="javax.swing.JMenuBar" name="analysisMenuBar">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <SubComponents>
- <Menu class="javax.swing.JMenu" name="editMenu">
- <Properties>
- <Property name="text" type="java.lang.String" value="Edit"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editMenuActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="L10N.localiseButton(editMenu, "menu.edit_menu", "&Edit", true);"/>
- </AuxValues>
- <SubComponents>
- <MenuItem class="javax.swing.JMenuItem" name="selectAllMenuItem">
- <Properties>
- <Property name="accelerator" type="javax.swing.KeyStroke" editor="org.netbeans.modules.form.editors.KeyStrokeEditor">
- <KeyStroke key="Ctrl+A"/>
- </Property>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Select All"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="selectAllItemActionListener"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="L10N.localiseButton(selectAllMenuItem, "menu.selectall_item", "Select &All", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="copyMenuItem">
- <Properties>
- <Property name="accelerator" type="javax.swing.KeyStroke" editor="org.netbeans.modules.form.editors.KeyStrokeEditor">
- <KeyStroke key="Ctrl+C"/>
- </Property>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Copy"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="copyMenuItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="L10N.localiseButton(copyMenuItem, "menu.copy_item", "Copy", true);"/>
- </AuxValues>
- </MenuItem>
- </SubComponents>
- </Menu>
- </SubComponents>
- </Menu>
- </NonVisualComponents>
- <Properties>
- <Property name="title" type="java.lang.String" value="Analysis Errors" postCode="setTitle(L10N.getLocalString("dlg.analysiserrors_ttl", "Analysis Errors"));"/>
- </Properties>
- <SyntheticProperties>
- <SyntheticProperty name="menuBar" type="java.lang.String" value="analysisMenuBar"/>
- <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
- </SyntheticProperties>
- <Events>
- <EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="closeDialog"/>
- </Events>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
- <SubComponents>
- <Component class="javax.swing.JLabel" name="errorLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Errors occured during the analysis:"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="errorLabel.setText(L10N.getLocalString("dlg.analysiserror_lbl", "Errors occurred during analysis:"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="0" gridWidth="3" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="6" insetsBottom="3" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Container class="javax.swing.JScrollPane" name="errorMessageScrollPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="4" insetsLeft="6" insetsBottom="4" insetsRight="6" anchor="10" weightX="1.0" weightY="1.0"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JTextPane" name="errorMessageTextArea">
- <Properties>
- <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
- <Border info="org.netbeans.modules.form.compat2.border.BevelBorderInfo">
- <BevelBorder bevelType="1"/>
- </Border>
- </Property>
- <Property name="editable" type="boolean" value="false"/>
- </Properties>
- </Component>
- </SubComponents>
- </Container>
- <Component class="javax.swing.JSeparator" name="jSeparator1">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="2" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="leftSpacer">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.5" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="rightSpacer">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="2" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.5" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="okButton">
- <Properties>
- <Property name="mnemonic" type="int" value="79"/>
- <Property name="text" type="java.lang.String" value="OK"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="okButton.setText(L10N.getLocalString("dlg.ok_btn", "OK"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- </SubComponents>
-</Form>
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/AnalysisErrorDialog.java b/src/obsolete/edu/umd/cs/findbugs/gui/AnalysisErrorDialog.java
deleted file mode 100644
index b3152e4..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/AnalysisErrorDialog.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2003-2005, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * AnalysisErrorDialog.java
- *
- * Created on June 5, 2003, 3:20 PM
- */
-
-package edu.umd.cs.findbugs.gui;
-
-import edu.umd.cs.findbugs.BugReporter;
-import edu.umd.cs.findbugs.L10N;
-
-/**
- * A dialog to report errors that occured during analysis.
- *
- * @author David Hovemeyer
- */
-public class AnalysisErrorDialog extends javax.swing.JDialog {
-
- private BugReporter reporter;
-
- /**
- * Creates new form AnalysisErrorDialog
- */
- public AnalysisErrorDialog(java.awt.Frame parent, boolean modal, BugReporter reporter) {
- super(parent, modal);
- this.reporter = reporter;
- initComponents();
- }
-
- public void generateContents() {
- reporter.reportQueuedErrors();
- }
-
- /**
- * This method is called from within the constructor to
- * initialize the form.
- * WARNING: Do NOT modify this code. The content of this method is
- * always regenerated by the Form Editor.
- */
- private void initComponents() {//GEN-BEGIN:initComponents
- java.awt.GridBagConstraints gridBagConstraints;
-
- errorLabel = new javax.swing.JLabel();
- errorMessageScrollPane = new javax.swing.JScrollPane();
- errorMessageTextArea = new javax.swing.JTextPane();
- jSeparator1 = new javax.swing.JSeparator();
- leftSpacer = new javax.swing.JLabel();
- rightSpacer = new javax.swing.JLabel();
- okButton = new javax.swing.JButton();
- analysisMenuBar = new javax.swing.JMenuBar();
- editMenu = new javax.swing.JMenu();
- selectAllMenuItem = new javax.swing.JMenuItem();
- copyMenuItem = new javax.swing.JMenuItem();
-
- getContentPane().setLayout(new java.awt.GridBagLayout());
-
- setTitle("Analysis Errors");
- setTitle(L10N.getLocalString("dlg.analysiserrors_ttl", "Analysis Errors"));
- addWindowListener(new java.awt.event.WindowAdapter() {
- @Override
- public void windowClosing(java.awt.event.WindowEvent evt) {
- closeDialog(evt);
- }
- });
-
- errorLabel.setFont(new java.awt.Font("Dialog", 0, 12));
- errorLabel.setText("Errors occured during the analysis:");
- errorLabel.setText(L10N.getLocalString("dlg.analysiserror_lbl", "Errors occurred during analysis:"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 0;
- gridBagConstraints.gridwidth = 3;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
- gridBagConstraints.insets = new java.awt.Insets(6, 6, 3, 0);
- getContentPane().add(errorLabel, gridBagConstraints);
-
- errorMessageTextArea.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.LOWERED));
- errorMessageTextArea.setEditable(false);
- errorMessageScrollPane.setViewportView(errorMessageTextArea);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 1;
- gridBagConstraints.gridwidth = 3;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.weightx = 1.0;
- gridBagConstraints.weighty = 1.0;
- gridBagConstraints.insets = new java.awt.Insets(4, 6, 4, 6);
- getContentPane().add(errorMessageScrollPane, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 2;
- gridBagConstraints.gridwidth = 3;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- getContentPane().add(jSeparator1, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.weightx = 0.5;
- getContentPane().add(leftSpacer, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 2;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.weightx = 0.5;
- getContentPane().add(rightSpacer, gridBagConstraints);
-
- okButton.setMnemonic('O');
- okButton.setText("OK");
- okButton.setText(L10N.getLocalString("dlg.ok_btn", "OK"));
- okButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- okButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 0);
- getContentPane().add(okButton, gridBagConstraints);
-
- analysisMenuBar.setFont(new java.awt.Font("Dialog", 0, 12));
- editMenu.setText("Edit");
- editMenu.setFont(new java.awt.Font("Dialog", 0, 12));
- AnnotatedString.localiseButton(editMenu, "menu.edit_menu", "&Edit", true);
- editMenu.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- editMenuActionPerformed(evt);
- }
- });
-
- selectAllMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, java.awt.event.InputEvent.CTRL_MASK));
- selectAllMenuItem.setFont(new java.awt.Font("Dialog", 0, 12));
- selectAllMenuItem.setText("Select All");
- AnnotatedString.localiseButton(selectAllMenuItem, "menu.selectall_item", "Select &All", true);
- selectAllMenuItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- selectAllItemActionListener(evt);
- }
- });
-
- editMenu.add(selectAllMenuItem);
-
- copyMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_C, java.awt.event.InputEvent.CTRL_MASK));
- copyMenuItem.setFont(new java.awt.Font("Dialog", 0, 12));
- copyMenuItem.setText("Copy");
- AnnotatedString.localiseButton(copyMenuItem, "menu.copy_item", "Copy", true);
- copyMenuItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- copyMenuItemActionPerformed(evt);
- }
- });
-
- editMenu.add(copyMenuItem);
-
- analysisMenuBar.add(editMenu);
-
- setJMenuBar(analysisMenuBar);
-
- pack();
- }//GEN-END:initComponents
-
- private void copyMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyMenuItemActionPerformed
- errorMessageTextArea.copy();
- }//GEN-LAST:event_copyMenuItemActionPerformed
-
- private void selectAllItemActionListener(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectAllItemActionListener
- errorMessageTextArea.selectAll();
- }//GEN-LAST:event_selectAllItemActionListener
-
- private void editMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editMenuActionPerformed
- // TODO add your handling code here:
- }//GEN-LAST:event_editMenuActionPerformed
-
- private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
- closeDialog(null);
- }//GEN-LAST:event_okButtonActionPerformed
-
- /**
- * Closes the dialog
- */
- private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
- setVisible(false);
- dispose();
- }//GEN-LAST:event_closeDialog
-
- private StringBuilder buf = new StringBuilder();
-
- public void addLine(String line) {
- //System.out.println("Appending: " + line);
- int start = 0;
- int end = line.length() - 1;
- while(line.substring(start, end).length() - 100 > 50) {
- buf.append(line.substring(start, start + 99) + "-");
- buf.append('\n');
- start += 99;
- }
- buf.append(line.substring(start, end));
- buf.append('\n');
- }
-
- public void clear() {
- errorMessageTextArea.setText("");
- }
-
- public void finish() {
- errorMessageTextArea.setText(buf.toString());
- }
-
- // Variables declaration - do not modify//GEN-BEGIN:variables
- private javax.swing.JMenuBar analysisMenuBar;
- private javax.swing.JMenuItem copyMenuItem;
- private javax.swing.JMenu editMenu;
- private javax.swing.JLabel errorLabel;
- private javax.swing.JScrollPane errorMessageScrollPane;
- private javax.swing.JTextPane errorMessageTextArea;
- private javax.swing.JSeparator jSeparator1;
- private javax.swing.JLabel leftSpacer;
- private javax.swing.JButton okButton;
- private javax.swing.JLabel rightSpacer;
- private javax.swing.JMenuItem selectAllMenuItem;
- // End of variables declaration//GEN-END:variables
-
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/AnalysisRun.java b/src/obsolete/edu/umd/cs/findbugs/gui/AnalysisRun.java
deleted file mode 100644
index 17344e0..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/AnalysisRun.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2003-2005, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * AnalysisRun.java
- *
- * Created on April 1, 2003, 2:24 PM
- */
-
-package edu.umd.cs.findbugs.gui;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
-import java.text.MessageFormat;
-import java.util.HashMap;
-
-import javax.swing.tree.DefaultTreeModel;
-
-import org.dom4j.DocumentException;
-
-import edu.umd.cs.findbugs.BugInstance;
-import edu.umd.cs.findbugs.Detector;
-import edu.umd.cs.findbugs.DetectorFactoryCollection;
-import edu.umd.cs.findbugs.FindBugs2;
-import edu.umd.cs.findbugs.FindBugsProgress;
-import edu.umd.cs.findbugs.IFindBugsEngine;
-import edu.umd.cs.findbugs.L10N;
-import edu.umd.cs.findbugs.Project;
-import edu.umd.cs.findbugs.ProjectStats;
-import edu.umd.cs.findbugs.SystemProperties;
-import edu.umd.cs.findbugs.config.UserPreferences;
-import edu.umd.cs.findbugs.log.ConsoleLogger;
-import edu.umd.cs.findbugs.log.Logger;
-
-
-
-/**
- * Representation of a run of the FindBugs analysis on a Project.
- * This class has convenient methods which can be used to extract
- * bug reports in various interesting ways.
- *
- * @author David Hovemeyer
- */
-public class AnalysisRun {
- private FindBugsFrame frame;
- private String summary;
- private Logger logger;
- private IFindBugsEngine findBugs;
- private SwingGUIBugReporter reporter;
- private HashMap<String, DefaultTreeModel> treeModelMap;
-
- /**
- * Creates a new instance of AnalysisRun.
- */
- public AnalysisRun(Project project, FindBugsFrame frame) {
- this.frame = frame;
- this.logger = frame.getLogger();
- this.reporter = new SwingGUIBugReporter(this);
- this.reporter.setPriorityThreshold(Detector.EXP_PRIORITY);
-
- // Create IFindBugsEngine
- FindBugs2 engine = new FindBugs2();
- engine.setBugReporter(reporter);
- engine.setProject(project);
- engine.setDetectorFactoryCollection(DetectorFactoryCollection.instance());
-
- this.findBugs = engine;
- this.treeModelMap = new HashMap<String, DefaultTreeModel>();
- }
-
- /**
- * Get the FindBugsFrame which created this analysis run.
- *
- * @return the FindBugsFrame
- */
- public FindBugsFrame getFrame() {
- return frame;
- }
-
- /**
- * Run the analysis.
- * This should be done in a separate thread (not the GUI event thread).
- * The progress callback can be used to update the user interface to
- * reflect the progress of the analysis. The GUI may cancel the analysis
- * by interrupting the analysis thread, in which case InterruptedException
- * will be thrown by this method.
- *
- * @param progressCallback the progress callback
- * @throws IOException if an I/O error occurs during the analysis
- * @throws InterruptedException if the analysis thread is interrupted
- */
- public void execute(FindBugsProgress progressCallback) throws IOException, InterruptedException {
- findBugs.setProgressCallback(progressCallback);
-
- // Honor current UserPreferences
- findBugs.setUserPreferences(UserPreferences.getUserPreferences());
-
- // Set analysis feature settings
- findBugs.setAnalysisFeatureSettings(frame.getSettingList());
-
- // Run the analysis!
- findBugs.execute();
-
- if (!SystemProperties.getBoolean("findbugs.noSummary")) {
- // Get the summary!
- createSummary(reporter.getProjectStats());
- }
-
- }
-
- private static final String MISSING_SUMMARY_MESSAGE =
- "<html><head><title>Could not format summary</title></head>" +
- "<body><h1>Could not format summary</h1>" +
- "<p> Please report this failure to <a href=\"findbugs-discuss at cs.umd.edu\">" +
- "findbugs-discuss at cs.umd.edu</a>.</body></html>";
-
- private void createSummary(ProjectStats stats) throws IOException {
- StringWriter html = new StringWriter();
- try {
- stats.transformSummaryToHTML(html);
- summary = html.toString();
- } catch (Exception e) {
- logger.logMessage(ConsoleLogger.WARNING, MessageFormat.format(L10N.getLocalString("msg.failedtotransform_txt", "Failed to transform summary: {0}"), new Object[]{e.toString()}));
- summary = MISSING_SUMMARY_MESSAGE;
- }
- }
-
- private static final boolean CREATE_SUMMARY = !SystemProperties.getBoolean("findbugs.noSummary");
-
- /**
- * Load bugs from a file.
- */
- public void loadBugsFromFile(File file) throws IOException, org.dom4j.DocumentException {
- reporter.getBugCollection().readXML(file);
-
- // Update summary stats
- summary = reporter.getBugCollection().getSummaryHTML();
- }
-
- /**
- * Load bugs from an InputStream.
- *
- * @param in the InputStream
- * @throws IOException
- * @throws DocumentException
- */
- public void loadBugsFromInputStream(InputStream in) throws IOException, DocumentException {
- reporter.getBugCollection().readXML(in);
-
- // Update summary stats
- summary = reporter.getBugCollection().getSummaryHTML();
- }
-
- /**
- * Save bugs to a file.
- */
- public void saveBugsToFile(File file) throws IOException {
- reporter.getBugCollection().writeXML(file);
- }
-
- /**
- * Report any errors that may have occurred during analysis.
- */
- public void reportAnalysisErrors() {
- if (reporter.errorsOccurred()) {
- reporter.getErrorDialog().setSize(750, 520);
- reporter.getErrorDialog().setLocationRelativeTo(null); // center the dialog
- reporter.getErrorDialog().setVisible(true);
- }
- }
-
- /**
- * Return the collection of BugInstances.
- */
- public java.util.Collection<BugInstance> getBugInstances() {
- return reporter.getBugCollection().getCollection();
- }
-
- /**
- * Set the tree model to be used in the BugTree.
- *
- * @param groupByOrder the grouping order that the tree model will conform to
- * @param treeModel the tree model
- */
- public void setTreeModel(String groupByOrder, DefaultTreeModel treeModel) {
- treeModelMap.put(groupByOrder, treeModel);
- }
-
- /**
- * Get the tree model to be used in the BugTree.
- *
- * @param groupByOrder the grouping order that the tree model conforms to
- * @return the tree model
- */
- public DefaultTreeModel getTreeModel(String groupByOrder) {
- return treeModelMap.get(groupByOrder);
- }
-
- public String getSummary() {
- return summary;
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/BugCellRenderer.java b/src/obsolete/edu/umd/cs/findbugs/gui/BugCellRenderer.java
deleted file mode 100644
index aa53d9e..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/BugCellRenderer.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2003-2005, University of Maryland
- * Copyright (C) 2004 Dave Brosius <dbrosius at users.sourceforge.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package edu.umd.cs.findbugs.gui;
-
-import java.awt.Color;
-import java.awt.Component;
-
-import javax.swing.ImageIcon;
-import javax.swing.JTree;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.DefaultTreeCellRenderer;
-
-import edu.umd.cs.findbugs.BugInstance;
-import edu.umd.cs.findbugs.ClassAnnotation;
-import edu.umd.cs.findbugs.Detector;
-import edu.umd.cs.findbugs.FieldAnnotation;
-import edu.umd.cs.findbugs.MethodAnnotation;
-import edu.umd.cs.findbugs.SourceLineAnnotation;
-
-/**
- * Custom cell renderer for the bug tree.
- * We use this to select the tree icons, and to set the
- * text color based on the bug priority.
- */
-public class BugCellRenderer extends DefaultTreeCellRenderer {
-
- private static final BugCellRenderer theInstance = new BugCellRenderer();
-
- /**
- * Get the single instance.
- *
- * @return the instance
- */
- public static BugCellRenderer instance() {
- return theInstance;
- }
-
- private static final long serialVersionUID = 1L;
- private ImageIcon bugGroupIcon;
- private ImageIcon packageIcon;
- private ImageIcon bugIcon;
- private ImageIcon classIcon;
- private ImageIcon methodIcon;
- private ImageIcon fieldIcon;
- private ImageIcon sourceFileIcon;
- private Object value;
-
- private BugCellRenderer() {
- ClassLoader classLoader = this.getClass().getClassLoader();
- bugGroupIcon = new ImageIcon(classLoader.getResource("edu/umd/cs/findbugs/gui/bug.png"));
- packageIcon = new ImageIcon(classLoader.getResource("edu/umd/cs/findbugs/gui/package.png"));
- bugIcon = new ImageIcon(classLoader.getResource("edu/umd/cs/findbugs/gui/bug2.png"));
- classIcon = new ImageIcon(classLoader.getResource("edu/umd/cs/findbugs/gui/class.png"));
- methodIcon = new ImageIcon(classLoader.getResource("edu/umd/cs/findbugs/gui/method.png"));
- fieldIcon = new ImageIcon(classLoader.getResource("edu/umd/cs/findbugs/gui/field.png"));
- sourceFileIcon = new ImageIcon(classLoader.getResource("edu/umd/cs/findbugs/gui/sourcefile.png"));
- }
-
- @Override
- public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel,
- boolean expanded, boolean leaf, int row, boolean hasFocus) {
- DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
- Object obj = node.getUserObject();
-
- this.value = obj;
-
- super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
-
- // Set the icon, depending on what kind of node it is
- if (obj instanceof BugInstance) {
- setIcon(bugIcon);
- } else if (obj instanceof ClassAnnotation) {
- setIcon(classIcon);
- } else if (obj instanceof MethodAnnotation) {
- setIcon(methodIcon);
- } else if (obj instanceof FieldAnnotation) {
- setIcon(fieldIcon);
- } else if (obj instanceof SourceLineAnnotation) {
- setIcon(sourceFileIcon);
- } else if (obj instanceof BugInstanceGroup) {
- // This is a "group" node
- BugInstanceGroup groupNode = (BugInstanceGroup) obj;
- String groupType = groupNode.getGroupType();
- if (groupType == FindBugsFrame.GROUP_BY_CLASS) {
- setIcon(classIcon);
- } else if (groupType == FindBugsFrame.GROUP_BY_PACKAGE) {
- setIcon(packageIcon);
- } else if (groupType == FindBugsFrame.GROUP_BY_BUG_TYPE) {
- setIcon(bugGroupIcon);
- } else if (groupType == FindBugsFrame.GROUP_BY_BUG_CATEGORY) {
- setIcon(bugGroupIcon);
- }
- } else {
- setIcon(null);
- }
-
- return this;
- }
-
- @Override
- public Color getTextNonSelectionColor() {
- return getCellTextColor();
- }
-
- private Color getCellTextColor() {
- // Based on the priority, color-code the bug instance.
- Color color = Color.BLACK;
- if (value instanceof BugInstance) {
- BugInstance bugInstance = (BugInstance) value;
- switch (bugInstance.getPriority()) {
- case Detector.EXP_PRIORITY:
- color = FindBugsFrame.EXP_PRIORITY_COLOR;
- break;
- case Detector.LOW_PRIORITY:
- color = FindBugsFrame.LOW_PRIORITY_COLOR;
- break;
- case Detector.NORMAL_PRIORITY:
- color = FindBugsFrame.NORMAL_PRIORITY_COLOR;
- break;
- case Detector.HIGH_PRIORITY:
- color = FindBugsFrame.HIGH_PRIORITY_COLOR;
- break;
- }
- }
- return color;
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/BugInstanceGroup.java b/src/obsolete/edu/umd/cs/findbugs/gui/BugInstanceGroup.java
deleted file mode 100644
index 28b049f..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/BugInstanceGroup.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2003,2004 University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * BugInstanceGroup.java
- *
- * Created on April 6, 2003, 11:31 AM
- */
-
-package edu.umd.cs.findbugs.gui;
-
-/**
- * A BugInstanceGroup represents a node in the bug tree which groups
- * related bug instances. For example, it might group all of the bug instances
- * for the same class.
- *
- * @author David Hovemeyer
- */
-public class BugInstanceGroup {
-
- private String groupType;
- private String groupName;
- private int memberCount;
-
- /**
- * Creates a new instance of BugInstanceGroup.
- *
- * @param groupType string indicating why the bug instances in the group
- * are related
- * @param groupName name of the group (e.g., the class name if the group
- * is all bug instances in the same class)
- */
- public BugInstanceGroup(String groupType, String groupName) {
- this.groupType = groupType;
- this.groupName = groupName;
- this.memberCount = 0;
- }
-
- /**
- * Get the group type.
- */
- public String getGroupType() {
- return groupType;
- }
-
- /**
- * Increment the member count (number of bug instances in this group).
- */
- public void incrementMemberCount() {
- ++memberCount;
- }
-
- /**
- * Get the member count (number of bug instances in this group).
- */
- public int getMemberCount() {
- return memberCount;
- }
-
- /**
- * Convert to string.
- */
- @Override
- public String toString() {
- StringBuilder buf = new StringBuilder();
- buf.append(groupName);
- buf.append(" (");
- buf.append(memberCount);
- buf.append(")");
- return buf.toString();
- }
-
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/ConfigureDetectorsDialog.form b/src/obsolete/edu/umd/cs/findbugs/gui/ConfigureDetectorsDialog.form
deleted file mode 100644
index 01e7191..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/ConfigureDetectorsDialog.form
+++ /dev/null
@@ -1,138 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.0" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
- <Properties>
- <Property name="title" type="java.lang.String" value="Configure Detectors"/>
- </Properties>
- <SyntheticProperties>
- <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
- </SyntheticProperties>
- <Events>
- <EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="closeDialog"/>
- <EventHandler event="windowOpened" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowOpened"/>
- </Events>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
- <SubComponents>
- <Container class="javax.swing.JScrollPane" name="detectorTableScrollPane">
- <Properties>
- <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
- <Border info="org.netbeans.modules.form.compat2.border.BevelBorderInfo">
- <BevelBorder bevelType="1"/>
- </Border>
- </Property>
- </Properties>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="-1" gridY="-1" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="6" insetsBottom="2" insetsRight="6" anchor="10" weightX="1.0" weightY="0.8"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JTable" name="detectorTable">
- <Properties>
- <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor" postCode="populateTable();
detectorTable.getColumnModel().getColumn(ENABLED_COLUMN).setMaxWidth(60);
detectorTable.getColumnModel().getColumn(SPEED_COLUMN).setMaxWidth(60);
detectorTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
">
- <Table columnCount="3" rowCount="0">
- <Column editable="false" title="Bug Detector" type="java.lang.String"/>
- <Column editable="false" title="Speed" type="java.lang.String"/>
- <Column editable="true" title="Enabled" type="java.lang.Boolean"/>
- </Table>
- </Property>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="
{
 DefaultTableModel m = (DefaultTableModel)detectorTable.getModel();
 m.setColumnIdentifiers( new String[]
 {
 L10N.getLocalString("dlg.bugdetector_lbl", "Bug Detector"),
 L10N.getLocalString("dlg.speed_lbl", "Speed"),
 L10N.getLocalString("dlg.enabled_lbl", "Enabled"),
 }) [...]
- </AuxValues>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="detectorDescriptionScrollPane">
- <Properties>
- <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
- <Border info="org.netbeans.modules.form.compat2.border.BevelBorderInfo">
- <BevelBorder bevelType="1"/>
- </Border>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[110, 120]"/>
- </Property>
- </Properties>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="1" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="6" insetsBottom="2" insetsRight="6" anchor="10" weightX="0.0" weightY="0.3"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JEditorPane" name="detectorDescription">
- </Component>
- </SubComponents>
- </Container>
- <Component class="javax.swing.JSeparator" name="jSeparator1">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="2" gridWidth="4" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="okButton">
- <Properties>
- <Property name="mnemonic" type="int" value="79"/>
- <Property name="text" type="java.lang.String" value="OK"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="okButton.setText(L10N.getLocalString("dlg.ok_btn","OK"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="2" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="4" insetsRight="2" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="cancelButton">
- <Properties>
- <Property name="mnemonic" type="int" value="67"/>
- <Property name="text" type="java.lang.String" value="Cancel"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="cancelButton.setText(L10N.getLocalString("dlg.cancel_btn", "Cancel"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="3" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="2" insetsBottom="4" insetsRight="6" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="spacer">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="3" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="restoreDefaultsButton">
- <Properties>
- <Property name="text" type="java.lang.String" value="Restore Defaults"/>
- <Property name="horizontalAlignment" type="int" value="2"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="restoreDefaultsButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="restoreDefaultsButton.setText(L10N.getLocalString("dlg.restoredefaults_btn", "Restore Defaults"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- </SubComponents>
-</Form>
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/ConfigureDetectorsDialog.java b/src/obsolete/edu/umd/cs/findbugs/gui/ConfigureDetectorsDialog.java
deleted file mode 100644
index bf40256..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/ConfigureDetectorsDialog.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2003,2004 University of Maryland
- * Copyright (C) 2004 Dave Brosius <dbrosius at users.sourceforge.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * ConfigureDetectorsDialog.java
- *
- * Created on June 3, 2003, 3:52 PM
- */
-
-package edu.umd.cs.findbugs.gui;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.DefaultTableModel;
-import javax.swing.table.TableModel;
-
-import edu.umd.cs.findbugs.BugPattern;
-import edu.umd.cs.findbugs.DetectorFactory;
-import edu.umd.cs.findbugs.DetectorFactoryCollection;
-import edu.umd.cs.findbugs.L10N;
-import edu.umd.cs.findbugs.config.UserPreferences;
-
-/**
- * Configure Detectors by enabling/disabling them.
- *
- * @author David Hovemeyer
- */
-public class ConfigureDetectorsDialog extends javax.swing.JDialog {
- private static final long serialVersionUID = 1L;
-
- private static final int SPEED_COLUMN = 1;
- private static final int ENABLED_COLUMN = 2;
-
- /**
- * Creates new form ConfigureDetectorsDialog
- */
- public ConfigureDetectorsDialog(java.awt.Frame parent, boolean modal) {
- super(parent, modal);
- initComponents();
- postInitComponents();
- }
-
- /**
- * This method is called from within the constructor to
- * initialize the form.
- * WARNING: Do NOT modify this code. The content of this method is
- * always regenerated by the Form Editor.
- */
- private void initComponents() {//GEN-BEGIN:initComponents
- java.awt.GridBagConstraints gridBagConstraints;
-
- detectorTableScrollPane = new javax.swing.JScrollPane();
- detectorTable = new javax.swing.JTable();
- detectorDescriptionScrollPane = new javax.swing.JScrollPane();
- detectorDescription = new javax.swing.JEditorPane();
- jSeparator1 = new javax.swing.JSeparator();
- okButton = new javax.swing.JButton();
- cancelButton = new javax.swing.JButton();
- spacer = new javax.swing.JLabel();
- restoreDefaultsButton = new javax.swing.JButton();
-
- getContentPane().setLayout(new java.awt.GridBagLayout());
-
- setTitle("Configure Detectors");
- addWindowListener(new java.awt.event.WindowAdapter() {
- @Override
- public void windowClosing(java.awt.event.WindowEvent evt) {
- closeDialog(evt);
- }
- @Override
- public void windowOpened(java.awt.event.WindowEvent evt) {
- formWindowOpened(evt);
- }
- });
-
- detectorTableScrollPane.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.LOWERED));
- detectorTable.setModel(new javax.swing.table.DefaultTableModel(
- new Object [][] {
-
- },
- new String [] {
- "Bug Detector", "Speed", "Enabled"
- }
- ) {
- private static final long serialVersionUID = 1L;
- Class[] types = new Class [] {
- java.lang.String.class, java.lang.String.class, java.lang.Boolean.class
- };
- boolean[] canEdit = new boolean [] {
- false, false, true
- };
-
- @Override
- public Class<?> getColumnClass(int columnIndex) {
- return types [columnIndex];
- }
-
- @Override
- public boolean isCellEditable(int rowIndex, int columnIndex) {
- return canEdit [columnIndex];
- }
- });
- populateTable();
- detectorTable.getColumnModel().getColumn(ENABLED_COLUMN).setMaxWidth(60);
- detectorTable.getColumnModel().getColumn(SPEED_COLUMN).setMaxWidth(60);
- detectorTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-
- {
- DefaultTableModel m = (DefaultTableModel)detectorTable.getModel();
- m.setColumnIdentifiers( new String[]
- {
- L10N.getLocalString("dlg.bugdetector_lbl", "Bug Detector"),
- L10N.getLocalString("dlg.speed_lbl", "Speed"),
- L10N.getLocalString("dlg.enabled_lbl", "Enabled"),
- });
-
- DefaultSortedTableModel sortedModel = new DefaultSortedTableModel(m, detectorTable.getTableHeader());
- detectorTable.setModel(sortedModel);
- }
-
- detectorTableScrollPane.setViewportView(detectorTable);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridwidth = 4;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.weightx = 1.0;
- gridBagConstraints.weighty = 0.8;
- gridBagConstraints.insets = new java.awt.Insets(6, 6, 2, 6);
- getContentPane().add(detectorTableScrollPane, gridBagConstraints);
-
- detectorDescriptionScrollPane.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.LOWERED));
- detectorDescriptionScrollPane.setPreferredSize(new java.awt.Dimension(110, 120));
- detectorDescriptionScrollPane.setViewportView(detectorDescription);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 1;
- gridBagConstraints.gridwidth = 4;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.weighty = 0.3;
- gridBagConstraints.insets = new java.awt.Insets(2, 6, 2, 6);
- getContentPane().add(detectorDescriptionScrollPane, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 2;
- gridBagConstraints.gridwidth = 4;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 0);
- getContentPane().add(jSeparator1, gridBagConstraints);
-
- okButton.setMnemonic('O');
- okButton.setText("OK");
- okButton.setText(L10N.getLocalString("dlg.ok_btn","OK"));
- okButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- okButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 2;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.insets = new java.awt.Insets(0, 0, 4, 2);
- getContentPane().add(okButton, gridBagConstraints);
-
- cancelButton.setMnemonic('C');
- cancelButton.setText("Cancel");
- cancelButton.setText(L10N.getLocalString("dlg.cancel_btn", "Cancel"));
- cancelButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- cancelButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 3;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.insets = new java.awt.Insets(0, 2, 4, 6);
- getContentPane().add(cancelButton, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- gridBagConstraints.weightx = 1.0;
- getContentPane().add(spacer, gridBagConstraints);
-
- restoreDefaultsButton.setText("Restore Defaults");
- restoreDefaultsButton.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
- restoreDefaultsButton.setText(L10N.getLocalString("dlg.restoredefaults_btn", "Restore Defaults"));
- restoreDefaultsButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- restoreDefaultsButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 0);
- getContentPane().add(restoreDefaultsButton, gridBagConstraints);
-
- pack();
- }//GEN-END:initComponents
-
- private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened
- setTitle(L10N.getLocalString("dlg.configuredetectors_ttl", "Configure Detectors"));
- }//GEN-LAST:event_formWindowOpened
-
- /**
- * reverts the selected state of all the detectors to their defaults as specified in the findbugs.xml file
- *
- * @param evt the swing event corresponding to the mouse click of the Restore Defaults button
- */
- private void restoreDefaultsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_restoreDefaultsButtonActionPerformed
- Iterator<DetectorFactory> i = DetectorFactoryCollection.instance().factoryIterator();
- DefaultSortedTableModel sorter = (DefaultSortedTableModel) detectorTable.getModel();
- TableModel model = sorter.getBaseTableModel();
- int row = 0;
- while (i.hasNext()) {
- DetectorFactory factory = i.next();
- if (factory.isHidden())
- continue;
- model.setValueAt(factory.isDefaultEnabled() ? Boolean.TRUE : Boolean.FALSE, row++, ENABLED_COLUMN);
- }
- }//GEN-LAST:event_restoreDefaultsButtonActionPerformed
-
- private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
- closeDialog();
- }//GEN-LAST:event_cancelButtonActionPerformed
-
- private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
- // Update new enabled/disabled status for the Detectors
- int num = factoryList.size();
- DefaultSortedTableModel sorter = (DefaultSortedTableModel) detectorTable.getModel();
- TableModel model = sorter.getBaseTableModel();
- for (int i = 0; i < num; ++i) {
- DetectorFactory factory = factoryList.get(i);
- Boolean enabled = (Boolean) model.getValueAt(i, ENABLED_COLUMN);
- UserPreferences.getUserPreferences().enableDetector(
- factory, enabled.booleanValue());
- }
- closeDialog();
- }//GEN-LAST:event_okButtonActionPerformed
-
- /**
- * Closes the dialog
- */
- private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
- setVisible(false);
- dispose();
- }//GEN-LAST:event_closeDialog
-
- /**
- * installs a list selection listener to populate the bottom details page based on selection changes in top grid.
- * A conversion from the table sorter index to the base model index is done to get the correct details
- */
- private void postInitComponents() {
- // Listen to detector table selections so we can (hopefully)
- // display the description of the detector
-
- ListSelectionModel rowSM = detectorTable.getSelectionModel();
- rowSM.addListSelectionListener(new ListSelectionListener() {
- public void valueChanged(ListSelectionEvent e) {
- if (e.getValueIsAdjusting()) return;
-
- ListSelectionModel lsm = (ListSelectionModel) e.getSource();
- if (!lsm.isSelectionEmpty()) {
- int selectedRow = lsm.getMinSelectionIndex();
- DefaultSortedTableModel sorter = (DefaultSortedTableModel) detectorTable.getModel();
- viewDetectorDetails(factoryList.get(sorter.getBaseModelIndex(selectedRow)));
- }
- }
- });
- }
-
- /**
- * populates the bottom detector details pane based on the detector selected
- *
- * @param factory the detector that is currently selected
- */
- private void viewDetectorDetails(DetectorFactory factory) {
- String detailHTML = factory.getDetailHTML();
- if (detailHTML == null) {
- detectorDescription.setText("");
- } else {
- detectorDescription.setContentType("text/html");
- detectorDescription.setText(detailHTML);
- StringBuilder toolTip = new StringBuilder(100);
- toolTip.append("<html><body><b>");
- toolTip.append(factory.getFullName());
- toolTip.append("</b><br><br><table border='1' width='100%'><tr><th>");
- toolTip.append(L10N.getLocalString("msg.bugpatternsreported_txt", "Bug Patterns Reported"));
- toolTip.append("</th></tr>");
-
- Collection<BugPattern> patterns = factory.getReportedBugPatterns();
- for (BugPattern pattern : patterns) {
- toolTip.append("<tr><td align='center'>");
- toolTip.append("[");
- toolTip.append(pattern.getAbbrev());
- toolTip.append("] ");
- toolTip.append(pattern.getType());
- toolTip.append("</td></tr>");
- }
- toolTip.append("</body></html>");
- detectorDescription.setToolTipText(toolTip.toString());
- }
- }
-
- /**
- * populates the Detector JTable model with all available detectors
- * Due to Netbeans form builder, populate table gets called before the tablesorter is installed,
- * so it is correct for the model retrieved from the table to be assumed to be the base DefaultTableModel.
- */
- private void populateTable() {
- Iterator<DetectorFactory> i = DetectorFactoryCollection.instance().factoryIterator();
- while (i.hasNext()) {
- DetectorFactory factory = i.next();
- if (factory.isHidden())
- continue;
- DefaultTableModel model = (DefaultTableModel) detectorTable.getModel();
- model.addRow(new Object[]{
- factory.getShortName(),
- factory.getSpeed(),
- UserPreferences.getUserPreferences().isDetectorEnabled(factory)
- ? Boolean.TRUE : Boolean.FALSE
- });
- factoryList.add(factory);
- }
- }
-
- private void closeDialog() {
- setVisible(false);
- dispose();
- }
-
- /**
- * @param args the command line arguments
- */
- public static void main(String args[]) {
- new ConfigureDetectorsDialog(new javax.swing.JFrame(), true).setVisible(true);
- }
-
-
- // Variables declaration - do not modify//GEN-BEGIN:variables
- private javax.swing.JButton cancelButton;
- private javax.swing.JEditorPane detectorDescription;
- private javax.swing.JScrollPane detectorDescriptionScrollPane;
- private javax.swing.JTable detectorTable;
- private javax.swing.JScrollPane detectorTableScrollPane;
- private javax.swing.JSeparator jSeparator1;
- private javax.swing.JButton okButton;
- private javax.swing.JButton restoreDefaultsButton;
- private javax.swing.JLabel spacer;
- // End of variables declaration//GEN-END:variables
-
- // My variables
- private ArrayList<DetectorFactory> factoryList = new ArrayList<DetectorFactory>();
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/DefaultSortedTableModel.java b/src/obsolete/edu/umd/cs/findbugs/gui/DefaultSortedTableModel.java
deleted file mode 100644
index 720ae18..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/DefaultSortedTableModel.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2004,2005 Dave Brosius
- * Copyright (C) 2004,2005 University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-package edu.umd.cs.findbugs.gui;
-
-import java.awt.Component;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import javax.swing.ImageIcon;
-import javax.swing.JLabel;
-import javax.swing.JTable;
-import javax.swing.SwingConstants;
-import javax.swing.event.TableModelEvent;
-import javax.swing.event.TableModelListener;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.DefaultTableCellRenderer;
-import javax.swing.table.JTableHeader;
-import javax.swing.table.TableCellRenderer;
-import javax.swing.table.TableModel;
-
-/**
- * A Table model that sits between the JTable and the real model.
- * This model converts view row indexes, into sorted model row indexes.
- */
-public class DefaultSortedTableModel extends AbstractTableModel
-{
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- public static final int SORT_NO_ORDER = 0;
- public static final int SORT_ASCENDING_ORDER = 1;
- public static final int SORT_DESCENDING_ORDER = 2;
- public static final int NUM_SORT_DIREECTIONS = 3;
-
- private AbstractTableModel baseModel;
- private List<Integer> viewToModelMapping;
- private int sortDirection = SORT_ASCENDING_ORDER;
- private int sortColumn = 0;
- private ImageIcon upIcon, downIcon;
-
-
- public DefaultSortedTableModel( AbstractTableModel model, JTableHeader header ) {
- baseModel = model;
- model.addTableModelListener(new BaseTableModelListener());
-
- final JTableHeader baseHeader = header;
- baseHeader.addMouseListener(new HeaderListener());
- final TableCellRenderer baseRenderer = baseHeader.getDefaultRenderer();
- baseHeader.setDefaultRenderer( new DefaultTableCellRenderer() {
- @Override
- public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
- JLabel label = (JLabel)baseRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
- if (baseHeader.getTable().convertColumnIndexToModel(column) == sortColumn) {
- if (sortDirection != SORT_NO_ORDER) {
- label.setHorizontalTextPosition(SwingConstants.LEFT);
- label.setIcon( sortDirection == SORT_ASCENDING_ORDER ? downIcon : upIcon );
- } else {
- label.setIcon(null);
- }
- } else {
- label.setIcon(null);
- }
- return label;
- }
- });
-
- setupMapping();
- ClassLoader classLoader = this.getClass().getClassLoader();
- upIcon = new ImageIcon(classLoader.getResource("edu/umd/cs/findbugs/gui/up.png"));
- downIcon = new ImageIcon(classLoader.getResource("edu/umd/cs/findbugs/gui/down.png"));
- }
-
- // Base Model handling
-
- public TableModel getBaseTableModel() {
- return baseModel;
- }
-
- public int getBaseModelIndex( int viewIndex ) {
- return viewToModelMapping.get(viewIndex).intValue();
- }
-
- // Event handling
-
- @Override
- public void fireTableCellUpdated( int row, int col ) {
- if (baseModel != null)
- setupMapping();
- super.fireTableCellUpdated(row, col);
- }
-
- @Override
- public void fireTableChanged( TableModelEvent e ) {
- if (baseModel != null)
- setupMapping();
- super.fireTableChanged(e);
- }
-
- @Override
- public void fireTableDataChanged() {
- if (baseModel != null)
- setupMapping();
- super.fireTableDataChanged();
- }
-
- @Override
- public void fireTableRowsDeleted( int first, int last ) {
- if (baseModel != null)
- setupMapping();
- super.fireTableRowsDeleted(first,last);
- }
-
- @Override
- public void fireTableRowsInserted( int first, int last ) {
- if (baseModel != null)
- setupMapping();
- super.fireTableRowsInserted(first, last);
- }
-
- @Override
- public void fireTableRowsUpdated( int first, int last ) {
- if (baseModel != null)
- setupMapping();
- super.fireTableRowsUpdated(first, last);
- }
-
- @Override
- public void fireTableStructureChanged() {
- if (baseModel != null)
- setupMapping();
- super.fireTableStructureChanged();
- }
-
- // accessors
-
- @Override
- public int findColumn( String columnName ) {
- if (baseModel == null)
- return -1;
-
- return baseModel.findColumn(columnName);
- }
-
- public int getColumnCount() {
- if (baseModel == null)
- return 0;
-
- return baseModel.getColumnCount();
- }
-
- public int getRowCount() {
- if (baseModel == null)
- return 0;
-
- return baseModel.getRowCount();
- }
-
- @Override
- public Class<?> getColumnClass( int column ) {
- if (baseModel == null)
- return null;
-
- return baseModel.getColumnClass(column);
- }
-
- @Override
- public String getColumnName( int column ) {
- if (baseModel == null)
- return null;
-
- return baseModel.getColumnName(column);
- }
-
- @Override
- public boolean isCellEditable( int row, int col ) {
- if (baseModel == null)
- return false;
-
- return baseModel.isCellEditable( row, col );
- }
-
- public Object getValueAt( int row, int col ) {
- if (baseModel == null)
- return null;
-
- return baseModel.getValueAt(viewToModelMapping.get(row).intValue(), col);
- }
-
- @Override
- public void setValueAt( Object value, int row, int col ) {
- if (baseModel == null)
- return;
-
- baseModel.setValueAt( value, viewToModelMapping.get(row).intValue(), col );
- fireTableDataChanged();
- }
-
- private void setupMapping() {
- int numRows = baseModel.getRowCount();
- viewToModelMapping = new ArrayList<Integer>(numRows);
- for (int i = 0; i < numRows; i++)
- viewToModelMapping.add(i);
-
- Collections.sort( viewToModelMapping, new Comparator<Integer>() {
- @SuppressWarnings("unchecked")
- public int compare( Integer a, Integer b ) {
- if ((sortDirection == SORT_NO_ORDER) || (sortColumn == -1))
- return a.compareTo(b);
-
- Comparable<Object> first = (Comparable<Object>)baseModel.getValueAt( a.intValue(), sortColumn );
- Comparable<Object> second = (Comparable<Object>)baseModel.getValueAt( b.intValue(), sortColumn );
-
- if (sortDirection == SORT_ASCENDING_ORDER)
- return first.compareTo(second);
- else
- return second.compareTo(first);
- }
- });
-
- }
-
- private class BaseTableModelListener implements TableModelListener
- {
- public void tableChanged( TableModelEvent e ) {
- DefaultSortedTableModel.this.fireTableChanged(e);
- }
- }
-
- private class HeaderListener extends MouseAdapter
- {
- @Override
- public void mouseClicked(MouseEvent e) {
- JTableHeader header = (JTableHeader)e.getSource();
- int column = header.columnAtPoint(e.getPoint());
- column = header.getTable().convertColumnIndexToModel(column);
- if (column != sortColumn) {
- sortColumn = column;
- sortDirection = SORT_ASCENDING_ORDER;
- } else {
- sortDirection = (sortDirection + 1) % NUM_SORT_DIREECTIONS;
- }
- super.mouseClicked(e);
- DefaultSortedTableModel.this.fireTableDataChanged();
- }
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/FindBugsFrame.form b/src/obsolete/edu/umd/cs/findbugs/gui/FindBugsFrame.form
deleted file mode 100644
index 6bce104..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/FindBugsFrame.form
+++ /dev/null
@@ -1,1575 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.0" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
- <NonVisualComponents>
- <Component class="javax.swing.ButtonGroup" name="priorityButtonGroup">
- </Component>
- <Component class="javax.swing.ButtonGroup" name="effortButtonGroup">
- </Component>
- <Menu class="javax.swing.JMenuBar" name="theMenuBar">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <SubComponents>
- <Menu class="javax.swing.JMenu" name="fileMenu">
- <Properties>
- <Property name="text" type="java.lang.String" value="File"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="menuSelected" listener="javax.swing.event.MenuListener" parameters="javax.swing.event.MenuEvent" handler="fileMenuMenuSelected"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(fileMenu, "menu.file_menu", "&File", true);"/>
- </AuxValues>
- <SubComponents>
- <MenuItem class="javax.swing.JMenuItem" name="newProjectItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="New Project"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newProjectItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(newProjectItem, "menu.new_item", "&New Project", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="openProjectItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Open Project..."/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="openProjectItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(openProjectItem, "menu.open_item", "&Open Project...", true);"/>
- </AuxValues>
- </MenuItem>
- <Menu class="javax.swing.JMenu" name="recentProjectsMenu">
- <Properties>
- <Property name="text" type="java.lang.String" value="Recent Projects"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(recentProjectsMenu, "menu.recent_menu", "R&ecent Projects", true);
rebuildRecentProjectsMenu();"/>
- </AuxValues>
- </Menu>
- <MenuItem class="javax.swing.JSeparator" name="jSeparator9">
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="closeProjectItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Close Project"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeProjectItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(closeProjectItem, "menu.close_item", "&Close Project", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="saveProjectItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Save Project"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="saveProjectItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(saveProjectItem, "menu.save_item", "&Save Project", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="saveProjectAsItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Save Project As..."/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="saveProjectAsItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(saveProjectAsItem, "menu.saveas_item", "Save Project &As...", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="reloadProjectItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Reload Project"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="reloadProjectItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(reloadProjectItem, "menu.reload_item", "&Reload Project", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JSeparator" name="jSeparator3">
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="loadBugsItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Load Bugs..."/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="loadBugsItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(loadBugsItem, "menu.loadbugs_item", "&Load Bugs...", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="saveBugsItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Save Bugs"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="saveBugsItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(saveBugsItem, "menu.savebugs_item", "Save &Bugs...", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JSeparator" name="jSeparator6">
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="exitItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Exit"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="exitItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(exitItem, "menu.exit_item", "E&xit", true);"/>
- </AuxValues>
- </MenuItem>
- </SubComponents>
- </Menu>
- <Menu class="javax.swing.JMenu" name="editMenu">
- <Properties>
- <Property name="text" type="java.lang.String" value="Edit"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="enabled" type="boolean" value="false"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(editMenu, "menu.edit_menu", "&Edit", true);"/>
- </AuxValues>
- <SubComponents>
- <MenuItem class="javax.swing.JMenuItem" name="cutItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Cut"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cutActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(cutItem, "menu.cut_item", "Cut", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="copyItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Copy"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="copyActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(copyItem, "menu.copy_item", "Copy", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="pasteItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Paste"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="pasteActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(pasteItem, "menu.paste_item", "Paste", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JSeparator" name="jSeparator10">
- </MenuItem>
- <MenuItem class="javax.swing.JMenuItem" name="selectAllItem">
- <Properties>
- <Property name="accelerator" type="javax.swing.KeyStroke" editor="org.netbeans.modules.form.editors.KeyStrokeEditor">
- <KeyStroke key="Ctrl+A"/>
- </Property>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Select All"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="selectAllActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(selectAllItem, "menu.selectall_item", "Select &All", true);"/>
- </AuxValues>
- </MenuItem>
- </SubComponents>
- </Menu>
- <Menu class="javax.swing.JMenu" name="viewMenu">
- <Properties>
- <Property name="text" type="java.lang.String" value="View"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="menuSelected" listener="javax.swing.event.MenuListener" parameters="javax.swing.event.MenuEvent" handler="viewMenuMenuSelected"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(viewMenu, "menu.view_menu", "&View", true);
"/>
- </AuxValues>
- <SubComponents>
- <MenuItem class="javax.swing.JCheckBoxMenuItem" name="viewConsoleItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Console"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="viewConsoleItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(viewConsoleItem, "menu.console_item", "&Console", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JCheckBoxMenuItem" name="viewBugDetailsItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="selected" type="boolean" value="true"/>
- <Property name="text" type="java.lang.String" value="Bug Details"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="viewBugDetailsItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(viewBugDetailsItem, "menu.bugdetails_item", "Bug &Details", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JCheckBoxMenuItem" name="fullDescriptionsItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="selected" type="boolean" value="true"/>
- <Property name="text" type="java.lang.String" value="Full Descriptions"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="fullDescriptionsItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(fullDescriptionsItem, "menu.fulldescriptions_item", "&Full Descriptions", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JSeparator" name="jSeparator7">
- </MenuItem>
- <Menu class="javax.swing.JMenu" name="filterWarningsMenu">
- <Properties>
- <Property name="text" type="java.lang.String" value="Filter Warnings"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(filterWarningsMenu, "menu.filterwarnings_menu", "Filter &Warnings", true);"/>
- </AuxValues>
- <SubComponents>
- <MenuItem class="javax.swing.JRadioButtonMenuItem" name="expPriorityButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Experimental Priority"/>
- <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
- <ComponentRef name="priorityButtonGroup"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="expPriorityButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(expPriorityButton, "menu.exppriority_item", "&Experimental Priority", true);
expPriorityButton.setSelected(getPriorityThreshold() == Detector.EXP_PRIORITY);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JRadioButtonMenuItem" name="lowPriorityButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Low Priority"/>
- <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
- <ComponentRef name="priorityButtonGroup"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="lowPriorityButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(lowPriorityButton, "menu.lowpriority_item", "&Low Priority", true);
lowPriorityButton.setSelected(getPriorityThreshold() == Detector.LOW_PRIORITY);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JRadioButtonMenuItem" name="mediumPriorityButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Medium Priority"/>
- <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
- <ComponentRef name="priorityButtonGroup"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="mediumPriorityButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(mediumPriorityButton, "menu.mediumpriority_item", "&Medium Priority", true);
mediumPriorityButton.setSelected(getPriorityThreshold() == Detector.NORMAL_PRIORITY);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JRadioButtonMenuItem" name="highPriorityButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="High Priority"/>
- <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
- <ComponentRef name="priorityButtonGroup"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="highPriorityButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(highPriorityButton, "menu.highpriority_item", "&High Priority", true);
highPriorityButton.setSelected(getPriorityThreshold() == Detector.HIGH_PRIORITY);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JSeparator" name="jSeparator11">
- </MenuItem>
- </SubComponents>
- </Menu>
- <MenuItem class="javax.swing.JSeparator" name="jSeparator8">
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePre" type="java.lang.String" value="ButtonGroup bg = new ButtonGroup();
bg.add(expPriorityButton);
bg.add(lowPriorityButton);
bg.add(mediumPriorityButton);
bg.add(highPriorityButton);

"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JRadioButtonMenuItem" name="viewProjectItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="View Project Details"/>
- <Property name="enabled" type="boolean" value="false"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="viewProjectItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(viewProjectItem, "menu.viewprojectdetails_item", "View Project Details", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JRadioButtonMenuItem" name="viewBugsItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="View Bugs"/>
- <Property name="enabled" type="boolean" value="false"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="viewBugsItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(viewBugsItem, "menu.viewbugs_item", "View Bugs", true);"/>
- </AuxValues>
- </MenuItem>
- </SubComponents>
- </Menu>
- <Menu class="javax.swing.JMenu" name="settingsMenu">
- <Properties>
- <Property name="text" type="java.lang.String" value="Settings"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="settingsMenuActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(settingsMenu, "menu.settings_menu", "&Settings", true);"/>
- </AuxValues>
- <SubComponents>
- <MenuItem class="javax.swing.JMenuItem" name="configureDetectorsItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Configure Detectors..."/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="configureDetectorsItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(configureDetectorsItem, "menu.configure_item", "&Configure Detectors...", true);"/>
- </AuxValues>
- </MenuItem>
- <Menu class="javax.swing.JMenu" name="effortMenu">
- <Properties>
- <Property name="text" type="java.lang.String" value="Effort"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(effortMenu, "menu.effort_menu", "Effort", true);"/>
- </AuxValues>
- <SubComponents>
- <MenuItem class="javax.swing.JCheckBoxMenuItem" name="minEffortItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Minimum"/>
- <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
- <ComponentRef name="effortButtonGroup"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="minEffortItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(minEffortItem, "menu.mineffort_item", "&Minimum", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JCheckBoxMenuItem" name="normalEffortItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="selected" type="boolean" value="true"/>
- <Property name="text" type="java.lang.String" value="Normal"/>
- <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
- <ComponentRef name="effortButtonGroup"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="normalEffortItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(normalEffortItem, "menu.normaleffort_item", "&Normal", true);"/>
- </AuxValues>
- </MenuItem>
- <MenuItem class="javax.swing.JCheckBoxMenuItem" name="maxEffortItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Maximum"/>
- <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
- <ComponentRef name="effortButtonGroup"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="maxEffortItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(maxEffortItem, "menu.maxeffort_item", "&Maximum", true);"/>
- </AuxValues>
- </MenuItem>
- </SubComponents>
- </Menu>
- </SubComponents>
- </Menu>
- <Menu class="javax.swing.JMenu" name="helpMenu">
- <Properties>
- <Property name="text" type="java.lang.String" value="Help"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(helpMenu, "menu.help_menu", "&Help", true);"/>
- </AuxValues>
- <SubComponents>
- <MenuItem class="javax.swing.JMenuItem" name="aboutItem">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="About..."/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="aboutItemActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="localiseButton(aboutItem, "menu.about_item", "&About", true);"/>
- </AuxValues>
- </MenuItem>
- </SubComponents>
- </Menu>
- </SubComponents>
- </Menu>
- </NonVisualComponents>
- <SyntheticProperties>
- <SyntheticProperty name="menuBar" type="java.lang.String" value="theMenuBar"/>
- <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
- </SyntheticProperties>
- <Events>
- <EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="exitForm"/>
- <EventHandler event="windowOpened" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowOpened"/>
- </Events>
- <AuxValues>
- <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-58"/>
- </AuxValues>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
- <SubComponents>
- <Container class="javax.swing.JSplitPane" name="consoleSplitter">
- <Properties>
- <Property name="orientation" type="int" value="0"/>
- <Property name="resizeWeight" type="double" value="1.0"/>
- <Property name="oneTouchExpandable" type="boolean" value="true"/>
- </Properties>
- <Events>
- <EventHandler event="propertyChange" listener="java.beans.PropertyChangeListener" parameters="java.beans.PropertyChangeEvent" handler="consoleSplitterPropertyChange"/>
- </Events>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="0" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
- <SubComponents>
- <Container class="javax.swing.JPanel" name="viewPanel">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
- <JSplitPaneConstraints position="top"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
- <SubComponents>
- <Container class="javax.swing.JPanel" name="emptyPanel">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
- <CardConstraints cardName="EmptyPanel"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
- </Container>
- <Container class="javax.swing.JPanel" name="reportPanel">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
- <CardConstraints cardName="ReportPanel"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
- </Container>
- <Container class="javax.swing.JPanel" name="editProjectPanel">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
- <CardConstraints cardName="EditProjectPanel"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
- <SubComponents>
- <Component class="javax.swing.JLabel" name="jarFileLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Archive or directory:"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="jarFileLabel.setText(L10N.getLocalString("dlg.jarfile_lbl", "Archive or Directory:"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="13" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JTextField" name="jarNameTextField">
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jarNameTextFieldActionPerformed"/>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="addJarButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Add"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addJarButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="addJarButton.setText(L10N.getLocalString("dlg.add_btn", "Add"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="3" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="17" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="jarFileListLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Archives/directories:"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="jarFileListLabel.setText(L10N.getLocalString("dlg.jarlist_lbl", "Archives/Directories:"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="13" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="sourceDirLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Source directory:"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="sourceDirLabel.setText(L10N.getLocalString("dlg.srcfile_lbl", "Source directory:"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="8" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="13" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JTextField" name="srcDirTextField">
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="srcDirTextFieldActionPerformed"/>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="8" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="addSourceDirButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Add"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addSourceDirButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="addSourceDirButton.setText(L10N.getLocalString("dlg.add_btn", "Add"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="3" gridY="8" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="17" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="sourceDirListLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Source directories:"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="sourceDirListLabel.setText(L10N.getLocalString("dlg.srclist_lbl", "Source directories:"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="9" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="13" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="removeJarButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Remove"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="removeJarButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="removeJarButton.setText(L10N.getLocalString("dlg.remove_btn", "Remove"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="3" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="17" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="removeSrcDirButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Remove"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="removeSrcDirButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="removeSrcDirButton.setText(L10N.getLocalString("dlg.remove_btn", "Remove"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="3" gridY="9" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="17" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JSeparator" name="jSeparator1">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="1" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="browseJarButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Browse"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseJarButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="browseJarButton.setText(L10N.getLocalString("dlg.browse_btn", "Browse..."));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="browseSrcDirButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Browse"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseSrcDirButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="browseSrcDirButton.setText(L10N.getLocalString("dlg.browse_btn", "Browse..."));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="2" gridY="8" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="editProjectLabel">
- <Properties>
- <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
- <Color blue="cc" green="0" red="0" type="rgb"/>
- </Property>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="24" style="1"/>
- </Property>
- <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
- <Color blue="ff" green="ff" red="ff" type="rgb"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Project"/>
- <Property name="opaque" type="boolean" value="true"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="editProjectLabel.setText(L10N.getLocalString("dlg.project_lbl", "Project"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="0" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JSeparator" name="jSeparator2">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="7" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="findBugsButton">
- <Properties>
- <Property name="mnemonic" type="int" value="66"/>
- <Property name="text" type="java.lang.String" value="Find Bugs!"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findBugsButtonActionPerformed"/>
- </Events>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="21" gridWidth="4" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JSeparator" name="jSeparator4">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="14" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Container class="javax.swing.JScrollPane" name="jarFileListScrollPane">
- <Properties>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[259, 1]"/>
- </Property>
- </Properties>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="3" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="10" weightX="0.0" weightY="0.4"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JList" name="jarFileList">
- <Properties>
- <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
- <Border info="org.netbeans.modules.form.compat2.border.BevelBorderInfo">
- <BevelBorder bevelType="1"/>
- </Border>
- </Property>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="disableEditKeyBindings(jarFileList);

"/>
- </AuxValues>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="sourceDirListScrollPane">
- <Properties>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[259, 1]"/>
- </Property>
- </Properties>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="9" gridWidth="2" gridHeight="3" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="10" weightX="0.0" weightY="0.1"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JList" name="sourceDirList">
- <Properties>
- <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
- <Border info="org.netbeans.modules.form.compat2.border.BevelBorderInfo">
- <BevelBorder bevelType="1"/>
- </Border>
- </Property>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="disableEditKeyBindings(sourceDirList);"/>
- </AuxValues>
- </Component>
- </SubComponents>
- </Container>
- <Component class="javax.swing.JLabel" name="classpathEntryLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Classpath entry:"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="classpathEntryLabel.setText(L10N.getLocalString("dlg.classpathfile_lbl", "Classpath entry:"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="15" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="3" anchor="13" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="classpathEntryListLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Classpath entries:"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="classpathEntryListLabel.setText(L10N.getLocalString("dlg.classpathlist_lbl", "Classpath entries:"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="16" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="3" anchor="13" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JTextField" name="classpathEntryTextField">
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="15" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="browseClasspathEntryButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Browse"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseClasspathEntryButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="browseClasspathEntryButton.setText(L10N.getLocalString("dlg.browse_btn", "Browse..."));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="2" gridY="15" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="addClasspathEntryButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Add"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addClasspathEntryButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="addClasspathEntryButton.setText(L10N.getLocalString("dlg.add_btn", "Add"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="3" gridY="15" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="removeClasspathEntryButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Remove"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="removeClasspathEntryButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="removeClasspathEntryButton.setText(L10N.getLocalString("dlg.remove_btn", "Remove"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="3" gridY="16" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Container class="javax.swing.JScrollPane" name="classpathEntryListScrollPane">
- <Properties>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[259, 1]"/>
- </Property>
- </Properties>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="16" gridWidth="2" gridHeight="3" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="10" weightX="0.0" weightY="0.1"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JList" name="classpathEntryList">
- <Properties>
- <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
- <Border info="org.netbeans.modules.form.compat2.border.BevelBorderInfo">
- <BevelBorder bevelType="1"/>
- </Border>
- </Property>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="disableEditKeyBindings(classpathEntryList);"/>
- </AuxValues>
- </Component>
- </SubComponents>
- </Container>
- <Component class="javax.swing.JSeparator" name="jSeparator5">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="20" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="sourceUpButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Up"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="sourceUpButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="sourceUpButton.setText(L10N.getLocalString("dlg.up_btn", "Up"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="3" gridY="10" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.2"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="sourceDownButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Down"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="sourceDownButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="sourceDownButton.setText(L10N.getLocalString("dlg.down_btn", "Down"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="-1" gridY="11" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="classpathUpButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Up"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="classpathUpButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="classpathUpButton.setText(L10N.getLocalString("dlg.up_btn", "Up"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="3" gridY="17" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.2"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="classpathDownButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Down"/>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[90, 25]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="classpathDownButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="classpathDownButton.setText(L10N.getLocalString("dlg.down_btn", "Down"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="3" gridY="18" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JPanel" name="bugTreePanel">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
- <CardConstraints cardName="BugTree"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
- <SubComponents>
- <Container class="javax.swing.JSplitPane" name="bugTreeBugDetailsSplitter">
- <Properties>
- <Property name="orientation" type="int" value="0"/>
- <Property name="resizeWeight" type="double" value="1.0"/>
- <Property name="oneTouchExpandable" type="boolean" value="true"/>
- </Properties>
- <Events>
- <EventHandler event="propertyChange" listener="java.beans.PropertyChangeListener" parameters="java.beans.PropertyChangeEvent" handler="bugTreeBugDetailsSplitterPropertyChange"/>
- </Events>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="1" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
- <SubComponents>
- <Container class="javax.swing.JTabbedPane" name="groupByTabbedPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
- <JSplitPaneConstraints position="top"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
- <SubComponents>
- <Container class="javax.swing.JScrollPane" name="byClassScrollPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="By Class">
- <Property name="tabTitle" type="java.lang.String" value="By Class"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JTree" name="byClassBugTree">
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="byPackageScrollPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="By Package">
- <Property name="tabTitle" type="java.lang.String" value="By Package"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JTree" name="byPackageBugTree">
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="byBugTypeScrollPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="By Bug Type">
- <Property name="tabTitle" type="java.lang.String" value="By Bug Type"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JTree" name="byBugTypeBugTree">
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="byBugCategoryScrollPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="By Category Type">
- <Property name="tabTitle" type="java.lang.String" value="By Category Type"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JTree" name="byBugCategoryBugTree">
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="bySummary">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="Summary">
- <Property name="tabTitle" type="java.lang.String" value="Summary"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JEditorPane" name="bugSummaryEditorPane">
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JTabbedPane" name="bugDetailsTabbedPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
- <JSplitPaneConstraints position="bottom"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
- <SubComponents>
- <Container class="javax.swing.JScrollPane" name="bugDescriptionScrollPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="Details">
- <Property name="tabTitle" type="java.lang.String" value="Details"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JEditorPane" name="bugDescriptionEditorPane">
- <Properties>
- <Property name="editable" type="boolean" value="false"/>
- </Properties>
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="sourceTextAreaScrollPane">
- <Properties>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[22, 180]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[0, 100]"/>
- </Property>
- </Properties>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="Source code">
- <Property name="tabTitle" type="java.lang.String" value="Source code"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JTextArea" name="sourceTextArea">
- <Properties>
- <Property name="editable" type="boolean" value="false"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Monospaced" size="12" style="0"/>
- </Property>
- <Property name="enabled" type="boolean" value="false"/>
- </Properties>
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="annotationTextAreaScrollPane">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
- <JTabbedPaneConstraints tabName="Annotations">
- <Property name="tabTitle" type="java.lang.String" value="Annotations"/>
- </JTabbedPaneConstraints>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JTextArea" name="annotationTextArea">
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- </SubComponents>
- </Container>
- </SubComponents>
- </Container>
- </SubComponents>
- </Container>
- </SubComponents>
- </Container>
- <Container class="javax.swing.JScrollPane" name="consoleScrollPane">
- <Properties>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[22, 100]"/>
- </Property>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[0, 100]"/>
- </Property>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePre" type="java.lang.String" value="{ 
 equalizeControls( new JComponent[] 
 {
 addJarButton,
 addSourceDirButton,
 addClasspathEntryButton,
 removeJarButton,
 removeSrcDirButton,
 removeClasspathEntryButton,
 browseJarButton,
 browseSrcDirButton,
 browseClasspathEntryButton,
 sourceUpButton,
 sourceD [...]
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
- <JSplitPaneConstraints position="bottom"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
- <SubComponents>
- <Component class="javax.swing.JTextArea" name="consoleMessageArea">
- <Properties>
- <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
- <Color blue="cc" green="cc" red="cc" type="rgb"/>
- </Property>
- <Property name="editable" type="boolean" value="false"/>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Monospaced" size="12" style="0"/>
- </Property>
- <Property name="autoscrolls" type="boolean" value="false"/>
- <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[0, 0]"/>
- </Property>
- </Properties>
- <Events>
- <EventHandler event="focusGained" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="focusGainedHandler"/>
- </Events>
- </Component>
- </SubComponents>
- </Container>
- </SubComponents>
- </Container>
- <Component class="javax.swing.JLabel" name="urlLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="FindBugs - http://findbugs.sourceforge.net/"/>
- </Properties>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="2" insetsBottom="2" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Container class="javax.swing.JPanel" name="jPanel1">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="0" insetsBottom="2" insetsRight="2" anchor="14" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
- <SubComponents>
- <Component class="javax.swing.JLabel" name="logoLabel">
- </Component>
- <Component class="javax.swing.JLabel" name="growBoxSpacer">
- <Properties>
- <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[16, 16]"/>
- </Property>
- </Properties>
- </Component>
- </SubComponents>
- </Container>
- </SubComponents>
-</Form>
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/FindBugsFrame.java b/src/obsolete/edu/umd/cs/findbugs/gui/FindBugsFrame.java
deleted file mode 100644
index d35333b..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/FindBugsFrame.java
+++ /dev/null
@@ -1,3981 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2003-2005, University of Maryland
- * Copyright (C) 2004 Dave Brosius <dbrosius at users.sourceforge.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * FindBugsFrame.java
- *
- * Created on March 30, 2003, 12:05 PM
- */
-
-package edu.umd.cs.findbugs.gui;
-
-import java.awt.BorderLayout;
-import java.awt.CardLayout;
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Cursor;
-import java.awt.Dimension;
-import java.awt.Event;
-import java.awt.Font;
-import java.awt.Graphics;
-import java.awt.HeadlessException;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.Toolkit;
-import java.awt.datatransfer.Clipboard;
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.StringSelection;
-import java.awt.datatransfer.Transferable;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyEvent;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Serializable;
-import java.io.StringReader;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.TreeSet;
-
-import javax.swing.AbstractButton;
-import javax.swing.ButtonGroup;
-import javax.swing.DefaultListModel;
-import javax.swing.ImageIcon;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JComponent;
-import javax.swing.JDialog;
-import javax.swing.JFileChooser;
-import javax.swing.JList;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JRadioButton;
-import javax.swing.JScrollPane;
-import javax.swing.JSplitPane;
-import javax.swing.JTextField;
-import javax.swing.JTree;
-import javax.swing.JViewport;
-import javax.swing.KeyStroke;
-import javax.swing.ListModel;
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.filechooser.FileFilter;
-import javax.swing.text.BadLocationException;
-import javax.swing.text.DefaultHighlighter;
-import javax.swing.text.Highlighter;
-import javax.swing.text.JTextComponent;
-import javax.swing.text.Position;
-import javax.swing.text.View;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.TreePath;
-import javax.swing.tree.TreeSelectionModel;
-
-import edu.umd.cs.findbugs.cloud.SignInCancelledException;
-import org.dom4j.DocumentException;
-
-import edu.umd.cs.findbugs.BugAnnotation;
-import edu.umd.cs.findbugs.BugAnnotationWithSourceLines;
-import edu.umd.cs.findbugs.BugInstance;
-import edu.umd.cs.findbugs.BugPattern;
-import edu.umd.cs.findbugs.Detector;
-import edu.umd.cs.findbugs.DetectorFactoryCollection;
-import edu.umd.cs.findbugs.FindBugs;
-import edu.umd.cs.findbugs.FindBugsCommandLine;
-import edu.umd.cs.findbugs.I18N;
-import edu.umd.cs.findbugs.L10N;
-import edu.umd.cs.findbugs.Project;
-import edu.umd.cs.findbugs.ShowHelp;
-import edu.umd.cs.findbugs.SourceLineAnnotation;
-import edu.umd.cs.findbugs.SystemProperties;
-import edu.umd.cs.findbugs.annotations.SuppressWarnings;
-import edu.umd.cs.findbugs.ba.SourceFile;
-import edu.umd.cs.findbugs.ba.SourceFinder;
-import edu.umd.cs.findbugs.config.AnalysisFeatureSetting;
-import edu.umd.cs.findbugs.config.ProjectFilterSettings;
-import edu.umd.cs.findbugs.config.UserPreferences;
-import edu.umd.cs.findbugs.config.CommandLine.HelpRequestedException;
-import edu.umd.cs.findbugs.log.ConsoleLogger;
-import edu.umd.cs.findbugs.log.LogSync;
-import edu.umd.cs.findbugs.log.Logger;
-
-/**
- * The main GUI frame for FindBugs.
- *
- * @author David Hovemeyer
- */
-public final class FindBugsFrame extends javax.swing.JFrame implements LogSync {
- /**
- *
- */
- private static final int fontSize = 12;
- /**
- *
- */
- private static final Font SOURCE_FONT = new java.awt.Font("Monospaced", 0, fontSize);
- private static final Font JTREE_FONT = new java.awt.Font("SansSerif", 0, fontSize);
-
- /**
- *
- */
- private static final Font LABEL_FONT = new java.awt.Font("Dialog", 1, 2*fontSize);
-
- /**
- *
- */
- private static final Font BUTTON_FONT = new java.awt.Font("Dialog", 0, fontSize);
-
- private static final long serialVersionUID = 1L;
-
- /* ----------------------------------------------------------------------
- * Helper classes
- * ---------------------------------------------------------------------- */
- static final Color HIGH_PRIORITY_COLOR = new Color(0xff0000);
- static final Color NORMAL_PRIORITY_COLOR = new Color(0x9f0000);
- static final Color LOW_PRIORITY_COLOR = Color.BLACK;
- static final Color EXP_PRIORITY_COLOR = Color.BLACK;
-
- /**
- * Tree node type for BugInstances.
- * We use this instead of plain DefaultMutableTreeNodes in order to
- * get more control over the exact text that is shown in the tree.
- */
- private class BugTreeNode extends DefaultMutableTreeNode {
- private static final long serialVersionUID = 1L;
- private int count;
-
- public BugTreeNode(BugInstance bugInstance) {
- super(bugInstance);
- count = -1;
- }
-
- public void setCount(int count) {
- this.count = count;
- }
-
- @Override
- public String toString() {
- try {
- BugInstance bugInstance = (BugInstance) getUserObject();
- StringBuilder result = new StringBuilder();
-
- if (count >= 0) {
- result.append(count);
- result.append(": ");
- }
-
- if (bugInstance.isExperimental())
- result.append(L10N.getLocalString("msg.exp_txt", "EXP: "));
-
- result.append(fullDescriptionsItem.isSelected() ? bugInstance.getMessage() : bugInstance.toString());
-
- return result.toString();
- } catch (Exception e) {
- return MessageFormat.format(L10N.getLocalString("msg.errorformatting_txt", "Error formatting message for bug: "), new Object[]{e.toString()});
- }
- }
- }
-
- /**
- * Compare BugInstance class names.
- * This is useful for grouping bug instances by class.
- * Note that all instances with the same class name will compare
- * as equal.
- */
- private static class BugInstanceClassComparator implements Comparator<BugInstance> {
- public int compare(BugInstance lhs, BugInstance rhs) {
- return lhs.getPrimaryClass().compareTo(rhs.getPrimaryClass());
- }
- }
-
- /**
- * The instance of BugInstanceClassComparator.
- */
- private static final Comparator<BugInstance> bugInstanceClassComparator = new BugInstanceClassComparator();
-
- /**
- * Compare BugInstance package names.
- * This is useful for grouping bug instances by package.
- * Note that all instances with the same package name will compare
- * as equal.
- */
- private static class BugInstancePackageComparator implements Comparator<BugInstance>, Serializable {
- private static final long serialVersionUID = 1L;
- public int compare(BugInstance lhs, BugInstance rhs) {
- return lhs.getPrimaryClass().getPackageName().compareTo(rhs.getPrimaryClass().getPackageName());
- }
- }
-
- /**
- * The instance of BugInstancePackageComparator.
- */
- private static final Comparator<BugInstance> bugInstancePackageComparator = new BugInstancePackageComparator();
-
- /**
- * Compare BugInstance bug types.
- * This is useful for grouping bug instances by bug type.
- * Note that all instances with the same bug type will compare
- * as equal.
- */
- private static class BugInstanceTypeComparator implements Comparator<BugInstance>, Serializable {
- private static final long serialVersionUID = 1L;
- public int compare(BugInstance lhs, BugInstance rhs) {
- String lhsString = lhs.toString();
- String rhsString = rhs.toString();
- return lhsString.substring(0, lhsString.indexOf(':')).compareTo(rhsString.substring(0, rhsString.indexOf(':')));
- }
- }
-
- /**
- * The instance of BugInstanceTypeComparator.
- */
- private static final Comparator<BugInstance> bugInstanceTypeComparator = new BugInstanceTypeComparator();
-
- /**
- * Compare BugInstance bug categories.
- * This is useful for grouping bug instances by bug category.
- * Note that all instances with the same bug category will compare
- * as equal.
- */
- private static class BugInstanceCategoryComparator implements Comparator<BugInstance>, Serializable {
- private static final long serialVersionUID = 1L;
-
- public int compare(BugInstance lhs, BugInstance rhs) {
- return getCategory(lhs).compareTo(getCategory(rhs));
- }
-
- private String getCategory(BugInstance warning) {
- BugPattern bugPattern = warning.getBugPattern();
- if (bugPattern == null) {
- if (FindBugs.DEBUG)
- System.out.println("Unknown bug pattern for bug type: " + warning.getType());
- return "";
- } else {
- return bugPattern.getCategory();
- }
- }
- }
-
- /**
- * The instance of BugInstanceCategoryComparator.
- */
- private static final Comparator<BugInstance> bugInstanceCategoryComparator = new BugInstanceCategoryComparator();
-
- /**
- * Two-level comparison of bug instances by class name and
- * BugInstance natural ordering.
- */
- private static class BugInstanceByClassComparator implements Comparator<BugInstance>, Serializable {
- private static final long serialVersionUID = 1L;
- public int compare(BugInstance a, BugInstance b) {
- int cmp = bugInstanceClassComparator.compare(a, b);
- if (cmp != 0)
- return cmp;
- return a.compareTo(b);
- }
- }
-
- /**
- * The instance of BugInstanceByClassComparator.
- */
- private static final Comparator<BugInstance> bugInstanceByClassComparator = new FindBugsFrame.BugInstanceByClassComparator();
-
- /**
- * Two-level comparison of bug instances by package and
- * BugInstance natural ordering.
- */
- private static class BugInstanceByPackageComparator implements Comparator<BugInstance> {
- public int compare(BugInstance a, BugInstance b) {
- int cmp = bugInstancePackageComparator.compare(a, b);
- if (cmp != 0)
- return cmp;
- return a.compareTo(b);
- }
- }
-
- /**
- * The instance of BugInstanceByPackageComparator.
- */
- private static final Comparator<BugInstance> bugInstanceByPackageComparator = new FindBugsFrame.BugInstanceByPackageComparator();
-
- /**
- * Two-level comparison of bug instances by bug type and
- * BugInstance natural ordering.
- */
- private static class BugInstanceByTypeComparator implements Comparator<BugInstance>, Serializable {
- private static final long serialVersionUID = 1L;
- public int compare(BugInstance a, BugInstance b) {
- int cmp = bugInstanceTypeComparator.compare(a, b);
- if (cmp != 0)
- return cmp;
- return a.compareTo(b);
- }
- }
-
- /**
- * The instance of BugTypeByTypeComparator.
- */
- private static final Comparator<BugInstance> bugInstanceByTypeComparator = new FindBugsFrame.BugInstanceByTypeComparator();
-
- /**
- * Two-level comparison of bug instances by bug category and
- * BugInstance natural ordering.
- */
- private static class BugInstanceByCategoryComparator implements Comparator<BugInstance>, Serializable {
- private static final long serialVersionUID = 1L;
- public int compare(BugInstance a, BugInstance b) {
- int cmp = bugInstanceCategoryComparator.compare(a, b);
- if (cmp != 0)
- return cmp;
- return a.compareTo(b);
- }
- }
-
- /**
- * The instance of BugTypeByCategoryComparator.
- */
- private static final Comparator<BugInstance> bugInstanceByCategoryComparator = new FindBugsFrame.BugInstanceByCategoryComparator();
-
- /**
- * Swing FileFilter class for file selection dialogs for FindBugs project files.
- */
- private static class ProjectFileFilter extends FileFilter {
- @Override
- public boolean accept(File file) {
- return file.isDirectory() || file.getName().endsWith(".fb");
- }
-
- @Override
- public String getDescription() {
- return L10N.getLocalString("dlg.findbugsprojects_lbl", "FindBugs projects (*.fb)");
- }
- }
-
- /**
- * The instance of ProjectFileFilter.
- */
- private static final FileFilter projectFileFilter = new ProjectFileFilter();
-
- /**
- * Swing FileFilter for choosing an auxiliary classpath entry.
- * Both Jar files and directories can be chosen.
- */
- private static class AuxClasspathEntryFileFilter extends FileFilter {
- @Override
- public boolean accept(File file) {
- return file.isDirectory() || file.getName().endsWith(".jar");
- }
-
- @Override
- public String getDescription() {
- return L10N.getLocalString("dlg.jarsanddirectories_lbl", "Jar files and directories");
- }
- }
-
- /**
- * The instance of AuxClasspathEntryFileFilter.
- */
- private static final FileFilter auxClasspathEntryFileFilter = new AuxClasspathEntryFileFilter();
-
- /**
- * Swing FileFilter for choosing XML saved bug files.
- */
- private static class XMLFileFilter extends FileFilter {
- @Override
- public boolean accept(File file) {
- return file.isDirectory() || file.getName().endsWith(".xml");
- }
-
- @Override
- public String getDescription() {
- return L10N.getLocalString("dlg.xmlsavedbugs_lbl", "XML saved bug files");
- }
- }
-
- /**
- * The instance of XMLFileFilter.
- */
- private static final FileFilter xmlFileFilter = new XMLFileFilter();
-
- /**
- * Set of archive file extensions.
- */
- private static final HashSet<String> archiveExtensionSet = new HashSet<String>();
-
- static {
- archiveExtensionSet.add(".jar");
- archiveExtensionSet.add(".zip");
- archiveExtensionSet.add(".ear");
- archiveExtensionSet.add(".war");
- archiveExtensionSet.add(".sar");
- }
-
- /**
- * File filter for choosing archives and directories.
- */
- private static class ArchiveAndDirectoryFilter extends FileFilter {
- @Override
- public boolean accept(File file) {
- if (file.isDirectory())
- return true;
-
- String fileName = file.getName();
- int dot = fileName.lastIndexOf('.');
- if (dot < 0)
- return false;
- String extension = fileName.substring(dot);
- return archiveExtensionSet.contains(extension);
- }
-
- @Override
- public String getDescription() {
- return L10N.getLocalString("dlg.javaarchives_lbl", "Java archives (*.jar,*.zip,*.ear,*.war,*.sar)");
- }
- }
-
- /**
- * The instance of ArchiveAndDirectoryFilter.
- */
- private static final FileFilter archiveAndDirectoryFilter = new ArchiveAndDirectoryFilter();
-
- /* ----------------------------------------------------------------------
- * Constants
- * ---------------------------------------------------------------------- */
-
- static final String GROUP_BY_CLASS = "By class";
- static final String GROUP_BY_PACKAGE = "By package";
- static final String GROUP_BY_BUG_TYPE = "By bug type";
- static final String GROUP_BY_BUG_CATEGORY="By bug category";
- private static final String[] GROUP_BY_ORDER_LIST = {
- GROUP_BY_CLASS, GROUP_BY_PACKAGE, GROUP_BY_BUG_TYPE, GROUP_BY_BUG_CATEGORY
- };
-
- /**
- * A fudge value required in our hack to get the REAL maximum
- * divider location for a JSplitPane. Experience suggests that
- * the value "1" would work here, but setting it a little higher
- * makes the code a bit more robust.
- */
- private static final int DIVIDER_FUDGE = 3;
-
- private static final boolean BUG_COUNT = SystemProperties.getBoolean("findbugs.gui.bugCount");
-
- /* ----------------------------------------------------------------------
- * Member fields
- * ---------------------------------------------------------------------- */
- Component selectedComponent = null;
-
- /* ----------------------------------------------------------------------
- * Constructor
- * ---------------------------------------------------------------------- */
-
- /**
- * Creates new form FindBugsFrame.
- */
- public FindBugsFrame() {
-
- UserPreferences prefs = UserPreferences.getUserPreferences();
- prefs.read();
-
- String dirProp = SystemProperties.getProperty("user.dir");
-
- if (dirProp != null) {
- currentDirectory = new File(dirProp);
- }
-
- initComponents();
- postInitComponents();
- }
-
- /* ----------------------------------------------------------------------
- * Component initialization and event handlers
- * ---------------------------------------------------------------------- */
-
- /**
- * This method is called from within the constructor to
- * initialize the form.
- * WARNING: Do NOT modify this code. The content of this method is
- * always regenerated by the Form Editor.
- */
- private void initComponents() {//GEN-BEGIN:initComponents
- java.awt.GridBagConstraints gridBagConstraints;
-
- priorityButtonGroup = new javax.swing.ButtonGroup();
- effortButtonGroup = new javax.swing.ButtonGroup();
- //consoleSplitter = new javax.swing.JSplitPane();
- viewPanel = new javax.swing.JPanel();
- emptyPanel = new javax.swing.JPanel();
- reportPanel = new javax.swing.JPanel();
- editProjectPanel = new javax.swing.JPanel();
- jarFileLabel = new javax.swing.JLabel();
- jarNameTextField = new javax.swing.JTextField();
- addJarButton = new javax.swing.JButton();
- jarFileListLabel = new javax.swing.JLabel();
- sourceDirLabel = new javax.swing.JLabel();
- srcDirTextField = new javax.swing.JTextField();
- addSourceDirButton = new javax.swing.JButton();
- sourceDirListLabel = new javax.swing.JLabel();
- removeJarButton = new javax.swing.JButton();
- removeSrcDirButton = new javax.swing.JButton();
- jSeparator1 = new javax.swing.JSeparator();
- browseJarButton = new javax.swing.JButton();
- browseSrcDirButton = new javax.swing.JButton();
- editProjectLabel = new javax.swing.JLabel();
- jSeparator2 = new javax.swing.JSeparator();
- findBugsButton = new javax.swing.JButton();
- jSeparator4 = new javax.swing.JSeparator();
- jarFileListScrollPane = new javax.swing.JScrollPane();
- jarFileList = new javax.swing.JList();
- sourceDirListScrollPane = new javax.swing.JScrollPane();
- sourceDirList = new javax.swing.JList();
- classpathEntryLabel = new javax.swing.JLabel();
- classpathEntryListLabel = new javax.swing.JLabel();
- classpathEntryTextField = new javax.swing.JTextField();
- browseClasspathEntryButton = new javax.swing.JButton();
- addClasspathEntryButton = new javax.swing.JButton();
- removeClasspathEntryButton = new javax.swing.JButton();
- classpathEntryListScrollPane = new javax.swing.JScrollPane();
- classpathEntryList = new javax.swing.JList();
- jSeparator5 = new javax.swing.JSeparator();
- sourceUpButton = new javax.swing.JButton();
- sourceDownButton = new javax.swing.JButton();
- classpathUpButton = new javax.swing.JButton();
- classpathDownButton = new javax.swing.JButton();
- bugTreePanel = new javax.swing.JPanel();
- bugTreeBugDetailsSplitter = new javax.swing.JSplitPane();
- groupByTabbedPane = new javax.swing.JTabbedPane();
- byClassScrollPane = new javax.swing.JScrollPane();
- byClassBugTree = new javax.swing.JTree();
- byClassBugTree.setFont(JTREE_FONT);
- byPackageScrollPane = new javax.swing.JScrollPane();
- byPackageBugTree = new javax.swing.JTree();
- byPackageBugTree.setFont(JTREE_FONT);
- byBugTypeScrollPane = new javax.swing.JScrollPane();
- byBugTypeBugTree = new javax.swing.JTree();
- byBugTypeBugTree.setFont(JTREE_FONT);
- byBugCategoryScrollPane = new javax.swing.JScrollPane();
- byBugCategoryBugTree = new javax.swing.JTree();
- byBugCategoryBugTree.setFont(JTREE_FONT);
- bySummary = new javax.swing.JScrollPane();
- bugSummaryEditorPane = new javax.swing.JEditorPane();
- bugDetailsTabbedPane = new javax.swing.JTabbedPane();
- bugDescriptionScrollPane = new javax.swing.JScrollPane();
- bugDescriptionEditorPane = new javax.swing.JEditorPane();
- sourceTextAreaScrollPane = new javax.swing.JScrollPane();
- sourceTextArea = new javax.swing.JTextArea();
- annotationTextAreaScrollPane = new javax.swing.JScrollPane();
- annotationTextArea = new javax.swing.JTextArea();
- urlLabel = new javax.swing.JLabel();
- jPanel1 = new javax.swing.JPanel();
- logoLabel = new javax.swing.JLabel();
- growBoxSpacer = new javax.swing.JLabel();
- theMenuBar = new javax.swing.JMenuBar();
- fileMenu = new javax.swing.JMenu();
- newProjectItem = new javax.swing.JMenuItem();
- openProjectItem = new javax.swing.JMenuItem();
- recentProjectsMenu = new javax.swing.JMenu();
- jSeparator9 = new javax.swing.JSeparator();
- closeProjectItem = new javax.swing.JMenuItem();
- saveProjectItem = new javax.swing.JMenuItem();
- saveProjectAsItem = new javax.swing.JMenuItem();
- reloadProjectItem = new javax.swing.JMenuItem();
- jSeparator3 = new javax.swing.JSeparator();
- loadBugsItem = new javax.swing.JMenuItem();
- saveBugsItem = new javax.swing.JMenuItem();
- jSeparator6 = new javax.swing.JSeparator();
- exitItem = new javax.swing.JMenuItem();
- editMenu = new javax.swing.JMenu();
- cutItem = new javax.swing.JMenuItem();
- copyItem = new javax.swing.JMenuItem();
- pasteItem = new javax.swing.JMenuItem();
- jSeparator10 = new javax.swing.JSeparator();
- selectAllItem = new javax.swing.JMenuItem();
- viewMenu = new javax.swing.JMenu();
- viewBugDetailsItem = new javax.swing.JCheckBoxMenuItem();
- fullDescriptionsItem = new javax.swing.JCheckBoxMenuItem();
- jSeparator7 = new javax.swing.JSeparator();
- filterWarningsMenu = new javax.swing.JMenu();
- expPriorityButton = new javax.swing.JRadioButtonMenuItem();
- lowPriorityButton = new javax.swing.JRadioButtonMenuItem();
- mediumPriorityButton = new javax.swing.JRadioButtonMenuItem();
- highPriorityButton = new javax.swing.JRadioButtonMenuItem();
- jSeparator11 = new javax.swing.JSeparator();
- jSeparator8 = new javax.swing.JSeparator();
- viewProjectItem = new javax.swing.JRadioButtonMenuItem();
- viewBugsItem = new javax.swing.JRadioButtonMenuItem();
- settingsMenu = new javax.swing.JMenu();
- configureDetectorsItem = new javax.swing.JMenuItem();
- effortMenu = new javax.swing.JMenu();
- minEffortItem = new javax.swing.JCheckBoxMenuItem();
- normalEffortItem = new javax.swing.JCheckBoxMenuItem();
- maxEffortItem = new javax.swing.JCheckBoxMenuItem();
- helpMenu = new javax.swing.JMenu();
- aboutItem = new javax.swing.JMenuItem();
-
- getContentPane().setLayout(new java.awt.GridBagLayout());
-
- addWindowListener(new java.awt.event.WindowAdapter() {
- @Override
- public void windowClosing(java.awt.event.WindowEvent evt) {
- exitForm(evt);
- }
- @Override
- public void windowOpened(java.awt.event.WindowEvent evt) {
- formWindowOpened(evt);
- }
- });
-
- viewPanel.setLayout(new java.awt.CardLayout());
-
- viewPanel.add(emptyPanel, "EmptyPanel");
-
- viewPanel.add(reportPanel, "ReportPanel");
-
- editProjectPanel.setLayout(new java.awt.GridBagLayout());
-
- jarFileLabel.setFont(BUTTON_FONT);
- jarFileLabel.setText("Archive or directory:");
- jarFileLabel.setText(L10N.getLocalString("dlg.jarfile_lbl", "Archive or Directory:"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 2;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(jarFileLabel, gridBagConstraints);
-
- jarNameTextField.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- jarNameTextFieldActionPerformed(evt);
- }
- });
- jarNameTextField.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 2;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- gridBagConstraints.weightx = 1.0;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
- editProjectPanel.add(jarNameTextField, gridBagConstraints);
-
- addJarButton.setFont(BUTTON_FONT);
- addJarButton.setText("Add");
- addJarButton.setMaximumSize(new java.awt.Dimension(90, 25));
- addJarButton.setMinimumSize(new java.awt.Dimension(90, 25));
- addJarButton.setPreferredSize(new java.awt.Dimension(90, 25));
- addJarButton.setText(L10N.getLocalString("dlg.add_btn", "Add"));
- addJarButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- addJarButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 3;
- gridBagConstraints.gridy = 2;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(addJarButton, gridBagConstraints);
-
- jarFileListLabel.setFont(BUTTON_FONT);
- jarFileListLabel.setText("Archives/directories:");
- jarFileListLabel.setText(L10N.getLocalString("dlg.jarlist_lbl", "Archives/Directories:"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(jarFileListLabel, gridBagConstraints);
-
- sourceDirLabel.setFont(BUTTON_FONT);
- sourceDirLabel.setText("Source directory:");
- sourceDirLabel.setText(L10N.getLocalString("dlg.srcfile_lbl", "Source directory:"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 8;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(sourceDirLabel, gridBagConstraints);
-
- srcDirTextField.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- srcDirTextFieldActionPerformed(evt);
- }
- });
- srcDirTextField.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 8;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- gridBagConstraints.weightx = 1.0;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
- editProjectPanel.add(srcDirTextField, gridBagConstraints);
-
- addSourceDirButton.setFont(BUTTON_FONT);
- addSourceDirButton.setText("Add");
- addSourceDirButton.setMaximumSize(new java.awt.Dimension(90, 25));
- addSourceDirButton.setMinimumSize(new java.awt.Dimension(90, 25));
- addSourceDirButton.setPreferredSize(new java.awt.Dimension(90, 25));
- addSourceDirButton.setText(L10N.getLocalString("dlg.add_btn", "Add"));
- addSourceDirButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- addSourceDirButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 3;
- gridBagConstraints.gridy = 8;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(addSourceDirButton, gridBagConstraints);
-
- sourceDirListLabel.setFont(BUTTON_FONT);
- sourceDirListLabel.setText("Source directories:");
- sourceDirListLabel.setText(L10N.getLocalString("dlg.srclist_lbl", "Source directories:"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 9;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(sourceDirListLabel, gridBagConstraints);
-
- removeJarButton.setFont(BUTTON_FONT);
- removeJarButton.setText("Remove");
- removeJarButton.setMaximumSize(new java.awt.Dimension(90, 25));
- removeJarButton.setMinimumSize(new java.awt.Dimension(90, 25));
- removeJarButton.setPreferredSize(new java.awt.Dimension(90, 25));
- removeJarButton.setText(L10N.getLocalString("dlg.remove_btn", "Remove"));
- removeJarButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- removeJarButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 3;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(removeJarButton, gridBagConstraints);
-
- removeSrcDirButton.setFont(BUTTON_FONT);
- removeSrcDirButton.setText("Remove");
- removeSrcDirButton.setMaximumSize(new java.awt.Dimension(90, 25));
- removeSrcDirButton.setMinimumSize(new java.awt.Dimension(90, 25));
- removeSrcDirButton.setPreferredSize(new java.awt.Dimension(90, 25));
- removeSrcDirButton.setText(L10N.getLocalString("dlg.remove_btn", "Remove"));
- removeSrcDirButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- removeSrcDirButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 3;
- gridBagConstraints.gridy = 9;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(removeSrcDirButton, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 1;
- gridBagConstraints.gridwidth = 4;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
- editProjectPanel.add(jSeparator1, gridBagConstraints);
-
- browseJarButton.setFont(BUTTON_FONT);
- browseJarButton.setText("Browse");
- browseJarButton.setMaximumSize(new java.awt.Dimension(90, 25));
- browseJarButton.setMinimumSize(new java.awt.Dimension(90, 25));
- browseJarButton.setPreferredSize(new java.awt.Dimension(90, 25));
- browseJarButton.setText(L10N.getLocalString("dlg.browse_btn", "Browse..."));
- browseJarButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- browseJarButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 2;
- gridBagConstraints.gridy = 2;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(browseJarButton, gridBagConstraints);
-
- browseSrcDirButton.setFont(BUTTON_FONT);
- browseSrcDirButton.setText("Browse");
- browseSrcDirButton.setMaximumSize(new java.awt.Dimension(90, 25));
- browseSrcDirButton.setMinimumSize(new java.awt.Dimension(90, 25));
- browseSrcDirButton.setPreferredSize(new java.awt.Dimension(90, 25));
- browseSrcDirButton.setText(L10N.getLocalString("dlg.browse_btn", "Browse..."));
- browseSrcDirButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- browseSrcDirButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 2;
- gridBagConstraints.gridy = 8;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(browseSrcDirButton, gridBagConstraints);
-
- editProjectLabel.setBackground(new java.awt.Color(0, 0, 204));
- editProjectLabel.setFont(LABEL_FONT);
- editProjectLabel.setForeground(new java.awt.Color(255, 255, 255));
- editProjectLabel.setText("Project");
- editProjectLabel.setOpaque(true);
- editProjectLabel.setText(L10N.getLocalString("dlg.project_lbl", "Project"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 0;
- gridBagConstraints.gridwidth = 4;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- editProjectPanel.add(editProjectLabel, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 7;
- gridBagConstraints.gridwidth = 4;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
- editProjectPanel.add(jSeparator2, gridBagConstraints);
-
- findBugsButton.setMnemonic('B');
- findBugsButton.setText("Find Bugs!");
- findBugsButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- findBugsButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 21;
- gridBagConstraints.gridwidth = 4;
- gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
- editProjectPanel.add(findBugsButton, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 14;
- gridBagConstraints.gridwidth = 4;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
- editProjectPanel.add(jSeparator4, gridBagConstraints);
-
- jarFileListScrollPane.setPreferredSize(new java.awt.Dimension(259, 1));
- jarFileList.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.LOWERED));
- jarFileList.setFont(BUTTON_FONT);
- disableEditKeyBindings(jarFileList);
-
- jarFileList.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- jarFileListScrollPane.setViewportView(jarFileList);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.gridwidth = 2;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.weighty = 0.4;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(jarFileListScrollPane, gridBagConstraints);
-
- sourceDirListScrollPane.setPreferredSize(new java.awt.Dimension(259, 1));
- sourceDirList.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.LOWERED));
- sourceDirList.setFont(BUTTON_FONT);
- disableEditKeyBindings(sourceDirList);
- sourceDirList.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- sourceDirListScrollPane.setViewportView(sourceDirList);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 9;
- gridBagConstraints.gridwidth = 2;
- gridBagConstraints.gridheight = 3;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.weighty = 0.1;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(sourceDirListScrollPane, gridBagConstraints);
-
- classpathEntryLabel.setFont(BUTTON_FONT);
- classpathEntryLabel.setText("Classpath entry:");
- classpathEntryLabel.setText(L10N.getLocalString("dlg.classpathfile_lbl", "Classpath entry:"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 15;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
- gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 3);
- editProjectPanel.add(classpathEntryLabel, gridBagConstraints);
-
- classpathEntryListLabel.setFont(BUTTON_FONT);
- classpathEntryListLabel.setText("Classpath entries:");
- classpathEntryListLabel.setText(L10N.getLocalString("dlg.classpathlist_lbl", "Classpath entries:"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 16;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
- gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 3);
- editProjectPanel.add(classpathEntryListLabel, gridBagConstraints);
-
- classpathEntryTextField.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 15;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
- editProjectPanel.add(classpathEntryTextField, gridBagConstraints);
-
- browseClasspathEntryButton.setFont(BUTTON_FONT);
- browseClasspathEntryButton.setText("Browse");
- browseClasspathEntryButton.setMaximumSize(new java.awt.Dimension(90, 25));
- browseClasspathEntryButton.setMinimumSize(new java.awt.Dimension(90, 25));
- browseClasspathEntryButton.setPreferredSize(new java.awt.Dimension(90, 25));
- browseClasspathEntryButton.setText(L10N.getLocalString("dlg.browse_btn", "Browse..."));
- browseClasspathEntryButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- browseClasspathEntryButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 2;
- gridBagConstraints.gridy = 15;
- editProjectPanel.add(browseClasspathEntryButton, gridBagConstraints);
-
- addClasspathEntryButton.setFont(BUTTON_FONT);
- addClasspathEntryButton.setText("Add");
- addClasspathEntryButton.setMaximumSize(new java.awt.Dimension(90, 25));
- addClasspathEntryButton.setMinimumSize(new java.awt.Dimension(90, 25));
- addClasspathEntryButton.setPreferredSize(new java.awt.Dimension(90, 25));
- addClasspathEntryButton.setText(L10N.getLocalString("dlg.add_btn", "Add"));
- addClasspathEntryButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- addClasspathEntryButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 3;
- gridBagConstraints.gridy = 15;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
- editProjectPanel.add(addClasspathEntryButton, gridBagConstraints);
-
- removeClasspathEntryButton.setFont(BUTTON_FONT);
- removeClasspathEntryButton.setText("Remove");
- removeClasspathEntryButton.setMaximumSize(new java.awt.Dimension(90, 25));
- removeClasspathEntryButton.setMinimumSize(new java.awt.Dimension(90, 25));
- removeClasspathEntryButton.setPreferredSize(new java.awt.Dimension(90, 25));
- removeClasspathEntryButton.setText(L10N.getLocalString("dlg.remove_btn", "Remove"));
- removeClasspathEntryButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- removeClasspathEntryButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 3;
- gridBagConstraints.gridy = 16;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
- editProjectPanel.add(removeClasspathEntryButton, gridBagConstraints);
-
- classpathEntryListScrollPane.setPreferredSize(new java.awt.Dimension(259, 1));
- classpathEntryList.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.LOWERED));
- classpathEntryList.setFont(BUTTON_FONT);
- disableEditKeyBindings(classpathEntryList);
- classpathEntryList.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- classpathEntryListScrollPane.setViewportView(classpathEntryList);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 16;
- gridBagConstraints.gridwidth = 2;
- gridBagConstraints.gridheight = 3;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.weighty = 0.1;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- editProjectPanel.add(classpathEntryListScrollPane, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 20;
- gridBagConstraints.gridwidth = 4;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 0);
- editProjectPanel.add(jSeparator5, gridBagConstraints);
-
- sourceUpButton.setFont(BUTTON_FONT);
- sourceUpButton.setText("Up");
- sourceUpButton.setMaximumSize(new java.awt.Dimension(90, 25));
- sourceUpButton.setMinimumSize(new java.awt.Dimension(90, 25));
- sourceUpButton.setPreferredSize(new java.awt.Dimension(90, 25));
- sourceUpButton.setText(L10N.getLocalString("dlg.up_btn", "Up"));
- sourceUpButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- sourceUpButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 3;
- gridBagConstraints.gridy = 10;
- gridBagConstraints.weighty = 0.2;
- editProjectPanel.add(sourceUpButton, gridBagConstraints);
-
- sourceDownButton.setFont(BUTTON_FONT);
- sourceDownButton.setText("Down");
- sourceDownButton.setMaximumSize(new java.awt.Dimension(90, 25));
- sourceDownButton.setMinimumSize(new java.awt.Dimension(90, 25));
- sourceDownButton.setPreferredSize(new java.awt.Dimension(90, 25));
- sourceDownButton.setText(L10N.getLocalString("dlg.down_btn", "Down"));
- sourceDownButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- sourceDownButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridy = 11;
- editProjectPanel.add(sourceDownButton, gridBagConstraints);
-
- classpathUpButton.setFont(BUTTON_FONT);
- classpathUpButton.setText("Up");
- classpathUpButton.setMaximumSize(new java.awt.Dimension(90, 25));
- classpathUpButton.setMinimumSize(new java.awt.Dimension(90, 25));
- classpathUpButton.setPreferredSize(new java.awt.Dimension(90, 25));
- classpathUpButton.setText(L10N.getLocalString("dlg.up_btn", "Up"));
- classpathUpButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- classpathUpButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 3;
- gridBagConstraints.gridy = 17;
- gridBagConstraints.weighty = 0.2;
- editProjectPanel.add(classpathUpButton, gridBagConstraints);
-
- classpathDownButton.setFont(BUTTON_FONT);
- classpathDownButton.setText("Down");
- classpathDownButton.setMaximumSize(new java.awt.Dimension(90, 25));
- classpathDownButton.setMinimumSize(new java.awt.Dimension(90, 25));
- classpathDownButton.setPreferredSize(new java.awt.Dimension(90, 25));
- classpathDownButton.setText(L10N.getLocalString("dlg.down_btn", "Down"));
- classpathDownButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- classpathDownButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 3;
- gridBagConstraints.gridy = 18;
- editProjectPanel.add(classpathDownButton, gridBagConstraints);
-
- viewPanel.add(editProjectPanel, "EditProjectPanel");
-
- bugTreePanel.setLayout(new java.awt.GridBagLayout());
-
- bugTreeBugDetailsSplitter.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
- bugTreeBugDetailsSplitter.setResizeWeight(1.0);
- bugTreeBugDetailsSplitter.setOneTouchExpandable(true);
- bugTreeBugDetailsSplitter.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
- public void propertyChange(java.beans.PropertyChangeEvent evt) {
- bugTreeBugDetailsSplitterPropertyChange(evt);
- }
- });
-
- byClassBugTree.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- byClassScrollPane.setViewportView(byClassBugTree);
-
- groupByTabbedPane.addTab("By Class", byClassScrollPane);
-
- byPackageBugTree.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- byPackageScrollPane.setViewportView(byPackageBugTree);
-
- groupByTabbedPane.addTab("By Package", byPackageScrollPane);
-
- byBugTypeBugTree.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- byBugTypeScrollPane.setViewportView(byBugTypeBugTree);
-
- groupByTabbedPane.addTab("By Bug Type", byBugTypeScrollPane);
-
- byBugCategoryBugTree.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- byBugCategoryScrollPane.setViewportView(byBugCategoryBugTree);
-
- groupByTabbedPane.addTab("By Category Type", byBugCategoryScrollPane);
-
- bugSummaryEditorPane.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- bySummary.setViewportView(bugSummaryEditorPane);
-
- groupByTabbedPane.addTab("Summary", bySummary);
-
- bugTreeBugDetailsSplitter.setTopComponent(groupByTabbedPane);
-
- bugDescriptionEditorPane.setEditable(false);
- bugDescriptionEditorPane.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- bugDescriptionScrollPane.setViewportView(bugDescriptionEditorPane);
-
- bugDetailsTabbedPane.addTab("Details", bugDescriptionScrollPane);
-
- sourceTextAreaScrollPane.setMinimumSize(new java.awt.Dimension(22, 180));
- sourceTextAreaScrollPane.setPreferredSize(new java.awt.Dimension(0, 100));
- sourceTextArea.setEditable(false);
- sourceTextArea.setFont(SOURCE_FONT);
- sourceTextArea.setEnabled(false);
- sourceTextArea.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
-
- sourceTextAreaScrollPane.setViewportView(sourceTextArea);
- sourceLineNumberer = new LineNumberer(sourceTextArea);
- sourceLineNumberer.setBackground(Color.WHITE);
- sourceTextAreaScrollPane.setRowHeaderView(sourceLineNumberer);
-
- bugDetailsTabbedPane.addTab("Source code", sourceTextAreaScrollPane);
-
- annotationTextArea.addFocusListener(new java.awt.event.FocusAdapter() {
- @Override
- public void focusGained(java.awt.event.FocusEvent evt) {
- focusGainedHandler(evt);
- }
- });
-
- annotationTextAreaScrollPane.setViewportView(annotationTextArea);
-
- bugDetailsTabbedPane.addTab("Annotations", annotationTextAreaScrollPane);
-
- bugTreeBugDetailsSplitter.setBottomComponent(bugDetailsTabbedPane);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 1;
- gridBagConstraints.gridwidth = 2;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.weightx = 1.0;
- gridBagConstraints.weighty = 1.0;
- bugTreePanel.add(bugTreeBugDetailsSplitter, gridBagConstraints);
-
- viewPanel.add(bugTreePanel, "BugTree");
-
- {
- equalizeControls( new JComponent[]
- {
- addJarButton,
- addSourceDirButton,
- addClasspathEntryButton,
- removeJarButton,
- removeSrcDirButton,
- removeClasspathEntryButton,
- browseJarButton,
- browseSrcDirButton,
- browseClasspathEntryButton,
- sourceUpButton,
- sourceDownButton,
- classpathUpButton,
- classpathDownButton
- });
-
- groupByTabbedPane.setTitleAt(0, L10N.getLocalString( "dlg.byclass_tab", "By Class"));
- groupByTabbedPane.setTitleAt(1, L10N.getLocalString( "dlg.bypackage_tab", "By Package"));
- groupByTabbedPane.setTitleAt(2, L10N.getLocalString( "dlg.bybugtype_tab", "By Bug Type"));
- groupByTabbedPane.setTitleAt(3, L10N.getLocalString( "dlg.bybugcategory_tab", "By Bug Category"));
- groupByTabbedPane.setTitleAt(4, L10N.getLocalString( "dlg.summary_tab", "Summary"));
- bugDetailsTabbedPane.setTitleAt(0, L10N.getLocalString( "dlg.details_tab", "Details"));
- bugDetailsTabbedPane.setTitleAt(1, L10N.getLocalString( "dlg.sourcecode_tab", "Source Code"));
- bugDetailsTabbedPane.setTitleAt(2, L10N.getLocalString( "dlg.annotations_tab", "Annotations"));
- }
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 0;
- gridBagConstraints.gridwidth = 2;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.weightx = 1.0;
- gridBagConstraints.weighty = 1.0;
- getContentPane().add(viewPanel, gridBagConstraints);
-
- urlLabel.setFont(BUTTON_FONT);
- urlLabel.setText("FindBugs - http://findbugs.sourceforge.net/");
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 1;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
- gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 0);
- getContentPane().add(urlLabel, gridBagConstraints);
-
- jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.X_AXIS));
-
- jPanel1.add(logoLabel);
-
- growBoxSpacer.setMaximumSize(new java.awt.Dimension(16, 16));
- jPanel1.add(growBoxSpacer);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 1;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
- gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 2);
- getContentPane().add(jPanel1, gridBagConstraints);
-
- theMenuBar.setFont(BUTTON_FONT);
- fileMenu.setText("File");
- fileMenu.setFont(BUTTON_FONT);
- localiseButton(fileMenu, "menu.file_menu", "&File", true);
- fileMenu.addMenuListener(new javax.swing.event.MenuListener() {
- public void menuCanceled(javax.swing.event.MenuEvent evt) {
- }
- public void menuDeselected(javax.swing.event.MenuEvent evt) {
- }
- public void menuSelected(javax.swing.event.MenuEvent evt) {
- fileMenuMenuSelected(evt);
- }
- });
-
- newProjectItem.setFont(BUTTON_FONT);
- newProjectItem.setText("New Project");
- localiseButton(newProjectItem, "menu.new_item", "&New Project", true);
- newProjectItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- newProjectItemActionPerformed(evt);
- }
- });
-
- fileMenu.add(newProjectItem);
-
- openProjectItem.setFont(BUTTON_FONT);
- openProjectItem.setText("Open Project...");
- localiseButton(openProjectItem, "menu.open_item", "&Open Project...", true);
- openProjectItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- openProjectItemActionPerformed(evt);
- }
- });
-
- fileMenu.add(openProjectItem);
-
- recentProjectsMenu.setText("Recent Projects");
- recentProjectsMenu.setFont(BUTTON_FONT);
- localiseButton(recentProjectsMenu, "menu.recent_menu", "R&ecent Projects", true);
- rebuildRecentProjectsMenu();
- fileMenu.add(recentProjectsMenu);
-
- fileMenu.add(jSeparator9);
-
- closeProjectItem.setFont(BUTTON_FONT);
- closeProjectItem.setText("Close Project");
- localiseButton(closeProjectItem, "menu.close_item", "&Close Project", true);
- closeProjectItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- closeProjectItemActionPerformed(evt);
- }
- });
-
- fileMenu.add(closeProjectItem);
-
- saveProjectItem.setFont(BUTTON_FONT);
- saveProjectItem.setText("Save Project");
- localiseButton(saveProjectItem, "menu.save_item", "&Save Project", true);
- saveProjectItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- saveProjectItemActionPerformed(evt);
- }
- });
-
- fileMenu.add(saveProjectItem);
-
- saveProjectAsItem.setFont(BUTTON_FONT);
- saveProjectAsItem.setText("Save Project As...");
- localiseButton(saveProjectAsItem, "menu.saveas_item", "Save Project &As...", true);
- saveProjectAsItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- saveProjectAsItemActionPerformed(evt);
- }
- });
-
- fileMenu.add(saveProjectAsItem);
-
- reloadProjectItem.setFont(BUTTON_FONT);
- reloadProjectItem.setText("Reload Project");
- localiseButton(reloadProjectItem, "menu.reload_item", "&Reload Project", true);
- reloadProjectItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- reloadProjectItemActionPerformed(evt);
- }
- });
-
- fileMenu.add(reloadProjectItem);
-
- fileMenu.add(jSeparator3);
-
- loadBugsItem.setFont(BUTTON_FONT);
- loadBugsItem.setText("Load Bugs...");
- localiseButton(loadBugsItem, "menu.loadbugs_item", "&Load Bugs...", true);
- loadBugsItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- loadBugsItemActionPerformed(evt);
- }
- });
-
- fileMenu.add(loadBugsItem);
-
- saveBugsItem.setFont(BUTTON_FONT);
- saveBugsItem.setText("Save Bugs");
- localiseButton(saveBugsItem, "menu.savebugs_item", "Save &Bugs...", true);
- saveBugsItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- saveBugsItemActionPerformed(evt);
- }
- });
-
- fileMenu.add(saveBugsItem);
-
- fileMenu.add(jSeparator6);
-
- exitItem.setFont(BUTTON_FONT);
- exitItem.setText("Exit");
- localiseButton(exitItem, "menu.exit_item", "E&xit", true);
- exitItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- exitItemActionPerformed(evt);
- }
- });
-
- fileMenu.add(exitItem);
-
- theMenuBar.add(fileMenu);
-
- editMenu.setText("Edit");
- editMenu.setFont(BUTTON_FONT);
- editMenu.setEnabled(false);
- localiseButton(editMenu, "menu.edit_menu", "&Edit", true);
- cutItem.setFont(BUTTON_FONT);
- cutItem.setText("Cut");
- localiseButton(cutItem, "menu.cut_item", "Cut", true);
- cutItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- cutActionPerformed(evt);
- }
- });
-
- editMenu.add(cutItem);
-
- copyItem.setFont(BUTTON_FONT);
- copyItem.setText("Copy");
- localiseButton(copyItem, "menu.copy_item", "Copy", true);
- copyItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- copyActionPerformed(evt);
- }
- });
-
- editMenu.add(copyItem);
-
- pasteItem.setFont(BUTTON_FONT);
- pasteItem.setText("Paste");
- localiseButton(pasteItem, "menu.paste_item", "Paste", true);
- pasteItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- pasteActionPerformed(evt);
- }
- });
-
- editMenu.add(pasteItem);
-
- editMenu.add(jSeparator10);
-
- selectAllItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, java.awt.event.InputEvent.CTRL_MASK));
- selectAllItem.setFont(BUTTON_FONT);
- selectAllItem.setText("Select All");
- localiseButton(selectAllItem, "menu.selectall_item", "Select &All", true);
- selectAllItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- selectAllActionPerformed(evt);
- }
- });
-
- editMenu.add(selectAllItem);
-
- theMenuBar.add(editMenu);
-
- viewMenu.setText("View");
- viewMenu.setFont(BUTTON_FONT);
- localiseButton(viewMenu, "menu.view_menu", "&View", true);
-
- viewMenu.addMenuListener(new javax.swing.event.MenuListener() {
- public void menuCanceled(javax.swing.event.MenuEvent evt) {
- }
- public void menuDeselected(javax.swing.event.MenuEvent evt) {
- }
- public void menuSelected(javax.swing.event.MenuEvent evt) {
- viewMenuMenuSelected(evt);
- }
- });
-
- viewBugDetailsItem.setFont(BUTTON_FONT);
- viewBugDetailsItem.setSelected(true);
- viewBugDetailsItem.setText("Bug Details");
- localiseButton(viewBugDetailsItem, "menu.bugdetails_item", "Bug &Details", true);
- viewBugDetailsItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- viewBugDetailsItemActionPerformed(evt);
- }
- });
-
- viewMenu.add(viewBugDetailsItem);
-
- fullDescriptionsItem.setFont(BUTTON_FONT);
- fullDescriptionsItem.setSelected(true);
- fullDescriptionsItem.setText("Full Descriptions");
- localiseButton(fullDescriptionsItem, "menu.fulldescriptions_item", "&Full Descriptions", true);
- fullDescriptionsItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- fullDescriptionsItemActionPerformed(evt);
- }
- });
-
- viewMenu.add(fullDescriptionsItem);
-
- viewMenu.add(jSeparator7);
-
- filterWarningsMenu.setText("Filter Warnings");
- filterWarningsMenu.setFont(BUTTON_FONT);
- localiseButton(filterWarningsMenu, "menu.filterwarnings_menu", "Filter &Warnings", true);
- expPriorityButton.setFont(BUTTON_FONT);
- expPriorityButton.setText("Experimental Priority");
- priorityButtonGroup.add(expPriorityButton);
- localiseButton(expPriorityButton, "menu.exppriority_item", "&Experimental Priority", true);
- expPriorityButton.setSelected(getPriorityThreshold() == Detector.EXP_PRIORITY);
- expPriorityButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- expPriorityButtonActionPerformed(evt);
- }
- });
-
- filterWarningsMenu.add(expPriorityButton);
-
- lowPriorityButton.setFont(BUTTON_FONT);
- lowPriorityButton.setText("Low Priority");
- priorityButtonGroup.add(lowPriorityButton);
- localiseButton(lowPriorityButton, "menu.lowpriority_item", "&Low Priority", true);
- lowPriorityButton.setSelected(getPriorityThreshold() == Detector.LOW_PRIORITY);
- lowPriorityButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- lowPriorityButtonActionPerformed(evt);
- }
- });
-
- filterWarningsMenu.add(lowPriorityButton);
-
- mediumPriorityButton.setFont(BUTTON_FONT);
- mediumPriorityButton.setText("Medium Priority");
- priorityButtonGroup.add(mediumPriorityButton);
- localiseButton(mediumPriorityButton, "menu.mediumpriority_item", "&Medium Priority", true);
- mediumPriorityButton.setSelected(getPriorityThreshold() == Detector.NORMAL_PRIORITY);
- mediumPriorityButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- mediumPriorityButtonActionPerformed(evt);
- }
- });
-
- filterWarningsMenu.add(mediumPriorityButton);
-
- highPriorityButton.setFont(BUTTON_FONT);
- highPriorityButton.setText("High Priority");
- priorityButtonGroup.add(highPriorityButton);
- localiseButton(highPriorityButton, "menu.highpriority_item", "&High Priority", true);
- highPriorityButton.setSelected(getPriorityThreshold() == Detector.HIGH_PRIORITY);
- highPriorityButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- highPriorityButtonActionPerformed(evt);
- }
- });
-
- filterWarningsMenu.add(highPriorityButton);
-
- filterWarningsMenu.add(jSeparator11);
-
- viewMenu.add(filterWarningsMenu);
-
- ButtonGroup bg = new ButtonGroup();
- bg.add(expPriorityButton);
- bg.add(lowPriorityButton);
- bg.add(mediumPriorityButton);
- bg.add(highPriorityButton);
-
- viewMenu.add(jSeparator8);
-
- viewProjectItem.setFont(BUTTON_FONT);
- viewProjectItem.setText("View Project Details");
- viewProjectItem.setEnabled(false);
- localiseButton(viewProjectItem, "menu.viewprojectdetails_item", "View Project Details", true);
- viewProjectItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- viewProjectItemActionPerformed(evt);
- }
- });
-
- viewMenu.add(viewProjectItem);
-
- viewBugsItem.setFont(BUTTON_FONT);
- viewBugsItem.setText("View Bugs");
- viewBugsItem.setEnabled(false);
- localiseButton(viewBugsItem, "menu.viewbugs_item", "View Bugs", true);
- viewBugsItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- viewBugsItemActionPerformed(evt);
- }
- });
-
- viewMenu.add(viewBugsItem);
-
- theMenuBar.add(viewMenu);
-
- settingsMenu.setText("Settings");
- settingsMenu.setFont(BUTTON_FONT);
- localiseButton(settingsMenu, "menu.settings_menu", "&Settings", true);
- settingsMenu.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- settingsMenuActionPerformed(evt);
- }
- });
-
- configureDetectorsItem.setFont(BUTTON_FONT);
- configureDetectorsItem.setText("Configure Detectors...");
- localiseButton(configureDetectorsItem, "menu.configure_item", "&Configure Detectors...", true);
- configureDetectorsItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- configureDetectorsItemActionPerformed(evt);
- }
- });
-
- settingsMenu.add(configureDetectorsItem);
-
- effortMenu.setText("Effort");
- effortMenu.setFont(BUTTON_FONT);
- localiseButton(effortMenu, "menu.effort_menu", "Effort", true);
- minEffortItem.setFont(BUTTON_FONT);
- minEffortItem.setText("Minimum");
- effortButtonGroup.add(minEffortItem);
- localiseButton(minEffortItem, "menu.mineffort_item", "&Minimum", true);
- minEffortItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- minEffortItemActionPerformed(evt);
- }
- });
-
- effortMenu.add(minEffortItem);
-
- normalEffortItem.setFont(BUTTON_FONT);
- normalEffortItem.setSelected(true);
- normalEffortItem.setText("Normal");
- effortButtonGroup.add(normalEffortItem);
- localiseButton(normalEffortItem, "menu.normaleffort_item", "&Normal", true);
- normalEffortItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- normalEffortItemActionPerformed(evt);
- }
- });
-
- effortMenu.add(normalEffortItem);
-
- maxEffortItem.setFont(BUTTON_FONT);
- maxEffortItem.setText("Maximum");
- effortButtonGroup.add(maxEffortItem);
- localiseButton(maxEffortItem, "menu.maxeffort_item", "&Maximum", true);
- maxEffortItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- maxEffortItemActionPerformed(evt);
- }
- });
-
- effortMenu.add(maxEffortItem);
-
- settingsMenu.add(effortMenu);
-
- theMenuBar.add(settingsMenu);
-
- helpMenu.setText("Help");
- helpMenu.setFont(BUTTON_FONT);
- localiseButton(helpMenu, "menu.help_menu", "&Help", true);
- aboutItem.setFont(BUTTON_FONT);
- aboutItem.setText("About...");
- localiseButton(aboutItem, "menu.about_item", "&About", true);
- aboutItem.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- aboutItemActionPerformed(evt);
- }
- });
-
- helpMenu.add(aboutItem);
-
- theMenuBar.add(helpMenu);
-
- setJMenuBar(theMenuBar);
-
- pack();
- }//GEN-END:initComponents
-
- private void maxEffortItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_maxEffortItemActionPerformed
- settingList = FindBugs.MAX_EFFORT;
- }//GEN-LAST:event_maxEffortItemActionPerformed
-
- private void normalEffortItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_normalEffortItemActionPerformed
- settingList = FindBugs.DEFAULT_EFFORT;
- }//GEN-LAST:event_normalEffortItemActionPerformed
-
- private void minEffortItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_minEffortItemActionPerformed
- settingList = FindBugs.MIN_EFFORT;
- }//GEN-LAST:event_minEffortItemActionPerformed
-
- private void settingsMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_settingsMenuActionPerformed
- // TODO add your handling code here:
- }//GEN-LAST:event_settingsMenuActionPerformed
-
- private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened
- if (SystemProperties.getBoolean("findbugs.noSummary")) {
- groupByTabbedPane.remove(bySummary);
- }
- }//GEN-LAST:event_formWindowOpened
-
- private void selectAllActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectAllActionPerformed
- if (selectedComponent == null)
- return;
-
- if (selectedComponent instanceof JTextComponent)
- ((JTextComponent)selectedComponent).selectAll();
- else if (selectedComponent instanceof JList) {
- JList list = (JList)selectedComponent;
- list.setSelectionInterval(0, list.getModel().getSize()-1);
- }
- }//GEN-LAST:event_selectAllActionPerformed
-
- private void disableEditKeyBindings(JList list) {
- list.getInputMap().put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X, java.awt.event.InputEvent.CTRL_MASK), "none");
- list.getInputMap().put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_C, java.awt.event.InputEvent.CTRL_MASK), "none");
- list.getInputMap().put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_V, java.awt.event.InputEvent.CTRL_MASK), "none");
- }
-
- private String buildSelectPath(JList list) {
- StringBuilder path = new StringBuilder();
- int[] indices = list.getSelectedIndices();
- String separatorStr = SystemProperties.getProperty("path.separator");
- String sep = "";
- ListModel m = list.getModel();
- for (int indice : indices) {
- path.append(sep);
- sep = separatorStr;
- path.append(m.getElementAt(indice));
- }
- return path.toString();
- }
-
- private void pasteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pasteActionPerformed
- if (selectedComponent == null)
- return;
-
- if (selectedComponent instanceof JTextComponent)
- ((JTextComponent)selectedComponent).paste();
- else if (selectedComponent instanceof JList) {
- Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
- Transferable transfer = cb.getContents(this);
- if (transfer.isDataFlavorSupported(DataFlavor.stringFlavor)) {
- try {
- String path = (String)transfer.getTransferData(DataFlavor.stringFlavor);
-
- if (selectedComponent == jarFileList) {
- jarNameTextField.setText(path);
- addJarButtonActionPerformed(evt);
- }
- else if (selectedComponent == sourceDirList) {
- srcDirTextField.setText(path);
- this.addSourceDirButtonActionPerformed(evt);
- }
- else if (selectedComponent == classpathEntryList) {
- classpathEntryTextField.setText(path);
- addClasspathEntryButtonActionPerformed(evt);
- }
- } catch (Exception e) {
- }
- }
- }
- }//GEN-LAST:event_pasteActionPerformed
-
- private void copyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyActionPerformed
- if (selectedComponent == null)
- return;
-
- if (selectedComponent instanceof JTextComponent)
- ((JTextComponent)selectedComponent).copy();
- else if (selectedComponent instanceof JTree) {
- TreePath path = ((JTree)selectedComponent).getSelectionPath();
- StringSelection data = new StringSelection(path.getLastPathComponent().toString());
- Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
- cb.setContents(data, data);
- }
- else if (selectedComponent instanceof JList) {
- StringSelection path = new StringSelection(buildSelectPath((JList)selectedComponent));
- Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
- cb.setContents(path, path);
- }
- }//GEN-LAST:event_copyActionPerformed
-
- private void cutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cutActionPerformed
- if (selectedComponent == null)
- return;
-
- if (selectedComponent instanceof JTextComponent)
- ((JTextComponent)selectedComponent).cut();
- else if (selectedComponent instanceof JList) {
- StringSelection path = new StringSelection(buildSelectPath((JList)selectedComponent));
- Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
- cb.setContents(path, path);
- if (selectedComponent == jarFileList)
- removeJarButtonActionPerformed(evt);
- else if (selectedComponent == sourceDirList)
- removeSrcDirButtonActionPerformed(evt);
- else if (selectedComponent == classpathEntryList)
- removeClasspathEntryButtonActionPerformed(evt);
- }
- }//GEN-LAST:event_cutActionPerformed
-
- private void focusGainedHandler(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_focusGainedHandler
- Component old = evt.getOppositeComponent();
- if (old instanceof JList)
- ((JList) old).clearSelection();
- selectedComponent = evt.getComponent();
- ableEditMenu();
- }//GEN-LAST:event_focusGainedHandler
-
- private void classpathUpButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_classpathUpButtonActionPerformed
- if (moveEntriesUp(classpathEntryList))
- resyncAuxClasspathEntries();
- }//GEN-LAST:event_classpathUpButtonActionPerformed
-
- private void sourceDownButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sourceDownButtonActionPerformed
- if (moveEntriesDown(sourceDirList))
- resyncSourceEntries();
- }//GEN-LAST:event_sourceDownButtonActionPerformed
-
- private void sourceUpButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sourceUpButtonActionPerformed
- if (moveEntriesUp(sourceDirList))
- resyncSourceEntries();
- }//GEN-LAST:event_sourceUpButtonActionPerformed
-
- private void classpathDownButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_classpathDownButtonActionPerformed
- if (moveEntriesDown(classpathEntryList))
- resyncAuxClasspathEntries();
- }//GEN-LAST:event_classpathDownButtonActionPerformed
-
- private void viewBugsItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewBugsItemActionPerformed
- setView("BugTree");
- }//GEN-LAST:event_viewBugsItemActionPerformed
-
- private void viewProjectItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewProjectItemActionPerformed
- setView("EditProjectPanel");
- }//GEN-LAST:event_viewProjectItemActionPerformed
-
- private void highPriorityButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_highPriorityButtonActionPerformed
- setPriorityThreshold(Detector.HIGH_PRIORITY);
- }//GEN-LAST:event_highPriorityButtonActionPerformed
-
- private void mediumPriorityButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mediumPriorityButtonActionPerformed
- setPriorityThreshold(Detector.NORMAL_PRIORITY);
- }//GEN-LAST:event_mediumPriorityButtonActionPerformed
-
- private void lowPriorityButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lowPriorityButtonActionPerformed
- setPriorityThreshold(Detector.LOW_PRIORITY);
- }//GEN-LAST:event_lowPriorityButtonActionPerformed
-
- private void expPriorityButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_expPriorityButtonActionPerformed
- setPriorityThreshold(Detector.EXP_PRIORITY);
- }//GEN-LAST:event_expPriorityButtonActionPerformed
-
- private void saveBugsItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveBugsItemActionPerformed
-
- try {
- if (currentAnalysisRun == null) {
- logger.logMessage(Logger.ERROR, "No bugs are loaded!");
- return;
- }
-
- JFileChooser chooser = createFileChooser();
- chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
- chooser.setFileFilter(xmlFileFilter);
-
- int result = chooseFile(chooser, L10N.getLocalString("dlg.savebugs_ttl", "Save Bugs"));
-
- if (result != JFileChooser.CANCEL_OPTION) {
- // Make sure current annotation text is up to date with its
- // corresponding bug instance
- if (currentBugInstance != null)
- synchBugAnnotation(currentBugInstance);
-
- // Save bugs to file
- File selectedFile = chooser.getSelectedFile();
- currentAnalysisRun.saveBugsToFile(selectedFile);
- }
- } catch (Exception e) {
- if (FindBugs.DEBUG) {
- e.printStackTrace();
- }
- logger.logMessage(Logger.ERROR, "Could not save bugs: " + e.toString());
- }
- }//GEN-LAST:event_saveBugsItemActionPerformed
-
- private void loadBugsFromFile(File file) throws IOException, DocumentException {
- File selectedFile = file;
-
- Project project = new Project();
- AnalysisRun analysisRun = new AnalysisRun(project, this);
-
- analysisRun.loadBugsFromFile(selectedFile);
-
- project.setProjectFileName(file.getName()); // otherwise frame will show "<<unnamed project>>"
- setProject(project);
- synchAnalysisRun(analysisRun);
- }
-
- private void loadBugsFromURL(String urlspec) throws IOException, DocumentException {
- URL url = new URL(urlspec);
- InputStream in = url.openStream();
-
- Project project = new Project();
- AnalysisRun analysisRun = new AnalysisRun(project, this);
-
- analysisRun.loadBugsFromInputStream(in);
-
- setProject(project);
- synchAnalysisRun(analysisRun);
- }
-
- private void loadBugsItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadBugsItemActionPerformed
- // FIXME: offer to save current project and bugs
-
- try {
-
- JFileChooser chooser = createFileChooser();
- chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
- chooser.setFileFilter(xmlFileFilter);
-
- int result = chooseFile(chooser, L10N.getLocalString("dlg.loadbugs_ttl", "Load Bugs..."));
-
- if (result != JFileChooser.CANCEL_OPTION) {
- loadBugsFromFile(chooser.getSelectedFile());
- }
- } catch (Exception e) {
- if (FindBugs.DEBUG) {
- e.printStackTrace();
- }
- logger.logMessage(Logger.ERROR, "Could not load bugs: " + e.toString());
- }
-
- }//GEN-LAST:event_loadBugsItemActionPerformed
-
- private void configureDetectorsItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configureDetectorsItemActionPerformed
- ConfigureDetectorsDialog dialog = new ConfigureDetectorsDialog(this, true);
- dialog.setSize(700, 520);
- dialog.setLocationRelativeTo(null); // center the dialog
- dialog.setVisible(true);
- }//GEN-LAST:event_configureDetectorsItemActionPerformed
-
- private void reloadProjectItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reloadProjectItemActionPerformed
- Project current = getCurrentProject();
-
- if (current == null)
- return;
-
- try {
- String filename = current.getProjectFileName();
- Project project = new Project();
- project.read(filename);
- setProject(null);
- setProject(project);
- findBugsButtonActionPerformed(evt);
- } catch (IOException e) {
- logger.logMessage(Logger.ERROR, "Could not reload project: " + e.getMessage());
- }
-
- }//GEN-LAST:event_reloadProjectItemActionPerformed
-
- private void saveProjectAsItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveProjectAsItemActionPerformed
- saveProject(getCurrentProject(), L10N.getLocalString("dlg.saveprojectas_ttl", "Save Project As..."), true);
- }//GEN-LAST:event_saveProjectAsItemActionPerformed
-
- private void viewMenuMenuSelected(javax.swing.event.MenuEvent evt) {//GEN-FIRST:event_viewMenuMenuSelected
- // View bug details and full descriptions items,
- // are only enabled if there is a project open.
- boolean hasProject = getCurrentProject() != null;
- viewBugDetailsItem.setEnabled(hasProject);
- fullDescriptionsItem.setEnabled(hasProject);
- }//GEN-LAST:event_viewMenuMenuSelected
-
- private void fileMenuMenuSelected(javax.swing.event.MenuEvent evt) {//GEN-FIRST:event_fileMenuMenuSelected
- // Save and close project items are only enabled if there is a project open.
- boolean hasProject = getCurrentProject() != null;
- saveProjectItem.setEnabled(hasProject);
- saveProjectAsItem.setEnabled(hasProject);
- reloadProjectItem.setEnabled(hasProject && !getCurrentProject().getProjectFileName().equals(Project.UNNAMED_PROJECT));
- closeProjectItem.setEnabled(hasProject);
-
- // Save bugs is only enabled if there is a current analysis run
- boolean hasAnalysisRun = currentAnalysisRun != null;
- saveBugsItem.setEnabled(hasAnalysisRun);
-
- }//GEN-LAST:event_fileMenuMenuSelected
-
- private void closeProjectItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeProjectItemActionPerformed
- if (closeProjectHook(getCurrentProject(), L10N.getLocalString("dlg.closeproject_lbl", "Close Project"))) {
- setProject(null);
- }
- }//GEN-LAST:event_closeProjectItemActionPerformed
-
- private void removeClasspathEntryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeClasspathEntryButtonActionPerformed
- Project project = getCurrentProject();
- DefaultListModel listModel = (DefaultListModel) classpathEntryList.getModel();
-
- int[] selIndices = classpathEntryList.getSelectedIndices();
- for (int i = selIndices.length - 1; i >= 0; i--) {
- int sel = selIndices[i];
- project.removeAuxClasspathEntry(sel);
- listModel.remove(sel);
- }
- }//GEN-LAST:event_removeClasspathEntryButtonActionPerformed
-
- private void addClasspathEntryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addClasspathEntryButtonActionPerformed
- addClasspathEntryToList();
- }//GEN-LAST:event_addClasspathEntryButtonActionPerformed
-
- private void browseClasspathEntryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseClasspathEntryButtonActionPerformed
- JFileChooser chooser = createFileChooser();
- chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
- chooser.setFileFilter(auxClasspathEntryFileFilter);
- chooser.setMultiSelectionEnabled(true);
-
- int result = chooseFile(chooser, "Add Entry");
-
- if (result != JFileChooser.CANCEL_OPTION) {
- File[] selectedFileList = chooser.getSelectedFiles();
- for (int i = 0; i < selectedFileList.length; ++i) {
- selectedFileList[i] = verifyFileSelection(selectedFileList[i]);
- String entry = selectedFileList[i].getPath();
- addClasspathEntryToProject(entry);
- }
- }
- }//GEN-LAST:event_browseClasspathEntryButtonActionPerformed
-
- private void fullDescriptionsItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fullDescriptionsItemActionPerformed
- for (JTree bugTree : bugTreeList) {
- // Redisplay the displayed bug instance nodes
- DefaultTreeModel bugTreeModel = (DefaultTreeModel) bugTree.getModel();
- int numRows = bugTree.getRowCount();
-
- for (int i = 0; i < numRows; ++i) {
- //System.out.println("Getting path for row " + i);
- TreePath path = bugTree.getPathForRow(i);
- if (path == null)
- continue;
- DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
- if (node instanceof BugTreeNode)
- bugTreeModel.valueForPathChanged(path, node.getUserObject());
- }
- }
- }//GEN-LAST:event_fullDescriptionsItemActionPerformed
-
- private void viewBugDetailsItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewBugDetailsItemActionPerformed
- String view = getView();
- if (view.equals("BugTree")) {
- checkBugDetailsVisibility();
- }
-
- }//GEN-LAST:event_viewBugDetailsItemActionPerformed
-
- private void bugTreeBugDetailsSplitterPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_bugTreeBugDetailsSplitterPropertyChange
- // Here we want to
- // (1) Keep the View:Bug details checkbox item up to date, and
- // (2) keep the details window synchronized with the current bug instance
- String propertyName = evt.getPropertyName();
- if (propertyName.equals(JSplitPane.DIVIDER_LOCATION_PROPERTY)) {
- boolean isMaximized = isSplitterMaximized(bugTreeBugDetailsSplitter, evt);
- viewBugDetailsItem.setSelected(!isMaximized);
- if (!isMaximized) {
- // Details window is shown, so make sure it is populated
- // with bug detail information
- synchBugInstance();
- }
- }
- }//GEN-LAST:event_bugTreeBugDetailsSplitterPropertyChange
-
- private void openProjectItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openProjectItemActionPerformed
-
- if (!closeProjectHook(getCurrentProject(), L10N.getLocalString("msg.openproject_txt", "Open Project")))
- return;
-
- JFileChooser chooser = createFileChooser();
- chooser.setFileFilter(projectFileFilter);
- int result = chooseFileToOpen(chooser);
-
- if (result == JFileChooser.CANCEL_OPTION)
- return;
- try {
- File file = chooser.getSelectedFile();
- Project project = new Project();
- project.read(file.getPath());
- setProject(project);
- UserPreferences.getUserPreferences().useProject(file.getPath());
- rebuildRecentProjectsMenu();
-
- } catch (IOException e) {
- logger.logMessage(Logger.ERROR, MessageFormat.format( L10N.getLocalString("msg.couldnotopenproject_txt", "Could not open project: {0}"), new Object[]{e.getMessage()}));
- }
- }//GEN-LAST:event_openProjectItemActionPerformed
-
- private void saveProjectItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveProjectItemActionPerformed
- saveProject(getCurrentProject(), L10N.getLocalString("msg.saveproject_txt", "Save Project"));
- }//GEN-LAST:event_saveProjectItemActionPerformed
-
- private void aboutItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutItemActionPerformed
- about();
- }//GEN-LAST:event_aboutItemActionPerformed
-
- private void findBugsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_findBugsButtonActionPerformed
- Project project = getCurrentProject();
-
- if (project.getFileCount() == 0) {
- logger.logMessage(Logger.ERROR, MessageFormat.format(L10N.getLocalString("msg.projectnojars_txt", "Project {0} has no Jar files selected"), new Object[]{project}));
- return;
- }
-
- bugDescriptionEditorPane.setText("");
- currentBugDetailsKey = null;
- sourceTextArea.setText("");
- AnalysisRun analysisRun = new AnalysisRun(project, this);
-
- logger.logMessage(Logger.INFO, MessageFormat.format(L10N.getLocalString("msg.beginninganalysis_txt", "Beginning analysis of {0}"), new Object[]{project}));
-
- // Run the analysis!
- RunAnalysisDialog dialog = new RunAnalysisDialog(this, analysisRun, analysisPriority);
- dialog.setSize(400, 300);
- dialog.setLocationRelativeTo(null); // center the dialog
- dialog.setVisible(true);
-
- if (dialog.isCompleted()) {
- logger.logMessage(Logger.INFO, MessageFormat.format(L10N.getLocalString("msg.analysiscompleted_txt", "Analysis {0} completed"), new Object[]{project}));
-
- // Report any errors that might have occurred during analysis
- analysisRun.reportAnalysisErrors();
-
- // Now we have an analysis run to look at
- synchAnalysisRun(analysisRun);
- } else {
- if (dialog.exceptionOccurred()) {
- // The analysis was killed by an unexpected exception
- Exception e = dialog.getException();
- AnalysisErrorDialog err = new AnalysisErrorDialog(this, true, null);
- err.addLine(MessageFormat.format(L10N.getLocalString("msg.fatalanalysisexception_txt", "Fatal analysis exception: {0}"), new Object[]{e.toString()}));
- StackTraceElement[] callList = e.getStackTrace();
- for (StackTraceElement aCallList : callList)
- err.addLine("\t" + aCallList);
- err.finish();
- err.setSize(650, 500);
- err.setLocationRelativeTo(null); // center the dialog
- err.setVisible(true);
- } else {
- // Cancelled by user
- logger.logMessage(Logger.INFO, MessageFormat.format(L10N.getLocalString("msg.analysiscancelled_txt", "Analysis of {0} cancelled by user"), new Object[]{project}));
- }
- }
- }//GEN-LAST:event_findBugsButtonActionPerformed
-
- private void browseSrcDirButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseSrcDirButtonActionPerformed
- JFileChooser chooser = createFileChooser();
- chooser.setFileFilter(archiveAndDirectoryFilter);
- chooser.setMultiSelectionEnabled(true);
- chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
-
- int rc = chooseFile(chooser, L10N.getLocalString("msg_addsource_lbl", "Add source directory or archive"));
- if (rc == JFileChooser.APPROVE_OPTION) {
- File[] selectedFileList = chooser.getSelectedFiles();
- for (int i = 0; i < selectedFileList.length; ++i) {
- selectedFileList[i] = verifyFileSelection(selectedFileList[i]);
- String entry = selectedFileList[i].getPath();
- addSrcToProject(entry);
- }
- }
- }//GEN-LAST:event_browseSrcDirButtonActionPerformed
-
- private void srcDirTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_srcDirTextFieldActionPerformed
- addSourceDirToList();
- }//GEN-LAST:event_srcDirTextFieldActionPerformed
-
- private void jarNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jarNameTextFieldActionPerformed
- addJarToList();
- }//GEN-LAST:event_jarNameTextFieldActionPerformed
-
- private void browseJarButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseJarButtonActionPerformed
- JFileChooser chooser = createFileChooser();
- chooser.setFileFilter(archiveAndDirectoryFilter);
- chooser.setMultiSelectionEnabled(true);
- chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
-
- int rc = chooseFile(chooser, L10N.getLocalString("msg.addarchiveordirectory_txt", "Add archive or directory"));
- if (rc == JFileChooser.APPROVE_OPTION) {
- File[] selectedFileList = chooser.getSelectedFiles();
- for (int i = 0; i < selectedFileList.length; ++i) {
- selectedFileList[i] = verifyFileSelection(selectedFileList[i]);
- String entry = selectedFileList[i].getPath();
- addJarToProject(entry);
- }
- }
- }//GEN-LAST:event_browseJarButtonActionPerformed
-
- private void newProjectItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newProjectItemActionPerformed
-
- if (!closeProjectHook(getCurrentProject(), L10N.getLocalString("msg.newproject_txt", "New Project")))
- return;
-
- Project project = new Project();
- setProject(project);
- }//GEN-LAST:event_newProjectItemActionPerformed
-
- private void exitItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitItemActionPerformed
- exitFindBugs();
- }//GEN-LAST:event_exitItemActionPerformed
-
- private void removeSrcDirButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeSrcDirButtonActionPerformed
- Project project = getCurrentProject();
- DefaultListModel listModel = (DefaultListModel) sourceDirList.getModel();
-
- int[] selIndices = sourceDirList.getSelectedIndices();
- for (int i = selIndices.length - 1; i >= 0; i--) {
- int sel = selIndices[i];
- project.removeSourceDir(sel);
- listModel.remove(sel);
- }
- }//GEN-LAST:event_removeSrcDirButtonActionPerformed
-
- private void removeJarButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeJarButtonActionPerformed
- Project project = getCurrentProject();
- DefaultListModel listModel = (DefaultListModel) jarFileList.getModel();
-
- int[] selIndices = jarFileList.getSelectedIndices();
- for (int i = selIndices.length - 1; i >= 0; i--) {
- int sel = selIndices[i];
- project.removeFile(sel);
- listModel.remove(sel);
- }
- }//GEN-LAST:event_removeJarButtonActionPerformed
-
- private void addSourceDirButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addSourceDirButtonActionPerformed
- addSourceDirToList();
- }//GEN-LAST:event_addSourceDirButtonActionPerformed
-
- private void addJarButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addJarButtonActionPerformed
- addJarToList();
- }//GEN-LAST:event_addJarButtonActionPerformed
-
- /**
- * Exit the Application
- */
- private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
- exitFindBugs();
- }//GEN-LAST:event_exitForm
-
- /**
- * This makes the set of controls passed in all the same size, equal to
- * the minimum needed of the largest control.
- */
- private void equalizeControls(JComponent[] components) {
- Dimension d;
-
- int minX = 0, minY = 0;
- for (JComponent comp : components) {
- comp.setMaximumSize(null);
- comp.setMinimumSize(null);
- comp.setPreferredSize(null);
- d = comp.getPreferredSize();
- if (d.width > minX)
- minX = d.width;
- if (d.height > minY)
- minY = d.height;
- }
-
- d = new Dimension(minX, minY);
- for (JComponent comp : components) {
- comp.setMinimumSize(d);
- comp.setMaximumSize(d);
- comp.setPreferredSize(d);
- }
- }
-
- /**
- * This is called whenever the selection is changed in the bug tree.
- *
- * @param e the TreeSelectionEvent
- */
- private void bugTreeSelectionChanged(TreeSelectionEvent e) {
-
- BugInstance selected = getCurrentBugInstance();
- if (selected != null) {
- synchBugInstance();
- }
- }
-
- private void openRecentProjectItemActionPerformed(java.awt.event.ActionEvent evt) {
- if (!closeProjectHook(getCurrentProject(), L10N.getLocalString("msg.openproject_txt", "Open Project")))
- return;
-
- JMenuItem recentProjectItem = (JMenuItem) evt.getSource();
- File file = new File(recentProjectItem.getText());
- try {
- System.setProperty("user.dir", file.getParent());
- Project project = new Project();
- project.read(file.getPath());
- setProject(project);
- UserPreferences.getUserPreferences().useProject(file.getPath());
- } catch (IOException e) {
- UserPreferences.getUserPreferences().removeProject(file.getPath());
- logger.logMessage(Logger.ERROR, MessageFormat.format(L10N.getLocalString("msg.couldnotopenproject_txt", "Could not open project: {0}"), new Object[]{e.getMessage()}));
- } finally {
- rebuildRecentProjectsMenu();
- }
- }
-
- private boolean moveEntriesUp(JList entryList) {
- int[] selIndices = entryList.getSelectedIndices();
- if (selIndices.length == 0)
- return false;
-
- boolean changed = false;
- int lastInsertPos = -1;
- DefaultListModel model = (DefaultListModel) entryList.getModel();
- for (int i = 0; i < selIndices.length; i++) {
- int sel = selIndices[i];
- if ((sel - 1) > lastInsertPos) {
- model.add(sel - 1, model.remove(sel));
- selIndices[i] = sel - 1;
- changed = true;
- }
- lastInsertPos = selIndices[i];
- }
-
- entryList.setSelectedIndices(selIndices);
- return changed;
- }
-
- private boolean moveEntriesDown(JList entryList) {
- int[] selIndices = entryList.getSelectedIndices();
- if (selIndices.length == 0)
- return false;
-
- boolean changed = false;
- DefaultListModel model = (DefaultListModel) entryList.getModel();
- int lastInsertPos = model.getSize();
- for (int i = selIndices.length - 1; i >= 0; i--) {
- int sel = selIndices[i];
- if ((sel + 1) < lastInsertPos) {
- model.add(sel + 1, model.remove(sel));
- selIndices[i] = sel + 1;
- changed = true;
- }
- lastInsertPos = selIndices[i];
- }
-
- entryList.setSelectedIndices(selIndices);
- return changed;
- }
-
- private void resyncAuxClasspathEntries() {
- Project project = getCurrentProject();
- int numEntries = project.getNumAuxClasspathEntries();
- while (numEntries-- > 0)
- project.removeAuxClasspathEntry(0);
-
- DefaultListModel model = (DefaultListModel) classpathEntryList.getModel();
- for (int i = 0; i < model.size(); i++)
- project.addAuxClasspathEntry((String) model.get(i));
- }
-
- private void resyncSourceEntries() {
- Project project = getCurrentProject();
- int numEntries = project.getNumSourceDirs();
- while (numEntries-- > 0)
- project.removeSourceDir(0);
-
- DefaultListModel model = (DefaultListModel) sourceDirList.getModel();
- for (int i = 0; i < model.size(); i++)
- project.addSourceDir((String) model.get(i));
- }
-
- /**
- * Localise the given AbstractButton, setting the text and optionally mnemonic
- * Note that AbstractButton includes menus and menu items.
- * @param button The button to localise
- * @param key The key to look up in resource bundle
- * @param defaultString default String to use if key not found
- * @param setMnemonic whether or not to set the mnemonic. According to Sun's
- * guidelines, default/cancel buttons should not have mnemonics
- * but instead should use Return/Escape
- */
- private void localiseButton(AbstractButton button, String key, String defaultString,
- boolean setMnemonic) {
- AnnotatedString.localiseButton(button, key, defaultString, setMnemonic);
- }
-
- /* ----------------------------------------------------------------------
- * Component initialization support
- * ---------------------------------------------------------------------- */
-
- /**
- * This is called from the constructor to perform post-initialization
- * of the components in the form.
- */
- private void postInitComponents() {
- logger = new ConsoleLogger(this);
-
- // Add menu items for bug categories to View->Filter Settings menu.
- // These are automatically localized assuming that a
- // BugCategoryDescriptions_<locale>.properties file exists
- // in edu.umd.cs.findbugs.
- Collection<String> bugCategoryCollection = edu.umd.cs.findbugs.I18N.instance().getBugCategories();
- this.bugCategoryCheckBoxList = new JCheckBoxMenuItem[bugCategoryCollection.size()];
- this.bugCategoryList = new String[bugCategoryCollection.size()];
- int count = 0;
- for (String bugCategory : bugCategoryCollection) {
- String bugCategoryDescription = I18N.instance().getBugCategoryDescription(bugCategory);
-
- final JCheckBoxMenuItem item = new JCheckBoxMenuItem(bugCategoryDescription, true);
- item.setFont(BUTTON_FONT);
- item.setSelected(getFilterSettings().containsCategory(bugCategory));
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent evt) {
- toggleBugCategory(item);
- }
- });
-
- filterWarningsMenu.add(item);
-
- this.bugCategoryCheckBoxList[count] = item;
- this.bugCategoryList[count] = bugCategory;
-
- ++count;
- }
-
- viewPanelLayout = (CardLayout) viewPanel.getLayout();
-
- // List of bug group tabs.
- // This must be in the same order as GROUP_BY_ORDER_LIST!
- bugTreeList = new JTree[]{byClassBugTree, byPackageBugTree, byBugTypeBugTree, byBugCategoryBugTree};
-
- // Configure bug trees
- for (JTree bugTree : bugTreeList) {
- bugTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
- bugTree.setCellRenderer(BugCellRenderer.instance());
- bugTree.setRootVisible(false);
- bugTree.setShowsRootHandles(true);
- bugTree.addTreeSelectionListener(new TreeSelectionListener() {
- public void valueChanged(TreeSelectionEvent e) {
- bugTreeSelectionChanged(e);
- }
- });
- }
-
- jarFileList.setModel(new DefaultListModel());
- sourceDirList.setModel(new DefaultListModel());
- classpathEntryList.setModel(new DefaultListModel());
-
- // We use a special highlight painter to ensure that the highlights cover
- // complete source lines, even though the source text doesn't
- // fill the lines completely.
- final Highlighter.HighlightPainter painter =
- new DefaultHighlighter.DefaultHighlightPainter(sourceTextArea.getSelectionColor()) {
- @Override
- public Shape paintLayer(Graphics g, int offs0, int offs1,
- Shape bounds, JTextComponent c, View view) {
- try {
- Shape extent = view.modelToView(offs0, Position.Bias.Forward, offs1, Position.Bias.Backward, bounds);
- Rectangle rect = extent.getBounds();
- rect.x = 0;
- rect.width = bounds.getBounds().width;
- g.setColor(getColor());
- g.fillRect(rect.x, rect.y, rect.width, rect.height);
- return rect;
- } catch (BadLocationException e) {
- return null;
- }
- }
- };
- Highlighter sourceHighlighter = new DefaultHighlighter() {
- @Override
- public Object addHighlight(int p0, int p1, Highlighter.HighlightPainter p)
- throws BadLocationException {
- return super.addHighlight(p0, p1, painter);
- }
- };
- sourceTextArea.setHighlighter(sourceHighlighter);
-
- updateTitle(getCurrentProject());
-
- // Load the icon for the UMD logo
- ClassLoader classLoader = this.getClass().getClassLoader();
- ImageIcon logoIcon = new ImageIcon(classLoader.getResource("edu/umd/cs/findbugs/gui/logo_umd.png"));
- logoLabel.setIcon(logoIcon);
-
- // Set common Menu Accelerators
- final int MENU_MASK = getMenuMask();
- newProjectItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, MENU_MASK));
- openProjectItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, MENU_MASK));
- saveProjectItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_MASK));
- closeProjectItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, MENU_MASK));
- reloadProjectItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_MASK));
-
- cutItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, MENU_MASK));
- copyItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, MENU_MASK));
- pasteItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, MENU_MASK));
- selectAllItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, MENU_MASK));
-
- if (MAC_OS_X) {
- // Some more accelerators that use modifiers. Other platforms
- // tend not to use modifiers for menu accelerators
- saveProjectAsItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_MASK | Event.SHIFT_MASK));
- loadBugsItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, MENU_MASK | Event.ALT_MASK));
- saveBugsItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_MASK | Event.ALT_MASK));
-
- // Leave room for the growBox on Mac
- growBoxSpacer.setMinimumSize(new java.awt.Dimension(16,16));
-
- // Remove Unnecessary/Redundant menu items.
- fileMenu.remove(exitItem);
- fileMenu.remove(jSeparator6);
- theMenuBar.remove(helpMenu);
-
- // Set up listeners for Quit and About menu items using
- // Apple's EAWT API.
- // We use reflection here, so there is no posible chance that the
- // class loader will try to load OSXAdapter on a non Mac system
- try {
- Class<?> osxAdapter = Class.forName("edu.umd.cs.findbugs.gui.OSXAdapter");
- Class<?>[] defArgs = {FindBugsFrame.class};
- Method registerMethod = osxAdapter.getDeclaredMethod("registerMacOSXApplication", defArgs);
- if (registerMethod != null) {
- Object[] args = {this};
- registerMethod.invoke(osxAdapter, args);
- }
- } catch (NoClassDefFoundError e) {
- // This will be thrown first if the OSXAdapter is loaded on a system without the EAWT
- // because OSXAdapter extends ApplicationAdapter in its def
- System.err.println("This version of Mac OS X does not support the Apple EAWT. Application Menu handling has been disabled (" + e + ")");
- } catch (ClassNotFoundException e) {
- // This shouldn't be reached; if there's a problem with the OSXAdapter we should get the
- // above NoClassDefFoundError first.
- System.err.println("This version of Mac OS X does not support the Apple EAWT. Application Menu handling has been disabled (" + e + ")");
- } catch (Exception e) {
- System.err.println("Exception while loading the OSXAdapter: " + e);
- if (FindBugs.DEBUG) {
- e.printStackTrace();
- }
- }
- }
-
- }
-
- private void rebuildRecentProjectsMenu() {
- UserPreferences prefs = UserPreferences.getUserPreferences();
- final List<String> recentProjects = prefs.getRecentProjects();
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- recentProjectsMenu.removeAll();
- java.awt.Font ft = BUTTON_FONT;
- if (recentProjects.size() == 0) {
- JMenuItem emptyItem = new JMenuItem(L10N.getLocalString("menu.empty_item", "Empty"));
- emptyItem.setFont(ft);
- emptyItem.setEnabled(false);
- recentProjectsMenu.add(emptyItem);
- } else {
- for (String recentProject : recentProjects) {
- JMenuItem projectItem = new JMenuItem(recentProject);
- projectItem.setFont(ft);
- projectItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent evt) {
- openRecentProjectItemActionPerformed(evt);
- }
- });
- recentProjectsMenu.add(projectItem);
- }
- }
- }
- });
- }
-
- /* ----------------------------------------------------------------------
- * Helpers for accessing and modifying UI components
- * ---------------------------------------------------------------------- */
-
- /**
- * Based on the current tree selection path, get a user object
- * whose class is the same as the given class.
- *
- * @param tree the tree
- * @param c the class
- * @return an instance of the given kind of object which is in the
- * current selection, or null if there is no matching object
- */
- private static <E> E getTreeSelectionOf(JTree tree, Class<E> c) {
- TreePath selPath = tree.getSelectionPath();
-
- // There may not be anything selected at the moment
- if (selPath == null)
- return null;
-
- // Work backwards from end until we get to the kind of
- // object we're looking for.
- Object[] nodeList = selPath.getPath();
- for (int i = nodeList.length - 1; i >= 0; --i) {
- DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodeList[i];
- Object nodeInfo = node.getUserObject();
- if (nodeInfo != null && nodeInfo.getClass() == c)
- return c.cast(nodeInfo);
- }
- return null;
- }
-
- /**
- * Get the current project.
- */
- private Project getCurrentProject() {
- return currentProject;
- }
-
- /**
- * Get the current analysis run.
- */
- private AnalysisRun getCurrentAnalysisRun() {
- return currentAnalysisRun;
- }
-
- /**
- * Get the bug instance currently selected in the bug tree.
- */
- private BugInstance getCurrentBugInstance() {
- JTree bugTree = getCurrentBugTree();
- if (bugTree != null) {
- return getTreeSelectionOf(bugTree, BugInstance.class);
- }
- return null;
- }
-
- /**
- * Return whether or not the given splitter is "maximized", meaning that
- * the top window of the split has been given all of the space.
- * Note that this window assumes that the split is vertical (meaning
- * that we have top and bottom components).
- *
- * @param splitter the JSplitPane
- * @param evt the event that is changing the splitter value
- */
- private boolean isSplitterMaximized(JSplitPane splitter, java.beans.PropertyChangeEvent evt) {
- Integer location = (Integer) evt.getNewValue();
-
- int height = splitter.getHeight();
- int hopefullyMaxDivider = height - (splitter.getDividerSize() + DIVIDER_FUDGE);
- //System.out.println("Splitter: "+(splitter==consoleSplitter?"consoleSplitter":"bugTreeBugDetailsSplitter")+
- // ": height="+height+",location="+location+
- // ",hopefullyMax="+hopefullyMaxDivider);
- boolean isMaximized = location.intValue() >= hopefullyMaxDivider;
- return isMaximized;
- }
-
- private void checkBugDetailsVisibility() {
- if (viewBugDetailsItem.isSelected()) {
- bugTreeBugDetailsSplitter.resetToPreferredSizes();
- } else {
- bugTreeBugDetailsSplitter.setDividerLocation(1.0);
- }
- //System.out.("New bug detail splitter location " + bugTreeBugDetailsSplitter.getDividerLocation());
- }
-
- private JTree getCurrentBugTree() {
- JScrollPane selected = (JScrollPane) groupByTabbedPane.getSelectedComponent();
- Object view = selected.getViewport().getView();
- if (view instanceof JTree) {
- return (JTree) view;
- }
- return null;
- }
-
- /* ----------------------------------------------------------------------
- * Synchronization of data model and UI
- * ---------------------------------------------------------------------- */
-
- /**
- * Set the priority threshold for display of bugs in the bug tree.
- *
- * @param threshold the threshold
- */
- private void setPriorityThreshold(int threshold) {
- if (threshold != getFilterSettings().getMinPriorityAsInt()) {
- getFilterSettings().setMinPriority(ProjectFilterSettings.getIntPriorityAsString(threshold));
- if (currentAnalysisRun != null)
- synchAnalysisRun(currentAnalysisRun);
- }
- }
-
- private void ableEditMenu() {
- String view = getView();
- if ((view != null) && view.equals("EditProjectPanel")) {
- if (selectedComponent != null) {
- boolean hasSelection = false;
- if (selectedComponent instanceof JList) {
- JList list = (JList)selectedComponent;
- hasSelection = list.getSelectedIndices().length > 0;
- } else if (selectedComponent instanceof JTextField) {
- JTextField tf = (JTextField)selectedComponent;
- hasSelection = ((tf.getSelectedText() != null) &&
- (tf.getSelectedText().length() > 0));
- }
-
- cutItem.setEnabled(hasSelection);
- copyItem.setEnabled(hasSelection);
- selectAllItem.setEnabled(true);
- }
- // } else if (view.equals("BugTree")) {
- // } else if (view.equals("ReportPanel")) {
-
- } else {
- cutItem.setEnabled(false);
- copyItem.setEnabled(true);
- pasteItem.setEnabled(false);
- selectAllItem.setEnabled(false);
- }
- }
-
- private void setProject(Project project) {
- currentProject = project;
- if (project != null) {
- synchProject(project);
- setView("EditProjectPanel");
- editMenu.setEnabled(true);
- viewProjectItem.setEnabled(true);
- viewProjectItem.setSelected(true);
- viewBugsItem.setEnabled(false);
- viewBugsItem.setSelected(false);
- } else {
- editMenu.setEnabled(false);
- viewProjectItem.setEnabled(false);
- viewProjectItem.setSelected(false);
- viewBugsItem.setEnabled(false);
- viewBugsItem.setSelected(false);
- setView("EmptyPanel");
- }
- updateTitle(project);
- ableEditMenu();
- }
-
- private void updateTitle(Project project) {
- if (project == null)
- this.setTitle(L10N.getLocalString("dlg.noproject_lbl", "FindBugs - no project"));
- else
- this.setTitle("FindBugs - " + project.toString());
- }
-
- /**
- * Save given project.
- * If the project already has a valid filename, use that filename.
- * Otherwise, prompt for one.
- *
- * @param project the Project to save
- * @param dialogTitle the title for the save dialog (if needed)
- */
- private boolean saveProject(Project project, String dialogTitle) {
- return saveProject(project, dialogTitle, false);
- }
-
- /**
- * Offer to save the current Project to a file.
- *
- * @param project the Project to save
- * @param dialogTitle the title for the save dialog (if needed)
- * @param chooseFilename if true, force a dialog to prompt the user
- * for a filename
- * @return true if the project is saved successfully, false if the user
- * cancels or an error occurs
- */
- private boolean saveProject(Project project, String dialogTitle, boolean chooseFilename) {
- boolean useRelativePaths;
- try {
- if (project == null)
- return true;
-
- File file;
- String fileName = project.getProjectFileName();
-
- if (!fileName.startsWith("<") && !chooseFilename) {
- file = new File(fileName);
- useRelativePaths = project.getOption( Project.RELATIVE_PATHS );
- } else {
- JRadioButton relativePaths = new JRadioButton(L10N.getLocalString("msg.userelativepaths_txt", "Use Relative Paths"));
- relativePaths.setSelected(project.getOption(Project.RELATIVE_PATHS));
- JFileChooser chooser = createFileChooser(relativePaths);
- chooser.setFileFilter(projectFileFilter);
- int result = chooseFile(chooser, dialogTitle);
- if (result == JFileChooser.CANCEL_OPTION)
- return false;
- file = chooser.getSelectedFile();
- fileName = Project.transformFilename(file.getPath());
- file = new File(fileName);
- useRelativePaths = relativePaths.isSelected();
- }
-
- project.write(file.getPath(), useRelativePaths, file.getParent());
- logger.logMessage(Logger.INFO, "Project saved");
- project.setProjectFileName(file.getPath());
-
- UserPreferences prefs = UserPreferences.getUserPreferences();
- prefs.useProject(file.getPath());
- prefs.read();
- rebuildRecentProjectsMenu();
-
- updateTitle(project);
-
- return true;
- } catch (IOException e) {
- logger.logMessage(Logger.ERROR, "Could not save project: " + e.toString());
- JOptionPane.showMessageDialog(this, "Error saving project: " + e.toString(),
- "Error", JOptionPane.ERROR_MESSAGE);
- return false;
- }
- }
-
- /**
- * Hook to call before closing a project.
- *
- * @param project the project being closed
- * @param savePromptTitle title to use for the "Save project?" dialog
- * @return true if user has confirmed that the project should be closed,
- * false if the close is cancelled
- */
- private boolean closeProjectHook(Project project, String savePromptTitle) {
- if (project == null || !project.isModified())
- return true;
-
- // Confirm that the project should be closed.
- int option = JOptionPane.showConfirmDialog(this, L10N.getLocalString("msg.saveprojectquery_txt", "Save Project?"), savePromptTitle,
- JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
-
- if (option == JOptionPane.CANCEL_OPTION)
- return false;
- else if (option == JOptionPane.YES_OPTION) {
- boolean result = saveProject(project, "Save Project");
- if (result)
- JOptionPane.showMessageDialog(this, "Project was successfully saved.");
- return result;
- } else
- return true;
- }
-
- /**
- * Synchronize the edit project dialog with given project.
- *
- * @param project the selected project
- */
- private void synchProject(Project project) {
- // Clear text fields
- jarNameTextField.setText("");
- srcDirTextField.setText("");
- classpathEntryTextField.setText("");
-
- // Populate jar file, source directory, and aux classpath entry lists
-
- DefaultListModel jarListModel = (DefaultListModel) jarFileList.getModel();
- jarListModel.clear();
- for (int i = 0; i < project.getFileCount(); ++i) {
- jarListModel.addElement(project.getFile(i));
- }
-
- DefaultListModel srcDirListModel = (DefaultListModel) sourceDirList.getModel();
- srcDirListModel.clear();
- for (int i = 0; i < project.getNumSourceDirs(); ++i) {
- srcDirListModel.addElement(project.getSourceDir(i));
- }
-
- DefaultListModel classpathEntryListModel = (DefaultListModel) classpathEntryList.getModel();
- classpathEntryListModel.clear();
- for (int i = 0; i < project.getNumAuxClasspathEntries(); ++i) {
- classpathEntryListModel.addElement(project.getAuxClasspathEntry(i));
- }
- }
-
- /**
- * Synchronize the bug trees with the given analysisRun object.
- *
- * @param analysisRun the selected analysis run
- */
- private void synchAnalysisRun(AnalysisRun analysisRun) {
- // Create and populate tree models
- for (int i = 0; i < GROUP_BY_ORDER_LIST.length; ++i) {
- DefaultMutableTreeNode bugRootNode = new DefaultMutableTreeNode();
- DefaultTreeModel bugTreeModel = new DefaultTreeModel(bugRootNode);
-
- String groupByOrder = GROUP_BY_ORDER_LIST[i];
- analysisRun.setTreeModel(groupByOrder, bugTreeModel);
- populateAnalysisRunTreeModel(analysisRun, groupByOrder);
- if (i < bugTreeList.length)
- bugTreeList[i].setModel(bugTreeModel);
- }
-
- currentAnalysisRun = analysisRun;
-
- //set the summary output
- setSummary(analysisRun.getSummary());
- setView("BugTree");
- }
-
- private void setSummary(String summaryXML) {
- bugSummaryEditorPane.setContentType("text/html");
- /*
- bugSummaryEditorPane.setText(summaryXML);
- // : unfortunately, using setText() on the editor pane
- // results in the contents being scrolled to the bottom of the pane.
- // An immediate inline call to set the scroll position does nothing.
- // So, use invokeLater(), even though this results in flashing.
- // [What we really need is a way to set the text WITHOUT changing
- // the caret position. Need to investigate.]
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- bySummary.getViewport().setViewPosition(new Point(0, 0));
- }
- });
- */
- StringReader reader = null;
- try {
- if (summaryXML != null) {
- reader = new StringReader(summaryXML); // no need for BufferedReader
- bugSummaryEditorPane.read(reader, "html summary");
- } else {
- bugSummaryEditorPane.setText("");
- }
- } catch (IOException e) {
- bugSummaryEditorPane.setText("Could not set summary: " + e.getMessage());
- logger.logMessage(Logger.WARNING, e.getMessage());
- } finally {
- if (reader != null)
- reader.close(); // polite, but doesn't do much in StringReader
- }
-
- }
-
- /**
- * Populate an analysis run's tree model for given sort order.
- */
- private void populateAnalysisRunTreeModel(AnalysisRun analysisRun, final String groupBy) {
- //System.out.println("Populating bug tree for order " + groupBy);
-
- // Set busy cursor - this is potentially a time-consuming operation
- Cursor orig = this.getCursor();
- this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
-
- final DefaultTreeModel bugTreeModel = analysisRun.getTreeModel(groupBy);
- final DefaultMutableTreeNode bugRootNode = (DefaultMutableTreeNode) bugTreeModel.getRoot();
-
- // Delete all children from root node
- bugRootNode.removeAllChildren();
-
- // Sort the instances (considering only those that meet the
- // priority threshold)
- TreeSet<BugInstance> sortedCollection = new TreeSet<BugInstance>(getBugInstanceComparator(groupBy));
- for (BugInstance bugInstance : analysisRun.getBugInstances()) {
- if (getFilterSettings().displayWarning(bugInstance))
- sortedCollection.add(bugInstance);
- }
-
- // The grouper callback is what actually adds the group and bug
- // nodes to the tree.
- Grouper.Callback<BugInstance> callback = new Grouper.Callback<BugInstance>() {
- private BugInstanceGroup currentGroup;
- private DefaultMutableTreeNode currentGroupNode;
-
- public void startGroup(BugInstance member) {
- String groupName;
- if (groupBy == GROUP_BY_CLASS)
- groupName = member.getPrimaryClass().getClassName();
- else if (groupBy == GROUP_BY_PACKAGE) {
- groupName = member.getPrimaryClass().getPackageName();
- if (groupName.equals(""))
- groupName = "Unnamed package";
- } else if (groupBy == GROUP_BY_BUG_TYPE) {
- String desc = member.toString();
- String shortBugType = desc.substring(0, desc.indexOf(':'));
- String bugTypeDescription = I18N.instance().getBugTypeDescription(shortBugType);
- groupName = shortBugType + ": " + bugTypeDescription;
- } else if (groupBy == GROUP_BY_BUG_CATEGORY) {
- BugPattern pattern = member.getBugPattern();
- if (pattern == null) {
- if (FindBugs.DEBUG)
- System.out.println("Unknown bug pattern " + member.getType());
- groupName = "Unknown category";
- } else {
- groupName = I18N.instance().getBugCategoryDescription(pattern.getCategory());
- }
- } else
- throw new IllegalStateException("Unknown sort order: " + groupBy);
- currentGroup = new BugInstanceGroup(groupBy, groupName);
- currentGroupNode = new DefaultMutableTreeNode(currentGroup);
- bugTreeModel.insertNodeInto(currentGroupNode, bugRootNode, bugRootNode.getChildCount());
-
- insertIntoGroup(member);
- }
-
- public void addToGroup(BugInstance member) {
- insertIntoGroup(member);
- }
-
- private void insertIntoGroup(BugInstance member) {
- int count = currentGroup.getMemberCount();
- currentGroup.incrementMemberCount();
- BugTreeNode bugNode = new BugTreeNode(member);
- if (BUG_COUNT)
- bugNode.setCount(count);
- bugTreeModel.insertNodeInto(bugNode, currentGroupNode, currentGroupNode.getChildCount());
-
- // Insert annotations
- Iterator<BugAnnotation> j = member.annotationIterator();
- while (j.hasNext()) {
- BugAnnotation annotation = j.next();
- DefaultMutableTreeNode annotationNode = new DefaultMutableTreeNode(annotation);
- bugTreeModel.insertNodeInto(annotationNode, bugNode, bugNode.getChildCount());
- }
-
- }
- };
-
- // Create the grouper, and execute it to populate the bug tree
- Grouper<BugInstance> grouper = new Grouper<BugInstance>(callback);
- Comparator<BugInstance> groupComparator = getGroupComparator(groupBy);
- grouper.group(sortedCollection, groupComparator);
-
- // Let the tree know it needs to update itself
- bugTreeModel.nodeStructureChanged(bugRootNode);
-
- // Now we're done
- this.setCursor(orig);
- }
-
- /**
- * Get a BugInstance Comparator for given sort order.
- */
- private Comparator<BugInstance> getBugInstanceComparator(String sortOrder) {
- if (sortOrder.equals(GROUP_BY_CLASS))
- return bugInstanceByClassComparator;
- else if (sortOrder.equals(GROUP_BY_PACKAGE))
- return bugInstanceByPackageComparator;
- else if (sortOrder.equals(GROUP_BY_BUG_TYPE))
- return bugInstanceByTypeComparator;
- else if (sortOrder.equals(GROUP_BY_BUG_CATEGORY))
- return bugInstanceByCategoryComparator;
- else
- throw new IllegalArgumentException("Bad sort order: " + sortOrder);
- }
-
- /**
- * Get a Grouper for a given sort order.
- */
- private Comparator<BugInstance> getGroupComparator(String groupBy) {
- if (groupBy.equals(GROUP_BY_CLASS)) {
- return bugInstanceClassComparator;
- } else if (groupBy.equals(GROUP_BY_PACKAGE)) {
- return bugInstancePackageComparator;
- } else if (groupBy.equals(GROUP_BY_BUG_TYPE)) {
- return bugInstanceTypeComparator;
- } else if (groupBy.equals(GROUP_BY_BUG_CATEGORY)) {
- return bugInstanceCategoryComparator;
- } else
- throw new IllegalArgumentException("Bad sort order: " + groupBy);
- }
-
- /**
- * Set the view panel to display the named view.
- */
- private void setView(String viewName) {
- //System.out.println("Showing view " + viewName);
- viewPanelLayout.show(viewPanel, viewName);
- boolean viewingBugs = viewName.equals("BugTree");
- if (viewingBugs)
- checkBugDetailsVisibility();
-
- viewProjectItem.setSelected(!viewingBugs);
- if (viewingBugs)
- viewBugsItem.setEnabled(true);
- viewBugsItem.setSelected(viewingBugs);
-
- currentView = viewName;
- ableEditMenu();
- }
-
- /**
- * Get which view is displayed currently.
- */
- private String getView() {
- return currentView;
- }
-
- /**
- * Called to add the jar file in the jarNameTextField to the
- * Jar file list (and the project it represents).
- */
- private void addJarToList() {
- String dirs = jarNameTextField.getText();
- String[] jarDirs = parsePaths(dirs);
- for (String jarFile : jarDirs) {
- if (!jarFile.equals("")) {
- addJarToProject(jarFile);
- }
- }
- jarNameTextField.setText("");
- }
-
- /**
- * Add a Src file to the current project.
- *
- * @param srcFile the jar file to add to the project
- */
- private void addSrcToProject(String srcFile) {
- Project project = getCurrentProject();
- if (project.addSourceDir(srcFile)) {
- DefaultListModel listModel = (DefaultListModel) sourceDirList.getModel();
- listModel.addElement(srcFile);
- }
- }
-
- /**
- * Add a Jar file to the current project.
- *
- * @param jarFile the jar file to add to the project
- */
- private void addJarToProject(String jarFile) {
- Project project = getCurrentProject();
- if (project.addFile(jarFile)) {
- DefaultListModel listModel = (DefaultListModel) jarFileList.getModel();
- listModel.addElement(jarFile);
- }
- }
-
- /**
- * Parses a classpath into it's sub paths
- *
- * @param path the classpath
- * @return an array of paths
- */
- private String[] parsePaths(String paths) {
- return paths.split(SystemProperties.getProperty("path.separator"));
- }
-
- /**
- * Called to add the source directory in the sourceDirTextField
- * to the source directory list (and the project it represents).
- */
- private void addSourceDirToList() {
- String dirs = srcDirTextField.getText();
- String[] sourceDirs = parsePaths(dirs);
- for (String sourceDir : sourceDirs) {
- if (!sourceDir.equals("")) {
- Project project = getCurrentProject();
- if (project.addSourceDir(sourceDir)) {
- DefaultListModel listModel = (DefaultListModel) sourceDirList.getModel();
- listModel.addElement(sourceDir);
- }
- }
- }
- srcDirTextField.setText("");
- }
-
- /**
- * Called to add the classpath entry in the classpathEntryTextField
- * to the classpath entry list (and the project it represents).
- */
- private void addClasspathEntryToList() {
- String dirs = classpathEntryTextField.getText();
- String[] classDirs = parsePaths(dirs);
- for (String classpathEntry : classDirs) {
- if (!classpathEntry.equals("")) {
- addClasspathEntryToProject(classpathEntry);
- }
- }
- classpathEntryTextField.setText("");
- }
-
- /**
- * Add a classpath entry to the current project.
- *
- * @param classpathEntry the classpath entry to add
- */
- private void addClasspathEntryToProject(String classpathEntry) {
- Project project = getCurrentProject();
- if (project.addAuxClasspathEntry(classpathEntry)) {
- DefaultListModel listModel = (DefaultListModel) classpathEntryList.getModel();
- listModel.addElement(classpathEntry);
- }
- }
-
- /**
- * Synchronize current bug instance with the bug detail
- * window (source view, details window, etc.)
- */
- private void synchBugInstance() {
- // Get current bug instance
- BugInstance selected = getCurrentBugInstance();
- if (selected == null)
- return;
-
- // If the details window is minimized, then the user can't see
- // it and there is no point in updating it.
- if (!viewBugDetailsItem.isSelected())
- return;
-
- // Get the current source line annotation.
- // If the current leaf selected is not a source line annotation,
- // or a method annotation containing a source line annotation.
- // use the default source line annotation from the current bug instance
- // (if any).
- JTree bugTree = getCurrentBugTree();
-
- // if the summary window is shown then skip it
- if (bugTree == null) {
- return;
- }
- SourceLineAnnotation srcLine = null;
- TreePath selPath = bugTree.getSelectionPath();
- if (selPath != null) {
- Object leaf = ((DefaultMutableTreeNode) selPath.getLastPathComponent()).getUserObject();
- if (leaf instanceof SourceLineAnnotation)
- srcLine = (SourceLineAnnotation) leaf;
- else if (leaf instanceof BugAnnotationWithSourceLines)
- srcLine = ((BugAnnotationWithSourceLines) leaf).getSourceLines();
-
- if (srcLine == null)
- srcLine = selected.getPrimarySourceLineAnnotation();
- }
-
- // Show source code.
- if (srcLine == null || srcLine != currentSourceLineAnnotation) {
- Project project = getCurrentProject();
- AnalysisRun analysisRun = getCurrentAnalysisRun();
- if (project == null) throw new IllegalStateException("null project!");
- if (analysisRun == null) throw new IllegalStateException("null analysis run!");
- try {
- boolean success = viewSource(project, analysisRun, srcLine);
- sourceTextArea.setEnabled(success);
- if (!success)
- sourceTextArea.setText("No source line information for this bug");
- } catch (IOException e) {
- sourceTextArea.setText("Could not find source: " + e.getMessage());
- logger.logMessage(Logger.WARNING, e.getMessage());
- }
-
- currentSourceLineAnnotation = srcLine;
- }
-
- // Show bug info.
- showBugInfo(selected);
-
- // Synch annotation text.
- synchBugAnnotation(selected);
-
- // Now the bug details are up to date.
- currentBugInstance = selected;
- }
-
- private static final int SELECTION_VOFFSET = 2;
-
- /**
- * Update the source view window.
- *
- * @param project the project (containing the source directories to search)
- * @param analysisRun the analysis run (containing the mapping of classes to source files)
- * @param srcLine the source line annotation (specifying source file to load and
- * which lines to highlight)
- * @return true if the source was shown successfully, false otherwise
- */
- private boolean viewSource(Project project, AnalysisRun analysisRun, final SourceLineAnnotation srcLine)
- throws IOException {
- // Get rid of old source code text
- sourceTextArea.setText("");
-
- // There is nothing to do without a source annotation
- // TODO: actually, might want to put a message in the source window
- // explaining that we don't have the source file, and that
- // they might want to recompile with debugging info turned on.
- if (srcLine == null)
- return false;
-
- SourceFinder sourceFinder = project.getSourceFinder();
-
- // Look up the source file for this class.
- String sourceFile;
- InputStream in;
- try {
- SourceFile source = sourceFinder.findSourceFile(srcLine);
- sourceFile = source.getFullFileName();
- in = source.getInputStream();
- } catch (IOException e) {
- logger.logMessage(Logger.WARNING, "No source file for class " + srcLine.getClassName());
- return false;
- }
-
- BufferedReader reader = null;
-
- try {
- reader = new BufferedReader(new InputStreamReader(in));
- sourceTextArea.read(reader, sourceFile); // 2nd arg is mostly ignored
- } finally {
- if (reader != null)
- reader.close();
- }
-
- if (srcLine.isUnknown()) {
- // No line number information, so can't highlight anything
-
- // There was code here to scroll to the top, but that isn't
- // needed because sourceTextArea.read() does that for us.
- return true;
- }
-
- // Highlight the annotation.
- // There seems to be some bug in Swing that sometimes prevents this code
- // from working when executed immediately after populating the
- // text in the text area. My guess is that when a large amount of text
- // is added, Swing defers some UI update work until "later" that is needed
- // to compute the visibility of text in the text area.
- // So, post some code to do the update to the Swing event queue.
- // Not really an ideal solution, but it seems to work.
- // note: Could reimplement this to use sourceTextArea.scrollRectToVisible(),
- // but if it ain't broke...
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- // Highlight the lines from the source annotation.
- // Note that the source lines start at 1, while the line numbers
- // in the text area start at 0.
- try {
- int startLine = srcLine.getStartLine() - 1;
- int endLine = srcLine.getEndLine();
-
- // Compute number of rows visible.
- // What a colossal pain in the ass this is.
- // You'd think there would be a convenient method to
- // return this information, but no.
- JViewport viewport = sourceTextAreaScrollPane.getViewport();
- Rectangle viewportRect = viewport.getViewRect();
- int topRow = sourceTextArea.getLineOfOffset(sourceTextArea.viewToModel(viewportRect.getLocation()));
- int bottomRow = sourceTextArea.getLineOfOffset(sourceTextArea.viewToModel(new Point(viewportRect.x, (viewportRect.y + viewportRect.height) - 1)));
- int numRowsVisible = bottomRow - topRow;
-
- // Scroll the window so the beginning of the
- // annotation text will be (approximately) centered.
- int viewLine = Math.max(startLine - (numRowsVisible > 0 ? numRowsVisible / 2 : 0), 0);
- int viewBegin = sourceTextArea.getLineStartOffset(viewLine);
- Rectangle viewRect = sourceTextArea.modelToView(viewBegin);
- viewport.setViewPosition(new Point(viewRect.x, viewRect.y));
-
- // Select (and highlight) the annotation.
- int selBegin = sourceTextArea.getLineStartOffset(startLine);
- int selEnd = sourceTextArea.getLineStartOffset(endLine);
- sourceTextArea.select(selBegin, selEnd);
- sourceTextArea.getCaret().setSelectionVisible(true);
- } catch (javax.swing.text.BadLocationException e) {
- logger.logMessage(Logger.ERROR, e.toString());
- }
- }
- });
-
- return true;
- }
-
- /**
- * Show descriptive text about the type of bug
- *
- * @param bugInstance the bug instance
- */
- private void showBugInfo(BugInstance bugInstance) {
- // Are we already showing details for this kind of bug?
- String bugDetailsKey = bugInstance.getType();
- if (bugDetailsKey.equals(currentBugDetailsKey))
- return;
-
- // Display the details
- String html = I18N.instance().getDetailHTML(bugDetailsKey);
- bugDescriptionEditorPane.setContentType("text/html");
- currentBugDetailsKey = bugDetailsKey;
- /*
- bugDescriptionEditorPane.setText(html);
-
- // : unfortunately, using setText() on the editor pane
- // results in the contents being scrolled to the bottom of the pane.
- // An immediate inline call to set the scroll position does nothing.
- // So, use invokeLater(), even though this results in flashing.
- // [What we really need is a way to set the text WITHOUT changing
- // the caret position. Need to investigate.]
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- bugDescriptionScrollPane.getViewport().setViewPosition(new Point(0, 0));
- }
- });
- */
- StringReader reader = new StringReader(html); // no need for BufferedReader
- try {
- bugDescriptionEditorPane.read(reader, "html bug description");
- } catch (IOException e) {
- bugDescriptionEditorPane.setText("Could not find bug description: " + e.getMessage());
- logger.logMessage(Logger.WARNING, e.getMessage());
- } finally {
- reader.close(); // polite, but doesn't do much in StringReader
- }
- }
-
- /**
- * Synchronize the bug annotation text with the current bug instance,
- * and update the annotation text with the new bug instance.
- *
- * @param selected the new BugInstance
- */
- private void synchBugAnnotation(BugInstance selected) {
- if (currentBugInstance != null) {
- String text = annotationTextArea.getText();
- try {
- currentBugInstance.setAnnotationText(text, null);
- } catch (SignInCancelledException e) {
- logger.logMessage(Logger.WARNING, e.getMessage());
- }
- }
-
- //annotationTextArea.setText(selected.getAnnotationText());
- String userAnnotation = selected.getAnnotationText();
- if (userAnnotation==null || userAnnotation.length()==0) {
- // this is the common case, so might as well optimize it
- annotationTextArea.setText("");
- return;
- }
- StringReader reader = new StringReader(userAnnotation); // no need for BufferedReader
- try {
- annotationTextArea.read(reader, "user annotation");
- } catch (IOException e) {
- annotationTextArea.setText("Could not find user annotation: " + e.getMessage());
- logger.logMessage(Logger.WARNING, e.getMessage());
- } finally {
- reader.close(); // polite, but doesn't do much in StringReader
- }
- }
-
- /**
- * Toggle a bug category checkbox.
- * Changes are reflected in the displayed bug trees (if any)
- * and also in the user preferences.
- *
- * @param checkBox the bug category checkbox
- */
- private void toggleBugCategory(JCheckBoxMenuItem checkBox) {
- int index = 0;
-
- while (index < bugCategoryCheckBoxList.length) {
- if (bugCategoryCheckBoxList[index] == checkBox)
- break;
- ++index;
- }
-
- if (index == bugCategoryCheckBoxList.length) {
- error("Could not find bug category checkbox");
- return;
- }
-
- boolean selected = checkBox.isSelected();
- String bugCategory = bugCategoryList[index];
-
- if (selected) {
- getFilterSettings().addCategory(bugCategory);
- } else {
- getFilterSettings().removeCategory(bugCategory);
- }
-
- if (currentAnalysisRun != null) {
- synchAnalysisRun(currentAnalysisRun);
- }
- }
-
- /* ----------------------------------------------------------------------
- * Misc. helpers
- * ---------------------------------------------------------------------- */
-
- /**
- * Show About
- */
- void about() {
- AboutDialog dialog = new AboutDialog(this, logger, true);
- dialog.setSize(600, 554);
- dialog.setLocationRelativeTo(null); // center the dialog
- dialog.setVisible(true);
- }
-
- /**
- * Exit the application.
- */
- @SuppressWarnings("DM_EXIT")
- void exitFindBugs() {
- // TODO: offer to save work, etc.
-// UserPreferences.getUserPreferences().storeUserDetectorPreferences();
- UserPreferences.getUserPreferences().write();
- System.exit(0);
- }
-
- /**
- * Create a file chooser dialog.
- * Ensures that the dialog will start in the current directory.
- *
- * @return the file chooser
- */
- private JFileChooser createFileChooser() {
- return new JFileChooser(currentDirectory);
- }
-
- /**
- * Create a file chooser dialog.
- * Ensures that the dialog will start in the current directory.
- *
- * @param extraComp The extra component to append to the dialog
- * @return the file chooser
- */
- private JFileChooser createFileChooser(final JComponent extraComp) {
- return new JFileChooser(currentDirectory) {
- private static final long serialVersionUID = 1L;
-
- @Override
- protected JDialog createDialog(Component parent) throws HeadlessException {
- JDialog dialog = super.createDialog(parent);
- dialog.getContentPane().add(extraComp, BorderLayout.SOUTH);
- dialog.setLocation(300, 200);
- dialog.setResizable(false);
- return dialog;
- }
- };
- }
-
- /**
- * Run a file chooser dialog.
- * If a file is chosen, then the current directory is updated.
- *
- * @param dialog the file chooser dialog
- * @param dialogTitle the dialog title
- * @return the outcome
- */
- private int chooseFile(JFileChooser dialog, String dialogTitle) {
- int outcome = dialog.showDialog(this, dialogTitle);
- return updateCurrentDirectoryFromDialog(dialog, outcome);
- }
-
- /**
- * Run a file chooser dialog to choose a file to open.
- * If a file is chosen, then the current directory is updated.
- *
- * @param dialog the file chooser dialog
- * @return the outcome
- */
- private int chooseFileToOpen(JFileChooser dialog) {
- int outcome = dialog.showOpenDialog(this);
- return updateCurrentDirectoryFromDialog(dialog, outcome);
- }
-
- private int updateCurrentDirectoryFromDialog(JFileChooser dialog, int outcome) {
- if (outcome != JFileChooser.CANCEL_OPTION) {
- File selectedFile = dialog.getSelectedFile();
- currentDirectory = selectedFile.getParentFile();
- }
- return outcome;
- }
-
- /**
- * Get the Logger.
- */
- public Logger getLogger() {
- return logger;
- }
-
- /**
- * Show an error dialog.
- */
- public void error(String message) {
- JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE);
- }
-
- /**
- * Write a message to the console window.
- *
- * @param message the message to write
- */
- public void writeToLog(String message) {
-// consoleMessageArea.append(message);
-// consoleMessageArea.append("\n");
- }
-
- /**
- * Fix up the path that is received from JFileChooser, if necessary
- * Double clicking a directory causes a repeated name, for some reason
- * such as a:\b\c\c when a:\b\c was chosen
- */
- public File verifyFileSelection(File pickedFile) {
- if (pickedFile.exists())
- return pickedFile;
-
- File parent = pickedFile.getParentFile();
- if ((parent != null) && parent.getName().equals(pickedFile.getName()))
- return parent;
-
- //Something bad has happened
- return pickedFile;
- }
-
- /**
- * Get the current ProjectFilterSettings.
- */
- public ProjectFilterSettings getFilterSettings() {
- return UserPreferences.getUserPreferences().getFilterSettings();
- }
-
- /**
- * Get the current priority threshold.
- */
- public int getPriorityThreshold() {
- return getFilterSettings().getMinPriorityAsInt();
- }
-
- /**
- * Get list of AnalysisFeatureSettings.
- *
- * @return list of AnalysisFeatureSettings
- */
- public AnalysisFeatureSetting[] getSettingList() {
- return settingList;
- }
-
- /* ----------------------------------------------------------------------
- * main() method
- * ---------------------------------------------------------------------- */
-
- private static class SwingCommandLine extends FindBugsCommandLine {
- public SwingCommandLine() {
- addSwitch("-debug", "enable debug output");
- addSwitchWithOptionalExtraPart("-look", "plastic|gtk|native", "set look and feel");
- addOption("-project", "project file", "load given project");
- addOption("-priority", "thread priority",
- "set analysis thread's priority level (default is " +
- (Thread.NORM_PRIORITY-1) + ")");
- addOption("-loadbugs", "bugs xml filename", "load given bugs xml file");
- }
-
- String bugsFilename = "";
-
- public String getBugsFilename() {
- return bugsFilename;
- }
-
- // Thread priority for the analysis thread. The default is
- // just below the priority of the GUI
- private int priority = Thread.NORM_PRIORITY-1;
-
- /**
- * Retrieve thread priority for the analysis thread.
- * @return thread priority for the analysis thread
- */
- public int getPriority() {
- return priority;
- }
-
- @Override
- protected void handleOption(String option, String optionExtraPart) {
- if (option.equals("-debug")) {
- System.out.println("Setting findbugs.debug=true");
- System.setProperty("findbugs.debug", "true");
- } else if (option.equals("-look")) {
- String arg = optionExtraPart;
-
- String theme = null;
- if (arg.equals("plastic")) {
- // You can get the Plastic look and feel from jgoodies.com:
- // http://www.jgoodies.com/downloads/libraries.html
- // Just put "plastic.jar" in the lib directory, right next
- // to the other jar files.
- theme = "com.jgoodies.plaf.plastic.PlasticXPLookAndFeel";
- } else if (arg.equals("gtk")) {
- theme = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
- } else if (arg.equals("native")) {
- theme = UIManager.getSystemLookAndFeelClassName();
- } else {
- System.err.println("Style '" + arg + "' not supported");
- }
-
- if (theme != null) {
- try {
- UIManager.setLookAndFeel(theme);
- } catch (Exception e) {
- System.err.println("Couldn't load " + arg +
- " look and feel: " + e.toString());
- }
- }
- } else {
- super.handleOption(option, optionExtraPart);
- }
- }
-
-
- @Override
- protected void handleOptionWithArgument(String option, String argument) throws IOException {
- if (option.equals("-loadbugs")) {
- bugsFilename = argument;
- } else if (option.equals("-priority")) {
- int num;
- try {
- num = Integer.parseInt(argument);
- } catch(NumberFormatException e) {
- num = Thread.NORM_PRIORITY-1;
- }
- priority = num;
- } else {
- super.handleOptionWithArgument(option, argument);
- }
- }
- }
-
- /**
- * Invoke from the command line.
- *
- * @param args the command line arguments
- * @throws IOException
- */
- public static void main(String args[]) throws IOException {
- Project project = null;
-
- SwingCommandLine commandLine = new SwingCommandLine();
- try {
- commandLine.parse(args);
- } catch (IllegalArgumentException e) {
- System.err.println("Error: " + e.getMessage());
- showSynopsis();
- ShowHelp.showGeneralOptions();
- showCommandLineOptions();
- System.exit(1);
- } catch (HelpRequestedException e) {
- showSynopsis();
- ShowHelp.showGeneralOptions();
- showCommandLineOptions();
- System.exit(1);
- }
-
- if (commandLine.getProject().getFileCount() > 0) {
- project = commandLine.getProject();
- }
-
- // Uncomment one of these to test I18N
- // Locale.setDefault( Locale.FRENCH );
- // Locale.setDefault( Locale.GERMAN );
- // Locale.setDefault( Locale.JAPANESE );
- // Locale.setDefault( new Locale( "et" ));
- // Locale.setDefault( new Locale( "fi" ));
- // Locale.setDefault( new Locale( "es" ));
- // Locale.setDefault( new Locale( "pl" ));
-
- // Load plugins!
- DetectorFactoryCollection.instance();
-
- FindBugsFrame frame = new FindBugsFrame();
-
- if (project != null) {
- frame.setProject(project);
- } else if (commandLine.getBugsFilename().length() > 0) {
- try {
- File bugsFile = new File(commandLine.getBugsFilename());
- frame.loadBugsFromFile(bugsFile);
- } catch (Exception e) {
- System.err.println("Error: " + e.getMessage());
- }
- } else if (SystemProperties.getProperty("findbugs.loadBugsFromURL") != null) {
- // Allow JNLP launch to specify the URL of a report to load
- try {
- String urlspec = SystemProperties.getProperty("findbugs.loadBugsFromURL");
- frame.loadBugsFromURL(urlspec);
- } catch (Exception e) {
- System.err.println("Error: " + e.getMessage());
- }
- }
-
- frame.setPriority(commandLine.getPriority());
-
- if (commandLine.getSettingList() != null) {
- frame.settingList = commandLine.getSettingList();
- if (Arrays.equals(frame.settingList,FindBugs.MIN_EFFORT))
- frame.minEffortItem.setSelected(true);
- else if (Arrays.equals(frame.settingList, FindBugs.MAX_EFFORT))
- frame.maxEffortItem.setSelected(true);
- }
-
- frame.setSize(800, 600);
- frame.setLocationRelativeTo(null); // center the frame
- frame.setVisible(true);
- }
-
- private int analysisPriority = Thread.NORM_PRIORITY-1;
-
- public void setPriority(int priority) {
- this.analysisPriority = priority;
- }
-
- public static void showCommandLineOptions() {
- System.out.println("GUI options:");
- new SwingCommandLine().printUsage(System.out);
- }
-
- public static void showSynopsis() {
- System.out.println("Usage: findbugs [general options] [gui options]");
- }
-
- /* ----------------------------------------------------------------------
- * Instance variables
- * ---------------------------------------------------------------------- */
-
- // Variables declaration - do not modify//GEN-BEGIN:variables
- private javax.swing.JMenuItem aboutItem;
- private javax.swing.JButton addClasspathEntryButton;
- private javax.swing.JButton addJarButton;
- private javax.swing.JButton addSourceDirButton;
- private javax.swing.JTextArea annotationTextArea;
- private javax.swing.JScrollPane annotationTextAreaScrollPane;
- private javax.swing.JButton browseClasspathEntryButton;
- private javax.swing.JButton browseJarButton;
- private javax.swing.JButton browseSrcDirButton;
- private javax.swing.JEditorPane bugDescriptionEditorPane;
- private javax.swing.JScrollPane bugDescriptionScrollPane;
- private javax.swing.JTabbedPane bugDetailsTabbedPane;
- private javax.swing.JEditorPane bugSummaryEditorPane;
- private javax.swing.JSplitPane bugTreeBugDetailsSplitter;
- private javax.swing.JPanel bugTreePanel;
- private javax.swing.JTree byBugCategoryBugTree;
- private javax.swing.JScrollPane byBugCategoryScrollPane;
- private javax.swing.JTree byBugTypeBugTree;
- private javax.swing.JScrollPane byBugTypeScrollPane;
- private javax.swing.JTree byClassBugTree;
- private javax.swing.JScrollPane byClassScrollPane;
- private javax.swing.JTree byPackageBugTree;
- private javax.swing.JScrollPane byPackageScrollPane;
- private javax.swing.JScrollPane bySummary;
- private javax.swing.JButton classpathDownButton;
- private javax.swing.JLabel classpathEntryLabel;
- private javax.swing.JList classpathEntryList;
- private javax.swing.JLabel classpathEntryListLabel;
- private javax.swing.JScrollPane classpathEntryListScrollPane;
- private javax.swing.JTextField classpathEntryTextField;
- private javax.swing.JButton classpathUpButton;
- private javax.swing.JMenuItem closeProjectItem;
- private javax.swing.JMenuItem configureDetectorsItem;
- private javax.swing.JMenuItem copyItem;
- private javax.swing.JMenuItem cutItem;
- private javax.swing.JMenu editMenu;
- private javax.swing.JLabel editProjectLabel;
- private javax.swing.JPanel editProjectPanel;
- private javax.swing.ButtonGroup effortButtonGroup;
- private javax.swing.JMenu effortMenu;
- private javax.swing.JPanel emptyPanel;
- private javax.swing.JMenuItem exitItem;
- private javax.swing.JRadioButtonMenuItem expPriorityButton;
- private javax.swing.JMenu fileMenu;
- private javax.swing.JMenu filterWarningsMenu;
- private javax.swing.JButton findBugsButton;
- private javax.swing.JCheckBoxMenuItem fullDescriptionsItem;
- private javax.swing.JTabbedPane groupByTabbedPane;
- private javax.swing.JLabel growBoxSpacer;
- private javax.swing.JMenu helpMenu;
- private javax.swing.JRadioButtonMenuItem highPriorityButton;
- private javax.swing.JPanel jPanel1;
- private javax.swing.JSeparator jSeparator1;
- private javax.swing.JSeparator jSeparator10;
- private javax.swing.JSeparator jSeparator11;
- private javax.swing.JSeparator jSeparator2;
- private javax.swing.JSeparator jSeparator3;
- private javax.swing.JSeparator jSeparator4;
- private javax.swing.JSeparator jSeparator5;
- private javax.swing.JSeparator jSeparator6;
- private javax.swing.JSeparator jSeparator7;
- private javax.swing.JSeparator jSeparator8;
- private javax.swing.JSeparator jSeparator9;
- private javax.swing.JLabel jarFileLabel;
- private javax.swing.JList jarFileList;
- private javax.swing.JLabel jarFileListLabel;
- private javax.swing.JScrollPane jarFileListScrollPane;
- private javax.swing.JTextField jarNameTextField;
- private javax.swing.JMenuItem loadBugsItem;
- private javax.swing.JLabel logoLabel;
- private javax.swing.JRadioButtonMenuItem lowPriorityButton;
- private javax.swing.JCheckBoxMenuItem maxEffortItem;
- private javax.swing.JRadioButtonMenuItem mediumPriorityButton;
- private javax.swing.JCheckBoxMenuItem minEffortItem;
- private javax.swing.JMenuItem newProjectItem;
- private javax.swing.JCheckBoxMenuItem normalEffortItem;
- private javax.swing.JMenuItem openProjectItem;
- private javax.swing.JMenuItem pasteItem;
- private javax.swing.ButtonGroup priorityButtonGroup;
- private javax.swing.JMenu recentProjectsMenu;
- private javax.swing.JMenuItem reloadProjectItem;
- private javax.swing.JButton removeClasspathEntryButton;
- private javax.swing.JButton removeJarButton;
- private javax.swing.JButton removeSrcDirButton;
- private javax.swing.JPanel reportPanel;
- private javax.swing.JMenuItem saveBugsItem;
- private javax.swing.JMenuItem saveProjectAsItem;
- private javax.swing.JMenuItem saveProjectItem;
- private javax.swing.JMenuItem selectAllItem;
- private javax.swing.JMenu settingsMenu;
- private javax.swing.JLabel sourceDirLabel;
- private javax.swing.JList sourceDirList;
- private javax.swing.JLabel sourceDirListLabel;
- private javax.swing.JScrollPane sourceDirListScrollPane;
- private javax.swing.JButton sourceDownButton;
- private javax.swing.JTextArea sourceTextArea;
- private LineNumberer sourceLineNumberer;
- private javax.swing.JScrollPane sourceTextAreaScrollPane;
- private javax.swing.JButton sourceUpButton;
- private javax.swing.JTextField srcDirTextField;
- private javax.swing.JMenuBar theMenuBar;
- private javax.swing.JLabel urlLabel;
- private javax.swing.JCheckBoxMenuItem viewBugDetailsItem;
- private javax.swing.JRadioButtonMenuItem viewBugsItem;
- private javax.swing.JMenu viewMenu;
- private javax.swing.JPanel viewPanel;
- private javax.swing.JRadioButtonMenuItem viewProjectItem;
- // End of variables declaration//GEN-END:variables
-
- // My variable declarations
- private Logger logger;
- private CardLayout viewPanelLayout;
- private String currentView;
- private File currentDirectory;
- private Project currentProject;
- private JTree[] bugTreeList;
- private AnalysisRun currentAnalysisRun;
- private BugInstance currentBugInstance; // be lazy in switching bug instance details
- private SourceLineAnnotation currentSourceLineAnnotation; // as above
- private String currentBugDetailsKey;
- private JCheckBoxMenuItem[] bugCategoryCheckBoxList;
- private String[] bugCategoryList;
- private AnalysisFeatureSetting[] settingList = FindBugs.DEFAULT_EFFORT;
-
- // My constant declarations
- private final static boolean MAC_OS_X = SystemProperties.getProperty("os.name").toLowerCase().startsWith("mac os x");
-
- private static int getMenuMask() {
- return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- }
-
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/Grouper.java b/src/obsolete/edu/umd/cs/findbugs/gui/Grouper.java
deleted file mode 100644
index c4d1538..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/Grouper.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2003,2004 University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * Grouper.java
- *
- * Created on April 5, 2003, 3:46 PM
- */
-
-package edu.umd.cs.findbugs.gui;
-
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Iterator;
-
-/**
- * Given a sorted Collection and a Comparator, produces groups of objects
- * that compare as equal. If the Collection is not sorted, this
- * class will not work correctly.
- *
- * @author David Hovemeyer
- */
-public class Grouper <ElementType> {
-
- public interface Callback <ElementType2> {
- public void startGroup(ElementType2 firstMember);
-
- public void addToGroup(ElementType2 member);
- }
-
- private Callback<ElementType> callback;
-
- /**
- * Creates a new instance of Grouper.
- *
- * @param callback the callback which receives the groups and elements
- */
- public Grouper(Callback<ElementType> callback) {
- this.callback = callback;
- }
-
- /**
- * Group elements of given collection according to given
- * compartor's test for equality. The groups are specified by
- * calls to the Grouper's callback object.
- *
- * @param collection the collection
- * @param comparator the comparator
- */
- public void group(Collection<ElementType> collection, Comparator<ElementType> comparator) {
- Iterator<ElementType> i = collection.iterator();
- ElementType last = null;
- while (i.hasNext()) {
- ElementType current = i.next();
- if (last != null && comparator.compare(last, current) == 0) {
- // Same group as before
- callback.addToGroup(current);
- } else {
- // Start of a new group
- callback.startGroup(current);
- }
-
- last = current;
- }
- }
-
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/LineNumberer.java b/src/obsolete/edu/umd/cs/findbugs/gui/LineNumberer.java
deleted file mode 100644
index 4005e39..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/LineNumberer.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2005 Dave Brosius <dbrosius at users.sourceforge.net>
- * Copyright (C) 2005 University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package edu.umd.cs.findbugs.gui;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Font;
-import java.awt.FontMetrics;
-import java.awt.Graphics;
-import java.awt.Rectangle;
-
-import javax.swing.JComponent;
-import javax.swing.JTextArea;
-
-public class LineNumberer extends JComponent
-{
- public static final int PAD = 10;
- public static final String PROTOTYPE = "00000";
-
- private JTextArea textArea;
- private FontMetrics fm;
-
- public LineNumberer(JTextArea ta) {
- setFont( ta.getFont() );
- textArea = ta;
- setForeground( Color.BLUE );
-
- fm = this.getFontMetrics(ta.getFont());
- setWidths();
- }
-
- @Override
- public void setFont(Font font)
- {
- //ignore
- }
-
- private void setWidths() {
- int width = fm.stringWidth( PROTOTYPE );
- Dimension d = getPreferredSize();
- d.setSize(PAD + width, Integer.MAX_VALUE);
- setPreferredSize( d );
- setSize( d );
- }
-
-
- @Override
- public void paintComponent(Graphics g)
- {
- int lineHeight = fm.getHeight();
- int startOffset = textArea.getInsets().top + fm.getAscent();
-
- Rectangle clip = g.getClipBounds();
-
- g.setColor( getBackground() );
- g.fillRect(clip.x, clip.y, clip.width, clip.height);
-
- g.setColor( getForeground() );
- int beginLineNumber = (clip.y / lineHeight) + 1;
- int endLineNumber = beginLineNumber + (clip.height / lineHeight);
-
- int y = (clip.y / lineHeight) * lineHeight + startOffset;
-
- for (int i = beginLineNumber; i <= endLineNumber; i++)
- {
- String ln = String.valueOf(i);
- int width = fm.stringWidth( ln );
- int rowWidth = getSize().width;
- g.drawString(ln, rowWidth - width - PAD, y);
- y += lineHeight;
- }
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/OSXAdapter.java b/src/obsolete/edu/umd/cs/findbugs/gui/OSXAdapter.java
deleted file mode 100644
index baee45c..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/OSXAdapter.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package edu.umd.cs.findbugs.gui;
-
-import com.apple.eawt.ApplicationAdapter;
-import com.apple.eawt.ApplicationEvent;
-
-/*
- * Based on sample code from Apple.
- *
- * This is the only class that uses the Apple specific EAWT classes.
- * This class should only ever be referenced via reflection after
- * checking that we are running on Mac OS X.
- */
-public class OSXAdapter extends ApplicationAdapter {
-
- // pseudo-singleton model; no point in making multiple instances
- // of the EAWT application or our adapter
- private static OSXAdapter theAdapter;
- private static com.apple.eawt.Application theApplication;
-
- // reference to the app where the existing quit, about, prefs code is
- private FindBugsFrame mainApp;
-
- private OSXAdapter (FindBugsFrame inApp) {
- mainApp = inApp;
- }
-
- // implemented handler methods. These are basically hooks into
- // existing functionality from the main app, as if it came
- // over from another platform.
-
- @Override
- public void handleAbout(ApplicationEvent ae) {
- if (mainApp != null) {
- ae.setHandled(true);
- // We need to invoke modal About Dialog asynchronously
- // otherwise the Application queue is locked for the duration
- // of the about Dialog, which results in a deadlock if a URL is
- // selected, and we get a ReOpenApplication event when user
- // switches back to Findbugs.
- javax.swing.SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- mainApp.about();
- }
- });
- } else {
- throw new IllegalStateException("handleAbout: " +
- "MyApp instance detached from listener");
- }
- }
-
- @Override
- public void handlePreferences(ApplicationEvent ae) {
- if (mainApp != null) {
-// mainApp.preferences();
- ae.setHandled(true);
- } else {
- throw new IllegalStateException("handlePreferences: MyApp instance " +
- "detached from listener");
- }
- }
-
- @Override
- public void handleQuit(ApplicationEvent ae) {
- if (mainApp != null) {
-
- /*
- * You MUST setHandled(false) if you want to
- * delay or cancel the quit. This is important
- * for cross-platform development -- have a
- * universal quit routine that chooses whether
- * or not to quit, so the functionality is
- * identical on all platforms. This example
- * simply cancels the AppleEvent-based quit and
- * defers to that universal method.
- */
-
- ae.setHandled(false);
- mainApp.exitFindBugs();
- } else {
- throw new IllegalStateException("handleQuit: MyApp instance detached " +
- "from listener");
- }
- }
-
-
- // The main entry-point for this functionality. This is the only method
- // that needs to be called at runtime, and it can easily be done using
- // reflection (see MyApp.java)
- public static synchronized void registerMacOSXApplication(FindBugsFrame inApp) {
- if (theApplication == null) {
- theApplication = new com.apple.eawt.Application();
- }
-
- if (theAdapter == null) {
- theAdapter = new OSXAdapter(inApp);
- }
- theApplication.addApplicationListener(theAdapter);
- }
-
- // Another static entry point for EAWT functionality. Enables the
- // "Preferences..." menu item in the application menu.
- public static synchronized void enablePrefs(boolean enabled) {
- if (theApplication == null) {
- theApplication = new com.apple.eawt.Application();
- }
- theApplication.setEnabledPreferencesMenu(enabled);
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/RunAnalysisDialog.form b/src/obsolete/edu/umd/cs/findbugs/gui/RunAnalysisDialog.form
deleted file mode 100644
index e209f8f..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/RunAnalysisDialog.form
+++ /dev/null
@@ -1,152 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.0" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
- <Properties>
- <Property name="title" type="java.lang.String" value="Run Analysis" postCode="this.setTitle(L10N.getLocalString("dlg.runanalysis_ttl", "Run Analysis"));"/>
- </Properties>
- <SyntheticProperties>
- <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
- </SyntheticProperties>
- <Events>
- <EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="closeDialog"/>
- <EventHandler event="windowOpened" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowOpened"/>
- </Events>
-
- <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
- <SubComponents>
- <Component class="javax.swing.JLabel" name="findBugsLabel">
- <Properties>
- <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
- <Color blue="cc" green="0" red="0" type="rgb"/>
- </Property>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="24" style="1"/>
- </Property>
- <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
- <Color blue="ff" green="ff" red="ff" type="rgb"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Find Bugs!"/>
- <Property name="opaque" type="boolean" value="true"/>
- </Properties>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="-1" gridY="-1" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="11" weightX="1.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="countLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Count:"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="countLabel.setText(L10N.getLocalString("dlg.count_lbl", "Count:"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="13" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="progressLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Progress:"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="progressLabel.setText(L10N.getLocalString("dlg.progress_lbl", "Progress:"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="5" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="13" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JProgressBar" name="progressBar">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="5" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JButton" name="cancelButton">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Cancel"/>
- </Properties>
- <Events>
- <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
- </Events>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="cancelButton.setText(L10N.getLocalString("dlg.cancel_btn", "Cancel"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="8" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JSeparator" name="jSeparator1">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="7" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="stageLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- <Property name="text" type="java.lang.String" value="Stage:"/>
- </Properties>
- <AuxValues>
- <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="stageLabel.setText(L10N.getLocalString("dlg.stage_lbl", "Stage:"));"/>
- </AuxValues>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="13" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="stageNameLabel">
- <Properties>
- <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
- <Font name="Dialog" size="12" style="0"/>
- </Property>
- </Properties>
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="topVerticalFiller">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="6" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.5"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="bottomVerticalFiller">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.5"/>
- </Constraint>
- </Constraints>
- </Component>
- <Component class="javax.swing.JLabel" name="countValueLabel">
- <Constraints>
- <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
- <GridBagConstraints gridX="1" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
- </Constraint>
- </Constraints>
- </Component>
- </SubComponents>
-</Form>
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/RunAnalysisDialog.java b/src/obsolete/edu/umd/cs/findbugs/gui/RunAnalysisDialog.java
deleted file mode 100644
index 3acd457..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/RunAnalysisDialog.java
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2003,2004 University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * RunAnalysisDialog.java
- *
- * Created on April 1, 2003, 3:22 PM
- */
-
-package edu.umd.cs.findbugs.gui;
-
-import java.awt.event.WindowEvent;
-
-import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
-
-import edu.umd.cs.findbugs.FindBugsProgress;
-import edu.umd.cs.findbugs.L10N;
-
-/**
- * A modal dialog to run the actual FindBugs analysis on a project.
- * The analysis is done in a separate thread, so that the GUI can
- * still stay current while the analysis is running. We provide support
- * for reporting the progress of the analysis, and for asynchronously
- * cancelling the analysis before it completes.
- *
- * @author David Hovemeyer
- */
-public class RunAnalysisDialog extends javax.swing.JDialog {
- private static final long serialVersionUID = 1L;
-
- private class RunAnalysisProgress implements FindBugsProgress {
- private int goal, count;
-
- private synchronized int getGoal() {
- return goal;
- }
-
- private synchronized int getCount() {
- return count;
- }
-
- public void reportNumberOfArchives(final int numArchives) {
- beginStage(L10N.getLocalString("msg.scanningarchives_txt", "Scanning archives"), numArchives);
- }
-
- public void finishArchive() {
- step();
- }
-
- public void startAnalysis(int numClasses) {
- beginStage(L10N.getLocalString("msg.analysingclasses_txt", "Analyzing classes"), numClasses);
- }
-
- public void finishClass() {
- step();
- }
-
- public void finishPerClassAnalysis() {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- stageNameLabel.setText(L10N.getLocalString("msg.finishedanalysis_txt", "Finishing analysis"));
- }
- });
- }
-
- private void beginStage(final String stageName, final int goal) {
- synchronized (this) {
- this.count = 0;
- this.goal = goal;
- }
-
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- int goal = getGoal();
- stageNameLabel.setText(stageName);
- countValueLabel.setText("0/" + goal);
- progressBar.setMaximum(goal);
- progressBar.setValue(0);
- }
- });
- }
-
- private void step() {
- synchronized (this) {
- count++;
- }
-
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- int count = getCount();
- int goal = getGoal();
- countValueLabel.setText(count + "/" + goal);
- progressBar.setValue(count);
- }
- });
- }
-
- public void predictPassCount(int[] classesPerPass) {
- // noop
- }
-
- public void startArchive(String name) {
- // noop
- }
- }
-
- private final AnalysisRun analysisRun;
- private Thread analysisThread;
- private boolean completed;
- private Exception fatalException;
- private int analysisPriority;
-
- /**
- * Creates new form RunAnalysisDialog
- */
- public RunAnalysisDialog(java.awt.Frame parent, AnalysisRun analysisRun_, int analysisPriority) {
- super(parent, true);
- initComponents();
- this.analysisRun = analysisRun_;
- this.completed = false;
- this.analysisPriority = analysisPriority;
-
- // Create a progress callback to give the user feedback
- // about how far along we are.
- final FindBugsProgress progress = new RunAnalysisProgress();
-
- // This is the thread that will actually run the analysis.
- this.analysisThread = new Thread() {
- @Override
- public void run() {
- try {
- analysisRun.execute(progress);
- setCompleted(true);
- } catch (java.io.IOException e) {
- setException(e);
- } catch (InterruptedException e) {
- // We don't need to do anything here.
- // The completed flag is not set, so the frame
- // will know that the analysis did not complete.
- } catch (Exception e) {
- setException(e);
- }
-
- // Send a message to the dialog that it should close
- // That way, it goes away without any need for user intervention
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- closeDialog(new WindowEvent(RunAnalysisDialog.this, WindowEvent.WINDOW_CLOSING));
- }
- });
- }
- };
- }
-
- public synchronized void setCompleted(boolean completed) {
- this.completed = completed;
- }
-
- /**
- * The creator of the dialog may call this method to find out whether
- * or not the analysis completed normally.
- */
- public synchronized boolean isCompleted() {
- return completed;
- }
-
- public synchronized void setException(Exception e) {
- fatalException = e;
- }
-
- /**
- * Determine whether or not a fatal exception occurred
- * during analysis.
- */
- public synchronized boolean exceptionOccurred() {
- return fatalException != null;
- }
-
- /**
- * Get the exception that abnormally terminated the analysis.
- */
- public synchronized Exception getException() {
- return fatalException;
- }
-
- /**
- * This method is called from within the constructor to
- * initialize the form.
- * WARNING: Do NOT modify this code. The content of this method is
- * always regenerated by the Form Editor.
- */
- private void initComponents() {//GEN-BEGIN:initComponents
- java.awt.GridBagConstraints gridBagConstraints;
-
- findBugsLabel = new javax.swing.JLabel();
- countLabel = new javax.swing.JLabel();
- progressLabel = new javax.swing.JLabel();
- progressBar = new javax.swing.JProgressBar();
- cancelButton = new javax.swing.JButton();
- jSeparator1 = new javax.swing.JSeparator();
- stageLabel = new javax.swing.JLabel();
- stageNameLabel = new javax.swing.JLabel();
- topVerticalFiller = new javax.swing.JLabel();
- bottomVerticalFiller = new javax.swing.JLabel();
- countValueLabel = new javax.swing.JLabel();
-
- getContentPane().setLayout(new java.awt.GridBagLayout());
-
- setTitle("Run Analysis");
- this.setTitle(L10N.getLocalString("dlg.runanalysis_ttl", "Run Analysis"));
- addWindowListener(new java.awt.event.WindowAdapter() {
- @Override
- public void windowClosing(java.awt.event.WindowEvent evt) {
- closeDialog(evt);
- }
- @Override
- public void windowOpened(java.awt.event.WindowEvent evt) {
- formWindowOpened(evt);
- }
- });
-
- findBugsLabel.setBackground(new java.awt.Color(0, 0, 204));
- findBugsLabel.setFont(new java.awt.Font("Dialog", 1, 24));
- findBugsLabel.setForeground(new java.awt.Color(255, 255, 255));
- findBugsLabel.setText("Find Bugs!");
- findBugsLabel.setOpaque(true);
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridwidth = 2;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
- gridBagConstraints.weightx = 1.0;
- gridBagConstraints.insets = new java.awt.Insets(0, 0, 3, 0);
- getContentPane().add(findBugsLabel, gridBagConstraints);
-
- countLabel.setFont(new java.awt.Font("Dialog", 0, 12));
- countLabel.setText("Count:");
- countLabel.setText(L10N.getLocalString("dlg.count_lbl", "Count:"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
- gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
- getContentPane().add(countLabel, gridBagConstraints);
-
- progressLabel.setFont(new java.awt.Font("Dialog", 0, 12));
- progressLabel.setText("Progress:");
- progressLabel.setText(L10N.getLocalString("dlg.progress_lbl", "Progress:"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 5;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
- gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
- getContentPane().add(progressLabel, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 5;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
- getContentPane().add(progressBar, gridBagConstraints);
-
- cancelButton.setFont(new java.awt.Font("Dialog", 0, 12));
- cancelButton.setText("Cancel");
- cancelButton.setText(L10N.getLocalString("dlg.cancel_btn", "Cancel"));
- cancelButton.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- cancelButtonActionPerformed(evt);
- }
- });
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 8;
- gridBagConstraints.gridwidth = 2;
- gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 0);
- getContentPane().add(cancelButton, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 7;
- gridBagConstraints.gridwidth = 2;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- getContentPane().add(jSeparator1, gridBagConstraints);
-
- stageLabel.setFont(new java.awt.Font("Dialog", 0, 12));
- stageLabel.setText("Stage:");
- stageLabel.setText(L10N.getLocalString("dlg.stage_lbl", "Stage:"));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 2;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
- gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
- getContentPane().add(stageLabel, gridBagConstraints);
-
- stageNameLabel.setFont(new java.awt.Font("Dialog", 0, 12));
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 2;
- gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
- getContentPane().add(stageNameLabel, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 6;
- gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
- gridBagConstraints.weighty = 0.5;
- getContentPane().add(topVerticalFiller, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 1;
- gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
- gridBagConstraints.weighty = 0.5;
- getContentPane().add(bottomVerticalFiller, gridBagConstraints);
-
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 3;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
- gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
- getContentPane().add(countValueLabel, gridBagConstraints);
-
- pack();
- }//GEN-END:initComponents
-
- private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
- int option = JOptionPane.showConfirmDialog(this, L10N.getLocalString("msg.cancelanalysis_txt", "Cancel analysis?"), L10N.getLocalString("msg.analyze_txt", "Analysis"),
- JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
-
- if (option == JOptionPane.YES_OPTION) {
- // All we need to do to cancel the analysis is to interrupt
- // the analysis thread.
- analysisThread.interrupt();
- }
- }//GEN-LAST:event_cancelButtonActionPerformed
-
- private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened
- // Here is where we actually kick off the analysis thread.
-
- // Lower the priority of the analysis thread to leave more
- // CPU for interactive tasks.
- analysisThread.setPriority(analysisPriority);
-
- analysisThread.start();
- }//GEN-LAST:event_formWindowOpened
-
- /**
- * Closes the dialog
- */
- private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
- setVisible(false);
- dispose();
- }//GEN-LAST:event_closeDialog
-
- // Variables declaration - do not modify//GEN-BEGIN:variables
- private javax.swing.JLabel bottomVerticalFiller;
- private javax.swing.JButton cancelButton;
- private javax.swing.JLabel countLabel;
- private javax.swing.JLabel countValueLabel;
- private javax.swing.JLabel findBugsLabel;
- private javax.swing.JSeparator jSeparator1;
- private javax.swing.JProgressBar progressBar;
- private javax.swing.JLabel progressLabel;
- private javax.swing.JLabel stageLabel;
- private javax.swing.JLabel stageNameLabel;
- private javax.swing.JLabel topVerticalFiller;
- // End of variables declaration//GEN-END:variables
-
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/SwingGUIBugReporter.java b/src/obsolete/edu/umd/cs/findbugs/gui/SwingGUIBugReporter.java
deleted file mode 100644
index 16c1b9e..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/gui/SwingGUIBugReporter.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * FindBugs - Find bugs in Java programs
- * Copyright (C) 2003-2005, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package edu.umd.cs.findbugs.gui;
-
-import edu.umd.cs.findbugs.SortedBugCollection;
-import edu.umd.cs.findbugs.TextUIBugReporter;
-import edu.umd.cs.findbugs.classfile.ClassDescriptor;
-import edu.umd.cs.findbugs.log.ConsoleLogger;
-
-/**
- * BugReporter used by AnalysisRun.
- */
-public class SwingGUIBugReporter extends TextUIBugReporter {
- private final AnalysisRun analysisRun;
- private SortedBugCollection bugCollection;
- private AnalysisErrorDialog errorDialog;
- private int errorCount;
-
- /**
- * Constructor.
- *
- * @param analysisRun
- */
- public SwingGUIBugReporter(AnalysisRun analysisRun) {
- this.analysisRun = analysisRun;
- this.bugCollection = new SortedBugCollection(getProjectStats());
- }
-
- public SortedBugCollection getBugCollection() {
- return bugCollection;
- }
-
- public boolean errorsOccurred() {
- return errorCount > 0;
- }
-
- public AnalysisErrorDialog getErrorDialog() {
- return errorDialog;
- }
-
- public void observeClass(ClassDescriptor classDescriptor) {
- }
-
- @Override
- public void reportMissingClass(ClassNotFoundException ex) {
- ++errorCount;
- super.reportMissingClass(ex);
- String message = getMissingClassName(ex);
- bugCollection.addMissingClass(message);
- }
-
- @Override
- public void logError(String message) {
- ++errorCount;
- analysisRun.getFrame().getLogger().logMessage(ConsoleLogger.WARNING, message);
- super.logError(message);
- bugCollection.addError(message);
- }
-
- public void finish() {
- }
-
- @Override
- public void doReportBug(edu.umd.cs.findbugs.BugInstance bugInstance) {
- checkBugInstance(bugInstance);
- if (bugCollection.add(bugInstance))
- notifyObservers(bugInstance);
- }
-
- private void createDialog() {
- if (errorDialog == null) {
- errorDialog = new AnalysisErrorDialog(analysisRun.getFrame(), true, this);
- }
- }
-
-
- @Override
- public void reportQueuedErrors() {
- createDialog();
- errorDialog.clear();
- super.reportQueuedErrors();
- errorDialog.finish();
- }
-
-
- @Override
- protected void emitLine(String line) {
- line = line.replaceAll("\t", " ");
- errorDialog.addLine(line);
- }
-}
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/bug-logo.png b/src/obsolete/edu/umd/cs/findbugs/gui/bug-logo.png
deleted file mode 100644
index e13fa30..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/bug-logo.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/bug.png b/src/obsolete/edu/umd/cs/findbugs/gui/bug.png
deleted file mode 100644
index 73d9eff..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/bug.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/bug2.png b/src/obsolete/edu/umd/cs/findbugs/gui/bug2.png
deleted file mode 100644
index 5922ddf..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/bug2.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/class.png b/src/obsolete/edu/umd/cs/findbugs/gui/class.png
deleted file mode 100644
index 16ebc88..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/class.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/down.png b/src/obsolete/edu/umd/cs/findbugs/gui/down.png
deleted file mode 100644
index 76ad059..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/down.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/field.png b/src/obsolete/edu/umd/cs/findbugs/gui/field.png
deleted file mode 100644
index a12c0c8..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/field.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/informal.png b/src/obsolete/edu/umd/cs/findbugs/gui/informal.png
deleted file mode 100644
index 26d274b..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/informal.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/logo_umd.png b/src/obsolete/edu/umd/cs/findbugs/gui/logo_umd.png
deleted file mode 100644
index 5f2e2d5..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/logo_umd.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/method.png b/src/obsolete/edu/umd/cs/findbugs/gui/method.png
deleted file mode 100644
index 968b65c..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/method.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/package.png b/src/obsolete/edu/umd/cs/findbugs/gui/package.png
deleted file mode 100644
index 82d35ce..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/package.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/sourcefile.png b/src/obsolete/edu/umd/cs/findbugs/gui/sourcefile.png
deleted file mode 100644
index d08ac30..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/sourcefile.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/gui/up.png b/src/obsolete/edu/umd/cs/findbugs/gui/up.png
deleted file mode 100644
index 1b45cde..0000000
Binary files a/src/obsolete/edu/umd/cs/findbugs/gui/up.png and /dev/null differ
diff --git a/src/obsolete/edu/umd/cs/findbugs/ml/ConvertToARFF.java b/src/obsolete/edu/umd/cs/findbugs/ml/ConvertToARFF.java
deleted file mode 100644
index 904bca1..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ml/ConvertToARFF.java
+++ /dev/null
@@ -1,936 +0,0 @@
-/*
- * Machine Learning support for FindBugs
- * Copyright (C) 2004,2005 University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ml;
-
-import java.io.BufferedOutputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.PrintStream;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.TreeSet;
-
-import org.dom4j.Document;
-import org.dom4j.Element;
-import org.dom4j.Node;
-import org.dom4j.io.SAXReader;
-
-import edu.umd.cs.findbugs.config.CommandLine;
-
-/**
- * Convert a BugCollection into ARFF format. See Witten and Frank,
- * <em>Data Mining</em>, ISBN 1-55860-552-5.
- *
- * @see edu.umd.cs.findbugs.BugCollection
- * @see edu.umd.cs.findbugs.BugInstance
- * @author David Hovemeyer
- */
-public class ConvertToARFF {
- // ------------------------------------------------------------
- // Helper classes
- // ------------------------------------------------------------
-
- private static class DataFile {
- private Document document;
-
- private String appName;
-
- public DataFile(Document document, String appName) {
- this.document = document;
- this.appName = appName;
- }
-
- public Document getDocument() {
- return document;
- }
-
- public String getAppName() {
- return appName;
- }
- }
-
- private static class MissingNodeException extends Exception {
- private static final long serialVersionUID = -5042140832791541208L;
-
- public MissingNodeException(String msg) {
- super(msg);
- }
- }
-
- public interface Attribute {
- public String getName();
-
- public void scan(Element element, String appName) throws MissingNodeException;
-
- public String getRange();
-
- public String getInstanceValue(Element element, String appName) throws MissingNodeException;
- }
-
- private abstract static class XPathAttribute implements Attribute {
- private String name;
-
- private String xpath;
-
- public XPathAttribute(String name, String xpath) {
- this.name = name;
- this.xpath = xpath;
- }
-
- public String getName() {
- return name;
- }
-
- public String getInstanceValue(Element element, String appName) throws MissingNodeException {
- Object value = element.selectObject(xpath);
- if (value == null)
- throw new MissingNodeException("Could not get value from element (path=" + xpath + ")");
- if (value instanceof List) {
- List<?> list = (List<?>) value;
- if (list.size() == 0)
- throw new MissingNodeException("Could not get value from element (path=" + xpath + ")");
- value = list.get(0);
- }
-
- if (value instanceof Node) {
- Node node = (Node) value;
- return node.getText();
- } else if (value instanceof String) {
- return (String) value;
- } else if (value instanceof Number) {
- String s = value.toString();
- if (s.endsWith(".0"))
- s = s.substring(0, s.length() - 2);
- return s;
- } else
- throw new IllegalStateException("Unexpected object returned from xpath query: " + value);
- }
- }
-
- public static class NominalAttribute extends XPathAttribute {
- private Set<String> possibleValueSet;
-
- public NominalAttribute(String name, String xpath) {
- super(name, xpath);
- this.possibleValueSet = new TreeSet<String>();
- }
-
- public void scan(Element element, String appName) {
- try {
- possibleValueSet.add(getInstanceValue(element, appName));
- } catch (MissingNodeException ignore) {
- // Ignore: we'll just use an n/a value for this instance
- }
- }
-
- public String getRange() {
- return collectionToRange(possibleValueSet);
- }
-
- @Override
- public String getInstanceValue(Element element, String appName) throws MissingNodeException {
- return "\"" + super.getInstanceValue(element, appName) + "\"";
- }
- }
-
- public static class BooleanAttribute extends XPathAttribute {
- public BooleanAttribute(String name, String xpath) {
- super(name, xpath);
- }
-
- public void scan(Element element, String appName) throws MissingNodeException {
- // Nothing to do.
- }
-
- public String getRange() {
- return "{true, false}";
- }
-
- @Override
- public String getInstanceValue(Element element, String appName) throws MissingNodeException {
- try {
- String value = super.getInstanceValue(element, appName);
- return "\"" + Boolean.valueOf(value).toString() + "\"";
- } catch (MissingNodeException e) {
- return "\"false\"";
- }
- }
- }
-
- private static final int UNCLASSIFIED = 0;
-
- private static final int BUG = 1;
-
- private static final int NOT_BUG = 2;
-
- private static final int HARMLESS = 4;
-
- private static final int HARMLESS_BUG = HARMLESS | BUG;
-
- public static abstract class AbstractClassificationAttribute implements Attribute {
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#getName()
- */
- public String getName() {
- return "classification";
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#scan(org.dom4j.Element
- * , java.lang.String)
- */
- public void scan(Element element, String appName) throws MissingNodeException {
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#getInstanceValue(org
- * .dom4j.Element, java.lang.String)
- */
- public String getInstanceValue(Element element, String appName) throws MissingNodeException {
- String annotationText = element.valueOf("./UserAnnotation[text()]");
- // System.out.println("annotationText=" + annotationText);
-
- int state = getBugClassification(annotationText);
- return bugToString(state);
- }
-
- protected abstract String bugToString(int bugType) throws MissingNodeException;
-
- }
-
- public static class ClassificationAttribute extends AbstractClassificationAttribute {
- public String getRange() {
- return "{bug,not_bug,harmless_bug}";
- }
-
- @Override
- protected String bugToString(int state) throws MissingNodeException {
- if (state == NOT_BUG)
- return "not_bug";
- else if (state == BUG)
- return "bug";
- else if (state == HARMLESS_BUG)
- return "harmless_bug";
- else
- throw new MissingNodeException("Unclassified warning");
-
- }
- }
-
- public static class BinaryClassificationAttribute extends AbstractClassificationAttribute {
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#getRange()
- */
- public String getRange() {
- return "{bug, not_bug}";
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ml.ConvertToARFF.AbstractClassificationAttribute
- * #bugToString(int)
- */
- @Override
- protected String bugToString(int state) throws MissingNodeException {
- if (state == BUG)
- return "bug";
- else if (state == NOT_BUG || state == HARMLESS_BUG)
- return "not_bug";
- else
- throw new MissingNodeException("unclassified warning");
- }
- }
-
- public static class NumericAttribute extends XPathAttribute {
- public NumericAttribute(String name, String xpath) {
- super(name, xpath);
- }
-
- public void scan(Element element, String appName) throws MissingNodeException {
- }
-
- public String getRange() {
- return "numeric";
- }
- }
-
- public static class PriorityAttribute implements Attribute {
- public String getName() {
- return "priority";
- }
-
- public void scan(Element element, String appName) throws MissingNodeException {
- }
-
- public String getRange() {
- return "{low,medium,high}";
- }
-
- public String getInstanceValue(Element element, String appName) throws MissingNodeException {
- org.dom4j.Attribute attribute = element.attribute("priority");
- if (attribute == null)
- throw new MissingNodeException("Missing priority attribute");
- String value = attribute.getValue();
- try {
- int prio = Integer.parseInt(value);
- switch (prio) {
- case 1:
- return "high";
- case 2:
- return "medium";
- case 3:
- return "low";
- default:
- return "?";
- }
- } catch (NumberFormatException e) {
- throw new MissingNodeException("Invalid priority value: " + value);
- }
- }
- }
-
- /**
- * An attribute that just gives each instance a unique id. The application
- * name is prepended, so each unique id really unique, even across
- * applications. Obviously, this attribute shouldn't be used as input to a
- * learning algorithm.
- *
- * <p>
- * Uses the Element's uid attribute if it has one.
- * </p>
- */
- public static class IdAttribute implements Attribute {
- private TreeSet<String> possibleValueSet = new TreeSet<String>();
-
- private boolean scanning = true;
-
- private int count = 0;
-
- public String getName() {
- return "id";
- }
-
- public void scan(Element element, String appName) throws MissingNodeException {
- possibleValueSet.add(instanceValue(element, appName));
- }
-
- public String getRange() {
- return collectionToRange(possibleValueSet);
- }
-
- public String getInstanceValue(Element element, String appName) throws MissingNodeException {
- if (scanning) {
- count = 0;
- scanning = false;
- }
- return instanceValue(element, appName);
- }
-
- private String instanceValue(Element element, String appName) {
- String nextId;
-
- org.dom4j.Attribute uidAttr = element.attribute("uid");
- if (uidAttr != null) {
- nextId = uidAttr.getValue();
- } else {
- nextId = String.valueOf(count++);
- }
-
- return "\"" + appName + "-" + nextId + "\"";
- }
- }
-
- public static class IdStringAttribute implements Attribute {
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#getName()
- */
- public String getName() {
- return "ids";
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#scan(org.dom4j.Element
- * , java.lang.String)
- */
- public void scan(Element element, String appName) throws MissingNodeException {
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#getRange()
- */
- public String getRange() {
- return "string";
- }
-
- int count = 0;
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#getInstanceValue(org
- * .dom4j.Element, java.lang.String)
- */
- public String getInstanceValue(Element element, String appName) throws MissingNodeException {
- String value;
- org.dom4j.Attribute uidAttr = element.attribute("uid");
- if (uidAttr == null) {
- value = String.valueOf(count++);
- } else {
- value = uidAttr.getStringValue();
- }
-
- return "\"" + appName + "-" + value + "\"";
- }
-
- }
-
- private static final String RANDOM_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
- public static class RandomIdAttribute implements Attribute {
-
- private Random rng = new Random();
-
- private IdentityHashMap<Element, String> idMap = new IdentityHashMap<Element, String>();
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#getName()
- */
- public String getName() {
- return "idr";
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#scan(org.dom4j.Element
- * , java.lang.String)
- */
- public void scan(Element element, String appName) throws MissingNodeException {
- idMap.put(element, generateId());
- }
-
- private String generateId() {
- StringBuilder buf = new StringBuilder();
-
- for (int i = 0; i < 20; ++i) {
- char c = RANDOM_CHARS.charAt(rng.nextInt(RANDOM_CHARS.length()));
- buf.append(c);
- }
-
- return buf.toString();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#getRange()
- */
- public String getRange() {
- TreeSet<String> range = new TreeSet<String>();
- range.addAll(idMap.values());
- if (range.size() != idMap.size())
- throw new IllegalStateException("id collision!");
- return collectionToRange(range);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * edu.umd.cs.findbugs.ml.ConvertToARFF.Attribute#getInstanceValue(org
- * .dom4j.Element, java.lang.String)
- */
- public String getInstanceValue(Element element, String appName) throws MissingNodeException {
- String id = idMap.get(element);
- if (id == null)
- throw new IllegalStateException("Element not scanned?");
- return "\"" + id + "\"";
- }
-
- }
-
- public static class AppNameAttribute implements Attribute {
- private Set<String> appNameSet = new TreeSet<String>();
-
- public String getName() {
- return "appname";
- }
-
- public void scan(Element element, String appName) throws MissingNodeException {
- appNameSet.add(appName);
- }
-
- public String getRange() {
- return collectionToRange(appNameSet);
- }
-
- public String getInstanceValue(Element element, String appName) throws MissingNodeException {
- return "\"" + appName + "\"";
- }
- }
-
- public static String collectionToRange(Collection<String> collection) {
- StringBuilder buf = new StringBuilder();
- buf.append("{");
- for (String aCollection : collection) {
- if (buf.length() > 1)
- buf.append(',');
- buf.append(aCollection);
- }
- buf.append("}");
-
- return buf.toString();
- }
-
- public interface AttributeCallback {
- public void apply(Attribute attribute) throws MissingNodeException, IOException;
- }
-
- // ------------------------------------------------------------
- // Constants
- // ------------------------------------------------------------
-
- private static final String DEFAULT_NODE_SELECTION_XPATH = "/BugCollection/BugInstance";
-
- // ------------------------------------------------------------
- // Fields
- // ------------------------------------------------------------
-
- private List<Attribute> attributeList;
-
- private String nodeSelectionXpath;
-
- private boolean dropUnclassifiedWarnings;
-
- private String appName;
-
- // ------------------------------------------------------------
- // Public methods
- // ------------------------------------------------------------
-
- public ConvertToARFF() {
- this.attributeList = new LinkedList<Attribute>();
- this.nodeSelectionXpath = DEFAULT_NODE_SELECTION_XPATH;
- this.dropUnclassifiedWarnings = false;
- }
-
- public void setAppName(String appName) {
- this.appName = appName;
- }
-
- /**
- * Set the xpath expression used to select BugInstance nodes.
- *
- * @param nodeSelectionXpath
- * the node selection xpath expression
- */
- public void setNodeSelectionXpath(String nodeSelectionXpath) {
- this.nodeSelectionXpath = nodeSelectionXpath;
- }
-
- public int getNumAttributes() {
- return attributeList.size();
- }
-
- public void dropUnclassifiedWarnings() {
- this.dropUnclassifiedWarnings = true;
- }
-
- public void addAttribute(Attribute attribute) {
- attributeList.add(attribute);
- }
-
- public void addNominalAttribute(String name, String xpath) {
- addAttribute(new NominalAttribute(name, xpath));
- }
-
- public void addBooleanAttribute(String name, String xpath) {
- addAttribute(new BooleanAttribute(name, xpath));
- }
-
- public void addClassificationAttribute() {
- addAttribute(new ClassificationAttribute());
- }
-
- public void addNumericAttribute(String name, String xpath) {
- addAttribute(new NumericAttribute(name, xpath));
- }
-
- public void addPriorityAttribute() {
- addAttribute(new PriorityAttribute());
- }
-
- public void addIdAttribute() {
- addAttribute(new IdAttribute());
- }
-
- public void addAppNameAttribute() {
- addAttribute(new AppNameAttribute());
- }
-
- /**
- * Convert a single Document to ARFF format.
- *
- * @param relationName
- * the relation name
- * @param document
- * the Document
- * @param appName
- * the application name
- * @param out
- * Writer to write the ARFF output to
- */
- public void convert(String relationName, Document document, String appName, final Writer out) throws IOException,
- MissingNodeException {
- scan(document, appName);
- generateHeader(relationName, out);
- generateInstances(document, appName, out);
- }
-
- /**
- * Scan a Document to find out the ranges of attributes. All Documents must
- * be scanned before generating the ARFF header and instances.
- *
- * @param document
- * the Document
- * @param appName
- * the application name
- */
- public void scan(Document document, final String appName) throws MissingNodeException, IOException {
- List<Element> bugInstanceList = getBugInstanceList(document);
-
- for (final Element element : bugInstanceList) {
- scanAttributeList(new AttributeCallback() {
- public void apply(Attribute attribute) throws MissingNodeException {
- attribute.scan(element, appName);
- }
- });
- }
- }
-
- /**
- * Generate ARFF header. Documents must have already been scanned.
- *
- * @param relationName
- * the relation name
- * @param out
- * Writer to write the ARFF output to
- */
- public void generateHeader(String relationName, final Writer out) throws MissingNodeException, IOException {
- out.write("@relation ");
- out.write(relationName);
- out.write("\n\n");
-
- scanAttributeList(new AttributeCallback() {
- public void apply(Attribute attribute) throws IOException {
- out.write("@attribute ");
- out.write(attribute.getName());
- out.write(" ");
- out.write(attribute.getRange());
- out.write("\n");
- }
- });
- out.write("\n");
-
- out.write("@data\n");
- }
-
- /**
- * Generate instances from given Document. Document should already have been
- * scanned, and the ARFF header generated.
- *
- * @param document
- * the Document
- * @param appName
- * the application name
- * @param out
- * Writer to write the ARFF output to
- */
- public void generateInstances(Document document, final String appName, final Writer out) throws MissingNodeException,
- IOException {
- List<Element> bugInstanceList = getBugInstanceList(document);
-
- for (final Element element : bugInstanceList) {
- scanAttributeList(new AttributeCallback() {
- boolean first = true;
-
- public void apply(Attribute attribute) throws IOException {
- if (!first)
- out.write(",");
- first = false;
- String value;
- try {
- value = attribute.getInstanceValue(element, appName);
- } catch (MissingNodeException e) {
- value = "?";
- }
- out.write(value);
- }
- });
- out.write("\n");
- }
- }
-
- /**
- * Apply a callback to all Attributes.
- *
- * @param callback
- * the callback
- */
- public void scanAttributeList(AttributeCallback callback) throws MissingNodeException, IOException {
- for (Attribute attribute : attributeList) {
- callback.apply(attribute);
- }
- }
-
- // ------------------------------------------------------------
- // Implementation
- // ------------------------------------------------------------
-
- private static int getBugClassification(String annotationText) {
- StringTokenizer tok = new StringTokenizer(annotationText, " \t\r\n\f.,:;-");
-
- int state = UNCLASSIFIED;
-
- while (tok.hasMoreTokens()) {
- String s = tok.nextToken();
- if (s.equals("BUG"))
- state |= BUG;
- else if (s.equals("NOT_BUG"))
- state |= NOT_BUG;
- else if (s.equals("HARMLESS"))
- state |= HARMLESS;
- }
-
- if ((state & NOT_BUG) != 0)
- return NOT_BUG;
- else if ((state & BUG) != 0)
- return ((state & HARMLESS) != 0) ? HARMLESS_BUG : BUG;
- else
- return UNCLASSIFIED;
- }
-
- @SuppressWarnings("unchecked")
- private List<Element> getBugInstanceList(Document document) {
- List<Element> bugInstanceList = document.selectNodes(nodeSelectionXpath);
- if (dropUnclassifiedWarnings) {
- for (Iterator<Element> i = bugInstanceList.iterator(); i.hasNext();) {
- Element element = i.next();
- String annotationText = element.valueOf("./UserAnnotation[text()]");
- int classification = getBugClassification(annotationText);
- if (classification == UNCLASSIFIED)
- i.remove();
- }
- }
- return bugInstanceList;
- }
-
- private static class C2ACommandLine extends CommandLine {
- private ConvertToARFF converter = new ConvertToARFF();
-
- public C2ACommandLine() {
- addOption("-select", "xpath expression", "select BugInstance elements");
- addSwitch("-train", "drop unclassified warnings");
- addSwitch("-id", "add unique id attribute (as nominal)");
- addSwitch("-ids", "add unique id attribute (as string)");
- addSwitch("-idr", "add random unique id attribtue (as nominal)");
- addSwitch("-app", "add application name attribute");
- addOption("-nominal", "attrName,xpath", "add a nominal attribute");
- addOption("-boolean", "attrName,xpath", "add a boolean attribute");
- addOption("-numeric", "attrName,xpath", "add a numeric attribute");
- addSwitch("-classification", "add bug classification attribute");
- addSwitch("-binclass", "add binary (bug/not_bug) classification attribute");
- addSwitch("-priority", "add priority attribute");
- addOption("-appname", "app name", "set application name of all tuples");
- }
-
- public ConvertToARFF getConverter() {
- return converter;
- }
-
- @Override
- protected void handleOption(String option, String optionExtraPart) throws IOException {
- if (option.equals("-train")) {
- converter.dropUnclassifiedWarnings();
- } else if (option.equals("-id")) {
- converter.addIdAttribute();
- } else if (option.equals("-ids")) {
- converter.addAttribute(new IdStringAttribute());
- } else if (option.equals("-idr")) {
- converter.addAttribute(new RandomIdAttribute());
- } else if (option.equals("-app")) {
- converter.addAppNameAttribute();
- } else if (option.equals("-classification")) {
- converter.addClassificationAttribute();
- } else if (option.equals("-binclass")) {
- converter.addAttribute(new BinaryClassificationAttribute());
- } else if (option.equals("-priority")) {
- converter.addPriorityAttribute();
- }
- }
-
- private interface XPathAttributeCreator {
- public Attribute create(String name, String xpath);
- }
-
- @Override
- protected void handleOptionWithArgument(String option, String argument) throws IOException {
-
- if (option.equals("-select")) {
- converter.setNodeSelectionXpath(argument);
- } else if (option.equals("-nominal")) {
- addXPathAttribute(option, argument, new XPathAttributeCreator() {
- public Attribute create(String name, String xpath) {
- return new NominalAttribute(name, xpath);
- }
- });
- } else if (option.equals("-boolean")) {
- addXPathAttribute(option, argument, new XPathAttributeCreator() {
- public Attribute create(String name, String xpath) {
- return new BooleanAttribute(name, xpath);
- }
- });
- } else if (option.equals("-numeric")) {
- addXPathAttribute(option, argument, new XPathAttributeCreator() {
- public Attribute create(String name, String xpath) {
- return new NumericAttribute(name, xpath);
- }
- });
- } else if (option.equals("-appname")) {
- converter.setAppName(argument);
- }
- }
-
- protected void addXPathAttribute(String option, String argument, XPathAttributeCreator creator) {
- int comma = argument.indexOf(',');
- if (comma < 0) {
- throw new IllegalArgumentException("Missing comma separating attribute name and xpath in " + option + " option: "
- + argument);
- }
- String attrName = argument.substring(0, comma);
- String xpath = argument.substring(comma + 1);
- converter.addAttribute(creator.create(attrName, xpath));
- }
-
- public void printUsage(PrintStream out) {
- out.println("Usage: " + ConvertToARFF.class.getName()
- + " [options] <relation name> <output file> <findbugs results> [<findbugs results>...]");
- super.printUsage(out);
- }
- }
-
- public String toAppName(String fileName) {
- if (appName != null)
- return appName;
-
- // Remove file extension, if any
- int lastDot = fileName.lastIndexOf('.');
- if (lastDot >= 0)
- fileName = fileName.substring(0, lastDot);
- return fileName;
- }
-
- public static void main(String[] argv) throws Exception {
- // Expand any option files
- C2ACommandLine commandLine = new C2ACommandLine();
- argv = commandLine.expandOptionFiles(argv, true, true);
-
- // Parse command line arguments
- int argCount = commandLine.parse(argv);
- if (argCount > argv.length - 3) {
- commandLine.printUsage(System.err);
- System.exit(1);
- }
- String relationName = argv[argCount++];
- String outputFileName = argv[argCount++];
-
- // Create the converter
- ConvertToARFF converter = commandLine.getConverter();
- if (converter.getNumAttributes() == 0) {
- throw new IllegalArgumentException("No attributes specified!");
- }
-
- // Open output file
- Writer out = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(outputFileName)));
-
- // Read documents,
- // scan documents to find ranges of attributes
- List<DataFile> dataFileList = new ArrayList<DataFile>();
- while (argCount < argv.length) {
- String fileName = argv[argCount++];
-
- // Read input file as dom4j tree
- SAXReader reader = new SAXReader();
- Document document = reader.read(fileName);
-
- DataFile dataFile = new DataFile(document, converter.toAppName(fileName));
- dataFileList.add(dataFile);
-
- converter.scan(dataFile.getDocument(), dataFile.getAppName());
- }
-
- // Generate ARFF header
- converter.generateHeader(relationName, out);
-
- // Generate instances from each document
- for (DataFile dataFile : dataFileList) {
- converter.generateInstances(dataFile.getDocument(), dataFile.getAppName(), out);
- }
-
- out.close();
- }
-
-}
-
-// vim:ts=4
diff --git a/src/obsolete/edu/umd/cs/findbugs/ml/GenerateUIDs.java b/src/obsolete/edu/umd/cs/findbugs/ml/GenerateUIDs.java
deleted file mode 100644
index dbd31b7..0000000
--- a/src/obsolete/edu/umd/cs/findbugs/ml/GenerateUIDs.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Machine Learning support for FindBugs
- * Copyright (C) 2005, University of Maryland
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package edu.umd.cs.findbugs.ml;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
-import java.util.zip.GZIPInputStream;
-
-import org.dom4j.Attribute;
-import org.dom4j.Document;
-import org.dom4j.DocumentException;
-import org.dom4j.DocumentFactory;
-import org.dom4j.Element;
-import org.dom4j.io.OutputFormat;
-import org.dom4j.io.XMLWriter;
-
-import edu.umd.cs.findbugs.BugCollection;
-import edu.umd.cs.findbugs.Project;
-import edu.umd.cs.findbugs.SortedBugCollection;
-import edu.umd.cs.findbugs.annotations.NonNull;
-import edu.umd.cs.findbugs.xml.Dom4JXMLOutput;
-
-/**
- * Add uid attributes to BugInstances in a BugCollection. A uid is an integer
- * that uniquely identifies a BugInstance in a BugCollection. Right now this is
- * only used in machine learning experiments.
- *
- * @author David Hovemeyer
- */
-public class GenerateUIDs {
- private BugCollection bugCollection;
-
- @NonNull
- private Project project;
-
- private String inputFilename;
-
- private String outputFilename;
-
- public GenerateUIDs(String inputFilename, String outputFilename) {
- this.bugCollection = new SortedBugCollection();
- this.inputFilename = inputFilename;
- this.outputFilename = outputFilename;
- }
-
- @SuppressWarnings("unchecked")
- public void execute() throws IOException, DocumentException {
- InputStream in = null;
- try {
- if (inputFilename.equals("-")) {
- in = System.in;
- } else {
- in = new BufferedInputStream(new FileInputStream(inputFilename));
- if (inputFilename.endsWith(".gz"))
- in = new GZIPInputStream(in);
- }
-
- bugCollection.readXML(in);
- in = null;
- } finally {
- if (in != null)
- in.close();
- }
- Document document = DocumentFactory.getInstance().createDocument();
- Dom4JXMLOutput xmlOutput = new Dom4JXMLOutput(document);
- bugCollection.writeXML(xmlOutput);
-
- int count = 0;
-
- List<Element> bugInstanceList = document.selectNodes("/BugCollection/BugInstance");
- for (Element element : bugInstanceList) {
- Attribute uidAttr = element.attribute("uid");
- if (uidAttr == null) {
- element.addAttribute("uid", Integer.toString(count++));
- }
- }
-
- OutputStream out;
- if (outputFilename.equals("-")) {
- out = System.out;
- } else {
- out = new BufferedOutputStream(new FileOutputStream(outputFilename));
- }
-
- XMLWriter xmlWriter = new XMLWriter(out, OutputFormat.createPrettyPrint());
- try {
- xmlWriter.write(document);
- } finally {
- xmlWriter.close();
- }
- }
-
- public static void main(String[] args) throws IOException, DocumentException {
- if (args.length != 2) {
- System.err.println("Usage: " + GenerateUIDs.class.getName() + " <input file> <output file>");
- System.exit(1);
- }
-
- String inputFilename = args[0];
- String outputFilename = args[1];
-
- GenerateUIDs generateUIDs = new GenerateUIDs(inputFilename, outputFilename);
- generateUIDs.execute();
- }
-}
diff --git a/src/scripts/deprecated/bugHistory b/src/scripts/deprecated/bugHistory
old mode 100644
new mode 100755
diff --git a/src/scripts/deprecated/updateBugs b/src/scripts/deprecated/updateBugs
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/convertXmlToText b/src/scripts/standard/convertXmlToText
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/defectDensity b/src/scripts/standard/defectDensity
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/fbwrap b/src/scripts/standard/fbwrap
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/filterBugs b/src/scripts/standard/filterBugs
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/findbugs b/src/scripts/standard/findbugs
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/findbugs-csr b/src/scripts/standard/findbugs-csr
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/findbugs-dbStats b/src/scripts/standard/findbugs-dbStats
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/findbugs-msv b/src/scripts/standard/findbugs-msv
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/mineBugHistory b/src/scripts/standard/mineBugHistory
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/printAppVersion b/src/scripts/standard/printAppVersion
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/unionBugs b/src/scripts/standard/unionBugs
old mode 100644
new mode 100755
diff --git a/src/scripts/standard/xpathFind b/src/scripts/standard/xpathFind
old mode 100644
new mode 100755
diff --git a/src/tools/edu/umd/cs/findbugs/tools/CheckClassfileVersion.java b/src/tools/edu/umd/cs/findbugs/tools/CheckClassfileVersion.java
index 1e52a6c..c86a6c7 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/CheckClassfileVersion.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/CheckClassfileVersion.java
@@ -29,7 +29,7 @@ import java.util.jar.JarFile;
/**
* Verify that a set of jar files are compiled for Java 5.0, the release
* standard for FindBugs
- *
+ *
*/
public class CheckClassfileVersion {
@@ -44,47 +44,54 @@ public class CheckClassfileVersion {
ArrayList<File> s = new ArrayList<File>(args.length);
for (String f : args) {
File file = new File(f);
- if (!file.canRead())
+ if (!file.canRead()) {
System.out.println("Can't read " + f);
+ }
if (file.isDirectory()) {
- for (File f2 : file.listFiles())
- if (isJarFile(f2))
+ for (File f2 : file.listFiles()) {
+ if (isJarFile(f2)) {
s.add(f2);
- } else if (isJarFile(file))
+ }
+ }
+ } else if (isJarFile(file)) {
s.add(file);
+ }
}
for (File jarFile : s) {
String jarFileName = jarFile.getName();
System.out.println("Checking " + jarFileName);
- JarFile z = new JarFile(jarFile);
- for (Enumeration<JarEntry> e = z.entries(); e.hasMoreElements();) {
- JarEntry ze = e.nextElement();
- if (ze.isDirectory())
- continue;
+ try(JarFile z = new JarFile(jarFile)){
+ for (Enumeration<JarEntry> e = z.entries(); e.hasMoreElements();) {
+ JarEntry ze = e.nextElement();
+ if (ze.isDirectory()) {
+ continue;
+ }
- String name = ze.getName();
- boolean isClassFile = name.endsWith(".class");
- if (!isClassFile)
- continue;
+ String name = ze.getName();
+ boolean isClassFile = name.endsWith(".class");
+ if (!isClassFile) {
+ continue;
+ }
- DataInputStream zipIn = new DataInputStream(z.getInputStream(ze));
- int magic = zipIn.readInt();
- int minorVersion = zipIn.readUnsignedShort();
- int majorVersion = zipIn.readUnsignedShort();
- if (magic != 0xCAFEBABE) {
- System.out.printf("bad magic %x: %s %s%n", magic, jarFileName, name);
- fail = true;
- } else if (minorVersion >= 60) {
- System.out.printf("bad version %d:%s %s%n", minorVersion, jarFileName, name);
- fail = true;
+ DataInputStream zipIn = new DataInputStream(z.getInputStream(ze));
+ int magic = zipIn.readInt();
+ int minorVersion = zipIn.readUnsignedShort();
+ // int majorVersion = zipIn.readUnsignedShort();
+ if (magic != 0xCAFEBABE) {
+ System.out.printf("bad magic %x: %s %s%n", magic, jarFileName, name);
+ fail = true;
+ } else if (minorVersion >= 60) {
+ System.out.printf("bad version %d:%s %s%n", minorVersion, jarFileName, name);
+ fail = true;
+ }
+ zipIn.close();
}
- zipIn.close();
}
- z.close();
}
- if (fail)
+ if (fail) {
System.exit(1);
+ }
}
}
diff --git a/src/tools/edu/umd/cs/findbugs/tools/ComparePerfomance.java b/src/tools/edu/umd/cs/findbugs/tools/ComparePerfomance.java
index efe6eeb..4f11004 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/ComparePerfomance.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/ComparePerfomance.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -39,51 +39,57 @@ import edu.umd.cs.findbugs.xml.XMLUtil;
* @author pugh
*/
public class ComparePerfomance {
-
+
final int num;
final Map<String, int[]> performance = new TreeMap<String, int[]>();
-
+
ComparePerfomance(String [] args) throws DocumentException, IOException {
num = args.length;
for(int i = 0; i < args.length; i++) {
foo(new File(args[i]), i);
}
-
+
}
-
-
+
+
public int[] getRecord(String className) {
int [] result = performance.get(className);
- if (result != null)
+ if (result != null) {
return result;
+ }
result = new int[num];
performance.put(className, result);
return result;
}
+
public void foo(File f, int i) throws DocumentException, IOException {
Document doc;
SAXReader reader = new SAXReader();
String fName = f.getName();
InputStream in = new FileInputStream(f);
- if (fName.endsWith(".gz"))
- in = new GZIPInputStream(in);
- doc = reader.read(in);
- Node summary = doc.selectSingleNode("/BugCollection/FindBugsSummary");
- double cpu_seconds = Double.parseDouble(summary.valueOf("@cpu_seconds"));
- putStats("cpu_seconds", i, (int) (cpu_seconds * 1000));
- double gc_seconds = Double.parseDouble(summary.valueOf("@gc_seconds"));
- putStats("gc_seconds", i, (int) (gc_seconds * 1000));
-
- List<Node> profileNodes = XMLUtil.selectNodes(doc, "/BugCollection/FindBugsSummary/FindBugsProfile/ClassProfile");
- for(Node n : profileNodes) {
- String name = n.valueOf("@name");
- int totalMilliseconds = Integer.parseInt(n.valueOf("@totalMilliseconds"));
- int invocations = Integer.parseInt(n.valueOf("@invocations"));
- putStats(name, i, totalMilliseconds);
-// System.out.printf("%6d %10d %s%n", invocations, totalMilliseconds, simpleName);
+ try {
+ if (fName.endsWith(".gz")) {
+ in = new GZIPInputStream(in);
+ }
+ doc = reader.read(in);
+ Node summary = doc.selectSingleNode("/BugCollection/FindBugsSummary");
+ double cpu_seconds = Double.parseDouble(summary.valueOf("@cpu_seconds"));
+ putStats("cpu_seconds", i, (int) (cpu_seconds * 1000));
+ double gc_seconds = Double.parseDouble(summary.valueOf("@gc_seconds"));
+ putStats("gc_seconds", i, (int) (gc_seconds * 1000));
+
+ List<Node> profileNodes = XMLUtil.selectNodes(doc, "/BugCollection/FindBugsSummary/FindBugsProfile/ClassProfile");
+ for(Node n : profileNodes) {
+ String name = n.valueOf("@name");
+ int totalMilliseconds = Integer.parseInt(n.valueOf("@totalMilliseconds"));
+ int invocations = Integer.parseInt(n.valueOf("@invocations"));
+ putStats(name, i, totalMilliseconds);
+ // System.out.printf("%6d %10d %s%n", invocations, totalMilliseconds, simpleName);
+ }
+ } finally {
+ in.close();
}
- in.close();
}
@@ -96,20 +102,21 @@ public class ComparePerfomance {
int [] stats = getRecord(name);
stats[i] = totalMilliseconds;
}
-
+
public void print() {
for(Map.Entry<String, int[]> e : performance.entrySet()) {
String name = e.getKey();
int lastDot = name.lastIndexOf('.');
String simpleName = name.substring(lastDot+1);
System.out.printf("%s,%s", name, simpleName);
- for(int x : e.getValue())
+ for(int x : e.getValue()) {
System.out.printf(",%d", x);
+ }
System.out.println();
}
}
-
-
+
+
public static void main(String args[]) throws Exception {
ComparePerfomance p = new ComparePerfomance(args);
p.print();
diff --git a/src/tools/edu/umd/cs/findbugs/tools/FilterAndCombineBitfieldPropertyDatabase.java b/src/tools/edu/umd/cs/findbugs/tools/FilterAndCombineBitfieldPropertyDatabase.java
index 99c29c8..b2334fd 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/FilterAndCombineBitfieldPropertyDatabase.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/FilterAndCombineBitfieldPropertyDatabase.java
@@ -54,11 +54,13 @@ public class FilterAndCombineBitfieldPropertyDatabase {
Map<String, Integer> properties = new TreeMap<String, Integer>();
Map<String, Integer> accessFlags = new TreeMap<String, Integer>();
- if (args.length == 0)
+ if (args.length == 0) {
process(System.in, properties, accessFlags);
- else
- for (String f : args)
+ } else {
+ for (String f : args) {
process(new FileInputStream(f), properties, accessFlags);
+ }
+ }
for (Entry<String, Integer> e : properties.entrySet()) {
String key = e.getKey();
@@ -74,18 +76,20 @@ public class FilterAndCombineBitfieldPropertyDatabase {
static Status getStatus(@DottedClassName String name) {
if (name.startsWith("com.sun") || name.startsWith("com.oracle")
- || name.startsWith("sun") || name.startsWith("netscape"))
+ || name.startsWith("sun") || name.startsWith("netscape")) {
return Status.UNEXPOSED;
+ }
Status result = classStatus.get(name);
- if (result != null)
+ if (result != null) {
return result;
+ }
try {
Class<?> c = Class.forName(name, false, ClassLoader.getSystemClassLoader());
int accessFlags = c.getModifiers();
- if ((accessFlags & FLAGS) != 0)
+ if ((accessFlags & FLAGS) != 0) {
result = Status.EXPOSED;
- else {
+ } else {
result = Status.UNEXPOSED;
}
} catch (Exception e) {
@@ -108,22 +112,25 @@ public class FilterAndCombineBitfieldPropertyDatabase {
try {
while (true) {
String s = in.readLine();
- if (s == null)
+ if (s == null) {
break;
+ }
Matcher m = p.matcher(s);
if (m.find()) {
String key = m.group(1);
String className = m.group(2);
- if (getStatus(className) == Status.UNEXPOSED)
+ if (getStatus(className) == Status.UNEXPOSED) {
continue;
+ }
int accFlags = Integer.parseInt(m.group(3));
int bits = Integer.parseInt(m.group(4));
if ((accFlags & FLAGS) != 0) {
accessFlags.put(key, accFlags);
- if (properties.containsKey(key))
+ if (properties.containsKey(key)) {
properties.put(key, bits | properties.get(key));
- else
+ } else {
properties.put(key, bits);
+ }
}
}
diff --git a/src/tools/edu/umd/cs/findbugs/tools/FilterPropertyDatabase.java b/src/tools/edu/umd/cs/findbugs/tools/FilterPropertyDatabase.java
index 8fcc97f..ec13f44 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/FilterPropertyDatabase.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/FilterPropertyDatabase.java
@@ -48,8 +48,9 @@ public class FilterPropertyDatabase {
*/
public static void main(String[] args) throws IOException {
InputStream inSource = System.in;
- if (args.length > 0)
+ if (args.length > 0) {
inSource = new FileInputStream(args[0]);
+ }
process(inSource);
}
@@ -65,20 +66,23 @@ public class FilterPropertyDatabase {
in = new BufferedReader(Util.getReader(inSource));
Pattern p = Pattern.compile("^(([^,]+),.+),([0-9]+)\\|(.+)$");
-
+
while (true) {
String s = in.readLine();
- if (s == null)
+ if (s == null) {
break;
+ }
Matcher m = p.matcher(s);
if (m.find()) {
String className = m.group(2);
- if (FilterAndCombineBitfieldPropertyDatabase.getStatus(className) == Status.UNEXPOSED)
+ if (FilterAndCombineBitfieldPropertyDatabase.getStatus(className) == Status.UNEXPOSED) {
continue;
+ }
int accFlags = Integer.parseInt(m.group(3));
-
- if ((accFlags & FLAGS) != 0)
+
+ if ((accFlags & FLAGS) != 0) {
System.out.println(s);
+ }
}
}
diff --git a/src/tools/edu/umd/cs/findbugs/tools/FixIndentation.java b/src/tools/edu/umd/cs/findbugs/tools/FixIndentation.java
index 0f1c996..a519fe5 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/FixIndentation.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/FixIndentation.java
@@ -42,16 +42,18 @@ public class FixIndentation {
static final String SPACES = " ";
static final boolean performUpdate = SystemProperties.getBoolean("fix.identation");
-
+
public static void main(String args[]) throws Exception {
File root = new File(args[0]);
- if (!root.exists() || !root.canRead())
+ if (!root.exists() || !root.canRead()) {
throw new IllegalArgumentException("Unable to read " +root);
+ }
recursiveFix(root, true);
System.out.printf("Updated %d/%d files%n", updated, examined);
System.out.printf("%d nonblank lines%n", lines);
- if (!performUpdate)
+ if (!performUpdate) {
System.out.println("No update actually performed");
+ }
}
static void recursiveFix(File root, boolean partial) throws IOException {
@@ -63,26 +65,33 @@ public class FixIndentation {
while (!todo.isEmpty()) {
File next = todo.remove().getAbsoluteFile();
String nextPath = next.getAbsolutePath();
- if (!nextPath.startsWith(rootPath))
+ if (!nextPath.startsWith(rootPath)) {
continue;
+ }
if (next.isDirectory()) {
File[] contents = next.listFiles();
- if (contents != null)
- for (File c : contents)
- if (seen.add(c))
+ if (contents != null) {
+ for (File c : contents) {
+ if (seen.add(c)) {
todo.add(c);
- } else if (nextPath.endsWith(".java") || nextPath.endsWith(".xml"))
+ }
+ }
+ }
+ } else if (nextPath.endsWith(".java") || nextPath.endsWith(".xml")) {
fix(next, partial);
+ }
}
}
static boolean TRIM_TRAILING_WS = false;
static String fix(String s) {
- if (s.length() == 0)
+ if (s.length() == 0) {
return s;
- if (TRIM_TRAILING_WS && s.trim().length() == 0)
+ }
+ if (TRIM_TRAILING_WS && s.trim().length() == 0) {
return "";
+ }
int pos = 0;
int indentation = 0;
int tabs = 0;
@@ -93,21 +102,24 @@ public class FixIndentation {
} else if (c == '\t') {
indentation += 4;
tabs++;
- } else
+ } else {
break;
+ }
}
if (TRIM_TRAILING_WS || tabs > 0) {
- if (pos >= s.length())
+ if (pos >= s.length()) {
return "";
+ }
return SPACES.substring(0, indentation) + s.substring(pos).trim();
} else {
- if (pos >= s.length())
+ if (pos >= s.length()) {
return s;
+ }
return SPACES.substring(0, indentation) + s.substring(pos);
}
-
+
}
@@ -124,27 +136,32 @@ public class FixIndentation {
try {
while (true) {
String s = in.readLine();
- if (s == null)
+ if (s == null) {
break;
- if (s.trim().length() > 0)
+ }
+ if (s.trim().length() > 0) {
lines++;
+ }
String s2 = fix(s);
if (!s2.equals(s)) {
consecutiveFixes++;
if (consecutiveFixes > 3 && partial) {
s2 = s;
consecutiveFixes = 0;
- } else
+ } else {
anyChanges = true;
- } else
+ }
+ } else {
consecutiveFixes = 0;
+ }
out.println(s2);
}
} finally {
in.close();
}
- if (!anyChanges)
+ if (!anyChanges) {
return;
+ }
updated++;
if (!performUpdate) {
System.out.println("Would update " + fileToUpdate);
@@ -157,14 +174,15 @@ public class FixIndentation {
try {
while (true) {
int sz = stringReader.read(buffer);
- if (sz < 0)
+ if (sz < 0) {
break;
+ }
outFile.write(buffer, 0, sz);
}
} finally {
outFile.close();
}
-
+
}
}
diff --git a/src/tools/edu/umd/cs/findbugs/tools/GenerateUpdateXml.java b/src/tools/edu/umd/cs/findbugs/tools/GenerateUpdateXml.java
index fe668ec..a9d3dea 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/GenerateUpdateXml.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/GenerateUpdateXml.java
@@ -1,17 +1,17 @@
/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2008 University of Maryland
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -27,7 +27,7 @@ import edu.umd.cs.findbugs.Plugin;
* @author pugh
*/
public class GenerateUpdateXml {
-
+
public static void main(String args[]) {
FindBugs.setNoAnalysis();
DetectorFactoryCollection dfc = DetectorFactoryCollection.instance();
@@ -36,9 +36,9 @@ public class GenerateUpdateXml {
System.out.println(p.getReleaseDate());
System.out.println(p.getVersion());
System.out.println();
-
+
}
-
+
}
}
diff --git a/src/tools/edu/umd/cs/findbugs/tools/html/ColorAlternator.java b/src/tools/edu/umd/cs/findbugs/tools/html/ColorAlternator.java
index a24ed99..c6e41cc 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/html/ColorAlternator.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/html/ColorAlternator.java
@@ -20,7 +20,7 @@
package edu.umd.cs.findbugs.tools.html;
public class ColorAlternator {
- private String[] colorList;
+ private final String[] colorList;
int index;
@@ -33,4 +33,3 @@ public class ColorAlternator {
}
}
-// vim:ts=3
diff --git a/src/tools/edu/umd/cs/findbugs/tools/html/PlainPrintBugDescriptions.java b/src/tools/edu/umd/cs/findbugs/tools/html/PlainPrintBugDescriptions.java
index 286bac6..68b7452 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/html/PlainPrintBugDescriptions.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/html/PlainPrintBugDescriptions.java
@@ -47,7 +47,8 @@ public class PlainPrintBugDescriptions extends PrintBugDescriptions {
@Override
protected void prologue() throws IOException {
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">" +
- "\n<html><head><title>" + docTitle + "</title>");
+ "\n<html><head><META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">" +
+ "\n<title>" + docTitle + "</title>");
header();
out.println("</head><body>");
beginBody();
@@ -80,10 +81,10 @@ public class PlainPrintBugDescriptions extends PrintBugDescriptions {
public static void main(String[] args) throws Exception {
String docTitle = "FindBugs Bug Descriptions";
- if (args.length > 0)
+ if (args.length > 0) {
docTitle = args[0];
+ }
new PlainPrintBugDescriptions(docTitle, System.out).print();
}
}
-// vim:ts=3
diff --git a/src/tools/edu/umd/cs/findbugs/tools/html/PrettyPrintBugDescriptions.java b/src/tools/edu/umd/cs/findbugs/tools/html/PrettyPrintBugDescriptions.java
index 29e9b2c..a2de1fb 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/html/PrettyPrintBugDescriptions.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/html/PrettyPrintBugDescriptions.java
@@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.DetectorFactory;
import edu.umd.cs.findbugs.I18N;
public class PrettyPrintBugDescriptions extends PlainPrintBugDescriptions {
- private Set<BugPattern> bugPatternSet;
+ private final Set<BugPattern> bugPatternSet;
private String headerText;
@@ -47,13 +47,16 @@ public class PrettyPrintBugDescriptions extends PlainPrintBugDescriptions {
private static final String[] TABLE_COLORS = new String[] { "#eeeeee", "#ffffff" };
private static class BugPatternComparator implements Comparator<BugPattern>, Serializable {
+ @Override
public int compare(BugPattern a, BugPattern b) {
int cmp = a.getCategory().compareTo(b.getCategory());
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
cmp = a.getAbbrev().compareTo(b.getAbbrev());
- if (cmp != 0)
+ if (cmp != 0) {
return cmp;
+ }
return a.getType().compareTo(b.getType());
}
}
@@ -161,7 +164,7 @@ public class PrettyPrintBugDescriptions extends PlainPrintBugDescriptions {
int argCount = 0;
boolean unabridged = false;
- if (argCount < args.length && args[argCount].equals("-unabridged")) {
+ if (argCount < args.length && "-unabridged".equals(args[argCount])) {
++argCount;
// Unabridged mode: emit all warnings reported by at least one
// detector, even for disabled detectors.
@@ -191,11 +194,11 @@ public class PrettyPrintBugDescriptions extends PlainPrintBugDescriptions {
pp.setEndBodyText(args[argCount++]);
}
- if (unabridged)
+ if (unabridged) {
pp.unabridged = true;
+ }
pp.print();
}
}
-// vim:ts=3
diff --git a/src/tools/edu/umd/cs/findbugs/tools/html/PrintBugDescriptions.java b/src/tools/edu/umd/cs/findbugs/tools/html/PrintBugDescriptions.java
index e1f19d6..a149bbe 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/html/PrintBugDescriptions.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/html/PrintBugDescriptions.java
@@ -37,8 +37,9 @@ public abstract class PrintBugDescriptions {
Collection<BugPattern> enabledPatternSet = new HashSet<BugPattern>();
for (Iterator<DetectorFactory> i = factories.factoryIterator(); i.hasNext();) {
DetectorFactory factory = i.next();
- if (isEnabled(factory))
+ if (isEnabled(factory)) {
enabledPatternSet.addAll(factory.getReportedBugPatterns());
+ }
}
prologue();
@@ -46,8 +47,9 @@ public abstract class PrintBugDescriptions {
Iterator<BugPattern> i = DetectorFactoryCollection.instance().bugPatternIterator();
while (i.hasNext()) {
BugPattern bugPattern = i.next();
- if (!enabledPatternSet.contains(bugPattern))
+ if (!enabledPatternSet.contains(bugPattern)) {
continue;
+ }
emit(bugPattern);
}
@@ -65,4 +67,3 @@ public abstract class PrintBugDescriptions {
protected abstract void epilogue() throws IOException;
}
-// vim:ts=3
diff --git a/src/tools/edu/umd/cs/findbugs/tools/junit/JUnitJarRunner.java b/src/tools/edu/umd/cs/findbugs/tools/junit/JUnitJarRunner.java
index a78d6c9..c789f37 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/junit/JUnitJarRunner.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/junit/JUnitJarRunner.java
@@ -37,17 +37,17 @@ import junit.framework.TestSuite;
* Run all of the JUnit tests in a jar file using the JUnit textui. There might
* be a simple way of doing this directly with JUnit. However, I'm lazy and
* impatient, and writing some code to do this was very simple.
- *
+ *
* @author David Hovemeyer
*/
public class JUnitJarRunner {
- private String jarFileName;
+ private final String jarFileName;
private String classpath;
/**
* Constructor.
- *
+ *
* @param jarFileName
* name of jar file to load tests from
*/
@@ -58,7 +58,7 @@ public class JUnitJarRunner {
/**
* Set the classpath containing the code to be tested (if it is not already
* on the system classpath).
- *
+ *
* @param classpath
* the classpath
*/
@@ -68,7 +68,7 @@ public class JUnitJarRunner {
/**
* Build a TestSuite of all the tests contained in the jar file.
- *
+ *
* @return TestSuite for running all of the tests in the jar file
*/
public TestSuite buildTestSuite() throws Exception {
@@ -85,6 +85,7 @@ public class JUnitJarRunner {
ClassLoader cl = AccessController.doPrivileged(new PrivilegedExceptionAction<URLClassLoader>() {
+ @Override
public URLClassLoader run() throws Exception {
return new URLClassLoader(urlList.toArray(new URL[urlList.size()]));
@@ -93,23 +94,25 @@ public class JUnitJarRunner {
Class<junit.framework.TestCase> testCaseClass = getTestCase(cl);
- JarFile jarFile = new JarFile(jarFileName);
- Enumeration<JarEntry> e = jarFile.entries();
- while (e.hasMoreElements()) {
- JarEntry entry = e.nextElement();
- String entryName = entry.getName();
- if (entryName.endsWith(".class")) {
- String className = entryName.substring(0, entryName.length() - ".class".length()).replace('/', '.');
- if (!className.endsWith("Test"))
- continue;
- System.out.println("Loading test class: " + className);
- System.out.flush();
- Class<?> jarClass = cl.loadClass(className);
- if (testCaseClass.isAssignableFrom(jarClass))
- suite.addTestSuite(testCaseClass.asSubclass(testCaseClass));
+ try(JarFile jarFile = new JarFile(jarFileName)){
+ Enumeration<JarEntry> e = jarFile.entries();
+ while (e.hasMoreElements()) {
+ JarEntry entry = e.nextElement();
+ String entryName = entry.getName();
+ if (entryName.endsWith(".class")) {
+ String className = entryName.substring(0, entryName.length() - ".class".length()).replace('/', '.');
+ if (!className.endsWith("Test")) {
+ continue;
+ }
+ System.out.println("Loading test class: " + className);
+ System.out.flush();
+ Class<?> jarClass = cl.loadClass(className);
+ if (testCaseClass.isAssignableFrom(jarClass)) {
+ suite.addTestSuite(testCaseClass.asSubclass(testCaseClass));
+ }
+ }
}
}
- jarFile.close();
return suite;
}
@@ -122,13 +125,14 @@ public class JUnitJarRunner {
}
public void run(TestSuite suite, String how) {
- if (how.equals("-textui")) {
+ if ("-textui".equals(how)) {
junit.textui.TestRunner.run(suite);
- } else if (how.equals("-swingui")) {
+ } else if ("-swingui".equals(how)) {
// junit.swingui.TestRunner.run(suite);
throw new UnsupportedOperationException("I don't know how to run the Swing UI on a test suite yet");
- } else
+ } else {
throw new IllegalArgumentException("Unknown option: " + how);
+ }
}
public static void main(String[] argv) throws Exception {
@@ -144,11 +148,10 @@ public class JUnitJarRunner {
}
String jarFileName = argv[arg++];
JUnitJarRunner runner = new JUnitJarRunner(jarFileName);
- if (arg < argv.length)
+ if (arg < argv.length) {
runner.setClassPath(argv[arg++]);
+ }
TestSuite suite = runner.buildTestSuite();
runner.run(suite, how);
}
}
-
-// vim:ts=4
diff --git a/src/tools/edu/umd/cs/findbugs/tools/xml/CheckMessages.java b/src/tools/edu/umd/cs/findbugs/tools/xml/CheckMessages.java
index 0f0e4b1..215ad95 100644
--- a/src/tools/edu/umd/cs/findbugs/tools/xml/CheckMessages.java
+++ b/src/tools/edu/umd/cs/findbugs/tools/xml/CheckMessages.java
@@ -56,9 +56,9 @@ public class CheckMessages {
}
private static class XMLFile {
- private String filename;
+ private final String filename;
- private Document document;
+ private final Document document;
public XMLFile(String filename) throws DocumentException {
this.filename = filename;
@@ -102,39 +102,45 @@ public class CheckMessages {
}
public Attribute checkAttribute(Node node, String attrName) throws DocumentException {
- if (!(node instanceof Element))
+ if (!(node instanceof Element)) {
throw new CheckMessagesException("Node is not an element", this, node);
+ }
Element element = (Element) node;
Attribute attr = element.attribute(attrName);
- if (attr == null)
+ if (attr == null) {
throw new CheckMessagesException("Missing " + attrName + " attribute", this, node);
+ }
return attr;
}
public Element checkElement(Node node, String elementName) throws DocumentException {
- if (!(node instanceof Element))
+ if (!(node instanceof Element)) {
throw new CheckMessagesException("Node is not an element", this, node);
+ }
Element element = (Element) node;
Element child = element.element(elementName);
- if (child == null)
+ if (child == null) {
throw new CheckMessagesException("Missing " + elementName + " element", this, node);
+ }
return child;
}
public String checkNonEmptyText(Node node) throws DocumentException {
- if (!(node instanceof Element))
+ if (!(node instanceof Element)) {
throw new CheckMessagesException("Node is not an element", this, node);
+ }
Element element = (Element) node;
String text = element.getText();
- if (text.equals(""))
+ if ("".equals(text)) {
throw new CheckMessagesException("Empty text in element", this, node);
+ }
return text;
}
}
- private Set<String> declaredDetectorsSet;
+ private final Set<String> declaredDetectorsSet;
- private Set<String> declaredAbbrevsSet;
+ private final Set<String> declaredAbbrevsSet;
public CheckMessages(String pluginDescriptorFilename) throws DocumentException {
@@ -147,7 +153,7 @@ public class CheckMessages {
/**
* Check given messages file for validity.
- *
+ *
* @throws DocumentException
* if the messages file is invalid
*/
@@ -196,8 +202,9 @@ public class CheckMessages {
notDescribed.addAll(declared);
notDescribed.removeAll(described);
- if (!notDescribed.isEmpty())
+ if (!notDescribed.isEmpty()) {
throw new CheckMessagesException(description + ": " + notDescribed.toString(), xmlFile);
+ }
}
public static void main(String[] argv) throws Exception {
@@ -225,4 +232,3 @@ public class CheckMessages {
}
}
-// vim:ts=3
diff --git a/src/xsl/color.xsl b/src/xsl/color.xsl
new file mode 100644
index 0000000..f4304ba
--- /dev/null
+++ b/src/xsl/color.xsl
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ FindBugs - Find bugs in Java programs
+ Copyright (C) 2004,2005 University of Maryland
+ Copyright (C) 2005, Chris Nappin
+ Copyright (C) 2015, Brahim Djoudi (modifications)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+-->
+<xsl:stylesheet version="1.0"
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:output
+ method="xml"
+ omit-xml-declaration="yes"
+ doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+ doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
+ indent="yes"
+ encoding="UTF-8"/>
+
+<xsl:variable name="bugTableHeader">
+ <tr class="tableheader">
+ <th align="left">Warning</th>
+ <th align="center">Priority</th>
+ <th align="left">Details</th>
+ </tr>
+</xsl:variable>
+
+<xsl:template match="/">
+ <html>
+ <head>
+ <title>FindBugs Report</title>
+ <style type="text/css">
+ .tablerow0 {
+ background: #EEEEEE;
+ }
+
+ .tablerow1 {
+ background: white;
+ }
+
+ .detailrow0 {
+ background: #EEEEEE;
+ }
+
+ .detailrow1 {
+ background: white;
+ }
+ .long_message {
+ color:#220001;
+ background: -moz-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.96) 24%, rgba(255,255,255,1) 25%, rgba(255,255,255,0) 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,0)), color-stop(24%,rgba(255,255,255,0.96)), color-stop(25%,rgba(255,255,255,1)), color-stop(100%,rgba(255,255,255,0))); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(left, rgba(255,255,255,0) 0%,rgba(255,255,255,0.96) 24%,rgba(255,255,255,1) 25%,rgba(255,255,255,0) 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(left, rgba(255,255,255,0) 0%,rgba(255,255,255,0.96) 24%,rgba(255,255,255,1) 25%,rgba(255,255,255,0) 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(left, rgba(255,255,255,0) 0%,rgba(255,255,255,0.96) 24%,rgba(255,255,255,1) 25%,rgba(255,255,255,0) 100%); /* IE10+ */
+ background: linear-gradient(to right, rgba(255,255,255,0) 0%,rgba(255,255,255,0.96) 24%,rgba(255,255,255,1) 25%,rgba(255,255,255,0) 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#00ffffff',GradientType=1 ); /* IE6-9 */
+ }
+
+ .tableheader {
+ font-size: larger;
+ background: -moz-linear-gradient(left, rgba(135,224,253,1) 0%, rgba(83,203,241,0.9) 40%, rgba(59,4,153,0.75) 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(135,224,253,1)), color-stop(40%,rgba(83,203,241,0.9)), color-stop(100%,rgba(59,4,153,0.75))); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(left, rgba(135,224,253,1) 0%,rgba(83,203,241,0.9) 40%,rgba(59,4,153,0.75) 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(left, rgba(135,224,253,1) 0%,rgba(83,203,241,0.9) 40%,rgba(59,4,153,0.75) 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(left, rgba(135,224,253,1) 0%,rgba(83,203,241,0.9) 40%,rgba(59,4,153,0.75) 100%); /* IE10+ */
+ background: linear-gradient(to right, rgba(135,224,253,1) 0%,rgba(83,203,241,0.9) 40%,rgba(59,4,153,0.75) 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#87e0fd', endColorstr='#bf3b0499',GradientType=1 ); /* IE6-9 */
+
+ }
+ .high {
+ background: -moz-linear-gradient(top, rgba(239,187,110,0.93) 0%, rgba(255,26,0,0.97) 52%, rgba(239,187,110,1) 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(239,187,110,0.93)), color-stop(52%,rgba(255,26,0,0.97)), color-stop(100%,rgba(239,187,110,1))); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, rgba(239,187,110,0.93) 0%,rgba(255,26,0,0.97) 52%,rgba(239,187,110,1) 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, rgba(239,187,110,0.93) 0%,rgba(255,26,0,0.97) 52%,rgba(239,187,110,1) 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, rgba(239,187,110,0.93) 0%,rgba(255,26,0,0.97) 52%,rgba(239,187,110,1) 100%); /* IE10+ */
+ background: linear-gradient(to bottom, rgba(239,187,110,0.93) 0%,rgba(255,26,0,0.97) 52%,rgba(239,187,110,1) 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#edefbb6e', endColorstr='#efbb6e',GradientType=0 ); /* IE6-9 */
+ }
+ .medium {
+ background: -moz-linear-gradient(top, rgba(244,232,117,1) 0%, rgba(239,187,110,0.96) 52%, rgba(244,232,117,0.93) 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(244,232,117,1)), color-stop(52%,rgba(239,187,110,0.96)), color-stop(100%,rgba(244,232,117,0.93))); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, rgba(244,232,117,1) 0%,rgba(239,187,110,0.96) 52%,rgba(244,232,117,0.93) 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, rgba(244,232,117,1) 0%,rgba(239,187,110,0.96) 52%,rgba(244,232,117,0.93) 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, rgba(244,232,117,1) 0%,rgba(239,187,110,0.96) 52%,rgba(244,232,117,0.93) 100%); /* IE10+ */
+ background: linear-gradient(to bottom, rgba(244,232,117,1) 0%,rgba(239,187,110,0.96) 52%,rgba(244,232,117,0.93) 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4e875', endColorstr='#edf4e875',GradientType=0 ); /* IE6-9 */
+ }
+ .low {
+ background: -moz-linear-gradient(top, rgba(244,232,117,0.93) 0%, rgba(140,186,124,0.97) 53%, rgba(244,232,117,1) 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(244,232,117,0.93)), color-stop(53%,rgba(140,186,124,0.97)), color-stop(100%,rgba(244,232,117,1))); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, rgba(244,232,117,0.93) 0%,rgba(140,186,124,0.97) 53%,rgba(244,232,117,1) 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, rgba(244,232,117,0.93) 0%,rgba(140,186,124,0.97) 53%,rgba(244,232,117,1) 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, rgba(244,232,117,0.93) 0%,rgba(140,186,124,0.97) 53%,rgba(244,232,117,1) 100%); /* IE10+ */
+ background: linear-gradient(to bottom, rgba(244,232,117,0.93) 0%,rgba(140,186,124,0.97) 53%,rgba(244,232,117,1) 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#edf4e875', endColorstr='#f4e875',GradientType=0 ); /* IE6-9 */
+ }
+ pre {
+ font-family: "Bitstream Vera Sans Mono", Consolas, Inconsolata, "Lucida Console", "Courier New", Monospace !important;
+ box-shadow: 0 0;
+ color: black;
+ border-width: 1px 1px 1px 6px;
+ border-style: solid;
+ padding: 2ex;
+ margin: 2ex 2ex 2ex 2ex;
+ overflow: auto;
+ -moz-border-radius: 0px;
+ -webkit-border-radius: 0px;
+ -khtml-border-radius: 0px;
+ border-radius: 0px;
+ border-color: #996666;
+
+ background: rgb(232,239,244); /* Old browsers */
+ background: -moz-linear-gradient(left, rgba(232,239,244,1) 1%, rgba(244,249,249,1) 23%, rgba(249,250,246,1) 87%, rgba(241,242,236,1) 98%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, right top, color-stop(1%,rgba(232,239,244,1)), color-stop(23%,rgba(244,249,249,1)), color-stop(87%,rgba(249,250,246,1)), color-stop(98%,rgba(241,242,236,1))); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(left, rgba(232,239,244,1) 1%,rgba(244,249,249,1) 23%,rgba(249,250,246,1) 87%,rgba(241,242,236,1) 98%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(left, rgba(232,239,244,1) 1%,rgba(244,249,249,1) 23%,rgba(249,250,246,1) 87%,rgba(241,242,236,1) 98%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(left, rgba(232,239,244,1) 1%,rgba(244,249,249,1) 23%,rgba(249,250,246,1) 87%,rgba(241,242,236,1) 98%); /* IE10+ */
+ background: linear-gradient(to right, rgba(232,239,244,1) 1%,rgba(244,249,249,1) 23%,rgba(249,250,246,1) 87%,rgba(241,242,236,1) 98%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e8eff4', endColorstr='#f1f2ec',GradientType=1 ); /* IE6-9 */
+ }
+ </style>
+ </head>
+
+ <xsl:variable name="unique-catkey" select="/BugCollection/BugCategory/@category"/>
+ <!--xsl:variable name="unique-catkey" select="/BugCollection/BugInstance[generate-id() = generate-id(key('bug-category-key', at category))]/@category"/-->
+
+ <body>
+
+ <h1>FindBugs Report</h1>
+ <p>Produced using <a href="http://findbugs.sourceforge.net">FindBugs </a> <xsl:value-of select="/BugCollection/@version"/>.</p>
+ <p>Project:
+ <xsl:choose>
+ <xsl:when test='string-length(/BugCollection/Project/@projectName)>0'><xsl:value-of select="/BugCollection/Project/@projectName" /></xsl:when>
+ <xsl:otherwise><xsl:value-of select="/BugCollection/Project/@filename" /></xsl:otherwise>
+ </xsl:choose>
+ </p>
+
+ <table style="width:90%;">
+ <tr>
+ <td>
+ <h2>Metrics</h2>
+ <xsl:apply-templates select="/BugCollection/FindBugsSummary"/>
+ </td>
+ <td>
+ <h2>Summary</h2>
+ <table cellpadding="5" cellspacing="2" style="width:90%;border-collapse: collapse;border-style:solid;border-width:thin;">
+ <tr class="tableheader">
+ <th align="left">Warning Type</th>
+ <th align="right">Number</th>
+ </tr>
+
+ <xsl:for-each select="$unique-catkey">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="catkey" select="."/>
+ <xsl:variable name="catdesc" select="/BugCollection/BugCategory[@category=$catkey]/Description"/>
+ <xsl:variable name="styleclass">
+ <xsl:choose><xsl:when test="position() mod 2 = 1">tablerow0</xsl:when>
+ <xsl:otherwise>tablerow1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <tr class="{$styleclass}">
+ <td><a href="#Warnings_{$catkey}"><xsl:value-of select="$catdesc"/> Warnings</a></td>
+ <td align="right"><xsl:value-of select="count(/BugCollection/BugInstance[@category=$catkey])"/></td>
+ </tr>
+ </xsl:for-each>
+
+ <xsl:variable name="styleclass">
+ <xsl:choose><xsl:when test="count($unique-catkey) mod 2 = 0">tablerow0</xsl:when>
+ <xsl:otherwise>tablerow1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$styleclass}">
+ <td><b>Total</b></td>
+ <td align="right"><b><xsl:value-of select="count(/BugCollection/BugInstance)"/></b></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+
+ <p><br/><br/></p>
+
+ <h1>Warnings</h1>
+
+ <p>Click on each warning link to see a full description of the issue, and
+ details of how to resolve it.</p>
+
+ <xsl:for-each select="$unique-catkey">
+ <xsl:sort select="." order="ascending"/>
+ <xsl:variable name="catkey" select="."/>
+ <xsl:variable name="catdesc" select="/BugCollection/BugCategory[@category=$catkey]/Description"/>
+
+ <xsl:call-template name="generateWarningTable">
+ <xsl:with-param name="warningSet" select="/BugCollection/BugInstance[@category=$catkey]"/>
+ <xsl:with-param name="sectionTitle"><xsl:value-of select="$catdesc"/> Warnings</xsl:with-param>
+ <xsl:with-param name="sectionId">Warnings_<xsl:value-of select="$catkey"/></xsl:with-param>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <p><br/><br/></p>
+ <h1><a name="Details">Warning Types</a></h1>
+
+ <xsl:apply-templates select="/BugCollection/BugPattern">
+ <xsl:sort select="@abbrev"/>
+ <xsl:sort select="ShortDescription"/>
+ </xsl:apply-templates>
+
+ </body>
+ </html>
+</xsl:template>
+
+<xsl:template match="BugInstance">
+ <xsl:variable name="warningId"><xsl:value-of select="generate-id()"/></xsl:variable>
+
+ <tr>
+ <!-- class="tablerow{position() mod 2}" -->
+ <xsl:choose>
+ <xsl:when test="@priority = 1"><xsl:attribute name="class">high</xsl:attribute></xsl:when>
+ <xsl:when test="@priority = 2"><xsl:attribute name="class">medium</xsl:attribute></xsl:when>
+ <xsl:when test="@priority = 3"><xsl:attribute name="class">low</xsl:attribute></xsl:when>
+ <xsl:otherwise><xsl:attribute name="bgcolor">#fdfdfd</xsl:attribute></xsl:otherwise>
+ </xsl:choose>
+ <td width="20%" valign="top">
+ <a href="#{@type}"><xsl:value-of select="ShortMessage"/></a>
+ </td>
+ <td width="10%" valign="top" align="center">
+ <xsl:choose>
+ <xsl:when test="@priority = 1"><strong>High</strong></xsl:when>
+ <xsl:when test="@priority = 2">Medium</xsl:when>
+ <xsl:when test="@priority = 3">Low</xsl:when>
+ <xsl:otherwise>Unknown</xsl:otherwise>
+ </xsl:choose>
+ </td>
+ <td width="70%">
+ <dl>
+ <dt class='long_message'><xsl:value-of select="LongMessage"/></dt>
+ <dd>
+ <!-- add source filename and line number(s), if any -->
+ <xsl:if test="SourceLine">
+ In file <tt><strong><xsl:value-of select="SourceLine/@sourcefile"/></strong></tt>,
+ <xsl:choose>
+ <xsl:when test="SourceLine/@start = SourceLine/@end">
+ line <xsl:value-of select="SourceLine/@start"/>
+ </xsl:when>
+ <xsl:otherwise>
+ lines <xsl:value-of select="SourceLine/@start"/>
+ to <xsl:value-of select="SourceLine/@end"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+
+ <xsl:for-each select="./*/Message">
+ <br/><xsl:value-of select="text()"/>
+ </xsl:for-each>
+ </dd>
+ </dl>
+ </td>
+ </tr>
+</xsl:template>
+
+<xsl:template match="BugPattern">
+ <h2><a name="{@type}"><xsl:value-of select="ShortDescription"/></a></h2>
+ <xsl:value-of select="Details" disable-output-escaping="yes"/>
+ <p><br/><br/></p>
+</xsl:template>
+
+<xsl:template name="generateWarningTable">
+ <xsl:param name="warningSet"/>
+ <xsl:param name="sectionTitle"/>
+ <xsl:param name="sectionId"/>
+
+ <h2><a name="{$sectionId}"><xsl:value-of select="$sectionTitle"/></a></h2>
+ <table class="warningtable" cellspacing="2" cellpadding="5" style="width:100%;border-collapse: collapse;border-style:solid;border-width:thin;">
+ <xsl:copy-of select="$bugTableHeader"/>
+ <xsl:choose>
+ <xsl:when test="count($warningSet) > 0">
+ <xsl:apply-templates select="$warningSet">
+ <xsl:sort select="@priority"/>
+ <xsl:sort select="@abbrev"/>
+ <xsl:sort select="Class/@classname"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <tr><td colspan="2"><p><i>None</i></p></td></tr>
+ </xsl:otherwise>
+ </xsl:choose>
+ </table>
+ <p><br/><br/></p>
+</xsl:template>
+
+<xsl:template match="FindBugsSummary">
+ <xsl:variable name="kloc" select="@total_size div 1000.0"/>
+ <xsl:variable name="format" select="'#######0.00'"/>
+
+ <p><xsl:value-of select="@total_size"/> lines of code analysed,
+ in <xsl:value-of select="@total_classes"/> classes,
+ in <xsl:value-of select="@num_packages"/> packages.</p>
+ <table cellpadding="5" cellspacing="2" style="width:90%;border-collapse: collapse;border-style:solid;border-width:thin;">
+ <tr class="tableheader">
+ <th align="left">Metric</th>
+ <th align="right">Total</th>
+ <th align="right">Density*</th>
+ </tr>
+ <tr class="high" >
+ <td>High Priority Warnings</td>
+ <td align="right"><xsl:value-of select="@priority_1"/></td>
+ <td align="right"><xsl:value-of select="format-number(@priority_1 div $kloc, $format)"/></td>
+ </tr>
+ <tr class="medium">
+ <td>Medium Priority Warnings</td>
+ <td align="right"><xsl:value-of select="@priority_2"/></td>
+ <td align="right"><xsl:value-of select="format-number(@priority_2 div $kloc, $format)"/></td>
+ </tr>
+
+ <xsl:choose>
+ <xsl:when test="@priority_3">
+ <tr class="low">
+ <td>Low Priority Warnings</td>
+ <td align="right"><xsl:value-of select="@priority_3"/></td>
+ <td align="right"><xsl:value-of select="format-number(@priority_3 div $kloc, $format)"/></td>
+ </tr>
+ </xsl:when>
+ </xsl:choose>
+
+ <tr bgcolor="#f0f0f0">
+ <td><b>Total Warnings</b></td>
+ <td align="right"><b><xsl:value-of select="@total_bugs"/></b></td>
+ <td align="right"><b><xsl:value-of select="format-number(@total_bugs div $kloc, $format)"/></b></td>
+ </tr>
+ </table>
+ <p><i>(* Defects per thousand lines of non-commenting source statements)</i></p>
+ <p><br/><br/></p>
+
+</xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/findbugs.git
More information about the pkg-java-commits
mailing list