Giter Site home page Giter Site logo

Comments (7)

shyiko avatar shyiko commented on May 24, 2024 1

@nedtwigg The feeling is mutual 🤝

from ktlint.

shyiko avatar shyiko commented on May 24, 2024

Hi Ned,
That looks interesting!

I'm not entirely sure where would be the right place for this kind of class, though. Also without the callback user would have no way of knowing whether all violations have been corrected or some require manual intervention. That means that callback would have to stay, which in turn is going to make access through reflection awkward again.

One way to solve this would be to create a module with com.github.shyiko:ktlint "provided" (in Maven terminology) dependency that does no reflection at all and just acts as a bridge between spotless & ktlint. This module would obviously have to be part of the spotless project. What do you think?

On a different note, here is the code (using Reflection API) that works:

ClassLoader classLoader = ...

Class<?> ktlintClass = classLoader.loadClass("com.github.shyiko.ktlint.core.KtLint");
Object ktlint = ktlintClass.getDeclaredField("INSTANCE").get(null);

Class<?> standardRuleSetProviderClass = classLoader.loadClass("com.gihub.shyiko.ktlint.ruleset.standard.StandardRuleSetProvider");
Object standardRuleSet = standardRuleSetProviderClass.getMethod("get").invoke(standardRuleSetProviderClass.newInstance());
Iterable<?> ruleSets = Collections.singletonList(standardRuleSet);

Class<?> function2Interface = classLoader.loadClass("kotlin.jvm.functions.Function2");
Object formatterCallback = Proxy.newProxyInstance(classLoader, new Class[]{function2Interface},
    (proxy, method, args) -> null);

Method formatterMethod = ktlintClass.getMethod("format", String.class, Iterable.class, function2Interface);

String input = "fun main() { x(1,3);  x(1, 3)       }";
String output = (String) formatterMethod.invoke(ktlint, input, ruleSets, formatterCallback);

from ktlint.

nedtwigg avatar nedtwigg commented on May 24, 2024

Spotless has an _ext folder for hosting shim modules, so that could be done. I don't yet have the Kotlin skill to build and maintain the shim, but I'd be happy to take a PR. Spotless has zero dependencies - it calls all its formatting libraries using reflection, but caches the classloaders to get the full JIT performance.

My immediate need is for Spotless, but I expect that other users of your formatting library would appreciate an easier entry point as well. In my eyes, the simplest interface for a formatter is a Function<String, String> that throws an exception if it can't generate an adequate return value. The easier it is for users to generate such a construct from your library, the easier it is to consume your library to meet a variety of usecases.

In the reflection code you pasted above, how does it handle "violations that require manual intervention"? Does it throw a descriptive exception? If not, is it possible to modify the pasted code so that it would throw a descriptive exception?

from ktlint.

shyiko avatar shyiko commented on May 24, 2024

You don't need Kotlin to make a shim. A little bit of Java will do:

try {
    output = KtLint.INSTANCE.format(input, Arrays.asList(new StandardRuleSetProvider().get()), (lintError, corrected) -> {
        if (!corrected) {
            throw new RuntimeException(lintError.getDetail());
        }
        return null;
    });
} catch (RuleExecutionException e) {
    System.err.println(e.getLine() + ":" + e.getCol() + " " + e.getMessage() + " (" + e.getRuleId() + ")");
}

In the reflection code you pasted above, how does it handle "violations that require manual intervention"?

It doesn't. But it's easy to correct:

Class<?> lintErrorClass = classLoader.loadClass("com.github.shyiko.ktlint.core.LintError");
Method detailGetter = lintErrorClass.getMethod("getDetail");
Object formatterCallback = Proxy.newProxyInstance(classLoader, new Class[]{function2Interface},
    (proxy, method, args) -> {
        Object lintError = args[0]; // com.github.shyiko.ktlint.core.LintError
        boolean corrected = (Boolean) args[1];
        if (!corrected) {
            String detail = (String) detailGetter.invoke(lintError);
            throw new RuntimeException(detail);
        }
        return null;
    });

...

try {
    output = (String) formatterMethod.invoke(ktlint, input, ruleSets, formatterCallback);
} catch (Exception e) {
   // InvocationTargetException -> RuleExecutionException (see prev code snippet)
}

from ktlint.

nedtwigg avatar nedtwigg commented on May 24, 2024

Awesome, thanks! That got it working. Next question: can you point me to an example kotlin file that should throw an error? I'd like to add a test which asserts that errors are being thrown properly, and that their messages are as expected.

I think we're almost ready to merge ktlint into spotless :)

from ktlint.

shyiko avatar shyiko commented on May 24, 2024

Sure. This is an example of the rule that cannot be fixed automatically and this is the one that can (there are bunch of other examples here). Let me know if you need anything else.

from ktlint.

nedtwigg avatar nedtwigg commented on May 24, 2024

Great, thanks! I think we're about ready to merge diffplug/spotless#71! Hopefully we'll be able to drive more users your way once it ships.

from ktlint.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.