Mark Drew (Redux)- cf_etc...

a compendium of railo, cfml, cfeclipse and technology topics

Mark Drew (Redux)- cf_etc...

Why CFC insight is difficult

February 20, 2008 · 11 Comments

One of the most requested features in CFEclipse is to have insight into CFC's to have method completion. I thought I would detail some of the problems that are involved in this task from an editor. I am putting this together so that when people ask me why not, I can point them to this, and of course, if they come up with some good answers, they can post them here! 1) What CFC are we calling? The simplest way to call a CFC is to do the following: <cfinvoke component="uk.co.markdrew.MyCompnent" returnvariable="myComp"> Now, at runtime, ColdFusion would figure out where "uk.co.markdrew.MyComponent" is located, this could be either by doing mappings in ColdFusion or in fact, by VirtualDirectories in Apache/IIS. This is pretty hard in CFEclipse unless we add a "uk/co/markdrew/MyCompnent.cfc in your project. If you had a separate directory, lets say you keep your components in /Project/components/uk/co/markdrew/MyComponent.cfc", it would be hard. Not impossible, since we can add linked folders and a feature I have been working on is to be able to mark a folder as a mapping, but pretty hard for all the different cases and layouts that people will have 2) A CFC location from a variable Since you can pass variables to tags, you could pass the CFC as a variable, for example: <cfinvoke component="#APPLICATION.MyComponent#" returnvariable="myComp"> In this case, and similar cases, it would be VERY hard to find out what myComp actually is! If the "APPLICATION.MyComponent" is set in Application.cfc for example or anywhere else (in the many different ways of setting an application variable, that I am not even going to go into here!) it would be impossible to find out what myComp is. 3) What is the returned object? The above code is probably something you wont do a lot, but how about something like: <cfinvoke component="uk.co.markdrew.MyCompnent" method="getObject" returnvariable="myComp"> And the function is defined as: <cffunction name="getObject" returntype="Any">
   <!--- Losts of complicated ways of getting an object, like looking it up in a database --->
   <cfreturn someObject>
</cffunction>
How would the editor know what the object, and thus what funtions it had, is? This is very much like what happens in ColdSpring so unless we write CFEclipse so it actually does everything a CF server does (and even then, that is dangerous at runtime!) it wont be able to know what is happening! So, how would you get round these problems? (put aside that its in Eclipse, try writing a parser in CF that just reads text files and let me know how you get on!)

Tags: cfeclipse · coldfusion

11 responses so far ↓

  • 1 Tom Chiverton // Sep 22, 2008 at 4:14 PM

    Assuming the code is all runable, is it totally unfeasable for CFE to write a small CFML template that runs the code, fire of a HTTP request and then examine the CFDUMP outout or something ?
    I suppose then you are trying to automatically figure out how to invoke line 4 in a particular template - again easy in the simple cases, quite hard in most of the real world examples. Bah.

    Tom, not now delating this incase someone else is thinking the same thing.
  • 2 Mark Drew // Sep 22, 2008 at 4:14 PM

    @Tom: I dont think running any code on the server should be part of editing something to be honest. Even looking stuff up through RDS I find kinda iffy. Other languages manage it through other means in the editors.

    Besides, its only in CF8 that you can get Metadata without actually running the constructor.
  • 3 Craig Hyatt // Sep 22, 2008 at 4:14 PM

    What about some sort of coldfusion process that runs periodically and produces a metafile with insight information for cfeclipse to use?

    This process could be a cfadministrator plugin (or not).

    Still would require running code on the server, but perhaps this is more palatable.
  • 4 Mark Drew // Sep 22, 2008 at 4:14 PM

    I dont like the idea of something running on the server, since this could introduce security vulnerabilities.

    Another part is that a CFC could run a database query (for logging) or affect other things when run, so you dont want it happening from the editor.
  • 5 phill.nacelli // Sep 22, 2008 at 4:14 PM

    Mark,

    First of all, thanks for considering such an option. Just curious if there's anything about the way that Aptana does for the js insight that could be done within CFEclipse for CFC insight. Here's what I'm talking about: http://www.aptana.tv/movies/aptana_code_assist_profiles/CodeAssistProfiles.html

    Once again, thank you!

    Cheers...
  • 6 Joel // Sep 22, 2008 at 4:14 PM

    I can completely see the problem.

    The only thing I can think of is by storing a metabase within eclipse of possible types. You could then associate a particular CFC File with a particular variable in memory, or xml or sommit.

    alternatively; This could be stored in a cute comment in a set such as

    &lt;!--- &lt;variable name=&quot;objMyWidget&quot; assertedType=&quot;widgets.com.bob&quot;/&gt; ---&gt;

    This would be helpful to the author of the file as it would suggest that the object was of that type.

    It wouldn't be ideal but it could be functional.

    You could also scan all the cfcs and store them tokenised backwards and compare the types/names to aid identification by the developer

    - Joel
  • 7 Mark Drew // Sep 22, 2008 at 4:14 PM

    @Joel: I went through a period of thinking about adding extra attributes to cffunciton calls but now I am against that, as the editor should not define the way you code.

    It would just take another developer using HomeSite or Dreamweaver to come and want to fix all the &quot;strange crazy attributes&quot; you put in there to ruin the plan eh?
  • 8 Sammy Larbi // Sep 22, 2008 at 4:14 PM

    Could you ignore the hard cases that would require context and give insight to the ones in the same project, and then add ones with mappings?

    It would still require looking at which templates are calling the functions, and seeing who incorporates those to getting to an original createObject call.

    If it is ambiguous, you could give all the option. For example, in IntelliJ IDEA's Ruby plugin, if it doesn't know, it just lists all the functions, and narrows down as you type - it's still a nice help for programming faster and if you're not sure of the method name.

    Also, if you do that, after the first time they use it from one object, you could possibly assume that same type for another (or if still ambiguous, again, list those that it matches).

    Most of my projects aren't reusing ton's of CFCs from outside other projects, so even if you just looked at CFCs defined within the project, it would be a tremendous help.

    And as you mention, if you could let us tell you a file to look at as an &quot;import&quot; then you could treat that as a member of the project too.

    That would cover a ton of cases, just not the variable ones.
  • 9 Danilo Celic // Sep 22, 2008 at 4:14 PM

    Mark,

    I believe that Dreamweaver pings the server and uses the cfc browser (or something similarly named) and then parses the response (it's not terribly fast, and it should probably handle caching of objects better). It then uses that info to populate the Components panel with all of the available CFCs, and their available methods and the arguments for those methods. Offhand I think that this would be the CFCs on the testing server, but may be those available on the live server. Because of this, I think that it takes into account the CF server mappings, as well as the virtual directories from the web server itself. However, with CF8 and the application specific mappings, I doubt that it would be able to handle such an issue.

    I've created a Dreamweaver extension for personal use that replicates the Components panel and adds the ability to get code hints for created CFCs. It can even handle a case where you have a dynamically created CFC ( the component=&quot;#APPLICATION.MyComponent#&quot; case) by allowing you to set code hitns for a specific component. But if you want to work with multiple objects, then the code hinting would get a bit confusing as all the methods of each set CFC would be mixed together, there wouldn't be a way to set the context of the code hints (at least I'm not aware of a way to do that).

    It does not handle methods and properties of returned objects (unless they are CFCs themselves and you manually add the code hints for that CFC using the exposed functionality I added), as that's an extra level of complexity that you discuss here.

    Anyway, this is a difficult issue to try to work with. I like the idea of setting up the &quot;mappings&quot; with your project so that the paths can be resolved appropriately and then you can parse the cfc(s) that you find (cached of course, with available refresh button/command).

    Thanks for all your efforts.
  • 10 Tero Pikala // Sep 22, 2008 at 4:14 PM

    At first look that Aptana approach seems like a something that could work?

    I would still consider calling server to to parse CFCs and get more information about them with getMetaData(). I think it would be only an issue if there is some code outside &lt;cffunction&gt; tags which should be relatively easy to recognize? Anyway I think most people who are using CFCs properly always add init() into CFC and never use that funny implied constructor.

    As long as components aren't inspected all the time I would be happy to accept performance penalty from this.

    If something comes out of this I would really like to see it support development model where code is in workspace/project and every change is copied to web directory with Ant script... Might even buy you a beer next time :)


    Tero
  • 11 Adam Haskell // Sep 22, 2008 at 4:14 PM

    @Tero

    http://cfrant.blogspot.com/2008/02/build-for-eclipse.html

    @Mark

    Aptana's approach might be a good idea. cfEclipse could also allow a user to define where their local ColdFusion engine is and then it could read the config file to get mappings etc.Parsing Application.cfc should fill out the rest of the mapping information. This method might get tricky when you introduce different CF engines but it should be doable, this defining of the cfm engine location would also allow for an automatic builder like the above ANT script. I would say hacking off the variable paths support initially (or indefinitely) would be an okay move, but I wouldn't generally be affect by that so others may disagree.

Leave a Comment