Variable does not expand in transformation - visual-studio-code

I am working on a VS code extension for a custom language. This contains a snippet that allows the user to create a function with parameters and start to set up some documentation inside the function. The way I am achieving this is to use variable transforms on the parameter variable (${2}) using some matching tricks to extract each individual parameter and data type. In this simpler example, each parameter name will be on its own line inside a block comment.
"function": {
"prefix": "func",
"body": [
"function ${1:functionName}(${2:params})",
"${2/([^,]+), *|([^,]+$)/\t${BLOCK_COMMENT_START} ${1}${2} ${BLOCK_COMMENT_END}\n/g}",
"end"
]
}, ...
The expected output is this:
function functionName(hello,world)
{ hello }
{ world }
end
The actual output is this:
function functionName(hello,world)
${BLOCK_COMMENT_START} hello ${BLOCK_COMMENT_END}
${BLOCK_COMMENT_START} world ${BLOCK_COMMENT_END}
end
The issue is that ${BLOCK_COMMENT_START} and _END do not expand inside the transform. I can easily get around this issue by hardcoding the curly braces in the snippet, but I would prefer to find a way where I do not have to do that.
"body": [
"function ${1:functionName}(${2:params})",
"${2/([^,]+), *|([^,]+$)/\t{ ${1}${2} }\n/g}",
"end"
]
Is there a way that I can have a variable expand in the transform?

Related

VSCode - Make custom user snippets overwriting default suggestion

To match my company's coding standards, I'm making custom snippets like so:
// php.json
{
"If block": {
"prefix": ["if"],
"body": ["if ( ${1:condition} )", "{", "\t$0", "}"],
"description": "if block",
},
// ...
}
Then, when I type if + Tab, I have two suggestions:
I'm forced to press enter to actually select the first one, which is my custom made snippet ; the second being PHP's default snippet.
Is there a way to actually ignore PHP's default snippets in case I have the exact same prefix?

Golang VS Code Snippet: Mimic "built-in" `variable.print!` snippet

Context: The Golang VS Code extension has built-in snippets/macros for creating a fmt.PrintX statement from a given variable:
Note how the variable name is filled in for me.
I frequently write methods, and the Golang extension's meth snippet, in my opinion, is slow, since there are 5 (!) tab stops:
So far, I've written a snippet that mimics the meth snippet:
"Struct Method": {
"prefix": ".meth",
"body": [
"func ($1 $2) $3($4) $5 {",
"\t$6",
"}"
],
"description": "some description"
}
And I would like this snippet to mimic the print! macro/snippet, where it fills in the variable name; for the method snippet, instead of filling a variable, it would automatically fill in the method receiver ($1 and $2) with the first letter of the struct name, and the full struct name in the second.
So, if I have the following struct:
type SomeStruct struct {}
and type:
SomeStruct.meth
then activate the snippet, it should output:
func (s SomeStruct) .(.) . {
.
}
where each . is a tab stop.
Is this sort of snippet possible? If so, how can I write it so it does this?
One thing you can do is to make a snippet in a keybinding that can parse the current line. Put this into your keybindings.json:
{
"key": "alt+w",
"command": "editor.action.insertSnippet",
"args": {
"snippet": "\n\nfunc (${TM_CURRENT_LINE/\\s*type\\s*(.)(.*)\\s* struct\\s*{}/${1:/downcase} $1$2)/} $1($2) $3 {\n\t$4\n}"
},
// "when": "langId == golang"
}
The workflow is different than what you mentioned but is also easier - you don't have to type SomeStruct.meth. Just trigger the keybinding at the end of the type SomeStruct struct {} line as in the demo.
If you want to be anywhere in the document and trigger a snippet completion, then the HyperSnips extension may be the way to go.

How can I select a part of TM_DIRECTORY variable?

I want to select a part of the TM_DIRECTORY variable on VScode snippet. I mean I want to select Tests\Setup of the d:\Projects\Hakhsin\hakhsin\tests\Setup in code-snippet file. Look at this:
// On snippet file
"PHP Class": {
"scope": "",
"prefix": ["phpClass"],
"body": [
"<?php\n\nnamespace ${TM_DIRECTORY/(?<=(?:[\w:\\]hakhsin\\)).+(?=\\)//};\n\nclass ${TM_FILENAME_BASE} {\n\t$2\n}"
],
"description": "New PHP Class"
},
And I want to get this result:
namespace Tests\Setup;
class StorageFactory {
}
But I get this result:
<?php
namespace d:\Projects\Hakhsin\hakhsin\tests\Setup;
class StorageFactory {
}
It doesn't appear you can use variables inside of other variables in a snippet transform.
You can try this code which is more "dynamic" than yours but not perfect:
"${TM_DIRECTORY/([^\\\\]*\\\\){4}(.*)/${2:/capitalize}/}",
The {4} in that is if you have 4 segments in the directory structure before the part you want, like d:\Projects\Hakhsin\hakhsin\tests\Setup The segments are d:\, Projects\, Hakhsin\ and hakhsin\. If that number of segments is known and stable than the snippet I showed works well.
I doubt the number of those segments would vary within a project but might very well between projects - you would just have to change the {x} item for each project if so.
I solved it but it is not dynamic.
namespace ${TM_DIRECTORY/(.*hakhsin\\\\)(.*)/${2:/capitalize}/};
Is there a better way? anything like this:
namespace ${TM_DIRECTORY/(.*${WORKSPACE_NAME}\\\\)(.*)/${2:/capitalize}/};
This is the result:
<?php
namespace Tests\Setup;
class StorageFactory {
}

Haxe: Creating a code completion macro for JSON files

I am trying to implement a code completion macro for JSON files by generating field definitions
var classOfChild = Type.getClass(child); // `child` may look like this array: [[1,2,3],[0.1,0.2,0.3]]
fields.push({
"name": childName,
"pos" : _pos,
"kind": childType,
});
I already watched some videos and read some tutorials on this, but there is no information how to get ComplexType from a Type.typeof(object) result.
I have tried code that doesn't work like:
//"kind": childType,
//"kind": childType.toString(),
//"kind": FVar(macro {childType.toString(); }),
//"kind": FVar(macro Array<$v{arrType}>)
but none of them worked (all of them raise some Error or )
Edit 1: here is my json data:
{"floatVar1":0.1, "str":"some string", "nullValueObject":null, "arrayOfInts":[11,20,9], "matrixLikeArray":[[14, 12, 13, 11, 18]], "floatMatrix":[[14.4, 12.3, 13.7, 11.9, 18.0]], "symbolPayouts":[0.05], "objectInObject":{"prop1":"some str", "prop2": "some str2", "prop3":10.17, "prop4":[[1,2,3],[19.3,20.4]]}}
I would like to create Definitions for prop4, ("prop4":[[1,2,3],[19.3,20.4]])
Edit 2: I have already figured out how to create the "kind" for the simple types ("kind": FVar(macro:Dynamic)) and the object (kind : FVar(TAnonymous( jsonFields ))). But how to do that for arrays, arrays of arrays, etc.
Edit 3: code in gist.github.com
When generating code with macros it is easy to attempt to generate something which isn't efficient and you did get side tracked by trying to define explicit types.
Based on your gist, you just need to define a json field and give it the content of your JSON file as the field's value as if you were defining the value as a Haxe literal object.
Your goal is then to generate something you could have written as:
private var json = { prop1:'hello', prop2:42, prop3:[1,2,3] };
The haxe compiler will strongly type this json field.
To achieve that, your macro just need to add one field with an initial value obtained from the JSON file; and likewise, the Haxe compiler will strictly type it.
Creating a variable with a type to be inferred by the compiler is simply FVar(null, valueExpr), which means your entire macro can be reduced to:
var fields = Context.getBuildFields();
var json = Json.parse(src);
fields.push({
name : "json",
pos : Context.currentPos(),
kind : FVar(null, macro $v{json}),
access: [APrivate],
});
return fields;
For a more elaborated version I can point you on the following gist: ResourceGenerator.hx which will generate recursively "inlinable" and dce-friendly objects.
PS: sadly your "prop4":[[1,2,3],[19.3,20.4]] is impossible because it will be seen by the compiler as an Array of incompatible types ([Array<Int>, Array<Float>]).

; expected but <place your favourite keyword here> found

I'm trying to write a class for a scala project and I get this error in multiple places with keywords such as class, def, while.
It happens in places like this:
var continue = true
while (continue) {
[..]
}
And I'm sure the error is not there since when I isolate that code in another class it doesn't give me any error.
Could you please give me a rule of thumb for such errors? Where should I find them? are there some common syntactic errors elsewhere when this happens?
It sounds like you're using reserved keywords as variable names. "Continue", for instance, is a Java keyword.
You probably don't have parentheses or braces matched somewhere, and the compiler can't tell until it hits a structure that looks like the one you showed.
The other possibility is that Scala sometimes has trouble distinguishing between the end of a statement with a new one on the next line, and a multi-line statement. In that case, just drop the ; at the end of the first line and see if the compiler's happy. (This doesn't seem like it fits your case, as Scala should be able to tell that nothing should come after true, and that you're done assigning a variable.)
Can you let us know what this code is inside? Scala expects "expressions" i.e. things that resolve to a particular value/type. In the case of "var continue = true", this does not evaluate to a value, so it cannot be at the end of an expression (i.e. inside an if-expression or match-expression or function block).
i.e.
def foo() = {
var continue = true
while (continue) {
[..]
}
}
This is a problem, as the function block is an expression and needs to have an (ignored?) return value, i.e.
def foo() = {
var continue = true
while (continue) {
[..]
}
()
}
() => a value representing the "Unit" type.
I get this error when I forget to put an = sign after a function definition:
def function(val: String):Boolean {
// Some stuff
}