nemerle icon indicating copy to clipboard operation
nemerle copied to clipboard

Type defined in an assembly level macro is not seen by VS integration

Open vasily-kirichenko opened this issue 9 years ago • 9 comments

...until VS is restarted.

[MacroUsage (MacroPhase.BeforeInheritance, MacroTargets.Assembly)]
public macro Yaml(name: PExpr, text: PExpr)
{
    def typer = Macros.ImplicitCTX();
    YamlImpl.Transform(typer, name, text);
}

module YamlImpl {
    public Transform(typer: Typer, typeName: PExpr, text: PExpr): PExpr {
        match (typeName, text) {
        | (<[ $(PExpr.Ref(typeName)) ]>, <[ $(PExpr.Literal(Literal.String(text))) ]>) => { 
            def builder = typer.Env.Define(<[ decl:
                public class $typeName {
                }
                ]>);

            builder.Compile();

            <[]>
          }
        | _ => Message.FatalError($"Name must be a symbol and text must be a string, but got $(typeName.GetType().ToString()), $(text.ToString())")
        }
    }
}

Look:

1

Is it a know issue? Maybe there's a key binding to refresh the VS integration without restarting VS?

vasily-kirichenko avatar Jan 12 '16 10:01 vasily-kirichenko

To force refresh autocomplete press Shift+Alt+R.

Oh, great, it works! :+1:

It's a major usability issue though, so I think it should be not closed.

vasily-kirichenko avatar Jan 12 '16 10:01 vasily-kirichenko

Try supply correct location to TypeBuilder with locate macro:

Util.locate(typeName.Location,
{
  def builder = typer.Env.Define(<[ decl:
                public class $typeName {
                }
                ]>);
            builder.Compile();
});

@someone-with-default-username I added Util.locate, but nothing's changed. What it's supposed to do?

vasily-kirichenko avatar Jan 12 '16 11:01 vasily-kirichenko

It fixes naviagation to definition via F12.

In general architecure of custom type definitions should be based on your own file type. Your macro should parse code from such files and create type builders etc.

It fixes naviagation to definition via F12.

Oh, yes, F12 works :) Cool.

In general architecure of custom type definitions should be based on your own file type. Your macro should parse code from such files and create type builders etc.

Mm. Cannot fully understand you. Do you mean that my macro should accept a file name, than read it, parse and generate types from it? Or you are talking about different things?

vasily-kirichenko avatar Jan 12 '16 12:01 vasily-kirichenko

Do you mean that my macro should accept a file name, than read it, parse and generate types from it?

In a some way. Currently there is no direct and simple way to make custom syntax plugins in compiler, but it has some helper API.

First of all - IParser - handles custom file extensions. Look at this stub implementation: https://github.com/JetBrains/Nitra/blob/master/Nitra/Nitra.Compiler/Integration/NitraParser.n It turns source file into assembly level macro invokation.

NitraSource macro declarations are here (very simple): https://github.com/JetBrains/Nitra/blob/master/Nitra/Nitra.Compiler/Macros/Macros.n

All actual work done in NitraSourceImpl type: https://github.com/JetBrains/Nitra/blob/master/Nitra/Nitra.Compiler/NitraSource.n Important thing is SubscribeSourceChangedWithCounter method - is subscribes on changes from IDE.

Hm. Interesting. But I'm trying to do a quite different thing: generate types from a non structured source, which can be anything: a json/xml/yaml literal or file, DB of some sort, discoverable web service etc. It's called "type provider" in F#. Look:

type MyService = Service<"http://service.org/foo?get=2">

let x = MyService.Operation1.Foo.Bar  // <-- it's already called the service and generate types

or

type MyJson = Json<"foo: { bar: 1 }">
let x = MyJson.Load("c:\\big.json").foo.bar // it's of type int

So the idea is that you give a TP a "sample" of untyped data and it generated types based on it. Then, at runtime, you can load other data of same shape and get typed access to it.

vasily-kirichenko avatar Jan 14 '16 11:01 vasily-kirichenko

We are doing similar in NemerleWeb. We generate classes from javascript. It is not a technical problem to do the same as in F#.

NN--- avatar Jan 14 '16 15:01 NN---