Skip to content

Commit

Permalink
Merge pull request #1 from MrLuje/moq
Browse files Browse the repository at this point in the history
Moq support
  • Loading branch information
MrLuje authored Feb 17, 2018
2 parents cad0186 + d51f84f commit 1ed0368
Show file tree
Hide file tree
Showing 17 changed files with 1,153 additions and 87 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ FakesAssemblies/
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
Expand Down
276 changes: 276 additions & 0 deletions .paket/Paket.Restore.targets

Large diffs are not rendered by default.

Binary file added .paket/paket.exe
Binary file not shown.
72 changes: 72 additions & 0 deletions .paket/paket.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>
<!-- Enable the restore command to run before builds -->
<RestorePackages Condition=" '$(RestorePackages)' == '' ">true</RestorePackages>
<PaketToolsPath>$(MSBuildThisFileDirectory)</PaketToolsPath>
<PaketRootPath>$(MSBuildThisFileDirectory)..\</PaketRootPath>
<PaketLockFilePath>$(PaketRootPath)paket.lock</PaketLockFilePath>
<PaketRestoreCacheFile>$(PaketRootPath)paket-files\paket.restore.cached</PaketRestoreCacheFile>
<MonoPath Condition="'$(MonoPath)' == '' And Exists('/Library/Frameworks/Mono.framework/Commands/mono')">/Library/Frameworks/Mono.framework/Commands/mono</MonoPath>
<MonoPath Condition="'$(MonoPath)' == ''">mono</MonoPath>
</PropertyGroup>

<PropertyGroup>
<!-- Paket command -->
<PaketExePath Condition=" '$(PaketExePath)' == '' AND Exists('$(PaketRootPath)paket.exe')">$(PaketRootPath)paket.exe</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' ">$(PaketToolsPath)paket.exe</PaketExePath>
<PaketCommand Condition=" '$(OS)' == 'Windows_NT'">"$(PaketExePath)"</PaketCommand>
<PaketCommand Condition=" '$(OS)' != 'Windows_NT' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"</PaketCommand>
</PropertyGroup>

<Choose> <!-- MyProject.fsproj.paket.references has the highest precedence -->
<When Condition="Exists('$(MSBuildProjectFullPath).paket.references')">
<PropertyGroup>
<PaketReferences>$(MSBuildProjectFullPath).paket.references</PaketReferences>
</PropertyGroup>
</When> <!-- MyProject.paket.references -->
<When Condition="Exists('$(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references')">
<PropertyGroup>
<PaketReferences>$(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references</PaketReferences>
</PropertyGroup>
</When> <!-- paket.references -->
<When Condition="Exists('$(MSBuildProjectDirectory)\paket.references')">
<PropertyGroup>
<PaketReferences>$(MSBuildProjectDirectory)\paket.references</PaketReferences>
</PropertyGroup>
</When> <!-- Set to empty if a reference file isn't found matching one of the 3 format options -->
<Otherwise>
<PropertyGroup>
<PaketReferences></PaketReferences>
</PropertyGroup>
</Otherwise>
</Choose>

<PropertyGroup>
<!-- Commands -->
<RestoreCommand>$(PaketCommand) restore --references-file "$(PaketReferences)"</RestoreCommand>
<!-- We need to ensure packages are restored prior to assembly resolve -->
<BuildDependsOn Condition="$(RestorePackages) == 'true'">RestorePackages; $(BuildDependsOn);</BuildDependsOn>
</PropertyGroup>
<Target Name="RestorePackages">
<PropertyGroup>
<PaketRestoreRequired>true</PaketRestoreRequired>
</PropertyGroup>

<PropertyGroup Condition="Exists('$(PaketRestoreCacheFile)') ">
<PaketRestoreCachedHash>$([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)'))</PaketRestoreCachedHash>
<PaketRestoreLockFileHash>$([System.IO.File]::ReadAllText('$(PaketLockFilePath)'))</PaketRestoreLockFileHash>
<PaketRestoreRequired>true</PaketRestoreRequired>
<PaketRestoreRequired Condition=" '$(PaketRestoreLockFileHash)' == '$(PaketRestoreCachedHash)' ">false</PaketRestoreRequired>
<PaketRestoreRequired Condition=" '$(PaketRestoreLockFileHash)' == '' ">true</PaketRestoreRequired>
</PropertyGroup>

<Exec Command="$(RestoreCommand)"
IgnoreStandardErrorWarningFormat="true"
WorkingDirectory="$(PaketRootPath)"
ContinueOnError="false"
Condition=" '$(PaketRestoreRequired)' == 'true' AND Exists('$(PaketReferences)') AND '$(PaketReferences)' != '' "
/>
</Target>
</Project>
8 changes: 7 additions & 1 deletion Mocking.Helpers.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2027
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocking.Helpers", "Mocking.Helpers\Mocking.Helpers\Mocking.Helpers.csproj", "{49B470A9-EFE4-4470-A1B3-154947BC7453}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mocking.Helpers", "Mocking.Helpers\Mocking.Helpers\Mocking.Helpers.csproj", "{49B470A9-EFE4-4470-A1B3-154947BC7453}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocking.Helpers.Vsix", "Mocking.Helpers\Mocking.Helpers.Vsix\Mocking.Helpers.Vsix.csproj", "{BB53B565-6B97-4B6E-806A-DD072023AE6F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{C7A83F62-91BD-4A9B-AF0D-DAE64BE55B4A}"
ProjectSection(SolutionItems) = preProject
paket.dependencies = paket.dependencies
paket.lock = paket.lock
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="Resources\moq.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 23 additions & 18 deletions Mocking.Helpers/Mocking.Helpers.Vsix/source.extension.vsixmanifest
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="Mocking.Helpers..9e3b8d25-be45-4b82-9e8d-eeceadcc1af3" Version="1.0" Language="en-US" Publisher="vince"/>
<DisplayName>Mocking.Helpers</DisplayName>
<Description xml:space="preserve">This is a sample code refactoring extension for the .NET Compiler Platform ("Roslyn").</Description>
</Metadata>
<Installation>
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[15.0,)" />
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="[4.5,)" />
</Dependencies>
<Assets>
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="Mocking.Helpers" Path="|Mocking.Helpers|"/>
</Assets>
<Prerequisites>
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[15.0,16.0)" DisplayName="Visual Studio core editor" />
<Prerequisite Id="Microsoft.VisualStudio.Component.Roslyn.LanguageServices" Version="[15.0,16.0)" DisplayName="Roslyn Language Services" />
</Prerequisites>
<Metadata>
<Identity Id="Mocking.Helpers..9e3b8d25-be45-4b82-9e8d-eeceadcc1af3" Version="1.0.0.0" Language="en-US" Publisher="MrLuje"/>
<DisplayName>Mocking.Helpers</DisplayName>
<Description xml:space="preserve">Collection of features to help working with various mocking framework</Description>
<MoreInfo>https://github.com/MrLuje/Mocking.Helpers</MoreInfo>
<PreviewImage>Resources\moq.png</PreviewImage>
<Tags>mocking roslyn moq</Tags>
</Metadata>
<Installation>
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[15.0,16.0)" />
<InstallationTarget Version="[15.0,16.0)" Id="Microsoft.VisualStudio.Pro" />
<InstallationTarget Version="[15.0,16.0)" Id="Microsoft.VisualStudio.Enterprise" />
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="[4.5,)" />
</Dependencies>
<Assets>
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="Mocking.Helpers" Path="|Mocking.Helpers|"/>
</Assets>
<Prerequisites>
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[15.0,16.0)" DisplayName="Visual Studio core editor" />
<Prerequisite Id="Microsoft.VisualStudio.Component.Roslyn.LanguageServices" Version="[15.0,16.0)" DisplayName="Roslyn Language Services" />
</Prerequisites>
</PackageManifest>
81 changes: 81 additions & 0 deletions Mocking.Helpers/Mocking.Helpers/CompletionService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Mocking.Helpers.Moq;
using System;
using System.Linq;

namespace Mocking.Helpers
{
public class CompletionService
{
private CompletionContext _context;
private CompletionItemRules _preselectCompletions;
private CompletionItemRules _defaultCompletions;
private readonly SyntaxToken _token;
private readonly SemanticModel _semanticModel;
private readonly MoqProvider _provider;

public CompletionService(CompletionContext context, SyntaxToken token, SemanticModel semanticModel, MoqProvider provider)
{
_context = context;
_token = token;
_semanticModel = semanticModel;

_preselectCompletions = CompletionItemRules.Default.WithMatchPriority(MatchPriority.Preselect).WithSelectionBehavior(CompletionItemSelectionBehavior.SoftSelection);
_defaultCompletions = CompletionItemRules.Default.WithSelectionBehavior(CompletionItemSelectionBehavior.SoftSelection);
_provider = provider;
}

public void AddSuggestionsForMethod(IMethodSymbol methodSymbol, ArgumentListSyntax arguments)
{
switch (this._token.Kind())
{
// Starting parenthesis before parameters
case SyntaxKind.OpenParenToken:
AddSuggestionsForAllParameters(methodSymbol, arguments);
break;
// Somewhere after first parameter
default:
AddSuggestionsForNextParameters(methodSymbol, arguments);
break;
}
}

private void AddSuggestionsForAllParameters(IMethodSymbol methodSymbol, ArgumentListSyntax arguments)
{
// Suggestion for all parameters
this.AddSuggestion(this._provider.GenerateSuggestionForParameterWildcard(this._semanticModel, methodSymbol, arguments));

// Highlight suggestion of first parameter
if (methodSymbol.Parameters.Length > 1)
{
this.AddDefaultSuggestion(this._provider.GenerateSuggestionForParameterWildcardOfType(_semanticModel, methodSymbol.Parameters[0].Type, arguments));
}
}

private void AddSuggestionsForNextParameters(IMethodSymbol methodSymbol, ArgumentListSyntax arguments)
{
var currentParamIndex = arguments.ChildTokens()
.Where(t => t.IsKind(SyntaxKind.CommaToken))
.ToList()
.IndexOf(this._token);
var nextParamIndex = currentParamIndex + 1;

if (methodSymbol.Parameters.Length <= nextParamIndex) return;

this.AddDefaultSuggestion(this._provider.GenerateSuggestionForParameterWildcardOfType(_semanticModel, methodSymbol.Parameters[nextParamIndex].Type, arguments));
}

void AddSuggestion(string suggestion)
{
this._context.AddItem(CompletionItem.Create(suggestion, rules: _preselectCompletions));
}

void AddDefaultSuggestion(string suggestion)
{
this._context.AddItem(CompletionItem.Create(suggestion, rules: _defaultCompletions));
}
}
}
10 changes: 4 additions & 6 deletions Mocking.Helpers/Mocking.Helpers/Mocking.Helpers.csproj
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="2.4.0" PrivateAssets="all" />
<PackageReference Update="NETStandard.Library" PrivateAssets="all" />
</ItemGroup>

</Project>
<Import Project="..\..\.paket\Paket.Restore.targets" />
</Project>

This file was deleted.

65 changes: 65 additions & 0 deletions Mocking.Helpers/Mocking.Helpers/Moq/MoqIsAnyCompletion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Mocking.Helpers.Moq
{
[ExportCompletionProvider(nameof(MoqIsAnyCompletion), LanguageNames.CSharp)]
public class MoqIsAnyCompletion : CompletionProvider
{
private MoqProvider _provider;

public MoqIsAnyCompletion()
{
this._provider = new MoqProvider();
}

internal bool IsMoqSetupMethod(InvocationExpressionSyntax invocation)
{
return SyntaxHelpers.IsMethodNamed(invocation, this._provider.MockingMethodName);
}

public override async Task ProvideCompletionsAsync(CompletionContext context)
{
try
{
if (!context.Document.SupportsSemanticModel || !context.Document.SupportsSyntaxTree) return;

var hasMoqReferenced = context.Document.Project.MetadataReferences.Any(r => r.Display.Contains(this._provider.AssemblyName));
if (!hasMoqReferenced) return;

var syntaxRoot = await context.Document.GetSyntaxRootAsync();
var token = SyntaxHelpers.GetSelectedTokens(syntaxRoot, context.Position);

// ?ot in an opened method
if (token.Parent == null) return;

var mockedMethodArgumentList = token.Parent as ArgumentListSyntax;
var setupMethodInvocation = mockedMethodArgumentList.Ancestors()
.OfType<InvocationExpressionSyntax>()
.Where(IsMoqSetupMethod)
.FirstOrDefault();

if (setupMethodInvocation == null) return;

var semanticModel = await context.Document.GetSemanticModelAsync();
var matchingMockedMethods = SyntaxHelpers.GetCandidatesMockedMethodSignatures(semanticModel, setupMethodInvocation);

var completionService = new CompletionService(context, token, semanticModel, this._provider);

foreach (IMethodSymbol matchingMockedMethodSymbol in matchingMockedMethods)
{
completionService.AddSuggestionsForMethod(matchingMockedMethodSymbol, mockedMethodArgumentList);
}
}
catch
{
}
}
}
}
Loading

0 comments on commit 1ed0368

Please sign in to comment.