Files
2019-06-26 20:24:56 +01:00

159 lines
5.2 KiB
C#

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Util;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Entities;
namespace Semmle.Extraction.CSharp.Entities
{
public class Constructor : Method
{
Constructor(Context cx, IMethodSymbol init)
: base(cx, init) { }
public override void Populate()
{
PopulateMethod();
ExtractModifiers();
ContainingType.ExtractGenerics();
Context.Emit(Tuples.constructors(this, symbol.ContainingType.Name, ContainingType, (Constructor)OriginalDefinition));
Context.Emit(Tuples.constructor_location(this, Location));
if (symbol.IsImplicitlyDeclared)
{
var lineCounts = new LineCounts() { Total = 2, Code = 1, Comment = 0 };
Context.Emit(Tuples.numlines(this, lineCounts));
}
ExtractCompilerGenerated();
}
protected override void ExtractInitializers()
{
// Do not extract initializers for constructed types.
if (!IsSourceDeclaration) return;
var syntax = Syntax;
var initializer = syntax == null ? null : syntax.Initializer;
if (initializer == null) return;
Type initializerType;
var symbolInfo = Context.GetSymbolInfo(initializer);
switch (initializer.Kind())
{
case SyntaxKind.BaseConstructorInitializer:
initializerType = Type.Create(Context, symbol.ContainingType.BaseType);
break;
case SyntaxKind.ThisConstructorInitializer:
initializerType = ContainingType;
break;
default:
Context.ModelError(initializer, "Unknown initializer");
return;
}
var initInfo = new ExpressionInfo(Context,
new AnnotatedType(initializerType, Kinds.TypeAnnotation.NotAnnotated),
Context.Create(initializer.ThisOrBaseKeyword.GetLocation()),
Kinds.ExprKind.CONSTRUCTOR_INIT,
this,
-1,
false,
null);
var init = new Expression(initInfo);
var target = Constructor.Create(Context, (IMethodSymbol)symbolInfo.Symbol);
if (target == null)
{
Context.ModelError(symbol, "Unable to resolve call");
return;
}
Context.Emit(Tuples.expr_call(init, target));
int child = 0;
foreach (var arg in initializer.ArgumentList.Arguments)
{
Expression.Create(Context, arg.Expression, init, child++);
}
}
ConstructorDeclarationSyntax Syntax
{
get
{
return symbol.DeclaringSyntaxReferences.
Select(r => r.GetSyntax()).
OfType<ConstructorDeclarationSyntax>().
FirstOrDefault();
}
}
public new static Constructor Create(Context cx, IMethodSymbol constructor)
{
if (constructor == null) return null;
switch (constructor.MethodKind)
{
case MethodKind.StaticConstructor:
case MethodKind.Constructor:
return ConstructorFactory.Instance.CreateEntity(cx, constructor);
default:
throw new InternalError(constructor, "Attempt to create a Constructor from a symbol that isn't a constructor");
}
}
public override IId Id
{
get
{
return new Key(tb =>
{
if (symbol.IsStatic) tb.Append("static");
tb.Append(ContainingType);
AddParametersToId(Context, tb, symbol);
tb.Append(";constructor");
});
}
}
ConstructorDeclarationSyntax GetSyntax() =>
symbol.DeclaringSyntaxReferences.Select(r => r.GetSyntax()).OfType<ConstructorDeclarationSyntax>().FirstOrDefault();
public override Microsoft.CodeAnalysis.Location FullLocation => ReportingLocation;
public override Microsoft.CodeAnalysis.Location ReportingLocation
{
get
{
var syn = GetSyntax();
if (syn != null)
{
return syn.Identifier.GetLocation();
}
else if (symbol.IsImplicitlyDeclared)
{
return ContainingType.ReportingLocation;
}
else
{
return symbol.ContainingType.Locations.FirstOrDefault();
}
}
}
class ConstructorFactory : ICachedEntityFactory<IMethodSymbol, Constructor>
{
public static readonly ConstructorFactory Instance = new ConstructorFactory();
public Constructor Create(Context cx, IMethodSymbol init) => new Constructor(cx, init);
}
}
}