Skip to content

Commit dacb33d

Browse files
committed
C#: Adjust Roslyn workaround
1 parent 71ddd00 commit dacb33d

File tree

4 files changed

+52
-17
lines changed

4 files changed

+52
-17
lines changed

csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ protected override void Populate(TextWriter trapFile)
9090
var tts = (TupleTypeSyntax)syntax;
9191
var tt = (TupleType)type;
9292
Emit(trapFile, loc ?? syntax.GetLocation(), parent, type);
93-
tts.Elements.Zip(tt.TupleElements, (s, t) => Create(Context, s.Type, this, t.Type)).Enumerate();
93+
foreach (var (s, t) in tts.Elements.Zip(tt.TupleElements, (s, t) => (s, t?.Type)))
94+
{
95+
if (t is not null)
96+
Create(Context, s.Type, this, t);
97+
}
9498
return;
9599
case SyntaxKind.GenericName:
96100
Emit(trapFile, loc ?? syntax.GetLocation(), parent, type);

csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ private class TupleTypeFactory : CachedEntityFactory<INamedTypeSymbol, TupleType
2424

2525
private TupleType(Context cx, INamedTypeSymbol init) : base(cx, init)
2626
{
27-
tupleElementsLazy = new Lazy<Field[]>(() => Symbol.TupleElementsAdjusted().Select(t => Field.Create(cx, t)).ToArray());
27+
tupleElementsLazy = new Lazy<Field?[]>(() => Symbol.GetTupleElementsMaybeNull().Select(t => t is null ? null : Field.Create(cx, t)).ToArray());
2828
}
2929

3030
// All tuple types are "local types"
@@ -47,7 +47,10 @@ public override void Populate(TextWriter trapFile)
4747

4848
var index = 0;
4949
foreach (var element in TupleElements)
50-
trapFile.tuple_element(this, index++, element);
50+
{
51+
if (element is not null)
52+
trapFile.tuple_element(this, index++, element);
53+
}
5154

5255
// Note: symbol.Locations seems to be very inconsistent
5356
// about what locations are available for a tuple type.
@@ -56,9 +59,10 @@ public override void Populate(TextWriter trapFile)
5659
trapFile.type_location(this, Context.CreateLocation(l));
5760
}
5861

59-
private readonly Lazy<Field[]> tupleElementsLazy;
60-
public Field[] TupleElements => tupleElementsLazy.Value;
62+
private readonly Lazy<Field?[]> tupleElementsLazy;
63+
public Field?[] TupleElements => tupleElementsLazy.Value;
6164

62-
public override IEnumerable<Type> TypeMentions => TupleElements.Select(e => e.Type);
65+
public override IEnumerable<Type> TypeMentions =>
66+
TupleElements.OfType<Field>().Select(e => e.Type);
6367
}
6468
}

csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -283,20 +283,27 @@ private static void BuildFunctionPointerTypeId(this IFunctionPointerTypeSymbol f
283283
/// <summary>
284284
/// Workaround for a Roslyn bug: https://github.com/dotnet/roslyn/issues/53943
285285
/// </summary>
286-
public static IEnumerable<IFieldSymbol> TupleElementsAdjusted(this INamedTypeSymbol type) =>
287-
type.TupleElements.Where(f => f is not null && f.Type is not null);
286+
public static IEnumerable<IFieldSymbol?> GetTupleElementsMaybeNull(this INamedTypeSymbol type) =>
287+
type.TupleElements;
288288

289289
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
290290
{
291291
if (!constructUnderlyingTupleType && named.IsTupleType)
292292
{
293293
trapFile.Write('(');
294-
trapFile.BuildList(",", named.TupleElementsAdjusted(),
295-
f =>
294+
trapFile.BuildList(",", named.GetTupleElementsMaybeNull(),
295+
(i, f) =>
296296
{
297-
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
298-
trapFile.Write(":");
299-
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
297+
if (f is null)
298+
{
299+
trapFile.Write($"null({i})");
300+
}
301+
else
302+
{
303+
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
304+
trapFile.Write(":");
305+
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
306+
}
300307
}
301308
);
302309
trapFile.Write(")");
@@ -470,8 +477,14 @@ private static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, C
470477
trapFile.Write('(');
471478
trapFile.BuildList(
472479
",",
473-
namedType.TupleElementsAdjusted().Select(f => f.Type),
474-
t => t.BuildDisplayName(cx, trapFile));
480+
namedType.GetTupleElementsMaybeNull(),
481+
(i, f) =>
482+
{
483+
if (f is null)
484+
trapFile.Write($"null({i})");
485+
else
486+
f.Type.BuildDisplayName(cx, trapFile);
487+
});
475488
trapFile.Write(")");
476489
return;
477490
}

csharp/extractor/Semmle.Extraction/TrapExtensions.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,19 +232,33 @@ public static TextWriter AppendList<T>(this EscapingTextWriter trapFile, string
232232
/// <param name="items">The list of items.</param>
233233
/// <param name="action">The action on each item.</param>
234234
/// <returns>The original trap builder (fluent interface).</returns>
235-
public static T1 BuildList<T1, T2>(this T1 trapFile, string separator, IEnumerable<T2> items, Action<T2> action)
235+
public static T1 BuildList<T1, T2>(this T1 trapFile, string separator, IEnumerable<T2> items, Action<int, T2> action)
236236
where T1 : TextWriter
237237
{
238238
var first = true;
239+
var i = 0;
239240
foreach (var item in items)
240241
{
241242
if (first)
242243
first = false;
243244
else
244245
trapFile.Write(separator);
245-
action(item);
246+
action(i++, item);
246247
}
247248
return trapFile;
248249
}
250+
251+
/// <summary>
252+
/// Builds a trap builder using a separator and an action for each item in the list.
253+
/// </summary>
254+
/// <typeparam name="T">The type of the items.</typeparam>
255+
/// <param name="trapFile">The trap builder to append to.</param>
256+
/// <param name="separator">The separator string (e.g. ",")</param>
257+
/// <param name="items">The list of items.</param>
258+
/// <param name="action">The action on each item.</param>
259+
/// <returns>The original trap builder (fluent interface).</returns>
260+
public static T1 BuildList<T1, T2>(this T1 trapFile, string separator, IEnumerable<T2> items, Action<T2> action)
261+
where T1 : TextWriter =>
262+
trapFile.BuildList(separator, items, (_, item) => action(item));
249263
}
250264
}

0 commit comments

Comments
 (0)