Hi All,
Given that the previous thread had moved way off topic, I started this one.
After thinking about it a bit, considering Matthew's, Colomban's and Thomas's comments and looking at other systems I came to the understanding documented below. Frank probably already knew all this, but I have saved him writing lots of English. If its right and you think its worth using in the newsletter or anywhere else feel free to copy it.
Background ---------------
Starting at first principles, the purpose of version checking with plugins is:
1. to ensure the version of the plugin is likely to work as intended with the version of Geany, and
2. to increase convenience by not requiring plugin re-compilation every time Geany changes.
Note that item two is a convenience for developers but is an essential for users of packaged releases, otherwise no plugins would work between release of a packaged version of Geany and release of new packaged versions of the plugins.
In more detail this requires that:
1. Geany provides at least the functions that the plugin requires, and
2. those functions continue to work the same, that is the plugin doesn't need any changes, including re-compilation
Different stakeholders also have different needs and views of the process:
1. Plugin developers need to know the exact point that Geany provides the functions that the plugin needs, they can't wait for releases and they are always re-compiling.
2. Plugin packagers need to know which Geany is required for the plugin(s) they are packaging so they can set dependencies, but their view is only of the Geany package version number.
3. Users want to be able to upgrade Geany from their package repo and still have installed plugins work if its safe for them to do so.
The Geany plugin interface version system provides a reasonable match to these requirements providing some rules are met.
How it works ----------------
The Geany plugin interface is characterised by two numbers:
1. the API number which represents the set of functionality that Geany provides.
2. the ABI number that ensures that the plugin is compilation compatible, ie compilation is not required
Functionality can be carefully appended to the interface (changing the API number) without changing how existing plugins use the interface (ie the ABI number).
Removals, inserts or changes of semantics require that the ABI be changed.
Having a single ABI number that represents the whole interface may require that a plugin be re-compiled even if the parts of the interface it uses havn't changed. This is a trade off between simplicity, reduction in human error and the flexibility of the interface.
These numbers have no relationship to release numbers, but each release has a specific API/ABI pair.
The system does not handle cross platform issues (Linux/Windows/Mac? or 32/64 bit) assuming that package systems will address this and users of non-packaged systems will likely re-compile anyway.
How to Use it -----------------
A plugin must have been compiled with a version of Geany with the same ABI as the one it is being loaded into. This ensures that nothing has been removed, no semantics have changed and none of the low level bit patterns have changed.
Geany must also supply at least the functions the plugin needs, so the API must be greater than that needed by the plugin.
These two checks are done by the PLUGIN_VERSION_CHECK macro.
The check is performed at runtime, but a plugin compiled against a version of Geany that is too old will still fail at compile time because of missing declarations.
Plugins that wish to use newer features but still support older versions can only make the decision at compile time because the API number of the Geany that the plugin is being loaded into isn't available at runtime. Making the API number available at runtime may be a potential enhancement of the interface and allow plugins to support a wider range of versions.
The API and ABI number pair should be published (in release notes?) when a release is made for use by plugin packagers.
Binary packagers of plugins should use the published API/ABI to define the versions of Geany required to be the intersection of the two sets of releases:
1. releases where the API number is greater than or equal to the greatest API required by a plugin in the package.
2. releases where the ABI number matches the ABI number of the Geany version the package is compiled with.
If these rules are complied with, users who use packages and users who compile can just let the system do its stuff. Developers *should* also find it just works (tm).
Developers of bindings to the Geany plugin interface should specify which API number they support (ie which features have been bound).
Implications ---------------
Because the ABI must match exactly, every effort must be made to limit changes that affect the ABI. Otherwise as soon as a new Geany is released all plugins stop working until re-compiled, and new packages are released, and installed by users. This is bad :-(
This means that:
1. the interface should be as small as possible so that the least possible changes impact the ABI.
2. structures should not be visible in the interface, instead they should be hidden behind getter/setter functions, and
3. interface wrapper functions should be used to hide the implementation and side effects.
The last two have not been Geany policy to date but I now propose that they be.
Feel free to throw bricks (or bouquets).
Cheers Lex
On Wed, 17 Aug 2011 15:37:15 +1000 Lex Trotman elextr@gmail.com wrote:
- structures should not be visible in the interface, instead they
should be hidden behind getter/setter functions, and
- interface wrapper functions should be used to hide the
implementation and side effects.
The last two have not been Geany policy to date but I now propose that they be.
I guess this will change the way plugin developers currently working with the API. Give that this will stabilize the ABI even more I would second this. Can you go a bit more into detail what would need to be changed here?
Cheers, Frank
On 08/16/2011 10:37 PM, Lex Trotman wrote:
Hi All,
Given that the previous thread had moved way off topic, I started this one.
After thinking about it a bit, considering Matthew's, Colomban's and Thomas's comments and looking at other systems I came to the understanding documented below. Frank probably already knew all this, but I have saved him writing lots of English. If its right and you think its worth using in the newsletter or anywhere else feel free to copy it.
Great information, this should most certainly go into the Wiki (as well as any other useful places).
A plugin must have been compiled with a version of Geany with the same ABI as the one it is being loaded into. This ensures that nothing has been removed, no semantics have changed and none of the low level bit patterns have changed.
Geany must also supply at least the functions the plugin needs, so the API must be greater than that needed by the plugin.
These two checks are done by the PLUGIN_VERSION_CHECK macro.
Actually, I think usually the checks end up being done by GModule/dlopen since they try to load the plugin and bail-out when they get undefined symbol errors. Only after that is when the PLUGIN_VERSION_CHECK macro would have a chance to do it's checks. I could be completely wrong on this, but I think it's what I've observed.
Plugins that wish to use newer features but still support older versions can only make the decision at compile time because the API number of the Geany that the plugin is being loaded into isn't available at runtime. Making the API number available at runtime may be a potential enhancement of the interface and allow plugins to support a wider range of versions.
Wouldn't run-time be too late anyway, since the undefined functions didn't have a chance to get pre-processed out according the version?
Like:
void some_func(void) { if (geany_check_api_version(189)) undefined_function_here(); /* dlopen error */ }
The API and ABI number pair should be published (in release notes?) when a release is made for use by plugin packagers.
+1 ... Franks list on the Wiki is an great start!
IMO, it's quite useful/important that each function/member's doc-comments be annotated with the API version number as well, as has been discussed. This would let developers reading the API docs know *exactly* which API version they should check against to use a certain thing, even between releases.
This means that:
- the interface should be as small as possible so that the least
possible changes impact the ABI.
- structures should not be visible in the interface, instead they
should be hidden behind getter/setter functions, and
++1 ... This would be great.
Most importantly (I think) is that you could do whatever you want with the struct members without breaking API/ABI compatibility and such, since they would be opaque.
- interface wrapper functions should be used to hide the
implementation and side effects.
+1
The last two have not been Geany policy to date but I now propose that they be.
I agree wholeheartedly.
A bit O/T, but it would also be great to get rid of the need for those pesky globals `geany_plugin`, `geany_data`, and `geany_functions` required to defined/included in each TU of the plugin. At least for the first two, they could (one already is) be just passed into the plugin's entry-point (plugin_init()). As for `geany_functions`, I'm not sure, since all those weird macros in `geanyfunctions.h` require it.
Cheers, Matthew Brush
On Wed, 17 Aug 2011 11:34:11 -0700 Matthew Brush mbrush@codebrainz.ca wrote:
+1 ... Franks list on the Wiki is an great start!
Thx ;)
IMO, it's quite useful/important that each function/member's doc-comments be annotated with the API version number as well, as has been discussed. This would let developers reading the API docs know *exactly* which API version they should check against to use a certain thing, even between releases.
I disagree on the between releases point. Plugin developers are asked to develop against latest stable release of Geany. If they need something more recent, they know what they are doing.
My suggestion is to add this information with next API extensions. If somebody likes to dig into source history and check, which API version which API call is needed, I'm also fine with ;)
Cheers, Frank
On 08/17/2011 12:26 PM, Frank Lanitz wrote:
On Wed, 17 Aug 2011 11:34:11 -0700 Matthew Brushmbrush@codebrainz.ca wrote:
IMO, it's quite useful/important that each function/member's doc-comments be annotated with the API version number as well, as has been discussed. This would let developers reading the API docs know *exactly* which API version they should check against to use a certain thing, even between releases.
I disagree on the between releases point. Plugin developers are asked to develop against latest stable release of Geany. If they need something more recent, they know what they are doing.
I never heard this advice before, but I guess it's good advice. Though I still think from a user's point of view, the wider range of Geany versions supported by a plugin, the better.
My suggestion is to add this information with next API extensions. If somebody likes to dig into source history and check, which API version which API call is needed, I'm also fine with ;)
Agreed, going forward, it would be nice to document new extensions, but actually digging out this information after the fact is way too much work.
Cheers, Matthew Brush
On Wed, 17 Aug 2011 12:38:49 -0700 Matthew Brush mbrush@codebrainz.ca wrote:
On 08/17/2011 12:26 PM, Frank Lanitz wrote:
On Wed, 17 Aug 2011 11:34:11 -0700 Matthew Brushmbrush@codebrainz.ca wrote:
IMO, it's quite useful/important that each function/member's doc-comments be annotated with the API version number as well, as has been discussed. This would let developers reading the API docs know *exactly* which API version they should check against to use a certain thing, even between releases.
I disagree on the between releases point. Plugin developers are asked to develop against latest stable release of Geany. If they need something more recent, they know what they are doing.
I never heard this advice before, but I guess it's good advice. Though I still think from a user's point of view, the wider range of Geany versions supported by a plugin, the better.
I agree at this point. The only way currently is to use older API calls. Most of the new functions do already have a since entry, e.g. since 0.16. If you chose 0.19 and below it will work for 0.19 and 0.20. Burt as of the ABI change you will need to recompile it. Reasons for this have been discussed elsewhere.
Cheers, Frank
On 18 August 2011 04:34, Matthew Brush mbrush@codebrainz.ca wrote:
On 08/16/2011 10:37 PM, Lex Trotman wrote:
Hi All,
Given that the previous thread had moved way off topic, I started this one.
After thinking about it a bit, considering Matthew's, Colomban's and Thomas's comments and looking at other systems I came to the understanding documented below. Frank probably already knew all this, but I have saved him writing lots of English. If its right and you think its worth using in the newsletter or anywhere else feel free to copy it.
Great information, this should most certainly go into the Wiki (as well as any other useful places).
Oh yeah the wiki, I forgot about that :-)
@Enrico, When will it be declared online, ie prominently pointed to from the website?
[...]
Actually, I think usually the checks end up being done by GModule/dlopen since they try to load the plugin and bail-out when they get undefined symbol errors. Only after that is when the PLUGIN_VERSION_CHECK macro would have a chance to do it's checks. I could be completely wrong on this, but I think it's what I've observed.
You are correct that the sentence above should say "done at runtime by"...
And my next sentence is only partly correct, you may get compile time errors, unfortunately it is not guaranteed. See below for why.
Plugins that wish to use newer features but still support older versions can only make the decision at compile time because the API number of the Geany that the plugin is being loaded into isn't available at runtime. Making the API number available at runtime may be a potential enhancement of the interface and allow plugins to support a wider range of versions.
Wouldn't run-time be too late anyway, since the undefined functions didn't have a chance to get pre-processed out according the version?
Like:
void some_func(void) { if (geany_check_api_version(189)) undefined_function_here(); /* dlopen error */ }
You may be using functions that are not in the API? I see some more detail is needed, the way I understand it is meant to work is:
geanyplugin.h includes geanyfunctions.h which defines a macro for each function in the interface, thus hiding the actual function. Those macros map the function name to a call via a pointer member of the geanyfunctions structure. Since structure members are not checked by dlopen this means it should not check for any Geany functions when opened. If it is telling you that there are undefined functions then you are using functions directly not via the geanyfunctions structure. It may also be possible that there are functions documented as being in the API that are not in geanyfunctions, but thats a bug (either undocument or add to geanyfunctions). The pointers in the geany functions structure have full prototypes so the compiler can check them.
To get the structure declarations, geanyplugin.h includes Geany headers, so functions that are not in the interface are unfortunately made visible to the compiler. This is why the insistence on only using the things documented (and so in geanyfunctions), even if others are visible. This can't be fixed until we remove access to structures eg using getter/setter functions instead, and so remove the requirement for the Geany headers.
This means that your plugin must be compiled against a version of Geany that has the functions you use in the interface, so the compiler can resolve the structure offsets. But so long as it is ABI compatible it can be loaded into any version of Geany with at least your *minimum* API, which you set to not include those functions that you can avoid using, based on the runtime version of the API. If only you could get the runtime version of the API.
The API and ABI number pair should be published (in release notes?) when a release is made for use by plugin packagers.
+1 ... Franks list on the Wiki is an great start!
agree.
IMO, it's quite useful/important that each function/member's doc-comments be annotated with the API version number as well, as has been discussed. This would let developers reading the API docs know *exactly* which API version they should check against to use a certain thing, even between releases.
I agree, I find that the "since" info in things like GTK is invaluable, and I swear at any entries without it.
This means that:
- the interface should be as small as possible so that the least
possible changes impact the ABI.
- structures should not be visible in the interface, instead they
should be hidden behind getter/setter functions, and
++1 ... This would be great.
Most importantly (I think) is that you could do whatever you want with the struct members without breaking API/ABI compatibility and such, since they would be opaque.
Yep, my argument exactly, in fact members could even go away so long as the getter could calculate the value and the setter could change whatever was needed to get the same effect.
- interface wrapper functions should be used to hide the
implementation and side effects.
+1
The last two have not been Geany policy to date but I now propose that they be.
I agree wholeheartedly.
A bit O/T, but it would also be great to get rid of the need for those pesky globals `geany_plugin`, `geany_data`, and `geany_functions` required to defined/included in each TU of the plugin. At least for the first two, they could (one already is) be just passed into the plugin's entry-point (plugin_init()). As for `geany_functions`, I'm not sure, since all those weird macros in `geanyfunctions.h` require it.
See above for geanyfunctions, all these names are needed for the various re-direction macros to work. It is a bit of a fragile part of the interface, but it is compile time detected.
But perhaps they could be wrapped in a PLUGIN_DECLARE macro or similar.
Cheers Lex
On 08/17/2011 07:01 PM, Lex Trotman wrote:
On 18 August 2011 04:34, Matthew Brushmbrush@codebrainz.ca wrote:
[...]
You may be using functions that are not in the API? I see some more detail is needed, the way I understand it is meant to work is:
geanyplugin.h includes geanyfunctions.h which defines a macro for each function in the interface, thus hiding the actual function. Those macros map the function name to a call via a pointer member of the geanyfunctions structure. Since structure members are not checked by dlopen this means it should not check for any Geany functions when opened. If it is telling you that there are undefined functions then you are using functions directly not via the geanyfunctions structure. It may also be possible that there are functions documented as being in the API that are not in geanyfunctions, but thats a bug (either undocument or add to geanyfunctions). The pointers in the geany functions structure have full prototypes so the compiler can check them.
To get the structure declarations, geanyplugin.h includes Geany headers, so functions that are not in the interface are unfortunately made visible to the compiler. This is why the insistence on only using the things documented (and so in geanyfunctions), even if others are visible. This can't be fixed until we remove access to structures eg using getter/setter functions instead, and so remove the requirement for the Geany headers.
This means that your plugin must be compiled against a version of Geany that has the functions you use in the interface, so the compiler can resolve the structure offsets. But so long as it is ABI compatible it can be loaded into any version of Geany with at least your *minimum* API, which you set to not include those functions that you can avoid using, based on the runtime version of the API. If only you could get the runtime version of the API.
That was *extremely* useful information, you should put that on the Wiki too :)
IMO, it's quite useful/important that each function/member's doc-comments be annotated with the API version number as well, as has been discussed. This would let developers reading the API docs know *exactly* which API version they should check against to use a certain thing, even between releases.
I agree, I find that the "since" info in things like GTK is invaluable, and I swear at any entries without it.
For sure, and it's super easy to do, since changes are usually done bit by bit, it's literally an extra 30 seconds of time to add this information in the doc-comment.
But perhaps they could be wrapped in a PLUGIN_DECLARE macro or similar.
Would that just insert the prototypes for all the functions right into the source file where that macro is?
Cheers, Matthew Brush
[...]
That was *extremely* useful information, you should put that on the Wiki too :)
Sure if no one says its wrong.
For sure, and it's super easy to do, since changes are usually done bit by bit, it's literally an extra 30 seconds of time to add this information in the doc-comment.
But a bit of a pain to go back and do the existing ones, unless we decide to make them all since some arbitary API number and then do it right after that.
But perhaps they could be wrapped in a PLUGIN_DECLARE macro or similar.
Would that just insert the prototypes for all the functions right into the source file where that macro is?
The idea was only to declare the three pointers with the correct names (which need to be in the plugin namespace with the right names for the macros to work). I would agree that passing them might be nicer but then its harder to ensure they have the name that makes the macros work and they have to be passed to all functions in the plugin by the same name. Thats too error prone, this approach may not be nice, but its easier.
Cheers Lex
On 08/17/2011 08:56 PM, Lex Trotman wrote:
[...]
That was *extremely* useful information, you should put that on the Wiki too :)
Sure if no one says its wrong.
Only thing left out is how there's a separate struct for each set of function types, like `DocumentFuncs`, and `SciFuncs`, and so on, which are themselves members of a the `GeanyFunctions` struct. Just to add a little more detail.
For sure, and it's super easy to do, since changes are usually done bit by bit, it's literally an extra 30 seconds of time to add this information in the doc-comment.
But a bit of a pain to go back and do the existing ones, unless we decide to make them all since some arbitary API number and then do it right after that.
Agreed, something like:
/* * Does stuff with bar * @param bar A bar to perform foo on. * @return A new baz * * @since 0.21 (<= API v212) */ baz_t *foo(bar_t *bar);
I'm suggesting this assuming that I could write a little Python script to remove 90% of the manual labour from actually going through the sources and doing the annotations, otherwise I retract my previous statements :)
Cheers, Matthew Brush
[...]
Only thing left out is how there's a separate struct for each set of function types, like `DocumentFuncs`, and `SciFuncs`, and so on, which are themselves members of a the `GeanyFunctions` struct. Just to add a little more detail.
Like all the best text books say, discovering this and explaining why is left as an exercise for the reader :-) [...]
Cheers Lex
On Wed, 17 Aug 2011 22:16:00 -0700 Matthew Brush mbrush@codebrainz.ca wrote:
On 08/17/2011 08:56 PM, Lex Trotman wrote:
[...]
That was *extremely* useful information, you should put that on the Wiki too :)
Sure if no one says its wrong.
Only thing left out is how there's a separate struct for each set of function types, like `DocumentFuncs`, and `SciFuncs`, and so on, which are themselves members of a the `GeanyFunctions` struct. Just to add a little more detail.
I'd suggest just start to put the things into wiki. Its much easier to check and correct something over there instead of discussion on mailing list without having some fixed version.
Cheers, Frank
On Wed, 17 Aug 2011 22:16:00 -0700 Matthew Brush mbrush@codebrainz.ca wrote:
Agreed, something like:
/* * Does stuff with bar * @param bar A bar to perform foo on. * @return A new baz * * @since 0.21 (<= API v212) */ baz_t *foo(bar_t *bar);
+1
Cheers, Frank
Le 18/08/2011 07:16, Matthew Brush a écrit :
On 08/17/2011 08:56 PM, Lex Trotman wrote:
[...]
But a bit of a pain to go back and do the existing ones, unless we decide to make them all since some arbitary API number and then do it right after that.
Agreed, something like:
/* * Does stuff with bar * @param bar A bar to perform foo on. * @return A new baz * * @since 0.21 (<= API v212) */ baz_t *foo(bar_t *bar);
I'm suggesting this assuming that I could write a little Python script to remove 90% of the manual labour from actually going through the sources and doing the annotations, otherwise I retract my previous statements :)
I don't think it's a good idea to use something like "<= to whatever". I think we either:
1) leave only the Geany version (not good) 2) add the API version of that release and be OK with the fact it may be a little to tight -- but huh, who cares? 3) add the exact one, but that's a bit of work -- though Git and a clever script might be able to do the search part for us.
I'd vote for 2, except if someone want to do 3 :-'
Cheers, Colomban
On Thu, 18 Aug 2011 12:01:09 +1000 Lex Trotman elextr@gmail.com wrote:
Oh yeah the wiki, I forgot about that :-)
@Enrico, When will it be declared online, ie prominently pointed to from the website?
There will be a note inside the next newsletter.
Cheers, Frank
Le 17/08/2011 07:37, Lex Trotman a écrit :
Hi All,
Given that the previous thread had moved way off topic, I started this one.
After thinking about it a bit, considering Matthew's, Colomban's and Thomas's comments and looking at other systems I came to the understanding documented below. Frank probably already knew all this, but I have saved him writing lots of English. If its right and you think its worth using in the newsletter or anywhere else feel free to copy it.
[...]
Great writing :)
available at runtime. Making the API number available at runtime may be a potential enhancement of the interface and allow plugins to support a wider range of versions.
Yeah, that may help too; and as you explained later in the discussion, it would work with the current design.
[...]
Because the ABI must match exactly, every effort must be made to limit changes that affect the ABI. Otherwise as soon as a new Geany is released all plugins stop working until re-compiled, and new packages are released, and installed by users. This is bad :-(
This means that:
- the interface should be as small as possible so that the least
possible changes impact the ABI.
- structures should not be visible in the interface, instead they
should be hidden behind getter/setter functions, and
Agreed
- interface wrapper functions should be used to hide the
implementation and side effects.
What do you mean by "interface wrapper functions"?
IMO Geany should use the exact same API than plugins to do one thing. This would avoid having a broken getter in the API (or whatever) that we don't notice just because the core doesn't use it.
The last two have not been Geany policy to date but I now propose that they be.
Agreed (at least for 2, not sure what 3 is).
Regards, Colomban
[...]
- interface wrapper functions should be used to hide the
implementation and side effects.
What do you mean by "interface wrapper functions"?
In a situation where Geany does something by calling a few local static functions or if it calls a few functions from different modules, don't put the static functions in the API or expect the plugins to call groups of functions, instead make a wrapper function that calls the correct sequence so the exact implementation is hidden and it only needs to be changed in one place.
IMO Geany should use the exact same API than plugins to do one thing.
Of course Geany should call the wrapper too. Basically its ok for Geany to do implementation stuff directly, but only if its in one place. As soon as it is in the API it isn't one place any more.
This would avoid having a broken getter in the API (or whatever) that we don't notice just because the core doesn't use it.
With the past non-proactive adding of things to the API there should not be too much in that category, but over time it may accumulate as we add more but don't remove stuff so we don't break the ABI.
Cheers Lex
PS probably be a week or so before I get time to put stuff in the wiki
On Fri, 19 Aug 2011 10:02:23 +1000 Lex Trotman elextr@gmail.com wrote:
IMO Geany should use the exact same API than plugins to do one thing.
Of course Geany should call the wrapper too. Basically its ok for Geany to do implementation stuff directly, but only if its in one place. As soon as it is in the API it isn't one place any more.
Depending on the part of Geany, its really already doing this. But surely a couple of places might be missing and useful to do it the same wa< there.
This would avoid having a broken getter in the API (or whatever) that we don't notice just because the core doesn't use it.
With the past non-proactive adding of things to the API there should not be too much in that category, but over time it may accumulate as we add more but don't remove stuff so we don't break the ABI.
Well, I don't think this is a reason for using the same functions in core, but a good one to use a test framework which is testing the API maybe as a post commit hook.
PS probably be a week or so before I get time to put stuff in the wiki
Looking forward to.
Cheers, Frank
Le 19/08/2011 08:40, Frank Lanitz a écrit :
On Fri, 19 Aug 2011 10:02:23 +1000 Lex Trotman elextr@gmail.com wrote:
[...]
This would avoid having a broken getter in the API (or whatever) that we don't notice just because the core doesn't use it.
With the past non-proactive adding of things to the API there should not be too much in that category, but over time it may accumulate as we add more but don't remove stuff so we don't break the ABI.
Well, I don't think this is a reason for using the same functions in core, but a good one to use a test framework which is testing the API maybe as a post commit hook.
Would be really good. Not sure how to do this however, we'd need to spawn Geany, load a test plugin… any idea?
I'm afraid we can't do a classic suite of unit tests since we don't have real "units" (maybe we should, but that's another problem...).
Cheers, Colomban
On Sat, 20 Aug 2011 17:18:24 +0200 Colomban Wendling lists.ban@herbesfolles.org wrote:
Le 19/08/2011 08:40, Frank Lanitz a écrit :
On Fri, 19 Aug 2011 10:02:23 +1000 Lex Trotman elextr@gmail.com wrote:
[...]
This would avoid having a broken getter in the API (or whatever) that we don't notice just because the core doesn't use it.
With the past non-proactive adding of things to the API there should not be too much in that category, but over time it may accumulate as we add more but don't remove stuff so we don't break the ABI.
Well, I don't think this is a reason for using the same functions in core, but a good one to use a test framework which is testing the API maybe as a post commit hook.
Would be really good. Not sure how to do this however, we'd need to spawn Geany, load a test plugin… any idea?
Unfortunately no. I put it on the help wanted for page on every talk I was doing for Geany but nobody was asking me to help ;)
I'm afraid we can't do a classic suite of unit tests since we don't have real "units" (maybe we should, but that's another problem...).
hmmmm...
Cheers, Frank
On 08/20/2011 08:18 AM, Colomban Wendling wrote:
Le 19/08/2011 08:40, Frank Lanitz a écrit :
Well, I don't think this is a reason for using the same functions in core, but a good one to use a test framework which is testing the API maybe as a post commit hook.
Would be really good. Not sure how to do this however, we'd need to spawn Geany, load a test plugin… any idea?
I'm afraid we can't do a classic suite of unit tests since we don't have real "units" (maybe we should, but that's another problem...).
This would become much easier with full-coverage API bindings. Vala or Python, for example, would be much more pleasant to write test suites in. Of course with proper bindings, we could also test the plugin API and bindings at the same time (ex. using commit hooks).
I would say have a regular "Test" plugin under `plugins/` which can be built/loaded which runs the full test suite, just run it before pushing a commit that touches the API. Otherwise, it would be possible to compile `WITH_TESTS` which could add a `--test` argument to the GOptions for the main program and then would branch off into some code that would load a special plugin to run some specific tests.
Cheers, Matthew Brush
Le 19/08/2011 02:02, Lex Trotman a écrit :
[...]
- interface wrapper functions should be used to hide the
implementation and side effects.
What do you mean by "interface wrapper functions"?
In a situation where Geany does something by calling a few local static functions or if it calls a few functions from different modules, don't put the static functions in the API or expect the plugins to call groups of functions, instead make a wrapper function that calls the correct sequence so the exact implementation is hidden and it only needs to be changed in one place.
OK, so of course I agree :)
Cheers, Colomban