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-tp5711516p5711700.html
Sent from the gradle-dev mailing list archive at Nabble.com.

Reply via email to