Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

merged tag v0.1.0 back into master

  • Loading branch information...
commit 19d93fabad490b5c5aef5215b89b126c42cc87f9 2 parents d59b9d3 + 39e3473
Mirco authored
Showing with 4,083 additions and 109 deletions.
  1. +8 −0 .gitignore
  2. +81 −3 README.md
  3. +13 −0 build.sbt
  4. +9 −0 core/.classpath
  5. +18 −0 core/.project
  6. +3 −0  core/build.sbt
  7. BIN  core/src/main/resources/images/add.png
  8. BIN  core/src/main/resources/images/alert.png
  9. BIN  core/src/main/resources/images/broken.png
  10. BIN  core/src/main/resources/images/check.jpg
  11. BIN  core/src/main/resources/images/close.gif
  12. BIN  core/src/main/resources/images/down.png
  13. BIN  core/src/main/resources/images/exit.png
  14. BIN  core/src/main/resources/images/migration.jpg
  15. BIN  core/src/main/resources/images/remove.png
  16. BIN  core/src/main/resources/images/scala_logo.png
  17. BIN  core/src/main/resources/images/scala_logo2.png
  18. BIN  core/src/main/resources/images/typesafe.png
  19. BIN  core/src/main/resources/images/up.png
  20. +27 −0 core/src/main/resources/license/LICENSE
  21. +39 −0 core/src/main/scala/images/Icons.scala
  22. +8 −0 core/src/main/scala/license/License.scala
  23. +1 −1  {src/main/scala/ssol/tools/mima → core/src/main/scala/ssol/tools/mima/core}/BufferReader.scala
  24. +283 −0 core/src/main/scala/ssol/tools/mima/core/ClassInfo.scala
  25. +44 −8 {src/main/scala/ssol/tools/mima → core/src/main/scala/ssol/tools/mima/core}/ClassfileParser.scala
  26. +67 −0 core/src/main/scala/ssol/tools/mima/core/Config.scala
  27. +105 −0 core/src/main/scala/ssol/tools/mima/core/Definitions.scala
  28. +5 −0 core/src/main/scala/ssol/tools/mima/core/HasAccessFlags.scala
  29. +19 −9 {src/main/scala/ssol/tools/mima → core/src/main/scala/ssol/tools/mima/core}/MemberInfo.scala
  30. +3 −1 {src/main/scala/ssol/tools/mima → core/src/main/scala/ssol/tools/mima/core}/Members.scala
  31. +40 −24 {src/main/scala/ssol/tools/mima → core/src/main/scala/ssol/tools/mima/core}/PackageInfo.scala
  32. +1 −4 {src/main/scala/ssol/tools/mima → core/src/main/scala/ssol/tools/mima/core}/PathResolver.scala
  33. +132 −0 core/src/main/scala/ssol/tools/mima/core/Problems.scala
  34. +1 −1  {src/main/scala/ssol/tools/mima → core/src/main/scala/ssol/tools/mima/core}/Reference.scala
  35. +1 −1  {src/main/scala/ssol/tools/mima → core/src/main/scala/ssol/tools/mima/core}/Settings.scala
  36. +12 −37 {src/main/scala/ssol/tools/mima → core/src/main/scala/ssol/tools/mima/core}/Type.scala
  37. +1 −1  {src/main/scala/ssol/tools/mima → core/src/main/scala/ssol/tools/mima/core}/UTF8Codec.scala
  38. +4 −0 core/src/main/scala/ssol/tools/mima/core/WithAccessFlags.scala
  39. +31 −0 core/src/main/scala/ssol/tools/mima/core/WithAccessModifier.scala
  40. +11 −0 core/src/main/scala/ssol/tools/mima/core/WithLocalModifier.scala
  41. +18 −0 core/src/main/scala/ssol/tools/mima/core/ui/Centered.scala
  42. +69 −0 core/src/main/scala/ssol/tools/mima/core/ui/MimaFrame.scala
  43. +51 −0 core/src/main/scala/ssol/tools/mima/core/ui/MimaMenuBar.scala
  44. +24 −0 core/src/main/scala/ssol/tools/mima/core/ui/MimaSwingApp.scala
  45. +33 −0 core/src/main/scala/ssol/tools/mima/core/ui/WithConstraints.scala
  46. +5 −0 core/src/main/scala/ssol/tools/mima/core/ui/event/Exit.scala
  47. +46 −0 core/src/main/scala/ssol/tools/mima/core/ui/model/ReportTableModel.scala
  48. +63 −0 core/src/main/scala/ssol/tools/mima/core/ui/page/ConfigurationPanel.scala
  49. +22 −0 core/src/main/scala/ssol/tools/mima/core/ui/page/JavaEnvironmentPage.scala
  50. +54 −0 core/src/main/scala/ssol/tools/mima/core/ui/page/ProjectConfigurationPage.scala
  51. +281 −0 core/src/main/scala/ssol/tools/mima/core/ui/page/ReportPage.scala
  52. +94 −0 core/src/main/scala/ssol/tools/mima/core/ui/page/SaveMigrationPage.scala
  53. +18 −0 core/src/main/scala/ssol/tools/mima/core/ui/page/ThanksPage.scala
  54. +125 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/ClassPathEditor.scala
  55. +23 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/ClassPathFileChooser.scala
  56. +13 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/CloseButton.scala
  57. +58 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/FilePicker.scala
  58. +32 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/HtmlEditorPane.scala
  59. +35 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/ImagePanel.scala
  60. +80 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/ListItemsPanel.scala
  61. +239 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/LoadingPanel.scala
  62. +16 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/NavigationPanel.scala
  63. +133 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/ProblemInfoView.scala
  64. +80 −0 core/src/main/scala/ssol/tools/mima/core/ui/widget/ReportTable.scala
  65. +210 −0 core/src/main/scala/ssol/tools/mima/core/ui/wizard/Wizard.scala
  66. +48 −0 core/src/main/scala/ssol/tools/mima/core/ui/wizard/WizardPage.scala
  67. +56 −0 core/src/main/scala/ssol/tools/mima/core/util/Browse.scala
  68. +23 −0 core/src/main/scala/ssol/tools/mima/core/util/EventQueueProxy.scala
  69. +3 −1 {src/main/scala/ssol/tools → core/src/main/scala/ssol/tools/mima/core}/util/IndentedOutput.scala
  70. +14 −0 core/src/main/scala/ssol/tools/mima/core/util/Prefs.scala
  71. +65 −0 core/src/main/scala/ssol/tools/mima/core/util/UnexpectedErrorDialog.scala
  72. +12 −0 core/src/main/scala/ssol/tools/mima/core/util/Urls.scala
  73. +6 −0 core/src/main/scala/ssol/tools/mima/core/util/Version.scala
  74. +8 −0 core/src/main/scala/ssol/tools/mima/core/util/log/ConsoleLogging.scala
  75. +6 −0 core/src/main/scala/ssol/tools/mima/core/util/log/Logging.scala
  76. +16 −0 core/src/main/scala/ssol/tools/mima/core/util/log/UiLogger.scala
  77. +109 −0 project/Build.scala
  78. +0 −8 project/build.properties
  79. +0 −10 project/build/MimaProject.scala
  80. +9 −0 reporter/.classpath
  81. +18 −0 reporter/.project
  82. +12 −0 reporter/MiMaReporter.launch
  83. +7 −0 reporter/build.sbt
  84. +50 −0 reporter/functional-tests/src/main/scala/ssol/tools/mima/lib/CollectProblemsTest.scala
  85. 0  reporter/functional-tests/src/test/case-class-abstract-becomes-concrete-ok/problems.txt
  86. +1 −0  reporter/functional-tests/src/test/case-class-abstract-becomes-concrete-ok/v1/A.scala
  87. +1 −0  reporter/functional-tests/src/test/case-class-abstract-becomes-concrete-ok/v2/A.scala
  88. +1 −0  reporter/functional-tests/src/test/case-class-becomes-final-nok/problems.txt
  89. +1 −0  reporter/functional-tests/src/test/case-class-becomes-final-nok/v1/A.scala
  90. +1 −0  reporter/functional-tests/src/test/case-class-becomes-final-nok/v2/A.scala
  91. +4 −0 reporter/functional-tests/src/test/case-class-concrete-becomes-abstract-nok/problems.txt
  92. +1 −0  reporter/functional-tests/src/test/case-class-concrete-becomes-abstract-nok/v1/A.scala
  93. +1 −0  reporter/functional-tests/src/test/case-class-concrete-becomes-abstract-nok/v2/A.scala
  94. 0  reporter/functional-tests/src/test/case-class-was-final-becomes-open-ok/problems.txt
  95. +1 −0  reporter/functional-tests/src/test/case-class-was-final-becomes-open-ok/v1/A.scala
  96. +1 −0  reporter/functional-tests/src/test/case-class-was-final-becomes-open-ok/v2/A.scala
  97. 0  reporter/functional-tests/src/test/class-abstract-becomes-concrete-ok/problems.txt
  98. +1 −0  reporter/functional-tests/src/test/class-abstract-becomes-concrete-ok/v1/A.scala
  99. +1 −0  reporter/functional-tests/src/test/class-abstract-becomes-concrete-ok/v2/A.scala
  100. 0  reporter/functional-tests/src/test/class-added-class-in-new-version-ok/problems.txt
  101. +1 −0  reporter/functional-tests/src/test/class-added-class-in-new-version-ok/v1/A.scala
  102. +2 −0  reporter/functional-tests/src/test/class-added-class-in-new-version-ok/v2/A.scala
  103. 0  reporter/functional-tests/src/test/class-added-method-in-new-version-ok/problems.txt
  104. +3 −0  reporter/functional-tests/src/test/class-added-method-in-new-version-ok/v1/A.scala
  105. +4 −0 reporter/functional-tests/src/test/class-added-method-in-new-version-ok/v2/A.scala
  106. 0  reporter/functional-tests/src/test/class-added-same-class-in-different-package-is-ok/problems.txt
  107. +3 −0  reporter/functional-tests/src/test/class-added-same-class-in-different-package-is-ok/v1/A.scala
  108. +7 −0 reporter/functional-tests/src/test/class-added-same-class-in-different-package-is-ok/v2/A.scala
  109. 0  reporter/functional-tests/src/test/class-added-val-in-new-version-ok/problems.txt
  110. +1 −0  reporter/functional-tests/src/test/class-added-val-in-new-version-ok/v1/A.scala
  111. +3 −0  reporter/functional-tests/src/test/class-added-val-in-new-version-ok/v2/A.scala
  112. 0  reporter/functional-tests/src/test/class-added-var-in-new-version-ok/problems.txt
  113. +1 −0  reporter/functional-tests/src/test/class-added-var-in-new-version-ok/v1/A.scala
  114. +3 −0  reporter/functional-tests/src/test/class-added-var-in-new-version-ok/v2/A.scala
  115. +1 −0  reporter/functional-tests/src/test/class-becomes-final-nok/problems.txt
  116. +1 −0  reporter/functional-tests/src/test/class-becomes-final-nok/v1/A.scala
  117. +1 −0  reporter/functional-tests/src/test/class-becomes-final-nok/v2/A.scala
  118. +1 −0  reporter/functional-tests/src/test/class-becomes-object-nok/problems.txt
  119. +1 −0  reporter/functional-tests/src/test/class-becomes-object-nok/v1/A.scala
  120. +1 −0  reporter/functional-tests/src/test/class-becomes-object-nok/v2/A.scala
  121. +1 −0  reporter/functional-tests/src/test/class-becomes-trait-nok/problems.txt
  122. +3 −0  reporter/functional-tests/src/test/class-becomes-trait-nok/v1/A.scala
  123. +3 −0  reporter/functional-tests/src/test/class-becomes-trait-nok/v2/A.scala
  124. 0  reporter/functional-tests/src/test/class-bridge-method-ok/problems.txt
  125. +5 −0 reporter/functional-tests/src/test/class-bridge-method-ok/v1/A.scala
  126. +8 −0 reporter/functional-tests/src/test/class-bridge-method-ok/v2/A.scala
  127. 0  reporter/functional-tests/src/test/class-changed-method-with-val-in-new-version-ok/problems.txt
  128. +3 −0  reporter/functional-tests/src/test/class-changed-method-with-val-in-new-version-ok/v1/A.scala
  129. +3 −0  reporter/functional-tests/src/test/class-changed-method-with-val-in-new-version-ok/v2/A.scala
  130. 0  reporter/functional-tests/src/test/class-changed-method-with-var-in-new-version-ok/problems.txt
  131. +3 −0  reporter/functional-tests/src/test/class-changed-method-with-var-in-new-version-ok/v1/A.scala
  132. +3 −0  reporter/functional-tests/src/test/class-changed-method-with-var-in-new-version-ok/v2/A.scala
  133. +1 −0  reporter/functional-tests/src/test/class-changed-val-type-in-new-version-nok/problems.txt
  134. +3 −0  reporter/functional-tests/src/test/class-changed-val-type-in-new-version-nok/v1/A.scala
  135. +3 −0  reporter/functional-tests/src/test/class-changed-val-type-in-new-version-nok/v2/A.scala
  136. 0  reporter/functional-tests/src/test/class-changed-val-with-method-in-new-version-ok/problems.txt
  137. +3 −0  reporter/functional-tests/src/test/class-changed-val-with-method-in-new-version-ok/v1/A.scala
  138. +3 −0  reporter/functional-tests/src/test/class-changed-val-with-method-in-new-version-ok/v2/A.scala
  139. +2 −0  reporter/functional-tests/src/test/class-changed-var-type-in-new-version-nok/problems.txt
  140. +3 −0  reporter/functional-tests/src/test/class-changed-var-type-in-new-version-nok/v1/A.scala
  141. +3 −0  reporter/functional-tests/src/test/class-changed-var-type-in-new-version-nok/v2/A.scala
  142. +1 −0  reporter/functional-tests/src/test/class-changed-var-with-method-in-new-version-nok/problems.txt
  143. +3 −0  reporter/functional-tests/src/test/class-changed-var-with-method-in-new-version-nok/v1/A.scala
  144. +3 −0  reporter/functional-tests/src/test/class-changed-var-with-method-in-new-version-nok/v2/A.scala
  145. +1 −0  reporter/functional-tests/src/test/class-concrete-becomes-abstract-nok/problems.txt
  146. +1 −0  reporter/functional-tests/src/test/class-concrete-becomes-abstract-nok/v1/A.scala
  147. +1 −0  reporter/functional-tests/src/test/class-concrete-becomes-abstract-nok/v2/A.scala
  148. +1 −0  reporter/functional-tests/src/test/class-deleted-deprecated-method-nok/problems.txt
  149. +5 −0 reporter/functional-tests/src/test/class-deleted-deprecated-method-nok/v1/A.scala
  150. +3 −0  reporter/functional-tests/src/test/class-deleted-deprecated-method-nok/v2/A.scala
  151. 0  reporter/functional-tests/src/test/class-extending-new-trait-with-no-concrete-method-ok/problems.txt
  152. +1 −0  reporter/functional-tests/src/test/class-extending-new-trait-with-no-concrete-method-ok/v1/A.scala
  153. +5 −0 reporter/functional-tests/src/test/class-extending-new-trait-with-no-concrete-method-ok/v2/A.scala
  154. +1 −0  ...ter/functional-tests/src/test/class-method-abstract-override-of-concrete-superclass-method-nok/problems.txt
  155. +5 −0 reporter/functional-tests/src/test/class-method-abstract-override-of-concrete-superclass-method-nok/v1/A.scala
  156. +7 −0 reporter/functional-tests/src/test/class-method-abstract-override-of-concrete-superclass-method-nok/v2/A.scala
  157. +2 −0  ...ter/functional-tests/src/test/class-method-abstract-override-of-concrete-supertrait-method-nok/problems.txt
  158. +5 −0 reporter/functional-tests/src/test/class-method-abstract-override-of-concrete-supertrait-method-nok/v1/A.scala
  159. +7 −0 reporter/functional-tests/src/test/class-method-abstract-override-of-concrete-supertrait-method-nok/v2/A.scala
  160. +1 −0  reporter/functional-tests/src/test/class-method-became-final-nok/problems.txt
  161. +3 −0  reporter/functional-tests/src/test/class-method-became-final-nok/v1/A.scala
  162. +3 −0  reporter/functional-tests/src/test/class-method-became-final-nok/v2/A.scala
  163. +1 −0  reporter/functional-tests/src/test/class-method-changed-parameter-type-nok/problems.txt
  164. +3 −0  reporter/functional-tests/src/test/class-method-changed-parameter-type-nok/v1/A.scala
  165. +3 −0  reporter/functional-tests/src/test/class-method-changed-parameter-type-nok/v2/A.scala
  166. +1 −0  reporter/functional-tests/src/test/class-method-changed-parameters-nok/problems.txt
  167. +3 −0  reporter/functional-tests/src/test/class-method-changed-parameters-nok/v1/A.scala
  168. +3 −0  reporter/functional-tests/src/test/class-method-changed-parameters-nok/v2/A.scala
  169. +1 −0  reporter/functional-tests/src/test/class-method-changed-parameters2-nok/problems.txt
  170. +3 −0  reporter/functional-tests/src/test/class-method-changed-parameters2-nok/v1/A.scala
  171. +3 −0  reporter/functional-tests/src/test/class-method-changed-parameters2-nok/v2/A.scala
  172. 0  reporter/functional-tests/src/test/class-method-pushed-up-ok/problems.txt
  173. +7 −0 reporter/functional-tests/src/test/class-method-pushed-up-ok/v1/A.scala
  174. +5 −0 reporter/functional-tests/src/test/class-method-pushed-up-ok/v2/A.scala
  175. +1 −0  reporter/functional-tests/src/test/class-missing-method-in-new-version-nok/problems.txt
  176. +5 −0 reporter/functional-tests/src/test/class-missing-method-in-new-version-nok/v1/A.scala
  177. +5 −0 reporter/functional-tests/src/test/class-missing-method-in-new-version-nok/v2/A.scala
  178. +1 −0  reporter/functional-tests/src/test/class-missing-method-in-root-package-nok/problems.txt
  179. +3 −0  reporter/functional-tests/src/test/class-missing-method-in-root-package-nok/v1/A.scala
  180. +3 −0  reporter/functional-tests/src/test/class-missing-method-in-root-package-nok/v2/A.scala
  181. +1 −0  reporter/functional-tests/src/test/class-missing-nok/problems.txt
  182. +2 −0  reporter/functional-tests/src/test/class-missing-nok/v1/A.scala
  183. +1 −0  reporter/functional-tests/src/test/class-missing-nok/v2/A.scala
  184. +1 −0  reporter/functional-tests/src/test/class-narrowing-method-type-in-new-version-ok/problems.txt
  185. +6 −0 reporter/functional-tests/src/test/class-narrowing-method-type-in-new-version-ok/v1/A.scala
  186. +6 −0 reporter/functional-tests/src/test/class-narrowing-method-type-in-new-version-ok/v2/A.scala
  187. +1 −0  reporter/functional-tests/src/test/class-public-method-becomes-private-nok/problems.txt
  188. +3 −0  reporter/functional-tests/src/test/class-public-method-becomes-private-nok/v1/A.scala
  189. +3 −0  reporter/functional-tests/src/test/class-public-method-becomes-private-nok/v2/A.scala
  190. 0  reporter/functional-tests/src/test/class-push-up-method-maintaining-explicit-bridge-ok/problems.txt
  191. +4 −0 reporter/functional-tests/src/test/class-push-up-method-maintaining-explicit-bridge-ok/v1/A.scala
  192. +7 −0 reporter/functional-tests/src/test/class-push-up-method-maintaining-explicit-bridge-ok/v2/A.scala
  193. +1 −0  reporter/functional-tests/src/test/class-removed-constructor-in-new-version-nok/problems.txt
  194. +1 −0  reporter/functional-tests/src/test/class-removed-constructor-in-new-version-nok/v1/A.scala
  195. +3 −0  reporter/functional-tests/src/test/class-removed-constructor-in-new-version-nok/v2/A.scala
  196. 0  reporter/functional-tests/src/test/class-removed-superclass-nok/problems.txt
  197. +2 −0  reporter/functional-tests/src/test/class-removed-superclass-nok/v1/A.scala
  198. +2 −0  reporter/functional-tests/src/test/class-removed-superclass-nok/v2/A.scala
  199. 0  reporter/functional-tests/src/test/class-type-became-final-ok/problems.txt
  200. +3 −0  reporter/functional-tests/src/test/class-type-became-final-ok/v1/A.scala
  201. +3 −0  reporter/functional-tests/src/test/class-type-became-final-ok/v2/A.scala
  202. +1 −0  reporter/functional-tests/src/test/class-val-became-final-nok/problems.txt
  203. +3 −0  reporter/functional-tests/src/test/class-val-became-final-nok/v1/A.scala
  204. +3 −0  reporter/functional-tests/src/test/class-val-became-final-nok/v2/A.scala
  205. +2 −0  reporter/functional-tests/src/test/class-var-became-final-nok/problems.txt
  206. +3 −0  reporter/functional-tests/src/test/class-var-became-final-nok/v1/A.scala
  207. +3 −0  reporter/functional-tests/src/test/class-var-became-final-nok/v2/A.scala
  208. 0  reporter/functional-tests/src/test/class-was-final-becomes-not-final-ok/problems.txt
  209. +1 −0  reporter/functional-tests/src/test/class-was-final-becomes-not-final-ok/v1/A.scala
  210. +1 −0  reporter/functional-tests/src/test/class-was-final-becomes-not-final-ok/v2/A.scala
  211. +1 −0  reporter/functional-tests/src/test/class-widening-method-type-in-new-version-nok/problems.txt
  212. +3 −0  reporter/functional-tests/src/test/class-widening-method-type-in-new-version-nok/v1/A.scala
  213. +3 −0  reporter/functional-tests/src/test/class-widening-method-type-in-new-version-nok/v2/A.scala
  214. +1 −0  reporter/functional-tests/src/test/final-class-becomes-object-nok/problems.txt
  215. +1 −0  reporter/functional-tests/src/test/final-class-becomes-object-nok/v1/A.scala
  216. +1 −0  reporter/functional-tests/src/test/final-class-becomes-object-nok/v2/A.scala
  217. 0  reporter/functional-tests/src/test/missing-synthetic-classes-are-ignored-ok/problems.txt
  218. +4 −0 reporter/functional-tests/src/test/missing-synthetic-classes-are-ignored-ok/v1/A.scala
  219. +3 −0  reporter/functional-tests/src/test/missing-synthetic-classes-are-ignored-ok/v2/A.scala
  220. +1 −0  reporter/functional-tests/src/test/object-becomes-class-nok/problems.txt
  221. +1 −0  reporter/functional-tests/src/test/object-becomes-class-nok/v1/A.scala
  222. +1 −0  reporter/functional-tests/src/test/object-becomes-class-nok/v2/A.scala
  223. 0  reporter/functional-tests/src/test/object-becomes-class-with-companion-ok/problems.txt
  224. +1 −0  reporter/functional-tests/src/test/object-becomes-class-with-companion-ok/v1/A.scala
  225. +2 −0  reporter/functional-tests/src/test/object-becomes-class-with-companion-ok/v2/A.scala
  226. +3 −0  reporter/functional-tests/src/test/package-missing-in-new-version-is-ok/README.txt
  227. 0  reporter/functional-tests/src/test/package-missing-in-new-version-is-ok/problems.txt
  228. +8 −0 reporter/functional-tests/src/test/package-missing-in-new-version-is-ok/v1/A.scala
  229. +5 −0 reporter/functional-tests/src/test/package-missing-in-new-version-is-ok/v2/A.scala
  230. +1 −0  reporter/functional-tests/src/test/package-with-classes-missing-in-new-version-is-nok/README.txt
  231. +1 −0  reporter/functional-tests/src/test/package-with-classes-missing-in-new-version-is-nok/problems.txt
  232. +9 −0 reporter/functional-tests/src/test/package-with-classes-missing-in-new-version-is-nok/v1/A.scala
  233. +5 −0 reporter/functional-tests/src/test/package-with-classes-missing-in-new-version-is-nok/v2/A.scala
  234. 0  ...er/functional-tests/src/test/package-with-classes-splitted-into-two-files-in-new-version-is-ok/problems.txt
  235. +9 −0 ...rter/functional-tests/src/test/package-with-classes-splitted-into-two-files-in-new-version-is-ok/v1/A.scala
  236. +5 −0 ...rter/functional-tests/src/test/package-with-classes-splitted-into-two-files-in-new-version-is-ok/v2/A.scala
  237. +3 −0  ...rter/functional-tests/src/test/package-with-classes-splitted-into-two-files-in-new-version-is-ok/v2/B.scala
  238. +1 −0  reporter/functional-tests/src/test/trait-abstract-method-become-concrete-ok/README.txt
  239. 0  reporter/functional-tests/src/test/trait-abstract-method-become-concrete-ok/problems.txt
  240. +7 −0 reporter/functional-tests/src/test/trait-abstract-method-become-concrete-ok/v1/A.scala
  241. +7 −0 reporter/functional-tests/src/test/trait-abstract-method-become-concrete-ok/v2/A.scala
  242. +1 −0  reporter/functional-tests/src/test/trait-abstract-method-becomes-concrete2-ok/problems.txt
  243. +10 −0 reporter/functional-tests/src/test/trait-abstract-method-becomes-concrete2-ok/v1/A.scala
  244. +10 −0 reporter/functional-tests/src/test/trait-abstract-method-becomes-concrete2-ok/v2/A.scala
  245. +3 −0  reporter/functional-tests/src/test/trait-abstract-val-become-concrete-ok/README.txt
  246. +1 −0  reporter/functional-tests/src/test/trait-abstract-val-become-concrete-ok/problems.txt
  247. +7 −0 reporter/functional-tests/src/test/trait-abstract-val-become-concrete-ok/v1/A.scala
  248. +7 −0 reporter/functional-tests/src/test/trait-abstract-val-become-concrete-ok/v2/A.scala
  249. +1 −0  reporter/functional-tests/src/test/trait-abstract-var-become-concrete-ok/README.txt
  250. 0  reporter/functional-tests/src/test/trait-abstract-var-become-concrete-ok/problems.txt
  251. +7 −0 reporter/functional-tests/src/test/trait-abstract-var-become-concrete-ok/v1/A.scala
  252. +7 −0 reporter/functional-tests/src/test/trait-abstract-var-become-concrete-ok/v2/A.scala
  253. +1 −0  reporter/functional-tests/src/test/trait-added-method-in-new-version-nok/problems.txt
  254. +3 −0  reporter/functional-tests/src/test/trait-added-method-in-new-version-nok/v1/A.scala
  255. +4 −0 reporter/functional-tests/src/test/trait-added-method-in-new-version-nok/v2/A.scala
  256. +2 −0  reporter/functional-tests/src/test/trait-added-val-in-new-version-nok/problems.txt
  257. +3 −0  reporter/functional-tests/src/test/trait-added-val-in-new-version-nok/v1/A.scala
  258. +4 −0 reporter/functional-tests/src/test/trait-added-val-in-new-version-nok/v2/A.scala
  259. +2 −0  reporter/functional-tests/src/test/trait-added-var-in-new-version-nok/problems.txt
  260. +3 −0  reporter/functional-tests/src/test/trait-added-var-in-new-version-nok/v1/A.scala
  261. +4 −0 reporter/functional-tests/src/test/trait-added-var-in-new-version-nok/v2/A.scala
  262. +1 −0  reporter/functional-tests/src/test/trait-deleting-concrete-methods-is-nok/problems.txt
  263. +11 −0 reporter/functional-tests/src/test/trait-deleting-concrete-methods-is-nok/v1/A.scala
  264. +9 −0 reporter/functional-tests/src/test/trait-deleting-concrete-methods-is-nok/v2/A.scala
  265. 0  reporter/functional-tests/src/test/trait-extending-new-trait-with-no-concrete-method-ok/problems.txt
  266. +1 −0  reporter/functional-tests/src/test/trait-extending-new-trait-with-no-concrete-method-ok/v1/A.scala
  267. +5 −0 reporter/functional-tests/src/test/trait-extending-new-trait-with-no-concrete-method-ok/v2/A.scala
  268. +1 −0  reporter/functional-tests/src/test/trait-inherithing-from-class/problems.txt
  269. +6 −0 reporter/functional-tests/src/test/trait-inherithing-from-class/v1/A.scala
  270. +8 −0 reporter/functional-tests/src/test/trait-inherithing-from-class/v2/A.scala
  271. +1 −0  reporter/functional-tests/src/test/trait-method-overloading-is-ok/problems.txt
  272. +3 −0  reporter/functional-tests/src/test/trait-method-overloading-is-ok/v1/A.scala
  273. +4 −0 reporter/functional-tests/src/test/trait-method-overloading-is-ok/v2/A.scala
  274. +2 −0  reporter/functional-tests/src/test/trait-moving-methods-nok/problems.txt
  275. +8 −0 reporter/functional-tests/src/test/trait-moving-methods-nok/v1/A.scala
  276. +9 −0 reporter/functional-tests/src/test/trait-moving-methods-nok/v2/A.scala
  277. +1 −0  reporter/functional-tests/src/test/trait-moving-methods2-nok/problems.txt
  278. +8 −0 reporter/functional-tests/src/test/trait-moving-methods2-nok/v1/A.scala
  279. +9 −0 reporter/functional-tests/src/test/trait-moving-methods2-nok/v2/A.scala
  280. +1 −0  reporter/functional-tests/src/test/trait-pushing-up-abstract-methods-is-nok/problems.txt
  281. +7 −0 reporter/functional-tests/src/test/trait-pushing-up-abstract-methods-is-nok/v1/A.scala
  282. +7 −0 reporter/functional-tests/src/test/trait-pushing-up-abstract-methods-is-nok/v2/A.scala
  283. +2 −0  reporter/functional-tests/src/test/trait-pushing-up-concrete-methods-is-nok/problems.txt
  284. +7 −0 reporter/functional-tests/src/test/trait-pushing-up-concrete-methods-is-nok/v1/A.scala
  285. +7 −0 reporter/functional-tests/src/test/trait-pushing-up-concrete-methods-is-nok/v2/A.scala
  286. 0  reporter/functional-tests/src/test/trait-redeclaring-abstract-methods-in-subclass-is-ok/problems.txt
  287. +5 −0 reporter/functional-tests/src/test/trait-redeclaring-abstract-methods-in-subclass-is-ok/v1/A.scala
  288. +7 −0 reporter/functional-tests/src/test/trait-redeclaring-abstract-methods-in-subclass-is-ok/v2/A.scala
  289. 0  reporter/functional-tests/src/test/trait-removing-abstract-method-declared-in-superclass-is-ok/problems.txt
  290. +7 −0 reporter/functional-tests/src/test/trait-removing-abstract-method-declared-in-superclass-is-ok/v1/A.scala
  291. +5 −0 reporter/functional-tests/src/test/trait-removing-abstract-method-declared-in-superclass-is-ok/v2/A.scala
  292. +1 −0  reporter/functional-tests/src/test/trait-removing-class-type-from-inheritance-relationship-is-ok/README.txt
  293. 0  reporter/functional-tests/src/test/trait-removing-class-type-from-inheritance-relationship-is-ok/problems.txt
  294. +5 −0 reporter/functional-tests/src/test/trait-removing-class-type-from-inheritance-relationship-is-ok/v1/A.scala
  295. +5 −0 reporter/functional-tests/src/test/trait-removing-class-type-from-inheritance-relationship-is-ok/v2/A.scala
  296. 0  reporter/functional-tests/src/test/trait-use-type-alias-in-new-version-ok/problems.txt
  297. +3 −0  reporter/functional-tests/src/test/trait-use-type-alias-in-new-version-ok/v1/A.scala
  298. +4 −0 reporter/functional-tests/src/test/trait-use-type-alias-in-new-version-ok/v2/A.scala
  299. +87 −0 reporter/src/main/scala/ssol/tools/mima/lib/MiMaLib.scala
  300. +139 −0 reporter/src/main/scala/ssol/tools/mima/lib/analyze/Analyzer.scala
Sorry, we could not display the entire diff because too many files (321) changed.
View
8 .gitignore
@@ -0,0 +1,8 @@
+target/
+**/target
+*.scala_dependencies
+project/boot
+bin/
+.DS_Store
+**/.DS_Store
+.history
View
84 README.md
@@ -2,13 +2,91 @@ Migration Manager for Scala
==============
A tool for diagnosing and fixing migration problems for Scala libraries.
+=======
+The Migration Manager for Scala (MiMa in short) is a tool for diagnosing and fixing binary incompatibilities for Scala libraries.
+
+MiMa's Modules
+-------
+
+MiMa is split into three modules:
+
+- Core: Classes that are used by both the Reporter and Migrator modules.
+- Reporter: Used to diagnose binary incompatibilities between two different versions of a same library. (This was formerly named MiMa Lib)
+- Migrator: Used to fix binary incompatibilities of a client jar. (This was formerly named MiMa Client)
+
+Eclipse
+-------
+
+Folders `core`, `reporter` and `migrator` contain all metadata files used by Eclipse. To set up the three modules in Eclipse just click on `File > Import > General > Exisiting Projects Into Workspace`, and select the MiMa project's root folder, the three modules should be correctly loaded.
+
+In the `reporter` and `migrator` folders you can also find a `*.launch` file configuration, which can be imported in Eclipse and can be used to start the programs.
+
Build
-------
-Using [the sbt tool][sbt].
+Using [the xsbt tool][xsbt].
+
+ $ xsbt clean update compile
+
+
+Make sure to use tag 0.9.8, installation notes can be found [here][xsbt].
+
+[xsbt]: https://github.com/harrah/xsbt/tree/0.9
+
+This will recompile all MiMa's modules.
+
+
+Launch MiMa Reporter
+-------
+Type the following command to run the MiMa Reporter
+
+ $ xsbt // will start xsbt console
+ $ project reporter // will switch to the reporter project
+ $ run // will launch the MiMa Reporter UI
- $ sbt update compile
+Launch MiMa Migrator
+-------
+Type the following command to run the MiMa Reporter
+
+ $ xsbt // will start xsbt console
+ $ project migrator // will switch to the migrator project
+ $ run // will launch the MiMa Migrator UI
+
+
+MiMa Reporter: Functional Tests
+-------
+
+The directory containing the MiMa Reporter module ('reporter') there is a 'functional-tests' folder that contains several functional tests exercising the system. All tests are executed as part of the build, therefore when running
+
+ $ xsbt package
+
+if one (or more) test fails the build is stop and no jar will not be produced.
+
+To add a new functional test to the suite, create a new folder within 'functional-tests' directory with the following structure:
+
+ functional-tests
+ |
+ | --> <your-new-test-folder> (folder for your new test)
+ |
+ |-----> problems.txt (the expected list of reported errors - 1 line per error)
+ |-----> v1 (folder containing sources @ version 1)
+ |-----> v2 (folder containing sources @ version 2)
+
+After doing that, `reload` if you are in a `xsbt` console session (if that makes nosense to you, it means you are fine and you can run the test as usual).
+
+Tests within the `functional-tests` folder should always pass. If you spot a bug (or missing feature), please create a test that exercise the problem and put it in the `functional-tests-exposing-bugs` directory, located in the project root. Once the test succeed, then you should move it into the `functional-tests` directory.
+
+Note: The `problems.txt` is the test oracle. Expected errors are declared using the Mima's reporting output (i.e., the output of the tool and the expected errors should match perfectly). Admittedly, this coupling is an issue since the testing framework is highly coupled with the tool output used to report errors to the user. We should improve this and make the two independent. Until then, mind that by changing the output of the tool you will likely have to update some of the test oracles (i.e., problems.txt file).
+
+FAQ
+-------
+
+Exception - java.lang.OutOfMemoryError: Java heap space: If you are experiencing out of memory exception you may need to increase the VM arguments for the initial heap size and the maximum heap size. The default values are `-Xms64m` for for the initial heap size and `-Xmx256m` for the maximum heap size.
+
+Bugs and Feature requests
+-------
+Use the [Assembla project page][mima-assembla] for filing new tickets.
-[sbt]: http://code.google.com/p/simple-build-tool/
+[mima-assembla]: https://www.assembla.com/spaces/mima/tickets
View
13 build.sbt
@@ -0,0 +1,13 @@
+organization := "org.scalasolutions"
+
+name := "mima"
+
+version := "0.1"
+
+scalaVersion := "2.9.0"
+
+// Use the name and version to define the jar name.
+// XXX: Why this doesn't work?
+//jarName <<= (name, version) {
+// (name: String, version: String) => name + "-" + version + ".jar"
+//}
View
9 core/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/scala"/>
+ <classpathentry kind="src" path="src/main/resources"/>
+ <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
+ <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_COMPILER_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="target"/>
+</classpath>
View
18 core/.project
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>mima-core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.scala-ide.sdt.core.scalabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.scala-ide.sdt.core.scalanature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
View
3  core/build.sbt
@@ -0,0 +1,3 @@
+name := "mima-core"
+
+libraryDependencies ++= Seq("org.scala-lang" % "scala-swing" % "2.9.0" % "compile")
View
BIN  core/src/main/resources/images/add.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/alert.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/broken.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/check.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/close.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/down.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/exit.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/migration.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/remove.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/scala_logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/scala_logo2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/typesafe.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  core/src/main/resources/images/up.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
27 core/src/main/resources/license/LICENSE
@@ -0,0 +1,27 @@
+Typesafe Binary Code License Agreement for Migration Manager (Beta Release)
+
+TYPESAFE, INC. ("TYPESAFE"), FOR AND ON BEHALF OF ITSELF AND ITS SUBSIDIARIES AND AFFILIATES UNDER COMMON CONTROL, IS WILLING TO LICENSE THE SOFTWARE TO YOU ONLY UPON THE CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS BINARY CODE LICENSE AGREEMENT (COLLECTIVELY "AGREEMENT"). PLEASE READ THE AGREEMENT CAREFULLY. BY USING THE SOFTWARE YOU ACKNOWLEDGE THAT YOU HAVE READ THE TERMS AND AGREE TO THEM. IF YOU ARE AGREEING TO THESE TERMS ON BEHALF OF A COMPANY OR OTHER LEGAL ENTITY, YOU REPRESENT THAT YOU HAVE THE LEGAL AUTHORITY TO BIND THE LEGAL ENTITY TO THESE TERMS. IF YOU DO NOT HAVE SUCH AUTHORITY, OR IF YOU DO NOT WISH TO BE BOUND BY THE TERMS, THEN YOU MUST NOT USE THE SOFTWARE.
+
+1. DEFINITIONS. "Software" means the Typesafe Migration Manager (Beta Release) in binary form that you selected for download, install or use from Typesafe or its authorized licensees, any other machine readable materials (including, but not limited to, libraries, source files, header files, and data files), any updates or error corrections provided by Typesafe, and any user manuals, programming guides and other documentation provided to you by Typesafe under this Agreement.
+
+2. LICENSE TO USE. Subject to the terms and conditions of this Agreement, Typesafe grants you a non-exclusive, non-transferable, limited license without license fees to reproduce and use internally the Software complete and unmodified.
+
+3. RESTRICTIONS. The Software is copyrighted. Title to the Software and all associated intellectual property rights is retained by Typesafe and/or its licensors. Unless enforcement is prohibited by applicable law, you may not modify, decompile, or reverse engineer the Software. No right, title or interest in or to any trademark, service mark, logo or trade name of Typesafe or its licensors is granted under this Agreement.
+
+4. DISCLAIMER OF WARRANTY. THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. TYPESAFE FURTHER DISCLAIMS ALL WARRANTIES, EXPRESS AND IMPLIED, INCLUDING WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NONINFRINGEMENT.
+
+5. LIMITATION OF LIABILITY. IN NO EVENT SHALL TYPESAFE BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE OR CONSEQUENTIAL DAMAGES, OR DAMAGES FOR LOSS OF PROFITS, REVENUE, DATA OR DATA USE, INCURRED BY YOU OR ANY THIRD PARTY, WHETHER IN AN ACTION IN CONTRACT OR TORT, EVEN IF TYPESAFE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. TYPESAFE'S ENTIRE LIABILITY FOR DAMAGES HEREUNDER SHALL IN NO EVENT EXCEED ONE THOUSAND DOLLARS (U.S. $1,000).
+
+6. TERMINATION. This Agreement is effective until terminated. You may terminate this Agreement at any time by destroying all copies of Software. Typesafe may terminate this Agreement at any time by providing you with prior written notice. This Agreement will terminate immediately without notice from Typesafe if you fail to comply with any provision of this Agreement. Either party may terminate this Agreement immediately should any Software become, or in either party's opinion be likely to become, the subject of a claim of infringement of any intellectual property right. Upon termination, you must destroy all copies of the Software.
+
+7. EXPORT REGULATIONS. You agree that U.S. export control laws and other applicable export and import laws govern your use of the Software, including technical data. You agree that neither the Software nor any direct product thereof will be exported, directly, or indirectly, in violation of these laws, or will be used for any purpose prohibited by these laws.
+
+8. TRADEMARKS AND LOGOS. You acknowledge and agree as between you and Typesafe that Typesafe owns the TYPESAFE trademark and all TYPESAFE-related trademarks, service marks, logos and other brand designations ("Typesafe Marks").
+
+9. GOVERNING LAW. This agreement is governed by the laws of the Commonwealth of Massachusetts, without regard to the conflict of law principles. You and Typesafe agree to submit to the exclusive jurisdiction of, and venue in, the courts of the Commonwealth of Massachusetts in any dispute arising out of or relating to this agreement.
+
+10. SEVERABILITY. If any provision of this Agreement is held to be unenforceable, this Agreement will remain in effect with the provision omitted, unless omission would frustrate the intent of the parties, in which case this Agreement will immediately terminate.
+
+11. ENTIRE AGREEMENT. This Agreement is the entire agreement between you and Typesafe relating to its subject matter.
+
+Last updated May 28, 2011
View
39 core/src/main/scala/images/Icons.scala
@@ -0,0 +1,39 @@
+package images
+
+import scala.swing._
+import Swing._
+
+object Icons {
+
+ private lazy val sep = java.io.File.separator
+
+ private def getIcon = buildIcon _
+
+ /** Load the icon from the given path, or EmptyIcon if not found. */
+ private def buildIcon(filename: String) : javax.swing.Icon = {
+ getClass.getResource(filename) match {
+ case null => EmptyIcon
+ case value =>
+ val resource = Swing.Icon(value)
+ if(resource eq null) EmptyIcon else resource
+ }
+ }
+
+ lazy val typesafe = getIcon("typesafe.png")
+ lazy val scalaLogo = getIcon("scala_logo.png")
+
+ lazy val exit = getIcon("exit.png")
+ lazy val broken = getIcon("broken.png")
+ lazy val alert = getIcon("alert.png")
+
+ lazy val migration = getIcon("migration.jpg")
+ lazy val check = getIcon("check.jpg")
+
+ lazy val add = getIcon("add.png")
+ lazy val remove = getIcon("remove.png")
+ lazy val up = getIcon("up.png")
+ lazy val down = getIcon("down.png")
+
+ lazy val close = getIcon("close.gif")
+
+}
View
8 core/src/main/scala/license/License.scala
@@ -0,0 +1,8 @@
+package license
+
+object License {
+ val license: String = {
+ val url = getClass.getResourceAsStream("LICENSE")
+ io.Source.fromInputStream(url).mkString
+ }
+}
View
2  src/main/scala/ssol/tools/mima/BufferReader.scala → ...ain/scala/ssol/tools/mima/core/BufferReader.scala
@@ -4,7 +4,7 @@
*/
-package ssol.tools.mima
+package ssol.tools.mima.core
import java.lang.Float.intBitsToFloat
import java.lang.Double.longBitsToDouble
View
283 core/src/main/scala/ssol/tools/mima/core/ClassInfo.scala
@@ -0,0 +1,283 @@
+package ssol.tools.mima.core
+
+import scala.tools.nsc.io.AbstractFile
+import scala.reflect.NameTransformer
+
+object ClassInfo {
+ def formatClassName(str: String) = NameTransformer.decode(str).replace('$', '#')
+
+ /** We assume there can be only one java.lang.Object class, and that comes from the configuration
+ * class path.
+ */
+ lazy val ObjectClass = Config.baseDefinitions.fromName("java.lang.Object")
+}
+
+import ssol.tools.mima.core.util.log.{ConsoleLogging, Logging}
+
+/** A placeholder class info for a class that is not found on the classpath or in a given
+ * package.
+ */
+class SyntheticClassInfo(owner: PackageInfo, val name: String) extends ClassInfo(owner) {
+ loaded = true
+ def file: AbstractFile = throw new UnsupportedOperationException
+ override lazy val superClasses = Nil
+ override lazy val allTraits = Set.empty[ClassInfo]
+ override lazy val allInterfaces: Set[ClassInfo] = Set.empty[ClassInfo]
+}
+
+/** As the name implies. */
+object NoClass extends SyntheticClassInfo(null, "<noclass>")
+
+/** A class for which we have the classfile. */
+class ConcreteClassInfo(owner: PackageInfo, val file: AbstractFile) extends ClassInfo(owner) {
+ def name = PackageInfo.className(file.name)
+}
+
+abstract class ClassInfo(val owner: PackageInfo) extends WithAccessFlags {
+ import ClassInfo._
+
+ def file: AbstractFile
+
+ private var _sourceFileName = ""
+ def sourceFileName_=(fileName: String) = _sourceFileName = fileName
+ def sourceFileName = this match {
+ case c: ConcreteClassInfo => _sourceFileName
+ case _ => "compiler generated"
+ }
+
+ def name: String
+
+ lazy val fullName: String = {
+ assert(name != null)
+ if (owner.isRoot) name
+ else owner.fullName + "." + name
+ }
+
+ def formattedFullName = formatClassName(if (isObject) fullName.init else fullName)
+
+ def declarationPrefix = {
+ if (isObject) "object"
+ else if (isTrait) "trait"
+ else if (loaded && isInterface) "interface" // java interfaces and traits with no implementation methods
+ else "class"
+ }
+
+ def classString = (accessModifier + " " + declarationPrefix + " " + formattedFullName).trim
+
+ protected var loaded = false
+
+ import ssol.tools.mima.core.util.log.ConsoleLogging._
+ override protected def ensureLoaded() =
+ if (!loaded)
+ try {
+ info("parsing " + file)
+ owner.definitions.ClassfileParser.parse(this)
+ } finally {
+ loaded = true
+ }
+
+ private var _superClass: ClassInfo = NoClass
+ private var _interfaces: List[ClassInfo] = Nil
+ private var _fields: Members = NoMembers
+ private var _methods: Members = NoMembers
+ private var _flags: Int = 0
+ private var _isScala: Boolean = false
+
+ def superClass: ClassInfo = { ensureLoaded(); _superClass }
+ def interfaces: List[ClassInfo] = { ensureLoaded(); _interfaces }
+ def fields: Members = { ensureLoaded(); _fields }
+ def methods: Members = { ensureLoaded(); _methods }
+ override def flags: Int = _flags
+
+ /** currently not set! */
+ def isScala: Boolean = { ensureLoaded(); _isScala }
+
+ def superClass_=(x: ClassInfo) = _superClass = x
+ def interfaces_=(x: List[ClassInfo]) = _interfaces = x
+ def fields_=(x: Members) = _fields = x
+ def methods_=(x: Members) = _methods = x
+ def flags_=(x: Int) = _flags = x
+ def isScala_=(x: Boolean) = _isScala = x
+
+ lazy val superClasses: List[ClassInfo] =
+ (if (this == ClassInfo.ObjectClass) Nil else superClass :: superClass.superClasses)
+
+ def lookupClassFields(name: String): Iterator[MemberInfo] =
+ (Iterator.single(this) ++ superClasses.iterator) flatMap (_.fields.get(name))
+
+ def lookupClassMethods(name: String): Iterator[MemberInfo] =
+ (Iterator.single(this) ++ superClasses.iterator) flatMap (_.methods.get(name))
+
+ private def lookupInterfaceMethods(name: String): Iterator[MemberInfo] =
+ allInterfaces.iterator flatMap (_.methods.get(name))
+
+ def lookupMethods(name: String): Iterator[MemberInfo] =
+ lookupClassMethods(name) ++ lookupInterfaceMethods(name)
+
+ def lookupConcreteTraitMethods(name: String): Iterator[MemberInfo] =
+ allTraits.toList.flatten(_.concreteMethods).filter(_.name == name).toIterator
+
+ /** Is this class a non-trait that inherits !from a trait */
+ lazy val isClassInheritsTrait = !isInterface && _interfaces.exists(_.isTrait)
+
+ /** Should methods be parsed from classfile? */
+ def methodsAreRelevant = isTrait || isImplClass || _interfaces.exists(_.isTrait)
+
+ /** The constructors of this class
+ * pre: methodsAreRelevant
+ */
+ def constructors: List[MemberInfo] =
+ if (methods == null) null
+ else methods.iterator.filter(_.isClassConstructor).toList
+
+ /** The setter methods defined of this trait that correspond to
+ * a concrete field. TODO: define and check annotation for a mutable
+ * setter.
+ */
+ lazy val traitSetters: List[MemberInfo] = {
+ assert(isTrait)
+ methods.iterator filter (_.isTraitSetter) toList
+ }
+
+ /** The concrete methods of this trait */
+ lazy val concreteMethods: List[MemberInfo] = {
+ if(isTrait) methods.iterator filter (hasStaticImpl(_)) toList
+ else if(isClass) methods.iterator filter (!_.isDeferred) toList
+ else Nil
+ }
+
+ /** The deferred methods of this trait */
+ lazy val deferredMethods: List[MemberInfo] =
+ methods.iterator.toList -- concreteMethods
+
+ /** The inherited traits in the linearization of this class or trait,
+ * except any traits inherited by its superclass.
+ * Traits appear in linearization order of this class or trait.
+ */
+ lazy val directTraits: List[ClassInfo] = {
+ /** All traits in the transitive, reflexive inheritance closure of given trait `t' */
+ def traitClosure(t: ClassInfo): List[ClassInfo] =
+ if (superClass.allTraits contains t) Nil
+ else if (t.isTrait) parentsClosure(t) :+ t
+ else parentsClosure(t)
+
+ def parentsClosure(c: ClassInfo) =
+ (c.interfaces flatMap traitClosure).distinct
+
+ parentsClosure(this)
+ }
+
+ /** All traits inherited directly or indirectly by this class */
+ lazy val allTraits: Set[ClassInfo] =
+ if (this == ClassInfo.ObjectClass) Set.empty
+ else superClass.allTraits ++ directTraits
+
+ /** All traits inherited directly or indirectly by this class */
+ lazy val allInterfaces: Set[ClassInfo] =
+ if (this == ClassInfo.ObjectClass) Set.empty
+ else superClass.allInterfaces ++ interfaces ++ (interfaces flatMap (_.allInterfaces))
+
+ private def unimplemented(sel: ClassInfo => Traversable[MemberInfo]): List[MemberInfo] = {
+ ensureLoaded()
+ if (isClassInheritsTrait) {
+ for {
+ t <- directTraits.toList
+ m <- sel(t)
+ if !hasInstanceImpl(m)
+ } yield m
+ } else Nil
+ }
+
+ /** The methods that should be implemented by this class but aren't */
+ lazy val unimplementedMethods = unimplemented(_.concreteMethods)
+
+ /** The fields that should be implemented by this class but aren't */
+ lazy val unimplementedSetters = unimplemented(_.traitSetters)
+
+ /** Does this class have an implementation (forwarder or accessor) of given method `m'? */
+ private def hasInstanceImpl(m: MemberInfo) =
+ methods.get(m.name) exists (_.sig == m.sig)
+
+ /** Does this implementation class have a static implementation of given method `m'? */
+ def hasStaticImpl(m: MemberInfo) = staticImpl(m).isDefined
+
+ /** Optionally, the static implementation method corresponding to trait member `m' */
+ def staticImpl(m: MemberInfo): Option[MemberInfo] = {
+ if(isTrait) {
+ implClass match {
+ case impl: ConcreteClassInfo =>
+ assert(impl.isImplClass, impl)
+ impl.methods.get(m.name) find (im => hasImplSig(im.sig, m.sig))
+
+ case _ => None
+ }
+ }
+ else None
+ }
+
+ /** Does `isig' correspond to `tsig' if seen as the signature of the static
+ * implementation method of a trait method with signature `tsig'?
+ */
+ private def hasImplSig(isig: String, tsig: String) = {
+ assert(isig(0) == '(' && isig(1) == 'L' && tsig(0) == '(')
+ val ilen = isig.length
+ val tlen = tsig.length
+ var i = 2
+ while (isig(i) != ';') i += 1
+ i += 1
+ var j = 1
+ while (i < ilen && j < tlen && isig(i) == tsig(j)) {
+ i += 1
+ j += 1
+ }
+ i == ilen && j == tlen
+ }
+
+ /** Is this class an implementation class? */
+ lazy val isImplClass: Boolean = name endsWith PackageInfo.implClassSuffix
+
+ /** The implementation class corresponding to this trait */
+ private var _implClass: ClassInfo = NoClass
+
+ def implClass_=(ic: ClassInfo) = _implClass = ic
+
+ /** The implementation class of this trait, or NoClass if it is not a trait.
+ */
+ def implClass: ClassInfo = {
+ owner.traits // make sure we have implClass set
+ _implClass
+ }
+
+ /** is this a class, an object or a trait's implementation class*/
+ def isClass: Boolean = !isTrait && !isInterface
+
+ /** Is this class a trait with some concrete methods or fields? */
+ def isTrait: Boolean = implClass ne NoClass
+
+ /** Is this class a trait without concrete methods or a java interface? */
+ def isInterface: Boolean = {
+ ensureLoaded()
+ ClassfileParser.isInterface(flags)
+ }
+
+ def isObject: Boolean = name.endsWith("$")
+
+ /** Is this class public? */
+ /*
+ def isPackageVisible: Boolean = {
+ ensureLoaded()
+ !ClassfileParser.isPrivate(flags)
+ }*/
+
+ override def toString = "class " + name
+
+ def shortDescription = {
+ // using 'description' because elsewhere objects' name are not correctly translated.
+ // In fact, formatClassName(name) would have a suffixed '#' for an object name, which is annoying.
+ val descr = description
+ val index = descr.lastIndexOf(descr)
+ if (index < 0) descr else descr.substring(index)
+ }
+
+ def description: String = declarationPrefix + " " + formattedFullName
+}
View
52 src/main/scala/ssol/tools/mima/ClassfileParser.scala → .../scala/ssol/tools/mima/core/ClassfileParser.scala
@@ -3,25 +3,33 @@
* @author Martin Odersky
*/
-package ssol.tools.mima
+package ssol.tools.mima.core
import java.io.IOException
import scala.collection.mutable.ArrayBuffer
import scala.tools.nsc.symtab.classfile.ClassfileConstants._
import scala.annotation.switch
-object ClassfileParser extends ClassfileParser {
+class ClientClassfileParser(definitions: Definitions) extends ClassfileParser(definitions) {
var readFields = (clazz: ClassInfo) => false
var readMethods = (clazz: ClassInfo) => clazz.methodsAreRelevant
var readCode = (meth: MemberInfo) => meth.needCode
}
+class LibClassfileParser(definitions: Definitions) extends ClassfileParser(definitions) {
+ var readFields = (clazz: ClassInfo) => true
+ var readMethods = (clazz: ClassInfo) => true
+ var readCode = (meth: MemberInfo) => false
+}
+
+
/** This abstract class implements a class file parser.
*
* @author Martin Odersky
* @version 1.0
*/
-abstract class ClassfileParser {
+abstract class ClassfileParser(definitions: Definitions) {
+ import ClassfileParser._
/** Configuration:
*/
@@ -32,7 +40,6 @@ abstract class ClassfileParser {
var in: BufferReader = _ // the class file reader
private var thepool: ConstantPool = _
protected var parsedClass: ClassInfo = _
- var parsed: Int = 0
def pool: ConstantPool = thepool
@@ -127,7 +134,7 @@ abstract class ClassfileParser {
val start = starts(index)
if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
val name = getExternalName(in.getChar(start + 1))
- c = ClassInfo.fromName(name)
+ c = definitions.fromName(name)
//if (c == ClassInfo.NoClass) println("warning: missing class "+name+" referenced from "+parsedClass.file)
values(index) = c
}
@@ -237,19 +244,20 @@ abstract class ClassfileParser {
val externalName = pool.getClassName(nameIdx)
def parseSuperClass(): ClassInfo =
- if (hasAnnotation(clazz.flags)) { in.nextChar; ClassInfo.AnnotationClass }
+ if (hasAnnotation(clazz.flags)) { in.nextChar; definitions.AnnotationClass }
else pool.getSuperClass(in.nextChar)
def parseInterfaces(): List[ClassInfo] = {
val rawInterfaces =
for (i <- List.range(0, in.nextChar)) yield pool.getSuperClass(in.nextChar)
- rawInterfaces filter (_ != ClassInfo.NoClass)
+ rawInterfaces filter (_ != NoClass)
}
clazz.superClass = parseSuperClass()
clazz.interfaces = parseInterfaces()
parseFields(clazz)
parseMethods(clazz)
+ parseAttributes(clazz)
}
def skipAttributes() {
@@ -258,7 +266,25 @@ abstract class ClassfileParser {
in.skip(2); in.skip(in.nextInt)
}
}
-
+
+ def parseAttributes(c: ClassInfo) {
+ val attrCount = in.nextChar
+ for (i <- 0 until attrCount) {
+ val attrIndex = in.nextChar
+ val attrName = pool.getName(attrIndex)
+ val attrLen = in.nextInt
+ val attrEnd = in.bp + attrLen
+ if (attrName == "SourceFile") {
+ if(in.bp + 1 <= attrEnd) {
+ val attrNameIndex = in.nextChar
+ c.sourceFileName = pool.getName(attrNameIndex)
+ }
+ }
+
+ in.bp = attrEnd
+ }
+ }
+
/** Return true iff TraitSetter annotation found among attributes */
def parseAttributes(m: MemberInfo) {
val maybeTraitSetter = MemberInfo.maybeSetter(m.name)
@@ -286,6 +312,8 @@ abstract class ClassfileParser {
val maxLocals = in.nextChar
val codeLength = in.nextInt
m.codeOpt = Some((in.bp, in.bp + codeLength))
+ } else if (attrName == "Deprecated") {
+ m.isDeprecated = true
}
in.bp = attrEnd
}
@@ -326,9 +354,15 @@ abstract class ClassfileParser {
}
}
}
+}
+
+object ClassfileParser {
+ var parsed: Int = 0
@inline final def isPublic(flags: Int) =
(flags & JAVA_ACC_PUBLIC) != 0
+ @inline final def isProtected(flags: Int) =
+ (flags & JAVA_ACC_PROTECTED) != 0
@inline final def isPrivate(flags: Int) =
(flags & JAVA_ACC_PRIVATE) != 0
@inline final private def isStatic(flags: Int) =
@@ -339,4 +373,6 @@ abstract class ClassfileParser {
(flags & JAVA_ACC_INTERFACE) != 0
@inline final def isDeferred(flags: Int) =
(flags & JAVA_ACC_ABSTRACT) != 0
+ @inline final def isFinal(flags: Int) =
+ (flags & JAVA_ACC_FINAL) != 0
}
View
67 core/src/main/scala/ssol/tools/mima/core/Config.scala
@@ -0,0 +1,67 @@
+package ssol.tools.mima.core
+
+import scala.tools.nsc.io.{ Path, Directory }
+import scala.tools.nsc.util.JavaClassPath
+import scala.util.Properties
+import java.io.File
+
+object Config {
+
+ private var settings: Settings = _
+ private var _classpath: JavaClassPath = _
+
+ def inPlace = settings.mimaOutDir.isDefault
+
+ def verbose = settings.verbose.value
+ def debug = settings.debug.value
+
+ def fixall = settings.fixall.value
+
+ def error(msg: String) = System.err.println(msg)
+
+ def baseClassPath: JavaClassPath = _classpath
+
+ lazy val baseDefinitions = new Definitions(None, baseClassPath)
+
+ def baseClassPath_=(cp: JavaClassPath) {
+ _classpath = cp
+ }
+
+ def fatal(msg: String): Nothing = {
+ error(msg)
+ System.exit(-1)
+ throw new Error()
+ }
+
+ lazy val outDir: Directory = {
+ assert(!inPlace)
+ val f = Path(settings.mimaOutDir.value).toDirectory
+ if (!(f.isDirectory && f.canWrite)) fatal(f + " is not a writable directory")
+ f
+ }
+
+ /** Creates a help message for a subset of options based on cond */
+ def usageMsg(cmd: String): String =
+ settings.visibleSettings.
+ map(s => format(s.helpSyntax).padTo(21, ' ') + " " + s.helpDescription).
+ toList.sorted.mkString("Usage: " + cmd + " <options>\nwhere possible options include:\n ", "\n ", "\n")
+
+ def setup(s: Settings) {
+ settings = s
+ }
+
+ def setup(cmd: String, args: Array[String], specificOptions: String*): List[String] =
+ setup(cmd, args, _ => true, specificOptions: _*)
+
+ def setup(cmd: String, args: Array[String], validate: List[String] => Boolean, specificOptions: String*): List[String] = {
+ settings = new Settings(specificOptions: _*)
+ val (_, resargs) = settings.processArguments(args.toList, true)
+ baseClassPath = new PathResolver(settings).mimaResult
+ if (settings.help.value) {
+ println(usageMsg(cmd))
+ System.exit(0)
+ }
+ if (validate(resargs)) resargs
+ else fatal(usageMsg(cmd))
+ }
+}
View
105 core/src/main/scala/ssol/tools/mima/core/Definitions.scala
@@ -0,0 +1,105 @@
+package ssol.tools.mima.core
+
+import scala.tools.nsc.util.{ClassPath, JavaClassPath, DirectoryClassPath}
+
+
+/** This class holds together a root package and a classpath. It
+ * also offers definitions of commonly used classes, including
+ * java.lang.Object
+ *
+ * Each version of the input jar file has an instance of Definitions, used
+ * to resolve type names during classfile parsing.
+ */
+class Definitions(val lib: Option[DirectoryClassPath], val classPath: JavaClassPath) {
+ import ssol.tools.mima.core.util.log.ConsoleLogging._
+
+ lazy val root =
+ new ConcretePackageInfo(null,
+ new JavaClassPath(
+ if (lib.isDefined) List(lib.get, classPath)
+ else List(classPath), DefaultJavaContext), this)
+
+ /** Return all packages in the target library. */
+ lazy val targetPackage: PackageInfo = {
+ val pkg = new SyntheticPackageInfo(root, "<root>") {
+ override def isRoot = true
+ /** Needed to fetch classes located in the root (empty package) */
+ override lazy val classes = Definitions.this.root.classes
+ }
+ pkg.packages ++= lib.get.packages map (cp => cp.name -> new ConcretePackageInfo(pkg, cp, this))
+
+ debugLog("added packages to <root>: %s".format(pkg.packages.keys.mkString(", ")))
+ pkg
+ }
+
+ lazy val ObjectClass = fromName("java.lang.Object")
+ lazy val AnnotationClass = fromName("java.lang.annotation.Annotation")
+
+ lazy val ClassfileParser = new LibClassfileParser(this)
+
+ /** Return the class corresponding to the fully qualified name.
+ * If there is no such class in the current classpath, a SyntheticClassInfo
+ * and all necessary SyntheticPackageInfo are created along the way.
+ */
+ def fromName(name: String): ClassInfo = {
+ val parts = name.split("\\.")
+ var pkg: PackageInfo = this.root
+ var i = 0
+ var part = parts(i)
+ while (i < parts.length - 1) {
+ pkg.packages get part match {
+ case Some(p) => pkg = p
+ case None =>
+ val newpkg = new SyntheticPackageInfo(pkg, part)
+ pkg.packages += (part -> newpkg)
+ pkg = newpkg
+ }
+ i += 1
+ part = parts(i)
+ }
+ pkg.classes getOrElse (part, new SyntheticClassInfo(pkg, part))
+ }
+
+ import Type._
+
+ /** Return the type corresponding to 'sig'. Class names are resolved
+ * relative to the current classpath.
+ */
+ def fromSig(sig: String): Type = {
+ var in = 0
+
+ def getType(): Type = {
+ val ch = sig(in)
+ in += 1
+ abbrevToValueType get ch match {
+ case Some(tp) =>
+ tp
+ case None =>
+ if (ch == '[') {
+ ArrayType(getType())
+ } else if (ch == 'L') {
+ val end = sig indexOf (';', in)
+ val fullname = sig.substring(in, end) replace ('/', '.')
+ in = end + 1
+ ClassType(fromName(fullname))
+ } else if (ch == '(') {
+ val params = getParamTypes()
+ in += 1
+ MethodType(params, getType())
+ } else {
+ throw new MatchError("unknown signature: "+sig.substring(in))
+ }
+ }
+ }
+
+ def getParamTypes(): List[Type] =
+ if (sig(in) == ')') List()
+ else getType() :: getParamTypes()
+
+ getType()
+ }
+
+ override def toString = {
+ "definitions:\n\tlib: %s\n%s".format(lib, classPath.asClasspathString)
+ }
+}
View
5 core/src/main/scala/ssol/tools/mima/core/HasAccessFlags.scala
@@ -0,0 +1,5 @@
+package ssol.tools.mima.core
+
+trait HasAccessFlags {
+ protected def flags: Int
+}
View
28 src/main/scala/ssol/tools/mima/MemberInfo.scala → .../main/scala/ssol/tools/mima/core/MemberInfo.scala
@@ -1,4 +1,4 @@
-package ssol.tools.mima
+package ssol.tools.mima.core
import scala.reflect.NameTransformer
@@ -13,15 +13,25 @@ object MemberInfo {
def maybeSetter(name: String) = name.endsWith(setterSuffix)
}
-class MemberInfo(val owner: ClassInfo, val name: String, val flags: Int, val sig: String) {
- override def toString = "def "+name+": "+sig
+class MemberInfo(val owner: ClassInfo, val name: String, override val flags: Int, val sig: String) extends WithAccessFlags {
+ override def toString = "def "+name+": "+ sig
- def decodedName = NameTransformer.decode(name)
+ def decodedName = NameTransformer.decode(name)
def fieldString = "field "+decodedName+" in "+owner.classString
- def methodString = "method "+decodedName+Type.fromSig(sig)+" in "+owner.classString
+ def shortMethodString = (if(hasSyntheticName) "synthetic " else "") + (if(isDeprecated) "deprecated " else "") + "method "+decodedName + tpe
+ def methodString = shortMethodString + " in " + owner.classString
+ def defString = (if(isDeprecated) "@deprecated " else "") + "def " + decodedName + params.mkString("(", ",", ")") + ": " + tpe.resultType + " = "
+ def applyString = decodedName + params.mkString("(", ",", ")")
+
+ lazy val params: List[String] = tpe match {
+ case MethodType(paramTypes, resultType) =>
+ for ((ptype, index) <- paramTypes.zipWithIndex) yield "par" + index + ": " + ptype
+ }
+
+ def fullName = owner.formattedFullName + "." + decodedName
- def tpe: Type = Type.fromSig(sig)
+ def tpe: Type = owner.owner.definitions.fromSig(sig)
def staticImpl = owner.implClass.staticImpl(this)
@@ -40,6 +50,8 @@ class MemberInfo(val owner: ClassInfo, val name: String, val flags: Int, val sig
assert(sig(0) == '(')
sig substring ((sig indexOf ")") + 1)
}
+
+
var codeOpt: Option[(Int, Int)] = None
def isClassConstructor = name == "<init>"
@@ -50,9 +62,7 @@ class MemberInfo(val owner: ClassInfo, val name: String, val flags: Int, val sig
var isTraitSetter = maybeSetter(name) && setterIdx(name) >= 0
- def isPublic: Boolean = ClassfileParser.isPublic(flags)
-
- def isDeferred: Boolean = ClassfileParser.isDeferred(flags)
+ var isDeprecated = false
def hasSyntheticName: Boolean = decodedName contains '$'
View
4 src/main/scala/ssol/tools/mima/Members.scala → ...src/main/scala/ssol/tools/mima/core/Members.scala
@@ -1,4 +1,5 @@
-package ssol.tools.mima
+package ssol.tools.mima.core
+
import collection.mutable
import collection.TraversableOnce
@@ -15,3 +16,4 @@ class Members(val members: TraversableOnce[MemberInfo]) {
}
+object NoMembers extends Members(Nil)
View
64 src/main/scala/ssol/tools/mima/PackageInfo.scala → ...main/scala/ssol/tools/mima/core/PackageInfo.scala
@@ -1,4 +1,4 @@
-package ssol.tools.mima
+package ssol.tools.mima.core
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.util.ClassPath
@@ -7,66 +7,82 @@ import collection.mutable
object PackageInfo {
val classExtension = ".class"
val implClassSuffix = "$class"
+
def className(fileName: String) = {
assert(fileName endsWith classExtension)
fileName.substring(0, fileName.length - classExtension.length)
}
+
def traitName(iclassName: String) = {
assert(iclassName endsWith implClassSuffix)
iclassName.substring(0, iclassName.length - implClassSuffix.length)
}
- lazy val classpath = new PathResolver(Config.settings).mimaResult
- lazy val root = new ConcretePackageInfo(null, classpath)
- Config.info("classpath = "+classpath)
}
import PackageInfo._
class SyntheticPackageInfo(owner: PackageInfo, val name: String) extends PackageInfo(owner) {
- lazy val packages: mutable.Map[String, PackageInfo] = mutable.Map()
- lazy val classes: mutable.Map[String, ClassInfo] = mutable.Map()
+ def definitions: Definitions = error("Called definitions on synthetic package")
+ lazy val packages = mutable.Map.empty[String, PackageInfo]
+ lazy val classes = mutable.Map.empty[String, ClassInfo]
}
-class ConcretePackageInfo(owner: PackageInfo, cp: ClassPath[AbstractFile]) extends PackageInfo(owner) {
+object NoPackageInfo extends SyntheticPackageInfo(null, "<no package>")
+
+/** A concrete package. cp should be a directory classpath.
+ */
+class ConcretePackageInfo(owner: PackageInfo, cp: ClassPath[AbstractFile], val defs: Definitions) extends PackageInfo(owner) {
+ def definitions = defs
def name = cp.name
private def classFiles: List[AbstractFile] = cp.classes flatMap (_.binary)
lazy val packages: mutable.Map[String, PackageInfo] =
- mutable.Map() ++= (cp.packages map (cp => cp.name -> new ConcretePackageInfo(this, cp)))
+ mutable.Map() ++= (cp.packages map (cp => cp.name -> new ConcretePackageInfo(this, cp, defs)))
lazy val classes: mutable.Map[String, ClassInfo] =
mutable.Map() ++= (classFiles map (f => className(f.name) -> new ConcreteClassInfo(this, f)))
}
+/** Package information, including available classes and packages, and what is
+ * accessible.
+ */
abstract class PackageInfo(val owner: PackageInfo) {
def name: String
-
+
+ def definitions: Definitions
+
def isRoot = owner == null
+
+ private lazy val root: PackageInfo = if (isRoot) this else owner.root
- def fullName: String = if (isRoot) "<root>"
+ def fullName: String = if (isRoot) "<root>"
else if (owner.isRoot) name
else owner.fullName + "." + name
def packages: mutable.Map[String, PackageInfo]
def classes: mutable.Map[String, ClassInfo]
- private def isAccessible(clazz: ClassInfo, prefix: Set[ClassInfo]) = {
- val idx = clazz.name.lastIndexOf("$")
- val isReachable =
- if (idx < 0) prefix.isEmpty // class name contains no $
- else (prefix exists (_.name == clazz.name.substring(0, idx))) // prefix before dollar is an accessible class detected previously
- isReachable && clazz.isPublic
- }
-
- private def accessibleClassesUnder(prefix: Set[ClassInfo]): Set[ClassInfo] = {
- val vclasses = (classes.valuesIterator filter (isAccessible(_, prefix))).toSet
- if (vclasses.isEmpty) vclasses
- else vclasses union accessibleClassesUnder(vclasses)
+ lazy val accessibleClasses: Set[ClassInfo] = {
+ /** Fixed point iteration for finding all accessible classes. */
+ def accessibleClassesUnder(prefix: Set[ClassInfo]): Set[ClassInfo] = {
+ val vclasses = (classes.valuesIterator filter (isAccessible(_, prefix))).toSet
+ if (vclasses.isEmpty) vclasses
+ else vclasses union accessibleClassesUnder(vclasses)
+ }
+
+ def isAccessible(clazz: ClassInfo, prefix: Set[ClassInfo]) = {
+ val idx = clazz.name.lastIndexOf("$")
+ lazy val isReachable =
+ if (idx < 0) prefix.isEmpty // class name contains no $
+ else (prefix exists (_.name == clazz.name.substring(0, idx))) // prefix before dollar is an accessible class detected previously
+ clazz.isPublic && isReachable
+ }
+
+ accessibleClassesUnder(Set.empty)
}
-
- lazy val accessibleClasses: Set[ClassInfo] = accessibleClassesUnder(Set())
+ /** All implementation classes of traits (classes that end in '$class'). */
lazy val implClasses: mutable.Map[String, ClassInfo] =
classes filter { case (name, _) => name endsWith implClassSuffix }
View
5 src/main/scala/ssol/tools/mima/PathResolver.scala → ...ain/scala/ssol/tools/mima/core/PathResolver.scala
@@ -1,11 +1,8 @@
-package ssol.tools.mima
+package ssol.tools.mima.core
import scala.tools.nsc.util.{JavaClassPath, ClassPath}
class PathResolver(settings: Settings) extends scala.tools.util.PathResolver(settings, DefaultJavaContext) {
-// lazy val mimaBasis = Calculated.basis.tail // drop java bootclasspath
-// lazy val mimaContainersVup = basisVup.flatten.distinct
-
lazy val mimaResult = new JavaClassPath(containers, DefaultJavaContext)
}
View
132 core/src/main/scala/ssol/tools/mima/core/Problems.scala
@@ -0,0 +1,132 @@
+package ssol.tools.mima.core
+
+object Problem {
+ object Status extends Enumeration {
+ val Unfixable = Value("unfixable")
+ val Upgradable = Value("upgradable") // means MiMa Client can fix the bytecode
+ val Ignored = Value("ignored")
+ }
+
+ object ClassVersion extends Enumeration {
+ val New = Value("new")
+ val Old = Value("old")
+ }
+}
+
+trait ProblemRef {
+ type Ref
+ def ref: Ref
+ def fileName: String
+ def referredMember: String
+}
+
+trait TemplateRef extends ProblemRef {
+ type Ref = ClassInfo
+ def fileName: String = ref.sourceFileName
+ def referredMember: String = ref.shortDescription
+}
+
+trait MemberRef extends ProblemRef {
+ type Ref = MemberInfo
+ def fileName: String = ref.owner.sourceFileName
+ def referredMember: String = ref.fullName
+}
+
+sealed abstract class Problem extends ProblemRef {
+ var status = Problem.Status.Unfixable
+ var affectedVersion = Problem.ClassVersion.New
+ def description: String
+}
+
+abstract class TemplateProblem(override val ref: ClassInfo) extends Problem with TemplateRef
+
+abstract class MemberProblem(override val ref: MemberInfo) extends Problem with MemberRef
+
+case class MissingFieldProblem(oldfld: MemberInfo) extends MemberProblem(oldfld) {
+ def description = oldfld.fieldString + " does not have a correspondent in " + affectedVersion + " version"
+}
+
+case class MissingMethodProblem(meth: MemberInfo) extends MemberProblem(meth) {
+ def description = (if (meth.isDeferred && !meth.owner.isTrait) "abstract " else "") + meth.methodString + " does not have a correspondent in " + affectedVersion + " version"
+}
+
+case class UpdateForwarderBodyProblem(meth: MemberInfo) extends MemberProblem(meth) {
+ assert(meth.owner.isTrait)
+ assert(meth.owner.hasStaticImpl(meth))
+
+ status = Problem.Status.Upgradable
+
+ def description = "classes mixing " + meth.owner.fullName + " needs to update body of " + meth.shortMethodString
+}
+
+case class MissingClassProblem(oldclazz: ClassInfo) extends TemplateProblem(oldclazz) {
+ def description = oldclazz.classString + " does not have a correspondent in " + affectedVersion + " version"
+}
+
+case class AbstractClassProblem(oldclazz: ClassInfo) extends TemplateProblem(oldclazz) {
+ def description = oldclazz.classString + " was concrete; is declared abstract in " + affectedVersion + " version"
+}
+
+case class FinalClassProblem(oldclazz: ClassInfo) extends TemplateProblem(oldclazz) {
+ def description = oldclazz.classString + " is declared final in " + affectedVersion + " version"
+}
+
+case class FinalMethodProblem(newmemb: MemberInfo) extends MemberProblem(newmemb) {
+ def description = newmemb.methodString + " is declared final in " + affectedVersion + " version"
+}
+
+case class IncompatibleFieldTypeProblem(oldfld: MemberInfo, newfld: MemberInfo) extends MemberProblem(oldfld) {
+ def description = newfld.fieldString + "'s type has changed; was: " + oldfld.tpe + ", is now: " + newfld.tpe
+}
+
+case class IncompatibleMethTypeProblem(oldmeth: MemberInfo, newmeths: List[MemberInfo]) extends MemberProblem(oldmeth) {
+ def description = {
+ oldmeth.methodString + (if (newmeths.tail.isEmpty)
+ "'s type has changed; was " + oldmeth.tpe + ", is now: " + newmeths.head.tpe
+ else
+ " does not have a correspondent with same parameter signature among " +
+ (newmeths map (_.tpe) mkString ", "))
+ }
+}
+
+case class IncompatibleResultTypeProblem(oldmeth: MemberInfo, newmeth: MemberInfo) extends MemberProblem(oldmeth) {
+ def description = {
+ oldmeth.methodString + " has now a different result type; was: " +
+ oldmeth.tpe.resultType + ", is now: " + newmeth.tpe.resultType
+ }
+}
+
+case class AbstractMethodProblem(newmeth: MemberInfo) extends MemberProblem(newmeth) {
+ status = Problem.Status.Upgradable
+ def description = "abstract " + newmeth.methodString + " does not have a correspondent in " + affectedVersion + " version"
+}
+
+case class IncompatibleTemplateDefProblem(oldclazz: ClassInfo, newclazz: ClassInfo) extends TemplateProblem(oldclazz) {
+ def description = {
+ "declaration of " + oldclazz.description + " has changed to " + newclazz.description +
+ " in new version; changing " + oldclazz.declarationPrefix + " to " + newclazz.declarationPrefix + " breaks client code"
+ }
+}
+
+case class MissingTypesProblem(newclazz: ClassInfo, missing: Iterable[ClassInfo]) extends TemplateProblem(newclazz) {
+ def description = "the type hierarchy of " + newclazz.description + " has changed in new version. " +
+ "Missing types " + missing.map(_.fullName).mkString("{", ",", "}")
+}
+
+case class CyclicTypeReferenceProblem(clz: ClassInfo) extends TemplateProblem(clz) {
+ def description = {
+ "the type hierarchy of " + clz.description + " has changed in new version. Type " + clz.name + " appears to be a subtype of itself"
+ }
+}
+
+case class InaccessibleFieldProblem(newfld: MemberInfo) extends MemberProblem(newfld) {
+ def description = newfld.fieldString + " was public; is inaccessible in " + affectedVersion + " version"
+}
+
+case class InaccessibleMethodProblem(newmeth: MemberInfo) extends MemberProblem(newmeth) {
+ def description = newmeth.methodString + " was public; is inaccessible in " + affectedVersion + " version"
+}
+
+case class InaccessibleClassProblem(newclazz: ClassInfo) extends TemplateProblem(newclazz) {
+ def description = newclazz.classString + " was public; is inaccessible in " + affectedVersion + " version"
+}
View
2  src/main/scala/ssol/tools/mima/Reference.scala → ...c/main/scala/ssol/tools/mima/core/Reference.scala
@@ -1,4 +1,4 @@
-package ssol.tools.mima
+package ssol.tools.mima.core
case class Reference(clazz: ClassInfo, name: String, tpe: String)
View
2  src/main/scala/ssol/tools/mima/Settings.scala → ...rc/main/scala/ssol/tools/mima/core/Settings.scala
@@ -4,7 +4,7 @@
*/
// $Id: Settings.scala 12480 2007-08-06 17:39:10Z spoon $
-package ssol.tools.mima
+package ssol.tools.mima.core
import scala.tools.nsc
View
49 src/main/scala/ssol/tools/mima/Type.scala → core/src/main/scala/ssol/tools/mima/core/Type.scala
@@ -1,4 +1,4 @@
-package ssol.tools.mima
+package ssol.tools.mima.core
object Type {
@@ -22,56 +22,31 @@ object Type {
'D' -> doubleType,
'Z' -> booleanType,
'V' -> unitType)
-
- def fromSig(sig: String): Type = {
-
- var in = 0
-
- def getType(): Type = {
- val ch = sig(in)
- in += 1
- abbrevToValueType get ch match {
- case Some(tp) =>
- tp
- case None =>
- if (ch == '[') {
- ArrayType(getType())
- } else if (ch == 'L') {
- val end = sig indexOf (';', in)
- val fullname = sig.substring(in, end) replace ('/', '.')
- in = end + 1
- ClassType(ClassInfo.fromName(fullname))
- } else if (ch == '(') {
- val params = getParamTypes()
- in += 1
- MethodType(params, getType())
- } else {
- throw new MatchError("unknown signature: "+sig.substring(in))
- }
- }
- }
-
- def getParamTypes(): List[Type] =
- if (sig(in) == ')') List()
- else getType() :: getParamTypes()
-
- getType()
- }
}
abstract class Type {
def elemType: Type = throw new UnsupportedOperationException
def resultType: Type = throw new UnsupportedOperationException
+ def isSubtypeOf(that: Type): Boolean = throw new UnsupportedOperationException
}
case class ValueType(name: String) extends Type {
override def toString = name
+ override def isSubtypeOf(that: Type) = this == that
}
-case class ClassType(clazz: ClassInfo) extends Type {
+case class ClassType(private val clazz: ClassInfo) extends Type {
override def toString = ClassInfo.formatClassName(clazz.fullName)
+
+ override def isSubtypeOf(that: Type) = that match {
+ case ClassType(thatClazz) =>
+ if(thatClazz.isTrait) clazz.allTraits.exists(_.fullName == thatClazz.fullName)
+ else clazz.superClasses.exists(_.fullName == thatClazz.fullName)
+ case _ => false
+ }
}
case class ArrayType(override val elemType: Type) extends Type {
override def toString = "Array["+elemType+"]"
+ override def isSubtypeOf(that: Type) = this == that
}
case class MethodType(paramTypes: List[Type], override val resultType: Type) extends Type {
override def toString = paramTypes.mkString("(", ",", ")"+resultType)
View
2  src/main/scala/ssol/tools/mima/UTF8Codec.scala → ...c/main/scala/ssol/tools/mima/core/UTF8Codec.scala
@@ -8,7 +8,7 @@
// $Id: UTF8Codec.scala 11100 2007-05-21 08:32:16Z michelou $
-package ssol.tools.mima
+package ssol.tools.mima.core
/** This object provides methods for encoding/decoding UTF-8 characters.
*
View
4 core/src/main/scala/ssol/tools/mima/core/WithAccessFlags.scala
@@ -0,0 +1,4 @@
+package ssol.tools.mima.core
+
+trait WithAccessFlags extends WithAccessModifier
+ with WithLocalModifier with HasAccessFlags
View
31 core/src/main/scala/ssol/tools/mima/core/WithAccessModifier.scala
@@ -0,0 +1,31 @@
+package ssol.tools.mima.core
+
+trait WithAccessModifier extends HasAccessFlags {
+
+ def isPublic: Boolean = {
+ ensureLoaded()
+ ClassfileParser.isPublic(flags)
+ }
+
+ protected def isProtected: Boolean = {
+ ensureLoaded()
+ ClassfileParser.isProtected(flags)
+ }
+
+ protected def isPrivate: Boolean = {
+ ensureLoaded()
+ ClassfileParser.isPrivate(flags)
+ }
+
+ def isLessVisibleThan(that: WithAccessModifier) = {
+ (!isPublic && that.isPublic) || (isPrivate && that.isProtected)
+ }
+
+ protected def ensureLoaded() {}
+
+ def accessModifier = {
+ if(isProtected) "protected"
+ else if(isPrivate) "private"
+ else ""
+ }
+}
View
11 core/src/main/scala/ssol/tools/mima/core/WithLocalModifier.scala
@@ -0,0 +1,11 @@
+package ssol.tools.mima.core
+
+trait WithLocalModifier extends HasAccessFlags {
+ def isConcrete: Boolean = !isDeferred
+
+ def isDeferred: Boolean = ClassfileParser.isDeferred(flags)
+
+ def isFinal: Boolean = ClassfileParser.isFinal(flags)
+
+ def nonFinal: Boolean = !isFinal
+}
View
18 core/src/main/scala/ssol/tools/mima/core/ui/Centered.scala
@@ -0,0 +1,18 @@
+package ssol.tools.mima.core.ui
+
+import scala.swing.UIElement
+import scala.swing.Swing._
+
+import java.awt.Toolkit
+import java.awt.Dimension
+
+trait Centered { self: UIElement =>
+ def center = {
+ val tk = Toolkit.getDefaultToolkit
+ val screenSize = tk.getScreenSize
+ val screenHeight = screenSize.height
+ val screenWidth = screenSize.width
+ ((screenWidth - preferredSize.width) / 2,
+ (screenHeight - preferredSize.height) / 2)
+ }
+}
View
69 core/src/main/scala/ssol/tools/mima/core/ui/MimaFrame.scala
@@ -0,0 +1,69 @@
+package ssol.tools.mima.core.ui
+
+import scala.swing._
+import Swing._
+import ssol.tools.mima.core.ui._
+import ssol.tools.mima.core.ui.wizard._
+import ssol.tools.mima.core.Config
+import ssol.tools.mima.core.ui.page._
+import ssol.tools.mima.core.ui.event.Exit
+import ssol.tools.mima.core.util.Version
+
+import scala.tools.nsc.{ util, io }
+import util._
+import ClassPath._
+
+abstract class MimaFrame extends MainFrame with Centered {
+ import ssol.tools.mima.core.util.Urls._
+ object ScalaLogo extends widget.LinkImagePanel(ScalaWebsite, images.Icons.scalaLogo)
+
+ object TypesafeLogo extends widget.LinkImagePanel(TypesafeWebsite, images.Icons.typesafe)
+
+ title = "Migration Manager - " + Version.version
+ preferredSize = (1024, 768)
+ minimumSize = preferredSize
+ location = center
+ resizable = false
+
+
+ protected val mainContainer = new BorderPanel {
+ border = EmptyBorder(10)
+
+ private val topPanel = new BorderPanel {
+ add(ScalaLogo, BorderPanel.Position.West)
+ add(TypesafeLogo, BorderPanel.Position.East)
+ }
+ add(topPanel, BorderPanel.Position.North)
+
+ def setContent(c: Component): Unit = {
+ c.border = EmptyBorder(10, 0, 0, 0)
+ add(c, BorderPanel.Position.Center)
+ revalidate()
+ repaint()
+ }
+ }
+
+
+ menuBar = MimaMenuBar
+
+ contents = mainContainer
+
+ listenTo(menuBar)
+
+ reactions += {
+ case Exit =>
+ Dialog.showConfirmation(parent = null,
+ icon = images.Icons.exit,
+ title = "Exit MiMa",
+ message = "Are you sure you want to quit?") match {
+ case Dialog.Result.Ok => exit(0)
+ case _ => ()
+ }
+ }
+
+ protected def startWizard(wizard: Wizard) {
+ listenTo(wizard)
+ wizard.start()
+ mainContainer.setContent(wizard)
+ }
+}
View
51 core/src/main/scala/ssol/tools/mima/core/ui/MimaMenuBar.scala
@@ -0,0 +1,51 @@
+package ssol.tools.mima.core.ui
+
+import scala.swing._
+import scala.swing.event._
+
+import java.net.URI
+
+import ssol.tools.mima.core.ui.event.Exit
+import ssol.tools.mima.core.util.Browse
+
+object MimaMenuBar extends MenuBar {
+ import ssol.tools.mima.core.util.Urls._
+ // File menu
+ val file = new Menu("File") {
+ mnemonic = Key.F
+ }
+
+ contents += file
+
+ val exit = new MenuItem(new Action("Exit") {
+ def apply() = publish(Exit)
+ }) {
+ mnemonic = Key.E
+ }
+
+ file.contents += exit
+
+
+ // File menu
+ val help = new Menu("Help") {
+ mnemonic = Key.H
+ }
+
+ contents += help
+
+ val guide = new MenuItem(new Action("Online resources") {
+ def apply() = Browse to OnlineResource
+ }) {
+ mnemonic = Key.T
+ }
+
+ val bug = new MenuItem(new Action("Report a bug...") {
+ def apply() = Browse to BugReporting
+ }) {
+ mnemonic = Key.R
+ }
+
+ help.contents += (guide, bug)
+
+
+}
View
24 core/src/main/scala/ssol/tools/mima/core/ui/MimaSwingApp.scala
@@ -0,0 +1,24 @@
+package ssol.tools.mima.core.ui
+
+import javax.swing.UIManager
+import java.io.File
+
+import scala.swing._
+import Swing._
+import ssol.tools.mima.core.Config
+import ssol.tools.mima.core.util.WithEventQueueProxy
+
+trait MimaSwingApp extends SimpleSwingApplication with WithEventQueueProxy {
+
+ var resargs: List[String] = Nil
+
+ override def startup(args: Array[String]) {
+ resargs = Config.setup("scala " + launcherClassName +" <old-dir> <new-dir>", args, "-fixall")
+ super.startup(args)
+ }
+
+ protected def launcherClassName: String
+
+
+ override def top: Frame
+}
View
33 core/src/main/scala/ssol/tools/mima/core/ui/WithConstraints.scala
@@ -0,0 +1,33 @@
+package ssol.tools.mima.core.ui
+
+import scala.swing._
+import Swing._
+import java.awt.Color
+
+import javax.swing._
+import GridBagPanel._
+import java.awt.GridBagConstraints._
+
+trait WithConstraints extends GridBagPanel {
+ /** Convenience method for creating and adding components to a GridBagPanel.
+ * It has reasonable defaults for all parameters.
+ */
+ def withConstraints[T](gridx: Int = RELATIVE,
+ gridy: Int = RELATIVE,
+ gridwidth: Int = 1,
+ gridheight: Int = 1,
+ weightx: Double = 0.0,
+ weighty: Double = 0.0,
+ anchor: Anchor.Value = Anchor.NorthWest,
+ fill: Fill.Value = Fill.None,
+ insets: Insets = new Insets(0, 0, 0, 0),
+ ipadx: Int = 0,
+ ipady: Int = 0)(op: Constraints => T) = {
+ val c = new Constraints(gridx, gridy,
+ gridwidth, gridheight,
+ weightx, weighty,
+ anchor.id, fill.id, insets,
+ ipadx, ipady)
+ op(c)
+ }
+}
View
5 core/src/main/scala/ssol/tools/mima/core/ui/event/Exit.scala
@@ -0,0 +1,5 @@
+package ssol.tools.mima.core.ui.event
+
+import scala.swing.event.Event
+
+object Exit extends Event
View
46 core/src/main/scala/ssol/tools/mima/core/ui/model/ReportTableModel.scala
@@ -0,0 +1,46 @@
+package ssol.tools.mima.core.ui.model
+
+import ssol.tools.mima.core.Problem
+import javax.swing.table.AbstractTableModel
+
+object ReportTableModel {
+ private val ProblemDataColumn = 3
+
+ def apply(problems: List[Problem]) =
+ new ReportTableModel(problems.toArray.map(toArray(_)))
+
+ private def toArray(problem: Problem): Array[AnyRef] =
+ Array(problem.status, problem.referredMember, problem.description, problem)
+}
+
+class ReportTableModel(problems: Array[Array[AnyRef]]) extends AbstractTableModel {
+ private val columns = Array("Status", "Member", "Description")
+ private val columnsType = Array(classOf[Problem.Status.Value], classOf[String], classOf[String])
+
+ def hasUnfixableProblems = problems.exists(_(0) == Problem.Status.Unfixable)
+
+ def countUnfixableProblems = problems.count(_(0) == Problem.Status.Unfixable)
+
+ def countUpgradableProblems = problems.count(_(0) == Problem.Status.Upgradable)
+
+ override def getColumnName(n: Int) = columns(n)
+ def getColumnNames = columns.toList
+ def getColumnIndex(name: String) = (0 until columns.size).find(getColumnName(_).toLowerCase == name)
+
+ override def getColumnCount = columns.size
+ override def getRowCount = problems.size
+ override def getValueAt(x: Int, y: Int): AnyRef = problems(x)(y)
+
+ def getProblem(row: Int) = getValueAt(row, ReportTableModel.ProblemDataColumn).asInstanceOf[Problem]
+
+ override def isCellEditable(i: Int, j: Int) = false
+
+ override def getColumnClass(col: Int) = columnsType(col)
+
+ override def setValueAt(value: AnyRef, row: Int, col: Int): Unit = {
+ assert(isCellEditable(row, col))
+
+ problems(row)(col) = value
+ fireTableCellUpdated(row, col)
+ }
+}
View
63 core/src/main/scala/ssol/tools/mima/core/ui/page/ConfigurationPanel.scala
@@ -0,0 +1,63 @@
+package ssol.tools.mima.core.ui.page
+
+import java.io.File
+
+import scala.swing._
+import ssol.tools.mima.core.Config
+
+import Swing._
+import GridBagPanel._
+
+import ssol.tools.mima.core.ui.widget.{FilePicker, ClassPathEditor, FileSelected}
+import ssol.tools.mima.core.ui.WithConstraints
+
+/**
+ * A Panel used to configure MiMa. It allows jar file selection
+ * and setting up the classpath.
+ */
+class ConfigurationPanel(f1: Option[File] = None, f2: Option[File] = None) extends GridBagPanel with WithConstraints {
+
+ private val oldFilePicker = new FilePicker("Old:", this, f1)
+ private val newFilePicker = new FilePicker("New:", this, f2)
+
+ def oldFile = oldFilePicker.selectedFile.get
+ def newFile = newFilePicker.selectedFile.get
+
+ def areFilesSelected: Boolean = oldFilePicker.selectedFile.isDefined && newFilePicker.selectedFile.isDefined
+
+ listenTo(oldFilePicker)
+ listenTo(newFilePicker)
+
+ reactions += {
+ case FileSelected(_,_) =>
+ if(areFilesSelected) publish(FilesSelected(oldFile, newFile))
+ }
+
+ val ins = new Insets(0, 0, 10, 0)
+
+ import java.awt.Color
+ val files = new GridPanel(3, 1) {
+ border = LineBorder(Color.lightGray)
+ contents += new Label("Select the two libraries' versions you would like to compare") {
+ border = EmptyBorder(0, 5, 0, 0)
+ horizontalAlignment = Alignment.Left
+ }
+ contents += oldFilePicker
+ contents += newFilePicker
+ }
+
+
+ withConstraints(gridx = 0, gridy = 0, weightx = 1, fill = Fill.Both, anchor = Anchor.PageEnd, insets = ins) {
+ add(files, _)
+ }
+
+ val cpEditor = new ClassPathEditor(Nil) {
+ classpathLabel.text = "Library classpath:"
+ }
+
+ withConstraints(gridx = 0, gridy = 1, weightx = 1, weighty = 1, fill = Fill.Both, anchor = Anchor.PageEnd) {
+ add(cpEditor, _)
+ }
+}
+
+case class FilesSelected(oldLib: File, newLib: File) extends event.Event
View
22 core/src/main/scala/ssol/tools/mima/core/ui/page/JavaEnvironmentPage.scala
@@ -0,0 +1,22 @@
+package ssol.tools.mima.core.ui.page
+
+import scala.swing._
+import Swing._
+
+import ssol.tools.mima.core.ui.widget.ClassPathEditor
+import ssol.tools.mima.core.ui.WithConstraints
+
+class JavaEnvironmentPage extends GridBagPanel with WithConstraints {
+
+
+ protected val cpEditor = new ClassPathEditor {
+ classpathLabel.text = "Make sure the correct Java environment is selected"
+ }
+
+ import GridBagPanel._
+ import java.awt.GridBagConstraints
+ i