Skip to content

Commit

Permalink
Static Invocations Running
Browse files Browse the repository at this point in the history
  • Loading branch information
akshita31 committed Nov 29, 2017
1 parent aab82ac commit a6bcde1
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 21 deletions.
9 changes: 9 additions & 0 deletions src/OmniSharp.Roslyn.CSharp/OmniSharp.Roslyn.CSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,17 @@
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<LangVersion>latest</LangVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<LangVersion>latest</LangVersion>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\OmniSharp.Abstractions\OmniSharp.Abstractions.csproj" />
<ProjectReference Include="..\OmniSharp.Cake\OmniSharp.Cake.csproj" />
<ProjectReference Include="..\OmniSharp.Roslyn\OmniSharp.Roslyn.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
namespace OmniSharp.Roslyn.CSharp.Services.Signatures
{
static internal class CheckForStatic
{
public static bool IsInStaticContext(this SyntaxNode node)
{
// this/base calls are always static.
if (node.FirstAncestorOrSelf<ConstructorInitializerSyntax>() != null)
{
return true;
}

var memberDeclaration = node.FirstAncestorOrSelf<MemberDeclarationSyntax>();
if (memberDeclaration == null)
{
return false;
}

switch (memberDeclaration.Kind())
{
case SyntaxKind.MethodDeclaration:
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.EventDeclaration:
case SyntaxKind.IndexerDeclaration:
return GetModifiers(memberDeclaration).Any(SyntaxKind.StaticKeyword);

case SyntaxKind.PropertyDeclaration:
return GetModifiers(memberDeclaration).Any(SyntaxKind.StaticKeyword) ||
node.IsFoundUnder((PropertyDeclarationSyntax p) => p.Initializer);

case SyntaxKind.FieldDeclaration:
case SyntaxKind.EventFieldDeclaration:
// Inside a field one can only access static members of a type (unless it's top-level).
return !memberDeclaration.Parent.IsKind(SyntaxKind.CompilationUnit);

case SyntaxKind.DestructorDeclaration:
return false;
}

// Global statements are not a static context.
if (node.FirstAncestorOrSelf<GlobalStatementSyntax>() != null)
{
return false;
}

// any other location is considered static
return true;
}
public static SyntaxTokenList GetModifiers(SyntaxNode member)
{
if (member != null)
{
switch (member.Kind())
{
case SyntaxKind.EnumDeclaration:
return ((EnumDeclarationSyntax)member).Modifiers;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.StructDeclaration:
return ((TypeDeclarationSyntax)member).Modifiers;
case SyntaxKind.DelegateDeclaration:
return ((DelegateDeclarationSyntax)member).Modifiers;
case SyntaxKind.FieldDeclaration:
return ((FieldDeclarationSyntax)member).Modifiers;
case SyntaxKind.EventFieldDeclaration:
return ((EventFieldDeclarationSyntax)member).Modifiers;
case SyntaxKind.ConstructorDeclaration:
return ((ConstructorDeclarationSyntax)member).Modifiers;
case SyntaxKind.DestructorDeclaration:
return ((DestructorDeclarationSyntax)member).Modifiers;
case SyntaxKind.PropertyDeclaration:
return ((PropertyDeclarationSyntax)member).Modifiers;
case SyntaxKind.EventDeclaration:
return ((EventDeclarationSyntax)member).Modifiers;
case SyntaxKind.IndexerDeclaration:
return ((IndexerDeclarationSyntax)member).Modifiers;
case SyntaxKind.OperatorDeclaration:
return ((OperatorDeclarationSyntax)member).Modifiers;
case SyntaxKind.ConversionOperatorDeclaration:
return ((ConversionOperatorDeclarationSyntax)member).Modifiers;
case SyntaxKind.MethodDeclaration:
return ((MethodDeclarationSyntax)member).Modifiers;
case SyntaxKind.GetAccessorDeclaration:
case SyntaxKind.SetAccessorDeclaration:
case SyntaxKind.AddAccessorDeclaration:
case SyntaxKind.RemoveAccessorDeclaration:
return ((AccessorDeclarationSyntax)member).Modifiers;
}
}

return default;
}
public static bool IsFoundUnder<TParent>(this SyntaxNode node, Func<TParent, SyntaxNode> childGetter)
where TParent : SyntaxNode
{
var ancestor = node.GetAncestor<TParent>();
if (ancestor == null)
{
return false;
}

var child = childGetter(ancestor);

// See if node passes through child on the way up to ancestor.
return node.GetAncestorsOrThis<SyntaxNode>().Contains(child);
}
public static TNode GetAncestor<TNode>(this SyntaxNode node)
where TNode : SyntaxNode
{
var current = node.Parent;
while (current != null)
{
if (current is TNode tNode)
{
return tNode;
}

current = current.GetParent();
}

return null;
}
private static SyntaxNode GetParent(this SyntaxNode node)
{
return node is IStructuredTriviaSyntax trivia ? trivia.ParentTrivia.Token.Parent : node.Parent;
}

public static TNode FirstAncestorOrSelfUntil<TNode>(this SyntaxNode node, Func<SyntaxNode, bool> predicate)
where TNode : SyntaxNode
{
for (var current = node; current != null; current = current.GetParent())
{
if (current is TNode tnode)
{
return tnode;
}

if (predicate(current))
{
break;
}
}

return default;
}

public static TNode GetAncestorOrThis<TNode>(this SyntaxNode node)
where TNode : SyntaxNode
{
return node?.GetAncestorsOrThis<TNode>().FirstOrDefault();
}

public static IEnumerable<TNode> GetAncestorsOrThis<TNode>(this SyntaxNode node)
where TNode : SyntaxNode
{
var current = node;
while (current != null)
{
if (current is TNode tNode)
{
yield return tNode;
}

current = current.GetParent();
}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,26 @@ internal class InvocationContext
public SyntaxNode Receiver { get; }
public IEnumerable<TypeInfo> ArgumentTypes { get; }
public IEnumerable<SyntaxToken> Separators { get; }
public bool IsStatic { get; }

public InvocationContext(SemanticModel semModel, int position, SyntaxNode receiver, ArgumentListSyntax argList)
public InvocationContext(SemanticModel semModel, int position, SyntaxNode receiver, ArgumentListSyntax argList, bool isStatic)
{
SemanticModel = semModel;
Position = position;
Receiver = receiver;
ArgumentTypes = argList.Arguments.Select(argument => semModel.GetTypeInfo(argument.Expression));
Separators = argList.Arguments.GetSeparators();
IsStatic = isStatic;
}

public InvocationContext(SemanticModel semModel, int position, SyntaxNode receiver, AttributeArgumentListSyntax argList)
public InvocationContext(SemanticModel semModel, int position, SyntaxNode receiver, AttributeArgumentListSyntax argList, bool isStatic)
{
SemanticModel = semModel;
Position = position;
Receiver = receiver;
ArgumentTypes = argList.Arguments.Select(argument => semModel.GetTypeInfo(argument.Expression));
Separators = argList.Arguments.GetSeparators();
IsStatic = isStatic;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.LanguageServices;
using OmniSharp.Mef;
using OmniSharp.Models;
using OmniSharp.Models.SignatureHelp;
using System;


namespace OmniSharp.Roslyn.CSharp.Services.Signatures
{
Expand Down Expand Up @@ -67,24 +71,27 @@ public async Task<SignatureHelpResponse> Handle(SignatureHelpRequest request)
var throughExpression = ((MemberAccessExpressionSyntax)invocation.Receiver).Expression;
throughSymbol = invocation.SemanticModel.GetSpeculativeSymbolInfo(invocation.Position, throughExpression, SpeculativeBindingOption.BindAsExpression).Symbol;
throughType = invocation.SemanticModel.GetSpeculativeTypeInfo(invocation.Position, throughExpression, SpeculativeBindingOption.BindAsTypeOrNamespace).Type;
methodGroup = methodGroup.Where(m => (m.IsStatic && throughType != null) || (!m.IsStatic && (throughSymbol != null && !(throughSymbol is ITypeSymbol))));
var includeInstance = throughSymbol != null && !(throughSymbol is ITypeSymbol);
var includeStatic = (throughSymbol is INamedTypeSymbol) || throughType != null;
methodGroup = methodGroup.Where(m => (m.IsStatic && includeStatic) || (!m.IsStatic && includeInstance));
}
/* else if (invocation.Receiver is SimpleNameSyntax && invocationExpression.IsInStaticContext())

else if (invocation.Receiver is SimpleNameSyntax && invocation.IsStatic)
{
methodGroup = methodGroup.Where(m => m.IsStatic);
}
*/
foreach (var methodOverload in invocation.SemanticModel.GetMemberGroup(invocation.Receiver).OfType<IMethodSymbol>())

foreach (var methodOverload in methodGroup)
{
var signature = BuildSignature(methodOverload);
signaturesSet.Add(signature);

var score = InvocationScore(methodOverload, types);
if (score > bestScore)
{
bestScore = score;
bestScoredItem = signature;
}
var signature = BuildSignature(methodOverload);
signaturesSet.Add(signature);

var score = InvocationScore(methodOverload, types);
if (score > bestScore)
{
bestScore = score;
bestScoredItem = signature;
}
}
}

Expand All @@ -109,19 +116,19 @@ private async Task<InvocationContext> GetInvocation(Document document, Request r
if (node is InvocationExpressionSyntax invocation && invocation.ArgumentList.Span.Contains(position))
{
var semanticModel = await document.GetSemanticModelAsync();
return new InvocationContext(semanticModel, position, invocation.Expression, invocation.ArgumentList);
return new InvocationContext(semanticModel, position, invocation.Expression, invocation.ArgumentList, invocation.IsInStaticContext());
}

if (node is ObjectCreationExpressionSyntax objectCreation && objectCreation.ArgumentList.Span.Contains(position))
{
var semanticModel = await document.GetSemanticModelAsync();
return new InvocationContext(semanticModel, position, objectCreation, objectCreation.ArgumentList);
return new InvocationContext(semanticModel, position, objectCreation, objectCreation.ArgumentList,objectCreation.IsInStaticContext());
}

if (node is AttributeSyntax attributeSyntax && attributeSyntax.ArgumentList.Span.Contains(position))
{
var semanticModel = await document.GetSemanticModelAsync();
return new InvocationContext(semanticModel, position, attributeSyntax, attributeSyntax.ArgumentList);
return new InvocationContext(semanticModel, position, attributeSyntax, attributeSyntax.ArgumentList, attributeSyntax.IsInStaticContext());
}

node = node.Parent;
Expand Down Expand Up @@ -156,7 +163,7 @@ private int InvocationScore(IMethodSymbol symbol, IEnumerable<TypeInfo> types)
}
}

return score;
return score;
}

private static SignatureHelpItem BuildSignature(IMethodSymbol symbol)
Expand All @@ -178,5 +185,6 @@ private static SignatureHelpItem BuildSignature(IMethodSymbol symbol)

return signature;
}

}
}
4 changes: 2 additions & 2 deletions tests/OmniSharp.Roslyn.CSharp.Tests/SignatureHelpFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -661,11 +661,11 @@ public void M1(int a, int b) { }
class B : A
{
static void M1(int a,int b,int c)
void M1(int a,int b,int c)
{
M1($$)
}
public void M1(int a,int b,int c,int d) { }
static void M1(int a,int b,int c,int d) { }
}";
var actual = await GetSignatureHelp(source);
Assert.Equal(4, actual.Signatures.Count());
Expand Down

0 comments on commit a6bcde1

Please sign in to comment.