vshaxe icon indicating copy to clipboard operation
vshaxe copied to clipboard

No completion for generated types

Open object71 opened this issue 3 years ago • 1 comments

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

image

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:

/src/opengl/macros/OpenGLTypeBuildMacro.hx

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
}

/src/opengl/OpenGLContext.hx

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);

    }
}

/compile.hxml

--class-path src
--dce no

opengl.OpenGLContext

--each

--cpp bin/cpp
--library hxcpp

--next

--xml bin/types.xml

/completion.hxml

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
}

/res/gl.xml

Too big to fit in here

object71 avatar Jun 12 '21 17:06 object71

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:

  1. 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
  1. 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.
 }
}
  1. 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.

onehundredfeet avatar Feb 18 '22 07:02 onehundredfeet