mirror of
https://github.com/github/codeql.git
synced 2026-04-26 09:15:12 +02:00
Merge pull request #21351 from michaelnebel/csharp/fixpartialmethod
C#: Fix issue with partial method extraction.
This commit is contained in:
@@ -728,6 +728,15 @@ namespace Semmle.Extraction.CSharp
|
||||
public static INamedTypeSymbol? GetNonObjectBaseType(this ITypeSymbol symbol, Context cx) =>
|
||||
symbol is ITypeParameterSymbol || SymbolEqualityComparer.Default.Equals(symbol.BaseType, cx.Compilation.ObjectType) ? null : symbol.BaseType;
|
||||
|
||||
public static IMethodSymbol GetBodyDeclaringSymbol(this IMethodSymbol method) =>
|
||||
method.PartialImplementationPart ?? method;
|
||||
|
||||
public static IPropertySymbol GetBodyDeclaringSymbol(this IPropertySymbol property) =>
|
||||
property.PartialImplementationPart ?? property;
|
||||
|
||||
public static IEventSymbol GetBodyDeclaringSymbol(this IEventSymbol symbol) =>
|
||||
symbol.PartialImplementationPart ?? symbol;
|
||||
|
||||
[return: NotNullIfNotNull(nameof(symbol))]
|
||||
public static IEntity? CreateEntity(this Context cx, ISymbol symbol)
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
Overrides(trapFile);
|
||||
|
||||
if (Symbol.FromSource() && Block is null)
|
||||
if (Symbol.FromSource() && !HasBody)
|
||||
{
|
||||
trapFile.compiler_generated(this);
|
||||
}
|
||||
|
||||
@@ -9,9 +9,14 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal abstract class CachedSymbol<T> : CachedEntity<T> where T : class, ISymbol
|
||||
{
|
||||
private readonly Lazy<BlockSyntax?> blockLazy;
|
||||
private readonly Lazy<ExpressionSyntax?> expressionBodyLazy;
|
||||
|
||||
protected CachedSymbol(Context cx, T init)
|
||||
: base(cx, init)
|
||||
{
|
||||
blockLazy = new Lazy<BlockSyntax?>(() => GetBlock(Symbol));
|
||||
expressionBodyLazy = new Lazy<ExpressionSyntax?>(() => GetExpressionBody(Symbol));
|
||||
}
|
||||
|
||||
public virtual Type? ContainingType => Symbol.ContainingType is not null
|
||||
@@ -87,31 +92,29 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
Context.BindComments(this, FullLocation);
|
||||
}
|
||||
|
||||
protected virtual T BodyDeclaringSymbol => Symbol;
|
||||
|
||||
public BlockSyntax? Block
|
||||
private static BlockSyntax? GetBlock(T symbol)
|
||||
{
|
||||
get
|
||||
{
|
||||
return BodyDeclaringSymbol.DeclaringSyntaxReferences
|
||||
return symbol.DeclaringSyntaxReferences
|
||||
.SelectMany(r => r.GetSyntax().ChildNodes())
|
||||
.OfType<BlockSyntax>()
|
||||
.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public ExpressionSyntax? ExpressionBody
|
||||
private static ExpressionSyntax? GetExpressionBody(T symbol)
|
||||
{
|
||||
get
|
||||
{
|
||||
return BodyDeclaringSymbol.DeclaringSyntaxReferences
|
||||
return symbol.DeclaringSyntaxReferences
|
||||
.SelectMany(r => r.GetSyntax().ChildNodes())
|
||||
.OfType<ArrowExpressionClauseSyntax>()
|
||||
.Select(arrow => arrow.Expression)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public BlockSyntax? Block => blockLazy.Value;
|
||||
|
||||
public ExpressionSyntax? ExpressionBody => expressionBodyLazy.Value;
|
||||
|
||||
public bool HasBody => Block is not null || ExpressionBody is not null;
|
||||
|
||||
public virtual bool IsSourceDeclaration => Symbol.IsSourceDeclaration();
|
||||
|
||||
public override bool NeedsPopulation => Context.Defines(Symbol);
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
if (MakeSynthetic)
|
||||
if (MakeSyntheticBody)
|
||||
{
|
||||
// Create a synthetic empty body for primary and default constructors.
|
||||
Statements.SyntheticEmptyBlock.Create(Context, this, 0, Location);
|
||||
@@ -60,7 +60,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
// Do not extract initializers for constructed types.
|
||||
// Extract initializers for constructors with a body, primary constructors
|
||||
// and default constructors for classes and structs declared in source code.
|
||||
if (Block is null && ExpressionBody is null && !MakeSynthetic || Context.OnlyScaffold)
|
||||
if (!HasBody && !MakeSyntheticBody || Context.OnlyScaffold)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -211,7 +211,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
/// </summary>
|
||||
private bool IsBestSourceLocation => ReportingLocation is not null && Context.IsLocationInContext(ReportingLocation);
|
||||
|
||||
private bool MakeSynthetic => (IsPrimary || (IsDefault && IsBestSourceLocation)) && !Context.OnlyScaffold;
|
||||
private bool MakeSyntheticBody => (IsPrimary || (IsDefault && IsBestSourceLocation)) && !Context.OnlyScaffold;
|
||||
|
||||
[return: NotNullIfNotNull(nameof(constructor))]
|
||||
public static new Constructor? Create(Context cx, IMethodSymbol? constructor)
|
||||
|
||||
@@ -11,10 +11,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
private Event(Context cx, IEventSymbol init)
|
||||
: base(cx, init) { }
|
||||
|
||||
protected override IEventSymbol BodyDeclaringSymbol => Symbol.PartialImplementationPart ?? Symbol;
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location? ReportingLocation => BodyDeclaringSymbol.Locations.BestOrDefault();
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(ContainingType!);
|
||||
@@ -31,8 +27,8 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
var type = Type.Create(Context, Symbol.Type);
|
||||
trapFile.events(this, Symbol.GetName(), ContainingType!, type.TypeRef, Create(Context, Symbol.OriginalDefinition));
|
||||
|
||||
var adder = BodyDeclaringSymbol.AddMethod;
|
||||
var remover = BodyDeclaringSymbol.RemoveMethod;
|
||||
var adder = Symbol.AddMethod;
|
||||
var remover = Symbol.RemoveMethod;
|
||||
|
||||
if (adder is not null)
|
||||
Method.Create(Context, adder);
|
||||
@@ -76,7 +72,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntityFromSymbol(cx, symbol.GetBodyDeclaringSymbol());
|
||||
|
||||
private class EventFactory : CachedEntityFactory<IEventSymbol, Event>
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
Overrides(trapFile);
|
||||
|
||||
if (Symbol.FromSource() && Block is null)
|
||||
if (Symbol.FromSource() && !HasBody)
|
||||
{
|
||||
trapFile.compiler_generated(this);
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
var type = Type.Create(Context, Symbol.Type);
|
||||
trapFile.indexers(this, Symbol.GetName(useMetadataName: true), ContainingType!, type.TypeRef, OriginalDefinition);
|
||||
|
||||
var getter = BodyDeclaringSymbol.GetMethod;
|
||||
var setter = BodyDeclaringSymbol.SetMethod;
|
||||
var getter = Symbol.GetMethod;
|
||||
var setter = Symbol.SetMethod;
|
||||
|
||||
if (getter is null && setter is null)
|
||||
Context.ModelError(Symbol, "No indexer accessor defined");
|
||||
@@ -81,7 +81,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
TypeMention.Create(Context, syntax.Type, this, type);
|
||||
}
|
||||
|
||||
public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntityFromSymbol(cx, prop);
|
||||
public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntityFromSymbol(cx, prop.GetBodyDeclaringSymbol());
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
else
|
||||
Expression.Create(Context, expr!, this, 0);
|
||||
|
||||
NumberOfLines(trapFile, BodyDeclaringSymbol, this);
|
||||
NumberOfLines(trapFile, Symbol, this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,12 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override string Name => Symbol.GetName();
|
||||
|
||||
protected override IMethodSymbol BodyDeclaringSymbol => Symbol.PartialImplementationPart ?? Symbol;
|
||||
|
||||
public IMethodSymbol SourceDeclaration => Symbol.OriginalDefinition;
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation =>
|
||||
IsCompilerGeneratedDelegate()
|
||||
? Symbol.ContainingType.GetSymbolLocation()
|
||||
: BodyDeclaringSymbol.GetSymbolLocation();
|
||||
: Symbol.GetSymbolLocation();
|
||||
|
||||
public override bool NeedsPopulation =>
|
||||
(base.NeedsPopulation || IsCompilerGeneratedDelegate()) &&
|
||||
@@ -77,7 +75,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
cx.ExtractionContext.Logger.LogWarning("Reduced extension method symbols should not be directly extracted.");
|
||||
}
|
||||
|
||||
return OrdinaryMethodFactory.Instance.CreateEntityFromSymbol(cx, method);
|
||||
return OrdinaryMethodFactory.Instance.CreateEntityFromSymbol(cx, method.GetBodyDeclaringSymbol());
|
||||
}
|
||||
|
||||
private class OrdinaryMethodFactory : CachedEntityFactory<IMethodSymbol, OrdinaryMethod>
|
||||
|
||||
@@ -21,10 +21,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
private Type Type => type.Value;
|
||||
|
||||
protected override IPropertySymbol BodyDeclaringSymbol => Symbol.PartialImplementationPart ?? Symbol;
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location? ReportingLocation => BodyDeclaringSymbol.Locations.BestOrDefault();
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(Type);
|
||||
@@ -46,8 +42,8 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
var type = Type;
|
||||
trapFile.properties(this, Symbol.GetName(), ContainingType!, type.TypeRef, Create(Context, Symbol.OriginalDefinition));
|
||||
|
||||
var getter = BodyDeclaringSymbol.GetMethod;
|
||||
var setter = BodyDeclaringSymbol.SetMethod;
|
||||
var getter = Symbol.GetMethod;
|
||||
var setter = Symbol.SetMethod;
|
||||
|
||||
if (getter is not null)
|
||||
Method.Create(Context, getter);
|
||||
@@ -132,7 +128,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
var isIndexer = prop.IsIndexer || prop.Parameters.Any();
|
||||
|
||||
return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntityFromSymbol(cx, prop);
|
||||
return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntityFromSymbol(cx, prop.GetBodyDeclaringSymbol());
|
||||
}
|
||||
|
||||
private class PropertyFactory : CachedEntityFactory<IPropertySymbol, Property>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* Fixed an issue where the body of a partial member could be extracted twice. When both a *defining* and an *implementing* declaration exist, only the *implementing* declaration is now extracted.
|
||||
@@ -0,0 +1,40 @@
|
||||
models
|
||||
edges
|
||||
| Methods.cs:8:48:8:48 | o : Object | Methods.cs:10:16:10:16 | access to parameter o : Object | provenance | |
|
||||
| Methods.cs:8:48:8:48 | o : Object | Methods.cs:10:16:10:16 | access to parameter o : Object | provenance | |
|
||||
| Methods.cs:17:13:17:13 | access to local variable o : Object | Methods.cs:19:38:19:38 | access to local variable o : Object | provenance | |
|
||||
| Methods.cs:17:13:17:13 | access to local variable o : Object | Methods.cs:19:38:19:38 | access to local variable o : Object | provenance | |
|
||||
| Methods.cs:17:17:17:33 | call to method Source<Object> : Object | Methods.cs:17:13:17:13 | access to local variable o : Object | provenance | |
|
||||
| Methods.cs:17:17:17:33 | call to method Source<Object> : Object | Methods.cs:17:13:17:13 | access to local variable o : Object | provenance | |
|
||||
| Methods.cs:19:13:19:18 | access to local variable result : Object | Methods.cs:20:14:20:19 | access to local variable result | provenance | |
|
||||
| Methods.cs:19:13:19:18 | access to local variable result : Object | Methods.cs:20:14:20:19 | access to local variable result | provenance | |
|
||||
| Methods.cs:19:22:19:39 | call to method PartialMethod : Object | Methods.cs:19:13:19:18 | access to local variable result : Object | provenance | |
|
||||
| Methods.cs:19:22:19:39 | call to method PartialMethod : Object | Methods.cs:19:13:19:18 | access to local variable result : Object | provenance | |
|
||||
| Methods.cs:19:38:19:38 | access to local variable o : Object | Methods.cs:8:48:8:48 | o : Object | provenance | |
|
||||
| Methods.cs:19:38:19:38 | access to local variable o : Object | Methods.cs:8:48:8:48 | o : Object | provenance | |
|
||||
| Methods.cs:19:38:19:38 | access to local variable o : Object | Methods.cs:19:22:19:39 | call to method PartialMethod : Object | provenance | |
|
||||
| Methods.cs:19:38:19:38 | access to local variable o : Object | Methods.cs:19:22:19:39 | call to method PartialMethod : Object | provenance | |
|
||||
nodes
|
||||
| Methods.cs:8:48:8:48 | o : Object | semmle.label | o : Object |
|
||||
| Methods.cs:8:48:8:48 | o : Object | semmle.label | o : Object |
|
||||
| Methods.cs:10:16:10:16 | access to parameter o : Object | semmle.label | access to parameter o : Object |
|
||||
| Methods.cs:10:16:10:16 | access to parameter o : Object | semmle.label | access to parameter o : Object |
|
||||
| Methods.cs:17:13:17:13 | access to local variable o : Object | semmle.label | access to local variable o : Object |
|
||||
| Methods.cs:17:13:17:13 | access to local variable o : Object | semmle.label | access to local variable o : Object |
|
||||
| Methods.cs:17:17:17:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
|
||||
| Methods.cs:17:17:17:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
|
||||
| Methods.cs:19:13:19:18 | access to local variable result : Object | semmle.label | access to local variable result : Object |
|
||||
| Methods.cs:19:13:19:18 | access to local variable result : Object | semmle.label | access to local variable result : Object |
|
||||
| Methods.cs:19:22:19:39 | call to method PartialMethod : Object | semmle.label | call to method PartialMethod : Object |
|
||||
| Methods.cs:19:22:19:39 | call to method PartialMethod : Object | semmle.label | call to method PartialMethod : Object |
|
||||
| Methods.cs:19:38:19:38 | access to local variable o : Object | semmle.label | access to local variable o : Object |
|
||||
| Methods.cs:19:38:19:38 | access to local variable o : Object | semmle.label | access to local variable o : Object |
|
||||
| Methods.cs:20:14:20:19 | access to local variable result | semmle.label | access to local variable result |
|
||||
| Methods.cs:20:14:20:19 | access to local variable result | semmle.label | access to local variable result |
|
||||
subpaths
|
||||
| Methods.cs:19:38:19:38 | access to local variable o : Object | Methods.cs:8:48:8:48 | o : Object | Methods.cs:10:16:10:16 | access to parameter o : Object | Methods.cs:19:22:19:39 | call to method PartialMethod : Object |
|
||||
| Methods.cs:19:38:19:38 | access to local variable o : Object | Methods.cs:8:48:8:48 | o : Object | Methods.cs:10:16:10:16 | access to parameter o : Object | Methods.cs:19:22:19:39 | call to method PartialMethod : Object |
|
||||
testFailures
|
||||
#select
|
||||
| Methods.cs:20:14:20:19 | access to local variable result | Methods.cs:17:17:17:33 | call to method Source<Object> : Object | Methods.cs:20:14:20:19 | access to local variable result | $@ | Methods.cs:17:17:17:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
|
||||
| Methods.cs:20:14:20:19 | access to local variable result | Methods.cs:17:17:17:33 | call to method Source<Object> : Object | Methods.cs:20:14:20:19 | access to local variable result | $@ | Methods.cs:17:17:17:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
|
||||
12
csharp/ql/test/library-tests/dataflow/methods/MethodFlow.ql
Normal file
12
csharp/ql/test/library-tests/dataflow/methods/MethodFlow.ql
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import utils.test.InlineFlowTest
|
||||
import DefaultFlowTest
|
||||
import PathGraph
|
||||
|
||||
from PathNode source, PathNode sink
|
||||
where flowPath(source, sink)
|
||||
select sink, source, sink, "$@", source, source.toString()
|
||||
26
csharp/ql/test/library-tests/dataflow/methods/Methods.cs
Normal file
26
csharp/ql/test/library-tests/dataflow/methods/Methods.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
public partial class Partial
|
||||
{
|
||||
public partial object PartialMethod(object o);
|
||||
}
|
||||
|
||||
public partial class Partial
|
||||
{
|
||||
public partial object PartialMethod(object o)
|
||||
{
|
||||
return o;
|
||||
}
|
||||
}
|
||||
public class C
|
||||
{
|
||||
public void M()
|
||||
{
|
||||
var o = Source<object>(1);
|
||||
var p = new Partial();
|
||||
var result = p.PartialMethod(o);
|
||||
Sink(result); // $ hasValueFlow=1
|
||||
}
|
||||
|
||||
public static void Sink(object o) { }
|
||||
|
||||
static T Source<T>(object source) => throw null;
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
| Partial.cs:6:18:6:42 | PartialMethodWithoutBody1 | true |
|
||||
| Partial.cs:7:17:7:23 | Method2 | false |
|
||||
| Partial.cs:18:18:18:39 | PartialMethodWithBody1 | true |
|
||||
| Partial.cs:19:17:19:23 | Method3 | false |
|
||||
| Partial.cs:41:18:41:42 | PartialMethodWithoutBody2 | true |
|
||||
| Partial.cs:42:17:42:23 | Method4 | false |
|
||||
| Partial.cs:47:17:47:23 | Method5 | false |
|
||||
| Partial.cs:7:18:7:42 | PartialMethodWithoutBody1 | true |
|
||||
| Partial.cs:8:17:8:23 | Method2 | false |
|
||||
| Partial.cs:19:18:19:39 | PartialMethodWithBody1 | true |
|
||||
| Partial.cs:20:27:20:48 | PartialMethodWithBody2 | true |
|
||||
| Partial.cs:24:17:24:23 | Method3 | false |
|
||||
| Partial.cs:46:18:46:42 | PartialMethodWithoutBody2 | true |
|
||||
| Partial.cs:47:17:47:23 | Method4 | false |
|
||||
| Partial.cs:52:17:52:23 | Method5 | false |
|
||||
|
||||
@@ -3,6 +3,7 @@ using System;
|
||||
partial class TwoPartClass
|
||||
{
|
||||
partial void PartialMethodWithBody1();
|
||||
public partial object PartialMethodWithBody2(object obj);
|
||||
partial void PartialMethodWithoutBody1();
|
||||
public void Method2() { }
|
||||
// Declaring declaration.
|
||||
@@ -16,6 +17,10 @@ partial class TwoPartClass
|
||||
partial class TwoPartClass
|
||||
{
|
||||
partial void PartialMethodWithBody1() { }
|
||||
public partial object PartialMethodWithBody2(object obj)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
public void Method3() { }
|
||||
private object _backingField;
|
||||
// Implementation declaration.
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass |
|
||||
| Partial.cs:6:18:6:42 | PartialMethodWithoutBody1 |
|
||||
| Partial.cs:16:15:16:26 | TwoPartClass |
|
||||
| Partial.cs:18:18:18:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:22:27:22:42 | PartialProperty1 |
|
||||
| Partial.cs:24:9:24:11 | get_PartialProperty1 |
|
||||
| Partial.cs:25:9:25:11 | set_PartialProperty1 |
|
||||
| Partial.cs:29:27:29:30 | Item |
|
||||
| Partial.cs:31:9:31:11 | get_Item |
|
||||
| Partial.cs:32:9:32:11 | set_Item |
|
||||
| Partial.cs:36:39:36:51 | PartialEvent1 |
|
||||
| Partial.cs:36:55:36:57 | add_PartialEvent1 |
|
||||
| Partial.cs:36:63:36:68 | remove_PartialEvent1 |
|
||||
| Partial.cs:39:15:39:33 | OnePartPartialClass |
|
||||
| Partial.cs:41:18:41:42 | PartialMethodWithoutBody2 |
|
||||
| Partial.cs:7:18:7:42 | PartialMethodWithoutBody1 |
|
||||
| Partial.cs:17:15:17:26 | TwoPartClass |
|
||||
| Partial.cs:19:18:19:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:20:27:20:48 | PartialMethodWithBody2 |
|
||||
| Partial.cs:27:27:27:42 | PartialProperty1 |
|
||||
| Partial.cs:29:9:29:11 | get_PartialProperty1 |
|
||||
| Partial.cs:30:9:30:11 | set_PartialProperty1 |
|
||||
| Partial.cs:34:27:34:30 | Item |
|
||||
| Partial.cs:36:9:36:11 | get_Item |
|
||||
| Partial.cs:37:9:37:11 | set_Item |
|
||||
| Partial.cs:41:39:41:51 | PartialEvent1 |
|
||||
| Partial.cs:41:55:41:57 | add_PartialEvent1 |
|
||||
| Partial.cs:41:63:41:68 | remove_PartialEvent1 |
|
||||
| Partial.cs:44:15:44:33 | OnePartPartialClass |
|
||||
| Partial.cs:46:18:46:42 | PartialMethodWithoutBody2 |
|
||||
| PartialMultipleFiles1.cs:1:22:1:41 | PartialMultipleFiles |
|
||||
| PartialMultipleFiles2.cs:1:22:1:41 | PartialMultipleFiles |
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:3:15:3:26 | <object initializer> |
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:6:18:6:42 | PartialMethodWithoutBody1 |
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:7:17:7:23 | Method2 |
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:18:18:18:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:19:17:19:23 | Method3 |
|
||||
| Partial.cs:16:15:16:26 | TwoPartClass | Partial.cs:3:15:3:26 | <object initializer> |
|
||||
| Partial.cs:16:15:16:26 | TwoPartClass | Partial.cs:6:18:6:42 | PartialMethodWithoutBody1 |
|
||||
| Partial.cs:16:15:16:26 | TwoPartClass | Partial.cs:7:17:7:23 | Method2 |
|
||||
| Partial.cs:16:15:16:26 | TwoPartClass | Partial.cs:18:18:18:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:16:15:16:26 | TwoPartClass | Partial.cs:19:17:19:23 | Method3 |
|
||||
| Partial.cs:39:15:39:33 | OnePartPartialClass | Partial.cs:39:15:39:33 | <object initializer> |
|
||||
| Partial.cs:39:15:39:33 | OnePartPartialClass | Partial.cs:41:18:41:42 | PartialMethodWithoutBody2 |
|
||||
| Partial.cs:39:15:39:33 | OnePartPartialClass | Partial.cs:42:17:42:23 | Method4 |
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:7:18:7:42 | PartialMethodWithoutBody1 |
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:8:17:8:23 | Method2 |
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:19:18:19:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:20:27:20:48 | PartialMethodWithBody2 |
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:24:17:24:23 | Method3 |
|
||||
| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:3:15:3:26 | <object initializer> |
|
||||
| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:7:18:7:42 | PartialMethodWithoutBody1 |
|
||||
| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:8:17:8:23 | Method2 |
|
||||
| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:19:18:19:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:20:27:20:48 | PartialMethodWithBody2 |
|
||||
| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:24:17:24:23 | Method3 |
|
||||
| Partial.cs:44:15:44:33 | OnePartPartialClass | Partial.cs:44:15:44:33 | <object initializer> |
|
||||
| Partial.cs:44:15:44:33 | OnePartPartialClass | Partial.cs:46:18:46:42 | PartialMethodWithoutBody2 |
|
||||
| Partial.cs:44:15:44:33 | OnePartPartialClass | Partial.cs:47:17:47:23 | Method4 |
|
||||
| PartialMultipleFiles1.cs:1:22:1:41 | PartialMultipleFiles | PartialMultipleFiles1.cs:1:22:1:41 | <object initializer> |
|
||||
| PartialMultipleFiles2.cs:1:22:1:41 | PartialMultipleFiles | PartialMultipleFiles1.cs:1:22:1:41 | <object initializer> |
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
| Partial.cs:24:9:24:11 | get_PartialProperty1 | true |
|
||||
| Partial.cs:25:9:25:11 | set_PartialProperty1 | true |
|
||||
| Partial.cs:31:9:31:11 | get_Item | true |
|
||||
| Partial.cs:32:9:32:11 | set_Item | true |
|
||||
| Partial.cs:36:55:36:57 | add_PartialEvent1 | true |
|
||||
| Partial.cs:36:63:36:68 | remove_PartialEvent1 | true |
|
||||
| Partial.cs:48:30:48:32 | get_Property | false |
|
||||
| Partial.cs:48:35:48:37 | set_Property | false |
|
||||
| Partial.cs:51:9:51:11 | get_Item | false |
|
||||
| Partial.cs:52:9:52:11 | set_Item | false |
|
||||
| Partial.cs:54:31:54:35 | add_Event | false |
|
||||
| Partial.cs:54:31:54:35 | remove_Event | false |
|
||||
| Partial.cs:29:9:29:11 | get_PartialProperty1 | true |
|
||||
| Partial.cs:30:9:30:11 | set_PartialProperty1 | true |
|
||||
| Partial.cs:36:9:36:11 | get_Item | true |
|
||||
| Partial.cs:37:9:37:11 | set_Item | true |
|
||||
| Partial.cs:41:55:41:57 | add_PartialEvent1 | true |
|
||||
| Partial.cs:41:63:41:68 | remove_PartialEvent1 | true |
|
||||
| Partial.cs:53:30:53:32 | get_Property | false |
|
||||
| Partial.cs:53:35:53:37 | set_Property | false |
|
||||
| Partial.cs:56:9:56:11 | get_Item | false |
|
||||
| Partial.cs:57:9:57:11 | set_Item | false |
|
||||
| Partial.cs:59:31:59:35 | add_Event | false |
|
||||
| Partial.cs:59:31:59:35 | remove_Event | false |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:3:15:3:26 | {...} |
|
||||
| Partial.cs:39:15:39:33 | OnePartPartialClass | Partial.cs:39:15:39:33 | {...} |
|
||||
| Partial.cs:45:7:45:21 | NonPartialClass | Partial.cs:45:7:45:21 | {...} |
|
||||
| Partial.cs:44:15:44:33 | OnePartPartialClass | Partial.cs:44:15:44:33 | {...} |
|
||||
| Partial.cs:50:7:50:21 | NonPartialClass | Partial.cs:50:7:50:21 | {...} |
|
||||
| PartialMultipleFiles1.cs:1:22:1:41 | PartialMultipleFiles | PartialMultipleFiles1.cs:1:22:1:41 | {...} |
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Partial.cs:36:39:36:51 | PartialEvent1 | true |
|
||||
| Partial.cs:54:31:54:35 | Event | false |
|
||||
| Partial.cs:41:39:41:51 | PartialEvent1 | true |
|
||||
| Partial.cs:59:31:59:35 | Event | false |
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Partial.cs:29:27:29:30 | Item | true |
|
||||
| Partial.cs:49:19:49:22 | Item | false |
|
||||
| Partial.cs:34:27:34:30 | Item | true |
|
||||
| Partial.cs:54:19:54:22 | Item | false |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
| Partial.cs:6:18:6:42 | PartialMethodWithoutBody1 | false |
|
||||
| Partial.cs:18:18:18:39 | PartialMethodWithBody1 | true |
|
||||
| Partial.cs:41:18:41:42 | PartialMethodWithoutBody2 | false |
|
||||
| Partial.cs:7:18:7:42 | PartialMethodWithoutBody1 | false | 0 |
|
||||
| Partial.cs:19:18:19:39 | PartialMethodWithBody1 | true | 1 |
|
||||
| Partial.cs:20:27:20:48 | PartialMethodWithBody2 | true | 1 |
|
||||
| Partial.cs:46:18:46:42 | PartialMethodWithoutBody2 | false | 0 |
|
||||
|
||||
@@ -4,4 +4,4 @@ private boolean hasBody(Method m) { if m.hasBody() then result = true else resul
|
||||
|
||||
from Method m
|
||||
where m.fromSource() and m.isPartial()
|
||||
select m, hasBody(m)
|
||||
select m, hasBody(m), count(m.getBody())
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Partial.cs:22:27:22:42 | PartialProperty1 | true |
|
||||
| Partial.cs:48:19:48:26 | Property | false |
|
||||
| Partial.cs:27:27:27:42 | PartialProperty1 | true |
|
||||
| Partial.cs:53:19:53:26 | Property | false |
|
||||
|
||||
@@ -1,112 +1,116 @@
|
||||
Partial.cs:
|
||||
# 3| [Class] TwoPartClass
|
||||
# 6| 6: [Method] PartialMethodWithoutBody1
|
||||
# 6| -1: [TypeMention] Void
|
||||
# 7| 7: [Method] Method2
|
||||
# 7| 6: [Method] PartialMethodWithoutBody1
|
||||
# 7| -1: [TypeMention] Void
|
||||
# 7| 4: [BlockStmt] {...}
|
||||
# 18| 8: [Method] PartialMethodWithBody1
|
||||
# 5| -1: [TypeMention] Void
|
||||
# 18| 4: [BlockStmt] {...}
|
||||
# 19| 9: [Method] Method3
|
||||
# 8| 7: [Method] Method2
|
||||
# 8| -1: [TypeMention] Void
|
||||
# 8| 4: [BlockStmt] {...}
|
||||
# 19| 8: [Method] PartialMethodWithBody1
|
||||
# 19| -1: [TypeMention] Void
|
||||
# 19| 4: [BlockStmt] {...}
|
||||
# 20| 10: [Field] _backingField
|
||||
# 20| 9: [Method] PartialMethodWithBody2
|
||||
# 20| -1: [TypeMention] object
|
||||
# 22| 11: [Property] PartialProperty1
|
||||
# 9| -1: [TypeMention] object
|
||||
# 22| -1: [TypeMention] object
|
||||
# 24| 3: [Getter] get_PartialProperty1
|
||||
# 24| 4: [BlockStmt] {...}
|
||||
# 24| 0: [ReturnStmt] return ...;
|
||||
# 24| 0: [FieldAccess] access to field _backingField
|
||||
# 25| 4: [Setter] set_PartialProperty1
|
||||
#-----| 2: (Parameters)
|
||||
# 20| 0: [Parameter] obj
|
||||
# 20| -1: [TypeMention] object
|
||||
# 21| 4: [BlockStmt] {...}
|
||||
# 22| 0: [ReturnStmt] return ...;
|
||||
# 22| 0: [ParameterAccess] access to parameter obj
|
||||
# 24| 10: [Method] Method3
|
||||
# 24| -1: [TypeMention] Void
|
||||
# 24| 4: [BlockStmt] {...}
|
||||
# 25| 11: [Field] _backingField
|
||||
# 25| -1: [TypeMention] object
|
||||
# 27| 12: [Property] PartialProperty1
|
||||
# 27| -1: [TypeMention] object
|
||||
# 29| 3: [Getter] get_PartialProperty1
|
||||
# 29| 4: [BlockStmt] {...}
|
||||
# 29| 0: [ReturnStmt] return ...;
|
||||
# 29| 0: [FieldAccess] access to field _backingField
|
||||
# 30| 4: [Setter] set_PartialProperty1
|
||||
#-----| 2: (Parameters)
|
||||
# 25| 0: [Parameter] value
|
||||
# 25| 4: [BlockStmt] {...}
|
||||
# 25| 0: [ExprStmt] ...;
|
||||
# 25| 0: [AssignExpr] ... = ...
|
||||
# 25| 0: [FieldAccess] access to field _backingField
|
||||
# 25| 1: [ParameterAccess] access to parameter value
|
||||
# 27| 12: [Field] _backingArray
|
||||
# 27| -1: [TypeMention] Object[]
|
||||
# 27| 1: [TypeMention] object
|
||||
# 29| 13: [Indexer] Item
|
||||
# 11| -1: [TypeMention] object
|
||||
# 29| -1: [TypeMention] object
|
||||
# 30| 0: [Parameter] value
|
||||
# 30| 4: [BlockStmt] {...}
|
||||
# 30| 0: [ExprStmt] ...;
|
||||
# 30| 0: [AssignExpr] ... = ...
|
||||
# 30| 0: [FieldAccess] access to field _backingField
|
||||
# 30| 1: [ParameterAccess] access to parameter value
|
||||
# 32| 13: [Field] _backingArray
|
||||
# 32| -1: [TypeMention] Object[]
|
||||
# 32| 1: [TypeMention] object
|
||||
# 34| 14: [Indexer] Item
|
||||
# 34| -1: [TypeMention] object
|
||||
#-----| 1: (Parameters)
|
||||
# 11| 0: [Parameter] index
|
||||
# 11| -1: [TypeMention] int
|
||||
# 29| -1: [TypeMention] int
|
||||
# 31| 3: [Getter] get_Item
|
||||
# 34| 0: [Parameter] index
|
||||
# 34| -1: [TypeMention] int
|
||||
# 36| 3: [Getter] get_Item
|
||||
#-----| 2: (Parameters)
|
||||
# 29| 0: [Parameter] index
|
||||
# 31| 4: [BlockStmt] {...}
|
||||
# 31| 0: [ReturnStmt] return ...;
|
||||
# 31| 0: [ArrayAccess] access to array element
|
||||
# 31| -1: [FieldAccess] access to field _backingArray
|
||||
# 31| 0: [ParameterAccess] access to parameter index
|
||||
# 32| 4: [Setter] set_Item
|
||||
#-----| 2: (Parameters)
|
||||
# 29| 0: [Parameter] index
|
||||
# 32| 1: [Parameter] value
|
||||
# 32| 4: [BlockStmt] {...}
|
||||
# 32| 0: [ExprStmt] ...;
|
||||
# 32| 0: [AssignExpr] ... = ...
|
||||
# 32| 0: [ArrayAccess] access to array element
|
||||
# 32| -1: [FieldAccess] access to field _backingArray
|
||||
# 32| 0: [ParameterAccess] access to parameter index
|
||||
# 32| 1: [ParameterAccess] access to parameter value
|
||||
# 36| 14: [Event] PartialEvent1
|
||||
# 13| -1: [TypeMention] EventHandler
|
||||
# 36| 3: [AddEventAccessor] add_PartialEvent1
|
||||
#-----| 2: (Parameters)
|
||||
# 36| 0: [Parameter] value
|
||||
# 34| 0: [Parameter] index
|
||||
# 36| 4: [BlockStmt] {...}
|
||||
# 36| 4: [RemoveEventAccessor] remove_PartialEvent1
|
||||
# 36| 0: [ReturnStmt] return ...;
|
||||
# 36| 0: [ArrayAccess] access to array element
|
||||
# 36| -1: [FieldAccess] access to field _backingArray
|
||||
# 36| 0: [ParameterAccess] access to parameter index
|
||||
# 37| 4: [Setter] set_Item
|
||||
#-----| 2: (Parameters)
|
||||
# 36| 0: [Parameter] value
|
||||
# 36| 4: [BlockStmt] {...}
|
||||
# 39| [Class] OnePartPartialClass
|
||||
# 41| 6: [Method] PartialMethodWithoutBody2
|
||||
# 41| -1: [TypeMention] Void
|
||||
# 42| 7: [Method] Method4
|
||||
# 42| -1: [TypeMention] Void
|
||||
# 42| 4: [BlockStmt] {...}
|
||||
# 45| [Class] NonPartialClass
|
||||
# 47| 6: [Method] Method5
|
||||
# 34| 0: [Parameter] index
|
||||
# 37| 1: [Parameter] value
|
||||
# 37| 4: [BlockStmt] {...}
|
||||
# 37| 0: [ExprStmt] ...;
|
||||
# 37| 0: [AssignExpr] ... = ...
|
||||
# 37| 0: [ArrayAccess] access to array element
|
||||
# 37| -1: [FieldAccess] access to field _backingArray
|
||||
# 37| 0: [ParameterAccess] access to parameter index
|
||||
# 37| 1: [ParameterAccess] access to parameter value
|
||||
# 41| 15: [Event] PartialEvent1
|
||||
# 41| 3: [AddEventAccessor] add_PartialEvent1
|
||||
#-----| 2: (Parameters)
|
||||
# 41| 0: [Parameter] value
|
||||
# 41| 4: [BlockStmt] {...}
|
||||
# 41| 4: [RemoveEventAccessor] remove_PartialEvent1
|
||||
#-----| 2: (Parameters)
|
||||
# 41| 0: [Parameter] value
|
||||
# 41| 4: [BlockStmt] {...}
|
||||
# 44| [Class] OnePartPartialClass
|
||||
# 46| 6: [Method] PartialMethodWithoutBody2
|
||||
# 46| -1: [TypeMention] Void
|
||||
# 47| 7: [Method] Method4
|
||||
# 47| -1: [TypeMention] Void
|
||||
# 47| 4: [BlockStmt] {...}
|
||||
# 48| 7: [Property] Property
|
||||
# 48| -1: [TypeMention] object
|
||||
# 48| 3: [Getter] get_Property
|
||||
# 48| 4: [Setter] set_Property
|
||||
# 50| [Class] NonPartialClass
|
||||
# 52| 6: [Method] Method5
|
||||
# 52| -1: [TypeMention] Void
|
||||
# 52| 4: [BlockStmt] {...}
|
||||
# 53| 7: [Property] Property
|
||||
# 53| -1: [TypeMention] object
|
||||
# 53| 3: [Getter] get_Property
|
||||
# 53| 4: [Setter] set_Property
|
||||
#-----| 2: (Parameters)
|
||||
# 48| 0: [Parameter] value
|
||||
# 49| 8: [Indexer] Item
|
||||
# 49| -1: [TypeMention] object
|
||||
# 53| 0: [Parameter] value
|
||||
# 54| 8: [Indexer] Item
|
||||
# 54| -1: [TypeMention] object
|
||||
#-----| 1: (Parameters)
|
||||
# 49| 0: [Parameter] index
|
||||
# 49| -1: [TypeMention] int
|
||||
# 51| 3: [Getter] get_Item
|
||||
# 54| 0: [Parameter] index
|
||||
# 54| -1: [TypeMention] int
|
||||
# 56| 3: [Getter] get_Item
|
||||
#-----| 2: (Parameters)
|
||||
# 49| 0: [Parameter] index
|
||||
# 51| 4: [BlockStmt] {...}
|
||||
# 51| 0: [ReturnStmt] return ...;
|
||||
# 51| 0: [NullLiteral] null
|
||||
# 52| 4: [Setter] set_Item
|
||||
# 54| 0: [Parameter] index
|
||||
# 56| 4: [BlockStmt] {...}
|
||||
# 56| 0: [ReturnStmt] return ...;
|
||||
# 56| 0: [NullLiteral] null
|
||||
# 57| 4: [Setter] set_Item
|
||||
#-----| 2: (Parameters)
|
||||
# 49| 0: [Parameter] index
|
||||
# 52| 1: [Parameter] value
|
||||
# 52| 4: [BlockStmt] {...}
|
||||
# 54| 9: [Event] Event
|
||||
# 54| -1: [TypeMention] EventHandler
|
||||
# 54| 3: [AddEventAccessor] add_Event
|
||||
# 54| 0: [Parameter] index
|
||||
# 57| 1: [Parameter] value
|
||||
# 57| 4: [BlockStmt] {...}
|
||||
# 59| 9: [Event] Event
|
||||
# 59| -1: [TypeMention] EventHandler
|
||||
# 59| 3: [AddEventAccessor] add_Event
|
||||
#-----| 2: (Parameters)
|
||||
# 54| 0: [Parameter] value
|
||||
# 54| 4: [RemoveEventAccessor] remove_Event
|
||||
# 59| 0: [Parameter] value
|
||||
# 59| 4: [RemoveEventAccessor] remove_Event
|
||||
#-----| 2: (Parameters)
|
||||
# 54| 0: [Parameter] value
|
||||
# 59| 0: [Parameter] value
|
||||
PartialMultipleFiles1.cs:
|
||||
# 1| [Class] PartialMultipleFiles
|
||||
PartialMultipleFiles2.cs:
|
||||
|
||||
Reference in New Issue
Block a user