www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Automatic code refactoring

reply Robert Fraser <fraserogfthenight gmail.com> writes:
This is probably jumping way ahead of myself here, but if (some day, in the far
future), Descent were to gain some automated D code refactoring support, what
would you like to see?

So far I've thought of/stolen from the JDT:
----------
- Renaming/moving a module (references to it will be updated)

- Changing a function or template signature (and updating references/inserting
default values where appropriate)

- Renaming a variable/function/template/etc and updating references.

- A "use supertype where possible", where references to a particular
implementation of an interface or class are updated to use the
supertype/interface where possible.

- Extract abstract class, where some (or all, you choose which ones) of the
fields/methods of a class are moved to a new abstract class, and the remainder
remain as implementations in the subtype.

- Extract interface: create an interface for some or all of the methods of a
class.

- Inline a function (either a single invocation of it or everywhere it's used).

- Expand a mixin/compile-time function/etc. to its actual value/code (again,
either in a single place or everywhere).

- Struct-to-class or class-to-struct (possibly, I'm not sure how hard this
would be to automate. The class-to-struct one, esp. if structs get
constructors, seems like it'd be a lot easier if no inheritance is used).

- Automatically import modules for symbols if the symbols can be resolved
somewhere in the project or attached libraries (and choose from a list if there
are multiple possibilities). This will remove the need to manually import
stuff. Either the entire module or a selective import can be used.
----------

Anyone have any other ideas or things they'd like to see? Descent doesn't even
have semantic analysis yet, so this is a mostly theoretical topic, but someday
your dreams may become a reality...
Aug 02 2007
next sibling parent BCS <ao pathlink.com> writes:
Reply to Robert,

 This is probably jumping way ahead of myself here, but if (some day,
 in the far future), Descent were to gain some automated D code
 refactoring support, what would you like to see?
 
 So far I've thought of/stolen from the JDT:
 ----------
 - Extract abstract class, where some (or all, you choose which ones)
 of the fields/methods of a class are moved to a new abstract class,
 and the remainder remain as implementations in the subtype.
I'd go the other way I would like this is convert a class to abstract, derive a cocreate class from it that acts as the original class does, replace all 'new's and derivations with this new class.
 
 - Extract interface: create an interface for some or all of the
 methods of a class.
 
extract interface from several classes (only ask about overlapping functions)
 ----------
 
 Anyone have any other ideas or things they'd like to see? Descent
 doesn't even have semantic analysis yet, so this is a mostly
 theoretical topic, but someday your dreams may become a reality...
 
convert "auto T = ..." to it's actual type --- generate a explicit specialization of a template from a general one template T(U) { U foo; } becomes, for int template T(U) { U foo; } template T(U : int) { int foo; } --- select methods from a class and build a mixin template for them with interface extraction this would allow extracting interface + functionality blocks interface I { int foo() } template I_impl() { int foo(){...} } ... class C : I { mixin I_impl!() }
Aug 02 2007
prev sibling next sibling parent janderson <askme me.com> writes:
Robert Fraser wrote:
 This is probably jumping way ahead of myself here, but if (some day, in the
far future), Descent were to gain some automated D code refactoring support,
what would you like to see?
 
 So far I've thought of/stolen from the JDT:
 ----------
 - Renaming/moving a module (references to it will be updated)
 
 - Changing a function or template signature (and updating references/inserting
default values where appropriate)
 
 - Renaming a variable/function/template/etc and updating references.
 
 - A "use supertype where possible", where references to a particular
implementation of an interface or class are updated to use the
supertype/interface where possible.
 
 - Extract abstract class, where some (or all, you choose which ones) of the
fields/methods of a class are moved to a new abstract class, and the remainder
remain as implementations in the subtype.
 
 - Extract interface: create an interface for some or all of the methods of a
class.
 
 - Inline a function (either a single invocation of it or everywhere it's used).
 
 - Expand a mixin/compile-time function/etc. to its actual value/code (again,
either in a single place or everywhere).
 
 - Struct-to-class or class-to-struct (possibly, I'm not sure how hard this
would be to automate. The class-to-struct one, esp. if structs get
constructors, seems like it'd be a lot easier if no inheritance is used).
 
 - Automatically import modules for symbols if the symbols can be resolved
somewhere in the project or attached libraries (and choose from a list if there
are multiple possibilities). This will remove the need to manually import
stuff. Either the entire module or a selective import can be used.
 ----------
 
 Anyone have any other ideas or things they'd like to see? Descent doesn't even
have semantic analysis yet, so this is a mostly theoretical topic, but someday
your dreams may become a reality...
Personally I'd like everything in UML. To beable to zoom into a UML node (kinda google maps on iphone) and modify your code then zoom out to see the big picture, that would be awsome. To be able to re-factor that way live would be neat. Anyways, that's really just a pipe-dream. -Joel
Aug 02 2007
prev sibling next sibling parent reply Ingo Oeser <ioe-news rameria.de> writes:
Robert Fraser wrote:

 This is probably jumping way ahead of myself here, but if (some day, in
 the far future), Descent were to gain some automated D code refactoring
 support, what would you like to see?
 
 So far I've thought of/stolen from the JDT:
 ----------
 - Renaming/moving a module (references to it will be updated)
Yes. Without any question, since this this just file movement at the moment :-) + Make all imports of module private. + Make all imports of all modules private. + Make all imports of a module static and fix up users.
 - Changing a function or template signature (and updating
 references/inserting default values where appropriate)
 
 - Renaming a variable/function/template/etc and updating references.
Highly desired. Please have a possibility to ask the user per case or not. The implementation is also very simple, if you use the D compiler frontend already. Rationale: Sometimes you rename sth. to forcibly find all its users, when you have to break the semantic of sth. (e.g. badly designed, non extensible core interfaces) in a big project. Supporting this kind of workflow would be great.
 - Inline a function (either a single invocation of it or everywhere it's
 used).
Let the compiler do that. Always! Everything else just asks for long function bodies, if junior programmers try to "optimise" code.
 - Expand a mixin/compile-time function/etc. to its actual value/code
 (again, either in a single place or everywhere).
Very useful for readability! Undo would be important here :-)
 - Struct-to-class or class-to-struct (possibly, I'm not sure how hard this
 would be to automate. The class-to-struct one, esp. if structs get
 constructors, seems like it'd be a lot easier if no inheritance is used).
Maybe more useful and easier to implement would be: + Extract class members to private struct, build accessors to it into class and fix up all users. Struct to class might be nearly impossible, because structs have properties, which classes don't have (e.g. defined member order, can be stored and retrieved, can be shared with C/C++ etc.).
 - Automatically import modules for symbols if the symbols can be resolved
 somewhere in the project or attached libraries (and choose from a list if
 there are multiple possibilities). This will remove the need to manually
 import stuff. Either the entire module or a selective import can be used.
Very useful! But please do a private import, to not break interfaces this way. I guess not making private imports the default are a language design oversight, since I see really no reason for this.
 Anyone have any other ideas or things they'd like to see?
<joke> Adding "synchronized" where it would be required. </joke> Best regards Ingo Oeser
Aug 04 2007
next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Ingo Oeser Wrote:
 
 - Renaming a variable/function/template/etc and updating references.
Highly desired. Please have a possibility to ask the user per case or not. The implementation is also very simple, if you use the D compiler frontend already. Rationale: Sometimes you rename sth. to forcibly find all its users, when you have to break the semantic of sth. (e.g. badly designed, non extensible core interfaces) in a big project. Supporting this kind of workflow would be great.
Of course it'll be optional. But with semantic analysis, youy only need to click a button to find all the references to something.
  
 - Inline a function (either a single invocation of it or everywhere it's
 used).
Let the compiler do that. Always! Everything else just asks for long function bodies, if junior programmers try to "optimise" code.
I wasn't thinking about optimization... sometimes you want to change only part of a function and for whatever reason (it's in a library or someone else's code, it would only be useful in that one invocation, etc.), you don't want to add another parameter.
 - Struct-to-class or class-to-struct (possibly, I'm not sure how hard this
 would be to automate. The class-to-struct one, esp. if structs get
 constructors, seems like it'd be a lot easier if no inheritance is used).
Maybe more useful and easier to implement would be: + Extract class members to private struct, build accessors to it into class and fix up all users. Struct to class might be nearly impossible, because structs have properties, which classes don't have (e.g. defined member order, can be stored and retrieved, can be shared with C/C++ etc.).
That's true, but I was thinking that anyone clicking on the refactoring button would know that, and the refactoring would be able to detect things like that. Order-dependent struct literals could be converted into constructors, etc. A bit tougher than the other way around, but definitely not impossible.
 - Automatically import modules for symbols if the symbols can be resolved
 somewhere in the project or attached libraries (and choose from a list if
 there are multiple possibilities). This will remove the need to manually
 import stuff. Either the entire module or a selective import can be used.
Very useful! But please do a private import, to not break interfaces this way. I guess not making private imports the default are a language design oversight, since I see really no reason for this.
Imports are private by default now (I hink that was changed just before 1.0).
Aug 04 2007
next sibling parent renoX <renosky free.fr> writes:
Robert Fraser a écrit :
 Ingo Oeser Wrote:
 - Inline a function (either a single invocation of it or
 everywhere it's used).
Let the compiler do that. Always! Everything else just asks for long function bodies, if junior programmers try to "optimise" code.
I wasn't thinking about optimization... sometimes you want to change only part of a function and for whatever reason (it's in a library or someone else's code, it would only be useful in that one invocation, etc.), you don't want to add another parameter.
Copy/paste programming is usually a very bad form of programming, so I'm not sure that it should be helped.. renoX
Aug 04 2007
prev sibling parent Ingo Oeser <ioe-news rameria.de> writes:
Robert Fraser wrote:
 Ingo Oeser Wrote:
 - Inline a function (either a single invocation of it or everywhere
 it's used).
Let the compiler do that. Always! Everything else just asks for long function bodies, if junior programmers try to "optimise" code.
I wasn't thinking about optimization... sometimes you want to change only part of a function and for whatever reason (it's in a library or someone else's code, it would only be useful in that one invocation, etc.), you don't want to add another parameter.
Then do that in the library, abstract out the common code and use it in both functions. That one was missing: Find duplicate code in a module and suggest abstract version of it. If it's someone else' code, just contact him (e.g. send a patch, open a ticket) and implement the it the way you need it in a private function/method directly above the use case with the TODO comment, that it will be deleted later. Copy'n'Paste programming is a major source of maintenance problems, starting by duplicating bugs, code size increase and performance problems, due to code duplication. Please don't encourage that bad practise! The only valid use of Copy'n'Paste for the programmer is copying identifiers.
 Imports are private by default now (I hink that was changed just before
 1.0).
Oh! Didn't know that :-) I wonder why tango does explicit private imports then... Best Regards Ingo Oeser
Aug 09 2007
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Ingo Oeser wrote:
 Robert Fraser wrote:
 - Expand a mixin/compile-time function/etc. to its actual value/code
 (again, either in a single place or everywhere).
Very useful for readability! Undo would be important here :-)
What about an open/close box (the little square button kind that has a + when collapsed and a - when expanded) that doesn't modify the source but displays the template or mixin as it would be instantiated, with arguments propagated? For instance: template Bar (T) { T bar () { return T.init; } } class Foo { [+] mixin Bar!(int); } Click the button... template Bar (T) { T bar () { return T.init; } } class Foo { [-] int bar () { return int.init; } } That way, I don't have to refactor code to see what my mixin does, so I don't have to worry about checking its contents by refactoring and then forgetting to put it back and having that portion of the code out of sync with the rest. -cbw
Aug 04 2007
prev sibling next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
BCS Wrote:

 I'd go the other way
 
 I would like this is convert a class to abstract, derive a cocreate class 
 from it that acts as the original class does, replace all 'new's and
derivations 
 with this new class.
 
 
 extract interface from several classes (only ask about overlapping functions)
 
 
 convert "auto T = ..." to it's actual type
 ---
 select methods from a class and build a mixin template for them
 with interface extraction this would allow extracting interface +
functionality 
 blocks
 
 interface I       { int foo() }
 template I_impl() { int foo(){...} }
 ...
 class C : I { mixin I_impl!() }
All good ideas! They'll be there.
 generate a explicit specialization of a template from a general one
 
 template T(U) { U foo; }
 
 becomes, for int
 
 template T(U) { U foo; }
 template T(U : int) { int foo; }
 
I don't really understand what you mean here and why this would be useful. Can you elaborate, please?
Aug 04 2007
parent BCS <ao pathlink.com> writes:
Reply to Robert,

 BCS Wrote:
 
 I'd go the other way
 
 I would like this is convert a class to abstract, derive a cocreate
 class from it that acts as the original class does, replace all
 'new's and derivations with this new class.
 
 extract interface from several classes (only ask about overlapping
 functions)
 
 convert "auto T = ..." to it's actual type
 ---
 select methods from a class and build a mixin template for them
 with interface extraction this would allow extracting interface +
 functionality
 blocks
 interface I       { int foo() }
 template I_impl() { int foo(){...} }
 ...
 class C : I { mixin I_impl!() }
All good ideas! They'll be there.
 generate a explicit specialization of a template from a general one
 
 template T(U) { U foo; }
 
 becomes, for int
 
 template T(U) { U foo; }
 template T(U : int) { int foo; }
I don't really understand what you mean here and why this would be useful. Can you elaborate, please?
This would be for where you want to have a special case of a template for some given inputs. It assumes that the general case is good starting point. The most basic form would do a copy/paste of a template and insert "__ : type/value" code into the args list. A better version would then run whatever parts of the template logic it could and drop failed static ifs and maybe some type deductions.
Aug 05 2007
prev sibling next sibling parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Robert Fraser wrote:
 This is probably jumping way ahead of myself here, but if (some day, in the
far future), Descent were to gain some automated D code refactoring support,
what would you like to see?
 
 So far I've thought of/stolen from the JDT:
 ----------
 - Renaming/moving a module (references to it will be updated)
 
 - Changing a function or template signature (and updating references/inserting
default values where appropriate)
 
 - Renaming a variable/function/template/etc and updating references.
 
 - A "use supertype where possible", where references to a particular
implementation of an interface or class are updated to use the
supertype/interface where possible.
 
 - Extract abstract class, where some (or all, you choose which ones) of the
fields/methods of a class are moved to a new abstract class, and the remainder
remain as implementations in the subtype.
 
 - Extract interface: create an interface for some or all of the methods of a
class.
 
 - Inline a function (either a single invocation of it or everywhere it's used).
 
 - Expand a mixin/compile-time function/etc. to its actual value/code (again,
either in a single place or everywhere).
 
 - Struct-to-class or class-to-struct (possibly, I'm not sure how hard this
would be to automate. The class-to-struct one, esp. if structs get
constructors, seems like it'd be a lot easier if no inheritance is used).
 
 - Automatically import modules for symbols if the symbols can be resolved
somewhere in the project or attached libraries (and choose from a list if there
are multiple possibilities). This will remove the need to manually import
stuff. Either the entire module or a selective import can be used.
 ----------
 
 Anyone have any other ideas or things they'd like to see? Descent doesn't even
have semantic analysis yet, so this is a mostly theoretical topic, but someday
your dreams may become a reality...
After being spoiled by JDT, I could list lots and lots of semantic functionality I'd like to see in an IDE... :) But dreaming of the future is easy... who is going to implement all this I ask? :P -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Aug 04 2007
parent Ary Manzana <ary esperanto.org.ar> writes:
Bruno Medeiros escribió:
 Robert Fraser wrote:
 Anyone have any other ideas or things they'd like to see? Descent 
 doesn't even have semantic analysis yet, so this is a mostly 
 theoretical topic, but someday your dreams may become a reality...
After being spoiled by JDT, I could list lots and lots of semantic functionality I'd like to see in an IDE... :) But dreaming of the future is easy... who is going to implement all this I ask? :P
Why, you! :-P
Aug 04 2007
prev sibling next sibling parent BCS <ao pathlink.com> writes:
Reply to Robert,


 Anyone have any other ideas or things they'd like to see? Descent
 doesn't even have semantic analysis yet, so this is a mostly
 theoretical topic, but someday your dreams may become a reality...
 
overload locking: add casts, default args, whatever it takes to convert function calls to exact matches. (idea from hijacking thread) hijacking detection: look at a multi file diff and find places where a overload resolution changed. (and make it easy to select from that set and apply overload locking)
Aug 05 2007
prev sibling parent reply Carlos Santander <csantander619 gmail.com> writes:
Robert Fraser escribió:
 This is probably jumping way ahead of myself here, but if (some day, in the
far future), Descent were to gain some automated D code refactoring support,
what would you like to see?
 
 So far I've thought of/stolen from the JDT:
 ----------
 - Renaming/moving a module (references to it will be updated)
 
 - Changing a function or template signature (and updating references/inserting
default values where appropriate)
 
 - Renaming a variable/function/template/etc and updating references.
 
 - A "use supertype where possible", where references to a particular
implementation of an interface or class are updated to use the
supertype/interface where possible.
 
 - Extract abstract class, where some (or all, you choose which ones) of the
fields/methods of a class are moved to a new abstract class, and the remainder
remain as implementations in the subtype.
 
 - Extract interface: create an interface for some or all of the methods of a
class.
 
 - Inline a function (either a single invocation of it or everywhere it's used).
 
 - Expand a mixin/compile-time function/etc. to its actual value/code (again,
either in a single place or everywhere).
 
 - Struct-to-class or class-to-struct (possibly, I'm not sure how hard this
would be to automate. The class-to-struct one, esp. if structs get
constructors, seems like it'd be a lot easier if no inheritance is used).
 
 - Automatically import modules for symbols if the symbols can be resolved
somewhere in the project or attached libraries (and choose from a list if there
are multiple possibilities). This will remove the need to manually import
stuff. Either the entire module or a selective import can be used.
 ----------
 
 Anyone have any other ideas or things they'd like to see? Descent doesn't even
have semantic analysis yet, so this is a mostly theoretical topic, but someday
your dreams may become a reality...
First of all, the formatter is excellent! Great work! Next, a UI suggestion: add a vertical scroll bar and a horizontal scroll bar to "Brace positions" and "Set all to..." (in "Line wrapping style"), respectively. Finally, some feature suggestions: - insert new line after the closing parenthesis in a function literal - one-line syntax for "scope" statements - insert space before opening bracket in array declarations That's all I can think of for now. -- Carlos Santander Bernal
Aug 13 2007
parent Carlos Santander <csantander619 gmail.com> writes:
Carlos Santander escribió:
 
 That's all I can think of for now.
 
One more: something to allow this formatting: version (A) { // ... } version (NothingHere) {} else { // ... } -- Carlos Santander Bernal
Aug 13 2007