vshaxe
vshaxe copied to clipboard
No completion for generated types
Hello, I get no autocompletion for generated types. I initially asked in the community forum for Haxe as it is also present in HaxeDevelop but I think it is more of an IDE issue to deal with: forum topic
The main problem is I don't get intellisense for typedefs/types that I generate with a macro. It is still working fine for generated fields of an existing class though.
I am providing the minimal reproduction:
I create a project with the following files:
package opengl.macros;
#if macro
import sys.io.File;
import haxe.macro.Expr;
import haxe.macro.Context;
#end
using OpenGLTypeBuildMacro.XmlParseExtenders;
class XmlParseExtenders {
public static function firstElementNamed(node:Xml, name:String):Xml {
return node.elementsNamed(name).first();
}
public static function hasElementNamed(node:Xml, name:String):Bool {
return node.firstElementNamed(name) != null;
}
public static function first(it:Iterator<Xml>):Xml {
if (it.hasNext()) {
return it.next();
}
return null;
}
}
class OpenGLTypeBuildMacro {
#if macro
public static function buildTypes() {
var glSpec = Xml.parse(File.getContent("./res/gl.xml"));
var typeGroup = glSpec.firstElementNamed("registry").firstElementNamed("types");
var types = typeGroup.elementsNamed("type");
for (type in types) {
if (!type.hasElementNamed("name")) {
continue;
}
var name = type.firstElementNamed("name");
var typeName = name.firstChild().toString();
var regexStartsWith = ~/^[A-Z].*/;
if (!regexStartsWith.match(typeName)) {
continue;
}
var definition:TypeDefinition = {
name: typeName,
pack: ["opengl"],
fields: [],
kind: TDAlias(macro:Int),
pos: Context.currentPos(),
doc: "String",
};
Context.defineType(definition);
}
}
public static function build():Array<Field> {
buildTypes();
var fields = Context.getBuildFields();
var newField = {
name: "GLVersion",
doc: null,
meta: [],
access: [APublic, AStatic],
kind: FVar(macro:String, macro "3.3"),
pos: Context.currentPos()
};
fields.push(newField);
return fields;
}
#end
}
package opengl;
@:build(opengl.macros.OpenGLTypeBuildMacro.build())
class OpenGLContext {
public function new() {
var t: GLint = 5; // There is hover information for GLint but there is no intellisense when I try to type "var t: GLi" that would autocomplete the type
trace(GLVersion); // GLVersion has normal intellisense suggestion
trace(t);
}
}
--class-path src
--dce no
opengl.OpenGLContext
--each
--cpp bin/cpp
--library hxcpp
--next
--xml bin/types.xml
opengl.OpenGLContext
settings.json (for vscode)
{
"haxeTestExplorer.testCommand": [
"${haxe}",
"test.hxml"
],
"haxe.enableServerView": true,
"haxe.buildCompletionCache": true,
"haxe.enableCompilationServer": true,
"haxe.enableCompletionCacheWarning": true,
"haxe.enableCodeLens": false,
"haxe.useLegacyCompletion": false,
"haxe.configurations": [
["--xml", "bin/types.xml", "--class-path", "src"],
["completion.hxml"]
],
"haxe.displayServer": {
"arguments": ["--verbose"]
},
"haxe.displayPort": "auto",
"haxe.enableDiagnostics": true
}
Too big to fit in here
I have been debugging this extensively on a few of my projects. There seems to be multiple invisible snags that will just cause the code completion to give up. I'm still mapping them all out but I've found a few:
- Exception handling on Context.resolveType or Context.getType. Overly aggressive exception handling for whatever reason seems to cause an issue. I have no clue as to why.
try x = Context.resolveType( t, p ) catch (e:String) { doMyTypeDefinition(); } // This seems to work
try x = Context.resolveType( t, p ) catch (e) { doMyTypeDefinition(); } // This seems to NOT work, likely because silently not catching the string because it's the wrong type (Exception instead of string), but no error actually appears anywhere.
try x = Context.resolveType( t, p ) catch (_) { doMyTypeDefinition(); } // This seems to NOT work, e is any class
- Sharing generated classes between modules. I work on an ECS that will automatically generate view classes when encountered in the compiler. In one path, it is generated when file A encounters it, in another path, B will encounter it.
When using Context.resolveType, I get some kind of hidden issue where the type is more related to the module. When I do a 'get' type in front of the resolve type, it finds the more universal or original one.
try x = Context.getType(t) catch(e:String) { // Requires knowledge of the packages & module paths
try x = Context.resolveType(t) catch (e:String) {
doGeneration(); // this seems to be more robust than just using resolve type.
}
}
- Type redefinition. It really seems to struggle with anytime a type is redefined in an unexpected situation. I'm currently trying to figure out why castle DB doesn't autocomplete anymore and I'm using trivial examples.