
Say I have a file like this:
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Packages>
<# foreach(var fact in RootNode.Facts.Where(item => !string.IsNullOrEmpty(item.GetTag("AutogenerateEtl")))) { #>
<Package Name="LoadFact<#=fact.SsisSafeName#>" ConstraintMode="Linear">
<Variables>
<Variable Name="LoggingJobId" DataType="String">"Temp"</Variable>
<Variable Name="StartDate" DataType="DateTime">01/01/2011</Variable>
</Variables>
<Tasks>
<StartLoggingJob Name="Start Logging" JobName="LoadFact<#=fact.SsisSafeName#>" LoggingConnectionName="Logging" LoggingJobVariableName="LoggingJobId"></StartLoggingJob>
<CloneTableSchema Name="Ensure Process Table Exists" LoggingConnectionName="Logging" LoggingJobVariableName="LoggingJobId" SourceConnectionName="DataWarehouse" TargetConnectionName="DataWarehouse">
<SourceTable TableName="<#=fact.ScopedName#>"></SourceTable>
<ExternalTargetTable Table="<#=fact.GetTag("ProcessTable")#>"></ExternalTargetTable>
</CloneTableSchema>
<ExecuteSQL Name="Truncate Process Table" ConnectionName="DataWarehouse">
<DirectInput>TRUNCATE TABLE <#=fact.GetTag("ProcessTable")#></DirectInput>
</ExecuteSQL>
</Tasks>
</Package>
<# } #>
</Packages>
</Biml>
The <# and <#= tags are language transitions, using the Syntax Editor's language transition logic. We have intellisense and quick info working really well for this, but have hit a snag.
When I type a < in the line directly above the ExecuteSQL tag, I should see an intellisense pop-up but I don't. I know this is because my XmlContext has an incorrect hierarchy of: Biml / Packages / Package / Tasks / CloneTableSchema / ExternalTargetTable
I also know that when I go into the ExternalTargetTable element and remove the double quotes around the ProcessTable string, intellisense starts working again. Furthermore, if I add at least a single letter after the end parenthesis, intellisense works and the element hierarchy is correct.
My suspicion is there's an issue where the end quote within the <#=fact.GetTag("ProcessTable")#> nugget is being treated as an end attribute value, or at least not being processed corectly.
After reviewing the lexical transition sample in the Sample Browser, I believe the issue has to do with how I'm creating the lexical transition. Our methods to set up lexical transitions are as follows:
private void SetupLexicalTransitions()
{
var bimlScriptClassificationType = CreateBimlScriptClassificationType();
var dotNetLexer = _dotNetSyntaxLanguageBase.GetLexer() as IMergableLexer;
var bimlLexer = _xmlLexer as DynamicLexer;
var directiveLexer = _bimlScriptDirectiveSyntaxLanguage.GetLexer() as DynamicLexer;
if (bimlLexer != null && dotNetLexer != null && directiveLexer != null)
{
directiveLexer.Key = "BimlScriptDirective";
using (IDisposable batch = bimlLexer.CreateChangeBatch())
{
var codeNuggetLexicalState = new DynamicLexicalState(0, "BimlScriptCodeNugget") { DefaultTokenKey = "BimlScriptCodeNuggetText" };
bimlLexer.LexicalStates.Add(codeNuggetLexicalState);
// Insert the transition lexical state at the beginning of the parent language's default state's child states list so that it has top matching priority
bimlLexer.DefaultLexicalState.ChildLexicalStates.Insert(0, codeNuggetLexicalState);
InsertBimlScriptLexicalState(bimlLexer, codeNuggetLexicalState, true);
// Create the lexical scope for the transition lexical state
var codeNuggetLexicalScope = new DynamicLexicalScope();
codeNuggetLexicalScope.IsAncestorEndScopeCheckEnabled = false;
codeNuggetLexicalState.LexicalScopes.Add(codeNuggetLexicalScope);
codeNuggetLexicalScope.StartLexicalPatternGroup = new DynamicLexicalPatternGroup(DynamicLexicalPatternType.Explicit, "BimlScriptStartDelimiter", bimlScriptClassificationType);
codeNuggetLexicalScope.StartLexicalPatternGroup.Patterns.Add(new DynamicLexicalPattern(@"<#="));
codeNuggetLexicalScope.StartLexicalPatternGroup.Patterns.Add(new DynamicLexicalPattern(@"<#+"));
codeNuggetLexicalScope.StartLexicalPatternGroup.Patterns.Add(new DynamicLexicalPattern(@"<#"));
codeNuggetLexicalScope.EndLexicalPatternGroup = new DynamicLexicalPatternGroup(DynamicLexicalPatternType.Explicit, "BimlScriptEndDelimiter", bimlScriptClassificationType);
codeNuggetLexicalScope.EndLexicalPatternGroup.Patterns.Add(new DynamicLexicalPattern(@"#>"));
// Set up a direct transition on the lexical state so that when it is entered, it will transition directly to the child language's default lexical state
codeNuggetLexicalState.Transition = new LexicalStateTransition(_dotNetSyntaxLanguageBase, dotNetLexer.DefaultLexicalState, null);
var directiveLexicalState = new DynamicLexicalState(0, "BimlScriptDirective") { DefaultTokenKey = "BimlScriptDirectiveText" };
bimlLexer.LexicalStates.Add(directiveLexicalState);
// Insert the transition lexical state at the beginning of the parent language's default state's child states list so that it has top matching priority
bimlLexer.DefaultLexicalState.ChildLexicalStates.Insert(0, directiveLexicalState);
InsertBimlScriptLexicalState(bimlLexer, directiveLexicalState, false);
// Create the lexical scope for the transition lexical state
var directiveLexicalScope = new DynamicLexicalScope();
directiveLexicalScope.IsAncestorEndScopeCheckEnabled = false;
directiveLexicalState.LexicalScopes.Add(directiveLexicalScope);
directiveLexicalScope.StartLexicalPatternGroup = new DynamicLexicalPatternGroup(DynamicLexicalPatternType.Explicit, "BimlScriptDirectiveStartDelimiter", bimlScriptClassificationType);
directiveLexicalScope.StartLexicalPatternGroup.Patterns.Add(new DynamicLexicalPattern(@"<#@"));
directiveLexicalScope.EndLexicalPatternGroup = new DynamicLexicalPatternGroup(DynamicLexicalPatternType.Explicit, "BimlScriptDirectiveEndDelimiter", bimlScriptClassificationType);
directiveLexicalScope.EndLexicalPatternGroup.Patterns.Add(new DynamicLexicalPattern(@"#>"));
// Set up a direct transition on the lexical state so that when it is entered, it will transition directly to the child language's default lexical state
directiveLexicalState.Transition = new LexicalStateTransition(_bimlScriptDirectiveSyntaxLanguage, directiveLexer.DefaultLexicalState, null);
}
}
}
private static void InsertBimlScriptLexicalState(DynamicLexer bimlLexer, DynamicLexicalState dynamicLexicalState, bool isCodeNugget)
{
foreach (var lexicalState in bimlLexer.LexicalStates)
{
var isAttributeValue = lexicalState.DefaultClassificationType == new XmlClassificationTypeProvider().XmlAttributeValue;
var isCodeNuggetInStartTag = isCodeNugget && lexicalState.Key == "StartTag";
if (isAttributeValue || isCodeNuggetInStartTag)
{
lexicalState.ChildLexicalStates.Insert(0, dynamicLexicalState);
if (isAttributeValue)
{
// Add < to the lexicalState's lexicalPattern so that, within attribute values, we recognize < as a delimiter.
if (lexicalState.LexicalPatternGroups != null && lexicalState.LexicalPatternGroups.Count > 0)
{
var lexicalPatternGroup = lexicalState.LexicalPatternGroups[0];
if (lexicalPatternGroup.Patterns != null && lexicalPatternGroup.Patterns.Count > 0)
{
var lexicalPattern = lexicalPatternGroup.Patterns[0];
if (lexicalPattern != null)
{
lexicalPattern.Pattern = "[^\\\"\\>\\<]+";
}
}
}
}
}
}
}
I'm somewhat convinced our lexical state logic within the CreateBatch is where the problem lies. Assuming you agree with my diagnosis, do you see if there's a bug in the lexical transition logic that's causing this issue? Could a different problem cause these symptoms?
Note that I tried this with the latest WPF Studio and the issue still reproes.
Any help or thoughts would be greatly appreciated.
Thanks,
-Craig
[Modified 12 years ago]