|
3 | 3 | import coursierapi.Repository; |
4 | 4 | import scalafix.internal.interfaces.ScalafixCoursier; |
5 | 5 | import scalafix.internal.interfaces.ScalafixInterfacesClassloader; |
| 6 | +import scalafix.internal.interfaces.ScalafixProperties; |
| 7 | +import static scalafix.internal.interfaces.ScalafixProperties.PROPERTIES_PATH; |
6 | 8 |
|
7 | 9 | import java.io.IOException; |
8 | 10 | import java.io.InputStream; |
@@ -136,59 +138,96 @@ static Scalafix fetchAndClassloadInstance(String requestedScalaVersion) throws S |
136 | 138 | */ |
137 | 139 | static Scalafix fetchAndClassloadInstance(String requestedScalaVersion, List<Repository> repositories) |
138 | 140 | throws ScalafixException { |
139 | | - |
140 | | - String requestedScalaMajorMinorOrMajorVersion = |
141 | | - requestedScalaVersion.replaceAll("^(\\d+\\.\\d+).*", "$1"); |
142 | | - |
143 | | - String scalaVersionKey; |
144 | | - if (requestedScalaMajorMinorOrMajorVersion.equals("2.12")) { |
145 | | - scalaVersionKey = "scala212"; |
146 | | - } else if (requestedScalaMajorMinorOrMajorVersion.equals("2.13") || |
147 | | - requestedScalaMajorMinorOrMajorVersion.equals("2")) { |
148 | | - scalaVersionKey = "scala213"; |
149 | | - } else if (requestedScalaMajorMinorOrMajorVersion.equals("3.0") || |
150 | | - requestedScalaMajorMinorOrMajorVersion.equals("3.1") || |
151 | | - requestedScalaMajorMinorOrMajorVersion.equals("3.2") || |
152 | | - requestedScalaMajorMinorOrMajorVersion.equals("3.3")) { |
153 | | - scalaVersionKey = "scala33"; |
154 | | - } else if (requestedScalaMajorMinorOrMajorVersion.equals("3.5")) { |
155 | | - scalaVersionKey = "scala35"; |
156 | | - } else if (requestedScalaMajorMinorOrMajorVersion.equals("3.6")) { |
157 | | - scalaVersionKey = "scala36"; |
158 | | - } else if (requestedScalaMajorMinorOrMajorVersion.startsWith("3")) { |
159 | | - scalaVersionKey = "scala3Next"; |
160 | | - } else { |
161 | | - throw new IllegalArgumentException("Unsupported scala version " + requestedScalaVersion); |
162 | | - } |
163 | | - |
164 | | - Properties properties = new Properties(); |
165 | | - String propertiesPath = "scalafix-interfaces.properties"; |
166 | 141 | try { |
167 | | - InputStream stream = Scalafix.class.getClassLoader().getResourceAsStream(propertiesPath); |
| 142 | + Properties properties = new Properties(); |
| 143 | + InputStream stream = Scalafix.class.getClassLoader().getResourceAsStream(PROPERTIES_PATH); |
168 | 144 | properties.load(stream); |
| 145 | + |
| 146 | + ScalafixProperties scalafixProperties = new ScalafixProperties(properties); |
| 147 | + String scalafixVersion = scalafixProperties.scalafixVersion(); |
| 148 | + String scalaVersion = scalafixProperties.fullScalaVersion(requestedScalaVersion); |
| 149 | + |
| 150 | + List<URL> jars = ScalafixCoursier.scalafixCliJars(repositories, scalafixVersion, scalaVersion); |
| 151 | + ClassLoader parent = new ScalafixInterfacesClassloader(Scalafix.class.getClassLoader()); |
| 152 | + return classloadInstance(new URLClassLoader(jars.stream().toArray(URL[]::new), parent)); |
169 | 153 | } catch (Exception e) { |
170 | 154 | System.err.println( |
171 | | - "Failed to load '" + propertiesPath + "' from local artifact, " + |
| 155 | + "Failed to load '" + PROPERTIES_PATH + "' from local artifact, " + |
172 | 156 | "falling back to fetching the latest scalafix version..."); |
173 | 157 |
|
| 158 | + String latestVersion; |
174 | 159 | try { |
175 | | - List<URL> jars = ScalafixCoursier.latestScalafixPropertiesJars(repositories); |
176 | | - URLClassLoader classLoader = |
177 | | - new URLClassLoader(jars.stream().toArray(URL[]::new), null); |
178 | | - |
179 | | - InputStream stream = classLoader.getResourceAsStream(propertiesPath); |
180 | | - properties.load(stream); |
| 160 | + latestVersion = ScalafixCoursier.latestScalafixProperties(repositories); |
181 | 161 | } catch (Exception ee) { |
182 | | - throw new ScalafixException( |
183 | | - "Failed to load '" + propertiesPath + "' from local & remote artifacts", |
184 | | - ee); |
185 | | - } |
| 162 | + throw new ScalafixException( "Failed to lookup latest scalafix version", ee); |
| 163 | + } |
| 164 | + return fetchAndClassloadInstance(latestVersion, requestedScalaVersion, repositories); |
| 165 | + } |
| 166 | + } |
| 167 | + |
| 168 | + /** |
| 169 | + * Fetch JARs containing an implementation of {@link Scalafix} using Coursier and classload an instance of it via |
| 170 | + * runtime reflection. |
| 171 | + * <p> |
| 172 | + * The custom classloader optionally provided with {@link ScalafixArguments#withToolClasspath} to compile and |
| 173 | + * classload external rules must have the classloader of the returned instance as ancestor to share a common |
| 174 | + * loaded instance of `scalafix-core`, and therefore have been compiled against the requested Scala version. |
| 175 | + * |
| 176 | + * @param scalafixVersion Fetch a specific, implementation of {@link Scalafix}. Must be binary-compatible. |
| 177 | + * @param requestedScalaVersion A full Scala version (i.e. "3.3.4") or a major.minor one (i.e. "3.3") to infer |
| 178 | + * the major.minor Scala version that should be available in the classloader of the |
| 179 | + * returned instance. To be able to run advanced semantic rules using the Scala |
| 180 | + * Presentation Compiler such as ExplicitResultTypes, this must be source-compatible |
| 181 | + * with the version that the target classpath is built with, as provided with |
| 182 | + * {@link ScalafixArguments#withScalaVersion}. |
| 183 | + * @return An implementation of the {@link Scalafix} interface. |
| 184 | + * @throws ScalafixException in case of errors during artifact resolution/fetching. |
| 185 | + */ |
| 186 | + static Scalafix fetchAndClassloadInstance(String scalafixVersion, String requestedScalaVersion ) |
| 187 | + throws ScalafixException { |
| 188 | + return fetchAndClassloadInstance(scalafixVersion, requestedScalaVersion, Repository.defaults()); |
| 189 | + } |
| 190 | + |
| 191 | + /** |
| 192 | + * Fetch JARs containing an implementation of {@link Scalafix} from the provided repositories using Coursier and |
| 193 | + * classload an instance of it via runtime reflection. |
| 194 | + * <p> |
| 195 | + * The custom classloader optionally provided with {@link ScalafixArguments#withToolClasspath} to compile and |
| 196 | + * classload external rules must have the classloader of the returned instance as ancestor to share a common |
| 197 | + * loaded instance of `scalafix-core`, and therefore have been compiled against the requested Scala version. |
| 198 | + * |
| 199 | + * @param scalafixVersion Fetch a specific, implementation of {@link Scalafix}. Must be binary-compatible. |
| 200 | + * @param requestedScalaVersion A full Scala version (i.e. "3.3.4") or a major.minor one (i.e. "3.3") to infer |
| 201 | + * the major.minor Scala version that should be available in the classloader of the |
| 202 | + * returned instance. To be able to run advanced semantic rules using the Scala |
| 203 | + * Presentation Compiler such as ExplicitResultTypes, this must be source-compatible |
| 204 | + * with the version that the target classpath is built with, as provided with |
| 205 | + * {@link ScalafixArguments#withScalaVersion}. |
| 206 | + * @param repositories Maven/Ivy repositories to fetch the JARs from. |
| 207 | + * @return An implementation of the {@link Scalafix} interface. |
| 208 | + * @throws ScalafixException in case of errors during artifact resolution/fetching. |
| 209 | + */ |
| 210 | + static Scalafix fetchAndClassloadInstance( |
| 211 | + String scalafixVersion, |
| 212 | + String requestedScalaVersion, |
| 213 | + List<Repository> repositories |
| 214 | + ) throws ScalafixException { |
| 215 | + Properties properties = new Properties(); |
| 216 | + try { |
| 217 | + List<URL> jars = ScalafixCoursier.scalafixPropertiesJars(repositories, scalafixVersion); |
| 218 | + URLClassLoader classLoader = |
| 219 | + new URLClassLoader(jars.stream().toArray(URL[]::new), null); |
| 220 | + |
| 221 | + InputStream stream = classLoader.getResourceAsStream(PROPERTIES_PATH); |
| 222 | + properties.load(stream); |
| 223 | + } catch (Exception e) { |
| 224 | + throw new ScalafixException( |
| 225 | + "Failed to fetch '" + PROPERTIES_PATH + "' for scalafix version " + scalafixVersion, |
| 226 | + e); |
186 | 227 | } |
187 | 228 |
|
188 | | - String scalafixVersion = properties.getProperty("scalafixVersion"); |
189 | | - String scalaVersion = properties.getProperty(scalaVersionKey); |
190 | | - if (scalafixVersion == null || scalaVersion == null) |
191 | | - throw new ScalafixException("Failed to lookup versions from '" + propertiesPath + "'"); |
| 229 | + ScalafixProperties scalafixProperties = new ScalafixProperties(properties); |
| 230 | + String scalaVersion = scalafixProperties.fullScalaVersion(requestedScalaVersion); |
192 | 231 |
|
193 | 232 | List<URL> jars = ScalafixCoursier.scalafixCliJars(repositories, scalafixVersion, scalaVersion); |
194 | 233 | ClassLoader parent = new ScalafixInterfacesClassloader(Scalafix.class.getClassLoader()); |
|
0 commit comments