Merge pull request #4055 from tamasvajk/feature/partial-methods

C#: Add body to partial methods
This commit is contained in:
Tom Hvitved
2020-08-20 10:14:56 +02:00
committed by GitHub
11 changed files with 69 additions and 22 deletions

3
csharp/.gitignore vendored
View File

@@ -10,4 +10,5 @@ csharp.log
**/bin/Release
*.tlog
.vs
*.user
*.user
.vscode/launch.json

View File

@@ -80,7 +80,7 @@ namespace Semmle.Extraction.CSharp.Entities
else
Expression.Create(Context, expr, this, 0);
Context.NumberOfLines(trapFile, symbol, this);
Context.NumberOfLines(trapFile, BodyDeclaringSymbol, this);
});
}
@@ -126,7 +126,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
trapFile.Write('<');
// Encode the nullability of the type arguments in the label.
// Type arguments with different nullability can result in
// Type arguments with different nullability can result in
// a constructed method with different nullability of its parameters and return type,
// so we need to create a distinct database entity for it.
trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); trapFile.Write((int)ta.Nullability); });

View File

@@ -13,6 +13,8 @@ namespace Semmle.Extraction.CSharp.Entities
public override string Name => symbol.GetName();
protected override IMethodSymbol BodyDeclaringSymbol => symbol.PartialImplementationPart ?? symbol;
public IMethodSymbol SourceDeclaration
{
get

View File

@@ -95,14 +95,15 @@ namespace Semmle.Extraction.CSharp.Entities
Context.BindComments(this, FullLocation);
}
protected virtual T BodyDeclaringSymbol => symbol;
public BlockSyntax Block
{
get
{
return symbol.
return BodyDeclaringSymbol.
DeclaringSyntaxReferences.
Select(r => r.GetSyntax()).
SelectMany(n => n.ChildNodes()).
SelectMany(r => r.GetSyntax().ChildNodes()).
OfType<BlockSyntax>().
FirstOrDefault();
}
@@ -112,7 +113,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
get
{
return symbol.
return BodyDeclaringSymbol.
DeclaringSyntaxReferences.
SelectMany(r => r.GetSyntax().ChildNodes()).
OfType<ArrowExpressionClauseSyntax>().

View File

@@ -0,0 +1,7 @@
| Partial.cs:3:18:3:39 | PartialMethodWithBody1 | true |
| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | true |
| Partial.cs:5:17:5:23 | Method2 | false |
| Partial.cs:11:17:11:23 | Method3 | false |
| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | true |
| Partial.cs:17:17:17:23 | Method4 | false |
| Partial.cs:22:17:22:23 | Method5 | false |

View File

@@ -0,0 +1,7 @@
import csharp
private boolean isPartial(Method m) { if m.isPartial() then result = true else result = false }
from Method m
where m.fromSource()
select m, isPartial(m)

View File

@@ -1,11 +1,23 @@
partial class A
partial class TwoPartClass
{
partial void M();
public void M2() { }
partial void PartialMethodWithBody1();
partial void PartialMethodWithoutBody1();
public void Method2() { }
}
partial class A
partial class TwoPartClass
{
partial void M() { }
public void M3() { }
partial void PartialMethodWithBody1() { }
public void Method3() { }
}
partial class OnePartPartialClass
{
partial void PartialMethodWithoutBody2();
public void Method4() { }
}
class NonPartialClass
{
public void Method5() { }
}

View File

@@ -1,3 +1,6 @@
| Partial.cs:1:15:1:15 | A |
| Partial.cs:3:18:3:18 | M |
| Partial.cs:7:15:7:15 | A |
| Partial.cs:1:15:1:26 | TwoPartClass |
| Partial.cs:3:18:3:39 | PartialMethodWithBody1 |
| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 |
| Partial.cs:8:15:8:26 | TwoPartClass |
| Partial.cs:14:15:14:33 | OnePartPartialClass |
| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 |

View File

@@ -1,6 +1,10 @@
| Partial.cs:1:15:1:15 | A | Partial.cs:3:18:3:18 | M |
| Partial.cs:1:15:1:15 | A | Partial.cs:4:17:4:18 | M2 |
| Partial.cs:1:15:1:15 | A | Partial.cs:10:17:10:18 | M3 |
| Partial.cs:7:15:7:15 | A | Partial.cs:3:18:3:18 | M |
| Partial.cs:7:15:7:15 | A | Partial.cs:4:17:4:18 | M2 |
| Partial.cs:7:15:7:15 | A | Partial.cs:10:17:10:18 | M3 |
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:3:18:3:39 | PartialMethodWithBody1 |
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 |
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 |
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:11:17:11:23 | Method3 |
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:3:18:3:39 | PartialMethodWithBody1 |
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 |
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 |
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:11:17:11:23 | Method3 |
| Partial.cs:14:15:14:33 | OnePartPartialClass | Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 |
| Partial.cs:14:15:14:33 | OnePartPartialClass | Partial.cs:17:17:17:23 | Method4 |

View File

@@ -0,0 +1,3 @@
| Partial.cs:3:18:3:39 | PartialMethodWithBody1 | true |
| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | false |
| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | false |

View File

@@ -0,0 +1,7 @@
import csharp
private boolean hasBody(Method m) { if m.hasBody() then result = true else result = false }
from Method m
where m.fromSource() and m.isPartial()
select m, hasBody(m)