I have verified that it is possible to inject a custom model builder
(although highly inconvenient). While experimenting with this, I have
learned that custom models must be interfaces. Is there any technical
reason for that? If not, I would like this restriction to be removed
because it is quite inconvenient. That is, I don't need (in this case) any
kind of compatibilty and even if I did, I would rather use a serialization
proxy with immutable classes.

Also, is there any chance to make it easier to inject custom model builders
(without hacking with the init script)? So that I don't need to play around
with classpaths as well.


2013/8/13 Kelemen Attila <attila.keleme...@gmail.com>

> I can see that you are adamant about not giving access to `Project`.
> Anyway, I have realized that I already have access to the `Project`
> instance via init scripts *evil smile*. So, I can inject a custom model
> builder there.
>
> You say that "We don't want Netbeans, Eclipse, IDEA and my-custom-tool all
> deciding to use a different way of mapping to the simplified view".
> However, I have a different internal model representation, so I have to map
> things anyway. The only question is from what model do I do this
> conversion: DSL or a model created from the DSL. So, the created model
> (`IdeaProject`) does not make my life easier the slightest. Quite the
> contrary, I have to undo a lot of things, so your mapping efforts went in
> vain. This is because in NetBeans, I need something very close to the DSL
> without further mapping. For example, `SourceSet.getCompileClasspath()`
> would be a lot better than to have access to configurations like "compile"
> (which is unreliable to depend on). Actually, knowing "compile" instead of
> the actual classpath is a lot of pain to me because I have to do some
> dependency resolution myself (to make matters worse, I don't even have all
> the info), something which Gradle can already do itself.
>
> All in all, I believe that accessing models instead of the DSL doesn't
> make anything easier. It certainly is no easier for me. I believe that
> "re-implementing the same stuff in different ways" assumes that I need to
> same thing as other IDEs which is not the case. As I see, models only
> structure the information in a certain way but I'm pretty sure that
> different IDEs need to structure things in a different way. So why is it
> assumed, that choosing a particular structure of the information (other
> than the DSL) will help all the IDEs? That is, if I were to implement a
> model for "JavaProject", I would implement something benefical to NetBeans
> because I have to choose a structure and why should I choose something
> else? Also, I don't agree with your example of Android projects: They are
> not Java projects and should (and do) have a different model anyway. That
> is, if a build script does not apply the "java" plugin (implicitly or
> explicitly) then it is not a Java project, therefore needs a different
> model.
>
>
> 2013/8/13 Adam Murdoch [via Gradle] <
> ml-node+s1045684n5711697...@n5.nabble.com>
>
>
>> On 02/08/2013, at 9:34 AM, kelemen <[hidden 
>> email]<http://user/SendEmail.jtp?type=node&node=5711697&i=0>>
>> wrote:
>>
>> 2013/8/1 Adam Murdoch [via Gradle] <<a
>> href="x-msg://1801/user/SendEmail.jtp?type=node&amp;node=5711582&amp;i=0"
>> target="_top" rel="nofollow" link="external">[hidden email]>
>>
>>>
>>> On 30/07/2013, at 6:52 PM, kelemen <[hidden 
>>> email]<http://user/SendEmail.jtp?type=node&node=5711581&i=0>>
>>> wrote:
>>>
>>> 2013/7/30 Adam Murdoch [via Gradle] <<a href="<a
>>> href="x-msg://4953/user/SendEmail.jtp?type=node&amp;amp;node=5711554&amp;amp;i=0">x-msg://4953/user/SendEmail.jtp?type=node&amp;node=5711554&amp;i=0"
>>> target="_top" rel="nofollow" link="external">[hidden email]>
>>>
>>>
>>>> On 29/07/2013, at 4:25 PM, Alex Ruiz <[hidden 
>>>> email]<http://user/SendEmail.jtp?type=node&node=5711550&i=0>>
>>>> wrote:
>>>>
>>>> Thanks, Adam. I've been looking into (and debugging) how the current
>>>> API for retrieving models work, to have a better understanding on how the
>>>> API and implementation of this new action would look like.
>>>>
>>>> Attila: This approach may also benefit your work on Netbeans. Please
>>>> take a look.
>>>>
>>>> This is what I have in mind, based on what I have done this weekend:
>>>>
>>>> - The action interface can be simple, and so far this is what I think
>>>> about its API:
>>>>
>>>>   public interface ConsumerAction<T> extends Serializable {
>>>>     T execute(Project project);
>>>>   }
>>>>
>>>>    where Project is a org.gradle.api.Project. My understanding is that
>>>> by having a Project we can do everything we need  (through
>>>> Project#getService()).
>>>>
>>>>
>>>> The action should accept something other than `org.gradle.api.Project`,
>>>> for a few reasons:
>>>>
>>>> 1. `org.gradle.api.Project` is not version-independent. The entry point
>>>> for the action should be a function of the client's tooling API version,
>>>> not target Gradle version.
>>>> 2. Some actions don't need a configured project. For example, an action
>>>> may just be interested in the project hierarchy or the build environment.
>>>> Or it may not be interested in the tasks of a project, or the dependencies
>>>> of a project, or whatever. Instead, we need an interface that implies no
>>>> configuration is done, except for that which is explicitly requested by the
>>>> action.
>>>> 3. It's not going to work well with decoupled project mode (e.g.
>>>> parallel execution, configure on demand). This will become the default at
>>>> some point. The plan there is that there will be no way to navigate from
>>>> one project to another. Instead, we need an interface which provides access
>>>> to the whole build, but in a way that allows things like parallel
>>>> configuration and configuration on demand.
>>>> 4. There's no opportunity to cache models. We'd have to cache the whole
>>>> project model, which is unlikely to be possible any time soon.
>>>>
>>>>
>>> It would be very convenient to have access to `org.gradle.api.Project`
>>> regardless. Not being version independent is not necessarily a problem,
>>> since Gradle has to maintain compatibility due to the build scripts and
>>> this compatibility should be enough. Actually, I could provide a lot better
>>> experience in NB if this was possible. For example, I could easily display
>>> all the source root with proper classpaths including the usual "integTest"
>>> sources.
>>>
>>>
>>> The process of importing Gradle into an IDE has to involve some kind of
>>> mapping. The Gradle model is much richer that the IDEs and this model has
>>> to be converted into the simpler model of each IDE. This mapping is lossy
>>> and as such the mapping needs to be flexible, and the build author and the
>>> various plugins must be able to have some influence over it. The mapping
>>> shouldn't be hardcoded in the IDE. This is one of the reasons the tooling
>>> API exists.
>>>
>>> So, we have:
>>>
>>> Gradle model -> transformation -> IDE model
>>>
>>> It's a little more detailed than that:
>>>
>>> Gradle DSL -> transformation -> canonical model -> transformation -> IDE
>>> model
>>>
>>> That is, the user configures some stuff through the DSL, this is then
>>> converted to some internal model that various parts of Gradle use,
>>> including the IDE mapping. We keep the DSL backwards compatible, but we
>>> don't for the canonical model. We plan to, but we're not there yet.  In
>>> other words, the stuff you need from the project (i.e. the canonical model)
>>> is not backwards compatible at all.
>>>
>>> So, rather than access `Project` directly, I'd much prefer if you help
>>> us grow the tooling API models instead. It's easy to add stuff once you
>>> know the pattern.
>>>
>>> These models then form a contract, as they declare what you need from
>>> the model. We can keep this stable and make it faster over time. They also
>>> allow us to offer consistent behaviour across IDEs (which is important to
>>> us, possibly not so for you).
>>>
>>>
>> There might be some misundestanding between us, so I will try to clarify
>> my assumptions and see where it differs from yours:
>>
>> 1. The proposed `ConsumerAction` runs in the same process where the
>> project got evaluated, so I believe that the compatibility of the DSL is
>> sufficient. For example: I should be able to iterate over the sourcesets
>> because I can do so in the build script.
>>
>> 2. If projects are evaluated in multiple processes, then I'd prefer to
>> design an API which works even in this case but still runs foreign (i.e.,
>> foreign to Gradle) code in the process where the project got evaluated (in
>> multiple processes if necessary).
>>
>> 3. I assume that DSL compatibility implies that no methods or classes
>> will disappear from the http://www.gradle.org/docs/current/javadoc/. I
>> don't assume, that I can just implement interfaces (like `Project`).
>>
>> 4. I'm not sure what you mean by "canonical model". `Project` or
>> something else? If it is the `Project`, then I don't understand because the
>> build script can access it as well (see 3). If it is something else, then I
>> don't need that one.
>>
>>
>> Except that you do. There are multiple ways I can define, for example, a
>> Java project. For example, you can use the 'java' plugin, or the 'android'
>> plugin, or one of the new JVM language plugins or something entirely
>> custom. These are all different DSLs, but they are all translated to
>> produce a single DSL-independent model that describes things about how to
>> build the project, such as where the source is, the language level, the
>> compile dependencies and so on. This is the canonical model that the IDE
>> should be using as input. It should not be using the original DSL.
>>
>> The canonical model has to be further mapped in a lossy way to the
>> simpler view of the world that the IDEs have. It's not really the IDE's
>> business as to how this mapping should happen. It's the build's business.
>>
>> So, we have something like this:
>>
>> DSL 1 ----------+
>>                 |
>> DSL 2 ----------+--> canonical model --+--> simplified model --> IDE
>>                 |                      |
>> my custom DSL --+                      +--> other plugins
>>
>> It's the model that pops out the righthand side that the IDEs should be
>> using, not the models that go in at the lefthand side.
>>
>>  I just need the `Project` instance right after the buildscript set it
>> up. Of course, this limits the IDE integration (those using `Project`) in
>> some marginal use-cases. But there are already limitations, I don't think
>> an IDE integration should consider all extreme use cases. Build masters
>> should be sane enough to write build scripts so that the IDE understands
>> it. By the way, I already pass init scripts (optionally, opt-out) when
>> running tasks which means that I already access `Project`.
>>
>> 5. I don't understand what you mean on consistent behaviour.
>>
>>
>> The consistency is to do with how the mappings at each of the above
>> stages is done. We don't want Netbeans, Eclipse, IDEA and my-custom-tool
>> all deciding to use a different way of mapping to the simplified view.
>>
>>
>>  There are still models like `EclipseProject` and `IdeaProject`. How does
>> this help consistency? If you mean deprecating these models and adding
>> common models like `JavaProjectModel`, `GroovyProjectModel` and whatever
>> else, then this could mean an awful lot of models. Now, I may consider
>> adding models to Gradle myself (although I already spend lots of my free
>> time on coding other projects).
>>
>>
>> That would be great. Please give it a try. We'd very much welcome this.
>>
>>
>>  However, assume that I go mad adding lots models, which you find quality
>> enough to accept: Do you plan to support these models "forever" considering
>> backward (or worse, forward) compatibility without me?
>>
>>
>> Absolutely. That's the whole point. It's a collaboration. The models
>> describe what Netbeans needs to know about the build. We work together to
>> define this. And then, given this description, we can find the best ways to
>> provide that information, and that is free to change over time.
>>
>> This is only really a problem from our point of view if there's lots of
>> stuff that Netbeans needs to know that doesn't make sense for other IDEs to
>> know, but I don't think that's the case.
>>
>> To me, it's about putting the knowledge in a certain place based on where
>> it belongs, not based on who does the work. The mappings belong in the
>> build, but that doesn't mean that a Gradle core developer needs to
>> implement it.
>>
>>
>>  You see, even though it could be my true intent to support them for you,
>> I might die tomorrow. This is something you must consider. That is,
>> Gradleware cannot truly rely on external contributons for these models.
>>
>> 6. Let's be rational: I mean no offense but considering the past, you
>> spend a small portion of your resources for making models better. I believe
>> that it is not rational to believe that the percentage of resources you can
>> and will spend on adding new features to the model will be increased in the
>> future. To be honest, I think you shouldn't change your current priorities
>> too much because other things are very important as well.
>>
>>
>> It's a good point. We hope to do better at this, and reaching out to the
>> community is part of this. There are some improvements ready to be included
>> in the 1.8 release, and we want this to continue. Let's see how we go.
>>
>>
>>
>> So, given these, I wish to avoid Gradleware spending more resources on
>> maintaining compatibility for the new models. I want you to push these
>> maintaining work to IDE integration developers (like me).
>>
>>
>> Right, that's exactly the idea. But that's not not an argument for
>> accessing Project and each tool integrator re-implementing the same stuff
>> in different ways. To me, it's an argument for sharing work via the models.
>>
>>
>>  But you cannot do so by asking me to add new models (see 5) myself. If
>> you want me to create models without pushing these models to the Gradle
>> repo, then I don't see what is the gain. I still need to build that model
>> somehow from `Project`.
>>
>> What is the gain from accessing the `Project` through the Tooling API (as
>> proposed by Alex and me)? In this case, I'm relieved from the burden of
>> maintaining a backward (or forward) compatible model. Even if I screw up in
>> a version, I can simply fix this in a patch and release a new version of
>> the NB plugin independently of Gradle. Speaking of which, independent
>> release from Gradle allows me to consider users needs and react to these
>> needs on my own schedule. Also, different IDEs might have considerable
>> different view of the world and I'm also pretty sure that users of
>> different IDEs have different expectations on how things should be done
>> (there is a reason for why they choose one IDE over another).
>>
>> Saying all these, I'd prefer if developers of Idea and Eclipse
>> integration would voice their opinion. Also, I believe you should wait for
>> their opinion. That is, IDE integration developers are the main users of
>> this API (at least, I believe this is where these new changes matter most).
>>
>>
>>>
>>>
>>> Caching can be done external to Gradle. Actually, I already cache
>>> models. Also, there is no way to know in general if reevaluation of a
>>> project is necessary, so I believe that Gradle cannot do considerably
>>> better than an external process.
>>>
>>>
>>> There's an awful lot to track when checking for changes in the model.
>>> Here are some examples:
>>>
>>> - Changes in the build script and in one of the ancestor's build scripts.
>>> - Changes in the settings scripts.
>>> - Changes in the init scripts passed as command-line args, or in
>>> ~/.gradle/init.gradle or ~/.gradle/init.d
>>> - Changes in any local or remote scripts applied by any of the above or
>>> any init scripts bundled in the distributions.
>>> - Changes in gradle.properties and ~/.gradle/gradle.properties.
>>> - Changes to the Gradle version in gradle-wrapper.properties.
>>> - Changes in the source or dependencies of buildSrc
>>> - Changes in the classpath used at configuration time, eg local jars.
>>> - Changes to dependencies in the remote repositories.
>>> - Changes in the configuration files or remote resources that my custom
>>> plugin uses to configure the build.
>>>
>>> You get the idea. It think good change detection has to be a
>>> collaboration between Gradle and the IDE.
>>>
>>>
>>>
>> Knowing on what the build script depends is impossible. It can be a
>> content of a directory or other things (an absurd example would be
>> System.nanoTime % 2). Although it might be reasonable to expect the user
>> not to depend on anything he or she whishes. However, I have never seen
>> serious need for this automatic change detection. People seem to be content
>> with manual reloading. Also, it might be even harmful to reload a model
>> just because a build script or something else changes because the
>> background work (what Gradle does) might interfere with the user (reading
>> from the harddrive might slow down things) and actually, users don't really
>> need the new model for every small changes. Like adding a println to a file
>> in buildSrc is really not something to worry about.
>>
>> Although in the past I thought similar to you, I now believe that this
>> kind of caching is not something the users need. Caching which benefits the
>> user is something different and it is important that the user may refresh
>> at will (ignoring caching). I still need to implement persistent cache but
>> I believe that this is not something you should spend effort on. At least
>> not without explicitly polling the users need. But even if it turns that
>> this is something important, allowing access to `Project` shouldn't cause a
>> problem. Only that you won't cache `Project` instances, so anyone relying
>> it won't automatically benefit from your caching. The implementor (and its
>> users) then might choose if this is something worth losing the benefits of
>> being able to access `Project`.
>>
>>
>>
>> ------------------------------
>> View this message in context: Re: Proposal for retrieving multiple types
>> of models from a project in a single pass, using the Tooling 
>> API<http://gradle.1045684.n5.nabble.com/Proposal-for-retrieving-multiple-types-of-models-from-a-project-in-a-single-pass-using-the-Tooling-AI-tp5711516p5711582.html>
>> Sent from the gradle-dev mailing list 
>> archive<http://gradle.1045684.n5.nabble.com/gradle-dev-f1436218.html>at
>> Nabble.com.
>>
>>
>>
>> --
>> Adam Murdoch
>> Gradle Co-founder
>> http://www.gradle.org
>> VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
>> http://www.gradleware.com
>>
>>
>>
>>
>>
>> ------------------------------
>>  If you reply to this email, your message will be added to the
>> discussion below:
>>
>> http://gradle.1045684.n5.nabble.com/Proposal-for-retrieving-multiple-types-of-models-from-a-project-in-a-single-pass-using-the-Tooling-AI-tp5711516p5711697.html
>>  To unsubscribe from Proposal for retrieving multiple types of models
>> from a project in a single pass, using the Tooling API, click 
>> here<http://gradle.1045684.n5.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=5711516&code=YXR0aWxhLmtlbGVtZW44NUBnbWFpbC5jb218NTcxMTUxNnwtMTMxMjM2NTcwMA==>
>> .
>> NAML<http://gradle.1045684.n5.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>>
>
>




--
View this message in context: 
http://gradle.1045684.n5.nabble.com/Proposal-for-retrieving-multiple-types-of-models-from-a-project-in-a-single-pass-using-the-Tooling-AI-tp5711516p5711708.html
Sent from the gradle-dev mailing list archive at Nabble.com.

Reply via email to