Question about User Code Regions

Posts   
 
    
Cadmium avatar
Cadmium
User
Posts: 153
Joined: 19-Sep-2003
# Posted on: 14-Aug-2006 23:55:10   

I'm sure there's a good reason for this, but why exactly do user code regions rely on a leading tab? To me it seems to make using the region a bit fragile since a minor mis-step in vs and the tab is now replaced by spaces and my code disapeers the next generation.

Other than that, I have to admit I'm having some unpredictable behavior with user code region data disapearing after minor updates to a template. I haven't been able to come up with 100% reproducable case or else I would submit a bug report.

But for now I would love to know the reasoning behind the leading tabs simple_smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-Aug-2006 09:41:26   

It doesn't rely on a tab. This is the regex: [ \t]*('+|/{2,}) __LLBLGENPRO_USER_CODE_REGION_START (?<regionName>\w+)[ \t]\r\n(.\r\n)?[ \t]('+|/{2,}) __LLBLGENPRO_USER_CODE_REGION_END

As you can see it matches with 0 or more tabs or spaces before the comments begin.

Frans Bouma | Lead developer LLBLGen Pro
arschr
User
Posts: 893
Joined: 14-Dec-2003
# Posted on: 15-Aug-2006 13:37:52   

As you can see it matches with 0 or more tabs or spaces before the comments begin.

I don't see the 0 or more spaces part! maybe the \t's shouls be \s's?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-Aug-2006 15:02:42   

arschr wrote:

As you can see it matches with 0 or more tabs or spaces before the comments begin.

I don't see the 0 or more spaces part! maybe the \t's shouls be \s's?

[ \t]*

means: a space or a tab 0 or more times. simple_smile '*' means 0 or more times, [] are group of characters. There's a space and a tab character in there.

Frans Bouma | Lead developer LLBLGen Pro
Cadmium avatar
Cadmium
User
Posts: 153
Joined: 19-Sep-2003
# Posted on: 15-Aug-2006 17:21:34   

So if it's optional, why test at all? simple_smile

Also, try this in a template


    <%=DotNetTemplateEngine.GetUserCodeRegion("TEST", "//") %>

And generate the code a few times. The first line will work it's way across the file, forever...


                                    // __LLBLGENPRO_USER_CODE_REGION_START TEST
    // __LLBLGENPRO_USER_CODE_REGION_END

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-Aug-2006 17:44:26   

Cadmium wrote:

So if it's optional, why test at all? simple_smile

Also, try this in a template


    <%=DotNetTemplateEngine.GetUserCodeRegion("TEST", "//") %>

Place that at the start of the line instead. The indentation you see is increased with the indentation of the statement above.

It tests on them so the whitespace in front of the comment is also included in the MATCH of the regexp. If not, the code would be placed without the indenting inside the target code.

Frans Bouma | Lead developer LLBLGen Pro
arschr
User
Posts: 893
Joined: 14-Dec-2003
# Posted on: 15-Aug-2006 18:23:08   

[ \t]*

means: a space or a tab 0 or more times. Regular Smiley '*' means 0 or more times, [] are group of characters. There's a space and a tab character in there.

Not in any regular expression syntax I've ever used. disappointed

Have you tested it to see if you are matching spaces?

From the dot net help

\t Matches a tab \u0009.

\s Matches any white-space character. Equivalent to the Unicode character categories [\f\n\r\t\v\x85\p{Z}]. If ECMAScript-compliant behavior is specified with the ECMAScript option, \s is equivalent to [ \f\n\r\t\v].

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-Aug-2006 18:45:27   

arschr wrote:

[ \t]*

means: a space or a tab 0 or more times. Regular Smiley '*' means 0 or more times, [] are group of characters. There's a space and a tab character in there.

Not in any regular expression syntax I've ever used. disappointed

I only checked the .NET regex syntax wink

Have you tested it to see if you are matching spaces?

yes. Doesn't it match spaces with your code?

From the dot net help

\t Matches a tab \u0009.

\s Matches any white-space character. Equivalent to the Unicode character categories [\f\n\r\t\v\x85\p{Z}]. If ECMAScript-compliant behavior is specified with the ECMAScript option, \s is equivalent to [ \f\n\r\t\v].

I can't use \s because it will match a crlf as well, and I don't want to match that one.

Frans Bouma | Lead developer LLBLGen Pro
arschr
User
Posts: 893
Joined: 14-Dec-2003
# Posted on: 15-Aug-2006 19:08:17   

I only checked the .NET regex syntax

That's where I quoted the help from.

yes. Doesn't it match spaces with your code?

Let me check with one of my regex workbenches .... No it matches tabs.

I can't use \s

Then maybe a [\t ]?

mikeg22
User
Posts: 411
Joined: 30-Jun-2005
# Posted on: 15-Aug-2006 19:33:28   

arschr wrote:

I only checked the .NET regex syntax

That's where I quoted the help from.

yes. Doesn't it match spaces with your code?

Let me check with one of my regex workbenches .... No it matches tabs.

I can't use \s

Then maybe a [\t ]?

[\t ]* should work...

JimFoye avatar
JimFoye
User
Posts: 656
Joined: 22-Jun-2004
# Posted on: 16-Aug-2006 03:07:23   

As should

\s*

right?

[edit] I know that grabs newlines, and just realize you may not want those here. Anyway, [ \t]* is certainly correct.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 16-Aug-2006 10:07:20   

.. and I use [ \t]* simple_smile

Frans Bouma | Lead developer LLBLGen Pro
jungans
User
Posts: 18
Joined: 23-Jul-2006
# Posted on: 17-Aug-2006 20:06:05   

lol

zulu
User
Posts: 50
Joined: 25-Aug-2008
# Posted on: 24-May-2009 00:45:23   

Otis wrote:

Cadmium wrote:

So if it's optional, why test at all? simple_smile

Also, try this in a template


    <%=DotNetTemplateEngine.GetUserCodeRegion("TEST", "//") %>

Place that at the start of the line instead. The indentation you see is increased with the indentation of the statement above.

It tests on them so the whitespace in front of the comment is also included in the MATCH of the regexp. If not, the code would be placed without the indenting inside the target code.

It doesn't work:

Using this template code (indentation is 2 tabs):

        
        Private Shared Sub InitializeDefaultSorter()
        <%= DotNetTemplateEngine.GetUserCodeRegion("InitializeDefaultSorter","'") %>
        End Sub

The 1st time code is generated like this:


        Private Shared Sub InitializeDefaultSorter()
            ' __LLBLGENPRO_USER_CODE_REGION_START InitializeDefaultSorter
    ' __LLBLGENPRO_USER_CODE_REGION_END
        End Sub

and 2nd time like this:


        Private Shared Sub InitializeDefaultSorter()
                            ' __LLBLGENPRO_USER_CODE_REGION_START InitializeDefaultSorter
    ' __LLBLGENPRO_USER_CODE_REGION_END
        End Sub

??

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 25-May-2009 10:44:22   

You didnt place <%= DotNetTemplateEngine.GetUserCodeRegion("InitializeDefaultSorter","'") %> at the start of the line as I said. The region is inserted at the spot of the statement, so AFTER the two tabs, as these belong to the text before the statement, which isn't parsed at all, it's seen as literal text.

So instead do:

        Private Shared Sub InitializeDefaultSorter()
<%= DotNetTemplateEngine.GetUserCodeRegion("InitializeDefaultSorter","'") %>
        End Sub

Frans Bouma | Lead developer LLBLGen Pro
zulu
User
Posts: 50
Joined: 25-Aug-2008
# Posted on: 27-May-2009 10:50:40   

Otis wrote:

You didnt place <%= DotNetTemplateEngine.GetUserCodeRegion("InitializeDefaultSorter","'") %> at the start of the line as I said. The region is inserted at the spot of the statement, so AFTER the two tabs, as these belong to the text before the statement, which isn't parsed at all, it's seen as literal text.

So instead do:

        Private Shared Sub InitializeDefaultSorter()
<%= DotNetTemplateEngine.GetUserCodeRegion("InitializeDefaultSorter","'") %>
        End Sub

Ok, sorry, my bad. simple_smile Like this it looks like it's working, with one exception: when the user code region is in the imports/using section of code. Since the previous statement is at the beginning of the line too, the user code region is indented by a single tab. Not a big deal I suppose, just an observation.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 27-May-2009 11:29:35   

zulu wrote:

Otis wrote:

You didnt place <%= DotNetTemplateEngine.GetUserCodeRegion("InitializeDefaultSorter","'") %> at the start of the line as I said. The region is inserted at the spot of the statement, so AFTER the two tabs, as these belong to the text before the statement, which isn't parsed at all, it's seen as literal text.

So instead do:

        Private Shared Sub InitializeDefaultSorter()
<%= DotNetTemplateEngine.GetUserCodeRegion("InitializeDefaultSorter","'") %>
        End Sub

Ok, sorry, my bad. simple_smile Like this it looks like it's working, with one exception: when the user code region is in the imports/using section of code. Since the previous statement is at the beginning of the line too, the user code region is indented by a single tab. Not a big deal I suppose, just an observation.

Could you give a quote of such a statement please?

Frans Bouma | Lead developer LLBLGen Pro
zulu
User
Posts: 50
Joined: 25-Aug-2008
# Posted on: 27-May-2009 13:25:26   

Sure.

In one of my templates I have:

Imports SD.LLBLGen.Pro.ORMSupportClasses

<%= DotNetTemplateEngine.GetUserCodeRegion("AdditionalImports","'") %>

And it gets generated as:

Imports SD.LLBLGen.Pro.ORMSupportClasses

    ' __LLBLGENPRO_USER_CODE_REGION_START AdditionalImports
    ' __LLBLGENPRO_USER_CODE_REGION_END

As you said:

Place that at the start of the line instead. The indentation you see is increased with the indentation of the statement above.

and that's exactly what happens in this case too, but it shouldn't because the user code region in this case should not be indented with respect to the statement above.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 27-May-2009 13:31:24   

Interesting. Though I've to check whether the file itself contains this data right after the code generation step or that the VB.NET editor corrects this after the file has been loaded (as it does that for some constructs)

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 29-May-2009 13:59:06   

Indeed, I can reproduce this.


Imports System
    ' __LLBLGENPRO_USER_CODE_REGION_START AdditionalImports
    ' __LLBLGENPRO_USER_CODE_REGION_END


Public Class Foo

End Class

Looking at the code which actually produces the output:


Imports SD.LLBLGen.Pro.GeneratorCore
Imports SD.LLBLGen.Pro.ApplicationCore
Imports SD.LLBLGen.Pro.ApplicationCore.Tasks
Imports System
Imports SD.LLBLGen.Pro.ApplicationCore.TypedViews
Imports SD.LLBLGen.Pro.LptParser
Imports System.Collections
Imports SD.LLBLGen.Pro.ApplicationCore.Entities
Imports Microsoft.VisualBasic
Imports SD.LLBLGen.Pro.ApplicationCore.TypedLists
Imports SD.LLBLGen.Pro.ApplicationCore.StoredProcedures
Imports System.Collections.Generic
Imports System.ComponentModel
Imports SD.LLBLGen.Pro.DBDriverCore
Imports SD.LLBLGen.Pro.ApplicationCore.Templates
Imports System.IO


Public Class SD_UserRegion
    Implements ITemplateClass
    Private __outputWriter As StreamWriter
    Private _executingGenerator As IGenerator
    Private _parameters As Dictionary(Of String, TaskParameter)
    Private _activeObject As Object

    Public Sub New ()
        __outputWriter=Nothing
        _executingGenerator=Nothing
        _parameters=Nothing
        _activeObject=Nothing
    End Sub

    Private Sub __ScriptCode()
        __outputWriter.Write("Imports System" &  vbCrLf )
__outputWriter.Write( DotNetTemplateEngine.GetUserCodeRegion("AdditionalImports","'") )
        __outputWriter.Write( vbCrLf  &  vbCrLf  & "Public Class Foo" &  vbCrLf  &  vbCrLf  & "End Class")
    End Sub


    Public Sub ___RUN(executingGenerator As IGenerator, parameters As Dictionary(Of String, TaskParameter), outputWriter As StreamWriter, activeObject As Object) Implements ITemplateClass.___RUN
        __outputWriter = outputWriter
        _parameters = parameters
        _executingGenerator=executingGenerator
        _activeObject=activeObject
        __ScriptCode()
    End Sub

End Class

It shows that there's no preceding tab in the output. So something's wrong in the GetUserCodeRegion method. Looking into it

(edit) The code always prefixes the emitted region with a tab. This has been this way since forever. There's no info why this is done this way, I'm sorry (change logs didn't reveal why this was done this way, it's been this way since the beginning of this method, which was first added in 1.0.2005.1). It's been somewhat of a struggle to make the output always in the form as expected, and this tab is overlooked.

I'll add a change request for v3, so it will get re-examined why it isn't emitting the output without a tab.

Frans Bouma | Lead developer LLBLGen Pro
zulu
User
Posts: 50
Joined: 25-Aug-2008
# Posted on: 31-May-2009 21:32:40   

Great.. thanks for looking into it. if you manage to fix it in v3 it will be a plus. :-)

Thanks