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