Git Product home page Git Product logo

commandbox-cfformat's People

Contributors

abilioposada avatar bdw429s avatar elpete avatar euans avatar jcberquist avatar jordanclark avatar sbleon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

commandbox-cfformat's Issues

Unwanted line break before semi-colon

Input:

if (isTrue(url.debug ?: false)) {
	setting showdebugoutput="true";
};

Output:

if (isTrue(url.debug ?: false)) {
	setting showdebugoutput="true";
}
;

Expected:

if (isTrue(url.debug ?: false)) {
	setting showdebugoutput="true";
};

Add a `--check` flag to fail in CI if files need formatting

In a CI environment, we'd like to fail the build if there are any formatting changes CFFormat would make. We do not want to overwrite the formatting in CI because this would likely create git conflicts.

I see the message looking something like the following:

The following files do not match the cfformat rules:

/app/models/Foo.cfc
/app/handlers/Main.cfc

Please format the files using the `—overwrite` flag. 

Alignment of arguments and struct items

Our house coding style stipulates alignment of multiline arguments or struct items on the separator. For example:

doSomething(
	  arg1 = ""
	, argument2 = ""
	, aThirdArgument = ""
);

should be formatted as:

doSomething(
	  arg1           = ""
	, argument2      = ""
	, aThirdArgument = ""
);

We also align argument declarations like so:

function doSomething(
	  required string  id
	, required numeric numberValue
	,          string  optionalValue
) {
	// do something...
}

Would it be possible to implement this in CFFormat? We also try to align multiple variable declarations in the same way, but I understand that might be beyond the scope of an automatic procedure...

weird alignment issues

Hi @jcberquist just wanted to report some weird alignment issues. Please see attached screenshot. The correct alignments look really bad for properties where we use line breaks to align.
cfformat

Here is our .cfformat.json

{
	"array.empty_padding": false,
	"array.padding": true,
	"array.multiline.min_length": 40,
	"array.multiline.element_count": 4,
	"array.multiline.leading_comma.padding": true,
	"array.multiline.leading_comma": false,
	"alignment.consecutive.assignments": true,
	"alignment.consecutive.properties": true,
	"alignment.consecutive.params": true,
	"brackets.padding": true,
	"comment.asterisks": "align",
	"binary_operators.padding": true,
	"for_loop_semicolons.padding": true,
	"function_call.empty_padding": false,
	"function_call.padding": true,
	"function_call.multiline.leading_comma.padding": true,
	"function_call.casing.builtin": "cfdocs",
	"function_call.casing.userdefined": "",
	"function_call.multiline.element_count": 4,
	"function_call.multiline.leading_comma": false,
	"function_call.multiline.min_length": 40,
	"function_declaration.padding": true,
	"function_declaration.empty_padding": false,
	"function_declaration.multiline.leading_comma": false,
	"function_declaration.multiline.leading_comma.padding": true,
	"function_declaration.multiline.element_count": 4,
	"function_declaration.multiline.min_length": 40,
	"function_declaration.group_to_block_spacing": "compact",
	"function_anonymous.empty_padding": false,
	"function_anonymous.group_to_block_spacing": "compact",
	"function_anonymous.multiline.element_count": 4,
	"function_anonymous.multiline.leading_comma": false,
	"function_anonymous.multiline.leading_comma.padding": true,
	"function_anonymous.multiline.min_length": 40,
	"function_anonymous.padding": true,
	"indent_size": 4,
	"keywords.block_to_keyword_spacing": "spaced",
	"keywords.group_to_block_spacing": "spaced",
	"keywords.padding_inside_group": true,
	"keywords.spacing_to_block": "spaced",
	"keywords.spacing_to_group": true,
	"keywords.empty_group_spacing": false,
	"max_columns": 120,
	"parentheses.padding": true,
	"strings.quote": "double",
	"strings.attributes.quote": "double",
	"struct.separator": " : ",
	"struct.padding": true,
	"struct.empty_padding": false,
	"struct.multiline.leading_comma": false,
	"struct.multiline.leading_comma.padding": true,
	"struct.multiline.element_count": 4,
	"struct.multiline.min_length": 40,
	"tab_indent": true
}

Weird comments breaking parser

Sorry that I've got all of these weird edge cases!

The following example crashes the parser with this error:

key [1] doesn't exist                                                                                                                                                                        

/modules/commandbox-cfformat/models/cfscript/Keywords.cfc: line 188
186:         } else if (['do', 'try', 'catch'].find(keyword)) {
187:             var nextToken = cftokens.peek(true);
188:             if (!isNull(nextToken) && ['while', 'catch', 'finally'].find(nextToken[1])) {
189:                 formatted = formatted.rtrim();
190:                 if (settings['keywords.block_to_keyword_spacing'] == 'spaced') {
called from /modules/commandbox-cfformat/models/cfscript/Keywords.cfc: line 200
called from /modules/commandbox-cfformat/models/cfscript/Keywords.cfc: line 55
called from /modules/commandbox-cfformat/models/CFScript.cfc: line 98

Bad code:

component {
  public void function foo () {
    try {
      loadData();
    } catch (any e) {
    }
    /* <cfset bar = 'baz'> */
  }
}

Good code 1:

component {
  public void function foo () {
    try {
      loadData();
    } catch (any e) {
    }
  }
}

Good code 2:

component {
  public void function foo () {
    /* <cfset bar = 'baz'> */
  }
}

Missing indentation on param breaking

component {
    function run() {
        param arguments.ownerKey = related.getKey();
    }
}
{
    "alignment.consecutive.assignments":false,
    "alignment.consecutive.params":false,
    "alignment.consecutive.properties":false,
    "array.empty_padding":false,
    "array.multiline.element_count":4,
    "array.multiline.leading_comma":false,
    "array.multiline.leading_comma.padding":true,
    "array.multiline.min_length":40,
    "array.padding":true,
    "binary_operators.padding":true,
    "brackets.padding":true,
    "comment.asterisks":"align",
    "for_loop_semicolons.padding":true,
    "function_anonymous.empty_padding":false,
    "function_anonymous.group_to_block_spacing":"spaced",
    "function_anonymous.multiline.element_count":4,
    "function_anonymous.multiline.leading_comma":false,
    "function_anonymous.multiline.leading_comma.padding":true,
    "function_anonymous.multiline.min_length":40,
    "function_anonymous.padding":true,
    "function_call.casing.builtin":"cfdocs",
    "function_call.casing.userdefined":"camel",
    "function_call.empty_padding":false,
    "function_call.multiline.element_count":4,
    "function_call.multiline.leading_comma":false,
    "function_call.multiline.leading_comma.padding":true,
    "function_call.multiline.min_length":40,
    "function_call.padding":true,
    "function_declaration.empty_padding":false,
    "function_declaration.group_to_block_spacing":"spaced",
    "function_declaration.multiline.element_count":4,
    "function_declaration.multiline.leading_comma":false,
    "function_declaration.multiline.leading_comma.padding":true,
    "function_declaration.multiline.min_length":40,
    "function_declaration.padding":true,
    "indent_size":4,
    "keywords.block_to_keyword_spacing":"spaced",
    "keywords.empty_group_spacing":false,
    "keywords.group_to_block_spacing":"spaced",
    "keywords.padding_inside_group":true,
    "keywords.spacing_to_block":"spaced",
    "keywords.spacing_to_group":true,
    "max_columns":120,
    "method_call.chain.multiline":3,
    "newline":"os",
    "parentheses.padding":true,
    "strings.attributes.quote":"double",
    "strings.quote":"double",
    "struct.empty_padding":false,
    "struct.multiline.element_count":4,
    "struct.multiline.leading_comma":false,
    "struct.multiline.leading_comma.padding":true,
    "struct.multiline.min_length":40,
    "struct.padding":true,
    "struct.separator":": ",
    "tab_indent":false
}

Here the param formatting breaks on a dot (.) but doesn't indent on the next line.

component {
    function run() {
        param arguments.ownerKey = related
        .getKey();
    }
}

incorrect indenting of cfelse tag

Affected v0.12.* and v0.13.0

<cfelse> tag is incorrectly indented and also uses spaces even when "tab_indent": true

Input:

<cfcomponent>
	<cffunction name="init">
		<cfif 1>
			<cfset foo()>
		<cfelse>
			<cfset bar()>
		</cfif>
	</cffunction>
</cfcomponent>

Expected (unmodified):

<cfcomponent>
	<cffunction name="init">
		<cfif 1>
			<cfset foo()>
		<cfelse>
			<cfset bar()>
		</cfif>
	</cffunction>
</cfcomponent>

Actual:

<cfcomponent>
	<cffunction name="init">
		<cfif 1>
			<cfset foo()>
        <cfelse>
			<cfset bar()>
		</cfif>
	</cffunction>
</cfcomponent>	

Add a `watch` command

The watch command would watch all .cfc files for changes and format each added or changed file.

The biggest question here would be if you nested the original command (like cfformat run) to allow for cfformat watch or if you used a different command name (like cfformat-watch).

(Again, happy to implement this.)

Error when running cfformat on Ubuntu

I'm running CommandBox 4.7 on Ubuntu 19.04. I get the same output on an older Ubuntu machine which is also running CommandBox 4.7 from the apt repository.

I created a CFC component for testing purposes:

component {}

When running cfformat test.cfc, I get the following output:

CommandBox> cfformat Application.cfc
ERROR (4.7.0+00026)                                                                                                                                                                                                                                                                                                                                               Error invoking external process                                                                                                                                                  
/home/mark/.CommandBox/cfml/modules/commandbox-cfformat/bin/v0.7.0/cftokens_osx: 1: /home/mark/.CommandBox/cfml/modules/commandbox-cfformat/bin/v0.7.0/cftokens_osx: Syntax error: ")" unexpected
/home/mark/.CommandBox/cfml/modules/commandbox-cfformat/models/CFFormat.cfc: line 185
183:     function tokenizeFile(fullFilePath) {
184:         var tokens = '';
185:         cfexecute(name=executable arguments="""#fullFilePath#""" variable="tokens" timeout=10);
186:         if (!isJSON(tokens)) {
187:             throw(tokens);
called from /home/mark/.CommandBox/cfml/modules/commandbox-cfformat/models/CFFormat.cfc: line 76
called from /home/mark/.CommandBox/cfml/modules/commandbox-cfformat/commands/cfformat.cfc: line 284
called from /home/mark/.CommandBox/cfml/modules/commandbox-cfformat/commands/cfformat.cfc: line 128
called from /home/mark/.CommandBox/cfml/system/services/CommandService.cfc: line 342
called from /home/mark/.CommandBox/cfml/system/services/CommandService.cfc: line 138
called from /home/mark/.CommandBox/cfml/system/Shell.cfc: line 758
called from /home/mark/.CommandBox/cfml/system/Shell.cfc: line 578
called from /home/mark/.CommandBox/cfml/system/Bootstrap.cfm: line 145

lucee.runtime.exp.ApplicationException: Error invoking external process
        at lucee.runtime.tag.Execute.doEndTag(Execute.java:258)
        at modules.commandbox_cfformat495.models.cfformat_cfc$cf.udfCall2(/commandbox/modules/commandbox-cfformat/models/CFFormat.cfc:185)
        at modules.commandbox_cfformat495.models.cfformat_cfc$cf.udfCall(/commandbox/modules/commandbox-cfformat/models/CFFormat.cfc)
        at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)
        at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)
        at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)
        at lucee.runtime.type.scope.UndefinedImpl.call(UndefinedImpl.java:803)
        at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:756)
        at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1718)
        at modules.commandbox_cfformat495.models.cfformat_cfc$cf.udfCall1(/commandbox/modules/commandbox-cfformat/models/CFFormat.cfc:76)
        at modules.commandbox_cfformat495.models.cfformat_cfc$cf.udfCall(/commandbox/modules/commandbox-cfformat/models/CFFormat.cfc)
        at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)
        at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)
        at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)
        at lucee.runtime.ComponentImpl._call(ComponentImpl.java:693)
        at lucee.runtime.ComponentImpl._call(ComponentImpl.java:573)
        at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1997)
        at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:756)
        at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1718)
        at modules.commandbox_cfformat495.commands.cfformat_cfc$cf.udfCall2(/commandbox/modules/commandbox-cfformat/commands/cfformat.cfc:284)
        at modules.commandbox_cfformat495.commands.cfformat_cfc$cf.udfCall(/commandbox/modules/commandbox-cfformat/commands/cfformat.cfc)
        at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)
        at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)
        at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)
        at lucee.runtime.type.scope.UndefinedImpl.call(UndefinedImpl.java:803)
        at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:756)
        at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1718)
        at modules.commandbox_cfformat495.commands.cfformat_cfc$cf.udfCall1(/commandbox/modules/commandbox-cfformat/commands/cfformat.cfc:128)
        at modules.commandbox_cfformat495.commands.cfformat_cfc$cf.udfCall(/commandbox/modules/commandbox-cfformat/commands/cfformat.cfc)
        at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)
        at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)
        at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)
        at lucee.runtime.ComponentImpl._call(ComponentImpl.java:695)
        at lucee.runtime.ComponentImpl._call(ComponentImpl.java:573)
        at lucee.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:2014)
        at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)
        at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)
        at system.services.commandservice_cfc$cf.udfCall1(/commandbox/system/services/CommandService.cfc:342)
        at system.services.commandservice_cfc$cf.udfCall(/commandbox/system/services/CommandService.cfc)
        at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)
        at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)
        at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)
        at lucee.runtime.type.scope.UndefinedImpl.callWithNamedValues(UndefinedImpl.java:812)
        at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)
        at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)
        at system.services.commandservice_cfc$cf.udfCall1(/commandbox/system/services/CommandService.cfc:138)
        at system.services.commandservice_cfc$cf.udfCall(/commandbox/system/services/CommandService.cfc)
        at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)
        at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)
        at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)
        at lucee.runtime.ComponentImpl._call(ComponentImpl.java:693)
        at lucee.runtime.ComponentImpl._call(ComponentImpl.java:573)
        at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1997)
        at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:756)
        at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1718)
        at system.shell_cfc$cf.udfCall4(/commandbox/system/Shell.cfc:758)
        at system.shell_cfc$cf.udfCall(/commandbox/system/Shell.cfc)
        at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)
        at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)
        at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)
        at lucee.runtime.type.scope.UndefinedImpl.callWithNamedValues(UndefinedImpl.java:812)
        at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)
        at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)
        at system.shell_cfc$cf.udfCall3(/commandbox/system/Shell.cfc:578)
        at system.shell_cfc$cf.udfCall(/commandbox/system/Shell.cfc)
        at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)
        at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)
        at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)
        at lucee.runtime.ComponentImpl._call(ComponentImpl.java:695)
        at lucee.runtime.ComponentImpl._call(ComponentImpl.java:573)
        at lucee.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:2014)
        at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)
        at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)
        at mark._commandbox46.cfml.system.bootstrap_cfm$cf.call(/__commandbox_root/mark/.CommandBox/cfml/system/Bootstrap.cfm:145)
        at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:933)
        at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:823)
        at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:805)
        at g6u3r6cj3p08.call(Unknown Source)
        at lucee.runtime.compiler.Renderer.tag(Renderer.java:113)
        at lucee.runtime.compiler.Renderer.script(Renderer.java:101)
        at lucee.runtime.jsr223.ScriptEngineImpl.eval(ScriptEngineImpl.java:64)
        at lucee.runtime.jsr223.ScriptEngineImpl.eval(ScriptEngineImpl.java:199)
        at cliloader.LoaderCLIMain.execute(LoaderCLIMain.java:285)
        at cliloader.LoaderCLIMain.execute(LoaderCLIMain.java:152)
        at cliloader.LoaderCLIMain.main(LoaderCLIMain.java:509)

Error thrown formatting empty file

This is edge case.

When watching a folder and using touch SomeComponent.cfc, the error below is generated.

ERROR (4.7.0+00026)

Array index [1] out of range, array size is [0]

/modules/commandbox-cfformat/models/CFFormat.cfc: line 167
165: var bom = '';
166: if (
167: isArray(tokens.elements[1]) &&
168: arrayLen(tokens.elements[1][2]) &&
169: tokens.elements[1][2][1] == 'bom'
called from /modules/commandbox-cfformat/models/CFFormat.cfc: line 75
called from /modules/commandbox-cfformat/commands/cfformat.cfc: line 303
called from /modules/commandbox-cfformat/commands/cfformat.cfc: line 170
called from /system/util/Watcher.cfc: line 110

Quotes not formatted in component metadata

With the following settings file:

{
    "strings.quote": "double"
}

Running the following file:

component extends='coldbox.system.testing.BaseTestCase' appMapping='/' {

    function run() {
        describe( "about Suite", function() {
            beforeEach( function( currentSpec ) {
                setup();
            } );

            it( "index", function() {
                var event = execute( event = "about.index", renderResults = true );
                // expectations go here.
                expect( false ).toBeTrue();
            } );
        } );
    }

}

The quotes in the component metadata (extends, appMapping) are not converted.

Any plans to make this into an editor plugin?

This is kind of an absurd request, since you've already built a Sublime Text plugin for formatting CFML, but I was wondering if there are any plans to make this new engine available as an editor plugin.

I'm interested in this because we're working on setting up command-line code formatting, but we also really like the "just format the selected code" capability of your ST plugin. We'd rather not use both formatters, because even with the same author, it seems like the output isn't always going to be exactly the same. We'd also prefer to have a single configuration for both the CLI and editor-based formatter.

Let me know your thoughts. Thanks so much for building all of these great tools!

Option to not format comments.

The formatter currently strips all leading and trailing white space and then indents.

/**
 * Description
 *
 * @param Some parameter info
 */

is now

/**
* Description
*
* @param Some parameter info
*/

Unfortunately, this breaks my doc-block extension since it is expecting an extra space after the indent.

Space between `!`

Small thing, but I like to have space between a bang (!) and the code it is negating.

component {

    function run() {
        if ( ! true ) {
            writeDump( "Hi!" );
        }
    }

}

Currently this squashes into if ( !true ) {.

Additionally, if I use a double bang (!!) I would keep the bangs together: if ( !! true ) {.

Eaten code with extraneous hashes

Input:

loop from=1 to=#params.quantity# index="local.i" {
}

Expected:

loop from=1 to=#params.quantity# index="local.i" {
}

Actual:

loop from=1 to=# params {
}

Admittedly, the input syntax is pretty smelly.. but a fair chunk of code was eaten.

space formatting not happening on closures

Please see attached image. I am also attaching my rules below. But the formatting is not affecting
Screen Shot 2019-09-24 at 7 41 32 AM
the inner closures.

{
    "array.empty_padding" : false,
    "array.padding" : true,
    "array.multiline.min_length" : 40,
    "array.multiline.element_count" : 4,
    "array.multiline.leading_comma.padding" : true,
    "array.multiline.leading_comma" : false,
    "assignments.consecutive.alignment" : true,
    "brackets.padding" : true,
    "comment.asterisks" : "align",
    "binary_operators.padding" : true,
    "for_loop_semicolons.padding" : true,
    "function_call.empty_padding" : false,
    "function_call.padding" : true,
    "function_call.multiline.leading_comma.padding" : true,
    "function_call.casing.builtin" : "cfdocs",
    "function_call.casing.userdefined" : "",
    "function_call.multiline.element_count" : 4,
    "function_call.multiline.leading_comma" : false,
    "function_call.multiline.min_length" : 40,
    "function_declaration.padding" : true,
    "function_declaration.empty_padding" : false,
    "function_declaration.multiline.leading_comma" : false,
    "function_declaration.multiline.leading_comma.padding" : true,
    "function_declaration.multiline.element_count" : 4,
    "function_declaration.multiline.min_length" : 40,
    "function_declaration.group_to_block_spacing" : "compact",
    "function_anonymous.empty_padding" : false,
    "function_anonymous.group_to_block_spacing" : "compact",
    "function_anonymous.multiline.element_count" : 4,
    "function_anonymous.multiline.leading_comma" : false,
    "function_anonymous.multiline.leading_comma.padding" : true,
    "function_anonymous.multiline.min_length" : 40,
    "function_anonymous.padding" : false,
    "indent_size" : 4,
    "keywords.block_to_keyword_spacing" : "spaced",
    "keywords.group_to_block_spacing" : "spaced",
    "keywords.padding_inside_group" : true,
    "keywords.spacing_to_block" : "spaced",
    "keywords.spacing_to_group" : true,
    "keywords.empty_group_spacing" : false,
    "max_columns" : 120,
    "parentheses.padding" : true,
    "strings.quote" : "double",
    "strings.attributes.quote" : "double",
    "struct.separator" : " : ",
    "struct.padding" : true,
    "struct.empty_padding" : false,
    "struct.multiline.leading_comma" : false,
    "struct.multiline.leading_comma.padding" : true,
    "struct.multiline.element_count" : 4,
    "struct.multiline.min_length" : 40,
    "tab_indent" : true
}

Watcher not working

cfformat ./ --watch

Gives me this error on save:

```Error invoking external process
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 123, kind: Other, message: "The filename, directory name, or volume label syntax is incorrect." }', src\libcore\result.rs:999:5note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
D:\.Command Box\cfml\modules\commandbox-cfformat\models\CFFormat.cfc: line 140
138:     function tokenizeFile(fullFilePath) {
139:         var tokens = '';
140:         cfexecute(name=executable arguments="""#fullFilePath#""" variable="tokens" timeout=10);
141:         if (!isJSON(tokens)) {
142:             throw(tokens);```

Looks like we're double appending the base path on this line:

var allFiles = files.added.append(files.changed, true).map((p) => fullPath & p);

Removing the map made it work for me.

Conditional with inline comments is broken upon formatting

It's unusual, but sometimes we use inline comments to explain what's going on in a complex conditional. Running cfformat on this code breaks the syntax, making the file unparseable.

Input:

component {
  if (
    status == 0 // explanation
     || (
      [1, 2, 3].contains(status) // explanation
      && someOtherCondition // explanation
    )
  ) {
    Echo('foo');
  }
}

Actual Output:

component {

  if (
    status == 0 // explanation
     || ([1, 2, 3].contains(status) // explanation && someOtherCondition // explanation)
  ) {
    Echo('foo');
  }

}

Expected Output:

component {

  if (
    status == 0 // explanation
     || ([1, 2, 3].contains(status) // explanation
      && someOtherCondition // explanation
    )
  ) {
    Echo('foo');
  }

}

Add support for safe navigation operator

It looks like the safe navigation operator (?.) is being interpreted as a ternary operator. This causes some code breakage.

Config: default

Source:

component {

    function functionCallWithSafeNavigationOperator() {
        return getFoo()?.getBar();
    }

    function structWithSafeNavigationOperator() {
        return variables?.foo?.bar;
    }

}

Current Output:

component {

    function functionCallWithSafeNavigationOperator() {
        return getFoo() ? .getBar();
    }

    function structWithSafeNavigationOperator() {
        return variables ? .foo ? .bar;
    }

}

Alignment of code

This is more of a question than an issue just yet. But there are many places where we do code alignment for readability. With cfformat I have no way to reproduce this. Instead it removes this code alignment. Is this something possible? Please see screenshots

image

image

Remove Leading Comma Padding

It would be useful to have a settings that removed the space that is added after the comma moved by the .leading_comma settings. Maybe a setting like .leading_comma.padding

For example:

From this...

this.constraints = {
	'Title': { required: true, size: '1..255' },
	'Forename': { size: '0..255' },
	'Surname': { required: true, size: '1..255' }
}

...to this ("struct.multiline.leading_comma":true)...

this.constraints = {
	'Title': { required: true, size: '1..255' }
	, 'Forename': { size: '0..255' }
	, 'Surname': { required: true, size: '1..255' }
}

...finally to this ("struct.multiline.leading_comma.padding":false)...

this.constraints = {
	'Title': { required: true, size: '1..255' }
	,'Forename': { size: '0..255' }
	,'Surname': { required: true, size: '1..255' }
}

Unterminated quotes deletes lots of code

Here's a fun one: a non-terminated string in a file causes cfformat to delete code.

Source:

component extends="coldbox.system.testing.BaseTestCase" appMapping="/" {

    function run() {
        describe( 'about Suite", function() {
            it( "index", function() {
                var event = execute( event = "about.index", renderResults = true );
                expect( false ).toBeTrue();
            } );
        } );
    }

}

Output:

about Suite", function() {
            it( "index", function() {
                var event = execute( event = "about.index", renderResults = true );
                expect( false ).toBeTrue();
            } );
        } );
    }

}

I'm not sure how, but deleting code on a typo isn't exactly helpful. 😅

Support for a .cfformatignore file

I am currently creating scripts that specify all the globs I want to format in my box.json package scripts. This can get rather long and repetitive....

{
    "scripts":{
        "format":"cfformat run handlers/**/*.cfc,models/**/*.cfc,modules_app/**/*.cfc,tests/resources/**/*.cfc,tests/specs/**/*.cfc --overwrite",
        "format:check":"cfformat check handlers/**/*.cfc,models/**/*.cfc,modules_app/**/*.cfc,tests/resources/**/*.cfc,tests/specs/**/*.cfc"
    }
}

It could be a nice feature to check for some kind of ignore file so I could add files that should never get formatted. I assume this would follow the .gitignore syntax. (I believe CommandBox has some built in functions to help with this.) The command could look for a .cfformatignore file by default while allowing an alternate file name to be passed in. Additionally, perhaps a global .cfformatignore could be specified as a module setting. Then I won't ever accidently format all of ColdBox again. 😅

Require curlies for if statement body

I don't know how easy this one is or if it falls in the purview of CFFormat since it's actually adding code, not just whitespace. One of my big pet peeves is this:

if( condition )
  randomOrphan.codeThatCanGetSeperated();

I'd love to see an option to change it to this:

if( condition ) {
  niceCodeSecurley.insideIfBody();
}

min_length maybe not being respected?

I think something is off with the min_length determination.

component {

    public any function update( struct attributes = {}, boolean ignoreNonExistentAttributes = false, sssssssssss = "s" ) {
        writeDump( var = "Hello!" );
    }

}

This component does not split the arguments on to new lines no matter what I choose for any of min_length settings. However, add one more character to the argument list up there and it will split.

Comma formatting results in invalid syntax

This may be an edge case and tricky to solve, but changing leading to trailing commas with a commented line of code results in a syntax exception. Note missing comma after local.from,

input:

send(
  to = local.to
  ,from = local.from
  // ,user=local.user
  // ,thing=local.thing
  ,body = local.body
);

result:

send(
  to = local.to,
  from = local.from
  // ,user=local.user, // ,thing=local.thing
  body = local.body
);

expected:

send(
  to = local.to,
  from = local.from,
  // ,user=local.user, // ,thing=local.thing
  body = local.body
);

Spaces mistakenly removed

The following code causes cfformat to return invalid syntax:

Input:
include "foo.cfm";

Returns:
include"foo.cfm";

Workaround:
include template="foo.cfm";

line breaks not always added

This code block is formatted by CFFormat

component {

	function doSomething() {
		if( condition ) {
		} var i = 0; i++; i--;
	}

}

it did not add line breaks after the trailing } nor the individual statements.

method chaining formatting

It would be awesome to have chained methods be indented on a new line. ex.

bookService
   .getVersions( bookDirectory )
   .each( ( v ) => print.line( v ) );

as opposed to
bookService.getVersions( bookDirectory ).each( (v) => print.line( v ) );
or maybe have a max length

Breaks not respected on component declarations

I currently have a component declration like so:

image

component 
	extends="coldbox.system.testing.BaseModelTest" 
	model="cbvalidation.models.validators.MethodValidator" 
{

I would have expected for the formmater to respect the breaks. However, it does this:

component extends="coldbox.system.testing.BaseModelTest" model="cbvalidation.models.validators.MethodValidator" {

Here are my rules

{
	"array.empty_padding": false,
	"array.padding": true,
	"array.multiline.min_length": 40,
	"array.multiline.element_count": 4,
	"array.multiline.leading_comma.padding": true,
	"array.multiline.leading_comma": false,
	"alignment.consecutive.assignments": true,
	"alignment.consecutive.properties": true,
	"alignment.consecutive.params": true,
	"brackets.padding": true,
	"comment.asterisks": "align",
	"binary_operators.padding": true,
	"for_loop_semicolons.padding": true,
	"function_call.empty_padding": false,
	"function_call.padding": true,
	"function_call.multiline.leading_comma.padding": true,
	"function_call.casing.builtin": "cfdocs",
	"function_call.casing.userdefined": "camel",
	"function_call.multiline.element_count": 4,
	"function_call.multiline.leading_comma": false,
	"function_call.multiline.min_length": 40,
	"function_declaration.padding": true,
	"function_declaration.empty_padding": false,
	"function_declaration.multiline.leading_comma": false,
	"function_declaration.multiline.leading_comma.padding": true,
	"function_declaration.multiline.element_count": 4,
	"function_declaration.multiline.min_length": 40,
	"function_declaration.group_to_block_spacing": "compact",
	"function_anonymous.empty_padding": false,
	"function_anonymous.group_to_block_spacing": "compact",
	"function_anonymous.multiline.element_count": 4,
	"function_anonymous.multiline.leading_comma": false,
	"function_anonymous.multiline.leading_comma.padding": true,
	"function_anonymous.multiline.min_length": 40,
	"function_anonymous.padding": true,
	"indent_size": 4,
	"keywords.block_to_keyword_spacing": "spaced",
	"keywords.group_to_block_spacing": "spaced",
	"keywords.padding_inside_group": true,
	"keywords.spacing_to_block": "spaced",
	"keywords.spacing_to_group": true,
	"keywords.empty_group_spacing": false,
	"max_columns": 120,
	"parentheses.padding": true,
	"strings.quote": "double",
	"strings.attributes.quote": "double",
	"struct.separator": " : ",
	"struct.padding": true,
	"struct.empty_padding": false,
	"struct.multiline.leading_comma": false,
	"struct.multiline.leading_comma.padding": true,
	"struct.multiline.element_count": 4,
	"struct.multiline.min_length": 40,
	"tab_indent": true
}

Spaces removed incorrectly (tag-based code)

I'm working on a Application that has the following code in it

<cfif len(event.getValue('filter_service','')) eq 0
        AND len(event.getValue('filter_client','')) eq 0
        AND len(event.getValue('filter_filenumber','')) eq 0
        AND len(event.getValue('filter_selfrom','')) eq 0
        AND len(event.getValue('filter_selto','')) eq 0
        AND len(event.getValue('filter_period','')) eq 0
        AND len(event.getValue('filter_status','')) eq 0
        AND len(event.getValue('q','')) eq 0
        and not isDefined("rc.medicalReportsNeedApproval")>

When I run cfformat on it, with the default settings, it removes the space between AND and len(event.getValue....

<cfif len(event.getValue('filter_service', '')) eq 0
        ANDlen(event.getValue('filter_client', '')) eq 0
        ANDlen(event.getValue('filter_filenumber', '')) eq 0
        ANDlen(event.getValue('filter_selfrom', '')) eq 0
        ANDlen(event.getValue('filter_selto', '')) eq 0
        ANDlen(event.getValue('filter_period', '')) eq 0
        ANDlen(event.getValue('filter_status', '')) eq 0
        ANDlen(event.getValue('q', '')) eq 0
        andnot isDefined('rc.medicalReportsNeedApproval')>

when I first refactor it to cfscript, and then run cfformat, this issue does NOT occur

Function return type breaks

These are my settings:

{
    "brackets.padding": true,
	"strings.quote": "double",
	"strings.attributes.quote": "double",
	"function_call.empty_padding": false,
    "function_call.padding": true,
	"function_declaration.padding": true,
	"function_call.multiline.leading_comma.padding": true,
	"function_declaration.multiline.leading_comma.padding" : true,
	"function_declaration.empty_padding": false,
	"function_declaration.group_to_block_spacing": "compact",
	"struct.padding": true,
	"struct.empty_padding": false,
	"struct.multiline.leading_comma.padding" : true,
	"array.empty_padding":false,
    "array.padding":true,
    "array.multiline.leading_comma.padding":true,
    "binary_operators.padding":true,
    "for_loop_semicolons.padding":true,
    "indent_size":4,
    "parentheses.padding":true,
    "struct.separator":" : ",
	"tab_indent":true,
	"keywords.block_to_keyword_spacing" : "spaced",
	"keywords.group_to_block_spacing" : "spaced",
	"keywords.padding_inside_group" : true,
	"keywords.spacing_to_block" : "compact",
	"keywords.spacing_to_group" : true
}

This is current code

/**
* Set form params
* @name The name of the key in the form params
* @value The value
*/
OrtusPDF function setFormParam( required string name, required string value ){
	variables.formparams[ arguments.name ] = arguments.value;
	return this;
}

This is the formated code:

/**
* Set form params
* @name The name of the key in the form params
* @value The value
*/
OrtusPDF
function setFormParam( required string name, required string value ){
	variables.formparams[ arguments.name ] = arguments.value;
	return this;
}

As you can see it puts the return type of functions in a new line

Broken on lambda return x <> y

I have this line of code in my app - it's essentially stripping out query parameters which don't have an explicit value set.

params = params.filter( ( key, param ) => param.value <> "<NOTSET>" );

CFFormat changed this to: (Notice the double spaces between < and >.

params = params.filter( ( key, param ) => param.value <  > "<NOTSET>" );

I'm not sure what language construct CFFormat thinks that is, but it's definitely converting valid CFML to invalid CFML.

Is there somehow I can help fix this?

Case options for UDF vs native functions

It would be great to configure function case separately for native functions and user defined functions.

One code standard I have observed is that native cfml functions are PascalCase and user defined functions are camelCase.

Eg:

"function_call.native.case":"PascalCase" -- or "Upper / Lower"
"function_call.user_defined.case":"camelCase"

Input:

today = now();
earlier = OneDayAgo();

Output:

today = Now();
earlier = oneDayAgo();

Thanks again for a great extenstion!

Wizard to create settings file

This is just a random idea, but how about a command that presents the user with a little wizard to choose each setting with a code sample of each one. I'm imagining clearing the screen after each question and outputting two (or however many options there are) code samples demonstrating what the setting does, and then use the multi-select input for the user to toggle between the settings to choose what they want. Default each question to the default value. When the user is finished, we spit out a JSON file based on their responses and show them an example of their final choice.

Empty function calls have unwanted padding

Input:
return $$badRequest();

Output:
return $$badRequest( );

Expected:
return $$badRequest();

Settings:

{
	"array.empty_padding": false,
	"array.multiline.element_count": 4,
	"array.multiline.leading_comma": false,
	"array.multiline.leading_comma.padding": true,
	"array.multiline.min_length": 40,
	"array.padding": false,
	"binary_operators.padding": true,
	"brackets.padding": false,
	"for_loop_semicolons.padding": true,
	"function_call.casing.builtin": "pascal",
	"function_call.casing.userdefined": "camel",
	"function_call.empty_padding": false,
	"function_call.multiline.element_count": 4,
	"function_call.multiline.leading_comma": false,
	"function_call.multiline.leading_comma.padding": true,
	"function_call.multiline.min_length": 40,
	"function_call.padding": false,
	"function_declaration.empty_padding": false,
	"function_declaration.group_to_block_spacing": "spaced",
	"function_declaration.multiline.element_count": 4,
	"function_declaration.multiline.leading_comma": false,
	"function_declaration.multiline.leading_comma.padding": true,
	"function_declaration.multiline.min_length": 40,
	"function_declaration.padding": false,
	"indent_size": 2,
	"keywords.block_to_keyword_spacing": "spaced",
	"keywords.empty_group_spacing": false,
	"keywords.group_to_block_spacing": "spaced",
	"keywords.padding_inside_group": false,
	"keywords.spacing_to_block": "spaced",
	"keywords.spacing_to_group": true,
	"max_columns": 120,
	"parentheses.padding": false,
	"strings.quote": "double",
	"strings.attributes.quote": "double",
	"struct.empty_padding": false,
	"struct.multiline.element_count": 4,
	"struct.multiline.leading_comma": false,
	"struct.multiline.leading_comma.padding": true,
	"struct.multiline.min_length": 40,
	"struct.padding": false,
	"struct.separator": " = ",
	"tab_indent": true
}

Invalid code causes incorrect formatting

This example has an extra comma before the comment:

component {

	function doSomething() {
		var options = {
			datasource: 'xyz',
			// other stuff
		};
	}

}

instead of throwing an error about an invalid syntax, CFFormat does this which comments out the end of the struct literal.

component {

	function doSomething() {
		var options = { datasource: 'xyz', // other stuff };
	}

}

Unwanted line breaks in function string arguments

Input:

qry = querySim("
	id , fk_id , create_date
	1 | 3 | #Now()#
	2 | 4 | -
");

Output:

qry = querySim(
	"
	id , fk_id , create_date
	1 | 3 | #Now()#
	2 | 4 | -
"
);

Expected:

qry = querySim("
	id , fk_id , create_date
	1 | 3 | #Now()#
	2 | 4 | -
");

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.