@@ -247,7 +247,8 @@ public ComponentDirectiveVisitor(string filePath, IReadOnlyList<TagHelperDescrip
247247 {
248248 // If this is a child content tag helper, we want to add it if it's original type is in scope.
249249 // E.g, if the type name is `Test.MyComponent.ChildContent`, we want to add it if `Test.MyComponent` is in scope.
250- TrySplitNamespaceAndType ( typeName , out typeName , out var _ ) ;
250+ TrySplitNamespaceAndType ( typeName , out var typeNameTextSpan , out var _ ) ;
251+ typeName = GetTextSpanContent ( typeNameTextSpan , typeName ) ;
251252 }
252253
253254 if ( currentNamespace != null && IsTypeInScope ( typeName , currentNamespace ) )
@@ -336,7 +337,8 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node)
336337 {
337338 // If this is a child content tag helper, we want to add it if it's original type is in scope of the given namespace.
338339 // E.g, if the type name is `Test.MyComponent.ChildContent`, we want to add it if `Test.MyComponent` is in this namespace.
339- TrySplitNamespaceAndType ( typeName , out typeName , out var _ ) ;
340+ TrySplitNamespaceAndType ( typeName , out var typeNameTextSpan , out var _ ) ;
341+ typeName = GetTextSpanContent ( typeNameTextSpan , typeName ) ;
340342 }
341343 if ( typeName != null && IsTypeInNamespace ( typeName , @namespace ) )
342344 {
@@ -350,13 +352,13 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node)
350352
351353 internal static bool IsTypeInNamespace ( string typeName , string @namespace )
352354 {
353- if ( ! TrySplitNamespaceAndType ( typeName , out var typeNamespace , out var _ ) || typeNamespace == string . Empty )
355+ if ( ! TrySplitNamespaceAndType ( typeName , out var typeNamespace , out var _ ) || typeNamespace . Length == 0 )
354356 {
355357 // Either the typeName is not the full type name or this type is at the top level.
356358 return true ;
357359 }
358360
359- return typeNamespace . Equals ( @namespace , StringComparison . Ordinal ) ;
361+ return @namespace . Length == typeNamespace . Length && 0 == string . CompareOrdinal ( typeName , typeNamespace . Start , @namespace , 0 , @namespace . Length ) ;
360362 }
361363
362364 // Check if the given type is already in scope given the namespace of the current document.
@@ -366,12 +368,13 @@ internal static bool IsTypeInNamespace(string typeName, string @namespace)
366368 // Whereas `MyComponents.SomethingElse.OtherComponent` is not in scope.
367369 internal static bool IsTypeInScope ( string typeName , string currentNamespace )
368370 {
369- if ( ! TrySplitNamespaceAndType ( typeName , out var typeNamespace , out var _ ) || typeNamespace == string . Empty )
371+ if ( ! TrySplitNamespaceAndType ( typeName , out var typeNamespaceTextSpan , out var _ ) || typeNamespaceTextSpan . Length == 0 )
370372 {
371373 // Either the typeName is not the full type name or this type is at the top level.
372374 return true ;
373375 }
374376
377+ var typeNamespace = GetTextSpanContent ( typeNamespaceTextSpan , typeName ) ;
375378 var typeNamespaceSegments = typeNamespace . Split ( NamespaceSeparators , StringSplitOptions . RemoveEmptyEntries ) ;
376379 var currentNamespaceSegments = currentNamespace . Split ( NamespaceSeparators , StringSplitOptions . RemoveEmptyEntries ) ;
377380 if ( typeNamespaceSegments . Length > currentNamespaceSegments . Length )
@@ -399,21 +402,23 @@ internal static bool IsTagHelperFromMangledClass(TagHelperDescriptor tagHelper)
399402 {
400403 // If this is a child content tag helper, we want to look at it's original type.
401404 // E.g, if the type name is `Test.__generated__MyComponent.ChildContent`, we want to look at `Test.__generated__MyComponent`.
402- TrySplitNamespaceAndType ( typeName , out typeName , out var _ ) ;
405+ TrySplitNamespaceAndType ( typeName , out var typeNameTextSpan , out var _ ) ;
406+ typeName = GetTextSpanContent ( typeNameTextSpan , typeName ) ;
403407 }
404- if ( ! TrySplitNamespaceAndType ( typeName , out var _ , out var className ) )
408+ if ( ! TrySplitNamespaceAndType ( typeName , out var _ , out var classNameTextSpan ) )
405409 {
406410 return false ;
407411 }
412+ var className = GetTextSpanContent ( classNameTextSpan , typeName ) ;
408413
409414 return ComponentMetadata . IsMangledClass ( className ) ;
410415 }
411416
412417 // Internal for testing.
413- internal static bool TrySplitNamespaceAndType ( string fullTypeName , out string @namespace , out string typeName )
418+ internal static bool TrySplitNamespaceAndType ( string fullTypeName , out TextSpan @namespace , out TextSpan typeName )
414419 {
415- @namespace = string . Empty ;
416- typeName = string . Empty ;
420+ @namespace = default ;
421+ typeName = default ;
417422
418423 if ( string . IsNullOrEmpty ( fullTypeName ) )
419424 {
@@ -442,20 +447,26 @@ internal static bool TrySplitNamespaceAndType(string fullTypeName, out string @n
442447
443448 if ( splitLocation == - 1 )
444449 {
445- typeName = fullTypeName ;
450+ typeName = new TextSpan ( 0 , fullTypeName . Length ) ;
446451 return true ;
447452 }
448453
449- @namespace = fullTypeName . Substring ( 0 , splitLocation ) ;
454+ @namespace = new TextSpan ( 0 , splitLocation ) ;
450455
451456 var typeNameStartLocation = splitLocation + 1 ;
452457 if ( typeNameStartLocation < fullTypeName . Length )
453458 {
454- typeName = fullTypeName . Substring ( typeNameStartLocation , fullTypeName . Length - typeNameStartLocation ) ;
459+ typeName = new TextSpan ( typeNameStartLocation , fullTypeName . Length - typeNameStartLocation ) ;
455460 }
456461
457462 return true ;
458463 }
464+
465+ // Internal for testing.
466+ internal static string GetTextSpanContent ( TextSpan textSpan , string s )
467+ {
468+ return s . Substring ( textSpan . Start , textSpan . Length ) ;
469+ }
459470 }
460471 }
461472}
0 commit comments