Including one .linq file inside another - please comment

edited June 13
I've just written a proposal for an upcoming new feature - referencing .linq files from other queries:
https://www.linqpad.net/LinqReference.aspx

Please let me know what you think!

Comments

  • edited May 29
    Can you make the link to this thread absolute? It's now referring to https://www.linqpad.net/forum.linqpad.net/..

    Any thoughts about sharing queryies using Upload to instant share function? Currently queries referencing My Extensions are not runnable stand alone. Perhaps a little warning dialog "It looks like you're referencing another query... which will not be included in the uploaded file" with "Do not show this again" would be enough, both for referenced .linq files as well as My Extensions.
  • Will the include work for extension methods?
  • nescafe: thanks, the link is now fixed. A warning would be a good idea. It might even be possible to merge the queries, although there are edge cases that could cause this to fail.
  • user: there are no special restrictions on the kind of code that referenced queries can include, so classes that define extension methods are fine.

    If you were to reference several queries that all defined extension methods in a class with the same name (e.g., "Extensions"), you'd need to include the 'partial' keyword to avoid a collision.
  • edited May 31
    Given this 'The F12 shortcut ("go to definition") will also work with symbols defined in a reference query.' can My Extensions references also be made to work with F12 pulling up the source in My Extensions instead of decompiling?

    Lack of nested references will hurt but I will take the 80/20 rule any day on this.
  • My initial use case for this was a project with multiple queries against a complex set of CSV files. The (copied and pasted) base query defines sets of variables as LINQ queries that convert and standardize the data, which are then used in the other queries.

    How would this method of referencing a query work with trying to initialize lots of (query) global variables?
  • edited June 1
    Supporting F12 with My Extension functions could end up being tricky but I'll look into it. I don't think there's any Roslyn support for this because My Extensions is compiled to a DLL.

    Yes, it would work well in your CSV scenario. You'd declare your CSV variables as fields in the query, and populate them either with field initializers or in the OnStart() hook method.
  • I don't think that would work then - they use (lots of) anonymous types, so they are declared var?
  • While they are barely documented, don't CSX files expect recursive #load to work?
  • Is your query of type statements or program?
  • Originally they were of type statements, but since #region doesn't work in statements, the "base" query is of type program just to use #region, but I copy only the body of main and put it at the top of main in the child queries.
  • Check out the LINQPad 6 preview:

    forum.linqpad.net/discussion/1877/linqpad-6-for-net-core-3-preview-now-available

    It now supports the #load directive, and should work well in your scenario.
  • Unfortunately, my queries heavily use the CSV driver, and it looks like no external drivers are available for LINQPad 6 yet. It seems like LINQPad 5 will never add what I want, and LINQPad 6 won't be usable for me until next year, so I will wait.
  • Am I correct that this is only supported for C# ? Got it working on C# and it is a nice feature, but does not appear to work on F#. The FSharp compiler complains because the #load directive is specific to the FSharp Interactive tool.
    Is there an F# way ?
  • Yes, unfortunately it's C#-only for now. It would be a big job to get it working well in F#. For one, it relies on partial classes to minimize the performance hit to autocompletion and tooling.
  • Would this coming to LINQPad 5 as well or is this going to be 6 only?

  • LINQPad 6 only. It required some major refactoring.
  • I believe I found a bug:

    With the following two files, running 2.linq produces the following error:

    1.linq at line 11 (Ctrl+F11 to open): CS0246 The type or namespace name 'Something' could not be found
    1.linq

    void Main()
    {

    }

    public class Something {

    }

    public static class Boogers {
    public static void Test(this Something something) {
    something.Dump();
    }
    }
    2.linq

    #load ".\1.linq"

    void Main()
    {
    }
    If I change the extension method parameter to `this string something` instead of `this Something something`, the error goes away.

    So it seems there's a problem using reference types in extension methods?
  • Thanks for reporting. I overlooked adding the automatic import directive to #load-ed queries (static global::UserQuery). This is easy to fix, so it will make the next build.
  • edited September 16
    Are scripts loaded recursively?

    Meaning, if I load a script that itself has a load as well, will this work? I'm trying to create a series of scripts similar in structure to javascript modules and it doesn't seem to load beyond the first script.

    A.linq:
    #load ".\B"
    void Main()
    {
        MethodB();
    }
    B.linq:
    #load ".\C"
    void MethodB()
    {
        MethodC();
    }
    C.linq:
    void MethodC()
    {
    }
    Attempting to run A.linq, I would get an error along the lines of:

    Error in ...\B.linq at line 4: CS0103 The name 'MethodC' does not exist in the current context


    This applies to all methods and types (with varying error messages).

    A "workaround" I've found for now is to load all scripts depended on in the main script which I would rather not have to do (there's a lot of scripts).
  • Yes, that's a deliberate limitation, to simplify tooling and ensure good performance. Recursive #load-ing would be simple for me to enable, but making it work well would be a fairly big project.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!