diff --git a/.devcontainer.json b/.devcontainer.json deleted file mode 100644 index 2ca757d7..00000000 --- a/.devcontainer.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - // Install ESLint and Peacock extensions - "extensions": [ - "ms-vscode.csharp" - ] -} \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..b8062b19 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,9 @@ +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: +- package-ecosystem: nuget + directory: /src/ + schedule: + interval: weekly \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..73230659 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,96 @@ +name: build +on: + push: + branches: [ '*' ] + pull_request: + types: [opened, synchronize, reopened] + +env: + DOTNET_NOLOGO: true + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + +defaults: + run: + shell: bash + +jobs: + build: + name: ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - name: 🤘 checkout + uses: actions/checkout@v2 + - name: ⚙ dotnet 5.0 rc2 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.100-rc.2.20479.15 + - name: 🙏 build + run: dotnet msbuild -r -m:1 -bl:build.binlog -p:versionsuffix="$GITHUB_REF.$GITHUB_RUN_NUMBER" + - name: 🧪 test win + run: dotnet test --no-build --collect:"XPlat Code Coverage" + if: matrix.os == 'windows-latest' + - name: 🧪 test !win + run: dotnet test --no-build -f net5.0 --collect:"XPlat Code Coverage" + if: matrix.os != 'windows-latest' + - name: 🔍 coverage + if: 'false' + run: bash <(curl -s https://codecov.io/bash) + - name: 🔼 logs + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.os }} + path: | + *.binlog + **/coverage.cobertura.xml + - name: 🔼 packages + uses: actions/upload-artifact@v2 + with: + name: bin + path: bin/*.nupkg + + acceptance: + name: acceptance-${{ matrix.os }} + runs-on: ${{ matrix.os }} + needs: build + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - name: 🤘 checkout + uses: actions/checkout@v2 + - name: 🔽 packages + uses: actions/download-artifact@v2 + with: + name: bin + path: bin + - name: ⚙ dotnet 5.0 rc2 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.100-rc.2.20479.15 + - name: 🧪 test + run: dotnet test -m:1 -p:versionsuffix="$GITHUB_REF.$GITHUB_RUN_NUMBER" + working-directory: src/Acceptance + + push: + name: push nuget.ci + runs-on: ubuntu-latest + needs: [build, acceptance] + steps: + - name: 🔽 packages + uses: actions/download-artifact@v2 + with: + name: bin + path: bin + - name: ⚙ dotnet 2.1.x + uses: actions/setup-dotnet@v1 + if: matrix.os == 'ubuntu-latest' + with: + dotnet-version: 2.1.x + - name: 🚀 sleet + run: | + dotnet tool install -g --version 3.2.0 sleet + sleet push bin --config none -f --verbose -p "SLEET_FEED_CONTAINER=nuget" -p "SLEET_FEED_CONNECTIONSTRING=${{ secrets.SLEET_CONNECTION }}" -p "SLEET_FEED_TYPE=azure" \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..48f78e19 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,31 @@ +name: release +on: + release: + types: [created] + +env: + DOTNET_NOLOGO: true + Configuration: Release + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: 🤘 checkout + uses: actions/checkout@v2 + - name: ⚙ dotnet 5.0 rc2 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.100-rc.2.20479.15 + - name: 🙏 build + run: dotnet msbuild -r -m:1 -bl:build.binlog -p:version=${GITHUB_REF#refs/*/v} + - name: 🧪 test net5.0 + run: dotnet test --no-build -f net5.0 + - name: 🔼 logs + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.os }} + path: '*.binlog' + - name: 🚀 nuget + run: dotnet nuget push ./bin/**/*.nupkg -s https://api.nuget.org/v3/index.json -k ${{secrets.NUGET_API_KEY}} --skip-duplicate \ No newline at end of file diff --git a/.gitignore b/.gitignore index 74671e66..06c3a592 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,4 @@ obj *.log *.binlog *.rsp -/src/Usage -/src/Backup -/src/TestResults +TestResults diff --git a/Moq.sln b/Moq.sln new file mode 100644 index 00000000..a5b1359f --- /dev/null +++ b/Moq.sln @@ -0,0 +1,100 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28417.167 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq", "src\Moq\Moq.csproj", "{65F3AB28-9A74-405E-83B2-420D5AD5A459}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2093478C-CEA6-4034-BCDE-EDC7A5DD4532}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + src\Directory.Build.props = src\Directory.Build.props + Directory.Build.rsp = Directory.Build.rsp + src\Directory.Build.targets = src\Directory.Build.targets + src\Directory.Packages.props = src\Directory.Packages.props + README.md = README.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.Sdk", "src\Moq.Sdk\Moq.Sdk.csproj", "{80DE507E-3AF9-4360-9E56-66523B01FB51}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.Sdk.Tests", "src\Moq.Sdk.Tests\Moq.Sdk.Tests.csproj", "{EB66BC5E-4072-4F26-9772-979D8561883F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.Tests", "src\Moq.Tests\Moq.Tests.csproj", "{9A09225F-E0BC-4890-BED4-D9F6F5DAC146}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.DynamicProxy", "src\Moq.DynamicProxy\Moq.DynamicProxy.csproj", "{BA43EF2F-6CA8-49A5-A4E7-C2FF71928F05}" +EndProject +Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "Moq.Package", "src\Moq.Package\Moq.Package.msbuildproj", "{D486033C-1CCF-47BB-BDA6-28EA08018CDE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.StaticProxy", "src\Moq.StaticProxy\Moq.StaticProxy.csproj", "{0580AEDE-7661-4311-9A40-EAD4CD485742}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.CodeAnalysis", "src\Moq.CodeAnalysis\Moq.CodeAnalysis.csproj", "{1D05F2B9-B67D-4EFE-B4FF-D7F6907C2701}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.StaticProxy.UnitTests", "src\Moq.StaticProxy.UnitTests\Moq.StaticProxy.UnitTests.csproj", "{36A3DD24-4B67-4A9E-83F8-C4794336460F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{73262D37-1503-4F10-B7B2-E945523828E4}" + ProjectSection(SolutionItems) = preProject + azure-pipelines.yml = azure-pipelines.yml + .github\workflows\build.yml = .github\workflows\build.yml + .github\dependabot.yml = .github\dependabot.yml + .github\workflows\release.yml = .github\workflows\release.yml + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moq.CodeAnalysis.UnitTests", "src\Moq.CodeAnalysis.UnitTests\Moq.CodeAnalysis.UnitTests.csproj", "{7EFC63B5-6978-40C9-8FEF-4FEEB4019B4C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {65F3AB28-9A74-405E-83B2-420D5AD5A459}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65F3AB28-9A74-405E-83B2-420D5AD5A459}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65F3AB28-9A74-405E-83B2-420D5AD5A459}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65F3AB28-9A74-405E-83B2-420D5AD5A459}.Release|Any CPU.Build.0 = Release|Any CPU + {80DE507E-3AF9-4360-9E56-66523B01FB51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80DE507E-3AF9-4360-9E56-66523B01FB51}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80DE507E-3AF9-4360-9E56-66523B01FB51}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80DE507E-3AF9-4360-9E56-66523B01FB51}.Release|Any CPU.Build.0 = Release|Any CPU + {EB66BC5E-4072-4F26-9772-979D8561883F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EB66BC5E-4072-4F26-9772-979D8561883F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EB66BC5E-4072-4F26-9772-979D8561883F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EB66BC5E-4072-4F26-9772-979D8561883F}.Release|Any CPU.Build.0 = Release|Any CPU + {9A09225F-E0BC-4890-BED4-D9F6F5DAC146}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A09225F-E0BC-4890-BED4-D9F6F5DAC146}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A09225F-E0BC-4890-BED4-D9F6F5DAC146}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A09225F-E0BC-4890-BED4-D9F6F5DAC146}.Release|Any CPU.Build.0 = Release|Any CPU + {BA43EF2F-6CA8-49A5-A4E7-C2FF71928F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA43EF2F-6CA8-49A5-A4E7-C2FF71928F05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA43EF2F-6CA8-49A5-A4E7-C2FF71928F05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA43EF2F-6CA8-49A5-A4E7-C2FF71928F05}.Release|Any CPU.Build.0 = Release|Any CPU + {D486033C-1CCF-47BB-BDA6-28EA08018CDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D486033C-1CCF-47BB-BDA6-28EA08018CDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D486033C-1CCF-47BB-BDA6-28EA08018CDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D486033C-1CCF-47BB-BDA6-28EA08018CDE}.Release|Any CPU.Build.0 = Release|Any CPU + {0580AEDE-7661-4311-9A40-EAD4CD485742}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0580AEDE-7661-4311-9A40-EAD4CD485742}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0580AEDE-7661-4311-9A40-EAD4CD485742}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0580AEDE-7661-4311-9A40-EAD4CD485742}.Release|Any CPU.Build.0 = Release|Any CPU + {1D05F2B9-B67D-4EFE-B4FF-D7F6907C2701}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1D05F2B9-B67D-4EFE-B4FF-D7F6907C2701}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1D05F2B9-B67D-4EFE-B4FF-D7F6907C2701}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1D05F2B9-B67D-4EFE-B4FF-D7F6907C2701}.Release|Any CPU.Build.0 = Release|Any CPU + {36A3DD24-4B67-4A9E-83F8-C4794336460F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36A3DD24-4B67-4A9E-83F8-C4794336460F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36A3DD24-4B67-4A9E-83F8-C4794336460F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36A3DD24-4B67-4A9E-83F8-C4794336460F}.Release|Any CPU.Build.0 = Release|Any CPU + {7EFC63B5-6978-40C9-8FEF-4FEEB4019B4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7EFC63B5-6978-40C9-8FEF-4FEEB4019B4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7EFC63B5-6978-40C9-8FEF-4FEEB4019B4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EFC63B5-6978-40C9-8FEF-4FEEB4019B4C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {73262D37-1503-4F10-B7B2-E945523828E4} = {2093478C-CEA6-4034-BCDE-EDC7A5DD4532} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DA4CFD03-827D-482B-9304-83456D2A8115} + EndGlobalSection +EndGlobal diff --git a/NuGet.Config b/NuGet.Config deleted file mode 100644 index 1436d285..00000000 --- a/NuGet.Config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/README.md b/README.md index 03162b19..c336a856 100644 --- a/README.md +++ b/README.md @@ -2,57 +2,55 @@ The most popular and friendly mocking framework for .NET -[![CoreBuild Standard](https://img.shields.io/badge/√_corebuild-standard-blue.svg)](http://www.corebuild.io) -[![Build Status](https://dev.azure.com/kzu/oss/_apis/build/status/moq?branchName=master)](https://dev.azure.com/kzu/oss/_build/latest?definitionId=20&branchName=master) -[![Tests](https://img.shields.io/azure-devops/tests/kzu/oss/20.svg?compact_message&logo=azure-pipelines)](https://dev.azure.com/kzu/oss/_build/latest?definitionId=20&branchName=master&view=results) +[![Version](https://img.shields.io/endpoint?url=https://shields.kzu.io/vpre/Moq/main&label=nuget.ci&color=brightgreen)](https://pkg.kzu.io/index.json) +[![Status](https://github.com/moq/moq/workflows/build/badge.svg?branch=main)](https://github.com/moq/moq/actions?query=branch%3Amain+workflow%3Abuild+) [![License](https://img.shields.io/github/license/moq/moq.svg)](https://github.com/moq/moq/blob/master/LICENSE) -[![Join the chat at https://gitter.im/moq/moq](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/moq/moq?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Follow on Twitter](https://img.shields.io/twitter/follow/moqthis.svg?style=social&label=Follow)](http://twitter.com/intent/user?screen_name=moqthis) +[![Discord Chat](https://img.shields.io/badge/chat-on%20discord-7289DA.svg)](https://discord.gg/AfGsdRa) +[![GitHub](https://img.shields.io/badge/-source-181717.svg?logo=GitHub)](https://github.com/moq/moq) -This repository supports [corebuild](http://www.corebuild.io) for configure/build/test from `msbuild`. > **IMPORTANT**: this repository is for the *upcoming* version of Moq. Issues and source for the current stable Moq v4.x are at https://github.com/moq/moq4 -CI package feed: http://kzu.nuget.cloud/index.json (CDN) or https://kzu.blob.core.windows.net/nuget/index.json (blob). +CI package feed: https://pkg.kzu.io/index.json ## Building the repository ``` -msbuild /t:configure -msbuild +dotnet msbuild ``` -The default target is `Help`, which will render the documentation for the build itself and what targets are available. -Since this is a [corebuild](http://www.corebuild.io) standard repository, you can run: +Running tests: ``` -msbuild /t:configure -msbuild /t:build -msbuild /t:test +dotnet test ``` ## Testing built packages locally -Release builds will produce packages. In Debug builds, you will need to right-click and `Pack` the relevant project, -such as `Moq.Package` (which will also pack its dependencies like `Stunts.Package`). These packages will be dropped -in the `out` folder in the repository root directory. To test these packages you can just add a package source +You can either build from command line or explicitly Pack (from the context menu) the *Moq.Package* project. + +Packages are generated in the `bin` folder in the repository root. To test these packages you can just add a package source pointing to it. You can also just place a `NuGet.Config` like the following anywhere above the directory with the test solution(s): ```xml - + ``` -Every time the packages are produced, the local nuget cache is cleared, so that a subsequent restore in VS will -automatically cause the updated version to be unpacked again. If versions change between package builds, you can -just reference them with a wildcard so the latest will automatically be chosen, such as: +You can also do use project properties (or a *Directory.Build.props* to affect an entire folder hierarchy) with: ```xml - - - + + + https://api.nuget.org/v3/index.json;$(RestoreSources) + [cloned repo dir]\bin;$(RestoreSources) + + ``` + +Every time the packages are produced, the local nuget cache is cleared, so that a subsequent restore in VS will +automatically cause the updated version to be unpacked again. The locally built version will always have the version [42.42.42](https://en.wikipedia.org/wiki/42_(number)#The_Hitchhiker's_Guide_to_the_Galaxy). \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index b5ace6f6..00000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,129 +0,0 @@ -trigger: - batch: false - branches: - include: - - master - - features/* - - releases/* - - dev/* - paths: - exclude: - - docs -pr: - - master - - features/* - - releases/* - -variables: -- group: Sleet -- name: Configuration - value: Release - -stages: - -- stage: Build - jobs: - - job: Build - pool: - vmImage: 'windows-2019' - steps: - - checkout: self - clean: true - - - task: MSBuild@1 - displayName: Restore Script - inputs: - solution: build.proj - configuration: $(Configuration) - msbuildArguments: -t:restore - - - task: MSBuild@1 - displayName: Restore Solution - inputs: - solution: src/Moq.sln - configuration: $(Configuration) - msbuildArguments: -t:restore -bl:$(Build.ArtifactStagingDirectory)/logs/restore.binlog - - - task: MSBuild@1 - displayName: Set Version - inputs: - solution: src/Moq/Moq.Package/Moq.Package.msbuildproj - msbuildArguments: -t:Version -bl:$(Build.ArtifactStagingDirectory)/logs/setversion.binlog - - - task: MSBuild@1 - displayName: Build - inputs: - solution: src/Moq.sln - configuration: $(Configuration) - msbuildArguments: -p:PackOnBuild=true -p:PackageOutputPath=$(Build.ArtifactStagingDirectory)/pkg -bl:$(Build.ArtifactStagingDirectory)/logs/build.binlog - - - task: VSTest@2 - displayName: Test - inputs: - testAssemblyVer2: src/*/*/bin/*/*.Tests.dll - runInParallel: true - codeCoverageEnabled: true - publishRunAttachments: true - diagnosticsEnabled: false - rerunFailedTests: true - - - task: PublishBuildArtifacts@1 - displayName: Upload Packages - condition: always() - inputs: - PathtoPublish: $(Build.ArtifactStagingDirectory)/pkg - ArtifactName: packages - ArtifactType: Container - - - task: PublishBuildArtifacts@1 - displayName: Upload Logs - condition: always() - inputs: - PathtoPublish: $(Build.ArtifactStagingDirectory)/logs - ArtifactName: logs - ArtifactType: Container - -- stage: Deploy - variables: - - name: SleetVersion - value: 2.3.33 - jobs: - - deployment: Deploy - pool: - vmImage: 'windows-2019' - environment: sleet - strategy: - runOnce: - deploy: - steps: - - pwsh: | - $anyinstalled = (dotnet tool list -g | select-string sleet) -ne $null - Write-Host "##vso[task.setvariable variable=Sleet.AnyInstalled;]$anyinstalled" - - $sameinstalled = (dotnet tool list -g | select-string sleet | select-string $(SleetVersion)) -ne $null - Write-Host "##vso[task.setvariable variable=Sleet.SameInstalled;]$sameinstalled" - displayName: 'Check Sleet installed version' - - - task: DotNetCoreCLI@2 - displayName: 'Uninstall Sleet if necessary' - continueOnError: true - condition: and(eq(variables['Sleet.AnyInstalled'], 'True'), eq(variables['Sleet.SameInstalled'], 'False')) - inputs: - command: custom - custom: tool - arguments: 'uninstall -g Sleet' - - - task: DotNetCoreCLI@2 - displayName: 'Install Sleet if necessary' - condition: eq(variables['Sleet.SameInstalled'], 'False') - inputs: - command: custom - custom: tool - arguments: 'install --global Sleet --version $(SleetVersion)' - - - task: DownloadPipelineArtifact@2 - inputs: - artifactName: packages - - - script: 'sleet push --config none $(Pipeline.Workspace)/packages -f --verbose -p "SLEET_FEED_CONNECTIONSTRING=$(SLEET_FEED_CONNECTIONSTRING)"' - displayName: 'Push packages via Sleet' \ No newline at end of file diff --git a/build.proj b/build.proj deleted file mode 100644 index bd9c6a76..00000000 --- a/build.proj +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - Debug - net472 - - - - $(RestoreOutputPath)\ - Configuration=$(Configuration) - $(MSBuildProjectDirectory)\out - src\GitInfo.txt - $(MSBuildProjectDirectory)\src\Packages.props - - - - - - - - - - $(AdditionalProperties) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Acceptance/Acceptance.sln b/src/Acceptance/Acceptance.sln new file mode 100644 index 00000000..94bb1eb5 --- /dev/null +++ b/src/Acceptance/Acceptance.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30615.102 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B62AC629-EB97-4ACA-9130-A318C5B0EE41}" + ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Static", "Static\Static.csproj", "{11D3F1D8-C5DA-4FF6-9F28-F170BC69748B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dynamic", "Dynamic\Dynamic.csproj", "{ACF75738-6433-4FE3-9E7E-6506D34BEF03}" +EndProject +Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Dynamic.Basic", "Dynamic.Basic\Dynamic.Basic.vbproj", "{8CB8DB45-925F-4A9F-94A4-70F416E719B6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {11D3F1D8-C5DA-4FF6-9F28-F170BC69748B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {11D3F1D8-C5DA-4FF6-9F28-F170BC69748B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {11D3F1D8-C5DA-4FF6-9F28-F170BC69748B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {11D3F1D8-C5DA-4FF6-9F28-F170BC69748B}.Release|Any CPU.Build.0 = Release|Any CPU + {ACF75738-6433-4FE3-9E7E-6506D34BEF03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACF75738-6433-4FE3-9E7E-6506D34BEF03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACF75738-6433-4FE3-9E7E-6506D34BEF03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACF75738-6433-4FE3-9E7E-6506D34BEF03}.Release|Any CPU.Build.0 = Release|Any CPU + {8CB8DB45-925F-4A9F-94A4-70F416E719B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8CB8DB45-925F-4A9F-94A4-70F416E719B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CB8DB45-925F-4A9F-94A4-70F416E719B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8CB8DB45-925F-4A9F-94A4-70F416E719B6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4D227C00-ECBA-4191-99F8-5622198D7352} + EndGlobalSection +EndGlobal diff --git a/src/Acceptance/Directory.Build.props b/src/Acceptance/Directory.Build.props new file mode 100644 index 00000000..fe957239 --- /dev/null +++ b/src/Acceptance/Directory.Build.props @@ -0,0 +1,21 @@ + + + false + + + + + $(MSBuildThisFileDirectory)../../bin; + https://pkg.kzu.io/index.json; + https://api.nuget.org/v3/index.json + + + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../../../nugetizer/bin')); + $(RestoreSources) + + + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../../../stunts/bin')); + $(RestoreSources) + + + \ No newline at end of file diff --git a/src/Acceptance/Directory.Build.targets b/src/Acceptance/Directory.Build.targets new file mode 100644 index 00000000..1342991b --- /dev/null +++ b/src/Acceptance/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Acceptance/Dynamic.Basic/Dynamic.Basic.vbproj b/src/Acceptance/Dynamic.Basic/Dynamic.Basic.vbproj new file mode 100644 index 00000000..b10fd2b4 --- /dev/null +++ b/src/Acceptance/Dynamic.Basic/Dynamic.Basic.vbproj @@ -0,0 +1,16 @@ + + + + net472;net5.0 + Latest + + + + + + + + + + + \ No newline at end of file diff --git a/src/Samples/Moq.VisualBasic/IParser.vb b/src/Acceptance/Dynamic.Basic/IParser.vb similarity index 63% rename from src/Samples/Moq.VisualBasic/IParser.vb rename to src/Acceptance/Dynamic.Basic/IParser.vb index 02e0a6a5..1bc28d4c 100644 --- a/src/Samples/Moq.VisualBasic/IParser.vb +++ b/src/Acceptance/Dynamic.Basic/IParser.vb @@ -5,5 +5,5 @@ Public Interface IEnvironment End Interface Public Interface IParser - Function TryParse(ByVal input As String, ByRef result As DateTimeOffset) As Boolean + Function TryParse(input As String, ByRef result As DateTimeOffset) As Boolean End Interface \ No newline at end of file diff --git a/src/Acceptance/Dynamic.Basic/Model.vb b/src/Acceptance/Dynamic.Basic/Model.vb new file mode 100644 index 00000000..0eaddc20 --- /dev/null +++ b/src/Acceptance/Dynamic.Basic/Model.vb @@ -0,0 +1,33 @@ +Option Strict On +Imports System.Runtime.InteropServices + +Namespace Model + + Public Interface ICalculator + Event TurnedOn As EventHandler + ReadOnly Property IsOn As Boolean + Property Mode As CalculatorMode + Function Add(x As Integer, y As Integer) As Integer + Function Add(x As Integer, y As Integer, z As Integer) As Integer + Function TryAdd(ByRef x As Integer, ByRef y As Integer, ByRef z As Integer) As Boolean + Sub TurnOn() + Default Property Item(name As String) As Integer? + Sub Store(name As String, value As Integer) + Function Recall(name As String) As Integer? + Sub Clear(name As String) + ReadOnly Property Memory As ICalculatorMemory + End Interface + + Public Enum CalculatorMode + Standard + Scientific + End Enum + + Public Interface ICalculatorMemory + Sub Add(value As Integer) + Sub Subtract(value As Integer) + Sub Clear() + Function Recall() As Integer + End Interface + +End Namespace diff --git a/src/Acceptance/Dynamic.Basic/Tests.vb b/src/Acceptance/Dynamic.Basic/Tests.vb new file mode 100644 index 00000000..bc016bbd --- /dev/null +++ b/src/Acceptance/Dynamic.Basic/Tests.vb @@ -0,0 +1,44 @@ +Option Strict On +Option Infer On +Imports Moq +Imports Xunit +Imports System.Runtime.InteropServices +Imports Dynamic.Basic.Model + +Public Class Tests + + Public Sub StubProperties() + Dim calc = Mock.[Of](Of ICalculator)() + calc.Mode = CalculatorMode.Scientific + Assert.Equal(CalculatorMode.Scientific, calc.Mode) + calc.Mode = CalculatorMode.Standard + Assert.Equal(CalculatorMode.Standard, calc.Mode) + End Sub + + + Public Sub Recusive() + Dim calc = Mock.[Of](Of ICalculator)() + calc.Memory.Recall().Returns(5) + Assert.Equal(5, calc.Memory.Recall()) + End Sub + + + Public Sub RecusiveSetupScope() + Dim calc = Mock.[Of](Of ICalculator)() + + Using calc.Setup() + calc.Memory.Recall().Returns(5) + End Using + + Assert.Equal(5, calc.Memory.Recall()) + End Sub + + + Public Sub RecusiveSetup() + Dim calc = Mock.[Of](Of ICalculator, IDisposable)() + calc.Setup(Function(m) m.Memory.Recall()).Returns(5) + Assert.Equal(5, calc.Memory.Recall()) + Assert.IsAssignableFrom(Of IDisposable)(calc) + End Sub + +End Class diff --git a/src/Acceptance/Dynamic/Dynamic.csproj b/src/Acceptance/Dynamic/Dynamic.csproj new file mode 100644 index 00000000..133e0be3 --- /dev/null +++ b/src/Acceptance/Dynamic/Dynamic.csproj @@ -0,0 +1,22 @@ + + + + net472;net5.0 + + 8.0 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Acceptance/Static/Static.csproj b/src/Acceptance/Static/Static.csproj new file mode 100644 index 00000000..10c1922d --- /dev/null +++ b/src/Acceptance/Static/Static.csproj @@ -0,0 +1,16 @@ + + + + net472;net5.0 + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Acceptance/Static/Tests.cs b/src/Acceptance/Static/Tests.cs new file mode 100644 index 00000000..a2ed6941 --- /dev/null +++ b/src/Acceptance/Static/Tests.cs @@ -0,0 +1,107 @@ +using System; +using Moq; +using Sample; +using Xunit; + +public class Tests +{ + [Fact] + public void StubProperties() + { + var calc = Mock.Of(); + + calc.Mode = CalculatorMode.Scientific; + + Assert.Equal(CalculatorMode.Scientific, calc.Mode); + + calc.Mode = CalculatorMode.Standard; + + Assert.Equal(CalculatorMode.Standard, calc.Mode); + } + + [Fact(Skip = "Fluent recursive without setups not supported yet.")] + public void Recusive() + { + var calc = Mock.Of(); + + calc.Memory.Recall().Returns(5); + + Assert.Equal(5, calc.Memory.Recall()); + } + + [Fact] + public void RecusiveSetupScope() + { + var calc = Mock.Of(); + + using (calc.Setup()) + { + calc.Memory.Recall().Returns(5); + } + + Assert.Equal(5, calc.Memory.Recall()); + } + + [Fact] + public void RecusiveSetupBase() + { + var calc = Mock.Of(); + calc.Setup(m => m.Memory.Recall()).Returns(5); + + Assert.Equal(5, calc.Memory.Recall()); + Assert.IsAssignableFrom(calc); + } + + [Fact] + public void RecusiveSetup() + { + var calc = Mock.Of(); + calc.Setup(m => m.Memory.Recall()).Returns(5); + + Assert.Equal(5, calc.Memory.Recall()); + Assert.IsAssignableFrom(calc); + } + + [Fact] + public void DelegateOut() + { + var mock = Mock.Of(); + + mock.Setup(mock.TryParse) + .Returns((string input, out DateTimeOffset date) => DateTimeOffset.TryParse(input, out date)); + + var expected = DateTimeOffset.Now; + var value = expected.ToString("O"); + + Assert.True(mock.TryParse(value, out var actual)); + Assert.Equal(expected, actual); + } + + [Fact] + public void RecursiveDelegateOut() + { + var mock = Mock.Of(); + + var expected = DateTimeOffset.Now; + var value = expected.ToString("O"); + + mock.Setup(() => mock.Parser.TryParse) + .Returns((string input, out DateTimeOffset date) => DateTimeOffset.TryParse(value, out date)); + + Assert.True(mock.Parser.TryParse(value, out var actual)); + Assert.Equal(expected, actual); + } + + delegate bool TryParse(string input, out DateTimeOffset date); + +} + +public interface IEnvironment +{ + IParser Parser { get; } +} + +public interface IParser +{ + bool TryParse(string input, out DateTimeOffset date); +} diff --git a/src/Directory.Build.props b/src/Directory.Build.props index d62e7c5d..0e08f270 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,3 +1,83 @@ - - + + + + kzu + Copyright (C) Daniel Cazzulino $([System.DateTime]::Now.Year). All rights reserved. + false + MIT + + + 42.42.42 + $(VersionSuffix.Replace('refs/heads/', '')) + $(VersionSuffix.TrimEnd('.0123456789')) + $(VersionSuffix.Replace('refs/pull/', 'pr')) + $(VersionSuffix.Replace('/merge', '')) + $(VersionSuffix.Replace('/', '-')) + + true + true + + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\bin')) + + false + embedded + true + enable + + $(DefaultItemExcludes);*.binlog;*.zip;*.rsp;*.items + + + true + + https://pkg.kzu.io/index.json;https://api.nuget.org/v3/index.json;$(RestoreSources) + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\nugetizer\bin'));$(RestoreSources) + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\stunts\bin'));$(RestoreSources) + + $(MSBuildThisFileDirectory)Moq.snk + 002400000480000094000000060200000024000052534131000400000100010051155fd0ee280be78d81cc979423f1129ec5dd28edce9cd94fd679890639cad54c121ebdb606f8659659cd313d3b3db7fa41e2271158dd602bb0039a142717117fa1f63d93a2d288a1c2f920ec05c4858d344a45d48ebd31c1368ab783596b382b611d8c92f9c1b3d338296aa21b12f3bc9f34de87756100c172c52a24bad2db + 00352124762f2aa5 + true + + + true + true + true + true + + + true + + + + Preview + true + + + + false + true + + + + $(CI) + $(CI) + + + + + + + + + + + + + + GetTargetPath + + + \ No newline at end of file diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 8de2d61a..07afca9f 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -1,3 +1,75 @@ - - + + + + + 1.0.0 + $(VersionPrefix)-$(VersionSuffix) + $(VersionPrefix) + + + + $(DefineConstants);$(TargetFramework.ToUpperInvariant().TrimEnd('0').TrimEnd('.')) + + + + + + + + + + + + + + + + + + + $(SourceRevisionId.Substring(0, 9)) + + + + + + + + + + + + + + + + + $(Description) + + Built from $(RepositoryUrl)/tree/$(SourceRevisionId.Substring(0, 9)) + + + + + $(Description) + + + + + + + $(NuGetCache)\$(PackageId.ToLowerInvariant())\$(VersionPrefix) + + + + + + + \ No newline at end of file diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props new file mode 100644 index 00000000..565bf0d8 --- /dev/null +++ b/src/Directory.Packages.props @@ -0,0 +1,70 @@ + + + + 42.42.42-main.170 + 42.42.42 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/GitInfo.txt b/src/GitInfo.txt deleted file mode 100644 index 3f2e310e..00000000 --- a/src/GitInfo.txt +++ /dev/null @@ -1 +0,0 @@ -5.0.0-alpha \ No newline at end of file diff --git a/src/Moq.CodeAnalysis.UnitTests/Moq.CodeAnalysis.UnitTests.csproj b/src/Moq.CodeAnalysis.UnitTests/Moq.CodeAnalysis.UnitTests.csproj new file mode 100644 index 00000000..8187ef27 --- /dev/null +++ b/src/Moq.CodeAnalysis.UnitTests/Moq.CodeAnalysis.UnitTests.csproj @@ -0,0 +1,19 @@ + + + + net472;net5.0 + annotations + true + + + + + + + + + + + + + diff --git a/src/Moq/Moq.CodeAnalysis/MockNamingConvention.cs b/src/Moq.CodeAnalysis/MockNamingConvention.cs similarity index 96% rename from src/Moq/Moq.CodeAnalysis/MockNamingConvention.cs rename to src/Moq.CodeAnalysis/MockNamingConvention.cs index d248dddf..686e5b0f 100644 --- a/src/Moq/Moq.CodeAnalysis/MockNamingConvention.cs +++ b/src/Moq.CodeAnalysis/MockNamingConvention.cs @@ -1,5 +1,5 @@ using Moq.Sdk; -using Stunts; +using Stunts.CodeAnalysis; namespace Moq { diff --git a/src/Moq/Moq.CodeAnalysis/MockUnsupportedNestedTypeAnalyzer.cs b/src/Moq.CodeAnalysis/MockNestedTypeAnalyzer.cs similarity index 76% rename from src/Moq/Moq.CodeAnalysis/MockUnsupportedNestedTypeAnalyzer.cs rename to src/Moq.CodeAnalysis/MockNestedTypeAnalyzer.cs index 7dea629f..1a460949 100644 --- a/src/Moq/Moq.CodeAnalysis/MockUnsupportedNestedTypeAnalyzer.cs +++ b/src/Moq.CodeAnalysis/MockNestedTypeAnalyzer.cs @@ -11,12 +11,12 @@ namespace Stunts /// // TODO: F# [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] - public class MockUnsupportedNestedTypeAnalyzer : UnsupportedNestedTypeAnalyzer + public class MockUnsupportedNestedTypeAnalyzer : NestedTypeAnalyzer { /// /// Instantiates the analyzer with the default and /// for method invocations annotated with . /// - public MockUnsupportedNestedTypeAnalyzer() : base(new MockNamingConvention(), typeof(MockGeneratorAttribute)) { } + public MockUnsupportedNestedTypeAnalyzer() : base(typeof(MockGeneratorAttribute)) { } } } diff --git a/src/Moq/Moq.CodeAnalysis/MockValidateTypesAnalyzer.cs b/src/Moq.CodeAnalysis/MockValidateTypesAnalyzer.cs similarity index 100% rename from src/Moq/Moq.CodeAnalysis/MockValidateTypesAnalyzer.cs rename to src/Moq.CodeAnalysis/MockValidateTypesAnalyzer.cs diff --git a/src/Moq.CodeAnalysis/Moq.CodeAnalysis.csproj b/src/Moq.CodeAnalysis/Moq.CodeAnalysis.csproj new file mode 100644 index 00000000..0468d0f8 --- /dev/null +++ b/src/Moq.CodeAnalysis/Moq.CodeAnalysis.csproj @@ -0,0 +1,50 @@ + + + + + netstandard2.0 + analyzers\dotnet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + + Resources.Designer.cs + + + + \ No newline at end of file diff --git a/src/Moq/Moq.CodeAnalysis/RecursiveMockAnalyzer.cs b/src/Moq.CodeAnalysis/RecursiveMockAnalyzer.cs similarity index 100% rename from src/Moq/Moq.CodeAnalysis/RecursiveMockAnalyzer.cs rename to src/Moq.CodeAnalysis/RecursiveMockAnalyzer.cs diff --git a/src/Moq/Moq.CodeAnalysis/Properties/Resources.Designer.cs b/src/Moq.CodeAnalysis/Resources.Designer.cs similarity index 96% rename from src/Moq/Moq.CodeAnalysis/Properties/Resources.Designer.cs rename to src/Moq.CodeAnalysis/Resources.Designer.cs index 5c06bfaa..c15d69e6 100644 --- a/src/Moq/Moq.CodeAnalysis/Properties/Resources.Designer.cs +++ b/src/Moq.CodeAnalysis/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace Moq.Properties { +namespace Moq.CodeAnalysis { using System; @@ -19,7 +19,7 @@ namespace Moq.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Moq.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Moq.CodeAnalysis.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; diff --git a/src/Moq/Moq.CodeAnalysis/Properties/Resources.resx b/src/Moq.CodeAnalysis/Resources.resx similarity index 100% rename from src/Moq/Moq.CodeAnalysis/Properties/Resources.resx rename to src/Moq.CodeAnalysis/Resources.resx diff --git a/src/Moq/Moq.CodeFix/AssemblyInfo.cs b/src/Moq.CodeFix/AssemblyInfo.cs similarity index 100% rename from src/Moq/Moq.CodeFix/AssemblyInfo.cs rename to src/Moq.CodeFix/AssemblyInfo.cs diff --git a/src/Moq/Moq.CodeFix/CustomDelegateCodeFix.cs b/src/Moq.CodeFix/CustomDelegateCodeFix.cs similarity index 100% rename from src/Moq/Moq.CodeFix/CustomDelegateCodeFix.cs rename to src/Moq.CodeFix/CustomDelegateCodeFix.cs diff --git a/src/Moq/Moq.CodeFix/CustomMockCodeFixProvider.cs b/src/Moq.CodeFix/CustomMockCodeFixProvider.cs similarity index 100% rename from src/Moq/Moq.CodeFix/CustomMockCodeFixProvider.cs rename to src/Moq.CodeFix/CustomMockCodeFixProvider.cs diff --git a/src/Moq/Moq.CodeAnalysis/GlobalSuppressions.cs b/src/Moq.CodeFix/GlobalSuppressions.cs similarity index 100% rename from src/Moq/Moq.CodeAnalysis/GlobalSuppressions.cs rename to src/Moq.CodeFix/GlobalSuppressions.cs diff --git a/src/Moq/Moq.CodeFix/MockCodeFixProvider.cs b/src/Moq.CodeFix/MockCodeFixProvider.cs similarity index 100% rename from src/Moq/Moq.CodeFix/MockCodeFixProvider.cs rename to src/Moq.CodeFix/MockCodeFixProvider.cs diff --git a/src/Moq/Moq.CodeFix/Moq.CodeFix.csproj b/src/Moq.CodeFix/Moq.CodeFix.csproj similarity index 100% rename from src/Moq/Moq.CodeFix/Moq.CodeFix.csproj rename to src/Moq.CodeFix/Moq.CodeFix.csproj diff --git a/src/Moq/Moq.CodeFix/Properties/Resources.Designer.cs b/src/Moq.CodeFix/Properties/Resources.Designer.cs similarity index 100% rename from src/Moq/Moq.CodeFix/Properties/Resources.Designer.cs rename to src/Moq.CodeFix/Properties/Resources.Designer.cs diff --git a/src/Moq/Moq.CodeFix/Properties/Resources.resx b/src/Moq.CodeFix/Properties/Resources.resx similarity index 100% rename from src/Moq/Moq.CodeFix/Properties/Resources.resx rename to src/Moq.CodeFix/Properties/Resources.resx diff --git a/src/Moq/Moq.CodeAnalysis/Properties/launchSettings.json b/src/Moq.CodeFix/Properties/launchSettings.json similarity index 100% rename from src/Moq/Moq.CodeAnalysis/Properties/launchSettings.json rename to src/Moq.CodeFix/Properties/launchSettings.json diff --git a/src/Moq/Moq.CodeAnalysis/ResourceString.cs b/src/Moq.CodeFix/ResourceString.cs similarity index 100% rename from src/Moq/Moq.CodeAnalysis/ResourceString.cs rename to src/Moq.CodeFix/ResourceString.cs diff --git a/src/Moq/Moq.DynamicProxy/DynamicMockFactory.cs b/src/Moq.DynamicProxy/DynamicMockFactory.cs similarity index 73% rename from src/Moq/Moq.DynamicProxy/DynamicMockFactory.cs rename to src/Moq.DynamicProxy/DynamicMockFactory.cs index 16b4b69b..9c598c15 100644 --- a/src/Moq/Moq.DynamicProxy/DynamicMockFactory.cs +++ b/src/Moq.DynamicProxy/DynamicMockFactory.cs @@ -1,11 +1,9 @@ using System; -using System.Collections.ObjectModel; using System.Linq; using System.Reflection; using System.Threading; using Castle.DynamicProxy; using Stunts; -using Stunts.Sdk; namespace Moq.Sdk { @@ -21,7 +19,7 @@ public object CreateMock(Assembly mocksAssembly, Type baseType, Type[] implement /// /// Creates the mock proxy. /// - protected override object CreateProxy(Type baseType, Type[] implementedInterfaces, ProxyGenerationOptions options, object[] constructorArguments, bool notImplemented) + protected override object CreateProxy(Type baseType, Type[] implementedInterfaces, object[] constructorArguments, ProxyGenerationOptions options, Func getDefaultInterceptor) { if (!implementedInterfaces.Contains(typeof(IMocked))) { @@ -31,32 +29,28 @@ protected override object CreateProxy(Type baseType, Type[] implementedInterface implementedInterfaces = fixedInterfaces; } - var mocked = (IMocked)Generator.CreateClassProxy(baseType, implementedInterfaces, options, constructorArguments, new DynamicMockInterceptor(notImplemented)); + var mocked = (IMocked)Generator.CreateClassProxy(baseType, implementedInterfaces, options, constructorArguments, + new IInterceptor[] { new MockInterceptor(), getDefaultInterceptor() }); // Save for cloning purposes. We opened a generated proxy from DP to figure out the ctor signature it creates. // The lazy-calculated value allows us to provide a new interceptor for every retrieval. // Add first-class support in statebag for this pattern of either Func for values, or // Lazy, since both could be quite useful for expensive state that may be needed lazily. - mocked.Mock.State.Set(".ctor", () => new object[] { new IInterceptor[] { new DynamicMockInterceptor(notImplemented) } }.Concat(constructorArguments).ToArray()); + mocked.Mock.State.Set(".ctor", () => new object[] { new IInterceptor[] { new MockInterceptor(), getDefaultInterceptor() } }.Concat(constructorArguments).ToArray()); return mocked; } - class DynamicMockInterceptor : DynamicStuntInterceptor + private class MockInterceptor : IInterceptor { - IMock mock; + private IMock? mock; - public DynamicMockInterceptor(bool notImplemented) : base(notImplemented) { } - - public override void Intercept(IInvocation invocation) + public void Intercept(IInvocation invocation) { if (invocation.Method.DeclaringType == typeof(IMocked)) - { invocation.ReturnValue = LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock((IStunt)invocation.Proxy)); - return; - } - - base.Intercept(invocation); + else + invocation.Proceed(); } } } diff --git a/src/Moq.DynamicProxy/Mock.DynamicFactory.cs b/src/Moq.DynamicProxy/Mock.DynamicFactory.cs new file mode 100644 index 00000000..fb9a59d5 --- /dev/null +++ b/src/Moq.DynamicProxy/Mock.DynamicFactory.cs @@ -0,0 +1,17 @@ +namespace Moq +{ + internal partial class Mock + { + static Mock() + { + Sdk.MockFactory.Default = new Sdk.DynamicMockFactory(); + OnInitialized(); + } + + /// + /// Invoked after the default + /// is initialized. + /// + static partial void OnInitialized(); + } +} \ No newline at end of file diff --git a/src/Moq.DynamicProxy/Mock.DynamicFactory.vb b/src/Moq.DynamicProxy/Mock.DynamicFactory.vb new file mode 100644 index 00000000..9d316ad9 --- /dev/null +++ b/src/Moq.DynamicProxy/Mock.DynamicFactory.vb @@ -0,0 +1,16 @@ +Namespace Global.Moq + Partial Friend Class Mock + Shared Sub New() + Sdk.MockFactory.[Default] = New Sdk.DynamicMockFactory + OnInitialized() + End Sub + + ''' + ''' Invoked after the default + ''' is initialized. + ''' + Partial Private Shared Sub OnInitialized() + + End Sub + End Class +End Namespace \ No newline at end of file diff --git a/src/Moq.DynamicProxy/Moq.DynamicProxy.csproj b/src/Moq.DynamicProxy/Moq.DynamicProxy.csproj new file mode 100644 index 00000000..798f367d --- /dev/null +++ b/src/Moq.DynamicProxy/Moq.DynamicProxy.csproj @@ -0,0 +1,37 @@ + + + + netstandard2.0 + true + + + Provides run-time mock generation using Castle DynamicProxy, for projects that + cannot use the compile-time mock generation provided built-in by Moq, which + requires C# 9.0. + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Moq.DynamicProxy/Moq.DynamicProxy.targets b/src/Moq.DynamicProxy/Moq.DynamicProxy.targets new file mode 100644 index 00000000..a64c35ee --- /dev/null +++ b/src/Moq.DynamicProxy/Moq.DynamicProxy.targets @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/src/Moq/Moq/contentFiles/cs/netstandard2.0/Mocks/Mock.Overloads.cs b/src/Moq.Package/Mock.Overloads.cs similarity index 87% rename from src/Moq/Moq/contentFiles/cs/netstandard2.0/Mocks/Mock.Overloads.cs rename to src/Moq.Package/Mock.Overloads.cs index 0e13ba51..21f6a5a3 100644 --- a/src/Moq/Moq/contentFiles/cs/netstandard2.0/Mocks/Mock.Overloads.cs +++ b/src/Moq.Package/Mock.Overloads.cs @@ -1,4 +1,3 @@ -using System.CodeDom.Compiler; using System.Runtime.CompilerServices; namespace Moq @@ -6,53 +5,44 @@ namespace Moq /// /// Instantiates stunts for the specified types. /// - partial class Mock + internal partial class Mock { /// /// Creates a mock that inherits or implements the type . /// [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(params object[] constructorArgs) where T : class => Create(MockBehavior.Loose, constructorArgs); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(params object[] constructorArgs) where T : class => Create(MockBehavior.Loose, constructorArgs, typeof(T1)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(params object[] constructorArgs) where T : class => Create(MockBehavior.Loose, constructorArgs, typeof(T1), typeof(T2)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(params object[] constructorArgs) where T : class => Create(MockBehavior.Loose, constructorArgs, typeof(T1), typeof(T2), typeof(T3)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(params object[] constructorArgs) where T : class => Create(MockBehavior.Loose, constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(params object[] constructorArgs) where T : class => Create(MockBehavior.Loose, constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(params object[] constructorArgs) where T : class => Create(MockBehavior.Loose, constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(params object[] constructorArgs) where T : class => Create(MockBehavior.Loose, constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(params object[] constructorArgs) where T : class => Create(MockBehavior.Loose, constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8)); @@ -60,47 +50,38 @@ partial class Mock /// Creates a mock that inherits or implements the type . /// [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(MockBehavior behavior, params object[] constructorArgs) where T : class => Create(behavior, constructorArgs); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(MockBehavior behavior, params object[] constructorArgs) where T : class => Create(behavior, constructorArgs, typeof(T1)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(MockBehavior behavior, params object[] constructorArgs) where T : class => Create(behavior, constructorArgs, typeof(T1), typeof(T2)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(MockBehavior behavior, params object[] constructorArgs) where T : class => Create(behavior, constructorArgs, typeof(T1), typeof(T2), typeof(T3)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(MockBehavior behavior, params object[] constructorArgs) where T : class => Create(behavior, constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(MockBehavior behavior, params object[] constructorArgs) where T : class => Create(behavior, constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(MockBehavior behavior, params object[] constructorArgs) where T : class => Create(behavior, constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(MockBehavior behavior, params object[] constructorArgs) where T : class => Create(behavior, constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7)); [MockGenerator] - [GeneratedCode("Moq", "5.0")] [CompilerGenerated] public static T Of(MockBehavior behavior, params object[] constructorArgs) where T : class => Create(behavior, constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8)); } diff --git a/src/Moq/Moq/contentFiles/vb/netstandard2.0/Mocks/Mock.Overloads.vb b/src/Moq.Package/Mock.Overloads.vb similarity index 87% rename from src/Moq/Moq/contentFiles/vb/netstandard2.0/Mocks/Mock.Overloads.vb rename to src/Moq.Package/Mock.Overloads.vb index ffaff399..80a79ee7 100644 --- a/src/Moq/Moq/contentFiles/vb/netstandard2.0/Mocks/Mock.Overloads.vb +++ b/src/Moq.Package/Mock.Overloads.vb @@ -1,134 +1,112 @@ -Imports System.CodeDom.Compiler -Imports System.Reflection -Imports System.Runtime.CompilerServices -Imports Moq.Sdk -Imports Stunts +Imports System.Runtime.CompilerServices Namespace Global.Moq Partial Friend Class Mock - Public Shared Function [Of](Of T As Class)(ParamArray constructorArgs As Object()) As T Return Create(Of T)(MockBehavior.Loose, constructorArgs) End Function - Public Shared Function [Of](Of T As Class, T1)(ParamArray constructorArgs As Object()) As T Return Create(Of T)(MockBehavior.Loose, constructorArgs, GetType(T1)) End Function - Public Shared Function [Of](Of T As Class, T1, T2)(ParamArray constructorArgs As Object()) As T Return Create(Of T)(MockBehavior.Loose, constructorArgs, GetType(T1), GetType(T2)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3)(ParamArray constructorArgs As Object()) As T Return Create(Of T)(MockBehavior.Loose, constructorArgs, GetType(T1), GetType(T2), GetType(T3)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3, T4)(ParamArray constructorArgs As Object()) As T Return Create(Of T)(MockBehavior.Loose, constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3, T4, T5)(ParamArray constructorArgs As Object()) As T Return Create(Of T)(MockBehavior.Loose, constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3, T4, T5, T6)(ParamArray constructorArgs As Object()) As T Return Create(Of T)(MockBehavior.Loose, constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5), GetType(T6)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3, T4, T5, T6, T7)(ParamArray constructorArgs As Object()) As T Return Create(Of T)(MockBehavior.Loose, constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5), GetType(T6), GetType(T7)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3, T4, T5, T6, T7, T8)(ParamArray constructorArgs As Object()) As T Return Create(Of T)(MockBehavior.Loose, constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5), GetType(T6), GetType(T7), GetType(T8)) End Function - Public Shared Function [Of](Of T As Class)(ByVal behavior As MockBehavior, ParamArray constructorArgs As Object()) As T Return Create(Of T)(behavior, constructorArgs) End Function - Public Shared Function [Of](Of T As Class, T1)(ByVal behavior As MockBehavior, ParamArray constructorArgs As Object()) As T Return Create(Of T)(behavior, constructorArgs, GetType(T1)) End Function - Public Shared Function [Of](Of T As Class, T1, T2)(ByVal behavior As MockBehavior, ParamArray constructorArgs As Object()) As T Return Create(Of T)(behavior, constructorArgs, GetType(T1), GetType(T2)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3)(ByVal behavior As MockBehavior, ParamArray constructorArgs As Object()) As T Return Create(Of T)(behavior, constructorArgs, GetType(T1), GetType(T2), GetType(T3)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3, T4)(ByVal behavior As MockBehavior, ParamArray constructorArgs As Object()) As T Return Create(Of T)(behavior, constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3, T4, T5)(ByVal behavior As MockBehavior, ParamArray constructorArgs As Object()) As T Return Create(Of T)(MockBehavior.Loose, constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3, T4, T5, T6)(ByVal behavior As MockBehavior, ParamArray constructorArgs As Object()) As T Return Create(Of T)(behavior, constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5), GetType(T6)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3, T4, T5, T6, T7)(ByVal behavior As MockBehavior, ParamArray constructorArgs As Object()) As T Return Create(Of T)(behavior, constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5), GetType(T6), GetType(T7)) End Function - Public Shared Function [Of](Of T As Class, T1, T2, T3, T4, T5, T6, T7, T8)(ByVal behavior As MockBehavior, ParamArray constructorArgs As Object()) As T Return Create(Of T)(behavior, constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5), GetType(T6), GetType(T7), GetType(T8)) diff --git a/src/Moq.Package/Mock.StaticFactory.cs b/src/Moq.Package/Mock.StaticFactory.cs new file mode 100644 index 00000000..5e54bc24 --- /dev/null +++ b/src/Moq.Package/Mock.StaticFactory.cs @@ -0,0 +1,17 @@ +namespace Moq +{ + internal partial class Mock + { + static Mock() + { + Sdk.MockFactory.Default = new Sdk.StaticMockFactory(); + OnInitialized(); + } + + /// + /// Invoked after the default + /// is initialized. + /// + static partial void OnInitialized(); + } +} \ No newline at end of file diff --git a/src/Moq.Package/Mock.StaticFactory.vb b/src/Moq.Package/Mock.StaticFactory.vb new file mode 100644 index 00000000..0c4d52fb --- /dev/null +++ b/src/Moq.Package/Mock.StaticFactory.vb @@ -0,0 +1,16 @@ +Namespace Global.Moq + Partial Friend Class Mock + Shared Sub New() + MockFactory.[Default] = New Sdk.StaticMockFactory + OnInitialized() + End Sub + + ''' + ''' Invoked after the default + ''' is initialized. + ''' + Partial Private Shared Sub OnInitialized() + + End Sub + End Class +End Namespace \ No newline at end of file diff --git a/src/Moq/Moq/contentFiles/cs/netstandard2.0/Mocks/Mock.cs b/src/Moq.Package/Mock.cs similarity index 79% rename from src/Moq/Moq/contentFiles/cs/netstandard2.0/Mocks/Mock.cs rename to src/Moq.Package/Mock.cs index a1374bdf..12e2cd15 100644 --- a/src/Moq/Moq/contentFiles/cs/netstandard2.0/Mocks/Mock.cs +++ b/src/Moq.Package/Mock.cs @@ -1,5 +1,5 @@ using System; -using System.CodeDom.Compiler; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using Moq.Sdk; @@ -9,12 +9,10 @@ namespace Moq /// /// Instantiates mocks for the specified types. /// - [GeneratedCode("Moq", "5.0")] + [ExcludeFromCodeCoverage] [CompilerGenerated] - partial class Mock + internal partial class Mock { - static Mock() => MockFactory.Default = new Sdk.DynamicMockFactory(); - /// /// Gets the configuration and introspection for the given mocked instance. /// @@ -26,7 +24,7 @@ partial class Mock /// private static T Create(MockBehavior behavior, object[] constructorArgs, params Type[] interfaces) where T : class { - var mocked = (IMocked)MockFactory.Default.CreateMock(typeof(Mock).GetTypeInfo().Assembly, typeof(T), interfaces, constructorArgs); + var mocked = (IMocked)MockFactory.Default.CreateMock(typeof(Mock).Assembly, typeof(T), interfaces, constructorArgs); mocked.Initialize(behavior); diff --git a/src/Moq/Moq/contentFiles/vb/netstandard2.0/Mocks/Mock.vb b/src/Moq.Package/Mock.vb similarity index 66% rename from src/Moq/Moq/contentFiles/vb/netstandard2.0/Mocks/Mock.vb rename to src/Moq.Package/Mock.vb index dcd8f656..9ea01358 100644 --- a/src/Moq/Moq/contentFiles/vb/netstandard2.0/Mocks/Mock.vb +++ b/src/Moq.Package/Mock.vb @@ -1,22 +1,19 @@ Option Strict On Imports System -Imports System.CodeDom.Compiler +Imports System.Diagnostics.CodeAnalysis Imports System.Reflection Imports System.Runtime.CompilerServices Imports Moq.Sdk Namespace Global.Moq - + Partial Friend Class Mock - Private Shared Sub New() - MockFactory.[Default] = New Sdk.DynamicMockFactory() - End Sub Private Shared Function Create(Of T As Class)(ByVal behavior As MockBehavior, ByVal constructorArgs As Object(), ParamArray interfaces As Type()) As T - Dim mocked = DirectCast(MockFactory.[Default].CreateMock(GetType(Mock).GetTypeInfo().Assembly, GetType(T), interfaces, constructorArgs), IMocked) + Dim mocked = DirectCast(MockFactory.[Default].CreateMock(GetType(Mock).Assembly, GetType(T), interfaces, constructorArgs), IMocked) mocked.Initialize(behavior) diff --git a/src/Moq.Package/Moq.Package.msbuildproj b/src/Moq.Package/Moq.Package.msbuildproj new file mode 100644 index 00000000..d83ce139 --- /dev/null +++ b/src/Moq.Package/Moq.Package.msbuildproj @@ -0,0 +1,29 @@ + + + netstandard2.0 + .NETStandard,Version=v2.0 + Moq + Moq + The most popular and friendly mocking framework for .NET + moq mocking mock + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Moq.Package/Moq.props b/src/Moq.Package/Moq.props new file mode 100644 index 00000000..072af853 --- /dev/null +++ b/src/Moq.Package/Moq.props @@ -0,0 +1,10 @@ + + + + true + + 002400000480000094000000060200000024000052534131000400000100010051155fd0ee280be78d81cc979423f1129ec5dd28edce9cd94fd679890639cad54c121ebdb606f8659659cd313d3b3db7fa41e2271158dd602bb0039a142717117fa1f63d93a2d288a1c2f920ec05c4858d344a45d48ebd31c1368ab783596b382b611d8c92f9c1b3d338296aa21b12f3bc9f34de87756100c172c52a24bad2db + 00352124762f2aa5 + + + \ No newline at end of file diff --git a/src/Moq.Package/Moq.targets b/src/Moq.Package/Moq.targets new file mode 100644 index 00000000..c3b05273 --- /dev/null +++ b/src/Moq.Package/Moq.targets @@ -0,0 +1,36 @@ + + + + $(MSBuildThisFileDirectory)..\..\tools\netstandard2.0 + + true + + + + + + + + + + + + + + + + + + + + false + + + + + + \ No newline at end of file diff --git a/src/Moq/Moq.Sdk.Tests/AnyMatcherTests.cs b/src/Moq.Sdk.Tests/AnyMatcherTests.cs similarity index 94% rename from src/Moq/Moq.Sdk.Tests/AnyMatcherTests.cs rename to src/Moq.Sdk.Tests/AnyMatcherTests.cs index d9015794..88a08f1b 100644 --- a/src/Moq/Moq.Sdk.Tests/AnyMatcherTests.cs +++ b/src/Moq.Sdk.Tests/AnyMatcherTests.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Xunit; namespace Moq.Sdk.Tests @@ -110,9 +106,8 @@ public void MatchesDerivedType() Assert.True(x.Matches(new Derived())); } + private class Base { } - - class Base { } - class Derived : Base { } + private class Derived : Base { } } } diff --git a/src/Moq/Moq.Sdk.Tests/CallContextTests.cs b/src/Moq.Sdk.Tests/CallContextTests.cs similarity index 100% rename from src/Moq/Moq.Sdk.Tests/CallContextTests.cs rename to src/Moq.Sdk.Tests/CallContextTests.cs diff --git a/src/Moq/Moq.Sdk.Tests/ConditionalMatcherTests.cs b/src/Moq.Sdk.Tests/ConditionalMatcherTests.cs similarity index 96% rename from src/Moq/Moq.Sdk.Tests/ConditionalMatcherTests.cs rename to src/Moq.Sdk.Tests/ConditionalMatcherTests.cs index 38c1a562..a9761e30 100644 --- a/src/Moq/Moq.Sdk.Tests/ConditionalMatcherTests.cs +++ b/src/Moq.Sdk.Tests/ConditionalMatcherTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Xunit; namespace Moq.Sdk.Tests @@ -57,7 +56,8 @@ public void EqualsByConditionFunctionAndName() Assert.False(matcher.Equals(new ConditionalMatcher(_ => true, "foo"))); } - class Base { } - class Derived : Base { } + private class Base { } + + private class Derived : Base { } } } diff --git a/src/Moq/Moq.Sdk.Tests/DefaultMockTests.cs b/src/Moq.Sdk.Tests/DefaultMockTests.cs similarity index 90% rename from src/Moq/Moq.Sdk.Tests/DefaultMockTests.cs rename to src/Moq.Sdk.Tests/DefaultMockTests.cs index 42bfbe56..271e7151 100644 --- a/src/Moq/Moq.Sdk.Tests/DefaultMockTests.cs +++ b/src/Moq.Sdk.Tests/DefaultMockTests.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.ObjectModel; +using System.Collections.Generic; using System.Reflection; using System.Threading; using Stunts; @@ -60,7 +60,7 @@ public void TrackMockBehaviors() var behavior = new MockBehaviorPipeline(setup); stunt.AddBehavior(behavior); - stunt.AddBehavior(new DelegateStuntBehavior((m, n) => n().Invoke(m, n))); + stunt.AddBehavior((m, n) => n().Invoke(m, n)); Assert.Equal(initialBehaviors + 2, stunt.Behaviors.Count); Assert.Single(stunt.Mock.Setups); @@ -102,12 +102,12 @@ public void TracksTargetObject() public void InitializesState() => Assert.NotNull(new FakeStunt().Mock.State); - class FakeStunt : IStunt, IMocked + private class FakeStunt : IStunt, IMocked { - BehaviorPipeline pipeline = new BehaviorPipeline(); - DefaultMock mock; + private readonly BehaviorPipeline pipeline = new BehaviorPipeline(); + private DefaultMock mock; - public ObservableCollection Behaviors => pipeline.Behaviors; + public IList Behaviors => pipeline.Behaviors; public IMock Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); diff --git a/src/Moq/Moq.Sdk.Tests/EqualityTests.cs b/src/Moq.Sdk.Tests/EqualityTests.cs similarity index 96% rename from src/Moq/Moq.Sdk.Tests/EqualityTests.cs rename to src/Moq.Sdk.Tests/EqualityTests.cs index b7d6dca1..cde53526 100644 --- a/src/Moq/Moq.Sdk.Tests/EqualityTests.cs +++ b/src/Moq.Sdk.Tests/EqualityTests.cs @@ -1,10 +1,5 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; using Stunts; using Xunit; @@ -131,6 +126,6 @@ public void Matchers() Assert.False(hash.Add(value2)); } - void AMethod(bool b, string s, PlatformID p) { } + private void AMethod(bool b, string s, PlatformID p) { } } } diff --git a/src/Moq/Moq.Sdk.Tests/EventBehaviorTests.cs b/src/Moq.Sdk.Tests/EventBehaviorTests.cs similarity index 90% rename from src/Moq/Moq.Sdk.Tests/EventBehaviorTests.cs rename to src/Moq.Sdk.Tests/EventBehaviorTests.cs index fb6f3ac4..8ab38ddb 100644 --- a/src/Moq/Moq.Sdk.Tests/EventBehaviorTests.cs +++ b/src/Moq.Sdk.Tests/EventBehaviorTests.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.ObjectModel; using System.ComponentModel; using System.Reflection; -using System.Threading; using Stunts; using Xunit; @@ -35,7 +33,7 @@ public void AddsHandler() { var mock = new EventfulMock(); mock.Behaviors.Add(new EventBehavior()); - mock.Behaviors.Add(new DelegateStuntBehavior((m, n) => m.CreateValueReturn(null))); + mock.AddBehavior((m, n) => m.CreateValueReturn(null)); EventHandler handler = (_, __) => { }; mock.Empty += handler; @@ -49,7 +47,7 @@ public void RemovesHandler() { var mock = new EventfulMock(); mock.Behaviors.Add(new EventBehavior()); - mock.Behaviors.Add(new DelegateStuntBehavior((m, n) => m.CreateValueReturn(null))); + mock.AddBehavior((m, n) => m.CreateValueReturn(null)); EventHandler handler = (_, __) => { }; mock.Empty += handler; @@ -69,7 +67,7 @@ public void RaisesEventHandlerIfRaiserInContextOnAdd() { var mock = new EventfulMock(); mock.Behaviors.Add(new EventBehavior()); - mock.Behaviors.Add(new DelegateStuntBehavior((m, n) => m.CreateValueReturn(null))); + mock.AddBehavior((m, n) => m.CreateValueReturn(null)); var called = false; EventHandler handler = (_, __) => called = true; @@ -86,7 +84,7 @@ public void RaisesEventArgsIfRaiserInContextOnAdd() { var mock = new EventfulMock(); mock.Behaviors.Add(new EventBehavior()); - mock.Behaviors.Add(new DelegateStuntBehavior((m, n) => m.CreateValueReturn(null))); + mock.AddBehavior((m, n) => m.CreateValueReturn(null)); var expected = new Args(); var actual = default(Args); @@ -104,7 +102,7 @@ public void RaisesPropertyChangedIfRaiserInContextOnAdd() { var mock = new EventfulMock(); mock.Behaviors.Add(new EventBehavior()); - mock.Behaviors.Add(new DelegateStuntBehavior((m, n) => m.CreateValueReturn(null))); + mock.AddBehavior((m, n) => m.CreateValueReturn(null)); var expected = new PropertyChangedEventArgs("Foo"); var actual = default(PropertyChangedEventArgs); @@ -122,7 +120,7 @@ public void RaisesActionIfRaiserInContextOnAdd() { var mock = new EventfulMock(); mock.Behaviors.Add(new EventBehavior()); - mock.Behaviors.Add(new DelegateStuntBehavior((m, n) => m.CreateValueReturn(null))); + mock.AddBehavior((m, n) => m.CreateValueReturn(null)); var expected = 5; var actual = 0; @@ -140,7 +138,7 @@ public void RaisesCustomDelegateIfRaiserInContextOnAdd() { var mock = new EventfulMock(); mock.Behaviors.Add(new EventBehavior()); - mock.Behaviors.Add(new DelegateStuntBehavior((m, n) => m.CreateValueReturn(null))); + mock.AddBehavior((m, n) => m.CreateValueReturn(null)); var (id, name) = (5, "foo"); var (id2, name2) = (0, ""); diff --git a/src/Moq/Moq.Sdk.Tests/Fakes.cs b/src/Moq.Sdk.Tests/Fakes.cs similarity index 93% rename from src/Moq/Moq.Sdk.Tests/Fakes.cs rename to src/Moq.Sdk.Tests/Fakes.cs index 26e74c38..5537462c 100644 --- a/src/Moq/Moq.Sdk.Tests/Fakes.cs +++ b/src/Moq.Sdk.Tests/Fakes.cs @@ -1,7 +1,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Reflection; using Stunts; @@ -9,13 +8,13 @@ namespace Moq.Sdk.Tests { public class FakeMock : IStunt, IMocked { - DefaultMock mock; + private readonly DefaultMock mock; protected BehaviorPipeline Pipeline = new BehaviorPipeline(); public FakeMock() => mock = new DefaultMock(this); - public ObservableCollection Behaviors => Pipeline.Behaviors; + public IList Behaviors => Pipeline.Behaviors; public IMock Mock => mock; } diff --git a/src/Moq/Moq.Sdk.Tests/GlobalSuppressions.cs b/src/Moq.Sdk.Tests/GlobalSuppressions.cs similarity index 100% rename from src/Moq/Moq.Sdk.Tests/GlobalSuppressions.cs rename to src/Moq.Sdk.Tests/GlobalSuppressions.cs diff --git a/src/Moq/Moq.Sdk.Tests/MockBehaviorPipelineTests.cs b/src/Moq.Sdk.Tests/MockBehaviorPipelineTests.cs similarity index 100% rename from src/Moq/Moq.Sdk.Tests/MockBehaviorPipelineTests.cs rename to src/Moq.Sdk.Tests/MockBehaviorPipelineTests.cs diff --git a/src/Moq/Moq.Sdk.Tests/MockBehaviorTests.cs b/src/Moq.Sdk.Tests/MockBehaviorTests.cs similarity index 100% rename from src/Moq/Moq.Sdk.Tests/MockBehaviorTests.cs rename to src/Moq.Sdk.Tests/MockBehaviorTests.cs diff --git a/src/Moq/Moq.Sdk.Tests/MockExtensionsTests.cs b/src/Moq.Sdk.Tests/MockExtensionsTests.cs similarity index 97% rename from src/Moq/Moq.Sdk.Tests/MockExtensionsTests.cs rename to src/Moq.Sdk.Tests/MockExtensionsTests.cs index d6611fde..d6ee65b8 100644 --- a/src/Moq/Moq.Sdk.Tests/MockExtensionsTests.cs +++ b/src/Moq.Sdk.Tests/MockExtensionsTests.cs @@ -42,8 +42,8 @@ public void CanAssertInvocations() Assert.Equal(0, target.Add(2, 3)); Assert.Single(target.AsMock().InvocationsFor(c => c.Add(2, 3))); } - - class FakeCalls : FakeMock + + private class FakeCalls : FakeMock { public void TurnOn() => Pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); diff --git a/src/Moq/Moq.Sdk.Tests/MockNamingTests.cs b/src/Moq.Sdk.Tests/MockNamingTests.cs similarity index 100% rename from src/Moq/Moq.Sdk.Tests/MockNamingTests.cs rename to src/Moq.Sdk.Tests/MockNamingTests.cs diff --git a/src/Moq/Moq.Sdk.Tests/MockTrackingBehaviorTests.cs b/src/Moq.Sdk.Tests/MockTrackingBehaviorTests.cs similarity index 93% rename from src/Moq/Moq.Sdk.Tests/MockTrackingBehaviorTests.cs rename to src/Moq.Sdk.Tests/MockTrackingBehaviorTests.cs index 5dc0372e..98b533e8 100644 --- a/src/Moq/Moq.Sdk.Tests/MockTrackingBehaviorTests.cs +++ b/src/Moq.Sdk.Tests/MockTrackingBehaviorTests.cs @@ -1,6 +1,4 @@ -using System.Collections.ObjectModel; -using System.Reflection; -using System.Threading; +using System.Reflection; using Stunts; using Xunit; @@ -49,8 +47,7 @@ public void SkipInvocationRecordingIfSetupScopeActive() Assert.Empty(target.Mock.Invocations); } - - class TrackingMock : FakeMock + private class TrackingMock : FakeMock { public void Do() => Pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); } diff --git a/src/Moq/Moq.Sdk.Tests/Mocked.cs b/src/Moq.Sdk.Tests/Mocked.cs similarity index 60% rename from src/Moq/Moq.Sdk.Tests/Mocked.cs rename to src/Moq.Sdk.Tests/Mocked.cs index 4c85adc6..c31fdf7f 100644 --- a/src/Moq/Moq.Sdk.Tests/Mocked.cs +++ b/src/Moq.Sdk.Tests/Mocked.cs @@ -7,11 +7,11 @@ namespace Moq.Sdk.Tests { public class Mocked : IMocked, IStunt { - IMock mock; - ObservableCollection behaviors = new ObservableCollection(); + private IMock mock; + private readonly IList behaviors = new ObservableCollection(); public IMock Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - public ObservableCollection Behaviors => behaviors; + public IList Behaviors => behaviors; } } diff --git a/src/Moq.Sdk.Tests/Moq.Sdk.Tests.csproj b/src/Moq.Sdk.Tests/Moq.Sdk.Tests.csproj new file mode 100644 index 00000000..9ad3d51b --- /dev/null +++ b/src/Moq.Sdk.Tests/Moq.Sdk.Tests.csproj @@ -0,0 +1,25 @@ + + + + net472;net5.0 + annotations + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Moq/Moq.Sdk.Tests/NotMatcherTests.cs b/src/Moq.Sdk.Tests/NotMatcherTests.cs similarity index 96% rename from src/Moq/Moq.Sdk.Tests/NotMatcherTests.cs rename to src/Moq.Sdk.Tests/NotMatcherTests.cs index a12fbcbc..137fd76a 100644 --- a/src/Moq/Moq.Sdk.Tests/NotMatcherTests.cs +++ b/src/Moq.Sdk.Tests/NotMatcherTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Xunit; namespace Moq.Sdk.Tests @@ -49,7 +48,7 @@ public void MatcherEquals() Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); } - class Value + private class Value { public Value(Guid id) => Id = id; diff --git a/src/Moq/Moq.Sdk.Tests/PropertyBehaviorTests.cs b/src/Moq.Sdk.Tests/PropertyBehaviorTests.cs similarity index 95% rename from src/Moq/Moq.Sdk.Tests/PropertyBehaviorTests.cs rename to src/Moq.Sdk.Tests/PropertyBehaviorTests.cs index f5727300..71c7f0c2 100644 --- a/src/Moq/Moq.Sdk.Tests/PropertyBehaviorTests.cs +++ b/src/Moq.Sdk.Tests/PropertyBehaviorTests.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Reflection; -using System.Text; -using System.Threading.Tasks; using Stunts; using Xunit; diff --git a/src/Moq/Moq.Sdk.Tests/SetupScopeTests.cs b/src/Moq.Sdk.Tests/SetupScopeTests.cs similarity index 69% rename from src/Moq/Moq.Sdk.Tests/SetupScopeTests.cs rename to src/Moq.Sdk.Tests/SetupScopeTests.cs index 8c8717b5..6c564196 100644 --- a/src/Moq/Moq.Sdk.Tests/SetupScopeTests.cs +++ b/src/Moq.Sdk.Tests/SetupScopeTests.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Xunit; +using Xunit; namespace Moq.Sdk.Tests { diff --git a/src/Moq/Moq.Sdk.Tests/StrictMockBehaviorTests.cs b/src/Moq.Sdk.Tests/StrictMockBehaviorTests.cs similarity index 100% rename from src/Moq/Moq.Sdk.Tests/StrictMockBehaviorTests.cs rename to src/Moq.Sdk.Tests/StrictMockBehaviorTests.cs diff --git a/src/Moq/Moq.Sdk.Tests/TimesFixture.cs b/src/Moq.Sdk.Tests/TimesFixture.cs similarity index 100% rename from src/Moq/Moq.Sdk.Tests/TimesFixture.cs rename to src/Moq.Sdk.Tests/TimesFixture.cs diff --git a/src/Moq/Moq.Sdk/AnyMatcher.cs b/src/Moq.Sdk/AnyMatcher.cs similarity index 86% rename from src/Moq/Moq.Sdk/AnyMatcher.cs rename to src/Moq.Sdk/AnyMatcher.cs index f5f8a004..2f184625 100644 --- a/src/Moq/Moq.Sdk/AnyMatcher.cs +++ b/src/Moq.Sdk/AnyMatcher.cs @@ -12,9 +12,9 @@ namespace Moq.Sdk /// public class AnyMatcher : IArgumentMatcher, IEquatable { - TypeInfo info; - bool isValueType; - bool isNullable; + private readonly TypeInfo info; + private readonly bool isValueType; + private readonly bool isNullable; /// /// Initializes the matcher with the given . @@ -38,7 +38,7 @@ public AnyMatcher(Type argumentType) /// /// Evaluates whether the given value matches this instance. /// - public bool Matches(object value) + public bool Matches(object? value) { // Non-nullable value types never match against a null value. if (isValueType && !isNullable && value == null) @@ -61,10 +61,10 @@ public bool Matches(object value) #region Equality /// - public bool Equals(AnyMatcher other) => other != null && info.Equals(other.info); + public bool Equals(AnyMatcher other) => info.Equals(other.info); /// - public override bool Equals(object other) => Equals(other as AnyMatcher); + public override bool Equals(object other) => other is AnyMatcher matcher && Equals(matcher); /// public override int GetHashCode() => info.GetHashCode(); diff --git a/src/Moq/Moq.Sdk/AnyMatcher`1.cs b/src/Moq.Sdk/AnyMatcher`1.cs similarity index 87% rename from src/Moq/Moq.Sdk/AnyMatcher`1.cs rename to src/Moq.Sdk/AnyMatcher`1.cs index d0f93f88..302f93ef 100644 --- a/src/Moq/Moq.Sdk/AnyMatcher`1.cs +++ b/src/Moq.Sdk/AnyMatcher`1.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Diagnostics; using System.Reflection; using TypeNameFormatter; @@ -15,8 +14,8 @@ namespace Moq.Sdk public class AnyMatcher : IArgumentMatcher, IEquatable> { // Disable warning since we only use this member from this class - static bool IsValueType = typeof(T).GetTypeInfo().IsValueType; - static bool IsNullable = typeof(T).GetTypeInfo().IsGenericType && + private static readonly bool IsValueType = typeof(T).IsValueType; + private static readonly bool IsNullable = typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>); /// @@ -24,7 +23,7 @@ public class AnyMatcher : IArgumentMatcher, IEquatable> /// public static IArgumentMatcher Default { get; } = new AnyMatcher(); - AnyMatcher() { } + private AnyMatcher() { } /// /// Gets the type of the argument this matcher supports. @@ -34,14 +33,14 @@ public class AnyMatcher : IArgumentMatcher, IEquatable> /// /// Evaluates whether the given value matches this instance. /// - public bool Matches(object value) + public bool Matches(object? value) { // Non-nullable value types never match against a null value. if (IsValueType && !IsNullable && value == null) return false; return value == null || - typeof(T).GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo()); + typeof(T).IsAssignableFrom(value.GetType()); } /// @@ -72,7 +71,7 @@ public bool Matches(object value) /// /// if is not null and /// it's an with the same . - public override bool Equals(object other) => Equals(other as AnyMatcher); + public override bool Equals(object other) => other is AnyMatcher matcher && Equals(matcher); /// public override int GetHashCode() => typeof(T).GetHashCode(); diff --git a/src/Moq/Moq.Sdk/CallContext.cs b/src/Moq.Sdk/CallContext.cs similarity index 68% rename from src/Moq/Moq.Sdk/CallContext.cs rename to src/Moq.Sdk/CallContext.cs index 0175ed29..f0e99cd3 100644 --- a/src/Moq/Moq.Sdk/CallContext.cs +++ b/src/Moq.Sdk/CallContext.cs @@ -10,36 +10,36 @@ namespace Moq.Sdk /// public static class CallContext { - static readonly string defaultName = typeof(T).FullName; - static ConcurrentDictionary> state = new ConcurrentDictionary>(); + private static readonly string defaultName = typeof(T).FullName; + private static readonly ConcurrentDictionary> state = new(); /// /// Stores a given object. /// /// The object to store in the call context. - public static void SetData(T data) => SetData(defaultName, data); + public static void SetData(T? data) => SetData(defaultName, data); /// /// Stores a given object and associates it with the specified name. /// /// The name with which to associate the new item in the call context. /// The object to store in the call context. - public static void SetData(string name, T data) => - state.GetOrAdd(name, _ => new AsyncLocal()).Value = data; + public static void SetData(string name, T? data) + => state.GetOrAdd(name, _ => new AsyncLocal()).Value = data; /// /// Retrieves an object from the . /// /// The object in the call context associated with the specified name, or a default value for if none is found. - public static T GetData() => GetData(defaultName); + public static T? GetData() => GetData(defaultName); /// /// Retrieves an object with the specified name from the . /// /// The name of the item in the call context. /// The object in the call context associated with the specified name, or a default value for if none is found. - public static T GetData(string name) => - state.TryGetValue(name, out var data) ? data.Value : default; + public static T? GetData(string name) + => state.TryGetValue(name, out var data) ? data.Value : default; /// /// Retrieves an object from the , and @@ -47,7 +47,7 @@ public static T GetData(string name) => /// /// A function that will set the initial value of the given parameter, if it doesn't have a value already in the context. /// The object in the call context associated with the specified name, or the initial value returned from . - public static T GetData(Func setInitialValue) => GetData(defaultName, setInitialValue); + public static T? GetData(Func setInitialValue) => GetData(defaultName, setInitialValue); /// /// Retrieves an object with the specified name from the , and @@ -56,10 +56,10 @@ public static T GetData(string name) => /// The name of the item in the call context. /// A function that will set the initial value of the given parameter, if it doesn't have a value already in the context. /// The object in the call context associated with the specified name, or the initial value returned from . - public static T GetData(string name, Func setInitialValue) + public static T? GetData(string name, Func setInitialValue) { - var local = state.GetOrAdd(name, _ => new AsyncLocal { Value = setInitialValue() }); - if (object.Equals(local.Value, default(T))) + var local = state.GetOrAdd(name, _ => new AsyncLocal { Value = setInitialValue() }); + if (Equals(local.Value, default(T))) local.Value = setInitialValue(); return local.Value; @@ -72,22 +72,30 @@ public static T GetData(string name, Func setInitialValue) /// public static class CallContext { - static ConcurrentDictionary> state = new ConcurrentDictionary>(); + private static readonly ConcurrentDictionary> state = new(); /// /// Stores a given object and associates it with the specified name. /// /// The name with which to associate the new item in the call context. /// The object to store in the call context. - public static void SetData(string name, object data) => - state.GetOrAdd(name, _ => new AsyncLocal()).Value = data; + public static void SetData(string name, object? data) + => state.GetOrAdd(name, _ => new AsyncLocal()).Value = data; /// /// Retrieves an object with the specified name from the . /// /// The name of the item in the call context. /// The object in the call context associated with the specified name, or if not found. - public static object GetData(string name) => - state.TryGetValue(name, out var data) ? data.Value : null; + public static object? GetData(string name) + => state.TryGetValue(name, out var data) ? data.Value : null; + + /// + /// Throws with a message stating that an + /// unexpected null value was found in the context. + /// + /// Type of value that was unexpectedly null in the context. This is used as the key. + public static T ThrowUnexpectedNull() + => throw new InvalidOperationException(ThisAssembly.Strings.UnexpectedNullContextState(typeof(T).FullName)); } } diff --git a/src/Moq/Moq.Sdk/ConditionalMatcher.cs b/src/Moq.Sdk/ConditionalMatcher.cs similarity index 74% rename from src/Moq/Moq.Sdk/ConditionalMatcher.cs rename to src/Moq.Sdk/ConditionalMatcher.cs index fcbc9f69..95b47493 100644 --- a/src/Moq/Moq.Sdk/ConditionalMatcher.cs +++ b/src/Moq.Sdk/ConditionalMatcher.cs @@ -1,9 +1,6 @@ using System; -using System.Collections; -using System.Collections.Generic; using System.Diagnostics; using System.Reflection; -using Stunts; using TypeNameFormatter; namespace Moq.Sdk @@ -15,19 +12,19 @@ namespace Moq.Sdk /// Type of argument being conditioned. public class ConditionalMatcher : IArgumentMatcher, IEquatable> { - static readonly bool IsValueType = typeof(T).GetTypeInfo().IsValueType; - static readonly bool IsNullable = typeof(T).GetTypeInfo().IsGenericType && + private static readonly bool IsValueType = typeof(T).IsValueType; + private static readonly bool IsNullable = typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>); [DebuggerBrowsable(DebuggerBrowsableState.Never)] - readonly string name; + private readonly string name; [DebuggerBrowsable(DebuggerBrowsableState.Never)] - readonly Func condition; + private readonly Func condition; /// /// Initializes the matcher with the condition and optional friendly name. /// - public ConditionalMatcher(Func condition, string name = "condition") + public ConditionalMatcher(Func condition, string name = "condition") { this.condition = condition ?? throw new ArgumentNullException(nameof(condition)); this.name = name ?? throw new ArgumentNullException(nameof(name)); @@ -41,7 +38,7 @@ public ConditionalMatcher(Func condition, string name = "condition") /// /// Evaluates whether the given value matches this instance. /// - public bool Matches(object value) + public bool Matches(object? value) { // Non-nullable value types never match against a null value. if (IsValueType && !IsNullable && value == null) @@ -49,7 +46,7 @@ public bool Matches(object value) return (value == null || typeof(T) == value.GetType() || - typeof(T).GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo())) && + typeof(T).IsAssignableFrom(value.GetType())) && condition((T)value); } @@ -70,15 +67,15 @@ public bool Matches(object value) /// Checks whether has the same condition and friendly name. /// public bool Equals(ConditionalMatcher other) - => other != null && ReferenceEquals(condition, other.condition) && name.Equals(other.name); + => ReferenceEquals(condition, other.condition) && name.Equals(other.name); /// /// Checks whether has the same condition and friendly name. /// - public override bool Equals(object other) => Equals(other as ConditionalMatcher); + public override bool Equals(object other) => other is ConditionalMatcher matcher && Equals(matcher); /// - public override int GetHashCode() => new HashCode().Add(condition).Add(name).ToHashCode(); + public override int GetHashCode() => HashCode.Combine(condition, name); #endregion } diff --git a/src/Moq/Moq.Sdk/DefaultMock.cs b/src/Moq.Sdk/DefaultMock.cs similarity index 70% rename from src/Moq/Moq.Sdk/DefaultMock.cs rename to src/Moq.Sdk/DefaultMock.cs index 397f6b6d..e9199fc3 100644 --- a/src/Moq/Moq.Sdk/DefaultMock.cs +++ b/src/Moq.Sdk/DefaultMock.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Diagnostics; using System.Linq; -using Moq.Sdk.Properties; using Stunts; namespace Moq.Sdk @@ -29,18 +27,20 @@ public class DefaultMock : IMock public DefaultMock(IStunt stunt) { this.stunt = stunt ?? throw new ArgumentNullException(nameof(stunt)); + var behaviors = stunt.Behaviors; - if (!stunt.Behaviors.OfType().Any()) - stunt.Behaviors.Insert(0, new MockContextBehavior()); + if (!behaviors.OfType().Any()) + behaviors.Insert(0, new MockContextBehavior()); - if (!stunt.Behaviors.OfType().Any()) - stunt.Behaviors.Insert(1, new MockRecordingBehavior()); + if (!behaviors.OfType().Any()) + behaviors.Insert(1, new MockRecordingBehavior()); - stunt.Behaviors.CollectionChanged += OnBehaviorsChanged; + if (behaviors is INotifyCollectionChanged notify) + notify.CollectionChanged += OnBehaviorsChanged; } /// - public ObservableCollection Behaviors => stunt.Behaviors; + public IList Behaviors => stunt.Behaviors; /// public ICollection Invocations { get; } = new List(); @@ -59,48 +59,57 @@ public DefaultMock(IStunt stunt) public IMockBehaviorPipeline GetPipeline(IMockSetup setup) => setupBehaviorMap.GetOrAdd(setup, x => { + var behaviors = stunt.Behaviors; var behavior = new MockBehaviorPipeline(x); + // The tracking behavior must appear before the mock behaviors. - var context = Behaviors.OfType().FirstOrDefault(); + var context = behaviors.OfType().FirstOrDefault(); // If there is a recording behavior, it must be before mock behaviors too. - var recording = Behaviors.OfType().FirstOrDefault(); + var recording = behaviors.OfType().FirstOrDefault(); - var index = context == null ? 0 : Behaviors.IndexOf(context); + var index = context == null ? 0 : behaviors.IndexOf(context); if (recording != null) - index = Math.Max(index, Behaviors.IndexOf(recording)); + index = Math.Max(index, behaviors.IndexOf(recording)); // NOTE: latest setup wins, since it goes to the top of the list. - Behaviors.Insert(++index, behavior); + behaviors.Insert(++index, behavior); return behavior; }); - void OnBehaviorsChanged(object sender, NotifyCollectionChangedEventArgs e) + private void OnBehaviorsChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: + var behaviors = stunt.Behaviors; + // TODO: optimize these two checks // Can't have more than one of MockContextBehavior, since that causes problems. - if (Behaviors.OfType().Skip(1).Any()) - throw new InvalidOperationException(Resources.DuplicateContextBehavior); + if (behaviors.OfType().Skip(1).Any()) + throw new InvalidOperationException(ThisAssembly.Strings.DuplicateContextBehavior); // Can't have more than one of MockRecordingBehavior, since that causes problems. - if (Behaviors.OfType().Skip(1).Any()) - throw new InvalidOperationException(Resources.DuplicateRecordingBehavior); + if (behaviors.OfType().Skip(1).Any()) + throw new InvalidOperationException(ThisAssembly.Strings.DuplicateRecordingBehavior); foreach (var behavior in e.NewItems.OfType()) setupBehaviorMap.TryAdd(behavior.Setup, behavior); break; + case NotifyCollectionChangedAction.Remove: foreach (var behavior in e.OldItems.OfType()) setupBehaviorMap.TryRemove(behavior.Setup, out _); break; + case NotifyCollectionChangedAction.Replace: - foreach (var behavior in e.NewItems.OfType()) - setupBehaviorMap.TryAdd(behavior.Setup, behavior); foreach (var behavior in e.OldItems.OfType()) setupBehaviorMap.TryRemove(behavior.Setup, out _); + foreach (var behavior in e.NewItems.OfType()) + setupBehaviorMap.TryAdd(behavior.Setup, behavior); break; + case NotifyCollectionChangedAction.Reset: setupBehaviorMap.Clear(); + foreach (var behavior in stunt.Behaviors.OfType()) + setupBehaviorMap.TryAdd(behavior.Setup, behavior); break; } } diff --git a/src/Moq/Moq.Sdk/DelegateMockBehavior.cs b/src/Moq.Sdk/DelegateMockBehavior.cs similarity index 94% rename from src/Moq/Moq.Sdk/DelegateMockBehavior.cs rename to src/Moq.Sdk/DelegateMockBehavior.cs index a92afaaa..78c800e9 100644 --- a/src/Moq/Moq.Sdk/DelegateMockBehavior.cs +++ b/src/Moq.Sdk/DelegateMockBehavior.cs @@ -12,8 +12,8 @@ namespace Moq.Sdk [DebuggerDisplay("{DisplayName}")] public class DelegateMockBehavior : IMockBehavior { - readonly Lazy displayName; - readonly ExecuteMockDelegate behavior; + private readonly Lazy displayName; + private readonly ExecuteMockDelegate behavior; /// /// Creates an instance of the invokable behavior with the given diff --git a/src/Moq/Moq.Sdk/EventBehavior.cs b/src/Moq.Sdk/EventBehavior.cs similarity index 94% rename from src/Moq/Moq.Sdk/EventBehavior.cs rename to src/Moq.Sdk/EventBehavior.cs index 8927cb8c..4ba4698c 100644 --- a/src/Moq/Moq.Sdk/EventBehavior.cs +++ b/src/Moq.Sdk/EventBehavior.cs @@ -30,8 +30,7 @@ public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) if (info != null) { - EventRaiser raiser = null; - if ((raiser = CallContext.GetData()) != null) + if (CallContext.GetData() is EventRaiser raiser) { try { @@ -77,7 +76,7 @@ public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) return next()(invocation, next); } - static void CombineDelegate(EventInfo info, Delegate handler, IMock mock) + private static void CombineDelegate(EventInfo info, Delegate handler, IMock mock) { var state = mock.State.GetOrAdd(info.Name, () => handler); if (state != handler) @@ -101,7 +100,7 @@ static void CombineDelegate(EventInfo info, Delegate handler, IMock mock) } } - static void RemoveDelegate(EventInfo info, Delegate handler, IMock mock) + private static void RemoveDelegate(EventInfo info, Delegate handler, IMock mock) { if (mock.State.TryGetValue(info.Name, out var state)) { diff --git a/src/Moq/Moq.Sdk/EventRaiser.cs b/src/Moq.Sdk/EventRaiser.cs similarity index 91% rename from src/Moq/Moq.Sdk/EventRaiser.cs rename to src/Moq.Sdk/EventRaiser.cs index 877967e5..bc7ecb7e 100644 --- a/src/Moq/Moq.Sdk/EventRaiser.cs +++ b/src/Moq.Sdk/EventRaiser.cs @@ -14,7 +14,7 @@ public abstract class EventRaiser public static EventRaiser Empty { get; } = new EmptyEventRaiser(); } - class EmptyEventRaiser : EventRaiser { } + internal class EmptyEventRaiser : EventRaiser { } /// /// Context state that signals an event must be @@ -28,12 +28,12 @@ public class EventArgsEventRaiser : EventRaiser /// Creates an instance of the /// with the given event arguments. /// - public EventArgsEventRaiser(object args) => EventArgs = args; + public EventArgsEventRaiser(object? args) => EventArgs = args; /// /// The event arguments for the raised event. /// - public object EventArgs { get; } + public object? EventArgs { get; } } /// diff --git a/src/Moq/Moq.Sdk/GlobalSuppressions.cs b/src/Moq.Sdk/GlobalSuppressions.cs similarity index 100% rename from src/Moq/Moq.Sdk/GlobalSuppressions.cs rename to src/Moq.Sdk/GlobalSuppressions.cs diff --git a/src/Moq/Moq.Sdk/IArgumentMatcher.cs b/src/Moq.Sdk/IArgumentMatcher.cs similarity index 87% rename from src/Moq/Moq.Sdk/IArgumentMatcher.cs rename to src/Moq.Sdk/IArgumentMatcher.cs index 79c3d9ae..039af635 100644 --- a/src/Moq/Moq.Sdk/IArgumentMatcher.cs +++ b/src/Moq.Sdk/IArgumentMatcher.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; namespace Moq.Sdk { @@ -16,6 +15,6 @@ public interface IArgumentMatcher /// /// Evaluates whether the given value matches this instance. /// - bool Matches(object value); + bool Matches(object? value); } } diff --git a/src/Moq/Moq.Sdk/IMock.cs b/src/Moq.Sdk/IMock.cs similarity index 100% rename from src/Moq/Moq.Sdk/IMock.cs rename to src/Moq.Sdk/IMock.cs diff --git a/src/Moq/Moq.Sdk/IMockBehavior.cs b/src/Moq.Sdk/IMockBehavior.cs similarity index 100% rename from src/Moq/Moq.Sdk/IMockBehavior.cs rename to src/Moq.Sdk/IMockBehavior.cs diff --git a/src/Moq/Moq.Sdk/IMockBehaviorPipeline.cs b/src/Moq.Sdk/IMockBehaviorPipeline.cs similarity index 100% rename from src/Moq/Moq.Sdk/IMockBehaviorPipeline.cs rename to src/Moq.Sdk/IMockBehaviorPipeline.cs diff --git a/src/Moq/Moq.Sdk/IMockFactory.cs b/src/Moq.Sdk/IMockFactory.cs similarity index 100% rename from src/Moq/Moq.Sdk/IMockFactory.cs rename to src/Moq.Sdk/IMockFactory.cs diff --git a/src/Moq/Moq.Sdk/IMockSetup.cs b/src/Moq.Sdk/IMockSetup.cs similarity index 100% rename from src/Moq/Moq.Sdk/IMockSetup.cs rename to src/Moq.Sdk/IMockSetup.cs diff --git a/src/Moq/Moq.Sdk/IMock`1.cs b/src/Moq.Sdk/IMock`1.cs similarity index 100% rename from src/Moq/Moq.Sdk/IMock`1.cs rename to src/Moq.Sdk/IMock`1.cs diff --git a/src/Moq/Moq.Sdk/IMocked.cs b/src/Moq.Sdk/IMocked.cs similarity index 61% rename from src/Moq/Moq.Sdk/IMocked.cs rename to src/Moq.Sdk/IMocked.cs index f0aa8104..2720aafc 100644 --- a/src/Moq/Moq.Sdk/IMocked.cs +++ b/src/Moq.Sdk/IMocked.cs @@ -1,5 +1,4 @@ -using System.CodeDom.Compiler; -using System.Diagnostics; +using System.Diagnostics; using System.Runtime.CompilerServices; namespace Moq.Sdk @@ -9,16 +8,13 @@ namespace Moq.Sdk /// the interface for introspecting /// a mock instance. /// - // These attributes prevent registering the "Implement through behavior pipeline" codefix. - // See CustomMockCodeFixProvider and its base class CustomStuntCodeFixProvider. - [GeneratedCode("Moq", ThisAssembly.Metadata.Version)] [CompilerGenerated] public interface IMocked { /// /// The introspection information for the current mock. /// - [DebuggerDisplay("Invocations = {Mock.Invocations.Count}", Name = nameof(IMocked) + "." + nameof(IMocked.Mock))] + [DebuggerDisplay("Invocations = {Mock.Invocations.Count}", Name = nameof(IMocked) + "." + nameof(Mock))] [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] IMock Mock { get; } } diff --git a/src/Moq/Moq.Sdk/MockBehaviorPipeline.cs b/src/Moq.Sdk/MockBehaviorPipeline.cs similarity index 97% rename from src/Moq/Moq.Sdk/MockBehaviorPipeline.cs rename to src/Moq.Sdk/MockBehaviorPipeline.cs index fa0a890d..cf562d21 100644 --- a/src/Moq/Moq.Sdk/MockBehaviorPipeline.cs +++ b/src/Moq.Sdk/MockBehaviorPipeline.cs @@ -1,7 +1,6 @@ using System; using System.Collections.ObjectModel; using System.Diagnostics; -using Moq.Sdk.Properties; using Stunts; namespace Moq.Sdk @@ -38,7 +37,7 @@ public class MockBehaviorPipeline : IMockBehaviorPipeline /// public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) { - var mock = (invocation.Target as IMocked)?.Mock ?? throw new ArgumentException(Resources.TargetNotMock); + var mock = (invocation.Target as IMocked)?.Mock ?? throw new ArgumentException(ThisAssembly.Strings.TargetNotMock); // NOTE: the mock behavior is like a sub-pipeline within the overall stunt // behavior pipeline, where all the behaviors added automatically apply diff --git a/src/Moq/Moq.Sdk/MockContext.cs b/src/Moq.Sdk/MockContext.cs similarity index 91% rename from src/Moq/Moq.Sdk/MockContext.cs rename to src/Moq.Sdk/MockContext.cs index adfb71ea..2870053d 100644 --- a/src/Moq/Moq.Sdk/MockContext.cs +++ b/src/Moq.Sdk/MockContext.cs @@ -12,7 +12,7 @@ public static class MockContext /// The most recent invocation performed on the mock, tracked /// by the . /// - public static IMethodInvocation CurrentInvocation + public static IMethodInvocation? CurrentInvocation { get => CallContext.GetData(); set => CallContext.SetData(value); @@ -28,7 +28,7 @@ public static IMethodInvocation CurrentInvocation /// This property is also tracked and populated by the /// . /// - public static IMockSetup CurrentSetup + public static IMockSetup? CurrentSetup { get => CallContext.GetData(); set => CallContext.SetData(value); diff --git a/src/Moq/Moq.Sdk/MockContextBehavior.cs b/src/Moq.Sdk/MockContextBehavior.cs similarity index 100% rename from src/Moq/Moq.Sdk/MockContextBehavior.cs rename to src/Moq.Sdk/MockContextBehavior.cs diff --git a/src/Moq/Moq.Sdk/MockDecorator.cs b/src/Moq.Sdk/MockDecorator.cs similarity index 90% rename from src/Moq/Moq.Sdk/MockDecorator.cs rename to src/Moq.Sdk/MockDecorator.cs index dd329998..277e1ec6 100644 --- a/src/Moq/Moq.Sdk/MockDecorator.cs +++ b/src/Moq.Sdk/MockDecorator.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Collections.ObjectModel; using Stunts; namespace Moq.Sdk @@ -9,7 +8,7 @@ namespace Moq.Sdk /// public abstract class MockDecorator : IMock { - readonly IMock mock; + private readonly IMock mock; /// /// Initializes the decorator with the given underlying @@ -44,7 +43,7 @@ public virtual StateBag State /// /// See . /// - public virtual ObservableCollection Behaviors => mock.Behaviors; + public virtual IList Behaviors => mock.Behaviors; /// /// See . diff --git a/src/Moq/Moq.Sdk/MockDecorator`1.cs b/src/Moq.Sdk/MockDecorator`1.cs similarity index 93% rename from src/Moq/Moq.Sdk/MockDecorator`1.cs rename to src/Moq.Sdk/MockDecorator`1.cs index 664e8853..35edcd0b 100644 --- a/src/Moq/Moq.Sdk/MockDecorator`1.cs +++ b/src/Moq.Sdk/MockDecorator`1.cs @@ -5,7 +5,7 @@ /// public abstract class MockDecorator : MockDecorator, IMock where T : class { - readonly IMock mock; + private readonly IMock mock; /// /// Initializes the decorator with the given underlying diff --git a/src/Moq/Moq.Sdk/MockException.cs b/src/Moq.Sdk/MockException.cs similarity index 92% rename from src/Moq/Moq.Sdk/MockException.cs rename to src/Moq.Sdk/MockException.cs index 36b29e6b..36007644 100644 --- a/src/Moq/Moq.Sdk/MockException.cs +++ b/src/Moq.Sdk/MockException.cs @@ -1,6 +1,4 @@ using System; -using System.Linq; -using System.Reflection; namespace Moq.Sdk { diff --git a/src/Moq/Moq.Sdk/MockExtensions.cs b/src/Moq.Sdk/MockExtensions.cs similarity index 73% rename from src/Moq/Moq.Sdk/MockExtensions.cs rename to src/Moq.Sdk/MockExtensions.cs index baf27854..79183377 100644 --- a/src/Moq/Moq.Sdk/MockExtensions.cs +++ b/src/Moq.Sdk/MockExtensions.cs @@ -1,10 +1,9 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel; +using System.Data; using System.Diagnostics; using System.Linq; -using Moq.Sdk.Properties; using Stunts; namespace Moq.Sdk @@ -21,7 +20,7 @@ public static class MockExtensions public static IMock AsMock(this T instance) where T : class => (instance is MulticastDelegate @delegate ? @delegate.Target as IMocked : - instance as IMocked)?.Mock.As(instance) ?? throw new ArgumentException(Strings.TargetNotMock, nameof(instance)); + instance as IMocked)?.Mock.As(instance) ?? throw new ArgumentException(ThisAssembly.Strings.TargetNotMock, nameof(instance)); /// /// Clones a mock by creating a new instance of the @@ -32,22 +31,29 @@ public static IMock Clone(this IMock mock) where T : class if (!mock.State.TryGetValue(".ctor", out var ctor)) throw new ArgumentException("No constructor state found for cloning."); - // TODO: THIS DOESN'T WORK WITH DYNAMIC PROXIES, SINCE WE'RE MISSING THE INTERCEPTORS - // This is what it looks like in a DP: public BaseWithCtorProxy(IInterceptor[] interceptorArray, string value) : base(value) - // So we need to persist the interceptors as part of the ctor array, maybe? var clone = ((IMocked)Activator.CreateInstance(mock.Object.GetType(), ctor)).Mock; clone.State = mock.State.Clone(); - clone.Behaviors.Clear(); - foreach (var behavior in mock.Behaviors) + var behaviors = clone.Behaviors; + (behaviors as ISupportInitialize)?.BeginInit(); + try { - clone.Behaviors.Add(behavior); + behaviors.Clear(); + foreach (var behavior in mock.Behaviors) + { + behaviors.Add(behavior); + } + } + finally + { + (behaviors as ISupportInitialize)?.EndInit(); } - clone.Invocations.Clear(); + var invocations = clone.Invocations; + invocations.Clear(); foreach (var invocation in mock.Invocations) { - clone.Invocations.Add(invocation); + invocations.Add(invocation); } return ((T)clone.Object).AsMock(); @@ -62,7 +68,7 @@ public static IEnumerable InvocationsFor(this IMock moc using (new SetupScope()) { action(mock.Object); - var setup = MockContext.CurrentSetup; + var setup = MockContext.CurrentSetup ?? CallContext.ThrowUnexpectedNull(); return mock.Invocations.Where(x => setup.AppliesTo(x)); } } @@ -76,16 +82,16 @@ public static IEnumerable InvocationsFor(this IMo using (new SetupScope()) { function(mock.Object); - var setup = MockContext.CurrentSetup; + var setup = MockContext.CurrentSetup ?? CallContext.ThrowUnexpectedNull(); return mock.Invocations.Where(x => setup.AppliesTo(x)); } } - static IMock As(this IMock mock, T target) where T : class => mock == null ? null : new Mock(mock, target); + private static IMock? As(this IMock? mock, T target) where T : class => mock == null ? null : new Mock(mock, target); - class Mock : IMock where T : class + private class Mock : IMock where T : class { - IMock mock; + private readonly IMock mock; public Mock(IMock mock, T target) { @@ -108,7 +114,7 @@ public StateBag State public IEnumerable Setups => mock.Setups; - public ObservableCollection Behaviors => mock.Behaviors; + public IList Behaviors => mock.Behaviors; public IMockBehaviorPipeline GetPipeline(IMockSetup setup) => mock.GetPipeline(setup); } diff --git a/src/Moq.Sdk/MockFactory.cs b/src/Moq.Sdk/MockFactory.cs new file mode 100644 index 00000000..ad72b539 --- /dev/null +++ b/src/Moq.Sdk/MockFactory.cs @@ -0,0 +1,34 @@ +using System; +using System.Reflection; + +namespace Moq.Sdk +{ + /// + /// Allows accessing the default used + /// to create mocks. + /// + public class MockFactory : IMockFactory + { + private static readonly IMockFactory nullFactory = new MockFactory(); + + /// + /// Gets or sets the default to use + /// to create mocks. Defaults to the factory. + /// + public static IMockFactory Default { get; set; } = nullFactory; + + /// + /// A factory that throws . + /// + public static IMockFactory NotImplemented { get; } = nullFactory; + + private MockFactory() { } + + /// + /// Throws since this is the default + /// factory. + /// + public object CreateMock(Assembly mocksAssembly, Type baseType, Type[] implementedInterfaces, object[] constructorArguments) + => throw new NotImplementedException(ThisAssembly.Strings.MockFactoryNotImplemented); + } +} \ No newline at end of file diff --git a/src/Moq/Moq.Sdk/MockFactoryExtensions.cs b/src/Moq.Sdk/MockFactoryExtensions.cs similarity index 100% rename from src/Moq/Moq.Sdk/MockFactoryExtensions.cs rename to src/Moq.Sdk/MockFactoryExtensions.cs diff --git a/src/Moq/Moq.Sdk/MockGeneratorAttribute.cs b/src/Moq.Sdk/MockGeneratorAttribute.cs similarity index 100% rename from src/Moq/Moq.Sdk/MockGeneratorAttribute.cs rename to src/Moq.Sdk/MockGeneratorAttribute.cs diff --git a/src/Moq/Moq.Sdk/MockNaming.cs b/src/Moq.Sdk/MockNaming.cs similarity index 100% rename from src/Moq/Moq.Sdk/MockNaming.cs rename to src/Moq.Sdk/MockNaming.cs diff --git a/src/Moq/Moq.Sdk/MockRecordingBehavior.cs b/src/Moq.Sdk/MockRecordingBehavior.cs similarity index 94% rename from src/Moq/Moq.Sdk/MockRecordingBehavior.cs rename to src/Moq.Sdk/MockRecordingBehavior.cs index d4cc5852..e8b3150a 100644 --- a/src/Moq/Moq.Sdk/MockRecordingBehavior.cs +++ b/src/Moq.Sdk/MockRecordingBehavior.cs @@ -1,6 +1,4 @@ -using System; -using Stunts; -using System.Diagnostics; +using Stunts; namespace Moq.Sdk { diff --git a/src/Moq/Moq.Sdk/MockSetup.Static.cs b/src/Moq.Sdk/MockSetup.Static.cs similarity index 83% rename from src/Moq/Moq.Sdk/MockSetup.Static.cs rename to src/Moq.Sdk/MockSetup.Static.cs index 0308d69f..862d9e07 100644 --- a/src/Moq/Moq.Sdk/MockSetup.Static.cs +++ b/src/Moq.Sdk/MockSetup.Static.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Stunts; @@ -19,9 +20,9 @@ public partial class MockSetup public static T Push(IArgumentMatcher matcher) { CallContext>.GetData(() => new Queue()) - .Enqueue(matcher); + ?.Enqueue(matcher); - return default; + return default!; } /// @@ -32,7 +33,9 @@ public static T Push(IArgumentMatcher matcher) /// An that can be used to filter invocations in a behavior pipeline. internal static IMockSetup Freeze(IMethodInvocation invocation) { - var currentMatchers = CallContext>.GetData(() => new Queue()); + var currentMatchers = CallContext>.GetData(() => new Queue()) + ?? throw new InvalidOperationException(ThisAssembly.Strings.UnexpectedNullContextState(typeof(Queue).FullName)); + var finalMatchers = new List(); var parameters = invocation.MethodBase.GetParameters(); var defaultValue = (invocation.Target as IMocked)?. @@ -47,9 +50,9 @@ internal static IMockSetup Freeze(IMethodInvocation invocation) // This is a bit fuzzy since we compare the actual argument value against the // default value for the parameter type, or the type of the matcher in the // queue of argument matchers to see if applies instead. - if (object.Equals(argument, defaultValue.GetDefault(parameter.ParameterType)) && + if (Equals(argument, defaultValue.GetDefault(parameter.ParameterType)) && currentMatchers.Count != 0 && - parameter.ParameterType.GetValueTypeInfo().IsAssignableFrom(currentMatchers.Peek().ArgumentType.GetValueTypeInfo())) + parameter.ParameterType.IsAssignableFrom(currentMatchers.Peek().ArgumentType)) { finalMatchers.Add(currentMatchers.Dequeue()); } diff --git a/src/Moq/Moq.Sdk/MockSetup.cs b/src/Moq.Sdk/MockSetup.cs similarity index 92% rename from src/Moq/Moq.Sdk/MockSetup.cs rename to src/Moq.Sdk/MockSetup.cs index 034baf17..8901ccf1 100644 --- a/src/Moq/Moq.Sdk/MockSetup.cs +++ b/src/Moq.Sdk/MockSetup.cs @@ -1,6 +1,4 @@ using System; -using System.Collections; -using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; @@ -16,9 +14,9 @@ namespace Moq.Sdk public partial class MockSetup : IMockSetup, IEquatable { [DebuggerBrowsable(DebuggerBrowsableState.Never)] - readonly IMethodInvocation invocation; + private readonly IMethodInvocation invocation; [DebuggerBrowsable(DebuggerBrowsableState.Never)] - readonly IArgumentMatcher[] matchers; + private readonly IArgumentMatcher[] matchers; /// /// Initializes the class with the and @@ -135,7 +133,7 @@ public override string ToString() #region Equality /// - public bool Equals(IMockSetup other) + public bool Equals(IMockSetup? other) => other != null && Invocation.Equals(other.Invocation) && Matchers.SequenceEqual(other.Matchers); /// @@ -147,8 +145,16 @@ public override bool Equals(object obj) => Equals(obj as IMockSetup); /// - public override int GetHashCode() - => new HashCode().Add(Invocation).AddRange(Matchers).ToHashCode(); + public override int GetHashCode() + { + var hash = new HashCode(); + hash.Add(Invocation); + foreach (var matcher in Matchers) + { + hash.Add(matcher); + } + return hash.ToHashCode(); + } #endregion } diff --git a/src/Moq.Sdk/Moq.Sdk.csproj b/src/Moq.Sdk/Moq.Sdk.csproj new file mode 100644 index 00000000..6b7920a8 --- /dev/null +++ b/src/Moq.Sdk/Moq.Sdk.csproj @@ -0,0 +1,21 @@ + + + + netstandard2.0 + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Moq/Moq.Sdk/NotMatcher.cs b/src/Moq.Sdk/NotMatcher.cs similarity index 71% rename from src/Moq/Moq.Sdk/NotMatcher.cs rename to src/Moq.Sdk/NotMatcher.cs index a5730acf..b4b1ae71 100644 --- a/src/Moq/Moq.Sdk/NotMatcher.cs +++ b/src/Moq.Sdk/NotMatcher.cs @@ -1,6 +1,5 @@ using System; using System.Diagnostics; -using Stunts; namespace Moq.Sdk { @@ -12,12 +11,12 @@ namespace Moq.Sdk public class NotMatcher : IArgumentMatcher, IEquatable> { [DebuggerBrowsable(DebuggerBrowsableState.Never)] - readonly T value; + private readonly T? value; /// /// Initalizes the matcher with the value to check for. /// - public NotMatcher(T value) => this.value = value; + public NotMatcher(T? value) => this.value = value; /// /// Gets the type of the argument this matcher supports. @@ -28,7 +27,7 @@ public class NotMatcher : IArgumentMatcher, IEquatable> /// Evaluates whether the given value matches this instance, which is always /// the case unless the initial value equals the . /// - public bool Matches(object value) => !(Object.Equals(this.value, value)); + public bool Matches(object? value) => !(Equals(this.value, value)); /// /// Gets a friendly representation of the object. @@ -39,20 +38,18 @@ public class NotMatcher : IArgumentMatcher, IEquatable> /// No actual behavior depends on these strings. /// [DebuggerNonUserCode] - public override string ToString() => "!" + (value is string ? "\"" + value + "\"" : value.ToString()); + public override string ToString() => "!" + (value is string ? "\"" + value + "\"" : (value == null ? "null" : value.ToString())); #region Equality /// - public bool Equals(NotMatcher other) => other == null ? false : - ArgumentType == other.ArgumentType && object.Equals(value, other.value); + public bool Equals(NotMatcher other) => other != null && ArgumentType == other.ArgumentType && Equals(value, other.value); /// - public override bool Equals(object obj) => Equals(obj as NotMatcher); + public override bool Equals(object obj) => obj is NotMatcher matcher && Equals(matcher); /// - public override int GetHashCode() - => new HashCode().Add(ArgumentType).Add(value == null ? 0 : value.GetHashCode()).ToHashCode(); + public override int GetHashCode() => HashCode.Combine(ArgumentType, value == null ? 0 : value.GetHashCode()); #endregion } diff --git a/src/Moq/Moq.Sdk/PropertyBehavior.cs b/src/Moq.Sdk/PropertyBehavior.cs similarity index 96% rename from src/Moq/Moq.Sdk/PropertyBehavior.cs rename to src/Moq.Sdk/PropertyBehavior.cs index b2e91595..871766c1 100644 --- a/src/Moq/Moq.Sdk/PropertyBehavior.cs +++ b/src/Moq.Sdk/PropertyBehavior.cs @@ -1,5 +1,4 @@ using System; -using Moq.Sdk.Properties; using Stunts; namespace Moq.Sdk @@ -34,7 +33,7 @@ public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) { if (invocation == null) throw new ArgumentNullException(nameof(invocation)); - var state = (invocation.Target as IMocked ?? throw new ArgumentException(Strings.TargetNotMock, nameof(invocation))) + var state = (invocation.Target as IMocked ?? throw new ArgumentException(ThisAssembly.Strings.TargetNotMock, nameof(invocation))) .Mock.State; if (invocation.MethodBase.Name.StartsWith("get_", StringComparison.Ordinal) && diff --git a/src/Moq/Moq.Sdk/Properties/Resources.resx b/src/Moq.Sdk/Resources.resx similarity index 94% rename from src/Moq/Moq.Sdk/Properties/Resources.resx rename to src/Moq.Sdk/Resources.resx index 1b5c69cd..67ee010b 100644 --- a/src/Moq/Moq.Sdk/Properties/Resources.resx +++ b/src/Moq.Sdk/Resources.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Could not locate event for attach or detach method {0}. + Could not locate event for attach or detach method '{0}'. No setup is currently being performed on the mock. @@ -132,4 +132,10 @@ The mock already contains a recording behavior. + + Default factory does not implement mock creation. + + + Did not expect the call context to have a null value for key '{0}'. + \ No newline at end of file diff --git a/src/Moq/Moq.Sdk/SetupScope.cs b/src/Moq.Sdk/SetupScope.cs similarity index 93% rename from src/Moq/Moq.Sdk/SetupScope.cs rename to src/Moq.Sdk/SetupScope.cs index 504c3661..44a2d750 100644 --- a/src/Moq/Moq.Sdk/SetupScope.cs +++ b/src/Moq.Sdk/SetupScope.cs @@ -18,7 +18,7 @@ namespace Moq /// public class SetupScope : IDisposable { - static AsyncLocal setup = new AsyncLocal(); + private static readonly AsyncLocal setup = new AsyncLocal(); /// /// Initializes the setup scope. diff --git a/src/Moq/Moq.Sdk/StackTraceExtensions.cs b/src/Moq.Sdk/StackTraceExtensions.cs similarity index 100% rename from src/Moq/Moq.Sdk/StackTraceExtensions.cs rename to src/Moq.Sdk/StackTraceExtensions.cs diff --git a/src/Moq/Moq.Sdk/StateBag.cs b/src/Moq.Sdk/StateBag.cs similarity index 91% rename from src/Moq/Moq.Sdk/StateBag.cs rename to src/Moq.Sdk/StateBag.cs index 4b9d347f..fbe8afb9 100644 --- a/src/Moq/Moq.Sdk/StateBag.cs +++ b/src/Moq.Sdk/StateBag.cs @@ -11,17 +11,14 @@ namespace Moq.Sdk public class StateBag { [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] - ConcurrentDictionary state; + private readonly ConcurrentDictionary state; /// /// Creates a new instance of the state bag. /// - public StateBag() - : this(new ConcurrentDictionary()) - { - } + public StateBag() : this(new()) { } - private StateBag(ConcurrentDictionary initialState) => state = new ConcurrentDictionary(initialState); + private StateBag(ConcurrentDictionary initialState) => state = new(initialState); /// /// Creates a copy of the state bag. @@ -49,20 +46,20 @@ public StateBag() /// specified function, if a value with the given type does not already exist. /// public T GetOrAdd(Func valueFactory) - => (T)state.GetOrAdd(typeof(T), _ => valueFactory()); + => (T)state.GetOrAdd(typeof(T), _ => valueFactory()!); /// /// Adds the state of the given type and /// by using the specified function, if a value with the given type does not already exist. /// public T GetOrAdd(object key, Func valueFactory) - => (T)state.GetOrAdd(Key(key), _ => valueFactory()); + => (T)state.GetOrAdd(Key(key), _ => valueFactory()!); /// /// Sets the state of the given type , /// regardless of whether there is an existing value assigned. /// - public void Set(T value) + public void Set(T? value) { if (value == null) state.TryRemove(typeof(T), out _); @@ -74,7 +71,7 @@ public void Set(T value) /// Sets the state of the given type , /// regardless of whether there is an existing value assigned. /// - public void Set(Func value) + public void Set(Func? value) { if (value == null) state.TryRemove(typeof(T), out _); @@ -86,7 +83,7 @@ public void Set(Func value) /// Sets the state of the given type and , /// regardless of whether there is an existing value assigned. /// - public void Set(object key, T value) + public void Set(object key, T? value) { if (value == null) state.TryRemove(Key(key), out _); @@ -98,7 +95,7 @@ public void Set(object key, T value) /// Sets the state of the given type and , /// regardless of whether there is an existing value assigned. /// - public void Set(object key, Func value) + public void Set(object key, Func? value) { if (value == null) state.TryRemove(Key(key), out _); @@ -112,7 +109,7 @@ public void Set(object key, Func value) /// The type of value to add. /// The value of the element to add. /// - public bool TryAdd(T value) => state.TryAdd(typeof(T), value); + public bool TryAdd(T value) => state.TryAdd(typeof(T), value!); /// /// Attempts to add the specified value to the mock state with the given @@ -122,7 +119,7 @@ public void Set(object key, Func value) /// The key of the element to add. /// The value of the element to add. /// - public bool TryAdd(object key, T value) => state.TryAdd(Key(key), value); + public bool TryAdd(object key, T value) => state.TryAdd(Key(key), value!); /// /// Attempts to get the value of the given from the mock state. @@ -131,7 +128,7 @@ public void Set(object key, Func value) /// When this method returns, contains the object from the mock state /// that has the specified , or the default value of the type if /// the operation failed. - public bool TryGetValue(out T value) + public bool TryGetValue(out T? value) { var result = state.TryGetValue(typeof(T), out var _value); value = default; @@ -150,7 +147,7 @@ public bool TryGetValue(out T value) /// When this method returns, contains the object from the mock state /// that has the specified , or the default value of the type if /// the operation failed. - public bool TryGetValue(object key, out T value) + public bool TryGetValue(object key, out T? value) { var result = state.TryGetValue(Key(key), out var _value); value = default; @@ -173,7 +170,7 @@ public bool TryGetValue(object key, out T value) /// When this method returns, contains the object removed from the /// mock state, or the default value of the type if key does not exist. /// if the object was removed successfully; otherwise, . - public bool TryRemove(out T value) + public bool TryRemove(out T? value) { var result = state.TryRemove(typeof(T), out var _value); value = default; @@ -192,7 +189,7 @@ public bool TryRemove(out T value) /// When this method returns, contains the object removed from the /// mock state, or the default value of the type if key does not exist. /// if the object was removed successfully; otherwise, . - public bool TryRemove(object key, out T value) + public bool TryRemove(object key, out T? value) { var result = state.TryRemove(Key(key), out var _value); value = default; @@ -214,7 +211,7 @@ public bool TryRemove(object key, out T value) /// if the value with the given was equal /// to and was replaced with ; otherwise, /// . - public bool TryUpdate(T newValue, T comparisonValue) => state.TryUpdate(typeof(T), newValue, comparisonValue); + public bool TryUpdate(T newValue, T comparisonValue) => state.TryUpdate(typeof(T), newValue!, comparisonValue!); /// /// Compares the existing value for of the specified with a specified value, @@ -229,11 +226,11 @@ public bool TryRemove(object key, out T value) /// if the value with the given was equal /// to and was replaced with ; otherwise, /// . - public bool TryUpdate(object key, T newValue, T comparisonValue) => state.TryUpdate(Key(key), newValue, comparisonValue); + public bool TryUpdate(object key, T newValue, T comparisonValue) => state.TryUpdate(Key(key), newValue!, comparisonValue!); /// /// Gets the key to use depending on the received . /// - object Key(object key) => typeof(T) == typeof(object) ? key : (Key: key, Type: typeof(T)); + private object Key(object key) => typeof(T) == typeof(object) ? key : (Key: key, Type: typeof(T)); } } \ No newline at end of file diff --git a/src/Moq.Sdk/StaticMockFactory.cs b/src/Moq.Sdk/StaticMockFactory.cs new file mode 100644 index 00000000..30814c93 --- /dev/null +++ b/src/Moq.Sdk/StaticMockFactory.cs @@ -0,0 +1,32 @@ +using System; +using System.ComponentModel; +using System.Reflection; + +namespace Moq.Sdk +{ + /// + /// Provides a that creates mocks from types + /// generated at compile-time that are included in the received mock + /// assembly in . + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public class StaticMockFactory : IMockFactory + { + /// + /// Uses the method to + /// determine the expected full type name of a compile-time generated mocks + /// and tries to locate it from . + /// + /// The assembly containing the compile-time generated mocks. + /// Base type of the mock. + /// Additional interfaces the mock implements. + /// Optional additional constructor arguments for the mock. + public object CreateMock(Assembly mocksAssembly, Type baseType, Type[] implementedInterfaces, object[] constructorArguments) + { + var name = MockNaming.GetFullName(baseType, implementedInterfaces); + var type = mocksAssembly.GetType(name, true, false); + + return Activator.CreateInstance(type, constructorArguments); + } + } +} diff --git a/src/Moq/Moq.Sdk/StrictMockBehavior.cs b/src/Moq.Sdk/StrictMockBehavior.cs similarity index 95% rename from src/Moq/Moq.Sdk/StrictMockBehavior.cs rename to src/Moq.Sdk/StrictMockBehavior.cs index 25641033..016edc1a 100644 --- a/src/Moq/Moq.Sdk/StrictMockBehavior.cs +++ b/src/Moq.Sdk/StrictMockBehavior.cs @@ -1,5 +1,4 @@ -using System; -using Stunts; +using Stunts; namespace Moq.Sdk { diff --git a/src/Moq/Moq.Sdk/StrictMockException.cs b/src/Moq.Sdk/StrictMockException.cs similarity index 100% rename from src/Moq/Moq.Sdk/StrictMockException.cs rename to src/Moq.Sdk/StrictMockException.cs diff --git a/src/Moq/Moq.Sdk/Times.cs b/src/Moq.Sdk/Times.cs similarity index 98% rename from src/Moq/Moq.Sdk/Times.cs rename to src/Moq.Sdk/Times.cs index 8b61ce77..4b49c6bd 100644 --- a/src/Moq/Moq.Sdk/Times.cs +++ b/src/Moq.Sdk/Times.cs @@ -1,6 +1,5 @@ using System; using System.ComponentModel; -using Stunts; namespace Moq.Sdk { @@ -9,7 +8,7 @@ namespace Moq.Sdk /// public readonly struct Times : IEquatable { - readonly Lazy hashCode; + private readonly Lazy hashCode; /// /// Initializes the constraint with the given and @@ -20,7 +19,7 @@ public Times(int from, int to) { From = from; To = to; - hashCode = new Lazy(() => new HashCode().AddRange(from, to).ToHashCode()); + hashCode = new Lazy(() => HashCode.Combine(from, to)); } /// diff --git a/src/Moq/Moq.Sdk/TypeExtensions.cs b/src/Moq.Sdk/TypeExtensions.cs similarity index 93% rename from src/Moq/Moq.Sdk/TypeExtensions.cs rename to src/Moq.Sdk/TypeExtensions.cs index 2dce7d7c..64b099e8 100644 --- a/src/Moq/Moq.Sdk/TypeExtensions.cs +++ b/src/Moq.Sdk/TypeExtensions.cs @@ -3,7 +3,7 @@ namespace Moq.Sdk { - static class TypeExtensions + internal static class TypeExtensions { /// /// Gets the for the underlying value that diff --git a/src/Moq/Moq.Sdk/ValueMatcher.cs b/src/Moq.Sdk/ValueMatcher.cs similarity index 77% rename from src/Moq/Moq.Sdk/ValueMatcher.cs rename to src/Moq.Sdk/ValueMatcher.cs index f2bb26e1..e2927bef 100644 --- a/src/Moq/Moq.Sdk/ValueMatcher.cs +++ b/src/Moq.Sdk/ValueMatcher.cs @@ -8,14 +8,14 @@ namespace Moq.Sdk /// public class ValueMatcher : IArgumentMatcher, IEquatable { - readonly Tuple value; + private readonly Tuple value; /// /// Initializes a new instance of the class. /// /// Type of the argument to match. /// The value to match against. - public ValueMatcher(Type argumentType, object matchValue) => value = Tuple.Create(argumentType, matchValue); + public ValueMatcher(Type argumentType, object? matchValue) => value = Tuple.Create(argumentType, matchValue); /// /// Gets the type of the argument this matcher supports. @@ -25,13 +25,13 @@ public class ValueMatcher : IArgumentMatcher, IEquatable /// /// The value to match against invocation arguments. /// - public object MatchValue => value.Item2; + public object? MatchValue => value.Item2; /// /// Evaluates whether the given value equals the /// received in the constructor, using default object equality behavior. /// - public bool Matches(object value) => object.Equals(value, MatchValue); + public bool Matches(object? value) => Equals(value, MatchValue); /// /// Gets a friendly representation of the object. @@ -47,16 +47,16 @@ public override string ToString() ? "\"" + MatchValue + "\"" : (MatchValue?.ToString() ?? "null"); - static bool IsString(Type type) => type == typeof(string) || + private static bool IsString(Type type) => type == typeof(string) || (type.IsByRef && type.HasElementType && type.GetElementType() == typeof(string)); #region Equality /// - public bool Equals(ValueMatcher other) => object.Equals(value, other?.value); + public bool Equals(ValueMatcher other) => Equals(value, other?.value); /// - public override bool Equals(object obj) => Equals(obj as ValueMatcher); + public override bool Equals(object obj) => obj is ValueMatcher matcher && Equals(matcher); /// public override int GetHashCode() => value.GetHashCode(); diff --git a/src/Moq.StaticProxy.UnitTests/Moq.StaticProxy.UnitTests.csproj b/src/Moq.StaticProxy.UnitTests/Moq.StaticProxy.UnitTests.csproj new file mode 100644 index 00000000..857f79cd --- /dev/null +++ b/src/Moq.StaticProxy.UnitTests/Moq.StaticProxy.UnitTests.csproj @@ -0,0 +1,51 @@ + + + + net472;net5.0 + annotations + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Moq.StaticProxy.UnitTests/RoslynHelpers.cs b/src/Moq.StaticProxy.UnitTests/RoslynHelpers.cs new file mode 100644 index 00000000..3fe2ee15 --- /dev/null +++ b/src/Moq.StaticProxy.UnitTests/RoslynHelpers.cs @@ -0,0 +1,31 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Emit; +using Xunit; + +internal static class RoslynHelpers +{ + public static Assembly Emit(this Compilation compilation) + { + using var stream = new MemoryStream(); + var result = compilation.Emit(stream); + result.AssertSuccess(); + + stream.Seek(0, SeekOrigin.Begin); + return Assembly.Load(stream.ToArray()); + } + + public static void AssertSuccess(this EmitResult result) + { + if (!result.Success) + { + Assert.False(true, + "Emit failed:\r\n" + + Environment.NewLine + + string.Join(Environment.NewLine, result.Diagnostics.Select(d => d.ToString()))); + } + } +} \ No newline at end of file diff --git a/src/Moq.StaticProxy.UnitTests/SourceGeneratorTests.cs b/src/Moq.StaticProxy.UnitTests/SourceGeneratorTests.cs new file mode 100644 index 00000000..d940c676 --- /dev/null +++ b/src/Moq.StaticProxy.UnitTests/SourceGeneratorTests.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Moq; +using Moq.Sdk; +using TypeNameFormatter; +using Xunit; + +namespace Stunts.UnitTests +{ + public class SourceGeneratorTests + { + [Fact] + public void GeneratesRecursiveMockForProperties() + { + var code = @" +using Moq; + +namespace UnitTests +{ + public class Test + { + public void Do() + { + var mock = Mock.Of(); + + mock.Bar.Baz.Name.Returns(""hi""); + } + } + + public interface IFoo + { + IBar Bar { get; } + } + + public interface IBar + { + IBaz Baz { get; } + } + + public interface IBaz + { + string Name { get; } + } +}"; + + var (diagnostics, compilation) = GetGeneratedOutput(code); + + Assert.Empty(diagnostics); + + var assembly = compilation.Emit(); + + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IFoo" + MockNaming.DefaultSuffix)); + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IBar" + MockNaming.DefaultSuffix)); + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IBaz" + MockNaming.DefaultSuffix)); + } + + [Fact] + public void GeneratesRecursiveMockForMethods() + { + var code = @" +using Moq; + +namespace UnitTests +{ + public class Test + { + public void Do() + { + var mock = Mock.Of(); + + mock.GetBar().GetBaz().Name.Returns(""hi""); + } + } + + public interface IFoo + { + IBar GetBar(); + } + + public interface IBar + { + IBaz GetBaz(); + } + + public interface IBaz + { + string Name { get; } + } +}"; + + var (diagnostics, compilation) = GetGeneratedOutput(code); + + Assert.Empty(diagnostics); + + var assembly = compilation.Emit(); + + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IFoo" + MockNaming.DefaultSuffix)); + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IBar" + MockNaming.DefaultSuffix)); + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IBaz" + MockNaming.DefaultSuffix)); + } + + [Fact] + public void GeneratesRecursiveMockSetup() + { + var code = @" +using Moq; + +namespace UnitTests +{ + public class Test + { + public void Do() + { + var mock = Mock.Of(); + + mock.Setup(x => x.GetBar().Baz.Name).Returns(""hi""); + } + } + + public interface IFoo + { + IBar GetBar(); + } + + public interface IBar + { + IBaz Baz { get; } + } + + public interface IBaz + { + string Name { get; } + } +}"; + + var (diagnostics, compilation) = GetGeneratedOutput(code); + + Assert.Empty(diagnostics); + + var assembly = compilation.Emit(); + + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IFoo" + MockNaming.DefaultSuffix)); + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IBar" + MockNaming.DefaultSuffix)); + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IBaz" + MockNaming.DefaultSuffix)); + } + + [Fact] + public void GeneratesRecursiveMockSetupScope() + { + var code = @" +using Moq; + +namespace UnitTests +{ + public class Test + { + public void Do() + { + var mock = Mock.Of(); + using (new SetupScope()) + { + mock.GetBar().Baz.Name.Returns(""hi""); + } + } + } + + public interface IFoo + { + IBar GetBar(); + } + + public interface IBar + { + IBaz Baz { get; } + } + + public interface IBaz + { + string Name { get; } + } +}"; + + var (diagnostics, compilation) = GetGeneratedOutput(code); + + Assert.Empty(diagnostics); + + var assembly = compilation.Emit(); + + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IFoo" + MockNaming.DefaultSuffix)); + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IBar" + MockNaming.DefaultSuffix)); + Assert.NotNull(assembly.GetType(MockNaming.DefaultNamespace + ".IBaz" + MockNaming.DefaultSuffix)); + } + + [Fact] + public void GeneratesOneMockPerType() + { + var code = @" +using System; +using Moq; + +namespace UnitTests +{ + public class Test + { + public void Do() + { + var mock = Mock.Of(); + var services = Mock.Of(); + + Console.WriteLine(mock.ToString()); + } + + public void DoToo() + { + var other = Mock.Of(); + var sp = Mock.Of(); + } + } +}"; + + var (diagnostics, compilation) = GetGeneratedOutput(code); + + Assert.Empty(diagnostics); + + var assembly = compilation.Emit(); + + Assert.NotNull(assembly.GetType(MockNaming.GetFullName(typeof(IDisposable)))); + Assert.NotNull(assembly.GetType(MockNaming.GetFullName(typeof(IServiceProvider)))); + } + + [InlineData(typeof(IDisposable), typeof(IServiceProvider), typeof(IFormatProvider))] + [InlineData(typeof(ICollection), typeof(IDisposable))] + [InlineData(typeof(IDictionary, IReadOnlyList>), typeof(IDisposable))] + [InlineData(typeof(IDisposable))] + [Theory] + public void GenerateCode(params Type[] types) + { + var code = @" +using System; +using Moq; + +namespace UnitTests +{ + public class Test + { + public void Do() + { + var mock = Mock.Of<$$>(); + Console.WriteLine(mock.ToString()); + } + } +}".Replace("$$", string.Join(", ", types.Select(t => + t.GetFormattedName(TypeNameFormatOptions.Namespaces)))); + + var (diagnostics, compilation) = GetGeneratedOutput(code); + + Assert.Empty(diagnostics); + + var assembly = compilation.Emit(); + + var name = MockNaming.GetFullName(types.First(), types.Skip(1).ToArray()); + var type = assembly.GetType(name); + + Assert.NotNull(type); + + var stunt = Activator.CreateInstance(type!); + + foreach (var iface in types) + { + Assert.IsAssignableFrom(type, stunt); + } + } + + private static (ImmutableArray, Compilation) GetGeneratedOutput(string source, [CallerMemberName] string? test = null) + { + var syntaxTree = CSharpSyntaxTree.ParseText(source, path: test + ".cs"); + + var references = new List(); + // Force-load Moq.dll, Mock.Sdk and Stunts + Debug.WriteLine(MockBehavior.Default); + Debug.WriteLine(typeof(IMockBehavior)); + Debug.WriteLine(typeof(IStunt)); + + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach (var assembly in assemblies) + { + if (!assembly.IsDynamic && !string.IsNullOrEmpty(assembly.Location)) + references.Add(MetadataReference.CreateFromFile(assembly.Location)); + } + + var compilation = CSharpCompilation.Create(test, + new SyntaxTree[] + { + syntaxTree, + CSharpSyntaxTree.ParseText(File.ReadAllText("Moq/Mock.cs"), path: "Mock.cs"), + CSharpSyntaxTree.ParseText(File.ReadAllText("Moq/Mock.Overloads.cs"), path: "Mock.Overloads.cs"), + }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + + var diagnostics = compilation.GetDiagnostics().RemoveAll(d => d.Severity == DiagnosticSeverity.Hidden || d.Severity == DiagnosticSeverity.Info); + if (diagnostics.Any()) + return (diagnostics, compilation); + + ISourceGenerator generator = new MockSourceGenerator(); + + var driver = CSharpGeneratorDriver.Create(generator); + driver.RunGeneratorsAndUpdateCompilation(compilation, out var output, out diagnostics); + + return (diagnostics, output); + } + } +} diff --git a/src/Moq.StaticProxy/AnalyzerExtensions.cs b/src/Moq.StaticProxy/AnalyzerExtensions.cs new file mode 100644 index 00000000..2bdc5928 --- /dev/null +++ b/src/Moq.StaticProxy/AnalyzerExtensions.cs @@ -0,0 +1,24 @@ +using System.Diagnostics; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Moq +{ + internal static class AnalyzerExtensions + { + public static void CheckDebugger(this AnalyzerConfigOptionsProvider analyzerOptions, string debugableName) + { + if (analyzerOptions.GlobalOptions.TryGetValue("build_property.DebugSourceGenerators", out var debugValue) && + bool.TryParse(debugValue, out var shouldDebug) && + shouldDebug) + { + Debugger.Launch(); + } + else if (analyzerOptions.GlobalOptions.TryGetValue("build_property.Debug" + debugableName, out debugValue) && + bool.TryParse(debugValue, out shouldDebug) && + shouldDebug) + { + Debugger.Launch(); + } + } + } +} diff --git a/src/Moq/Moq.CodeFix/MockGenerator.cs b/src/Moq.StaticProxy/MockDocumentGenerator.cs similarity index 55% rename from src/Moq/Moq.CodeFix/MockGenerator.cs rename to src/Moq.StaticProxy/MockDocumentGenerator.cs index c26db199..18620cfb 100644 --- a/src/Moq/Moq.CodeFix/MockGenerator.cs +++ b/src/Moq.StaticProxy/MockDocumentGenerator.cs @@ -3,6 +3,7 @@ using Moq.Processors; using Moq.Sdk; using Stunts; +using Stunts.CodeAnalysis; using Stunts.Processors; namespace Moq @@ -11,23 +12,27 @@ namespace Moq /// Customizes the Stunts.Sdk /// with Moq-specific document processors. /// - class MockGenerator : StuntGenerator + internal class MockDocumentGenerator : StuntDocumentGenerator { - public MockGenerator() : this(new MockNamingConvention()) { } + public MockDocumentGenerator() : this(new MockNamingConvention()) { } - public MockGenerator(NamingConvention naming) + public MockDocumentGenerator(NamingConvention naming) : base(naming, new IDocumentProcessor[] { - new DefaultImports(typeof(LazyInitializer).Namespace, typeof(IMocked).Namespace), + new DefaultImports(typeof(LazyInitializer).Namespace!, typeof(IMocked).Namespace!), } - .Concat(GetDefaultProcessors().Where(p => !(p is FixupImports))) + .Concat(DefaultProcessors.Where(p => !(p is FixupImports))) .Concat(new IDocumentProcessor[] { new CSharpMocked(), new VisualBasicMocked(), new FixupImports(), + new CSharpFileHeader(), + new CSharpPragmas(), + new VisualBasicFileHeader(), }).ToArray()) { + GeneratorAttribute = typeof(MockGeneratorAttribute); } } } diff --git a/src/Moq.StaticProxy/MockSourceGenerator.cs b/src/Moq.StaticProxy/MockSourceGenerator.cs new file mode 100644 index 00000000..93ddf1e7 --- /dev/null +++ b/src/Moq.StaticProxy/MockSourceGenerator.cs @@ -0,0 +1,123 @@ +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Runtime.CompilerServices; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Moq.Sdk; +using Stunts; +using Stunts.CodeAnalysis; + +namespace Moq +{ + /// + /// Generates mocks by inspecting the current compilation for + /// invocations to methods annotated with [MockGenerator]. + /// + [Generator] + public class MockSourceGenerator : StuntSourceGenerator + { + protected override StuntDocumentGenerator DocumentGenerator => new MockDocumentGenerator(); + + [MethodImpl(MethodImplOptions.NoInlining)] + public override void Execute(GeneratorExecutionContext context) + { + context.AnalyzerConfigOptions.CheckDebugger(nameof(MockSourceGenerator)); + + if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.MoqAnalyzerDir", out var analyerDir)) + AddResolveDirectory(analyerDir); + + base.Execute(context); + } + + protected override void OnExecute(GeneratorExecutionContext context, StuntDocumentGenerator generator, IEnumerable candidates) + { + var additional = new List(); + + if (context.SyntaxReceiver is IEnumerable receivers && + receivers.OfType().FirstOrDefault() is var recursive) + { + var generatorAttr = context.Compilation.GetTypeByMetadataName(generator.GeneratorAttribute.FullName!); + var moqmodule = context.Compilation.GetTypeByMetadataName("Moq.IMoq")!.ContainingModule; + var sdkmodule = context.Compilation.GetTypeByMetadataName(typeof(IMock).FullName!)!.ContainingModule; + + // If we can't know what's the attribute that annotates mock generators, we can't do anything. + if (generatorAttr != null) + { + foreach (var node in recursive.CandidateNodes) + { + var semantic = context.Compilation.GetSemanticModel(node.SyntaxTree); + if (semantic == null) + break; + + var flow = semantic.AnalyzeDataFlow(node); + + // There are two possible flows: + // mock.Prop.Method().Returns(...): this is recursive "normal" flow In + // mock.Setup(x => x.Prop.Method()).Returns(...): + // this is a recursive "read outside" flow: the flow into the recursive expression + // is actually the lambda parameter, not useful. But the "read outside" is the actual + // mock variable where the Setup is being performed, which is what we need. + bool IsMockFlow(ImmutableArray data) => + data.Length == 1 && + data[0].DeclaringSyntaxReferences.Length == 1 && + data[0].DeclaringSyntaxReferences[0].GetSyntax(context.CancellationToken) is VariableDeclaratorSyntax variable && + variable.Initializer?.Value is InvocationExpressionSyntax create && + semantic!.GetSymbolInfo(create, context.CancellationToken).Symbol is IMethodSymbol method && + method.GetAttributes().Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, generatorAttr)); + + // Detect if the variable being accessed was initialized from a generator method call + if (!IsMockFlow(flow.DataFlowsIn) && !IsMockFlow(flow.ReadOutside)) + continue; + + var symbol = semantic.GetSymbolInfo(node); + // TODO: see if we need to consider symbol.CandidateSymbols too + if (symbol.Symbol == null || + SymbolEqualityComparer.Default.Equals(symbol.Symbol.ContainingModule, moqmodule) || + SymbolEqualityComparer.Default.Equals(symbol.Symbol.ContainingModule, sdkmodule)) + continue; + + // We only process recursive property and method accesses + if (symbol.Symbol.Kind != SymbolKind.Property && + symbol.Symbol.Kind != SymbolKind.Method) + continue; + + var methodSymbol = symbol.Symbol as IMethodSymbol; + var propertySymbol = symbol.Symbol as IPropertySymbol; + + // Extension methods are not considered for mocking + if (methodSymbol?.IsExtensionMethod == true || + // void methods can't result in a recursive mock either + methodSymbol?.ReturnsVoid == true) + continue; + + var type = (methodSymbol?.ReturnType ?? propertySymbol?.Type) as INamedTypeSymbol; + if (type != null && type.CanBeIntercepted() == false) + continue; + + additional.Add(new[] { type! }); + } + } + } + + // TODO: concat the symbols for recursive mocks + base.OnExecute(context, generator, candidates.Concat(additional)); + } + + protected override IEnumerable CreateSyntaxReceivers() + => base.CreateSyntaxReceivers().Concat(new[] { new RecursiveMockSyntaxReceiver() }); + + class RecursiveMockSyntaxReceiver : ISyntaxReceiver + { + public List CandidateNodes { get; } = new(); + + public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + { + if (syntaxNode.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.SimpleMemberAccessExpression) || + syntaxNode.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.InvocationExpression)) + CandidateNodes.Add(syntaxNode); + } + } + } +} \ No newline at end of file diff --git a/src/Moq.StaticProxy/Moq.StaticProxy.csproj b/src/Moq.StaticProxy/Moq.StaticProxy.csproj new file mode 100644 index 00000000..4b6177fe --- /dev/null +++ b/src/Moq.StaticProxy/Moq.StaticProxy.csproj @@ -0,0 +1,45 @@ + + + + netstandard2.0 + Moq + true + true + true + tools\$(TargetFramework) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Moq/Moq.CodeFix/Processors/CSharpMocked.cs b/src/Moq.StaticProxy/Processors/CSharpMocked.cs similarity index 95% rename from src/Moq/Moq.CodeFix/Processors/CSharpMocked.cs rename to src/Moq.StaticProxy/Processors/CSharpMocked.cs index 7ce2c309..793320f9 100644 --- a/src/Moq/Moq.CodeFix/Processors/CSharpMocked.cs +++ b/src/Moq.StaticProxy/Processors/CSharpMocked.cs @@ -14,7 +14,7 @@ namespace Moq.Processors /// /// Generates the C# implementation of the mock interfaces. /// - class CSharpMocked : IDocumentProcessor + internal class CSharpMocked : IDocumentProcessor { public string[] Languages { get; } = new[] { LanguageNames.CSharp }; @@ -25,18 +25,21 @@ public async Task ProcessAsync(Document document, CancellationToken ca var syntax = await document.GetSyntaxRootAsync(cancellationToken); syntax = new CSharpRewriteVisitor(SyntaxGenerator.GetGenerator(document)).Visit(syntax); + if (syntax == null) + return document; + return document.WithSyntaxRoot(syntax); } - class CSharpRewriteVisitor : CSharpSyntaxRewriter + private class CSharpRewriteVisitor : CSharpSyntaxRewriter { - SyntaxGenerator generator; + private readonly SyntaxGenerator generator; public CSharpRewriteVisitor(SyntaxGenerator generator) => this.generator = generator; public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) { - node = (ClassDeclarationSyntax)base.VisitClassDeclaration(node); + node = (ClassDeclarationSyntax)base.VisitClassDeclaration(node)!; if (!generator.GetBaseAndInterfaceTypes(node).Any(x => x.ToString() == nameof(IMocked) || diff --git a/src/Moq/Moq.CodeFix/Processors/VisualBasicMocked.cs b/src/Moq.StaticProxy/Processors/VisualBasicMocked.cs similarity index 96% rename from src/Moq/Moq.CodeFix/Processors/VisualBasicMocked.cs rename to src/Moq.StaticProxy/Processors/VisualBasicMocked.cs index 04ba8cf2..c30ec87b 100644 --- a/src/Moq/Moq.CodeFix/Processors/VisualBasicMocked.cs +++ b/src/Moq.StaticProxy/Processors/VisualBasicMocked.cs @@ -15,7 +15,7 @@ namespace Moq.Processors /// /// Generates the VB implementation of the mock interfaces. /// - class VisualBasicMocked : IDocumentProcessor + internal class VisualBasicMocked : IDocumentProcessor { public string[] Languages { get; } = new[] { LanguageNames.VisualBasic }; @@ -29,9 +29,9 @@ public async Task ProcessAsync(Document document, CancellationToken ca return document.WithSyntaxRoot(syntax); } - class VisualBasicRewriteVisitor : VisualBasicSyntaxRewriter + private class VisualBasicRewriteVisitor : VisualBasicSyntaxRewriter { - SyntaxGenerator generator; + private readonly SyntaxGenerator generator; public VisualBasicRewriteVisitor(SyntaxGenerator generator) => this.generator = generator; diff --git a/src/Moq/Moq.Tests.Basic/App.config b/src/Moq.Tests.Basic/App.config similarity index 100% rename from src/Moq/Moq.Tests.Basic/App.config rename to src/Moq.Tests.Basic/App.config diff --git a/src/Moq/Moq.Tests.Basic/Moq.Tests.Basic.vbproj b/src/Moq.Tests.Basic/Moq.Tests.Basic.vbproj similarity index 100% rename from src/Moq/Moq.Tests.Basic/Moq.Tests.Basic.vbproj rename to src/Moq.Tests.Basic/Moq.Tests.Basic.vbproj diff --git a/src/Moq/Moq.Tests.Basic/Tests.vb b/src/Moq.Tests.Basic/Tests.vb similarity index 100% rename from src/Moq/Moq.Tests.Basic/Tests.vb rename to src/Moq.Tests.Basic/Tests.vb diff --git a/src/Moq/Moq.Tests/CallBaseTests.cs b/src/Moq.Tests/CallBaseTests.cs similarity index 100% rename from src/Moq/Moq.Tests/CallBaseTests.cs rename to src/Moq.Tests/CallBaseTests.cs diff --git a/src/Moq/Moq.Tests/DelegateMocksTests.cs b/src/Moq.Tests/DelegateMocksTests.cs similarity index 100% rename from src/Moq/Moq.Tests/DelegateMocksTests.cs rename to src/Moq.Tests/DelegateMocksTests.cs diff --git a/src/Moq/Moq.Tests/LegacyTests.cs b/src/Moq.Tests/LegacyTests.cs similarity index 100% rename from src/Moq/Moq.Tests/LegacyTests.cs rename to src/Moq.Tests/LegacyTests.cs diff --git a/src/Moq/Moq.Tests/Mocks/CalculatorMock.cs b/src/Moq.Tests/Mocks/CalculatorMock.cs similarity index 100% rename from src/Moq/Moq.Tests/Mocks/CalculatorMock.cs rename to src/Moq.Tests/Mocks/CalculatorMock.cs diff --git a/src/Moq/Moq.Tests/Mocks/ICalculatorMemoryMock.cs b/src/Moq.Tests/Mocks/ICalculatorMemoryMock.cs similarity index 100% rename from src/Moq/Moq.Tests/Mocks/ICalculatorMemoryMock.cs rename to src/Moq.Tests/Mocks/ICalculatorMemoryMock.cs diff --git a/src/Moq/Moq.Tests/Mocks/ICalculatorMock.cs b/src/Moq.Tests/Mocks/ICalculatorMock.cs similarity index 100% rename from src/Moq/Moq.Tests/Mocks/ICalculatorMock.cs rename to src/Moq.Tests/Mocks/ICalculatorMock.cs diff --git a/src/Moq/Moq.Tests/Mocks/INotifyPropertyChangedMock.cs b/src/Moq.Tests/Mocks/INotifyPropertyChangedMock.cs similarity index 100% rename from src/Moq/Moq.Tests/Mocks/INotifyPropertyChangedMock.cs rename to src/Moq.Tests/Mocks/INotifyPropertyChangedMock.cs diff --git a/src/Moq/Moq.Tests/Mocks/IRecursiveBranchMock.cs b/src/Moq.Tests/Mocks/IRecursiveBranchMock.cs similarity index 100% rename from src/Moq/Moq.Tests/Mocks/IRecursiveBranchMock.cs rename to src/Moq.Tests/Mocks/IRecursiveBranchMock.cs diff --git a/src/Moq/Moq.Tests/Mocks/IRecursiveLeafMock.cs b/src/Moq.Tests/Mocks/IRecursiveLeafMock.cs similarity index 100% rename from src/Moq/Moq.Tests/Mocks/IRecursiveLeafMock.cs rename to src/Moq.Tests/Mocks/IRecursiveLeafMock.cs diff --git a/src/Moq/Moq.Tests/Mocks/IRecursiveRootMock.cs b/src/Moq.Tests/Mocks/IRecursiveRootMock.cs similarity index 100% rename from src/Moq/Moq.Tests/Mocks/IRecursiveRootMock.cs rename to src/Moq.Tests/Mocks/IRecursiveRootMock.cs diff --git a/src/Moq/Moq.Tests/Mocks/IRefOutMock.cs b/src/Moq.Tests/Mocks/IRefOutMock.cs similarity index 100% rename from src/Moq/Moq.Tests/Mocks/IRefOutMock.cs rename to src/Moq.Tests/Mocks/IRefOutMock.cs diff --git a/src/Moq/Moq.Tests/Mocks/IRefOutParentMock.cs b/src/Moq.Tests/Mocks/IRefOutParentMock.cs similarity index 100% rename from src/Moq/Moq.Tests/Mocks/IRefOutParentMock.cs rename to src/Moq.Tests/Mocks/IRefOutParentMock.cs diff --git a/src/Moq.Tests/Moq.Tests.csproj b/src/Moq.Tests/Moq.Tests.csproj new file mode 100644 index 00000000..78e47b8a --- /dev/null +++ b/src/Moq.Tests/Moq.Tests.csproj @@ -0,0 +1,45 @@ + + + + net472;net5.0 + annotations + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Moq/Moq.Tests/MoqTests.cs b/src/Moq.Tests/MoqTests.cs similarity index 99% rename from src/Moq/Moq.Tests/MoqTests.cs rename to src/Moq.Tests/MoqTests.cs index cad4c172..ba9f1c32 100644 --- a/src/Moq/Moq.Tests/MoqTests.cs +++ b/src/Moq.Tests/MoqTests.cs @@ -11,7 +11,7 @@ namespace Moq.Tests { public class MoqTests { - ITestOutputHelper output; + private readonly ITestOutputHelper output; public MoqTests(ITestOutputHelper output) { diff --git a/src/Moq/Moq.Tests/RecursiveMocksTests.cs b/src/Moq.Tests/RecursiveMocksTests.cs similarity index 100% rename from src/Moq/Moq.Tests/RecursiveMocksTests.cs rename to src/Moq.Tests/RecursiveMocksTests.cs diff --git a/src/Moq/Moq.Tests/RefOutTests.cs b/src/Moq.Tests/RefOutTests.cs similarity index 91% rename from src/Moq/Moq.Tests/RefOutTests.cs rename to src/Moq.Tests/RefOutTests.cs index 5d6d9cd0..ac606e6d 100644 --- a/src/Moq/Moq.Tests/RefOutTests.cs +++ b/src/Moq.Tests/RefOutTests.cs @@ -1,5 +1,4 @@ using System; -using Moq.Sdk; using Sample; using Xunit; using Xunit.Abstractions; @@ -8,7 +7,7 @@ namespace Moq.Tests.RefOut { public class RefOutTests { - ITestOutputHelper output; + private readonly ITestOutputHelper output; public RefOutTests(ITestOutputHelper output) { @@ -82,9 +81,9 @@ public void CanSetTypedOutInRecursiveMock() Assert.Equal(expected, actual); } - delegate bool TryParse(string input, out DateTimeOffset date); + private delegate bool TryParse(string input, out DateTimeOffset date); - delegate bool TryAdd(ref int x, ref int y, out int z); + private delegate bool TryAdd(ref int x, ref int y, out int z); } public interface IRefOutParent diff --git a/src/Moq/Moq.Tests/VerificationTests.cs b/src/Moq.Tests/VerificationTests.cs similarity index 99% rename from src/Moq/Moq.Tests/VerificationTests.cs rename to src/Moq.Tests/VerificationTests.cs index 42292a85..472ddcf6 100644 --- a/src/Moq/Moq.Tests/VerificationTests.cs +++ b/src/Moq.Tests/VerificationTests.cs @@ -8,7 +8,7 @@ namespace Moq.Tests { public class VerificationTests { - readonly ITestOutputHelper output; + private readonly ITestOutputHelper output; public VerificationTests(ITestOutputHelper output) { diff --git a/src/Moq.sln b/src/Moq.sln deleted file mode 100644 index d6a3fa98..00000000 --- a/src/Moq.sln +++ /dev/null @@ -1,122 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28417.167 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq", "Moq\Moq\Moq.csproj", "{65F3AB28-9A74-405E-83B2-420D5AD5A459}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2093478C-CEA6-4034-BCDE-EDC7A5DD4532}" - ProjectSection(SolutionItems) = preProject - ..\.editorconfig = ..\.editorconfig - ..\azure-pipelines.yml = ..\azure-pipelines.yml - ..\build.proj = ..\build.proj - ..\CODE_OF_CONDUCT.md = ..\CODE_OF_CONDUCT.md - Directory.Build.props = Directory.Build.props - Directory.Build.targets = Directory.Build.targets - GitInfo.txt = GitInfo.txt - ..\global.json = ..\global.json - ..\NuGet.Config = ..\NuGet.Config - Packages.props = Packages.props - ..\README.md = ..\README.md - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stunts", "Stunts\Stunts\Stunts.csproj", "{AE46AE30-8002-4F2C-B368-44546B1D71D8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.Sdk", "Moq\Moq.Sdk\Moq.Sdk.csproj", "{80DE507E-3AF9-4360-9E56-66523B01FB51}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stunts", "Stunts", "{EEC3EC48-ACB2-4D25-B592-F360F676BE45}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.Sdk.Tests", "Moq\Moq.Sdk.Tests\Moq.Sdk.Tests.csproj", "{EB66BC5E-4072-4F26-9772-979D8561883F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample", "Samples\Sample\Sample.csproj", "{03D94BF7-F2BA-476D-BDBA-9E49048D7F03}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.Tests", "Moq\Moq.Tests\Moq.Tests.csproj", "{9A09225F-E0BC-4890-BED4-D9F6F5DAC146}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{1DBDFC27-21EC-4EAC-B51B-84EDC8DBB9D5}" - ProjectSection(SolutionItems) = preProject - build\PackageReference.CopyLocal.targets = build\PackageReference.CopyLocal.targets - build\PackageReferences.targets = build\PackageReferences.targets - build\Packaging.props = build\Packaging.props - build\Packaging.targets = build\Packaging.targets - build\Settings.props = build\Settings.props - build\Settings.targets = build\Settings.targets - build\Settings.Tests.props = build\Settings.Tests.props - build\Settings.Tests.targets = build\Settings.Tests.targets - build\Version.targets = build\Version.targets - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stunts.Tests", "Stunts\Stunts.Tests\Stunts.Tests.csproj", "{EDBDA217-CA42-4C82-826F-7D990185EC0F}" -EndProject -Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "Stunts.Package", "Stunts\Stunts.Package\Stunts.Package.msbuildproj", "{336A513F-BEC7-44EE-A720-F61E3A65410F}" -EndProject -Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "Moq.Package", "Moq\Moq.Package\Moq.Package.msbuildproj", "{09C65B0B-9206-4682-9837-6B98936553C1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stunts.DynamicProxy", "Stunts\Stunts.DynamicProxy\Stunts.DynamicProxy.csproj", "{2FC48D20-CB36-4606-A9DC-22981DD13A3D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.DynamicProxy", "Moq\Moq.DynamicProxy\Moq.DynamicProxy.csproj", "{BA43EF2F-6CA8-49A5-A4E7-C2FF71928F05}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {65F3AB28-9A74-405E-83B2-420D5AD5A459}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {65F3AB28-9A74-405E-83B2-420D5AD5A459}.Debug|Any CPU.Build.0 = Debug|Any CPU - {65F3AB28-9A74-405E-83B2-420D5AD5A459}.Release|Any CPU.ActiveCfg = Release|Any CPU - {65F3AB28-9A74-405E-83B2-420D5AD5A459}.Release|Any CPU.Build.0 = Release|Any CPU - {AE46AE30-8002-4F2C-B368-44546B1D71D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AE46AE30-8002-4F2C-B368-44546B1D71D8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AE46AE30-8002-4F2C-B368-44546B1D71D8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AE46AE30-8002-4F2C-B368-44546B1D71D8}.Release|Any CPU.Build.0 = Release|Any CPU - {80DE507E-3AF9-4360-9E56-66523B01FB51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {80DE507E-3AF9-4360-9E56-66523B01FB51}.Debug|Any CPU.Build.0 = Debug|Any CPU - {80DE507E-3AF9-4360-9E56-66523B01FB51}.Release|Any CPU.ActiveCfg = Release|Any CPU - {80DE507E-3AF9-4360-9E56-66523B01FB51}.Release|Any CPU.Build.0 = Release|Any CPU - {EB66BC5E-4072-4F26-9772-979D8561883F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EB66BC5E-4072-4F26-9772-979D8561883F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EB66BC5E-4072-4F26-9772-979D8561883F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EB66BC5E-4072-4F26-9772-979D8561883F}.Release|Any CPU.Build.0 = Release|Any CPU - {03D94BF7-F2BA-476D-BDBA-9E49048D7F03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {03D94BF7-F2BA-476D-BDBA-9E49048D7F03}.Debug|Any CPU.Build.0 = Debug|Any CPU - {03D94BF7-F2BA-476D-BDBA-9E49048D7F03}.Release|Any CPU.ActiveCfg = Release|Any CPU - {03D94BF7-F2BA-476D-BDBA-9E49048D7F03}.Release|Any CPU.Build.0 = Release|Any CPU - {9A09225F-E0BC-4890-BED4-D9F6F5DAC146}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9A09225F-E0BC-4890-BED4-D9F6F5DAC146}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9A09225F-E0BC-4890-BED4-D9F6F5DAC146}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9A09225F-E0BC-4890-BED4-D9F6F5DAC146}.Release|Any CPU.Build.0 = Release|Any CPU - {EDBDA217-CA42-4C82-826F-7D990185EC0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EDBDA217-CA42-4C82-826F-7D990185EC0F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EDBDA217-CA42-4C82-826F-7D990185EC0F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EDBDA217-CA42-4C82-826F-7D990185EC0F}.Release|Any CPU.Build.0 = Release|Any CPU - {336A513F-BEC7-44EE-A720-F61E3A65410F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {336A513F-BEC7-44EE-A720-F61E3A65410F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {336A513F-BEC7-44EE-A720-F61E3A65410F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {336A513F-BEC7-44EE-A720-F61E3A65410F}.Release|Any CPU.Build.0 = Release|Any CPU - {09C65B0B-9206-4682-9837-6B98936553C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {09C65B0B-9206-4682-9837-6B98936553C1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {09C65B0B-9206-4682-9837-6B98936553C1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {09C65B0B-9206-4682-9837-6B98936553C1}.Release|Any CPU.Build.0 = Release|Any CPU - {2FC48D20-CB36-4606-A9DC-22981DD13A3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2FC48D20-CB36-4606-A9DC-22981DD13A3D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2FC48D20-CB36-4606-A9DC-22981DD13A3D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2FC48D20-CB36-4606-A9DC-22981DD13A3D}.Release|Any CPU.Build.0 = Release|Any CPU - {BA43EF2F-6CA8-49A5-A4E7-C2FF71928F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BA43EF2F-6CA8-49A5-A4E7-C2FF71928F05}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BA43EF2F-6CA8-49A5-A4E7-C2FF71928F05}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BA43EF2F-6CA8-49A5-A4E7-C2FF71928F05}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {AE46AE30-8002-4F2C-B368-44546B1D71D8} = {EEC3EC48-ACB2-4D25-B592-F360F676BE45} - {1DBDFC27-21EC-4EAC-B51B-84EDC8DBB9D5} = {2093478C-CEA6-4034-BCDE-EDC7A5DD4532} - {EDBDA217-CA42-4C82-826F-7D990185EC0F} = {EEC3EC48-ACB2-4D25-B592-F360F676BE45} - {336A513F-BEC7-44EE-A720-F61E3A65410F} = {EEC3EC48-ACB2-4D25-B592-F360F676BE45} - {2FC48D20-CB36-4606-A9DC-22981DD13A3D} = {EEC3EC48-ACB2-4D25-B592-F360F676BE45} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {DA4CFD03-827D-482B-9304-83456D2A8115} - EndGlobalSection -EndGlobal diff --git a/src/Moq.snk b/src/Moq.snk new file mode 100644 index 00000000..8e181aea Binary files /dev/null and b/src/Moq.snk differ diff --git a/src/Moq/Moq/Arg.cs b/src/Moq/Arg.cs similarity index 82% rename from src/Moq/Moq/Arg.cs rename to src/Moq/Arg.cs index 92f6046c..7c656164 100644 --- a/src/Moq/Moq/Arg.cs +++ b/src/Moq/Arg.cs @@ -19,13 +19,13 @@ public static class Arg /// /// The type of the argument. /// The condition to check against actual invocation values. - public static T Any(Func condition) => MockSetup.Push(new ConditionalMatcher(condition)); + public static T Any(Func condition) => MockSetup.Push(new ConditionalMatcher(condition)); /// /// Matches any value that is not equal to the provided constant value. /// /// The type of the argument. - public static T Not(T value) => MockSetup.Push(new NotMatcher(value)); + public static T Not(T? value) => MockSetup.Push(new NotMatcher(value)); } /// @@ -42,6 +42,6 @@ public static class Arg /// /// Matches any value that is not equal to the provided constant value. /// - public static T Not(T value) => MockSetup.Push(new NotMatcher(value)); + public static T Not(T? value) => MockSetup.Push(new NotMatcher(value)); } } \ No newline at end of file diff --git a/src/Moq/Moq/CallBaseBehavior.cs b/src/Moq/CallBaseBehavior.cs similarity index 100% rename from src/Moq/Moq/CallBaseBehavior.cs rename to src/Moq/CallBaseBehavior.cs diff --git a/src/Moq/Moq/CallBaseExtension.cs b/src/Moq/CallBaseExtension.cs similarity index 60% rename from src/Moq/Moq/CallBaseExtension.cs rename to src/Moq/CallBaseExtension.cs index bf1c8141..e2cd8a7d 100644 --- a/src/Moq/Moq/CallBaseExtension.cs +++ b/src/Moq/CallBaseExtension.cs @@ -22,14 +22,16 @@ public static T CallBase(this T target) else if (MockContext.CurrentInvocation != null) { // Configure CallBase at the invocation level - MockContext.CurrentInvocation.Target.AsMock().GetPipeline(MockContext.CurrentSetup).Behaviors.Add(new DelegateMockBehavior( - (m, i, next) => - { - // set CallBase - i.Context[nameof(IMoq.CallBase)] = true; - return next().Invoke(i.Target.AsMock(), i, next); - }, - nameof(IMoq.CallBase))); + MockContext.CurrentInvocation.Target.AsMock() + .GetPipeline(MockContext.CurrentSetup ?? CallContext.ThrowUnexpectedNull()) + .Behaviors.Add(new DelegateMockBehavior( + (m, i, next) => + { + // set CallBase + i.Context[nameof(IMoq.CallBase)] = true; + return next().Invoke(i.Target.AsMock(), i, next); + }, + nameof(IMoq.CallBase))); } // TODO: else throw? diff --git a/src/Moq/Moq/CallbackExtension.Overloads.cs b/src/Moq/CallbackExtension.Overloads.cs similarity index 96% rename from src/Moq/Moq/CallbackExtension.Overloads.cs rename to src/Moq/CallbackExtension.Overloads.cs index be1267a1..bb1950d3 100644 --- a/src/Moq/Moq/CallbackExtension.Overloads.cs +++ b/src/Moq/CallbackExtension.Overloads.cs @@ -1,8 +1,12 @@ -using System; +#nullable disable +// Disable nullable since this works from the Arguments collection which we know can have nulls +// A NRE here would be a mis-configuration from the user, which the compiler would have caught +// already in the test setups anyway. +using System; namespace Moq { - partial class CallbackExtension + public partial class CallbackExtension { /// /// Specifies a callback to invoke when the method is called. diff --git a/src/Moq/Moq/CallbackExtension.cs b/src/Moq/CallbackExtension.cs similarity index 96% rename from src/Moq/Moq/CallbackExtension.cs rename to src/Moq/CallbackExtension.cs index 8fc49261..7d2edd49 100644 --- a/src/Moq/Moq/CallbackExtension.cs +++ b/src/Moq/CallbackExtension.cs @@ -11,7 +11,7 @@ namespace Moq [EditorBrowsable(EditorBrowsableState.Never)] public static partial class CallbackExtension { - static TResult Callback(this TResult target, Action callback) + private static TResult Callback(this TResult target, Action callback) { var setup = MockContext.CurrentSetup; if (setup != null) diff --git a/src/Moq/Moq/ConfigurePipelineBehavior.cs b/src/Moq/ConfigurePipelineBehavior.cs similarity index 89% rename from src/Moq/Moq/ConfigurePipelineBehavior.cs rename to src/Moq/ConfigurePipelineBehavior.cs index 8ec50a6f..e9a32986 100644 --- a/src/Moq/Moq/ConfigurePipelineBehavior.cs +++ b/src/Moq/ConfigurePipelineBehavior.cs @@ -32,7 +32,8 @@ public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) // We need this to skip the StrictBehavior in the CallBaseBehavior if (SetupScope.IsActive) { - invocation.Target.AsMock().GetPipeline(MockContext.CurrentSetup); + invocation.Target.AsMock() + .GetPipeline(MockContext.CurrentSetup ?? CallContext.ThrowUnexpectedNull()); } return next().Invoke(invocation, next); diff --git a/src/Moq/Moq/Extensions.cs b/src/Moq/Extensions.cs similarity index 73% rename from src/Moq/Moq/Extensions.cs rename to src/Moq/Extensions.cs index 1e56cdf5..eee3e1cc 100644 --- a/src/Moq/Moq/Extensions.cs +++ b/src/Moq/Extensions.cs @@ -5,9 +5,9 @@ namespace Moq { - static class Extensions + internal static class Extensions { - const string TaskFullName = "System.Threading.Tasks.Task"; + private const string TaskFullName = "System.Threading.Tasks.Task"; public static void EnsureCompatible(this IMethodInvocation invocation, Delegate @delegate) { @@ -19,10 +19,10 @@ public static void EnsureCompatible(this IMethodInvocation invocation, Delegate } public static bool CanBeIntercepted(this Type type) - => !type.GetTypeInfo().IsValueType && + => !type.IsValueType && !type.FullName.StartsWith(TaskFullName, StringComparison.Ordinal) && - (type.GetTypeInfo().IsInterface || - (type.GetTypeInfo().IsClass && !type.GetTypeInfo().IsSealed)); + (type.IsInterface || + (type.IsClass && !type.IsSealed)); public static IMoq AsMoq(this T instance) where T : class => new Moq(instance.AsMock()); } diff --git a/src/Moq/Moq.CodeFix/GlobalSuppressions.cs b/src/Moq/GlobalSuppressions.cs similarity index 100% rename from src/Moq/Moq.CodeFix/GlobalSuppressions.cs rename to src/Moq/GlobalSuppressions.cs diff --git a/src/Moq/Moq/IMoq.cs b/src/Moq/IMoq.cs similarity index 98% rename from src/Moq/Moq/IMoq.cs rename to src/Moq/IMoq.cs index 2ae3bf34..974254f9 100644 --- a/src/Moq/Moq/IMoq.cs +++ b/src/Moq/IMoq.cs @@ -1,4 +1,5 @@ using Moq.Sdk; +using Stunts; namespace Moq { diff --git a/src/Moq/Moq/IMoq`1.cs b/src/Moq/IMoq`1.cs similarity index 100% rename from src/Moq/Moq/IMoq`1.cs rename to src/Moq/IMoq`1.cs diff --git a/src/Moq/Moq/ISetup.cs b/src/Moq/ISetup.cs similarity index 100% rename from src/Moq/Moq/ISetup.cs rename to src/Moq/ISetup.cs diff --git a/src/Moq/Moq/Legacy/It.cs b/src/Moq/Legacy/It.cs similarity index 63% rename from src/Moq/Moq/Legacy/It.cs rename to src/Moq/Legacy/It.cs index f78f3790..1dc726c0 100644 --- a/src/Moq/Moq/Legacy/It.cs +++ b/src/Moq/Legacy/It.cs @@ -1,5 +1,4 @@ -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member -using System; +using System; using System.ComponentModel; using static Moq.Syntax; @@ -15,7 +14,6 @@ public static class It /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] - public static T Is(Func condition) => Any(condition); + public static T Is(Func condition) => Any(condition); } -} -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member \ No newline at end of file +} \ No newline at end of file diff --git a/src/Moq/Moq/Legacy/MockSetup`1.cs b/src/Moq/Legacy/MockSetup`1.cs similarity index 95% rename from src/Moq/Moq/Legacy/MockSetup`1.cs rename to src/Moq/Legacy/MockSetup`1.cs index 8c86e81a..95b6dea9 100644 --- a/src/Moq/Moq/Legacy/MockSetup`1.cs +++ b/src/Moq/Legacy/MockSetup`1.cs @@ -1,5 +1,4 @@ -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member -using System; +using System; using System.ComponentModel; using Moq.Sdk; @@ -9,9 +8,9 @@ namespace Moq [EditorBrowsable(EditorBrowsableState.Never)] public class MockSetup where TTarget : class { - readonly TTarget target; - readonly IMock mock; - readonly Action action; + private readonly TTarget target; + private readonly IMock mock; + private readonly Action action; /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] @@ -175,5 +174,4 @@ public MockSetup Throws(Exception exception) return this; } } -} -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member \ No newline at end of file +} \ No newline at end of file diff --git a/src/Moq/Moq/Legacy/MockSetup`2.cs b/src/Moq/Legacy/MockSetup`2.cs similarity index 97% rename from src/Moq/Moq/Legacy/MockSetup`2.cs rename to src/Moq/Legacy/MockSetup`2.cs index 2f201bee..cdc56c57 100644 --- a/src/Moq/Moq/Legacy/MockSetup`2.cs +++ b/src/Moq/Legacy/MockSetup`2.cs @@ -1,5 +1,4 @@ -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member -using System; +using System; using System.ComponentModel; using Moq.Sdk; @@ -9,9 +8,9 @@ namespace Moq [EditorBrowsable(EditorBrowsableState.Never)] public class MockSetup where TTarget : class { - readonly TTarget target; - readonly IMock mock; - readonly Func function; + private readonly TTarget target; + private readonly IMock mock; + private readonly Func function; /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] @@ -319,9 +318,8 @@ public MockSetup Returns(TResult value) [EditorBrowsable(EditorBrowsableState.Never)] public MockSetup Throws(Exception exception) { - target.Setup(function).Throws(exception); + target.Setup(function)!.Throws(exception); return this; } } -} -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member \ No newline at end of file +} \ No newline at end of file diff --git a/src/Moq/Moq/Legacy/Mock`1.Overloads.cs b/src/Moq/Legacy/Mock`1.Overloads.cs similarity index 97% rename from src/Moq/Moq/Legacy/Mock`1.Overloads.cs rename to src/Moq/Legacy/Mock`1.Overloads.cs index b0f6a105..ca7a5b52 100644 --- a/src/Moq/Moq/Legacy/Mock`1.Overloads.cs +++ b/src/Moq/Legacy/Mock`1.Overloads.cs @@ -1,5 +1,4 @@ -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member -using System.ComponentModel; +using System.ComponentModel; using System.Reflection; namespace Moq @@ -163,5 +162,4 @@ public Mock(params object[] args) : base(Assembly.GetCallingAssembly(), MockBeha [MockGenerator] public Mock(MockBehavior behavior, params object[] args) : base(Assembly.GetCallingAssembly(), behavior, args) { } } -} -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member \ No newline at end of file +} \ No newline at end of file diff --git a/src/Moq/Moq/Legacy/Mock`1.cs b/src/Moq/Legacy/Mock`1.cs similarity index 89% rename from src/Moq/Moq/Legacy/Mock`1.cs rename to src/Moq/Legacy/Mock`1.cs index 47bcf5d9..21696f49 100644 --- a/src/Moq/Moq/Legacy/Mock`1.cs +++ b/src/Moq/Legacy/Mock`1.cs @@ -14,13 +14,13 @@ public class Mock where T : class { static Mock() { - if (MockFactory.Default == null) + if (MockFactory.Default == MockFactory.NotImplemented) MockFactory.Default = new DynamicMockFactory(); } - T target; - IMock mock; - readonly MockBehavior behavior; + private readonly T target; + private readonly IMock mock; + private readonly MockBehavior behavior; /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] @@ -55,7 +55,7 @@ protected Mock(Assembly mocksAssembly, MockBehavior behavior, params object[] ar mock = target.AsMock(); } - Mock(T target, IMock mock, MockBehavior behavior) + private Mock(T target, IMock mock, MockBehavior behavior) { this.target = target; this.mock = mock; @@ -77,7 +77,12 @@ public bool CallBase /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] public Mock As() where TInterface : class - => new Mock(target as TInterface, (target as TInterface)?.AsMock(), behavior); + { + if (target is not TInterface iface) + throw new InvalidOperationException(ThisAssembly.Strings.Legacy.AsInterfaceNotImplemented); + + return new Mock(iface, iface.AsMock(), behavior); + } /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] @@ -122,12 +127,12 @@ public void Verify(Expression> expression) /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] - public void Verify(Expression> expression, Times times, string message = null) + public void Verify(Expression> expression, Times times, string? message = null) => Moq.Verify.CalledImpl(() => expression.Compile().Invoke(target), times.ToSdk(), message); /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] - public void Verify(Expression> expression, Func times, string message = null) + public void Verify(Expression> expression, Func times, string? message = null) => Moq.Verify.CalledImpl(() => expression.Compile().Invoke(target), times().ToSdk(), message); /// Supports the legacy API. @@ -137,12 +142,12 @@ public void Verify(Expression> expression) /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] - public void Verify(Expression> expression, Times times, string message = null) + public void Verify(Expression> expression, Times times, string? message = null) => Moq.Verify.CalledImpl(() => expression.Compile().Invoke(target), times.ToSdk(), message); /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] - public void Verify(Expression> expression, Func times, string message = null) + public void Verify(Expression> expression, Func times, string? message = null) => Moq.Verify.CalledImpl(() => expression.Compile().Invoke(target), times().ToSdk(), message); } } diff --git a/src/Moq/Moq/Legacy/Range.cs b/src/Moq/Legacy/Range.cs similarity index 65% rename from src/Moq/Moq/Legacy/Range.cs rename to src/Moq/Legacy/Range.cs index 04536a22..89e1285f 100644 --- a/src/Moq/Moq/Legacy/Range.cs +++ b/src/Moq/Legacy/Range.cs @@ -1,5 +1,4 @@ -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member -using System.ComponentModel; +using System.ComponentModel; namespace Moq { @@ -15,5 +14,4 @@ public enum Range [EditorBrowsable(EditorBrowsableState.Never)] Exclusive } -} -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member \ No newline at end of file +} \ No newline at end of file diff --git a/src/Moq/Moq/Legacy/Times.cs b/src/Moq/Legacy/Times.cs similarity index 94% rename from src/Moq/Moq/Legacy/Times.cs rename to src/Moq/Legacy/Times.cs index d1b7e7ab..4ead9a2f 100644 --- a/src/Moq/Moq/Legacy/Times.cs +++ b/src/Moq/Legacy/Times.cs @@ -1,5 +1,4 @@ -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member -using System; +using System; using System.ComponentModel; using System.Diagnostics; @@ -9,9 +8,9 @@ namespace Moq [EditorBrowsable(EditorBrowsableState.Never)] public readonly struct Times : IEquatable { - readonly int from; - readonly int to; - readonly Kind kind; + private readonly int from; + private readonly int to; + private readonly Kind kind; /// Supports the legacy API. [EditorBrowsable(EditorBrowsableState.Never)] @@ -38,7 +37,7 @@ public Sdk.Times ToSdk() } } - Times(Kind kind, int from, int to) + private Times(Kind kind, int from, int to) { this.from = from; this.to = to; @@ -145,7 +144,7 @@ public bool Equals(Times other) return from == otherFrom && to == otherTo; } - enum Kind + private enum Kind { AtLeastOnce, AtLeast, @@ -158,5 +157,4 @@ enum Kind Never, } } -} -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member \ No newline at end of file +} \ No newline at end of file diff --git a/src/Moq/Moq/MockBehavior.cs b/src/Moq/MockBehavior.cs similarity index 100% rename from src/Moq/Moq/MockBehavior.cs rename to src/Moq/MockBehavior.cs diff --git a/src/Moq/MockInitializer.cs b/src/Moq/MockInitializer.cs new file mode 100644 index 00000000..e081447c --- /dev/null +++ b/src/Moq/MockInitializer.cs @@ -0,0 +1,59 @@ +using System.ComponentModel; +using Moq.Sdk; +using Stunts; + +namespace Moq +{ + /// + /// Provides the method for configuring the initial + /// set of behaviors for a given . + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static class MockInitializer + { + /// + /// Clears any existing behavior (including any setups) and + /// adds the necessary behaviors to the so + /// that it behaves as specified by the + /// enumeration. + /// + /// + /// This method can be used by custom mocks to ensure they have the + /// same default behaviors as a mock created using Mock.Of{T}. + /// + public static void Initialize(this IMocked mocked, MockBehavior behavior = MockBehavior.Loose) + { + var mock = mocked.Mock; + var behaviors = mock.Behaviors; + (behaviors as ISupportInitialize)?.BeginInit(); + + try + { + behaviors.Clear(); + + mocked.AsMoq().Behavior = behavior; + + behaviors.Add(new SetupScopeBehavior()); + behaviors.Add(new MockContextBehavior()); + behaviors.Add(new ConfigurePipelineBehavior()); + behaviors.Add(new MockRecordingBehavior()); + behaviors.Add(new EventBehavior()); + behaviors.Add(new PropertyBehavior { SetterRequiresSetup = behavior == MockBehavior.Strict }); + behaviors.Add(new DefaultEqualityBehavior()); + behaviors.Add(new RecursiveMockBehavior()); + behaviors.Add(new CallBaseBehavior()); + + // Dynamically configured by the ConfigurePipelineBehavior. + behaviors.Add(new StrictMockBehavior()); + + var defaultValue = mock.State.GetOrAdd(() => new DefaultValueProvider()); + behaviors.Add(new DefaultValueBehavior(defaultValue)); + mock.State.Set(defaultValue); + } + finally + { + (behaviors as ISupportInitialize)?.EndInit(); + } + } + } +} diff --git a/src/Moq/Moq.CodeAnalysis/AssemblyInfo.cs b/src/Moq/Moq.CodeAnalysis/AssemblyInfo.cs deleted file mode 100644 index 881eb43e..00000000 --- a/src/Moq/Moq.CodeAnalysis/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Moq.Sdk.Tests")] \ No newline at end of file diff --git a/src/Moq/Moq.CodeAnalysis/MockDiagnostics.cs b/src/Moq/Moq.CodeAnalysis/MockDiagnostics.cs deleted file mode 100644 index 7a59785f..00000000 --- a/src/Moq/Moq.CodeAnalysis/MockDiagnostics.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using Microsoft.CodeAnalysis; -using Moq.Properties; - -namespace Moq -{ - /// - /// Known diagnostics reported by the Moq analyzers. - /// - public static class MockDiagnostics - { - /// - /// Diagnostic reported whenever an expected mock is not found in the current compilation. - /// - public static DiagnosticDescriptor Missing { get; } = new DiagnosticDescriptor( - "MOQ001", - new ResourceString(nameof(Resources.MissingMockAnalyzer_Title)), - new ResourceString(nameof(Resources.MissingMockAnalyzer_Message)), - "Build", - bool.TryParse(Environment.GetEnvironmentVariable("AutoCodeFix"), out var value) && value ? DiagnosticSeverity.Warning : DiagnosticSeverity.Info, - true, - new ResourceString(nameof(Resources.MissingMockAnalyzer_Description))); - - /// - /// Diagnostic reported whenever an existing mock is outdated with regards to the interfaces - /// it implements or abstract base class it inherits from. - /// - public static DiagnosticDescriptor Outdated { get; } = new DiagnosticDescriptor( - "MOQ002", - new ResourceString(nameof(Resources.OutdatedMockAnalyzer_Title)), - new ResourceString(nameof(Resources.OutdatedMockAnalyzer_Message)), - "Build", - bool.TryParse(Environment.GetEnvironmentVariable("AutoCodeFix"), out var value) && value ? DiagnosticSeverity.Warning : DiagnosticSeverity.Info, - true, - new ResourceString(nameof(Resources.OutdatedMockAnalyzer_Description))); - } -} diff --git a/src/Moq/Moq.CodeAnalysis/MockGeneratorAnalyzer.cs b/src/Moq/Moq.CodeAnalysis/MockGeneratorAnalyzer.cs deleted file mode 100644 index b60efd35..00000000 --- a/src/Moq/Moq.CodeAnalysis/MockGeneratorAnalyzer.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using Stunts; - -namespace Moq -{ - /// - /// Analyzer that reports missing and outdated mocks. - /// - // TODO: F# - [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] - public class MockGeneratorAnalyzer : StuntGeneratorAnalyzer - { - /// - public override DiagnosticDescriptor MissingDiagnostic => MockDiagnostics.Missing; - - /// - public override DiagnosticDescriptor OutdatedDiagnostic => MockDiagnostics.Outdated; - - /// - /// Initializes the analyzer, passing the default - /// and to the base class. - /// - public MockGeneratorAnalyzer() : base(new MockNamingConvention(), typeof(MockGeneratorAttribute), false) { } - } -} diff --git a/src/Moq/Moq.CodeAnalysis/Moq.CodeAnalysis.csproj b/src/Moq/Moq.CodeAnalysis/Moq.CodeAnalysis.csproj deleted file mode 100644 index 36a13193..00000000 --- a/src/Moq/Moq.CodeAnalysis/Moq.CodeAnalysis.csproj +++ /dev/null @@ -1,47 +0,0 @@ - - - - - netstandard2.0 - Moq - true - Analyzers - true - - - - - - PrimaryOutputKind=$(PrimaryOutputKind) - - - - - - - - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - <_RoslynVisualBasic Include="@(ReferencePath -> WithMetadataValue('NuGetPackageId', 'Microsoft.CodeAnalysis.VisualBasic'))" /> - - - - - \ No newline at end of file diff --git a/src/Moq/Moq.CodeFix/MockCodeAction.cs b/src/Moq/Moq.CodeFix/MockCodeAction.cs deleted file mode 100644 index 1ccda8be..00000000 --- a/src/Moq/Moq.CodeFix/MockCodeAction.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.CodeAnalysis; -using Stunts; - -namespace Moq -{ - /// - /// Overrides Stunts.Sdk's built-in - /// with our own custom generator and naming conventions. - /// - class MockCodeAction : StuntCodeAction - { - public MockCodeAction(string title, Document document, Diagnostic diagnostic) - : base(title, document, diagnostic, new MockNamingConvention()) - { - } - - protected override StuntGenerator CreateGenerator(NamingConvention naming) => new MockGenerator(naming); - } -} \ No newline at end of file diff --git a/src/Moq/Moq.CodeFix/Properties/launchSettings.json b/src/Moq/Moq.CodeFix/Properties/launchSettings.json deleted file mode 100644 index 6a115347..00000000 --- a/src/Moq/Moq.CodeFix/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profiles": { - "Moq.Analyzer": { - "commandName": "Executable", - "executablePath": "$(VsInstallRoot)\\Common7\\IDE\\devenv.exe", - "commandLineArgs": "$(SolutionDir)Samples\\Samples.sln" - } - } -} \ No newline at end of file diff --git a/src/Moq/Moq.CodeFix/ResourceString.cs b/src/Moq/Moq.CodeFix/ResourceString.cs deleted file mode 100644 index a494ffbe..00000000 --- a/src/Moq/Moq.CodeFix/ResourceString.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Globalization; -using Microsoft.CodeAnalysis; -using Moq.Properties; - -namespace Moq -{ - class ResourceString : LocalizableString - { - readonly string name; - - public ResourceString(string name) => this.name = name; - - protected override bool AreEqual(object other) - => (other as ResourceString)?.name == name; - - protected override int GetHash() => name.GetHashCode(); - - protected override string GetText(IFormatProvider formatProvider) - => Resources.ResourceManager.GetString(name, (formatProvider as CultureInfo ?? CultureInfo.CurrentUICulture)) ?? ""; - } -} diff --git a/src/Moq/Moq.DynamicProxy/Moq.DynamicProxy.csproj b/src/Moq/Moq.DynamicProxy/Moq.DynamicProxy.csproj deleted file mode 100644 index 4b433613..00000000 --- a/src/Moq/Moq.DynamicProxy/Moq.DynamicProxy.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - netstandard2.0 - Moq.Sdk - - - - - - - - diff --git a/src/Moq/Moq.Package/Moq.Package.msbuildproj b/src/Moq/Moq.Package/Moq.Package.msbuildproj deleted file mode 100644 index 2ca68b35..00000000 --- a/src/Moq/Moq.Package/Moq.Package.msbuildproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - netstandard2.0 - PackageReference - Moq - Moq - The most popular and friendly mocking framework for .NET - The most popular and friendly mocking framework for .NET - moq mocking mock - true - - - - - - - - - - <_PackageContent Condition="'%(Kind)' == 'Dependency'"> - .NETStandard,Version=v2.0 - - all - - - - \ No newline at end of file diff --git a/src/Moq/Moq.Sdk.Tests/DefaultValueTests.cs b/src/Moq/Moq.Sdk.Tests/DefaultValueTests.cs deleted file mode 100644 index 4e797e4d..00000000 --- a/src/Moq/Moq.Sdk.Tests/DefaultValueTests.cs +++ /dev/null @@ -1,207 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Stunts; -using Xunit; - -namespace Moq.Sdk.Tests -{ - public class DefaultValueTests - { - [Fact] - public void DoesNotSetRefValue() - { - var method = typeof(IDefaultValues).GetMethod(nameof(IDefaultValues.VoidWithRef)); - IStuntBehavior behavior = new DefaultValueBehavior(); - var value = new object(); - - var result = behavior.Execute(new MethodInvocation(new object(), method, value), () => null); - - Assert.Equal(1, result.Outputs.Count); - Assert.NotNull(result.Outputs[0]); - Assert.Same(result.Outputs[0], value); - } - - [Fact] - public void DoesNotSetsRefEnumValue() - { - var method = typeof(IDefaultValues).GetMethod(nameof(IDefaultValues.VoidWithRefEnum)); - IStuntBehavior behavior = new DefaultValueBehavior(); - var platform = PlatformID.Xbox; - - var result = behavior.Execute(new MethodInvocation(new object(), method, platform), () => null); - - Assert.Equal(1, result.Outputs.Count); - Assert.NotNull(result.Outputs[0]); - Assert.Equal(platform, result.Outputs[0]); - } - - [Fact] - public void SetsOutValue() - { - var method = typeof(IDefaultValues).GetMethod(nameof(IDefaultValues.VoidWithOut)); - IStuntBehavior behavior = new DefaultValueBehavior(); - - var result = behavior.Execute(new MethodInvocation(new object(), method, new object[1]), () => null); - - Assert.Equal(1, result.Outputs.Count); - Assert.NotNull(result.Outputs[0]); - Assert.True(result.Outputs[0] is object[]); - } - - [Fact] - public void SetsReturnEnum() - { - var method = typeof(IDefaultValues).GetMethod(nameof(IDefaultValues.ReturnEnum)); - IStuntBehavior behavior = new DefaultValueBehavior(); - - var result = behavior.Execute(new MethodInvocation(new object(), method, new object[0]), () => null); - - Assert.Equal(default(PlatformID), result.ReturnValue); - } - - [Fact] - public void DoesNotFailWithNonMethodInfo() - { - var ctor = typeof(Foo).GetConstructors().First(); - IStuntBehavior behavior = new DefaultValueBehavior(); - - behavior.Execute(new MethodInvocation(new object(), ctor, new object[1]), () => null); - } - - [Fact] - public void DefaultForNullableValueTypeIsNull() - => Assert.Null(new DefaultValueProvider().GetDefault()); - - [Fact] - public void DefaultForArrayIsEmpty() - { - var value = new DefaultValueProvider().GetDefault(typeof(object[])); - - Assert.NotNull(value); - Assert.IsType(value); - Assert.Empty(((Array)value)); - } - - [Fact] - public void DefaultForTaskIsCompleted() - { - var value = new DefaultValueProvider().GetDefault(); - - Assert.NotNull(value); - Assert.True(value.IsCompleted); - } - - [Fact] - public void DefaultForTaskOfEnumIsDefaultValue() - { - var value = new DefaultValueProvider().GetDefault>(); - - Assert.NotNull(value); - Assert.True(value.IsCompleted); - Assert.Equal(default(PlatformID), value.Result); - } - - [Fact] - public void DefaultForEnumerableIsNotNull() - => Assert.NotNull(new DefaultValueProvider().GetDefault()); - - [Fact] - public void DefaultForGenericEnumerableIsEmpty() - => Assert.Empty(new DefaultValueProvider().GetDefault>()); - - [Fact] - public void DefaultForQueryableIsNotNull() - => Assert.NotNull(new DefaultValueProvider().GetDefault()); - - [Fact] - public void DefaultForGenericQueryableIsEmpty() - => Assert.Empty(new DefaultValueProvider().GetDefault>()); - - [Fact] - public void DefaultForRefIsElementType() - { - var method = typeof(IDefaultValues).GetMethod(nameof(IDefaultValues.VoidWithRef)); - var parameter = method.GetParameters()[0]; - - Assert.True(parameter.ParameterType.IsByRef); - - var value = new DefaultValueProvider().GetDefault(parameter.ParameterType); - - Assert.NotNull(value); - Assert.True(value is object[]); - Assert.Empty((object[])value); - } - - [Fact] - public void DefaultForArrayWithRankIsEmpty() - => Assert.Empty(new DefaultValueProvider().GetDefault()); - - [Fact] - public void DefaultForValueTupleHasDefaults() - { - var (providers, formatter, platform) = new DefaultValueProvider().GetDefault<(IServiceProvider[], Task, PlatformID)>(); - - Assert.Empty(providers); - Assert.True(formatter.IsCompleted); - Assert.Equal(default(PlatformID), platform); - } - - [Fact] - public void RegisterDefaultValue() - { - var provider = new DefaultValueProvider(); - var expected = new object[] { 5, 10 }; - - provider.Register(typeof(IEnumerable), _ => expected); - - var value = provider.GetDefault>(); - - Assert.Same(expected, value); - } - - [Fact] - public void RegisterDefaultValueGeneric() - { - var provider = new DefaultValueProvider(); - var expected = new object[] { 5, 10 }; - - provider.Register>(() => expected); - - var value = provider.GetDefault>(); - - Assert.Same(expected, value); - } - - [Fact] - public void DeregisterRemovesDefaultValue() - { - var provider = new DefaultValueProvider(); - - provider.Register(() => new Foo(PlatformID.Win32NT)); - Assert.True(provider.Deregister()); - - Assert.Null(provider.GetDefault()); - } - - public class Foo - { - public Foo(PlatformID platform) - { - } - } - - public interface IDefaultValues - { - void VoidWithRef(ref object[] refValue); - - void VoidWithRefEnum(ref PlatformID refEnum); - - void VoidWithOut(out object[] refValue); - - PlatformID ReturnEnum(); - } - } -} diff --git a/src/Moq/Moq.Sdk.Tests/Moq.Sdk.Tests.csproj b/src/Moq/Moq.Sdk.Tests/Moq.Sdk.Tests.csproj deleted file mode 100644 index 9689bc1f..00000000 --- a/src/Moq/Moq.Sdk.Tests/Moq.Sdk.Tests.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - netcoreapp3.0 - net472 - true - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Moq/Moq.Sdk/AssemblyInfo.cs b/src/Moq/Moq.Sdk/AssemblyInfo.cs deleted file mode 100644 index 881eb43e..00000000 --- a/src/Moq/Moq.Sdk/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Moq.Sdk.Tests")] \ No newline at end of file diff --git a/src/Moq/Moq.Sdk/DefaultValueBehavior.cs b/src/Moq/Moq.Sdk/DefaultValueBehavior.cs deleted file mode 100644 index e9c36d3c..00000000 --- a/src/Moq/Moq.Sdk/DefaultValueBehavior.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Linq; -using System.Reflection; -using Stunts; - -namespace Moq.Sdk -{ - /// - /// A that returns default values from an - /// invocation, both for the method return type as well as any out/ref - /// parameters. - /// - public class DefaultValueBehavior : IStuntBehavior - { - /// - /// Initializes the behavior with a default . - /// - public DefaultValueBehavior() - : this(new DefaultValueProvider()) { } - - /// - /// Initializes the behavior with a specific . - /// - public DefaultValueBehavior(DefaultValueProvider provider) => Provider = provider; - - /// - /// Gets or sets the provider of default values for the behavior. - /// - public DefaultValueProvider Provider { get; set; } - - /// - /// Always returns - /// - public bool AppliesTo(IMethodInvocation invocation) => true; - - /// - /// Fills in the ref, out and return values with the defaults determined - /// by the utility class. - /// - IMethodReturn IStuntBehavior.Execute(IMethodInvocation invocation, GetNextBehavior next) - { - var arguments = invocation.Arguments?.ToArray() ?? new object[0]; - var parameters = invocation.MethodBase?.GetParameters() ?? new ParameterInfo[0]; - for (var i = 0; i < parameters.Length; i++) - { - var parameter = parameters[i]; - // Only provide default values for out parameters. - // NOTE: does not touch ByRef values. - if (parameter.IsOut) - arguments[i] = Provider.GetDefault(parameter.ParameterType); - } - - var returnValue = default(object); - if (invocation.MethodBase is MethodInfo info && - info.ReturnType != typeof(void)) - { - returnValue = Provider.GetDefault(info.ReturnType); - } - - return invocation.CreateValueReturn(returnValue, arguments); - } - } -} diff --git a/src/Moq/Moq.Sdk/DefaultValueProvider.cs b/src/Moq/Moq.Sdk/DefaultValueProvider.cs deleted file mode 100644 index 1525b141..00000000 --- a/src/Moq/Moq.Sdk/DefaultValueProvider.cs +++ /dev/null @@ -1,165 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; - -namespace Moq.Sdk -{ - /// - /// Utility class that generates default values for certain types. - /// See . - /// - public class DefaultValueProvider - { - [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] - readonly ConcurrentDictionary> factories = new ConcurrentDictionary>(); - - /// - /// Initializes the provider. - /// - /// Whether to register the default value factories. - public DefaultValueProvider(bool registerDefaults = true) - { - if (registerDefaults) - { - factories[typeof(Array)] = CreateArray; - factories[typeof(Task)] = CreateTask; - factories[typeof(Task<>)] = CreateTaskOf; - factories[typeof(IEnumerable)] = CreateEnumerable; - factories[typeof(IEnumerable<>)] = CreateEnumerableOf; - factories[typeof(IQueryable)] = CreateQueryable; - factories[typeof(IQueryable<>)] = CreateQueryableOf; - factories[typeof(ValueTuple<>)] = CreateValueTupleOf; - factories[typeof(ValueTuple<,>)] = CreateValueTupleOf; - factories[typeof(ValueTuple<,,>)] = CreateValueTupleOf; - factories[typeof(ValueTuple<,,,>)] = CreateValueTupleOf; - factories[typeof(ValueTuple<,,,,>)] = CreateValueTupleOf; - factories[typeof(ValueTuple<,,,,,>)] = CreateValueTupleOf; - factories[typeof(ValueTuple<,,,,,,>)] = CreateValueTupleOf; - factories[typeof(ValueTuple<,,,,,,,>)] = CreateValueTupleOf; - } - - string foo = null; - Console.WriteLine(foo); - } - - /// - /// Gets a default value for the given type . - /// - public T GetDefault() => (T)GetDefault(typeof(T)); - - /// - /// Gets a default value for the given type - /// - public object GetDefault(Type type) - { - // If type is by ref, we need to get the actual element type of the ref. - // i.e. Object[]& has ElementType = Object[] - var valueType = type.IsByRef && type.HasElementType ? type.GetElementType() : type; - var info = valueType.GetTypeInfo(); - var typeKey = valueType.IsArray ? typeof(Array) : valueType; - - // Try get a handler with the concrete type first. - if (factories.TryGetValue(typeKey, out var factory)) - return factory.Invoke(valueType); - - // Fallback to getting one for the generic type, if available - if (info.IsGenericType && factories.TryGetValue(valueType.GetGenericTypeDefinition(), out factory)) - return factory.Invoke(valueType); - - return GetFallbackDefaultValue(valueType); - } - - /// - /// Deregisters a default value factory for the given . - /// - /// Whether there was a registered factory and it was removed. - public bool Deregister(Type key) => factories.TryRemove(key, out _); - - /// - /// Registers a default value factory for the given . - /// - public void Register(Type key, Func factory) => factories[key] = factory; - - /// - /// Deregisters a default value factory for the given . - /// - /// Whether there was a registered factory and it was removed. - public bool Deregister() => Deregister(typeof(T)); - - /// - /// Registers a default value factory for the given . - /// - public void Register(Func factory) => Register(typeof(T), _ => factory()); - - /// - /// Determines the default value for the given when no suitable factory is registered for it. - /// - /// The type of which to produce a value. - protected virtual object GetFallbackDefaultValue(Type type) - { - if (type.GetTypeInfo().IsValueType) - { - // For nullable value types, return null. - if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) - return null; - - return Activator.CreateInstance(type); - } - - return null; - } - - private static object CreateArray(Type type) => Array.CreateInstance(type.GetElementType(), new int[type.GetArrayRank()]); - - private static object CreateTask(Type type) => Task.CompletedTask; - - private static object CreateEnumerable(Type type) => Enumerable.Empty(); - - private static object CreateEnumerableOf(Type type) => Array.CreateInstance(type.GetTypeInfo().GenericTypeArguments[0], 0); - - private static object CreateQueryable(Type type) => Enumerable.Empty().AsQueryable(); - - private static object CreateQueryableOf(Type type) - { - var elementType = type.GetGenericArguments()[0]; - var array = Array.CreateInstance(elementType, 0); - - return typeof(Queryable).GetMethods() - .Single(x => x.Name == nameof(Queryable.AsQueryable) && x.IsGenericMethod) - .MakeGenericMethod(elementType) - .Invoke(null, new[] { array }); - } - - private object CreateValueTupleOf(Type type) - { - var itemTypes = type.GetGenericArguments(); - var items = new object[itemTypes.Length]; - for (int i = 0, n = itemTypes.Length; i < n; ++i) - { - items[i] = GetDefault(itemTypes[i]); - } - - return Activator.CreateInstance(type, items); - - } - private object CreateTaskOf(Type type) => GetCompletedTaskForType(type.GetTypeInfo().GenericTypeArguments[0]); - - private Task GetCompletedTaskForType(Type type) - { - var tcs = Activator.CreateInstance(typeof(TaskCompletionSource<>).MakeGenericType(type)); - - var setResultMethod = tcs.GetType().GetTypeInfo().GetDeclaredMethod("SetResult"); - var taskProperty = tcs.GetType().GetTypeInfo().GetDeclaredProperty("Task"); - var result = GetDefault(type); - - setResultMethod.Invoke(tcs, new[] { result }); - - return (Task)taskProperty.GetValue(tcs, null); - } - } -} diff --git a/src/Moq/Moq.Sdk/MockFactory.cs b/src/Moq/Moq.Sdk/MockFactory.cs deleted file mode 100644 index e026982e..00000000 --- a/src/Moq/Moq.Sdk/MockFactory.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Reflection; - -namespace Moq.Sdk -{ - /// - /// Allows accessing the default to use to - /// create mocks. - /// - public static class MockFactory - { - /// - /// Gets or sets the default to use - /// to create mocks. - /// - public static IMockFactory Default { get; set; } - } -} \ No newline at end of file diff --git a/src/Moq/Moq.Sdk/Moq.Sdk.csproj b/src/Moq/Moq.Sdk/Moq.Sdk.csproj deleted file mode 100644 index 7fa18f6f..00000000 --- a/src/Moq/Moq.Sdk/Moq.Sdk.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - - netstandard2.0 - true - - - - - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - - - - \ No newline at end of file diff --git a/src/Moq/Moq.Sdk/Properties/Resources.Designer.cs b/src/Moq/Moq.Sdk/Properties/Resources.Designer.cs deleted file mode 100644 index 0229dcc5..00000000 --- a/src/Moq/Moq.Sdk/Properties/Resources.Designer.cs +++ /dev/null @@ -1,108 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Moq.Sdk.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Moq.Sdk.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to The mock already contains a context behavior.. - /// - internal static string DuplicateContextBehavior { - get { - return ResourceManager.GetString("DuplicateContextBehavior", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The mock already contains a recording behavior.. - /// - internal static string DuplicateRecordingBehavior { - get { - return ResourceManager.GetString("DuplicateRecordingBehavior", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Could not locate event for attach or detach method {0}.. - /// - internal static string EventNotFound { - get { - return ResourceManager.GetString("EventNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to No setup is currently being performed on the mock.. - /// - internal static string NoCurrentSetup { - get { - return ResourceManager.GetString("NoCurrentSetup", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The target of the invocation is not a mock.. - /// - internal static string TargetNotMock { - get { - return ResourceManager.GetString("TargetNotMock", resourceCulture); - } - } - } -} diff --git a/src/Moq/Moq.Sdk/SetupScopeAttribute.cs b/src/Moq/Moq.Sdk/SetupScopeAttribute.cs deleted file mode 100644 index e15b2f4f..00000000 --- a/src/Moq/Moq.Sdk/SetupScopeAttribute.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -namespace Moq -{ - /// - /// Annotates a method that creates an implicit . - /// - /// - /// This allows a method like Setup that receives a lambda, to have - /// its parameter considered as a setup lambda, so that executing it does - /// not cause the actual mock behavior to run, and instead it turns on - /// an automatic so that behaviors can adapt to - /// the invocation dynamically. - /// - [AttributeUsage(AttributeTargets.Method)] - public class SetupScopeAttribute : Attribute - { - } -} \ No newline at end of file diff --git a/src/Moq/Moq.Tests/Moq.Tests.csproj b/src/Moq/Moq.Tests/Moq.Tests.csproj deleted file mode 100644 index a5c18663..00000000 --- a/src/Moq/Moq.Tests/Moq.Tests.csproj +++ /dev/null @@ -1,41 +0,0 @@ - - - - - netcoreapp3.0 - net472 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Moq/Moq.csproj b/src/Moq/Moq.csproj new file mode 100644 index 00000000..0c0a6b04 --- /dev/null +++ b/src/Moq/Moq.csproj @@ -0,0 +1,21 @@ + + + + netstandard2.0 + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Moq/Moq/AssemblyInfo.cs b/src/Moq/Moq/AssemblyInfo.cs deleted file mode 100644 index 8d580398..00000000 --- a/src/Moq/Moq/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Moq.Tests")] \ No newline at end of file diff --git a/src/Moq/Moq/GlobalSuppressions.cs b/src/Moq/Moq/GlobalSuppressions.cs deleted file mode 100644 index 36e74184..00000000 --- a/src/Moq/Moq/GlobalSuppressions.cs +++ /dev/null @@ -1,8 +0,0 @@ - -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "False positives on expression-bodied members.")] - diff --git a/src/Moq/Moq/MockInitializer.cs b/src/Moq/Moq/MockInitializer.cs deleted file mode 100644 index 48f50138..00000000 --- a/src/Moq/Moq/MockInitializer.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.ComponentModel; -using Moq.Sdk; -using Stunts; - -namespace Moq -{ - /// - /// Provides the method for configuring the initial - /// set of behaviors for a given . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class MockInitializer - { - /// - /// Clears any existing behavior (including any setups) and - /// adds the necessary behaviors to the so - /// that it behaves as specified by the - /// enumeration. - /// - /// - /// This method can be used by custom mocks to ensure they have the - /// same default behaviors as a mock created using Mock.Of{T}. - /// - public static void Initialize(this IMocked mocked, MockBehavior behavior = MockBehavior.Loose) - { - var mock = mocked.Mock; - mock.Behaviors.Clear(); - - mocked.AsMoq().Behavior = behavior; - - mock.Behaviors.Add(new SetupScopeBehavior()); - mock.Behaviors.Add(new MockContextBehavior()); - mock.Behaviors.Add(new ConfigurePipelineBehavior()); - mock.Behaviors.Add(new MockRecordingBehavior()); - mock.Behaviors.Add(new EventBehavior()); - mock.Behaviors.Add(new PropertyBehavior { SetterRequiresSetup = behavior == MockBehavior.Strict }); - mock.Behaviors.Add(new DefaultEqualityBehavior()); - mock.Behaviors.Add(new RecursiveMockBehavior()); - mock.Behaviors.Add(new CallBaseBehavior()); - - // Dynamically configured by the ConfigurePipelineBehavior. - mock.Behaviors.Add(new StrictMockBehavior()); - - var defaultValue = mock.State.GetOrAdd(() => new DefaultValueProvider()); - mock.Behaviors.Add(new DefaultValueBehavior(defaultValue)); - mock.State.Set(defaultValue); - } - } -} diff --git a/src/Moq/Moq/Moq.csproj b/src/Moq/Moq/Moq.csproj deleted file mode 100644 index 7b26fd15..00000000 --- a/src/Moq/Moq/Moq.csproj +++ /dev/null @@ -1,41 +0,0 @@ - - - - - netstandard2.0 - Moq.Core - false - true - $(IncludeApi) - None - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - \ No newline at end of file diff --git a/src/Moq/Moq/Properties/Resources.Designer.cs b/src/Moq/Moq/Properties/Resources.Designer.cs deleted file mode 100644 index 273368c4..00000000 --- a/src/Moq/Moq/Properties/Resources.Designer.cs +++ /dev/null @@ -1,81 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Moq.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Moq.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to The target does not have either {0} or {1} behaviors.. - /// - internal static string TargetNotLooseOrStrict { - get { - return ResourceManager.GetString("TargetNotLooseOrStrict", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The target is not a mock.. - /// - internal static string TargetNotMock { - get { - return ResourceManager.GetString("TargetNotMock", resourceCulture); - } - } - } -} diff --git a/src/Moq/Moq/build/Moq.props b/src/Moq/Moq/build/Moq.props deleted file mode 100644 index 5e0fd69d..00000000 --- a/src/Moq/Moq/build/Moq.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - true - - - - - - - false - - - - - \ No newline at end of file diff --git a/src/Moq/Moq/Moq`1.cs b/src/Moq/Moq`1.cs similarity index 99% rename from src/Moq/Moq/Moq`1.cs rename to src/Moq/Moq`1.cs index 790f10a6..ab9dc9ee 100644 --- a/src/Moq/Moq/Moq`1.cs +++ b/src/Moq/Moq`1.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Linq; using Moq.Sdk; +using Stunts; namespace Moq { diff --git a/src/Moq/Moq/NamedExtension.cs b/src/Moq/NamedExtension.cs similarity index 100% rename from src/Moq/Moq/NamedExtension.cs rename to src/Moq/NamedExtension.cs diff --git a/src/Moq/Moq/OccurrenceExtension.cs b/src/Moq/OccurrenceExtension.cs similarity index 98% rename from src/Moq/Moq/OccurrenceExtension.cs rename to src/Moq/OccurrenceExtension.cs index da9f5b8a..c2135fc2 100644 --- a/src/Moq/Moq/OccurrenceExtension.cs +++ b/src/Moq/OccurrenceExtension.cs @@ -40,7 +40,7 @@ public static TResult AtLeastOnce(this TResult target) // TODO: throw if no setup? } - return default; + return target; } /// @@ -66,7 +66,7 @@ public static TResult Once(this TResult target) // TODO: throw if no setup? } - return default; + return target; } /// diff --git a/src/Moq/Moq/Overloads.linq b/src/Moq/Overloads.linq similarity index 100% rename from src/Moq/Moq/Overloads.linq rename to src/Moq/Overloads.linq diff --git a/src/Moq/Moq/Raise.cs b/src/Moq/Raise.cs similarity index 84% rename from src/Moq/Moq/Raise.cs rename to src/Moq/Raise.cs index 443cd5d9..28a94502 100644 --- a/src/Moq/Moq/Raise.cs +++ b/src/Moq/Raise.cs @@ -12,7 +12,7 @@ public static class Raise /// Raises the event being attached to, passing the target mock /// as the sender, and args. /// - public static EventHandler Event() + public static EventHandler? Event() { CallContext.SetData(EventRaiser.Empty); return default; @@ -23,7 +23,7 @@ public static EventHandler Event() /// as the sender, and the given as the /// event arguments. /// - public static EventHandler Event(TEventArgs args) + public static EventHandler? Event(TEventArgs args) { CallContext.SetData(new EventArgsEventRaiser(args)); return default; @@ -34,7 +34,7 @@ public static EventHandler Event(TEventArgs args) /// as the sender, and the given as the /// event arguments. /// - public static EventHandler Event(EventArgs args) + public static EventHandler? Event(EventArgs args) { CallContext.SetData(new EventArgsEventRaiser(args)); return default; @@ -45,7 +45,7 @@ public static EventHandler Event(EventArgs args) /// as the sender, and the given as the /// event arguments. /// - public static TEventHandler Event(EventArgs args) + public static TEventHandler? Event(EventArgs args) { CallContext.SetData(new EventArgsEventRaiser(args)); return default; @@ -55,7 +55,7 @@ public static TEventHandler Event(EventArgs args) /// Raises the event being attached to, passing the given /// as the event arguments. /// - public static TEventHandler Event(params object[] args) + public static TEventHandler? Event(params object[] args) { CallContext.SetData(new CustomEventRaiser(args)); return default; diff --git a/src/Moq/Moq/RecursiveMockBehavior.cs b/src/Moq/RecursiveMockBehavior.cs similarity index 96% rename from src/Moq/Moq/RecursiveMockBehavior.cs rename to src/Moq/RecursiveMockBehavior.cs index f4aa1e7e..2b3418d0 100644 --- a/src/Moq/Moq/RecursiveMockBehavior.cs +++ b/src/Moq/RecursiveMockBehavior.cs @@ -44,7 +44,7 @@ public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) // yet. var recursiveMock = ((IMocked)MockFactory.Default.CreateMock( // Use the same assembly as the current target - invocation.Target.GetType().GetTypeInfo().Assembly, + invocation.Target.GetType().Assembly, info.ReturnType, new Type[0], new object[0])).Mock; @@ -60,7 +60,7 @@ public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) } // Set up the current invocation to return the created value - var setup = currentMock.GetPipeline(MockContext.CurrentSetup); + var setup = currentMock.GetPipeline(MockContext.CurrentSetup ?? CallContext.ThrowUnexpectedNull()); var returnBehavior = setup.Behaviors.OfType().FirstOrDefault(); if (returnBehavior != null) returnBehavior.Value = recursiveMock.Object; diff --git a/src/Moq/Moq/Properties/Resources.resx b/src/Moq/Resources.resx similarity index 92% rename from src/Moq/Moq/Properties/Resources.resx rename to src/Moq/Resources.resx index 55daa037..27ed819d 100644 --- a/src/Moq/Moq/Properties/Resources.resx +++ b/src/Moq/Resources.resx @@ -117,10 +117,22 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Cannot convert target mock to the requested interface. + + + Expected a delegate argument. + + + Expected a delegate argument. + The target does not have either {0} or {1} behaviors. The target is not a mock. + + Verification failed. + \ No newline at end of file diff --git a/src/Moq/Moq/ReturnsBehavior.cs b/src/Moq/ReturnsBehavior.cs similarity index 74% rename from src/Moq/Moq/ReturnsBehavior.cs rename to src/Moq/ReturnsBehavior.cs index 38f3ff69..c259ec25 100644 --- a/src/Moq/Moq/ReturnsBehavior.cs +++ b/src/Moq/ReturnsBehavior.cs @@ -17,16 +17,20 @@ namespace Moq internal class ReturnsBehavior : IMockBehavior { [DebuggerBrowsable(DebuggerBrowsableState.Never)] - Func getter; + private Func getter; [DebuggerBrowsable(DebuggerBrowsableState.Never)] - object value; + private object? value; - public ReturnsBehavior(Func valueGetter) => ValueGetter = valueGetter; + public ReturnsBehavior(Func valueGetter) => getter = valueGetter; - public ReturnsBehavior(object value) => Value = value; + public ReturnsBehavior(object? value) + { + Value = value; + getter = _ => value; + } [DebuggerBrowsable(DebuggerBrowsableState.Never)] - public object Value + public object? Value { set { @@ -36,7 +40,7 @@ public object Value } [DebuggerBrowsable(DebuggerBrowsableState.Never)] - public Func ValueGetter + public Func ValueGetter { get => getter; set @@ -48,7 +52,7 @@ public Func ValueGetter } [DebuggerBrowsable(DebuggerBrowsableState.Never)] - object DebuggerValue => value ?? ""; + private object DebuggerValue => value ?? ""; public IMethodReturn Execute(IMock mock, IMethodInvocation invocation, GetNextMockBehavior next) => invocation.CreateValueReturn(getter(invocation.Arguments), invocation.Arguments.ToArray()); diff --git a/src/Moq/Moq/ReturnsDelegateBehavior.cs b/src/Moq/ReturnsDelegateBehavior.cs similarity index 95% rename from src/Moq/Moq/ReturnsDelegateBehavior.cs rename to src/Moq/ReturnsDelegateBehavior.cs index 0558eaf5..edea6d47 100644 --- a/src/Moq/Moq/ReturnsDelegateBehavior.cs +++ b/src/Moq/ReturnsDelegateBehavior.cs @@ -12,7 +12,7 @@ namespace Moq internal class ReturnsDelegateBehavior : IMockBehavior { [DebuggerDisplay("")] - Delegate @delegate; + private readonly Delegate @delegate; public ReturnsDelegateBehavior(Delegate @delegate) => this.@delegate = @delegate; diff --git a/src/Moq/Moq/ReturnsExtension.Overloads.cs b/src/Moq/ReturnsExtension.Overloads.cs similarity index 97% rename from src/Moq/Moq/ReturnsExtension.Overloads.cs rename to src/Moq/ReturnsExtension.Overloads.cs index 1de52d22..4bcfa4db 100644 --- a/src/Moq/Moq/ReturnsExtension.Overloads.cs +++ b/src/Moq/ReturnsExtension.Overloads.cs @@ -1,9 +1,13 @@ -using System; +#nullable disable +// Disable nullable since this works from the Arguments collection which we know can have nulls +// A NRE here would be a mis-configuration from the user, which the compiler would have caught +// already in the test setups anyway. +using System; using System.Linq; namespace Moq { - partial class ReturnsExtension + public partial class ReturnsExtension { /// /// Sets the return value for a property or non-void method to diff --git a/src/Moq/Moq/ReturnsExtension.cs b/src/Moq/ReturnsExtension.cs similarity index 92% rename from src/Moq/Moq/ReturnsExtension.cs rename to src/Moq/ReturnsExtension.cs index 5663b11e..12889d1e 100644 --- a/src/Moq/Moq/ReturnsExtension.cs +++ b/src/Moq/ReturnsExtension.cs @@ -1,6 +1,7 @@ using System; using System.ComponentModel; using System.Linq; +using Castle.Components.DictionaryAdapter; using Moq.Sdk; using Stunts; @@ -30,7 +31,7 @@ public static TResult Returns(this TResult target, TResult value) behavior.Behaviors.Add(new ReturnsBehavior(value)); } - return default; + return target; } /// @@ -53,7 +54,7 @@ public static TResult Returns(this TResult target, Func value) behavior.Behaviors.Add(new ReturnsBehavior(_ => value())); } - return default; + return target; } /// @@ -77,7 +78,7 @@ public static TResult Returns(this TResult target, Func value(x))); } - return default; + return target; } /// @@ -90,12 +91,14 @@ public static TResult Returns(this TResult target, FuncThe lambda to invoke when the setup is matched. public static void Returns(this ISetup target, TDelegate handler) { + if (handler is not Delegate @delegate) + throw new ArgumentException(ThisAssembly.Strings.Returns.DelegateExpected, nameof(handler)); + using (new SetupScope()) { - var @delegate = handler as Delegate; // Simulate Any matchers for each member parameter var parameters = @delegate.Method.GetParameters(); - var arguments = new object[parameters.Length]; + object?[] arguments = new object[parameters.Length]; var defaultValue = new DefaultValueProvider(false); for (var i = 0; i < arguments.Length; i++) { @@ -120,7 +123,7 @@ public static void Returns(this ISetup target, TDelegate h } } - static TResult Returns(Delegate value, ExecuteMockDelegate behavior) + private static TResult? Returns(Delegate value, ExecuteMockDelegate behavior) { var setup = MockContext.CurrentSetup; if (setup != null) diff --git a/src/Moq/Moq/SetupExtension.cs b/src/Moq/SetupExtension.cs similarity index 71% rename from src/Moq/Moq/SetupExtension.cs rename to src/Moq/SetupExtension.cs index 5c7774a0..dac3faf6 100644 --- a/src/Moq/Moq/SetupExtension.cs +++ b/src/Moq/SetupExtension.cs @@ -11,10 +11,20 @@ namespace Moq [EditorBrowsable(EditorBrowsableState.Never)] public static class SetupExtension { + /// + /// Marks a code block as being setup for mocks (any, not just the + /// argument). Usage: using (mock.Setup()) { ... }. + /// + /// + /// Even though this is an extension method on a particular instance of a mock, the scope + /// is active and affects all invocations to any mocks called within the block. + /// + /// + public static IDisposable Setup(this T mock) => new SetupScope(); + /// /// Sets up the mock with the given void method call. /// - [SetupScope] public static ISetup Setup(this T mock, Action action) { using (new SetupScope()) @@ -27,7 +37,6 @@ public static ISetup Setup(this T mock, Action action) /// /// Sets up the mock with the given function. /// - [SetupScope] public static TResult Setup(this T mock, Func function) { using (new SetupScope()) @@ -41,9 +50,8 @@ public static TResult Setup(this T mock, Func function) /// access and set ref/out arguments. A code fix will automatically /// generate a delegate with the right signature when using this overload. /// - [SetupScope] public static ISetup Setup(this object mock, TDelegate member) - => new DefaultSetup(member as Delegate); + => new DefaultSetup(member as Delegate ?? throw new ArgumentException(ThisAssembly.Strings.Setup.DelegateExpected)); /// /// Sets up the mock with the given method reference, typically used to @@ -53,27 +61,26 @@ public static ISetup Setup(this object mock, TDelegate mem /// and pass in the method group directly instead. A code fix will automatically /// generate a delegate with the right signature when using this overload. /// - [SetupScope] public static ISetup Setup(this object mock, Func memberFunction) { using (new SetupScope()) { - return new DefaultSetup(memberFunction() as Delegate); + return new DefaultSetup(memberFunction() as Delegate ?? throw new ArgumentException(ThisAssembly.Strings.Setup.DelegateExpected)); } } - class DefaultSetup : ISetup + private class DefaultSetup : ISetup { public DefaultSetup(Delegate @delegate) => Delegate = @delegate; public Delegate Delegate { get; } } - class DefaultSetup : ISetup + private class DefaultSetup : ISetup { public static ISetup Default { get; } = new DefaultSetup(); - DefaultSetup() { } + private DefaultSetup() { } } } } \ No newline at end of file diff --git a/src/Moq/Moq/SetupScopeBehavior.cs b/src/Moq/SetupScopeBehavior.cs similarity index 93% rename from src/Moq/Moq/SetupScopeBehavior.cs rename to src/Moq/SetupScopeBehavior.cs index cb1fbca8..59d386a9 100644 --- a/src/Moq/Moq/SetupScopeBehavior.cs +++ b/src/Moq/SetupScopeBehavior.cs @@ -13,7 +13,7 @@ namespace Moq [EditorBrowsable(EditorBrowsableState.Never)] internal class SetupScopeBehavior : IStuntBehavior { - static readonly HashSet setupScopeBehaviors = new HashSet + private static readonly HashSet setupScopeBehaviors = new HashSet { typeof(DefaultValueBehavior), typeof(MockContextBehavior), diff --git a/src/Moq/Moq/Syntax.cs b/src/Moq/Syntax.cs similarity index 80% rename from src/Moq/Moq/Syntax.cs rename to src/Moq/Syntax.cs index 93fd50f5..95e03109 100644 --- a/src/Moq/Moq/Syntax.cs +++ b/src/Moq/Syntax.cs @@ -27,7 +27,7 @@ public static class Syntax /// /// The type of the argument. /// The condition to check against actual invocation values. - public static T Any(Func condition) => Arg.Any(condition); + public static T Any(Func condition) => Arg.Any(condition); /// /// Matches all values that do not equal the specified value. @@ -38,38 +38,39 @@ public static class Syntax /// Raises the event being attached to, passing the target mock /// as the sender, and args. /// - public static EventHandler Raise() => Moq.Raise.Event(); + public static EventHandler? Raise() => Moq.Raise.Event(); /// /// Raises the event being attached to, passing the target mock /// as the sender, and the given as the /// event arguments. /// - public static EventHandler Raise(TEventArgs args) => Moq.Raise.Event(args); + public static EventHandler? Raise(TEventArgs args) => Moq.Raise.Event(args); /// /// Raises the event being attached to, passing the target mock /// as the sender, and the given as the /// event arguments. /// - public static EventHandler Raise(EventArgs args) => Moq.Raise.Event(args); + public static EventHandler? Raise(EventArgs args) => Moq.Raise.Event(args); /// /// Raises the event being attached to, passing the target mock /// as the sender, and the given as the /// event arguments. /// - public static TEventHandler Raise(EventArgs args) => Moq.Raise.Event(args); + public static TEventHandler? Raise(EventArgs args) => Moq.Raise.Event(args); /// /// Raises the event being attached to, passing the given /// as the event arguments. /// - public static TEventHandler Raise(params object[] args) => Moq.Raise.Event(args); + public static TEventHandler? Raise(params object[] args) => Moq.Raise.Event(args); /// /// Marks a code block as being setup for mocks. Usage: using (Setup()) { ... }. /// + /// public static IDisposable Setup() => new SetupScope(); } } diff --git a/src/Moq/Moq/ThrowsExtension.cs b/src/Moq/ThrowsExtension.cs similarity index 100% rename from src/Moq/Moq/ThrowsExtension.cs rename to src/Moq/ThrowsExtension.cs diff --git a/src/Moq/Moq/Verify.cs b/src/Moq/Verify.cs similarity index 84% rename from src/Moq/Moq/Verify.cs rename to src/Moq/Verify.cs index e03d9888..ba0ff98d 100644 --- a/src/Moq/Moq/Verify.cs +++ b/src/Moq/Verify.cs @@ -49,7 +49,7 @@ internal static bool IsVerifying(IMock mock) /// Optional number of times the method should have been called. Defaults to . /// An integer value can also be specificed since there is built-in conversion support from integer to . /// Optional user message to show. - public static void Called(Func function, int times = -1, string message = null) => CalledImpl(function, times, message); + public static void Called(Func function, int times = -1, string? message = null) => CalledImpl(function, times, message); /// /// Verifies a method invocation matching the was executed at @@ -59,13 +59,13 @@ internal static bool IsVerifying(IMock mock) /// Optional number of times the method should have been called. Defaults to . /// An integer value can also be specificed since there is built-in conversion support from integer to . /// Optional user message to show. - internal static void CalledImpl(Func function, Sdk.Times times = default, string message = null) + internal static void CalledImpl(Func function, Sdk.Times times = default, string? message = null) { using (new SetupScope()) { function(); - var setup = MockContext.CurrentSetup; - var mock = MockContext.CurrentInvocation.Target.AsMock(); + var setup = MockContext.CurrentSetup ?? CallContext.ThrowUnexpectedNull(); + var mock = (MockContext.CurrentInvocation ?? CallContext.ThrowUnexpectedNull()).Target.AsMock(); var calls = mock.Invocations.Where(x => setup.AppliesTo(x)); if (!times.Validate(calls.Count())) throw new VerifyException(mock, setup, message); @@ -96,7 +96,7 @@ internal static void CalledImpl(Func function, Sdk.Times times = default, /// Optional number of times the method should have been called. Defaults to . /// An integer value can also be specificed since there is built-in conversion support from integer to . /// Optional user message to show. - public static void Called(Action action, int times = -1, string message = null) => CalledImpl(action, times, message); + public static void Called(Action action, int times = -1, string? message = null) => CalledImpl(action, times, message); /// /// Verifies a method invocation matching the was executed at @@ -106,13 +106,13 @@ internal static void CalledImpl(Func function, Sdk.Times times = default, /// Optional number of times the method should have been called. Defaults to . /// An integer value can also be specificed since there is built-in conversion support from integer to . /// Optional user message to show. - internal static void CalledImpl(Action action, Sdk.Times times = default, string message = null) + internal static void CalledImpl(Action action, Sdk.Times times = default, string? message = null) { using (new SetupScope()) { action(); - var setup = MockContext.CurrentSetup; - var mock = MockContext.CurrentInvocation.Target.AsMock(); + var setup = MockContext.CurrentSetup ?? CallContext.ThrowUnexpectedNull(); + var mock = (MockContext.CurrentInvocation ?? CallContext.ThrowUnexpectedNull()).Target.AsMock(); var calls = mock.Invocations.Where(x => setup.AppliesTo(x)); if (!times.Validate(calls.Count())) throw new VerifyException(mock, setup, message); @@ -132,14 +132,14 @@ internal static void CalledImpl(Action action, Sdk.Times times = default, string /// /// The method invocation to match against actual calls. /// Optional user message to show. - public static void NotCalled(Func function, string message = null) => CalledImpl(function, Sdk.Times.Never, message); + public static void NotCalled(Func function, string? message = null) => CalledImpl(function, Sdk.Times.Never, message); /// /// Verifies a method invocation matching the was never called. /// /// The method invocation to match against actual calls. /// Optional user message to show. - public static void NotCalled(Action action, string message = null) => CalledImpl(action, Sdk.Times.Never, message); + public static void NotCalled(Action action, string? message = null) => CalledImpl(action, Sdk.Times.Never, message); /// /// Verifies all setups that had an occurrence constraint applied, @@ -160,8 +160,8 @@ public static void Calls(Func function, Action(); + var mock = (MockContext.CurrentInvocation ?? CallContext.ThrowUnexpectedNull()).Target.AsMock(); calls.Invoke(mock.Invocations.Where(x => setup.AppliesTo(x))); } } @@ -177,8 +177,8 @@ public static void Calls(Action action, Action> c using (new SetupScope()) { action(); - var setup = MockContext.CurrentSetup; - var mock = MockContext.CurrentInvocation.Target.AsMock(); + var setup = MockContext.CurrentSetup ?? CallContext.ThrowUnexpectedNull(); + var mock = (MockContext.CurrentInvocation ?? CallContext.ThrowUnexpectedNull()).Target.AsMock(); calls.Invoke(mock.Invocations.Where(x => setup.AppliesTo(x))); } } @@ -187,12 +187,12 @@ public static void Calls(Action action, Action> c /// Gets the mock after verifying that all setups that specified occurrence /// constraints have succeeded. /// - static IMock GetVerified(T target) where T : class + private static IMock GetVerified(T target) where T : class { var mock = target.AsMock(); var failures = (from pipeline in mock.Setups where pipeline.Setup.Occurrence != null - let times = pipeline.Setup.Occurrence.Value + let times = pipeline.Setup.Occurrence!.Value let calls = mock.Invocations.Where(x => pipeline.AppliesTo(x)).ToArray() where !times.Validate(calls.Length) select pipeline.Setup @@ -211,7 +211,7 @@ select pipeline.Setup /// Whether to add a behavior that verifies the invocations performed on /// the clone were never performed on the original mock. /// - static T GetVerifier(IMock mock, bool notCalled = false) where T : class + private static T GetVerifier(IMock mock, bool notCalled = false) where T : class { // If the mock is already being verified, we don't need to clone again. if (mock.State.TryGetValue(typeof(Verify), out var verifying) && verifying) @@ -225,20 +225,10 @@ static T GetVerifier(IMock mock, bool notCalled = false) where T : class if (recording != null) clone.Behaviors.Remove(recording); - // The target replacer is needed so that whenever we try to get the target object - // and the IMock from it for occurrence verification, we actually get to the actual - // target being verified, not the cloned mock. Otherwise, invocations won't match - // with the setups, since the target would be different. - clone.Behaviors.Insert( - clone.Behaviors.IndexOf(clone.Behaviors.OfType().First()) + 1, - new TargetReplacerBehavior(mock.Object)); - if (notCalled) - { clone.Behaviors.Insert( - clone.Behaviors.IndexOf(clone.Behaviors.OfType().First()) + 1, + clone.Behaviors.IndexOf(clone.Behaviors.OfType().First()) + 1, new NotCalledBehavior()); - } // Sets up the right behaviors for a loose mock new Moq(clone).Behavior = MockBehavior.Loose; @@ -248,30 +238,19 @@ static T GetVerifier(IMock mock, bool notCalled = false) where T : class return clone.Object; } - class NotCalledBehavior : IStuntBehavior + private class NotCalledBehavior : IStuntBehavior { public bool AppliesTo(IMethodInvocation invocation) => true; public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) { var mock = invocation.Target.AsMock(); - var setup = MockContext.CurrentSetup; + var setup = MockContext.CurrentSetup ?? CallContext.ThrowUnexpectedNull(); if (mock.Invocations.Where(x => setup.AppliesTo(x)).Any()) throw new VerifyException(mock, setup); return next().Invoke(invocation, next); } } - - class TargetReplacerBehavior : IStuntBehavior - { - readonly object target; - - public TargetReplacerBehavior(object target) => this.target = target; - - public bool AppliesTo(IMethodInvocation invocation) => true; - - public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) => next().Invoke(invocation, next); - } } } diff --git a/src/Moq/Moq/VerifyException.cs b/src/Moq/VerifyException.cs similarity index 90% rename from src/Moq/Moq/VerifyException.cs rename to src/Moq/VerifyException.cs index 3e40b94b..a14f32dc 100644 --- a/src/Moq/Moq/VerifyException.cs +++ b/src/Moq/VerifyException.cs @@ -12,7 +12,7 @@ public class VerifyException : MockException /// Initializes the exception with the target /// mock and setup that failed to match invocations. /// - public VerifyException(IMock mock, IMockSetup setup, string message = null) + public VerifyException(IMock mock, IMockSetup setup, string? message = null) : this(mock, new[] { setup }, message) { } @@ -21,8 +21,8 @@ public VerifyException(IMock mock, IMockSetup setup, string message = null) /// Initializes the exception with the target /// mock and setup(s) that failed to match invocations. /// - public VerifyException(IMock mock, IMockSetup[] setups, string message = null) - : base(message) + public VerifyException(IMock mock, IMockSetup[] setups, string? message = null) + : base(message ?? ThisAssembly.Strings.VerifyExceptionMessage) { Mock = mock; Setups = setups; diff --git a/src/Moq/Moq/VerifyExtension.cs b/src/Moq/VerifyExtension.cs similarity index 97% rename from src/Moq/Moq/VerifyExtension.cs rename to src/Moq/VerifyExtension.cs index 1b9aa0f9..6a41d386 100644 --- a/src/Moq/Moq/VerifyExtension.cs +++ b/src/Moq/VerifyExtension.cs @@ -1,6 +1,5 @@ using System; using System.ComponentModel; -using Moq.Sdk; namespace Moq { @@ -39,7 +38,7 @@ public static void Verify(this T target, Action action, string message) /// Optional number of times the method should have been called. Defaults to . /// An integer value can also be specificed since there is built-in conversion support from integer to . /// Optional user message to show. - public static void Verify(this T target, Action action, int times = -1, string message = null) + public static void Verify(this T target, Action action, int times = -1, string? message = null) => Moq.Verify.CalledImpl(() => action(target), (Sdk.Times)times, message); /// @@ -71,7 +70,7 @@ public static void Verify(this T target, Func function, /// Optional number of times the method should have been called. Defaults to . /// An integer value can also be specificed since there is built-in conversion support from integer to . /// Optional user message to show. - public static void Verify(this T target, Func function, int times = -1, string message = null) + public static void Verify(this T target, Func function, int times = -1, string? message = null) => Moq.Verify.CalledImpl(() => function(target), (Sdk.Times)times, message); } } diff --git a/src/Packages.props b/src/Packages.props deleted file mode 100644 index a0fe0df8..00000000 --- a/src/Packages.props +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Samples/Directory.Build.props b/src/Samples/Directory.Build.props deleted file mode 100644 index e017dd40..00000000 --- a/src/Samples/Directory.Build.props +++ /dev/null @@ -1,8 +0,0 @@ - - - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), .gitignore))\ - $(RootPath)bin\$(Configuration)\ - true - - \ No newline at end of file diff --git a/src/Samples/Directory.Build.targets b/src/Samples/Directory.Build.targets deleted file mode 100644 index ad789d15..00000000 --- a/src/Samples/Directory.Build.targets +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Class1.cs b/src/Samples/Moq.CSharp/Class1.cs deleted file mode 100644 index 4954d4a0..00000000 --- a/src/Samples/Moq.CSharp/Class1.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using Moq; - -namespace Sample.CSharp -{ - public class Class1 - { - public void Test() - { - var mock = Mock.Of(); - - mock.Setup(m => m.Memory.Recall()).Returns(1); - - var foo = Mock.Of(); - var bar = Mock.Of(); - - var value = "foo"; - - foo.Id - .Callback(() => value = "before") - .Returns(() => value) - .Callback(() => value = "after") - .Returns(() => value); - - Console.WriteLine(foo.Id); - Console.WriteLine(foo.Id); - } - - public void Test1() - { - var fake = Mock.Of(); - - fake.Memory.Recall().Returns(5); - } - - public void Test2() - { - var fake = Mock.Of(); - - fake.Memory.Recall().Returns(5); - } - } -} - -public interface IBar -{ - void DoBar(); -} - -public interface IFoo -{ - void Do(bool donow); - - string Id { get; } - string Title { get; set; } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/FooMock.cs b/src/Samples/Moq.CSharp/FooMock.cs deleted file mode 100644 index 8e228efe..00000000 --- a/src/Samples/Moq.CSharp/FooMock.cs +++ /dev/null @@ -1,48 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using Moq.Sdk; -using Stunts; -using System; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Threading; - -public class FooMock : IStunt, IMocked, IDisposable, IFormatProvider, INotifyPropertyChanged -{ - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - IMock mock; - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - [CompilerGenerated] - IMock IMocked.Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - - [CompilerGenerated] - public void Dispose() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - - [CompilerGenerated] - public object GetFormat(Type formatType) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), formatType)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public event PropertyChangedEventHandler PropertyChanged - { - add => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); - remove => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/IParser.cs b/src/Samples/Moq.CSharp/IParser.cs deleted file mode 100644 index 27c1dcc5..00000000 --- a/src/Samples/Moq.CSharp/IParser.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Moq.CSharp -{ - public interface IParser - { - bool TryParse(string input, out DateTimeOffset date); - } -} diff --git a/src/Samples/Moq.CSharp/Mocks/CalculatorBaseICustomFormatterIDisposableMock.cs b/src/Samples/Moq.CSharp/Mocks/CalculatorBaseICustomFormatterIDisposableMock.cs deleted file mode 100644 index 82a7c1e4..00000000 --- a/src/Samples/Moq.CSharp/Mocks/CalculatorBaseICustomFormatterIDisposableMock.cs +++ /dev/null @@ -1,81 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using Sample; -using System; -using System.Threading; -using Moq.Sdk; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Mocks -{ - public partial class CalculatorBaseICustomFormatterIDisposableMock : CalculatorBase, ICustomFormatter, IDisposable, IStunt, IMocked - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - IMock mock; - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - IMock IMocked.Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - - [CompilerGenerated] - public override int? this[string name] { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); } - - [CompilerGenerated] - public override bool IsOn => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override CalculatorMode Mode { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - - [CompilerGenerated] - public override ICalculatorMemory Memory => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override int Add(int x, int y) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y)); - [CompilerGenerated] - public override int Add(int x, int y, int z) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - [CompilerGenerated] - public override void Clear(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - [CompilerGenerated] - public void Dispose() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public string Format(string format, object arg, IFormatProvider formatProvider) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), format, arg, formatProvider)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override int? Recall(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - [CompilerGenerated] - public override void Store(string name, int value) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override bool TryAdd(ref int x, ref int y, out int z) - { - z = default(int); - IMethodReturn returns = pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - x = (int)returns.Outputs["x"]; - y = (int)returns.Outputs["y"]; - z = (int)returns.Outputs["z"]; - return (bool)returns.ReturnValue; - } - - [CompilerGenerated] - public override void TurnOn() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override event EventHandler TurnedOn { add => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); remove => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Mocks/IBarMock.cs b/src/Samples/Moq.CSharp/Mocks/IBarMock.cs deleted file mode 100644 index f4e7f4d8..00000000 --- a/src/Samples/Moq.CSharp/Mocks/IBarMock.cs +++ /dev/null @@ -1,39 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System.Threading; -using Moq.Sdk; -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Mocks -{ - public partial class IBarMock : IBar, IStunt, IMocked - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - IMock mock; - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - IMock IMocked.Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - - [CompilerGenerated] - public void DoBar() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Mocks/ICalculatorMemoryMock.cs b/src/Samples/Moq.CSharp/Mocks/ICalculatorMemoryMock.cs deleted file mode 100644 index b22c0cf2..00000000 --- a/src/Samples/Moq.CSharp/Mocks/ICalculatorMemoryMock.cs +++ /dev/null @@ -1,46 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using Sample; -using System.Threading; -using Moq.Sdk; -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Mocks -{ - public partial class ICalculatorMemoryMock : ICalculatorMemory, IStunt, IMocked - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - IMock mock; - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - IMock IMocked.Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - - [CompilerGenerated] - public void Add(int value) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); - [CompilerGenerated] - public void Clear() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public int Recall() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public void Subtract(int value) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Mocks/ICalculatorMock.cs b/src/Samples/Moq.CSharp/Mocks/ICalculatorMock.cs deleted file mode 100644 index 29b4f7db..00000000 --- a/src/Samples/Moq.CSharp/Mocks/ICalculatorMock.cs +++ /dev/null @@ -1,77 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using Sample; -using System.Threading; -using Moq.Sdk; -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Mocks -{ - public partial class ICalculatorMock : ICalculator, IStunt, IMocked - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - IMock mock; - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - IMock IMocked.Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - - [CompilerGenerated] - public int? this[string name] { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); } - - [CompilerGenerated] - public bool IsOn => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public CalculatorMode Mode { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - - [CompilerGenerated] - public ICalculatorMemory Memory => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public int Add(int x, int y) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y)); - [CompilerGenerated] - public int Add(int x, int y, int z) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - [CompilerGenerated] - public void Clear(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public int? Recall(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - [CompilerGenerated] - public void Store(string name, int value) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public bool TryAdd(ref int x, ref int y, out int z) - { - z = default(int); - IMethodReturn returns = pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - x = (int)returns.Outputs["x"]; - y = (int)returns.Outputs["y"]; - z = (int)returns.Outputs["z"]; - return (bool)returns.ReturnValue; - } - - [CompilerGenerated] - public void TurnOn() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public event EventHandler TurnedOn { add => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); remove => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Mocks/ICustomFormatterIDisposableMock.cs b/src/Samples/Moq.CSharp/Mocks/ICustomFormatterIDisposableMock.cs deleted file mode 100644 index f54fdcd0..00000000 --- a/src/Samples/Moq.CSharp/Mocks/ICustomFormatterIDisposableMock.cs +++ /dev/null @@ -1,41 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using System.Threading; -using Moq.Sdk; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Mocks -{ - public partial class ICustomFormatterIDisposableMock : ICustomFormatter, IDisposable, IStunt, IMocked - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - IMock mock; - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - IMock IMocked.Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - - [CompilerGenerated] - public void Dispose() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public string Format(string format, object arg, IFormatProvider formatProvider) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), format, arg, formatProvider)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Mocks/IFooMock.cs b/src/Samples/Moq.CSharp/Mocks/IFooMock.cs deleted file mode 100644 index a9f86a9c..00000000 --- a/src/Samples/Moq.CSharp/Mocks/IFooMock.cs +++ /dev/null @@ -1,45 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System.Threading; -using Moq.Sdk; -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Mocks -{ - public partial class IFooMock : IFoo, IStunt, IMocked - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - IMock mock; - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - IMock IMocked.Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - - [CompilerGenerated] - public string Id => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public string Title { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - - [CompilerGenerated] - public void Do(bool donow) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), donow)); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Mocks/IParserMock.cs b/src/Samples/Moq.CSharp/Mocks/IParserMock.cs deleted file mode 100644 index ffc76424..00000000 --- a/src/Samples/Moq.CSharp/Mocks/IParserMock.cs +++ /dev/null @@ -1,47 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using Moq.CSharp; -using System.Threading; -using Moq.Sdk; -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Mocks -{ - public partial class IParserMock : IParser, IStunt, IMocked - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - IMock mock; - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - IMock IMocked.Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public bool TryParse(string input, out DateTimeOffset date) - { - date = default(DateTimeOffset); - IMethodReturn returns = pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), input, date)); - date = (DateTimeOffset)returns.Outputs["date"]; - return (bool)returns.ReturnValue; - } - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Mocks/IRefOutMock.cs b/src/Samples/Moq.CSharp/Mocks/IRefOutMock.cs deleted file mode 100644 index bf6c32ac..00000000 --- a/src/Samples/Moq.CSharp/Mocks/IRefOutMock.cs +++ /dev/null @@ -1,47 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using Sample.CSharp; -using System.Threading; -using Moq.Sdk; -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Mocks -{ - public partial class IRefOutMock : IRefOut, IStunt, IMocked - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - IMock mock; - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - IMock IMocked.Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public bool TryParse(string input, out DateTimeOffset date) - { - date = default(DateTimeOffset); - IMethodReturn returns = pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), input, date)); - date = (DateTimeOffset)returns.Outputs["date"]; - return (bool)returns.ReturnValue; - } - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Mocks/IRefOutParentMock.cs b/src/Samples/Moq.CSharp/Mocks/IRefOutParentMock.cs deleted file mode 100644 index 81cb5987..00000000 --- a/src/Samples/Moq.CSharp/Mocks/IRefOutParentMock.cs +++ /dev/null @@ -1,41 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using Sample.CSharp; -using System.Threading; -using Moq.Sdk; -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Mocks -{ - public partial class IRefOutParentMock : IRefOutParent, IStunt, IMocked - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - IMock mock; - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - IMock IMocked.Mock => LazyInitializer.EnsureInitialized(ref mock, () => new DefaultMock(this)); - - [CompilerGenerated] - public IRefOut RefOut => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Moq.CSharp.csproj b/src/Samples/Moq.CSharp/Moq.CSharp.csproj deleted file mode 100644 index cfbfdb36..00000000 --- a/src/Samples/Moq.CSharp/Moq.CSharp.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - net471 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/Recursive.cs b/src/Samples/Moq.CSharp/Recursive.cs deleted file mode 100644 index af179fff..00000000 --- a/src/Samples/Moq.CSharp/Recursive.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using Moq; - -namespace Sample.CSharp -{ - public class Recursive - { - CalculatorBase calculator; - - public Recursive() - { - calculator = Mock.Of(); - } - - public void FieldTest() - { - calculator.Setup(m => m.Memory.Recall()).Returns(5); - var c = Mock.Of(); - - c.Recall("foo").Returns(5); - - - c.Setup(x => x.Store("foo", 5)); - } - } -} \ No newline at end of file diff --git a/src/Samples/Moq.CSharp/RefOut.cs b/src/Samples/Moq.CSharp/RefOut.cs deleted file mode 100644 index d279cac5..00000000 --- a/src/Samples/Moq.CSharp/RefOut.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Diagnostics; -using Moq; -using Moq.CSharp; - -namespace Sample.CSharp -{ - public class Foo - { - public void Test() - { - var mock = Mock.Of(); - - mock.Setup(mock.TryParse) - .Returns((string input, out DateTimeOffset date) => DateTimeOffset.TryParse(input, out date)); - - var expected = DateTimeOffset.Now; - var value = expected.ToString("O"); - - Debug.Assert(mock.TryParse(value, out var actual)); - Debug.Assert(actual == expected); - } - - public void Test2() - { - var mock = Mock.Of(); - - var expected = DateTimeOffset.Now; - var value = expected.ToString("O"); - - mock.Setup(() => mock.RefOut.TryParse) - .Returns((string input, out DateTimeOffset date) => DateTimeOffset.TryParse(value, out date)); - - Debug.Assert(mock.RefOut.TryParse(value, out var actual)); - Debug.Assert(actual == expected); - } - - delegate bool TryParse(string input, out DateTimeOffset date); - } - - public interface IRefOutParent - { - IRefOut RefOut { get; } - } - - public interface IRefOut - { - bool TryParse(string input, out DateTimeOffset date); - } -} \ No newline at end of file diff --git a/src/Samples/Moq.VisualBasic/Class1.vb b/src/Samples/Moq.VisualBasic/Class1.vb deleted file mode 100644 index ac8eb0ec..00000000 --- a/src/Samples/Moq.VisualBasic/Class1.vb +++ /dev/null @@ -1,38 +0,0 @@ -Namespace Sample.CSharp - - Public Class Class1 - - Public Sub Test() - Dim formatter As ICustomFormatter = Mock.Of(Of ICustomFormatter, IDisposable) - Dim foo = Mock.Of(Of IFoo) - Dim bar = Mock.Of(Of IBar) - Dim value = "foo" - - foo.Id _ - .Callback(Sub() value = "before") _ - .Returns(Function() value) _ - .Callback(Sub() value = "after") _ - .Returns(Function() value) - - Console.WriteLine(foo.Id) - Console.WriteLine(foo.Id) - End Sub - - End Class -End Namespace - -Public Interface IBar - - Sub DoBar() - -End Interface - -Public Interface IFoo - - Sub [Do]() - - Property Id As String - - Property Title As String - -End Interface diff --git a/src/Samples/Moq.VisualBasic/FooMock.vb b/src/Samples/Moq.VisualBasic/FooMock.vb deleted file mode 100644 index 66254d83..00000000 --- a/src/Samples/Moq.VisualBasic/FooMock.vb +++ /dev/null @@ -1,139 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Imports Moq.Sdk -Imports Sample -Imports Stunts -Imports System -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports System.Runtime.CompilerServices -Imports System.Threading - -Public Class FooMock - Inherits CalculatorBase - Implements IStunt, IMocked - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - Dim _mock As IMock - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - - ReadOnly Property Mock As IMock Implements IMocked.Mock - Get - Return LazyInitializer.EnsureInitialized(_mock, (Function() New DefaultMock(Me))) - End Get - End Property - - - Public Overrides ReadOnly Property IsOn As Boolean - Get - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - End Property - - - Public Overrides Property Mode As CalculatorMode - Get - Return pipeline.Execute(Of CalculatorMode - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - Set(value As CalculatorMode) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), value)) - End Set - End Property - - - Default Public Overrides Property Item(name As String) As Integer? - Get - Return pipeline.Execute(Of Integer? - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Get - Set(value As Integer?) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name, value)) - End Set - End Property - - - Public Overrides ReadOnly Property Memory As ICalculatorMemory - Get - Return pipeline.Execute(Of ICalculatorMemory - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - End Property - - - Public Overrides Sub TurnOn() - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Sub - - - Public Overrides Sub Store(name As String, value As Integer) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name, value)) - End Sub - - - Public Overrides Sub Clear(name As String) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Sub - - - Public Overrides Function Add(x As Integer, y As Integer) As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y)) - End Function - - - Public Overrides Function Add(x As Integer, y As Integer, z As Integer) As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y, z)) - End Function - - - Public Overrides Function TryAdd(ByRef x As Integer, ByRef y As Integer, ByRef z As Integer) As Boolean - Dim returns As IMethodReturn = pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y, z)) - x = DirectCast(returns.Outputs("x"), Integer) - y = DirectCast(returns.Outputs("y"), Integer) - z = DirectCast(returns.Outputs("z"), Integer) - Return DirectCast(returns.ReturnValue, Boolean -) - End Function - - - Public Overrides Function Recall(name As String) As Integer? - Return pipeline.Execute(Of Integer? - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Function - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function -End Class diff --git a/src/Samples/Moq.VisualBasic/Mocks/CalculatorBaseIDisposableMock.vb b/src/Samples/Moq.VisualBasic/Mocks/CalculatorBaseIDisposableMock.vb deleted file mode 100644 index ab597561..00000000 --- a/src/Samples/Moq.VisualBasic/Mocks/CalculatorBaseIDisposableMock.vb +++ /dev/null @@ -1,145 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Imports Sample -Imports System -Imports System.Threading -Imports Moq.Sdk -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices - -Namespace Global.Mocks -Public Partial Class CalculatorBaseIDisposableMock - Inherits CalculatorBase - Implements IDisposable, IStunt, IMocked - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - Dim _mock As IMock - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - ReadOnly Property Mock As IMock Implements IMocked.Mock - Get - Return LazyInitializer.EnsureInitialized(_mock, (Function() New DefaultMock(Me))) - End Get - End Property - - - Public Overrides ReadOnly Property IsOn As Boolean - Get - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - End Property - - - Public Overrides Property Mode As CalculatorMode - Get - Return pipeline.Execute(Of CalculatorMode - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - Set(value As CalculatorMode) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), value)) - End Set - End Property - - - Default Public Overrides Property Item(name As String) As Integer? - Get - Return pipeline.Execute(Of Integer? - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Get - Set(value As Integer?) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name, value)) - End Set - End Property - - - Public Overrides ReadOnly Property Memory As ICalculatorMemory - Get - Return pipeline.Execute(Of ICalculatorMemory - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - End Property - - - Public Overrides Sub TurnOn() - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Sub - - - Public Overrides Sub Store(name As String, value As Integer) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name, value)) - End Sub - - - Public Overrides Sub Clear(name As String) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Sub - - - Public Sub Dispose() Implements IDisposable.Dispose - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Sub - - - Public Overrides Function Add(x As Integer, y As Integer) As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y)) - End Function - - - Public Overrides Function Add(x As Integer, y As Integer, z As Integer) As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y, z)) - End Function - - - Public Overrides Function TryAdd(ByRef x As Integer, ByRef y As Integer, ByRef z As Integer) As Boolean - Dim returns As IMethodReturn = pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y, z)) - x = DirectCast(returns.Outputs("x"), Integer) - y = DirectCast(returns.Outputs("y"), Integer) - z = DirectCast(returns.Outputs("z"), Integer) - Return DirectCast(returns.ReturnValue, Boolean -) - End Function - - - Public Overrides Function Recall(name As String) As Integer? - Return pipeline.Execute(Of Integer? - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Function - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - End Class -End Namespace diff --git a/src/Samples/Moq.VisualBasic/Mocks/IBarMock.vb b/src/Samples/Moq.VisualBasic/Mocks/IBarMock.vb deleted file mode 100644 index 55244e03..00000000 --- a/src/Samples/Moq.VisualBasic/Mocks/IBarMock.vb +++ /dev/null @@ -1,64 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Imports Moq.VisualBasic -Imports System.Threading -Imports Moq.Sdk -Imports System -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices - -Namespace Global.Mocks - - Public Partial Class IBarMock - Implements IBar, IStunt, IMocked - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - Dim _mock As IMock - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - ReadOnly Property Mock As IMock Implements IMocked.Mock - Get - Return LazyInitializer.EnsureInitialized(_mock, (Function() New DefaultMock(Me))) - End Get - End Property - - - Public Sub DoBar() Implements IBar.DoBar - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Sub - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - End Class -End Namespace diff --git a/src/Samples/Moq.VisualBasic/Mocks/ICalculatorMemoryMock.vb b/src/Samples/Moq.VisualBasic/Mocks/ICalculatorMemoryMock.vb deleted file mode 100644 index a22416c6..00000000 --- a/src/Samples/Moq.VisualBasic/Mocks/ICalculatorMemoryMock.vb +++ /dev/null @@ -1,78 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Imports Sample -Imports System.Threading -Imports Moq.Sdk -Imports System -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices - -Namespace Global.Mocks -Public Partial Class ICalculatorMemoryMock - Implements ICalculatorMemory, IStunt, IMocked - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - Dim _mock As IMock - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - ReadOnly Property Mock As IMock Implements IMocked.Mock - Get - Return LazyInitializer.EnsureInitialized(_mock, (Function() New DefaultMock(Me))) - End Get - End Property - - - Public Sub Add(value As Integer) Implements ICalculatorMemory.Add - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), value)) - End Sub - - - Public Sub Subtract(value As Integer) Implements ICalculatorMemory.Subtract - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), value)) - End Sub - - - Public Sub Clear() Implements ICalculatorMemory.Clear - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Sub - - - Public Function Recall() As Integer Implements ICalculatorMemory.Recall - Return pipeline.Execute(Of Integer)(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - End Class -End Namespace diff --git a/src/Samples/Moq.VisualBasic/Mocks/ICalculatorMock.vb b/src/Samples/Moq.VisualBasic/Mocks/ICalculatorMock.vb deleted file mode 100644 index 85d15875..00000000 --- a/src/Samples/Moq.VisualBasic/Mocks/ICalculatorMock.vb +++ /dev/null @@ -1,143 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Imports Sample -Imports System.Threading -Imports Moq.Sdk -Imports System -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices - -Namespace Global.Mocks -Public Partial Class ICalculatorMock - Implements ICalculator, IStunt, IMocked - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - Dim _mock As IMock - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - ReadOnly Property Mock As IMock Implements IMocked.Mock - Get - Return LazyInitializer.EnsureInitialized(_mock, (Function() New DefaultMock(Me))) - End Get - End Property - - - Public ReadOnly Property IsOn As Boolean Implements ICalculator.IsOn - Get - Return pipeline.Execute(Of Boolean)(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - End Property - - - Public Property Mode As CalculatorMode Implements ICalculator.Mode - Get - Return pipeline.Execute(Of CalculatorMode)(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - Set(value As CalculatorMode) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), value)) - End Set - End Property - - - Default Public Property Item(name As String) As Integer? Implements ICalculator.Item - Get - Return pipeline.Execute(Of Integer?)(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Get - Set(value As Integer?) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name, value)) - End Set - End Property - - - Public ReadOnly Property Memory As ICalculatorMemory Implements ICalculator.Memory - Get - Return pipeline.Execute(Of ICalculatorMemory)(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - End Property - - - Public Sub TurnOn() Implements ICalculator.TurnOn - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Sub - - - Public Sub Store(name As String, value As Integer) Implements ICalculator.Store - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name, value)) - End Sub - - - Public Sub Clear(name As String) Implements ICalculator.Clear - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Sub - - - Public Function Add(x As Integer, y As Integer) As Integer Implements ICalculator.Add - Return pipeline.Execute(Of Integer)(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y)) - End Function - - - Public Function Add(x As Integer, y As Integer, z As Integer) As Integer Implements ICalculator.Add - Return pipeline.Execute(Of Integer)(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y, z)) - End Function - - - Public Function TryAdd(ByRef x As Integer, ByRef y As Integer, ByRef z As Integer) As Boolean Implements ICalculator.TryAdd - Dim returns As IMethodReturn = pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y, z)) - x = DirectCast(returns.Outputs("x"), Integer) - y = DirectCast(returns.Outputs("y"), Integer) - z = DirectCast(returns.Outputs("z"), Integer) - Return DirectCast(returns.ReturnValue, Boolean) - End Function - - - Public Function Recall(name As String) As Integer? Implements ICalculator.Recall - Return pipeline.Execute(Of Integer?)(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Function - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Custom Event TurnedOn As EventHandler Implements ICalculator.TurnedOn - AddHandler(value As EventHandler) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), value)) - End AddHandler - RemoveHandler(value As EventHandler) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), value)) - End RemoveHandler - RaiseEvent(sender As Object, args As EventArgs) - End RaiseEvent - End Event - End Class -End Namespace diff --git a/src/Samples/Moq.VisualBasic/Mocks/ICustomFormatterIDisposableMock.vb b/src/Samples/Moq.VisualBasic/Mocks/ICustomFormatterIDisposableMock.vb deleted file mode 100644 index 95a92655..00000000 --- a/src/Samples/Moq.VisualBasic/Mocks/ICustomFormatterIDisposableMock.vb +++ /dev/null @@ -1,69 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Imports System -Imports System.Threading -Imports Moq.Sdk -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices - -Namespace Global.Mocks - - Public Partial Class ICustomFormatterIDisposableMock - Implements ICustomFormatter, IDisposable, IMocked, IStunt - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - - Public Sub Dispose() Implements IDisposable.Dispose - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Sub - - - Public Function Format(_format As String, arg As Object, formatProvider As IFormatProvider) As String Implements ICustomFormatter.Format - Return pipeline.Execute(Of String)(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), _format, arg, formatProvider)) - End Function - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - Dim _mock As IMock - - - ReadOnly Property Mock As IMock Implements IMocked.Mock - Get - Return LazyInitializer.EnsureInitialized(_mock, (Function() New DefaultMock(Me))) - End Get - End Property - End Class -End Namespace diff --git a/src/Samples/Moq.VisualBasic/Mocks/IEnvironmentMock.vb b/src/Samples/Moq.VisualBasic/Mocks/IEnvironmentMock.vb deleted file mode 100644 index fffbabb3..00000000 --- a/src/Samples/Moq.VisualBasic/Mocks/IEnvironmentMock.vb +++ /dev/null @@ -1,65 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Imports Moq.VisualBasic -Imports System.Threading -Imports Moq.Sdk -Imports System -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices - -Namespace Global.Mocks -Public Partial Class IEnvironmentMock - Implements IEnvironment, IStunt, IMocked - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - Dim _mock As IMock - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - ReadOnly Property Mock As IMock Implements IMocked.Mock - Get - Return LazyInitializer.EnsureInitialized(_mock, (Function() New DefaultMock(Me))) - End Get - End Property - - - Public ReadOnly Property Parser As IParser Implements IEnvironment.Parser - Get - Return pipeline.Execute(Of IParser)(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - End Property - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - End Class -End Namespace diff --git a/src/Samples/Moq.VisualBasic/Mocks/IFooMock.vb b/src/Samples/Moq.VisualBasic/Mocks/IFooMock.vb deleted file mode 100644 index 6090b2f8..00000000 --- a/src/Samples/Moq.VisualBasic/Mocks/IFooMock.vb +++ /dev/null @@ -1,83 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Imports Moq.VisualBasic -Imports System.Threading -Imports Moq.Sdk -Imports System -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices - -Namespace Global.Mocks - - Public Partial Class IFooMock - Implements IFoo, IStunt, IMocked - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - Dim _mock As IMock - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - ReadOnly Property Mock As IMock Implements IMocked.Mock - Get - Return LazyInitializer.EnsureInitialized(_mock, (Function() New DefaultMock(Me))) - End Get - End Property - - - Public Property Id As String Implements IFoo.Id - Get - Return pipeline.Execute(Of String)(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - Set(value As String) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), value)) - End Set - End Property - - - Public Property Title As String Implements IFoo.Title - Get - Return pipeline.Execute(Of String)(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - Set(value As String) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), value)) - End Set - End Property - - - Public Sub [Do]() Implements IFoo.Do - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Sub - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - End Class -End Namespace diff --git a/src/Samples/Moq.VisualBasic/Mocks/IParserMock.vb b/src/Samples/Moq.VisualBasic/Mocks/IParserMock.vb deleted file mode 100644 index 42d3c578..00000000 --- a/src/Samples/Moq.VisualBasic/Mocks/IParserMock.vb +++ /dev/null @@ -1,66 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Imports Moq.VisualBasic -Imports System.Threading -Imports Moq.Sdk -Imports System -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices -Imports System.Runtime.InteropServices - -Namespace Global.Mocks -Public Partial Class IParserMock - Implements IParser, IStunt, IMocked - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - Dim _mock As IMock - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - ReadOnly Property Mock As IMock Implements IMocked.Mock - Get - Return LazyInitializer.EnsureInitialized(_mock, (Function() New DefaultMock(Me))) - End Get - End Property - - - Public Function TryParse(input As String, ByRef result As DateTimeOffset) As Boolean Implements IParser.TryParse - Dim returns As IMethodReturn = pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), input, result)) - result = DirectCast(returns.Outputs("result"), DateTimeOffset) - Return DirectCast(returns.ReturnValue, Boolean) - End Function - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - End Class -End Namespace diff --git a/src/Samples/Moq.VisualBasic/Moq.VisualBasic.vbproj b/src/Samples/Moq.VisualBasic/Moq.VisualBasic.vbproj deleted file mode 100644 index cf893431..00000000 --- a/src/Samples/Moq.VisualBasic/Moq.VisualBasic.vbproj +++ /dev/null @@ -1,38 +0,0 @@ - - - - net471 - - - - - My Project\%(Filename)%(Extension) - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Samples/Moq.VisualBasic/My Project/Resources.Designer.vb b/src/Samples/Moq.VisualBasic/My Project/Resources.Designer.vb deleted file mode 100644 index 01351fcf..00000000 --- a/src/Samples/Moq.VisualBasic/My Project/Resources.Designer.vb +++ /dev/null @@ -1,72 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' Runtime Version:4.0.30319.42000 -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict On -Option Explicit On - -Imports System - -Namespace My.Resources - - 'This class was auto-generated by the StronglyTypedResourceBuilder - 'class via a tool like ResGen or Visual Studio. - 'To add or remove a member, edit your .ResX file then rerun ResGen - 'with the /str option, or rebuild your VS project. - ''' - ''' A strongly-typed resource class, for looking up localized strings, etc. - ''' - _ - Friend Module Resources - - Private resourceMan As Global.System.Resources.ResourceManager - - Private resourceCulture As Global.System.Globalization.CultureInfo - - ''' - ''' Returns the cached ResourceManager instance used by this class. - ''' - _ - Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager - Get - If Object.ReferenceEquals(resourceMan, Nothing) Then - Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Moq.VisualBasic.Resources", GetType(Resources).Assembly) - resourceMan = temp - End If - Return resourceMan - End Get - End Property - - ''' - ''' Overrides the current thread's CurrentUICulture property for all - ''' resource lookups using this strongly typed resource class. - ''' - _ - Friend Property Culture() As Global.System.Globalization.CultureInfo - Get - Return resourceCulture - End Get - Set - resourceCulture = value - End Set - End Property - - ''' - ''' Looks up a localized string similar to ar. - ''' - Friend ReadOnly Property foo() As String - Get - Return ResourceManager.GetString("foo", resourceCulture) - End Get - End Property - End Module -End Namespace diff --git a/src/Samples/Moq.VisualBasic/My Project/Resources.resx b/src/Samples/Moq.VisualBasic/My Project/Resources.resx deleted file mode 100644 index 37c8d941..00000000 --- a/src/Samples/Moq.VisualBasic/My Project/Resources.resx +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ar - - \ No newline at end of file diff --git a/src/Samples/Moq.VisualBasic/Recursive.vb b/src/Samples/Moq.VisualBasic/Recursive.vb deleted file mode 100644 index 2b24bfb1..00000000 --- a/src/Samples/Moq.VisualBasic/Recursive.vb +++ /dev/null @@ -1,13 +0,0 @@ -Imports Sample -Imports Moq - -Public Class Recursive - - Public Sub TestRecursive() - Dim m As CalculatorBase = Mock.Of(Of CalculatorBase, IDisposable) - - m.Setup(Function(x) x.Memory.Recall()).Returns(5) - - End Sub - -End Class \ No newline at end of file diff --git a/src/Samples/Moq.VisualBasic/RefOut.vb b/src/Samples/Moq.VisualBasic/RefOut.vb deleted file mode 100644 index d7d973c3..00000000 --- a/src/Samples/Moq.VisualBasic/RefOut.vb +++ /dev/null @@ -1,41 +0,0 @@ -Imports System.Runtime.InteropServices -Imports Moq - -Namespace Test - - Public Class Foo - - Public Sub Test() - Dim parser = Mock.Of(Of IParser) - - parser.Setup(Of TryParse)(AddressOf parser.TryParse) _ - .Returns(Function(input As String, ByRef result As DateTimeOffset) DateTimeOffset.TryParse(input, result)) - - Dim expected = DateTimeOffset.Now - Dim value = expected.ToString("O") - Dim actual As DateTimeOffset - - Debug.Assert(parser.TryParse(value, actual)) - Debug.Assert(actual = expected) - - End Sub - - Public Sub Test2() - Dim target = Mock.Of(Of IEnvironment) - - Dim expected = DateTimeOffset.Now - Dim value = expected.ToString("O") - Dim actual As DateTimeOffset - - target.Setup(Of TryParse)(Function() AddressOf target.Parser.TryParse) _ - .Returns(Function(input As String, ByRef result As DateTimeOffset) DateTimeOffset.TryParse(input, result)) - - Debug.Assert(target.Parser.TryParse(value, actual)) - Debug.Assert(actual = expected) - - End Sub - - Delegate Function TryParse(input As String, ByRef result As DateTimeOffset) As Boolean - End Class - -End Namespace \ No newline at end of file diff --git a/src/Samples/Sample/AssemblyInfo.cs b/src/Samples/Sample/AssemblyInfo.cs deleted file mode 100644 index 672d9b06..00000000 --- a/src/Samples/Sample/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Stunts.Tests")] \ No newline at end of file diff --git a/src/Samples/Sample/Calculator.cs b/src/Samples/Sample/Calculator.cs deleted file mode 100644 index a4c5d073..00000000 --- a/src/Samples/Sample/Calculator.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Sample -{ - public class Calculator : ICalculator, IDisposable - { - CalculatorMemory memory = new CalculatorMemory(); - Dictionary namedMemory = new Dictionary(); - - public virtual event EventHandler TurnedOn; - - public bool TurnOnCalled { get; set; } - - public virtual bool IsOn { get; private set; } - - public virtual CalculatorMode Mode { get; set; } - - public virtual int Add(int x, int y) => x + y; - - public virtual int Add(int x, int y, int z) => x + y + z; - - public virtual void TurnOn() - { - TurnedOn?.Invoke(this, EventArgs.Empty); - IsOn = true; - TurnOnCalled = true; - } - - public virtual int? this[string name] - { - get => Recall(name); - set - { - if (value == null) - namedMemory.Remove(name); - else - Store(name, value.Value); - } - } - - public virtual void Clear(string name) => namedMemory.Remove(name ?? "null"); - - public virtual int? Recall(string name) => (namedMemory.TryGetValue(name ?? "null", out int i)) ? i : default(int?); - - public virtual void Store(string name, int value) => namedMemory[name ?? "null"] = value; - - public virtual bool TryAdd(ref int x, ref int y, out int z) - { - z = x + y; - return true; - } - - public virtual void Dispose() => namedMemory.Clear(); - - public virtual ICalculatorMemory Memory { get => memory; } - } -} \ No newline at end of file diff --git a/src/Samples/Sample/CalculatorBase.cs b/src/Samples/Sample/CalculatorBase.cs deleted file mode 100644 index e855a5a7..00000000 --- a/src/Samples/Sample/CalculatorBase.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; - -namespace Sample -{ - public abstract class CalculatorBase - { -#pragma warning disable CS0067 - public virtual event EventHandler TurnedOn; -#pragma warning restore CS0067 - - public abstract bool IsOn { get; } - - public abstract CalculatorMode Mode { get; set; } - - public abstract int Add(int x, int y); - - public abstract int Add(int x, int y, int z); - - public abstract bool TryAdd(ref int x, ref int y, out int z); - - public abstract void TurnOn(); - - public abstract int? this[string name] { get; set; } - - public abstract void Store(string name, int value); - - public abstract int? Recall(string name); - - public abstract void Clear(string name); - - public abstract ICalculatorMemory Memory { get; } - } -} \ No newline at end of file diff --git a/src/Samples/Sample/CalculatorClassStunt.cs b/src/Samples/Sample/CalculatorClassStunt.cs deleted file mode 100644 index 09c39f3f..00000000 --- a/src/Samples/Sample/CalculatorClassStunt.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; - -namespace Sample -{ - public class CalculatorClassStunt : Calculator, IStunt - { - BehaviorPipeline pipeline = new BehaviorPipeline(); - - public ObservableCollection Behaviors => pipeline.Behaviors; - - public override event EventHandler TurnedOn - { - add => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value), (m, n) => { base.TurnedOn += value; return m.CreateValueReturn(null, value); }); - remove => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value), (m, n) => { base.TurnedOn -= value; return m.CreateValueReturn(null, value); }); - } - - public override CalculatorMode Mode - { - get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod()), (m, n) => m.CreateValueReturn(base.Mode)); - set => pipeline.Invoke(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value), (m, n) => { base.Mode = value; return m.CreateValueReturn(null, value); }); - } - - public override int? this[string name] - { - get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod()), (m, n) => m.CreateValueReturn(base[name])); - set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value), (m, n) => { base[name] = value; return m.CreateValueReturn(null, value); }); - } - - public override bool IsOn => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod()), (m, n) => m.CreateValueReturn(base.IsOn)); - - public override int Add(int x, int y) => - pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y), (m, n) => m.CreateValueReturn(base.Add(x, y), x, y)); - - public override int Add(int x, int y, int z) => - pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z), (m, n) => m.CreateValueReturn(base.Add(x, y, z), x, y, z)); - - public override bool TryAdd(ref int x, ref int y, out int z) - { - z = default(int); - var local_x = x; - var local_y = y; - var local_z = z; - - var result = pipeline.Invoke(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z), - (m, n) => m.CreateValueReturn(base.TryAdd(ref local_x, ref local_y, out local_z), local_x, local_y, local_z), true); - - x = (int)result.Outputs["x"]; - y = (int)result.Outputs["y"]; - z = (int)result.Outputs["z"]; - - return (bool)result.ReturnValue; - } - - public override void TurnOn() => - pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod()), (m, n) => { base.TurnOn(); return m.CreateValueReturn(null); }); - - public override void Store(string name, int value) => - pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value), (m, n) => { base.Store(name, value); return m.CreateValueReturn(null, name, value); }); - - public override int? Recall(string name) => - pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name), (m, n) => m.CreateValueReturn(base.Recall(name), name)); - - public override void Clear(string name) => - pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name), (m, n) => { base.Clear(name); return m.CreateValueReturn(null, name); }); - - public override ICalculatorMemory Memory - { - get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod()), (m, n) => m.CreateValueReturn(base.Memory)); - } - } -} \ No newline at end of file diff --git a/src/Samples/Sample/CalculatorInterfaceStunt.cs b/src/Samples/Sample/CalculatorInterfaceStunt.cs deleted file mode 100644 index 76826d3c..00000000 --- a/src/Samples/Sample/CalculatorInterfaceStunt.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; - -namespace Sample -{ - public class CalculatorInterfaceStunt : ICalculator, IDisposable, IStunt - { - BehaviorPipeline pipeline = new BehaviorPipeline(); - - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - public event EventHandler TurnedOn - { - add => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - remove => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } - - public bool IsOn - { - get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } - - public CalculatorMode Mode - { - get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); - } - - public int? this[string name] - { - get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); - } - - public int Add(int x, int y) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y)); - - public int Add(int x, int y, int z) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - - public bool TryAdd(ref int x, ref int y, out int z) - { - z = default(int); - var returns = pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - - x = (int)returns.Outputs["x"]; - y = (int)returns.Outputs["y"]; - z = (int)returns.Outputs["z"]; - - return (bool)returns.ReturnValue; - } - - public void TurnOn() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - public void Store(string name, int value) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); - - public int? Recall(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - - public void Clear(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - - public void Dispose() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - public ICalculatorMemory Memory - { - get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } - } -} diff --git a/src/Samples/Sample/CalculatorMemory.cs b/src/Samples/Sample/CalculatorMemory.cs deleted file mode 100644 index 818a0f0a..00000000 --- a/src/Samples/Sample/CalculatorMemory.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Sample -{ - public class CalculatorMemory : ICalculatorMemory - { - int memory; - - public virtual void Add(int value) => memory += value; - - public virtual void Clear() => memory = 0; - - public virtual int Recall() => memory; - - public virtual void Subtract(int value) => memory -= value; - } -} diff --git a/src/Samples/Sample/CalculatorMemoryBase.cs b/src/Samples/Sample/CalculatorMemoryBase.cs deleted file mode 100644 index 925d53f5..00000000 --- a/src/Samples/Sample/CalculatorMemoryBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Sample -{ - public abstract class CalculatorMemoryBase : ICalculatorMemory - { - public abstract void Add(int value); - - public abstract void Clear(); - - public abstract int Recall(); - - public abstract void Subtract(int value); - } -} diff --git a/src/Samples/Sample/CalculatorMode.cs b/src/Samples/Sample/CalculatorMode.cs deleted file mode 100644 index fbcac70a..00000000 --- a/src/Samples/Sample/CalculatorMode.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Sample -{ - public enum CalculatorMode - { - Standard, - Scientific - } -} \ No newline at end of file diff --git a/src/Samples/Sample/ICalculator.cs b/src/Samples/Sample/ICalculator.cs deleted file mode 100644 index d7d37ad0..00000000 --- a/src/Samples/Sample/ICalculator.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; - -namespace Sample -{ - public interface ICalculator - { - event EventHandler TurnedOn; - - bool IsOn { get; } - - CalculatorMode Mode { get; set; } - - int Add(int x, int y); - - int Add(int x, int y, int z); - - bool TryAdd(ref int x, ref int y, out int z); - - void TurnOn(); - - int? this[string name] { get; set; } - - void Store(string name, int value); - - int? Recall(string name); - - void Clear(string name); - - ICalculatorMemory Memory { get; } - } -} \ No newline at end of file diff --git a/src/Samples/Sample/ICalculatorMemory.cs b/src/Samples/Sample/ICalculatorMemory.cs deleted file mode 100644 index 4ed2af36..00000000 --- a/src/Samples/Sample/ICalculatorMemory.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Sample -{ - public interface ICalculatorMemory - { - void Add(int value); - - void Subtract(int value); - - void Clear(); - - int Recall(); - } -} diff --git a/src/Samples/Sample/Sample.csproj b/src/Samples/Sample/Sample.csproj deleted file mode 100644 index d2bd80fc..00000000 --- a/src/Samples/Sample/Sample.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - netstandard2.0 - - - - - \ No newline at end of file diff --git a/src/Samples/Samples.sln b/src/Samples/Samples.sln deleted file mode 100644 index 0b0d3ec7..00000000 --- a/src/Samples/Samples.sln +++ /dev/null @@ -1,74 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2010 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stunts.CSharp", "Stunts.CSharp\Stunts.CSharp.csproj", "{2ECBF73E-266C-4124-A1D9-8BD9917DA0D9}" -EndProject -Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Stunts.VisualBasic", "Stunts.VisualBasic\Stunts.VisualBasic.vbproj", "{4FB91327-EE2B-4912-B4E0-211D3AC855F1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.CSharp", "Moq.CSharp\Moq.CSharp.csproj", "{D37B0764-9385-450B-96D3-38296BD2C50E}" -EndProject -Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Moq.VisualBasic", "Moq.VisualBasic\Moq.VisualBasic.vbproj", "{82E587FD-CD00-4007-B37D-AFE92F685689}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample", "Sample\Sample.csproj", "{2C21C0D3-E461-4484-B2AC-91A9C5772325}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{DC06C5F4-4D4B-456B-8BA7-A20B3599701E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stunts", "..\Stunts\Stunts\Stunts.csproj", "{4050B6B5-E06E-4F13-8DE7-D97747059841}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.Sdk", "..\Moq\Moq.Sdk\Moq.Sdk.csproj", "{39BB8D00-B6E8-417A-85E3-73996B13208F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq", "..\Moq\Moq\Moq.csproj", "{579C5F30-3E7E-4688-809F-5238156475B5}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2ECBF73E-266C-4124-A1D9-8BD9917DA0D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2ECBF73E-266C-4124-A1D9-8BD9917DA0D9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2ECBF73E-266C-4124-A1D9-8BD9917DA0D9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2ECBF73E-266C-4124-A1D9-8BD9917DA0D9}.Release|Any CPU.Build.0 = Release|Any CPU - {4FB91327-EE2B-4912-B4E0-211D3AC855F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4FB91327-EE2B-4912-B4E0-211D3AC855F1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4FB91327-EE2B-4912-B4E0-211D3AC855F1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4FB91327-EE2B-4912-B4E0-211D3AC855F1}.Release|Any CPU.Build.0 = Release|Any CPU - {D37B0764-9385-450B-96D3-38296BD2C50E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D37B0764-9385-450B-96D3-38296BD2C50E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D37B0764-9385-450B-96D3-38296BD2C50E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D37B0764-9385-450B-96D3-38296BD2C50E}.Release|Any CPU.Build.0 = Release|Any CPU - {82E587FD-CD00-4007-B37D-AFE92F685689}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {82E587FD-CD00-4007-B37D-AFE92F685689}.Debug|Any CPU.Build.0 = Debug|Any CPU - {82E587FD-CD00-4007-B37D-AFE92F685689}.Release|Any CPU.ActiveCfg = Release|Any CPU - {82E587FD-CD00-4007-B37D-AFE92F685689}.Release|Any CPU.Build.0 = Release|Any CPU - {2C21C0D3-E461-4484-B2AC-91A9C5772325}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2C21C0D3-E461-4484-B2AC-91A9C5772325}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2C21C0D3-E461-4484-B2AC-91A9C5772325}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2C21C0D3-E461-4484-B2AC-91A9C5772325}.Release|Any CPU.Build.0 = Release|Any CPU - {4050B6B5-E06E-4F13-8DE7-D97747059841}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4050B6B5-E06E-4F13-8DE7-D97747059841}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4050B6B5-E06E-4F13-8DE7-D97747059841}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4050B6B5-E06E-4F13-8DE7-D97747059841}.Release|Any CPU.Build.0 = Release|Any CPU - {39BB8D00-B6E8-417A-85E3-73996B13208F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {39BB8D00-B6E8-417A-85E3-73996B13208F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {39BB8D00-B6E8-417A-85E3-73996B13208F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {39BB8D00-B6E8-417A-85E3-73996B13208F}.Release|Any CPU.Build.0 = Release|Any CPU - {579C5F30-3E7E-4688-809F-5238156475B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {579C5F30-3E7E-4688-809F-5238156475B5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {579C5F30-3E7E-4688-809F-5238156475B5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {579C5F30-3E7E-4688-809F-5238156475B5}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {4050B6B5-E06E-4F13-8DE7-D97747059841} = {DC06C5F4-4D4B-456B-8BA7-A20B3599701E} - {39BB8D00-B6E8-417A-85E3-73996B13208F} = {DC06C5F4-4D4B-456B-8BA7-A20B3599701E} - {579C5F30-3E7E-4688-809F-5238156475B5} = {DC06C5F4-4D4B-456B-8BA7-A20B3599701E} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {FB034936-6446-4000-877B-DB0D9E9F0555} - EndGlobalSection -EndGlobal diff --git a/src/Samples/Stunts.CSharp/Class1.cs b/src/Samples/Stunts.CSharp/Class1.cs deleted file mode 100644 index 00cb522d..00000000 --- a/src/Samples/Stunts.CSharp/Class1.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using Sample; -using System.Linq; -using Stunts; -using System.Reflection; - -public class Tests -{ - public void WhenFakingCalculatorBase() - { - var fake = Stunt.Of(); - } - - public void WhenFakingFormatterThenCanInvokeIt() - { - var stunt1 = Stunt.Of(); - var stunt2 = Stunt.Of(); - - stunt1.AddBehavior(new DefaultValueBehavior()); - stunt1.InsertBehavior(0, - (m, n) => m.CreateValueReturn(string.Format((string)m.Arguments[0], m.Arguments.Skip(1).ToArray())), - m => m.MethodBase.Name == nameof(ICustomFormatter.Format), - "Format"); - - stunt2.AddBehavior(new DefaultValueBehavior()); - - var result1 = stunt1.Format("Hello {0}", "World", null); - var result2 = stunt2.Format("Hello {0}", "World", null); - - Console.WriteLine(result1); - Console.WriteLine(result2); - - var bar = Stunt.Of(); - } - - public void when_using_custom_generator() - { - var ping = Randomizer.Of(); - - Console.WriteLine(ping.Ping()); - Console.WriteLine(ping.Ping()); - } -} - -public interface IPing -{ - int Ping(); -} - -public static class Randomizer -{ - static readonly Random random = new Random(); - - [StuntGenerator] - public static T Of() - => Stunt.Of() - .AddBehavior( - (invocation, next) => invocation.CreateValueReturn(random.Next()), - invocation => invocation.MethodBase is MethodInfo info && info.ReturnType == typeof(int)); -} - - - -namespace Sample -{ - public interface IBar - { - void Bar(); - } - - public interface IFoo - { - void Do(); - - int Bar(); - } -} diff --git a/src/Samples/Stunts.CSharp/FooStunt.cs b/src/Samples/Stunts.CSharp/FooStunt.cs deleted file mode 100644 index 305499bd..00000000 --- a/src/Samples/Stunts.CSharp/FooStunt.cs +++ /dev/null @@ -1,78 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; -using Sample; -using System.Collections.ObjectModel; - -namespace Stunts.CSharp -{ - class FooStunt : CalculatorBase, IStunt, IDisposable, IServiceProvider - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - - [CompilerGenerated] - public override int? this[string name] { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); } - - [CompilerGenerated] - public override bool IsOn => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override CalculatorMode Mode { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - - [CompilerGenerated] - public override ICalculatorMemory Memory => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - [CompilerGenerated] - public override int Add(int x, int y) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y)); - [CompilerGenerated] - public override int Add(int x, int y, int z) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - [CompilerGenerated] - public override void Clear(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override int? Recall(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - [CompilerGenerated] - public override void Store(string name, int value) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override bool TryAdd(ref int x, ref int y, out int z) - { - z = default(int); - IMethodReturn returns = pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - x = (int)returns.Outputs["x"]; - y = (int)returns.Outputs["y"]; - z = (int)returns.Outputs["z"]; - return (bool)returns.ReturnValue; - } - - [CompilerGenerated] - public override void TurnOn() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public void Dispose() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public object GetService(Type serviceType) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), serviceType)); - - [CompilerGenerated] - public override event EventHandler TurnedOn { add => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); remove => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - } -} diff --git a/src/Samples/Stunts.CSharp/MyClass.cs b/src/Samples/Stunts.CSharp/MyClass.cs deleted file mode 100644 index c264a8f5..00000000 --- a/src/Samples/Stunts.CSharp/MyClass.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.Reflection; - -using Stunts; - -public class MyBase { } - -public class MyClassTest -{ - public void Configure() - { - // var instance = new MyClass(); - - var cloneable = Stunt.Of(); - - } -} - -public class MyClass : IDisposable, IStunt -{ - private readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - public void Dispose() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); -} - -//[CompilerGenerated] -//public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); -//[CompilerGenerated] -//public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); -//[CompilerGenerated] -//public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); diff --git a/src/Samples/Stunts.CSharp/MyProxy.cs b/src/Samples/Stunts.CSharp/MyProxy.cs deleted file mode 100644 index 9e383192..00000000 --- a/src/Samples/Stunts.CSharp/MyProxy.cs +++ /dev/null @@ -1,34 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using Sample; -using Stunts; -using System.Collections.ObjectModel; -using System.Reflection; -using System.Runtime.CompilerServices; - -public class MyProxy : IDisposable, IBar, IStunt -{ - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - [CompilerGenerated] - public void Bar() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public void Dispose() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); -} diff --git a/src/Samples/Stunts.CSharp/Stunts.CSharp.csproj b/src/Samples/Stunts.CSharp/Stunts.CSharp.csproj deleted file mode 100644 index 5b8edb57..00000000 --- a/src/Samples/Stunts.CSharp/Stunts.CSharp.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - net471 - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Samples/Stunts.CSharp/Stunts/CalculatorBaseStunt.cs b/src/Samples/Stunts.CSharp/Stunts/CalculatorBaseStunt.cs deleted file mode 100644 index eade5f5d..00000000 --- a/src/Samples/Stunts.CSharp/Stunts/CalculatorBaseStunt.cs +++ /dev/null @@ -1,72 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; -using Sample; - -namespace Stunts -{ - public partial class CalculatorBaseStunt : CalculatorBase, IStunt - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - [CompilerGenerated] - public override int? this[string name] { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); } - - [CompilerGenerated] - public override bool IsOn => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override CalculatorMode Mode { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - - [CompilerGenerated] - public override ICalculatorMemory Memory => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override int Add(int x, int y) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y)); - [CompilerGenerated] - public override int Add(int x, int y, int z) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - [CompilerGenerated] - public override void Clear(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override int? Recall(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - [CompilerGenerated] - public override void Store(string name, int value) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override bool TryAdd(ref int x, ref int y, out int z) - { - z = default(int); - IMethodReturn returns = pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - x = (int)returns.Outputs["x"]; - y = (int)returns.Outputs["y"]; - z = (int)returns.Outputs["z"]; - return (bool)returns.ReturnValue; - } - - [CompilerGenerated] - public override void TurnOn() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public override event EventHandler TurnedOn { add => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); remove => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - } -} \ No newline at end of file diff --git a/src/Samples/Stunts.CSharp/Stunts/IBarStunt.cs b/src/Samples/Stunts.CSharp/Stunts/IBarStunt.cs deleted file mode 100644 index 6f977eb8..00000000 --- a/src/Samples/Stunts.CSharp/Stunts/IBarStunt.cs +++ /dev/null @@ -1,35 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using Sample; -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Stunts -{ - public partial class IBarStunt : IBar, IStunt - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - [CompilerGenerated] - public void Bar() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } -} \ No newline at end of file diff --git a/src/Samples/Stunts.CSharp/Stunts/ICalculatorStunt.cs b/src/Samples/Stunts.CSharp/Stunts/ICalculatorStunt.cs deleted file mode 100644 index 00b0431a..00000000 --- a/src/Samples/Stunts.CSharp/Stunts/ICalculatorStunt.cs +++ /dev/null @@ -1,72 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using Sample; -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Stunts -{ - public partial class ICalculatorStunt : ICalculator, IStunt - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - [CompilerGenerated] - public int? this[string name] { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); } - - [CompilerGenerated] - public bool IsOn => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public CalculatorMode Mode { get => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); set => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - - [CompilerGenerated] - public ICalculatorMemory Memory => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public int Add(int x, int y) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y)); - [CompilerGenerated] - public int Add(int x, int y, int z) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - [CompilerGenerated] - public void Clear(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public int? Recall(string name) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name)); - [CompilerGenerated] - public void Store(string name, int value) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), name, value)); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public bool TryAdd(ref int x, ref int y, out int z) - { - z = default(int); - var returns = pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), x, y, z)); - x = (int)returns.Outputs["x"]; - y = (int)returns.Outputs["y"]; - z = (int)returns.Outputs["z"]; - return (bool)returns.ReturnValue; - } - - [CompilerGenerated] - public void TurnOn() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - - [CompilerGenerated] - public event EventHandler TurnedOn { add => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); remove => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), value)); } - } -} \ No newline at end of file diff --git a/src/Samples/Stunts.CSharp/Stunts/ICloneableStunt.cs b/src/Samples/Stunts.CSharp/Stunts/ICloneableStunt.cs deleted file mode 100644 index a7300c7b..00000000 --- a/src/Samples/Stunts.CSharp/Stunts/ICloneableStunt.cs +++ /dev/null @@ -1,34 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Stunts -{ - public partial class ICloneableStunt : ICloneable, IStunt - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - - [CompilerGenerated] - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - [CompilerGenerated] - public object Clone() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - [CompilerGenerated] - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - [CompilerGenerated] - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } -} \ No newline at end of file diff --git a/src/Samples/Stunts.CSharp/Stunts/ICustomFormatterIDisposableStunt.cs b/src/Samples/Stunts.CSharp/Stunts/ICustomFormatterIDisposableStunt.cs deleted file mode 100644 index 2e03a5cd..00000000 --- a/src/Samples/Stunts.CSharp/Stunts/ICustomFormatterIDisposableStunt.cs +++ /dev/null @@ -1,30 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Stunts -{ - public partial class ICustomFormatterIDisposableStunt : ICustomFormatter, IDisposable, IStunt - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - public void Dispose() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - public string Format(string format, object arg, IFormatProvider formatProvider) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), format, arg, formatProvider)); - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } -} \ No newline at end of file diff --git a/src/Samples/Stunts.CSharp/Stunts/ICustomFormatterStunt.cs b/src/Samples/Stunts.CSharp/Stunts/ICustomFormatterStunt.cs deleted file mode 100644 index 56cd7a42..00000000 --- a/src/Samples/Stunts.CSharp/Stunts/ICustomFormatterStunt.cs +++ /dev/null @@ -1,29 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using System.Collections.ObjectModel; -using System.Reflection; -using Stunts; -using System.Runtime.CompilerServices; - -namespace Stunts -{ - public partial class ICustomFormatterStunt : ICustomFormatter, IStunt - { - readonly BehaviorPipeline pipeline = new BehaviorPipeline(); - - ObservableCollection IStunt.Behaviors => pipeline.Behaviors; - - public override bool Equals(object obj) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), obj)); - public string Format(string format, object arg, IFormatProvider formatProvider) => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod(), format, arg, formatProvider)); - public override int GetHashCode() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - public override string ToString() => pipeline.Execute(new MethodInvocation(this, MethodBase.GetCurrentMethod())); - } -} \ No newline at end of file diff --git a/src/Samples/Stunts.VisualBasic/Class1.vb b/src/Samples/Stunts.VisualBasic/Class1.vb deleted file mode 100644 index cee8bf89..00000000 --- a/src/Samples/Stunts.VisualBasic/Class1.vb +++ /dev/null @@ -1,14 +0,0 @@ -Imports Sample - -Public Class Class1 - Public Sub New() - Dim stunt1 As ICustomFormatter = Stunt.Of(Of ICustomFormatter) - Dim stunt2 As ICustomFormatter = Stunt.Of(Of ICustomFormatter) - - Dim result1 As String = stunt1.Format("Hello {0}", "World", Nothing) - Dim result2 As String = stunt2.Format("Hello {0}", "World", Nothing) - - Dim calculator As ICalculator = CType(Stunt.Of(Of CalculatorBase), ICalculator) - - End Sub -End Class diff --git a/src/Samples/Stunts.VisualBasic/FooStunt.vb b/src/Samples/Stunts.VisualBasic/FooStunt.vb deleted file mode 100644 index 16eb0a5b..00000000 --- a/src/Samples/Stunts.VisualBasic/FooStunt.vb +++ /dev/null @@ -1,50 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Imports System -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices - -Public Class FooStunt - Implements IStunt, IDisposable - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - - Public Sub Dispose() Implements IDisposable.Dispose - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Sub - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function -End Class \ No newline at end of file diff --git a/src/Samples/Stunts.VisualBasic/Stunts.VisualBasic.vbproj b/src/Samples/Stunts.VisualBasic/Stunts.VisualBasic.vbproj deleted file mode 100644 index cefbf587..00000000 --- a/src/Samples/Stunts.VisualBasic/Stunts.VisualBasic.vbproj +++ /dev/null @@ -1,29 +0,0 @@ - - - - net471 - On - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Samples/Stunts.VisualBasic/Stunts/CalculatorBaseStunt.vb b/src/Samples/Stunts.VisualBasic/Stunts/CalculatorBaseStunt.vb deleted file mode 100644 index ef874053..00000000 --- a/src/Samples/Stunts.VisualBasic/Stunts/CalculatorBaseStunt.vb +++ /dev/null @@ -1,132 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Imports Sample -Imports System -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices - -Namespace Global.Stunts - - Public Partial Class CalculatorBaseStunt - Inherits CalculatorBase - - Implements IStunt - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - - Public Overrides ReadOnly Property IsOn As Boolean - Get - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - End Property - - - Public Overrides Property Mode As CalculatorMode - Get - Return pipeline.Execute(Of CalculatorMode - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - Set(value As CalculatorMode) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), value)) - End Set - End Property - - - Default Public Overrides Property Item(name As String) As Integer? - Get - Return pipeline.Execute(Of Integer? - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Get - Set(value As Integer?) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name, value)) - End Set - End Property - - - Public Overrides ReadOnly Property Memory As ICalculatorMemory - Get - Return pipeline.Execute(Of ICalculatorMemory - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Get - End Property - - - Public Overrides Sub TurnOn() - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Sub - - - Public Overrides Sub Store(name As String, value As Integer) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name, value)) - End Sub - - - Public Overrides Sub Clear(name As String) - pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Sub - - - Public Overrides Function Add(x As Integer, y As Integer) As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y)) - End Function - - - Public Overrides Function Add(x As Integer, y As Integer, z As Integer) As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y, z)) - End Function - - - Public Overrides Function TryAdd(ByRef x As Integer, ByRef y As Integer, ByRef z As Integer) As Boolean - Dim returns As IMethodReturn = pipeline.Execute(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), x, y, z)) - x = DirectCast(returns.Outputs("x"), Integer) - y = DirectCast(returns.Outputs("y"), Integer) - z = DirectCast(returns.Outputs("z"), Integer) - Return DirectCast(returns.ReturnValue, Boolean -) - End Function - - - Public Overrides Function Recall(name As String) As Integer? - Return pipeline.Execute(Of Integer? - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), name)) - End Function - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - End Class -End Namespace diff --git a/src/Samples/Stunts.VisualBasic/Stunts/ICustomFormatterStunt.vb b/src/Samples/Stunts.VisualBasic/Stunts/ICustomFormatterStunt.vb deleted file mode 100644 index ef611684..00000000 --- a/src/Samples/Stunts.VisualBasic/Stunts/ICustomFormatterStunt.vb +++ /dev/null @@ -1,53 +0,0 @@ -'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Imports System -Imports System.Collections.ObjectModel -Imports System.Reflection -Imports Stunts -Imports System.Runtime.CompilerServices - -Namespace Global.Stunts - - Public Partial Class ICustomFormatterStunt - Implements ICustomFormatter, IStunt - - ReadOnly pipeline As BehaviorPipeline = New BehaviorPipeline() - - - ReadOnly Property Behaviors As ObservableCollection(Of IStuntBehavior) Implements IStunt.Behaviors - Get - Return pipeline.Behaviors - End Get - End Property - - - Public Function Format(_format As String, arg As Object, formatProvider As IFormatProvider) As String Implements ICustomFormatter.Format - Return pipeline.Execute(Of String)(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), _format, arg, formatProvider)) - End Function - - - Public Overrides Function ToString() As String - Return pipeline.Execute(Of String - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - - - Public Overrides Function Equals(obj As Object) As Boolean - Return pipeline.Execute(Of Boolean - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod(), obj)) - End Function - - - Public Overrides Function GetHashCode() As Integer - Return pipeline.Execute(Of Integer - )(New MethodInvocation(Me, MethodBase.GetCurrentMethod())) - End Function - End Class -End Namespace diff --git a/src/Stunts/Stunts.AcceptanceTests/AcceptanceTests.cs b/src/Stunts/Stunts.AcceptanceTests/AcceptanceTests.cs deleted file mode 100644 index d8ff84b6..00000000 --- a/src/Stunts/Stunts.AcceptanceTests/AcceptanceTests.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using System.Web.Http.Tracing; -using Microsoft.CodeAnalysis; -using Xunit; -using Xunit.Abstractions; - -namespace Moq.Proxy -{ - public class AcceptanceTests : IClassFixture - { - ITestOutputHelper output; - AcceptanceTestsContext context; - - public AcceptanceTests(ITestOutputHelper output, AcceptanceTestsContext context) - { - this.context = context; - this.output = output; - } - - public static int AsyncTimeoutMilliseconds => Debugger.IsAttached ? int.MaxValue : 5000; - - [InlineData(LanguageNames.CSharp)] - [InlineData(LanguageNames.VisualBasic)] - [Theory] - public Task CanGenerateSpecific(string languageName) - => CanGenerateAllProxies(languageName, typeof(ITraceWriter), 0); - - [Trait("LongRunning", "true")] - [MemberData(nameof(GetTypesToMock))] - [Theory] - public async Task CanGenerateAllProxies(string language, Type type, int index) - { - var project = context.GetProject(language); - var compilation = await context.GetCompilationAsync(language, new CancellationTokenSource(AsyncTimeoutMilliseconds).Token); - - if (compilation.GetDiagnostics().Any(d => d.Severity == DiagnosticSeverity.Error)) - { - Assert.False(true, - Environment.NewLine + - string.Join(Environment.NewLine, compilation - .GetDiagnostics() - .Where(d => d.Severity == DiagnosticSeverity.Error) - .Select(d => d.ToString()))); - } - - var typeName = type.FullName; - var symbol = compilation.GetTypeByMetadataName(type.FullName); - - if (symbol != null) - { - var document = await new ProxyGenerator().GenerateProxyAsync( - context.Workspace, - project, - new CancellationTokenSource(AsyncTimeoutMilliseconds).Token, - symbol); - - var syntax = await document.GetSyntaxRootAsync(new CancellationTokenSource(AsyncTimeoutMilliseconds).Token); - document = project.AddDocument("proxy." + (language == LanguageNames.CSharp ? "cs" : "vb"), syntax, filePath: Path.GetTempFileName()); - - await AssertCode.NoErrorsAsync(document); - } - } - - static IEnumerable GetTypesToMock() => ReferencePaths.Paths - // Some CodeAnalysis types have dependencies on editor/langsvc assemblies - .Where(path => !path.EndsWith("mscorlib.dll") && !Path.GetFileName(path).StartsWith("Microsoft.CodeAnalysis")) - .Select(path => Assembly.ReflectionOnlyLoadFrom(path)) - .SelectMany(asm => TryGetExportedTypes(asm) - .Where(x => x.IsInterface && !x.IsGenericTypeDefinition && !typeof(Delegate).IsAssignableFrom(x) - // Hard-coded exclusions we know don't work - && !x.GetCustomAttributesData().Any(d => d.AttributeType == typeof(ObsoleteAttribute)) // Obsolete types could generate build errors - && x.Name[0] != '_' // These are sort of internal... - && x.FullName != typeof(ITraceWriter).FullName // This one fails when running all, but not individually. Seems a fusion/binding error. - && x.FullName != typeof(IProxy).FullName - ) - ) -#if QUICK - .Take(1) -#endif - //.Where(x => - // x.FullName == "System.Web.Http.Controllers.IActionHttpMethodProvider" - // || x.FullName == "System.Net.Http.Formatting.IContentNegotiator" - //) - .SelectMany((x, i) => new object[][] - { - new object[] { LanguageNames.CSharp, x, i }, - new object[] { LanguageNames.VisualBasic, x, i }, - }); - - static Type[] TryGetExportedTypes(Assembly assembly) - { - try - { - return assembly.GetExportedTypes(); - } - catch - { - return new Type[0]; - } - } - - static AcceptanceTests() - { - AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (sender, args) => - { - var name = new AssemblyName(args.Name); - var file = name.Name + ".dll"; - var path = ReferencePaths.Paths.FirstOrDefault(x => x.EndsWith(file)); - if (path != null) - return Assembly.ReflectionOnlyLoadFrom(path); - - Assert.False(true, $"Failed to resolve {args.Name}."); - return null; - }; - } - } -} diff --git a/src/Stunts/Stunts.AcceptanceTests/AcceptanceTestsContext.cs b/src/Stunts/Stunts.AcceptanceTests/AcceptanceTestsContext.cs deleted file mode 100644 index 87f74816..00000000 --- a/src/Stunts/Stunts.AcceptanceTests/AcceptanceTestsContext.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.VisualBasic; -using static TestHelpers; - -namespace Moq.Proxy -{ - public class AcceptanceTestsContext : IDisposable - { - static readonly AdhocWorkspace workspace = new AdhocWorkspace(ProxyGenerator.CreateHost()); - //The location of the .NET assemblies - static readonly string frameworkPath = Path.GetDirectoryName(typeof(object).Assembly.Location); - static readonly MetadataReference[] references = new[] - { - Path.Combine(frameworkPath, "mscorlib.dll"), - Path.Combine(frameworkPath, "System.dll"), - Path.Combine(frameworkPath, "System.Core.dll"), - Path.Combine(frameworkPath, "System.ObjectModel.dll"), - Path.Combine(frameworkPath, "System.Reflection.dll"), - Path.Combine(frameworkPath, "System.Runtime.dll"), - } - .Concat(ReferencePaths.Paths) - .Where(path => !string.IsNullOrEmpty(path) && File.Exists(path)) - .Distinct(FileNameEqualityComparer.Default) - .Select(path => MetadataReference.CreateFromFile(path)) - .ToArray(); - - Lazy csproj; - Lazy vbproj; - Lazy> csbuild; - Lazy> vbbuild; - - public AcceptanceTestsContext() - { - csproj = new Lazy(() => workspace.AddProject(ProjectInfo.Create( - ProjectId.CreateNewId(), - VersionStamp.Create(), - "cscode", - "cscode.dll", - LanguageNames.CSharp, - compilationOptions: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary), - metadataReferences: references))); - - csbuild = new Lazy>(() => csproj.Value.GetCompilationAsync(new CancellationTokenSource(AcceptanceTests.AsyncTimeoutMilliseconds).Token)); - - vbproj = new Lazy(() => workspace.AddProject(ProjectInfo.Create( - ProjectId.CreateNewId(), - VersionStamp.Create(), - "vbcode", - "vbcode.dll", - LanguageNames.VisualBasic, - compilationOptions: new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary, optionStrict: OptionStrict.On), - metadataReferences: references))); - - vbbuild = new Lazy>(() => vbproj.Value.GetCompilationAsync(new CancellationTokenSource(AcceptanceTests.AsyncTimeoutMilliseconds).Token)); - } - - public AdhocWorkspace Workspace - => workspace; - - public Project GetProject(string language) - => language == LanguageNames.CSharp ? csproj.Value : vbproj.Value; - - public Task GetCompilationAsync(string language, CancellationToken cancellationToken) - => language == LanguageNames.CSharp ? csbuild.Value : vbbuild.Value; - - public void Dispose() - { - workspace.Dispose(); - } - } -} diff --git a/src/Stunts/Stunts.AcceptanceTests/App.config b/src/Stunts/Stunts.AcceptanceTests/App.config deleted file mode 100644 index 011a04ec..00000000 --- a/src/Stunts/Stunts.AcceptanceTests/App.config +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Stunts/Stunts.AcceptanceTests/Mock.cs b/src/Stunts/Stunts.AcceptanceTests/Mock.cs deleted file mode 100644 index 321f995a..00000000 --- a/src/Stunts/Stunts.AcceptanceTests/Mock.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Moq.Proxy; - -public static class Mock -{ - // NOTE: for the proxy generator acceptance tests, we only care that we can - // generate proxies that compile without errors only, not that they can - // be constructed and used, so we can avoid taking more deps than necessary - // by just returning null from this method invocation. - // What matters to the generator is the presence of the [ProxyGenerator] - // attribute only, and the generic type parameters. - [ProxyGenerator] - public static T Of() => default(T); -} \ No newline at end of file diff --git a/src/Stunts/Stunts.AcceptanceTests/Moq.Proxy.AcceptanceTests.csproj b/src/Stunts/Stunts.AcceptanceTests/Moq.Proxy.AcceptanceTests.csproj deleted file mode 100644 index d7ef2854..00000000 --- a/src/Stunts/Stunts.AcceptanceTests/Moq.Proxy.AcceptanceTests.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - net461 - true - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Stunts/Stunts.AcceptanceTests/Readme.md b/src/Stunts/Stunts.AcceptanceTests/Readme.md deleted file mode 100644 index fb9266d0..00000000 --- a/src/Stunts/Stunts.AcceptanceTests/Readme.md +++ /dev/null @@ -1,15 +0,0 @@ -# Moq.Proxy Acceptance Tests - -The acceptance tests ensure that a broad range of types can -be properly proxied by the proxy generator. - -In order to achieve this, all referenced assemblies in the -project are enumerated, all public types are retrieved, and -proxy generation is attempted on all of them. Failure to -compile these generated proxies would indicate an unsupported -scenario that would require fixing. - -If you come across one such unsupported proxy generation -scenario, please just add a nuget package reference to the -project, run the tests (to cause the failure) and send a PR -with the change so it can be fixed. \ No newline at end of file diff --git a/src/Stunts/Stunts.CodeAnalysis/AnalyzerOptionsExtensions.cs b/src/Stunts/Stunts.CodeAnalysis/AnalyzerOptionsExtensions.cs deleted file mode 100644 index 60d3638f..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/AnalyzerOptionsExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Stunts -{ - /// - /// Allows retrieving code fix settings from the configured analyzer options. - /// - public static class AnalyzerOptionsExtensions - { - static readonly Dictionary emptySettings = new Dictionary(); - - /// - /// Gets the optional generator settings from the configured analyzer options. - /// - public static IDictionary GetCodeFixSettings(this AnalyzerOptions options) - { - var metadataFile = options.AdditionalFiles.FirstOrDefault(x => x.Path.EndsWith("AutoCodeFix.ini", StringComparison.OrdinalIgnoreCase)); - if (metadataFile != null) - { - // We can pass ourselves arbitrary settings by adding items. - // If items are calculated, you can create a target and run BeforeTargets="SaveAutoFixSettings". - return File.ReadAllLines(metadataFile.Path) - .Where(line => !string.IsNullOrEmpty(line)) - .Select(line => line.Split('=')) - .Where(pair => pair.Length == 2) - .ToDictionary(pair => pair[0].Trim(), pair => pair[1].Trim()); - } - - return emptySettings; - } - } -} diff --git a/src/Stunts/Stunts.CodeAnalysis/DiagnosticsExtensions.cs b/src/Stunts/Stunts.CodeAnalysis/DiagnosticsExtensions.cs deleted file mode 100644 index 31e519b1..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/DiagnosticsExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace Stunts -{ - /// - /// Helper extension methods useful when authoring diagnostics. - /// - public static class DiagnosticsExtensions - { - static readonly HashSet compilationErrorIds = new HashSet - { - // C# non-implemented abstract member - "CS0534", - // C# non-implemented interface member - "CS0535", - // VB non-implemented abstract member - "BC30610", - // VB non-implemented interface member - "BC30149", - }; - - /// - /// Gets the diagnostics that represent build errors that happen when generated - /// code is out of date. - /// - public static Diagnostic[] GetCompilationErrors(this Compilation compilation) - => compilation.GetDiagnostics().Where(d => compilationErrorIds.Contains(d.Id)).ToArray(); - - /// - /// Checks if any of the diagnostics provided applies to the given symbol. - /// - public static bool HasDiagnostic(this INamedTypeSymbol symbol, Diagnostic[] diagnostics) - { - var symbolPath = symbol.Locations[0].GetLineSpan().Path; - bool isSymbolLoc(Location loc) => loc.IsInSource && loc.GetLineSpan().Path == symbolPath; - - return diagnostics - .Any(d => isSymbolLoc(d.Location) || d.AdditionalLocations.Any(isSymbolLoc)); - } - } -} diff --git a/src/Stunts/Stunts.CodeAnalysis/GlobalSuppressions.cs b/src/Stunts/Stunts.CodeAnalysis/GlobalSuppressions.cs deleted file mode 100644 index 36e74184..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/GlobalSuppressions.cs +++ /dev/null @@ -1,8 +0,0 @@ - -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "False positives on expression-bodied members.")] - diff --git a/src/Stunts/Stunts.CodeAnalysis/NamingConvention.cs b/src/Stunts/Stunts.CodeAnalysis/NamingConvention.cs deleted file mode 100644 index 880d5346..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/NamingConvention.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis; - -namespace Stunts -{ - /// - /// Naming conventions used for analyzers, code fixes and code generation. - /// - public class NamingConvention - { - /// - /// The namespace of the generated code. - /// - public virtual string Namespace => StuntNaming.DefaultNamespace; - - /// - /// Suffix appended to the type name, i.e. IFooStunt. - /// - public virtual string NameSuffix => StuntNaming.DefaultSuffix; - - /// - /// The type name to generate for the given (optional) base type and implemented interfaces. - /// - public string GetName(IEnumerable symbols) - { - var builder = new StringBuilder(); - // First add the base class - AddNames(builder, symbols.Where(x => x.TypeKind == TypeKind.Class)); - // Then the interfaces - AddNames(builder, symbols.Where(x => x.TypeKind == TypeKind.Interface).OrderBy(x => x.Name)); - return builder.Append(NameSuffix).ToString(); - } - - static void AddNames(StringBuilder builder, IEnumerable symbols) - { - foreach (var symbol in symbols) - { - builder.Append(symbol.Name); - if (symbol is INamedTypeSymbol named && named.IsGenericType) - { - builder.Append("Of"); - AddNames(builder, named.TypeArguments); - } - } - } - - /// - /// The full type name for the given (optional) base type and implemented interfaces. - /// - public string GetFullName(IEnumerable symbols) - => Namespace + "." + GetName(symbols); - } -} diff --git a/src/Stunts/Stunts.CodeAnalysis/Properties/Resources.Designer.cs b/src/Stunts/Stunts.CodeAnalysis/Properties/Resources.Designer.cs deleted file mode 100644 index 7f006e48..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/Properties/Resources.Designer.cs +++ /dev/null @@ -1,351 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Stunts.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Stunts.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to When a base type is specified, it must be the first type in the type arguments list.. - /// - internal static string BaseTypeNotFirst_Description { - get { - return ResourceManager.GetString("BaseTypeNotFirst_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Base type '{0}' must be the first in the type arguments list.. - /// - internal static string BaseTypeNotFirst_Message { - get { - return ResourceManager.GetString("BaseTypeNotFirst_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Base type must be first. - /// - internal static string BaseTypeNotFirst_Title { - get { - return ResourceManager.GetString("BaseTypeNotFirst_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Implement stunt. - /// - internal static string CustomStuntCodeFix_ImplementStunt { - get { - return ResourceManager.GetString("CustomStuntCodeFix_ImplementStunt", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Implement though behavior pipeline. - /// - internal static string CustomStuntCodeFix_ImplementThroughBehavior { - get { - return ResourceManager.GetString("CustomStuntCodeFix_ImplementThroughBehavior", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot specify more than one base type.. - /// - internal static string DuplicateBaseType_Description { - get { - return ResourceManager.GetString("DuplicateBaseType_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot specify more than one base type.. - /// - internal static string DuplicateBaseType_Message { - get { - return ResourceManager.GetString("DuplicateBaseType_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Multiple base types specified. - /// - internal static string DuplicateBaseType_Title { - get { - return ResourceManager.GetString("DuplicateBaseType_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Generate all stunts in {0} {1}. - /// - internal static string GenerateStuntCodeFix_FixAllTitle { - get { - return ResourceManager.GetString("GenerateStuntCodeFix_FixAllTitle", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Add Stunt. - /// - internal static string GenerateStuntCodeFix_Title { - get { - return ResourceManager.GetString("GenerateStuntCodeFix_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Add {0} to {1}. - /// - internal static string GenerateStuntCodeFix_TitleFormat { - get { - return ResourceManager.GetString("GenerateStuntCodeFix_TitleFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot intercept sealed types.. - /// - internal static string InvalidSealedBaseType { - get { - return ResourceManager.GetString("InvalidSealedBaseType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Only classes and interfaces can be used in stunts. Invalid set of symbols: {0}.. - /// - internal static string InvalidStuntTypes { - get { - return ResourceManager.GetString("InvalidStuntTypes", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invoked method requires a stunt to be generated at design-time or compile-time.. - /// - internal static string MissingStunt_Description { - get { - return ResourceManager.GetString("MissingStunt_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Expected stunt '{0}' was not found in the current compilation.. - /// - internal static string MissingStunt_Message { - get { - return ResourceManager.GetString("MissingStunt_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Stunt not found. - /// - internal static string MissingStunt_Title { - get { - return ResourceManager.GetString("MissingStunt_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Move base type first. - /// - internal static string MoveBaseTypeFirst_Title { - get { - return ResourceManager.GetString("MoveBaseTypeFirst_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Existing generated stunt is no longer up-to-date.. - /// - internal static string OutdatedStunt_Description { - get { - return ResourceManager.GetString("OutdatedStunt_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Stunt '{0}' is outdated.. - /// - internal static string OutdatedStunt_Message { - get { - return ResourceManager.GetString("OutdatedStunt_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Stunt must be updated. - /// - internal static string OutdatedStunt_Title { - get { - return ResourceManager.GetString("OutdatedStunt_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot specify sealed base type.. - /// - internal static string SealedBaseType_Description { - get { - return ResourceManager.GetString("SealedBaseType_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot specify sealed base type '{0}'... - /// - internal static string SealedBaseType_Message { - get { - return ResourceManager.GetString("SealedBaseType_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid sealed base type. - /// - internal static string SealedBaseType_Title { - get { - return ResourceManager.GetString("SealedBaseType_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Project '{0}' does not reference the required Stunts assembly.. - /// - internal static string StuntsRequired { - get { - return ResourceManager.GetString("StuntsRequired", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to At least one symbol is required.. - /// - internal static string SymbolRequired { - get { - return ResourceManager.GetString("SymbolRequired", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Generating code for nested types is not supported yet.. - /// - internal static string UnsupportedNestedTypeAnalyzer_Description { - get { - return ResourceManager.GetString("UnsupportedNestedTypeAnalyzer_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot generate code for nested types: {0}. - /// - internal static string UnsupportedNestedTypeAnalyzer_Message { - get { - return ResourceManager.GetString("UnsupportedNestedTypeAnalyzer_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unsupported nested type. - /// - internal static string UnsupportedNestedTypeAnalyzer_Title { - get { - return ResourceManager.GetString("UnsupportedNestedTypeAnalyzer_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Update all stunts in {0} {1}. - /// - internal static string UpdateStuntCodeFix_FixAllTitle { - get { - return ResourceManager.GetString("UpdateStuntCodeFix_FixAllTitle", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Update Stunt. - /// - internal static string UpdateStuntCodeFix_Title { - get { - return ResourceManager.GetString("UpdateStuntCodeFix_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Update {0}. - /// - internal static string UpdateStuntCodeFix_TitleFormat { - get { - return ResourceManager.GetString("UpdateStuntCodeFix_TitleFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Only one base class can be specified, and it must be the first in the type list. Invalid set of symbols: {0}.. - /// - internal static string WrongBaseType { - get { - return ResourceManager.GetString("WrongBaseType", resourceCulture); - } - } - } -} diff --git a/src/Stunts/Stunts.CodeAnalysis/Properties/Resources.resx b/src/Stunts/Stunts.CodeAnalysis/Properties/Resources.resx deleted file mode 100644 index fb34bb6e..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/Properties/Resources.resx +++ /dev/null @@ -1,216 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - When a base type is specified, it must be the first type in the type arguments list. - - - Base type '{0}' must be the first in the type arguments list. - - - Base type must be first - - - Implement stunt - - - Implement though behavior pipeline - - - Cannot specify more than one base type. - - - Cannot specify more than one base type. - - - Multiple base types specified - - - Generate all stunts in {0} {1} - - - Add Stunt - - - Add {0} to {1} - - - Only classes and interfaces can be used in stunts. Invalid set of symbols: {0}. - - - Invoked method requires a stunt to be generated at design-time or compile-time. - - - Expected stunt '{0}' was not found in the current compilation. - - - Stunt not found - - - Move base type first - - - Existing generated stunt is no longer up-to-date. - - - Stunt '{0}' is outdated. - - - Stunt must be updated - - - Cannot specify sealed base type. - - - Cannot specify sealed base type '{0}'.. - - - Invalid sealed base type - - - Generating code for nested types is not supported yet. - - - Cannot generate code for nested types: {0} - - - Unsupported nested type - - - Update all stunts in {0} {1} - - - Update Stunt - - - Update {0} - - - Cannot intercept sealed types. - - - Project '{0}' does not reference the required Stunts assembly. - - - At least one symbol is required. - - - Only one base class can be specified, and it must be the first in the type list. Invalid set of symbols: {0}. - - \ No newline at end of file diff --git a/src/Stunts/Stunts.CodeAnalysis/Properties/launchSettings.json b/src/Stunts/Stunts.CodeAnalysis/Properties/launchSettings.json deleted file mode 100644 index d5eb1dfc..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profiles": { - "Stunts.CodeAnalysis": { - "commandName": "Executable", - "executablePath": "$(VsInstallRoot)\\Common7\\IDE\\devenv.exe", - "commandLineArgs": "$(SolutionDir)Samples\\Samples.sln" - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.CodeAnalysis/ResourceString.cs b/src/Stunts/Stunts.CodeAnalysis/ResourceString.cs deleted file mode 100644 index 8cb58d40..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/ResourceString.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Globalization; -using Microsoft.CodeAnalysis; -using Stunts.Properties; - -namespace Stunts -{ - class ResourceString : LocalizableString - { - readonly string name; - - public ResourceString(string name) => this.name = name; - - protected override bool AreEqual(object other) - => (other as ResourceString)?.name == name; - - protected override int GetHash() => name.GetHashCode(); - - protected override string GetText(IFormatProvider formatProvider) - => Resources.ResourceManager.GetString(name, (formatProvider as CultureInfo ?? CultureInfo.CurrentUICulture)) ?? ""; - } -} diff --git a/src/Stunts/Stunts.CodeAnalysis/StuntDiagnostics.cs b/src/Stunts/Stunts.CodeAnalysis/StuntDiagnostics.cs deleted file mode 100644 index 8b8ad330..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/StuntDiagnostics.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using Microsoft.CodeAnalysis; -using Stunts.Properties; - -namespace Stunts -{ - /// - /// Known diagnostics reported by the Stunts analyzer. - /// - public static class StuntDiagnostics - { - /// - /// Diagnostic reported whenever an expected stunt is not found in the current compilation. - /// - public static DiagnosticDescriptor MissingStunt { get; } = new DiagnosticDescriptor( - "ST001", - new ResourceString(nameof(Resources.MissingStunt_Title)), - new ResourceString(nameof(Resources.MissingStunt_Message)), - "Build", - bool.TryParse(Environment.GetEnvironmentVariable("AutoCodeFix"), out var value) && value ? DiagnosticSeverity.Warning : DiagnosticSeverity.Info, - true, - new ResourceString(nameof(Resources.MissingStunt_Description))); - - /// - /// Diagnostic reported whenever an existing stunt is outdated with regards to the interfaces - /// it implements or abstract base class it inherits from. - /// - public static DiagnosticDescriptor OutdatedStunt { get; } = new DiagnosticDescriptor( - "ST002", - new ResourceString(nameof(Resources.OutdatedStunt_Title)), - new ResourceString(nameof(Resources.OutdatedStunt_Message)), - "Build", - bool.TryParse(Environment.GetEnvironmentVariable("AutoCodeFix"), out var value) && value ? DiagnosticSeverity.Warning : DiagnosticSeverity.Info, - true, - new ResourceString(nameof(Resources.OutdatedStunt_Description))); - - /// - /// Diagnostic reported whenever type parameters specified for a - /// -annotated method contain a base - /// type but it is not the first provided type parameter. This matches - /// the compiler requirement of having the base class as the first type too. - /// - public static DiagnosticDescriptor BaseTypeNotFirst { get; } = new DiagnosticDescriptor( - "ST003", - new ResourceString(nameof(Resources.BaseTypeNotFirst_Title)), - new ResourceString(nameof(Resources.BaseTypeNotFirst_Message)), - "Build", - DiagnosticSeverity.Error, - true, - new ResourceString(nameof(Resources.BaseTypeNotFirst_Description))); - - /// - /// Diagnostic reported whenever the base type specified for a - /// -annotated method is duplicated. - /// - public static DiagnosticDescriptor DuplicateBaseType { get; } = new DiagnosticDescriptor( - "ST004", - new ResourceString(nameof(Resources.DuplicateBaseType_Title)), - new ResourceString(nameof(Resources.DuplicateBaseType_Message)), - "Build", - DiagnosticSeverity.Error, - true, - new ResourceString(nameof(Resources.DuplicateBaseType_Description))); - - /// - /// Diagnostic reported whenever the specified base type for a - /// -annotated method sealed. - /// - public static DiagnosticDescriptor SealedBaseType { get; } = new DiagnosticDescriptor( - "ST005", - new ResourceString(nameof(Resources.SealedBaseType_Title)), - new ResourceString(nameof(Resources.SealedBaseType_Message)), - "Build", - DiagnosticSeverity.Error, - true, - new ResourceString(nameof(Resources.SealedBaseType_Description))); - } -} diff --git a/src/Stunts/Stunts.CodeAnalysis/StuntGeneratorAnalyzer.cs b/src/Stunts/Stunts.CodeAnalysis/StuntGeneratorAnalyzer.cs deleted file mode 100644 index b6b59d3f..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/StuntGeneratorAnalyzer.cs +++ /dev/null @@ -1,214 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.IO; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Stunts -{ - /// - /// Analyzes source code looking for method invocations to methods annotated with - /// the and reports any missing or outdated - /// generated types using the given to locate the - /// generated types. - /// - // TODO: F# - [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] - public class StuntGeneratorAnalyzer : DiagnosticAnalyzer - { - private readonly NamingConvention naming; - private readonly bool recursive; - private Type generatorAttribute; - - /// - /// Instantiates the analyzer with the default and - /// for method invocations annotated with . - /// - public StuntGeneratorAnalyzer() : this(new NamingConvention(), typeof(StuntGeneratorAttribute)) { } - - /// - /// Customizes the analyzer by specifying a custom and - /// to lookup in method invocations. - /// - protected StuntGeneratorAnalyzer(NamingConvention naming, Type generatorAttribute, bool recursive = false) - { - this.naming = naming; - this.generatorAttribute = generatorAttribute; - this.recursive = recursive; - } - - /// - /// Provides metadata about the missing generated type diagnostic. - /// - public virtual DiagnosticDescriptor MissingDiagnostic => StuntDiagnostics.MissingStunt; - - /// - /// Provides metadata about the outdated generated type diagnostic. - /// - public virtual DiagnosticDescriptor OutdatedDiagnostic => StuntDiagnostics.OutdatedStunt; - - /// - /// Returns the single this analyzer supports. - /// - public sealed override ImmutableArray SupportedDiagnostics - { - // NOTE: this creates the return value at this point because both Missing and Outdated - // descriptors can be overridden as a customization point. - get { return ImmutableArray.Create(MissingDiagnostic, OutdatedDiagnostic); } - } - - /// - /// Registers the analyzer to take action on method invocation expressions. - /// - public override void Initialize(AnalysisContext context) - { - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, Microsoft.CodeAnalysis.CSharp.SyntaxKind.InvocationExpression); - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, Microsoft.CodeAnalysis.CSharp.SyntaxKind.ObjectCreationExpression); - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.SimpleMemberAccessExpression); - } - - private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) - { - // Get the matching symbol for the given generator attribute from the current compilation. - var generator = context.Compilation.GetTypeByMetadataName(generatorAttribute.FullName); - if (generator == null) - { - // This may be an extender authoring error, but another analyzer should ensure proper - // metadata references exist. Typically, the same NuGet package that adds this analyzer - // also adds the required assembly references, so this should never happen anyway. - return; - } - - var symbol = context.Compilation.GetSemanticModel(context.Node.SyntaxTree).GetSymbolInfo(context.Node); - if (symbol.Symbol?.Kind != SymbolKind.Method) - { - return; - } - - var method = (IMethodSymbol)symbol.Symbol; - ImmutableArray typeArguments = default; - if (!method.GetAttributes().Any(x => x.AttributeClass == generator)) - return; - - if (method.MethodKind == MethodKind.Constructor) - { - if (method.ReceiverType is INamedTypeSymbol owner && - owner.IsGenericType) - { - typeArguments = owner.TypeArguments; - } - else - { - return; - } - } - else - { - typeArguments = method.TypeArguments; - } - - if (method.GetAttributes().Any(x => x.AttributeClass == generator) && - // We don't generate anything if generator is applied to a non-generic method. - !typeArguments.IsDefaultOrEmpty && - typeArguments.TryValidateGeneratorTypes(out _)) - { - var name = naming.GetFullName(typeArguments.OfType()); - var compilationErrors = new Lazy(() => context.Compilation.GetCompilationErrors()); - HashSet recursiveSymbols; - - if (recursive) - { - // Collect recursive symbols to generate/update as needed. - recursiveSymbols = new HashSet(typeArguments.OfType().InterceptableRecursively() - .Where(x => - { - var candidate = context.Compilation.GetTypeByMetadataName(naming.GetFullName(new[] { x })); - return candidate == null || candidate.HasDiagnostic(compilationErrors.Value); - }) - .Select(x => x.ToFullName())); - } - else - { - recursiveSymbols = new HashSet(); - } - - // See if the stunt already exists - var stunt = context.Compilation.GetTypeByMetadataName(name); - if (stunt == null) - { - var diagnostic = Diagnostic.Create( - MissingDiagnostic, - context.Node.GetLocation(), - new Dictionary - { - { "TargetFullName", name }, - { "Symbols", string.Join("|", typeArguments - .OfType().Select(x => x.ToFullName())) }, - // By passing the detected recursive symbols to update/generate, - // we avoid doing all the work we already did during analysis. - // The code action can therefore simply act on them, without - // further inquiries to the compilation. - { "RecursiveSymbols", string.Join("|", recursiveSymbols) }, - }.ToImmutableDictionary(), - name); - - // Flag AutoCodeFix that the next build should generate the type. - if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("AutoCodeFix")) && - // We only flag if we're not being run by AutoCodeFix itself - context.Options.GetCodeFixSettings().TryGetValue("IntermediateOutputPath", out var intermediateOutputPath)) - { - File.WriteAllText(Path.Combine(intermediateOutputPath, "AutoCodeFixBeforeCompile.flag"), ""); - } - - context.ReportDiagnostic(diagnostic); - } - else - { - // See if the symbol has any compilation error diagnostics associated - if (stunt.HasDiagnostic(compilationErrors.Value) || - (recursive && recursiveSymbols.Any())) - { - var location = stunt.Locations.Length == 1 - ? stunt.Locations[0].GetLineSpan().Path - : stunt.Locations.FirstOrDefault(loc => - loc.GetLineSpan().Path.EndsWith(".g.cs", StringComparison.OrdinalIgnoreCase) || - loc.GetLineSpan().Path.EndsWith(".g.vb", StringComparison.OrdinalIgnoreCase)) - ?.GetLineSpan().Path - ?? ""; - - // Any outdated files should be automatically updated on the next build, - // so signal this to the build targets with a text file that the targets - // can use to determine a pre-compile analysis and codefix phase is needed. - if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("AutoCodeFix")) && - // We only flag if we're not being run by AutoCodeFix itself - context.Options.GetCodeFixSettings().TryGetValue("IntermediateOutputPath", out var intermediateOutputPath)) - { - File.WriteAllText(Path.Combine(intermediateOutputPath, "AutoCodeFixBeforeCompile.flag"), ""); - } - - // If there are compilation errors, we should update the proxy. - var diagnostic = Diagnostic.Create( - OutdatedDiagnostic, - context.Node.GetLocation(), - new Dictionary - { - { "TargetFullName", name }, - { "Location", location }, - { "Symbols", string.Join("|", typeArguments - .OfType().Select(x => x.ToFullName())) }, - // We pass the same recursive symbols in either case. The - // Different diagnostics exist only to customize the message - // displayed to the user. - { "RecursiveSymbols", string.Join("|", recursiveSymbols) }, - }.ToImmutableDictionary(), - name); - - context.ReportDiagnostic(diagnostic); - } - } - } - } - } -} diff --git a/src/Stunts/Stunts.CodeAnalysis/Stunts.CodeAnalysis.csproj b/src/Stunts/Stunts.CodeAnalysis/Stunts.CodeAnalysis.csproj deleted file mode 100644 index c83b0e71..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/Stunts.CodeAnalysis.csproj +++ /dev/null @@ -1,52 +0,0 @@ - - - - - netstandard2.0 - Stunts - true - Analyzers - true - - - - - - PrimaryOutputKind=$(PrimaryOutputKind) - - - - - - IncludeApi=false - - - - - - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - - $(PrimaryOutputKind.ToLowerInvariant())\netstandard1.3\%(Filename)%(Extension) - - - - - \ No newline at end of file diff --git a/src/Stunts/Stunts.CodeAnalysis/Stunts.CodeAnalysis.targets b/src/Stunts/Stunts.CodeAnalysis/Stunts.CodeAnalysis.targets deleted file mode 100644 index edfe013e..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/Stunts.CodeAnalysis.targets +++ /dev/null @@ -1,19 +0,0 @@ - - - - - %(PackageReference.Identity) - - - - - - - - - \ No newline at end of file diff --git a/src/Stunts/Stunts.CodeAnalysis/SymbolExtensions.cs b/src/Stunts/Stunts.CodeAnalysis/SymbolExtensions.cs deleted file mode 100644 index 0a1b62ae..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/SymbolExtensions.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Xml; -using Microsoft.CodeAnalysis; -using Stunts.Properties; - -namespace Stunts -{ - /// - /// Helper methods for dealing with s. - /// - public static class SymbolExtensions - { - const string TaskFullName = "System.Threading.Tasks.Task"; - - /// - /// Retrieves the distinct set of symbols that can be intercepted from the - /// given list, by inspecting each one and all its properties and methods - /// recursively looking for symbols that can be intercepted via codegen. - /// - /// - /// - public static ImmutableHashSet InterceptableRecursively(this IEnumerable symbols) - { - var set = new HashSet(); - foreach (var symbol in symbols) - { - CollectSymbols(symbol, set); - } - return set.ToImmutableHashSet(); - } - - static void CollectSymbols(INamedTypeSymbol symbol, HashSet set) - { - var members = symbol.GetMembers(); - // We only collect method return types and property types. - // TODO: collecting byref/out method parameters would be - // needed too to set their default values to mocks also... - var candidates = members - .OfType() - .Where(s => !s.ReturnsVoid && s.ReturnType.CanBeIntercepted()) - .Select(s => s.ReturnType) - .Concat(members - - .OfType() - .Where(s => s.Type.CanBeIntercepted()) - .Select(s => s.Type)) - .OfType(); - - foreach (var candidate in candidates) - { - if (set.Add(candidate)) - CollectSymbols(candidate, set); - } - } - - /// - /// Sorts and validates types so that the base class is the first and the remaining - /// interface implementations are the rest. - /// - /// The list of types is invalid for a generator invocation. - public static (INamedTypeSymbol baseType, ImmutableArray additionalInterfaces) ValidateGeneratorTypes(this IEnumerable types) - { - var symbols = types.ToArray(); - if (symbols.Length == 0) - throw new ArgumentException(Strings.SymbolRequired); - - var baseType = default(INamedTypeSymbol); - var additionalInterfaces = default(IEnumerable); - if (symbols[0].TypeKind == TypeKind.Class) - { - baseType = symbols[0]; - if (symbols.Skip(1).Any(x => x.TypeKind == TypeKind.Class)) - throw new ArgumentException(Strings.WrongBaseType(string.Join(",", symbols.Select(x => x.Name)))); - if (baseType.IsSealed) - throw new ArgumentException(Strings.InvalidSealedBaseType); - if (symbols.Skip(1).Any(x => x.TypeKind != TypeKind.Interface)) - throw new ArgumentException(Strings.InvalidStuntTypes(string.Join(",", symbols.Select(x => x.Name)))); - - additionalInterfaces = symbols.Skip(1); - } - else - { - if (symbols.Any(x => x.TypeKind == TypeKind.Class)) - throw new ArgumentException(Strings.WrongBaseType(string.Join(",", symbols.Select(x => x.Name)))); - if (symbols.Any(x => x.TypeKind != TypeKind.Interface)) - throw new ArgumentException(Strings.InvalidStuntTypes(string.Join(",", symbols.Select(x => x.Name)))); - - additionalInterfaces = symbols; - } - - return (baseType, additionalInterfaces.OrderBy(x => x.Name).ToImmutableArray()); - } - - /// - /// Validates the specified generator method type parameters, checking for base type - /// and implemented interfaces. - /// - /// The types in use by the generator. - /// The result of splitting the base type and the additional interfaces from the . - public static bool TryValidateGeneratorTypes(this IEnumerable types, - out (INamedTypeSymbol baseType, ImmutableArray additionalInterfaces) result) - { - var symbols = types.ToArray(); - result = default; - if (symbols.Length == 0) - return false; - - Debug.Assert(!symbols.Any(x => x.TypeKind == TypeKind.Error), "Symbol(s) contain errors."); - - var baseType = default(INamedTypeSymbol); - var additionalInterfaces = default(IEnumerable); - if (symbols[0].TypeKind == TypeKind.Class) - { - baseType = (INamedTypeSymbol)symbols[0]; - if (types.Skip(1).Any(x => x.TypeKind == TypeKind.Class)) - return false; - if (baseType.IsSealed) - return false; - if (types.Skip(1).Any(x => x.TypeKind != TypeKind.Interface)) - return false; - - additionalInterfaces = types.Skip(1).Cast(); - } - else - { - if (symbols.Any(x => x.TypeKind == TypeKind.Class)) - return false; - if (symbols.Any(x => x.TypeKind != TypeKind.Interface)) - return false; - - additionalInterfaces = types.Cast(); - } - - result = (baseType, additionalInterfaces.OrderBy(x => x.Name).ToImmutableArray()); - return true; - } - - /// - /// Whether the given type symbol is either an interface or a non-sealed class, and not a generic task. - /// - public static bool CanBeIntercepted(this ITypeSymbol symbol) - => symbol != null && - symbol.CanBeReferencedByName && - !symbol.IsValueType && - !symbol.MetadataName.StartsWith(TaskFullName, StringComparison.Ordinal) && - (symbol.TypeKind == TypeKind.Interface || - (symbol.TypeKind == TypeKind.Class && symbol.IsSealed == false)); - } -} diff --git a/src/Stunts/Stunts.CodeAnalysis/SymbolFullNameExtensions.cs b/src/Stunts/Stunts.CodeAnalysis/SymbolFullNameExtensions.cs deleted file mode 100644 index a351137e..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/SymbolFullNameExtensions.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading; -using Microsoft.CodeAnalysis; -using Superpower; -using Superpower.Parsers; - -namespace Stunts -{ - /// - /// Provides uniform rendering and resolving of symbols from a full name. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class SymbolFullNameExtensions - { - static readonly SymbolDisplayFormat fullNameFormat = new SymbolDisplayFormat( - typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, - genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, - miscellaneousOptions: SymbolDisplayMiscellaneousOptions.ExpandNullable); - - /// - /// Gets the full name for the symbol, which then be used with - /// to resolve it - /// back to the original symbol. - /// - public static string ToFullName(this ITypeSymbol symbol) => symbol.ToDisplayString(fullNameFormat); - - /// - /// Resolves a symbol given its full name, as returned by . - /// - public static ITypeSymbol GetTypeByFullName(this Compilation compilation, string symbolFullName) - => new SymbolResolver(compilation).Resolve(symbolFullName ?? throw new ArgumentNullException(nameof(symbolFullName))); - - class SymbolResolver - { - TextParser symbolArguments; - TextParser typeSymbol; - Compilation compilation; - - public SymbolResolver(Compilation compilation) => this.compilation = compilation; - - static TextParser Identifier { get; } = - from first in Character.Letter - from rest in Character.LetterOrDigit.Or(Character.EqualTo('_')).Many() - select first + new string(rest); - - static TextParser ArrayRank { get; } = - from open in Character.EqualTo('[') - from dimensions in Character.EqualTo(',').Many() - from close in Character.EqualTo(']') - select dimensions.Length + 1; - - static TextParser FullName { get; } = - from identifiers in Identifier.ManyDelimitedBy(Character.EqualTo('.').Or(Character.EqualTo('+'))) - select string.Join(".", identifiers); - - TextParser SymbolArguments => LazyInitializer.EnsureInitialized(ref symbolArguments, () => - from open in Character.EqualTo('<') - from arguments in TypeSymbol.ManyDelimitedBy(Character.EqualTo(',').IgnoreThen(Character.WhiteSpace)) - from close in Character.EqualTo('>') - select arguments); - - TextParser TypeSymbol => LazyInitializer.EnsureInitialized(ref typeSymbol, () => - from name in FullName - from dimensions in ArrayRank.OptionalOrDefault() - from arguments in SymbolArguments.OptionalOrDefault(Array.Empty()) - select ResolveSymbol(name, dimensions, arguments)); - - public ITypeSymbol Resolve(string typeName) => TypeSymbol.Parse(typeName); - - ITypeSymbol ResolveSymbol(string fullName, int arrayRank, ITypeSymbol[] typeArguments) - { - var metadataName = fullName; - if (typeArguments.Length > 0) - metadataName += "`" + typeArguments.Length; - - var symbol = compilation.GetTypeByMetadataName(metadataName); - if (symbol == null) - { - var nameBuilder = new StringBuilder(metadataName); - // Start replacing . with + to catch nested types, from - // last to first - while (symbol == null) - { - var indexOfDot = nameBuilder.ToString().LastIndexOf('.'); - if (indexOfDot == -1) - break; - - nameBuilder[indexOfDot] = '+'; - symbol = compilation.GetTypeByMetadataName(nameBuilder.ToString()); - } - } - - if (symbol == null) - return null; - - if (typeArguments.Length > 0) - symbol = symbol.Construct(typeArguments); - - if (arrayRank > 0 && symbol != null) - return compilation.CreateArrayTypeSymbol(symbol, arrayRank); - - return symbol; - } - } - } -} diff --git a/src/Stunts/Stunts.CodeAnalysis/UnsupportedNestedTypeAnalyzer.cs b/src/Stunts/Stunts.CodeAnalysis/UnsupportedNestedTypeAnalyzer.cs deleted file mode 100644 index 0e484eee..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/UnsupportedNestedTypeAnalyzer.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using Stunts.Properties; - -namespace Stunts -{ - /// - /// Analyzes source code looking for method invocations to methods annotated with - /// the and reports unsupported nested types for - /// codegen. - /// - // TODO: this is a stop-gap measure until we can figure out why the ImplementInterfaces codefix - // is not returning any code actions for the CSharpScaffold (maybe VB too?) when the type to - // be implemented is a nested interface :(. In the IDE, the code action is properly available after - // generating the (non-working, since the interface isn't implemented) mock class. - // One possible workaround to not prevent the scenario altogether would be to leverage the - // IImplementInterfaceService ourselves by duplicating the (simple) behavior of the CSharpImplementInterfaceCodeFixProvider - // (see http://source.roslyn.io/#Microsoft.CodeAnalysis.CSharp.Features/ImplementInterface/CSharpImplementInterfaceCodeFixProvider.cs,fd395d6b5f6a7dd3) - // and wrapping the code action in our own that would run the rewriters right after invoking the built-in one. I fear, - // however, that the same reason the codefix isn't showing up when we ask for it, will cause that service to return - // an empty list of code actions too. - // It may be costly to investigate, and it doesn't seem like a core scenario anyway. - // It can be worked around by creating a custom mock. - // TODO: F# - [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] - public class UnsupportedNestedTypeAnalyzer : DiagnosticAnalyzer - { - static readonly DiagnosticDescriptor descriptor = new DiagnosticDescriptor( - "ST009", - new ResourceString(nameof(Resources.UnsupportedNestedTypeAnalyzer_Title)), - new ResourceString(nameof(Resources.UnsupportedNestedTypeAnalyzer_Message)), - "Build", - DiagnosticSeverity.Error, - true, - new ResourceString(nameof(Resources.UnsupportedNestedTypeAnalyzer_Description))); - - readonly NamingConvention naming; - Type generatorAttribute; - - /// - /// Instantiates the analyzer with the default and - /// for method invocations annotated with . - /// - public UnsupportedNestedTypeAnalyzer() : this(new NamingConvention(), typeof(StuntGeneratorAttribute)) { } - - /// - /// Customizes the analyzer by specifying a custom and - /// to lookup in method invocations. - /// - protected UnsupportedNestedTypeAnalyzer(NamingConvention naming, Type generatorAttribute) - { - this.naming = naming; - this.generatorAttribute = generatorAttribute; - } - - /// - /// Returns the single descriptor this analyzer supports. - /// - public sealed override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(descriptor); - - /// - /// Registers the analyzer to take action on method invocation expressions. - /// - public override void Initialize(AnalysisContext context) - { - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, Microsoft.CodeAnalysis.CSharp.SyntaxKind.InvocationExpression); - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.SimpleMemberAccessExpression); - } - - void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) - { - // Get the matching symbol for the given generator attribute from the current compilation. - var generator = context.Compilation.GetTypeByMetadataName(generatorAttribute.FullName); - if (generator == null) - // This may be an extender authoring error, but another analyzer should ensure proper - // metadata references exist. Typically, the same NuGet package that adds this analyzer - // also adds the required assembly references, so this should never happen anyway. - return; - - var symbol = context.Compilation.GetSemanticModel(context.Node.SyntaxTree).GetSymbolInfo(context.Node); - if (symbol.Symbol?.Kind == SymbolKind.Method) - { - var method = (IMethodSymbol)symbol.Symbol; - if (method.GetAttributes().Any(x => x.AttributeClass == generator) && - // We don't generate anything if generator is applied to a non-generic method. - !method.TypeArguments.IsDefaultOrEmpty) - // Skip generic method definitions since they are typically usability overloads - // like Mock.Of(...) - // TODO: doesn't seem like this would be needed? - //!method.TypeArguments.Any(x => x.Kind == SymbolKind.TypeParameter)) - { - var args = method.TypeArguments.OfType().Where(t => t.ContainingType != null).ToArray(); - if (args.Length != 0) - { - var diagnostic = Diagnostic.Create( - descriptor, - context.Node.GetLocation(), - string.Join(", ", args.Select(t => t.ContainingType.Name + "." + t.Name))); - - context.ReportDiagnostic(diagnostic); - } - } - } - } - } -} diff --git a/src/Stunts/Stunts.CodeAnalysis/ValidateTypesAnalyzer.cs b/src/Stunts/Stunts.CodeAnalysis/ValidateTypesAnalyzer.cs deleted file mode 100644 index ef3975ad..00000000 --- a/src/Stunts/Stunts.CodeAnalysis/ValidateTypesAnalyzer.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Stunts -{ - /// - /// Analyzes source code looking for method invocations to methods annotated with - /// the and reports unsupported scenarios. - /// - // TODO: F# - [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] - public class ValidateTypesAnalyzer : DiagnosticAnalyzer - { - Type generatorAttribute; - - /// - /// Instantiates the analyzer to validate invocations to methods - /// annotated with . - /// - public ValidateTypesAnalyzer() : this(typeof(StuntGeneratorAttribute)) { } - - /// - /// Customizes the analyzer by specifying a custom - /// to lookup in method invocations. - /// - protected ValidateTypesAnalyzer(Type generatorAttribute) - => this.generatorAttribute = generatorAttribute; - - /// - /// Returns the single - /// diagnostic this analyzer supports. - /// - public sealed override ImmutableArray SupportedDiagnostics { get; } - = ImmutableArray.Create( - StuntDiagnostics.BaseTypeNotFirst, - StuntDiagnostics.DuplicateBaseType, - StuntDiagnostics.SealedBaseType); - - /// - /// Registers the analyzer to take action on method invocation expressions. - /// - public override void Initialize(AnalysisContext context) - { - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, Microsoft.CodeAnalysis.CSharp.SyntaxKind.InvocationExpression); - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.SimpleMemberAccessExpression); - } - - void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) - { - // Get the matching symbol for the given generator attribute from the current compilation. - var generator = context.Compilation.GetTypeByMetadataName(generatorAttribute.FullName); - if (generator == null) - return; - - var symbol = context.Compilation.GetSemanticModel(context.Node.SyntaxTree).GetSymbolInfo(context.Node); - if (symbol.Symbol?.Kind == SymbolKind.Method) - { - var method = (IMethodSymbol)symbol.Symbol; - if (method.GetAttributes().Any(x => x.AttributeClass == generator) && - !method.TypeArguments.IsDefaultOrEmpty) - { - var classes = method.TypeArguments.Where(x => x.TypeKind == TypeKind.Class).ToArray(); - if (classes.Length > 1) - { - context.ReportDiagnostic(Diagnostic.Create( - StuntDiagnostics.DuplicateBaseType, - context.Node.GetLocation())); - } - if (classes.Length == 1) - { - if (classes[0].IsSealed) - { - context.ReportDiagnostic(Diagnostic.Create( - StuntDiagnostics.SealedBaseType, - context.Node.GetLocation(), - classes[0].Name)); - } - else if (method.TypeArguments.IndexOf(classes[0]) != 0) - { - context.ReportDiagnostic(Diagnostic.Create( - StuntDiagnostics.BaseTypeNotFirst, - context.Node.GetLocation(), - classes[0].Name)); - } - } - } - } - } - } -} diff --git a/src/Stunts/Stunts.CodeFix/CustomStuntCodeFixProvider.cs b/src/Stunts/Stunts.CodeFix/CustomStuntCodeFixProvider.cs deleted file mode 100644 index 769bb5e1..00000000 --- a/src/Stunts/Stunts.CodeFix/CustomStuntCodeFixProvider.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System.CodeDom.Compiler; -using System.Collections.Immutable; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Editing; -using Stunts.Processors; -using Stunts.Properties; - -namespace Stunts -{ - /// - /// Adds support for generating stunt implementations for a custom stunt manually created - /// by the user. - /// - [ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic, Name = "CustomStunt")] - [ExtensionOrder(Before = "ImplementInterface")] - public class CustomStuntCodeFixProvider : CodeFixProvider - { - /// - public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create( - // See http://source.roslyn.io/#Microsoft.CodeAnalysis.CSharp.Features/ImplementAbstractClass/CSharpImplementAbstractClassCodeFixProvider.cs,15 - "CS0534", - // See http://source.roslyn.io/#Microsoft.CodeAnalysis.CSharp.Features/ImplementInterface/CSharpImplementInterfaceCodeFixProvider.cs,24 - "CS0535", - // See http://source.roslyn.io/#Microsoft.CodeAnalysis.VisualBasic.Features/ImplementAbstractClass/VisualBasicImplementAbstractClassCodeFixProvider.vb,15 - "BC30610", - // See http://source.roslyn.io/#Microsoft.CodeAnalysis.VisualBasic.Features/ImplementInterface/VisualBasicImplementInterfaceCodeFixProvider.vb,16 - "BC30149"); - - /// - public override async Task RegisterCodeFixesAsync(CodeFixContext context) - { - var document = context.Document; - var span = context.Span; - var root = await document.GetSyntaxRootAsync(context.CancellationToken); - - var token = root.FindToken(span.Start); - if (!token.Span.IntersectsWith(span)) - return; - - var model = await document.GetSemanticModelAsync(context.CancellationToken); - var generator = SyntaxGenerator.GetGenerator(document); - - // Getting the inner-most ensure we get the type identifiers, rather - // than the SimpleBaseTypeSyntax, from which we can't get the symbol. - var node = root.FindNode(span, getInnermostNodeForTie: true); - if (node == null) - return; - - bool isStunt(SyntaxNode n) - { - var symbol = model.GetSymbolInfo(n, context.CancellationToken); - return - symbol.Symbol != null && - symbol.Symbol.ToString() == typeof(IStunt).FullName && - symbol.Symbol.ContainingAssembly.Name == typeof(IStunt).Assembly.GetName().Name; - } - - bool isGenerated(SyntaxNode n) - { - var symbol = model.GetSymbolInfo(n, context.CancellationToken); - // [CompilerGenerated] and [GeneratedCode] are used in IStunt and IMocked to signal that - // no implementation should be offered thought the behavior pipeline - // because a custom code fix provides the implementation instead. - return - symbol.Symbol != null && - symbol.Symbol.GetAttributes().Any(attr => - attr.AttributeClass.ToFullName() == typeof(GeneratedCodeAttribute).FullName || - attr.AttributeClass.ToFullName() == typeof(CompilerGeneratedAttribute).FullName); - } - - // If we find a symbol that happens to be IStunt, implement the core interface. - if (generator.GetDeclarationKind(node) != DeclarationKind.Class && isStunt(node)) - { - context.RegisterCodeFix(new ImplementStuntCodeAction(context.Document), context.Diagnostics); - } - else if (!isGenerated(node)) - { - // Make sure the interface or abstract class is on a type that implements IStunt - // NOTE: if the node is already the class declaration (such as for abstract base class) - // this call returns the same declaration. Otherwise, it will return the declaration that - // an interface is added to. - var declaration = generator.GetDeclaration(node); - if (declaration != null && generator.GetBaseAndInterfaceTypes(declaration).Any(isStunt)) - context.RegisterCodeFix(new ImplementThroughStuntCodeAction(context.Document), context.Diagnostics); - } - } - - /// - /// Returns since this provider does not support batch-fixing. - /// - /// - public sealed override FixAllProvider GetFixAllProvider() => null; - - class ImplementStuntCodeAction : CodeAction - { - readonly Document document; - - public ImplementStuntCodeAction(Document document) => this.document = document; - - public override string Title => Strings.CustomStuntCodeFix.ImplementStunt; - - protected override Task GetChangedDocumentAsync(CancellationToken cancellationToken) - => new StuntGenerator( - new DefaultImports(), - new CSharpScaffold("OverrideAllMembersCodeFix"), - new CSharpRewrite(), - new CSharpStunt(), - new CSharpCompilerGenerated(), - new VisualBasicScaffold("OverrideAllMembersCodeFix"), - new VisualBasicRewrite(), - new VisualBasicStunt(), - new VisualBasicCompilerGenerated()) - .ApplyProcessors(document, cancellationToken); - } - - class ImplementThroughStuntCodeAction : CodeAction - { - readonly Document document; - - public ImplementThroughStuntCodeAction(Document document) => this.document = document; - - public override string Title => Strings.CustomStuntCodeFix.ImplementThroughBehavior; - - protected override Task GetChangedDocumentAsync(CancellationToken cancellationToken) - => new StuntGenerator( - new CSharpScaffold(), - new CSharpRewrite(), - new CSharpCompilerGenerated(), - new VisualBasicScaffold(), - new VisualBasicRewrite(), - new VisualBasicParameterFixup(), - new VisualBasicCompilerGenerated()) - .ApplyProcessors(document, cancellationToken); - } - } -} diff --git a/src/Stunts/Stunts.CodeFix/GlobalSuppressions.cs b/src/Stunts/Stunts.CodeFix/GlobalSuppressions.cs deleted file mode 100644 index 36e74184..00000000 --- a/src/Stunts/Stunts.CodeFix/GlobalSuppressions.cs +++ /dev/null @@ -1,8 +0,0 @@ - -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "False positives on expression-bodied members.")] - diff --git a/src/Stunts/Stunts.CodeFix/MoveBaseTypeFirstCodeFixProvider.cs b/src/Stunts/Stunts.CodeFix/MoveBaseTypeFirstCodeFixProvider.cs deleted file mode 100644 index 030a5a5b..00000000 --- a/src/Stunts/Stunts.CodeFix/MoveBaseTypeFirstCodeFixProvider.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Collections.Immutable; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Editing; -using Stunts.Properties; -using CSharp = Microsoft.CodeAnalysis.CSharp.Syntax; -using VisualBasic = Microsoft.CodeAnalysis.VisualBasic.Syntax; - -namespace Stunts -{ - /// - /// Allows automatically fixing the ordering of mock generator method - /// type parameters. - /// - // TODO: not working yet - // [ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic)] - public class MoveBaseTypeFirstCodeFixProvider : CodeFixProvider - { - /// - public override ImmutableArray FixableDiagnosticIds { get; } - = ImmutableArray.Create(StuntDiagnostics.BaseTypeNotFirst.Id); - - /// - public override async Task RegisterCodeFixesAsync(CodeFixContext context) - { - var document = context.Document; - var span = context.Span; - var root = await document.GetSyntaxRootAsync(context.CancellationToken); - - var token = root.FindToken(span.Start); - if (!token.Span.IntersectsWith(span)) - return; - - // Getting the inner-most ensure we get the type identifiers, rather - // than the SimpleBaseTypeSyntax, from which we can't get the symbol. - var node = root.FindNode(span, getInnermostNodeForTie: true); - if (node == null) - return; - - if (node.Language == LanguageNames.CSharp || - node.Language == LanguageNames.VisualBasic) - { - context.RegisterCodeFix(new MoveBaseTypeFirstCodeAction(document, node), context.Diagnostics); - } - } - - class MoveBaseTypeFirstCodeAction : CodeAction - { - readonly Document document; - SyntaxNode node; - - public MoveBaseTypeFirstCodeAction(Document document, SyntaxNode node) - { - this.document = document; - this.node = node; - } - - public override string Title => Resources.MoveBaseTypeFirst_Title; - - protected override async Task GetChangedDocumentAsync(CancellationToken cancellationToken) - { - var generator = SyntaxGenerator.GetGenerator(document); - var semantic = await document.GetSemanticModelAsync(cancellationToken); - - (SyntaxNode syntax, INamedTypeSymbol symbol)[] typeArguments; - - if (node.Language == LanguageNames.CSharp) - { - // In C#, the member access is actually the Expression inside an - // invocation syntax - node = ((CSharp.InvocationExpressionSyntax)node).Expression; - typeArguments = node - .DescendantNodes() - .OfType() - .SelectMany(x => x.ChildNodes().OfType()) - .Select(x => ((SyntaxNode)x, semantic.GetSymbolInfo(x, cancellationToken).Symbol as INamedTypeSymbol)) - .ToArray(); - } - else - { - typeArguments = node - .ChildNodes().OfType() - .SelectMany(g => g.ChildNodes().OfType()) - .SelectMany(g => g.ChildNodes().OfType()) - .Select(x => ((SyntaxNode)x, semantic.GetSymbolInfo(x, cancellationToken).Symbol as INamedTypeSymbol)) - .ToArray(); - } - - // Hardly optimal, but this codefix should run rarely and only - // for the few type arguments a typical stunt would implement. - var updated = generator.WithTypeArguments(node, - new[] { typeArguments.First(x => x.symbol?.TypeKind == TypeKind.Class) } - .Concat(typeArguments.Where(x => x.symbol?.TypeKind != TypeKind.Class)) - .Select(x => x.syntax)); - - return document.WithSyntaxRoot(await updated.SyntaxTree.GetRootAsync(cancellationToken)); - } - } - } -} diff --git a/src/Stunts/Stunts.CodeFix/OverrideAllMembersCodeFix.cs b/src/Stunts/Stunts.CodeFix/OverrideAllMembersCodeFix.cs deleted file mode 100644 index d6fd00cb..00000000 --- a/src/Stunts/Stunts.CodeFix/OverrideAllMembersCodeFix.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System.Collections.Immutable; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Editing; - -namespace Stunts -{ - /// - /// Implements the codefix for overriding all members in a class - /// using . - /// - [ExportCodeFixProvider(LanguageNames.CSharp, new[] { LanguageNames.VisualBasic }, Name = nameof(OverrideAllMembersCodeFix))] - class OverrideAllMembersCodeFix : CodeFixProvider - { - public sealed override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(OverridableMembersAnalyzer.DiagnosticId); - - public override async Task RegisterCodeFixesAsync(CodeFixContext context) - { - var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken); - var diagnostic = context.Diagnostics.FirstOrDefault(d => FixableDiagnosticIds.Contains(d.Id)); - if (diagnostic == null) - return; - - var sourceToken = root.FindToken(diagnostic.Location.SourceSpan.Start); - - // Find the invocation identified by the diagnostic. - var type = - (SyntaxNode)sourceToken.Parent.AncestorsAndSelf().OfType().FirstOrDefault() ?? - (SyntaxNode)sourceToken.Parent.AncestorsAndSelf().OfType().FirstOrDefault(); - - context.RegisterCodeFix( - CodeAction.Create( - title: "Override All Members", - createChangedSolution: c => OverrideAllMembersAsync(context.Document, type, c), - equivalenceKey: nameof(OverrideAllMembersCodeFix)), - diagnostic); - } - - async Task OverrideAllMembersAsync(Document document, SyntaxNode type, CancellationToken cancellationToken) - { - var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - var symbol = semanticModel.GetDeclaredSymbol(type) as INamedTypeSymbol; - if (symbol == null) - return document.Project.Solution; - - var overridables = RoslynInternals.GetOverridableMembers(symbol, cancellationToken); - - if (type.Language == LanguageNames.VisualBasic) - overridables = overridables - .Where(x => x.MetadataName != WellKnownMemberNames.DestructorName) - // VB doesn't support overriding events (yet). See https://github.com/dotnet/vblang/issues/63 - .Where(x => x.Kind != SymbolKind.Event) - .ToImmutableArray(); - - var generator = SyntaxGenerator.GetGenerator(document); - var memberTasks = overridables.Select( - m => RoslynInternals.OverrideAsync(generator, m, symbol, document, cancellationToken: cancellationToken)); - - var members = await Task.WhenAll(memberTasks); - var newDoc = await RoslynInternals.AddMemberDeclarationsAsync(document.Project.Solution, symbol, members, cancellationToken); - - return newDoc.Project.Solution; - } - } -} diff --git a/src/Stunts/Stunts.CodeFix/Properties/Resources.Designer.cs b/src/Stunts/Stunts.CodeFix/Properties/Resources.Designer.cs deleted file mode 100644 index 97504875..00000000 --- a/src/Stunts/Stunts.CodeFix/Properties/Resources.Designer.cs +++ /dev/null @@ -1,315 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Stunts.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Stunts.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to When a base type is specified, it must be the first type in the type arguments list.. - /// - internal static string BaseTypeNotFirst_Description { - get { - return ResourceManager.GetString("BaseTypeNotFirst_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Base type '{0}' must be the first in the type arguments list.. - /// - internal static string BaseTypeNotFirst_Message { - get { - return ResourceManager.GetString("BaseTypeNotFirst_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Base type must be first. - /// - internal static string BaseTypeNotFirst_Title { - get { - return ResourceManager.GetString("BaseTypeNotFirst_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Implement stunt. - /// - internal static string CustomStuntCodeFix_ImplementStunt { - get { - return ResourceManager.GetString("CustomStuntCodeFix_ImplementStunt", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Implement though behavior pipeline. - /// - internal static string CustomStuntCodeFix_ImplementThroughBehavior { - get { - return ResourceManager.GetString("CustomStuntCodeFix_ImplementThroughBehavior", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot specify more than one base type.. - /// - internal static string DuplicateBaseType_Description { - get { - return ResourceManager.GetString("DuplicateBaseType_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot specify more than one base type.. - /// - internal static string DuplicateBaseType_Message { - get { - return ResourceManager.GetString("DuplicateBaseType_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Multiple base types specified. - /// - internal static string DuplicateBaseType_Title { - get { - return ResourceManager.GetString("DuplicateBaseType_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Generate Stunt. - /// - internal static string GenerateStuntCodeFix_Title { - get { - return ResourceManager.GetString("GenerateStuntCodeFix_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Add {0} to project. - /// - internal static string GenerateStuntCodeFix_TitleFormat { - get { - return ResourceManager.GetString("GenerateStuntCodeFix_TitleFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Only classes and interfaces can be used in stunts. Invalid set of symbols: {0}.. - /// - internal static string InvalidStuntTypes { - get { - return ResourceManager.GetString("InvalidStuntTypes", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invoked method requires a stunt to be generated at design-time or compile-time.. - /// - internal static string MissingStunt_Description { - get { - return ResourceManager.GetString("MissingStunt_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Expected stunt '{0}' was not found in the current compilation.. - /// - internal static string MissingStunt_Message { - get { - return ResourceManager.GetString("MissingStunt_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Stunt not found. - /// - internal static string MissingStunt_Title { - get { - return ResourceManager.GetString("MissingStunt_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Move base type first. - /// - internal static string MoveBaseTypeFirst_Title { - get { - return ResourceManager.GetString("MoveBaseTypeFirst_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Existing generated stunt is no longer up-to-date.. - /// - internal static string OutdatedStunt_Description { - get { - return ResourceManager.GetString("OutdatedStunt_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Stunt '{0}' is outdated.. - /// - internal static string OutdatedStunt_Message { - get { - return ResourceManager.GetString("OutdatedStunt_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Stunt must be updated. - /// - internal static string OutdatedStunt_Title { - get { - return ResourceManager.GetString("OutdatedStunt_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot specify sealed base type.. - /// - internal static string SealedBaseType_Description { - get { - return ResourceManager.GetString("SealedBaseType_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot specify sealed base type '{0}'... - /// - internal static string SealedBaseType_Message { - get { - return ResourceManager.GetString("SealedBaseType_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid sealed base type. - /// - internal static string SealedBaseType_Title { - get { - return ResourceManager.GetString("SealedBaseType_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Fix {0}. - /// - internal static string StuntCodeAction_Title { - get { - return ResourceManager.GetString("StuntCodeAction_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Fix all {0} in {1}. - /// - internal static string StuntFixAllProvider_Title { - get { - return ResourceManager.GetString("StuntFixAllProvider_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Generating code for nested types is not supported yet.. - /// - internal static string UnsupportedNestedTypeAnalyzer_Description { - get { - return ResourceManager.GetString("UnsupportedNestedTypeAnalyzer_Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot generate code for nested types: {0}. - /// - internal static string UnsupportedNestedTypeAnalyzer_Message { - get { - return ResourceManager.GetString("UnsupportedNestedTypeAnalyzer_Message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unsupported nested type. - /// - internal static string UnsupportedNestedTypeAnalyzer_Title { - get { - return ResourceManager.GetString("UnsupportedNestedTypeAnalyzer_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Update Stunt. - /// - internal static string UpdateStuntCodeFix_Title { - get { - return ResourceManager.GetString("UpdateStuntCodeFix_Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Update {0}. - /// - internal static string UpdateStuntCodeFix_TitleFormat { - get { - return ResourceManager.GetString("UpdateStuntCodeFix_TitleFormat", resourceCulture); - } - } - } -} diff --git a/src/Stunts/Stunts.CodeFix/Properties/Resources.resx b/src/Stunts/Stunts.CodeFix/Properties/Resources.resx deleted file mode 100644 index 880840fd..00000000 --- a/src/Stunts/Stunts.CodeFix/Properties/Resources.resx +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - When a base type is specified, it must be the first type in the type arguments list. - - - Base type '{0}' must be the first in the type arguments list. - - - Base type must be first - - - Implement stunt - - - Implement though behavior pipeline - - - Cannot specify more than one base type. - - - Cannot specify more than one base type. - - - Multiple base types specified - - - Generate Stunt - - - Add {0} to project - - - Only classes and interfaces can be used in stunts. Invalid set of symbols: {0}. - - - Invoked method requires a stunt to be generated at design-time or compile-time. - - - Expected stunt '{0}' was not found in the current compilation. - - - Stunt not found - - - Move base type first - - - Existing generated stunt is no longer up-to-date. - - - Stunt '{0}' is outdated. - - - Stunt must be updated - - - Cannot specify sealed base type. - - - Cannot specify sealed base type '{0}'.. - - - Invalid sealed base type - - - Fix {0} - - - Fix all {0} in {1} - - - Generating code for nested types is not supported yet. - - - Cannot generate code for nested types: {0} - - - Unsupported nested type - - - Update Stunt - - - Update {0} - - \ No newline at end of file diff --git a/src/Stunts/Stunts.CodeFix/Properties/launchSettings.json b/src/Stunts/Stunts.CodeFix/Properties/launchSettings.json deleted file mode 100644 index ee4f2362..00000000 --- a/src/Stunts/Stunts.CodeFix/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profiles": { - "Stunts.CodeFix": { - "commandName": "Executable", - "executablePath": "$(VsInstallRoot)\\Common7\\IDE\\devenv.exe", - "commandLineArgs": "$(SolutionDir)Samples\\Samples.sln" - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.CodeFix/StuntCodeAction.cs b/src/Stunts/Stunts.CodeFix/StuntCodeAction.cs deleted file mode 100644 index a1979593..00000000 --- a/src/Stunts/Stunts.CodeFix/StuntCodeAction.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Simplification; -using Stunts.Properties; - -namespace Stunts -{ - /// - /// Code action that performs the actual code generation. - /// - public class StuntCodeAction : CodeAction - { - readonly string title; - readonly Document document; - readonly Diagnostic diagnostic; - readonly NamingConvention naming; - - /// - /// Initializes the action. - /// - public StuntCodeAction(Document document, Diagnostic diagnostic, NamingConvention naming) - : this(Resources.StuntCodeAction_Title, document, diagnostic, naming) - { - } - - /// - /// Initializes the action. - /// - public StuntCodeAction(string title, Document document, Diagnostic diagnostic, NamingConvention naming) - { - this.title = title; - this.document = document; - this.diagnostic = diagnostic; - this.naming = naming; - } - - /// - //public override string EquivalenceKey => diagnostic.Id + ":" + diagnostic.Properties["TargetFullName"]; - - public override string EquivalenceKey => diagnostic.Id; - - /// - public override string Title => title; - - /// - /// Gets the generator for the given coding convention. - /// - protected virtual StuntGenerator CreateGenerator(NamingConvention naming) => new StuntGenerator(naming); - - /// - protected override async Task GetChangedDocumentAsync(CancellationToken cancellationToken) - { - var root = await document.GetSyntaxRootAsync(cancellationToken); - if (root == null) - return document; - - var semanticModel = await document.GetSemanticModelAsync(cancellationToken); - if (semanticModel == null) - return document; - - var compilation = await document.Project.GetCompilationAsync(cancellationToken); - var symbols = diagnostic.Properties["Symbols"] - .Split('|') - .Select(x => (INamedTypeSymbol)compilation.GetTypeByFullName(x)) - .Where(t => t != null) - .ToArray(); - - var name = naming.GetFullName(symbols); - // Check if the compilation already contains the type, which will be - // the case in batch fixing - if (compilation.GetTypeByMetadataName(name) != null) - return document; - - var generator = SyntaxGenerator.GetGenerator(document.Project); - var stunts = CreateGenerator(naming); - - return await CreateStunt(symbols, generator, stunts, cancellationToken); - } - - async Task CreateStunt(IEnumerable symbols, SyntaxGenerator generator, StuntGenerator stunts, CancellationToken cancellationToken) - { - var (name, syntax) = stunts.CreateStunt(symbols, generator); - - // TODO: F# - var extension = document.Project.Language == LanguageNames.CSharp ? ".cs" : ".vb"; - - // The logical folder is always the split namespace, since generated code is - // expected to be added as hidden linked files. - var folders = naming.Namespace.Split('.'); - - if (!diagnostic.Properties.TryGetValue("Location", out var file) || - string.IsNullOrEmpty(file)) - { - file = Path.Combine(Path.GetDirectoryName(document.Project.FilePath), Path.Combine(folders), name + extension); - } - - var stuntDoc = document.Project.Documents.FirstOrDefault(d => d.Name == Path.GetFileName(file) && d.Folders.SequenceEqual(folders)); - - // NOTE: the environment variable tells us we're being run with AutoCodeFix enabled and - // active, meaning we should generate files into the intermediate output path instead. - var autoCodeFixEnabled = bool.TryParse(Environment.GetEnvironmentVariable("AutoCodeFix"), out var value) && value; - - // Update target file path if running from build-time codegen. - if (stuntDoc == null && autoCodeFixEnabled) - { - // Get configured generator options to build the final path - if (document.Project.AnalyzerOptions.GetCodeFixSettings().TryGetValue("IntermediateOutputPath", out var intermediateOutputPath)) - { - file = Path.Combine(intermediateOutputPath, Path.Combine(folders), name + ".g" + extension); - } - } - - if (stuntDoc == null) - { - if (document.Project.Solution.Workspace is AdhocWorkspace workspace) - { - stuntDoc = workspace.AddDocument(DocumentInfo - .Create( - DocumentId.CreateNewId(document.Project.Id), - Path.GetFileName(file), - folders: folders, - filePath: file)) - .WithSyntaxRoot(syntax); - } - else - { - // When running the generator from design-time, ensure the folder exists. - // This is necessary since we link files into the Mocks/Stunts folder, - // which becomes a "linked" folder itself, and when adding the document, - // VS fails to so. - if (!autoCodeFixEnabled) - { - var directory = Path.Combine(Path.GetDirectoryName(document.Project.FilePath), Path.Combine(folders)); - Directory.CreateDirectory(directory); - } - - stuntDoc = document.Project.AddDocument( - Path.GetFileName(file), - syntax, - folders, - file); - } - } - else - { - stuntDoc = stuntDoc.WithSyntaxRoot(syntax); - } - - stuntDoc = await stunts.ApplyProcessors(stuntDoc, cancellationToken); - - // This is somewhat expensive, but with the formatting, the code doesn't even compile :/ - stuntDoc = await Simplifier.ReduceAsync(stuntDoc); - if (document.Project.Language != LanguageNames.VisualBasic) - stuntDoc = await Formatter.FormatAsync(stuntDoc, Formatter.Annotation); - - syntax = await stuntDoc.GetSyntaxRootAsync(); - stuntDoc = stuntDoc.WithSyntaxRoot(syntax); - - return stuntDoc; - } - } -} diff --git a/src/Stunts/Stunts.CodeFix/StuntCodeFixProvider.cs b/src/Stunts/Stunts.CodeFix/StuntCodeFixProvider.cs deleted file mode 100644 index d90baf00..00000000 --- a/src/Stunts/Stunts.CodeFix/StuntCodeFixProvider.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Collections.Immutable; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Stunts.Properties; - -namespace Stunts -{ - /// - /// Generates code for stunts. - /// - // NOTE: all behavior is implemented in the StuntCodeFixProvider and the derived - // exported classes just provide the custom title depending on the - // analyzer that detected either a missing or outdated proxy. - // TODO: F# - [ExportCodeFixProvider(LanguageNames.CSharp, new[] { LanguageNames.VisualBasic }, Name = nameof(GenerateStuntCodeFix))] - public class GenerateStuntCodeFix : StuntCodeFixProvider - { - /// - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create("ST001"); - - /// - /// Creates the code action that will implement the fix. - /// - protected override CodeAction CreateCodeAction(Document document, Diagnostic diagnostic) - => new StuntCodeAction(Strings.GenerateStuntCodeFix.TitleFormat( - diagnostic.Properties["TargetFullName"]), document, diagnostic, new NamingConvention()); - } - - /// - /// Updates code for existing stunts. - /// - [ExportCodeFixProvider(LanguageNames.CSharp, new[] { LanguageNames.VisualBasic }, Name = nameof(UpdateStuntCodeFix))] - public class UpdateStuntCodeFix : StuntCodeFixProvider - { - /// - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create("ST002"); - - /// - /// Creates the code action that will implement the fix. - /// - protected override CodeAction CreateCodeAction(Document document, Diagnostic diagnostic) - => new StuntCodeAction(Strings.UpdateStuntCodeFix.TitleFormat( - diagnostic.Properties["TargetFullName"]), document, diagnostic, new NamingConvention()); - } - - /// - /// Base class that implements the core code generation for stunts, which is reused - /// by the generation and updating. - /// - public abstract class StuntCodeFixProvider : CodeFixProvider - { - /// - public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) - { - var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken); - // TODO: should we instead try to register for all diagnostics matching our fixable ones instead of just the first one? - var diagnostic = context.Diagnostics.FirstOrDefault(d => FixableDiagnosticIds.Contains(d.Id)); - if (diagnostic == null) - return; - - // Register a code action that will invoke the fix. - context.RegisterCodeFix( - CreateCodeAction(context.Document, diagnostic), - diagnostic); - } - - /// - /// Creates the code action that will implement the fix. - /// - protected abstract CodeAction CreateCodeAction(Document document, Diagnostic diagnostic); - - /// - /// Returns since the generator does not support batch fixing. - /// - /// - // See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/FixAllProvider.md for more information on Fix All Providers - //public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - public override FixAllProvider GetFixAllProvider() - => new StuntFixAllProvider(FixableDiagnosticIds.First(), CreateCodeAction); - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.CodeFix/StuntFixAllProvider.cs b/src/Stunts/Stunts.CodeFix/StuntFixAllProvider.cs deleted file mode 100644 index df574894..00000000 --- a/src/Stunts/Stunts.CodeFix/StuntFixAllProvider.cs +++ /dev/null @@ -1,197 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Stunts.Properties; - -namespace Stunts -{ - class StuntFixAllProvider : FixAllProvider - { - readonly string diagnosticId; - readonly Func codeActionFactory; - - public StuntFixAllProvider(string diagnosticId, Func codeActionFactory) - { - this.diagnosticId = diagnosticId; - this.codeActionFactory = codeActionFactory; - } - - public override async Task GetFixAsync(FixAllContext fixAllContext) - { - var diagnosticsToFix = new List>>(); - string title = null; - - switch (fixAllContext.Scope) - { - case FixAllScope.Document: - { - var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Document); - diagnostics = diagnostics.Where(d => d.Id == diagnosticId).ToImmutableArray(); - if (diagnostics.Length > 0) - diagnosticsToFix.Add(new KeyValuePair>(fixAllContext.Project, diagnostics)); - - title = string.Format(Resources.StuntFixAllProvider_Title, diagnosticId, fixAllContext.Document.Name); - break; - } - - case FixAllScope.Project: - { - Project project = fixAllContext.Project; - var diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project); - if (diagnostics.Length > 0) - diagnosticsToFix.Add(new KeyValuePair>(project, diagnostics)); - - title = string.Format(Resources.StuntFixAllProvider_Title, diagnosticId, fixAllContext.Project.Name); - break; - } - - case FixAllScope.Solution: - { - foreach (var project in fixAllContext.Solution.Projects) - { - var diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project); - if (diagnostics.Length > 0) - diagnosticsToFix.Add(new KeyValuePair>(project, diagnostics)); - } - - title = string.Format(Resources.StuntFixAllProvider_Title, diagnosticId, - fixAllContext.Solution.FilePath == null ? - nameof(FixAllScope.Solution) : - Path.GetFileName(fixAllContext.Solution.FilePath)); - break; - } - - case FixAllScope.Custom: - return null; - default: - break; - } - - return new FixAllProxiesCodeAction(title, fixAllContext.Solution, diagnosticsToFix, codeActionFactory); - } - - class FixAllProxiesCodeAction : CodeAction - { - readonly string title; - readonly Solution solution; - readonly List>> diagnosticsToFix; - readonly Func codeActionFactory; - - public FixAllProxiesCodeAction(string title, - Solution solution, - List>> diagnosticsToFix, - Func codeActionFactory) - { - this.title = title; - this.solution = solution; - this.diagnosticsToFix = diagnosticsToFix; - this.codeActionFactory = codeActionFactory; - } - - public override string Title => title; - - protected override async Task GetChangedSolutionAsync(CancellationToken cancellationToken) - { - var currentSolution = solution; - var fixerTasks = new List(); - var addedDocs = new ConcurrentBag(); - var updatedDocs = new ConcurrentBag(); - - foreach (var pair in diagnosticsToFix) - { - var project = solution.GetProject(pair.Key.Id); - Debug.Assert(project != null, "Failed to get project from solution."); - var diagnostics = pair.Value; - - var group = diagnostics.GroupBy(d => d.Properties["TargetFullName"]); - foreach (var diag in group) - { - var diagnostic = diag.First(); - var document = diagnostic.Location.IsInSource ? - project.Documents.FirstOrDefault(doc => doc.FilePath == diagnostic.Location.SourceTree.FilePath) : - project.GetDocument(diagnostic.Location.SourceTree); - - Debug.Assert(document != null, "Failed to locate document from diagnostic."); - - fixerTasks.Add(new CodeFixer(document, diagnostic, addedDocs, updatedDocs, codeActionFactory) - .RunAsync(cancellationToken)); - } - } - - await Task.WhenAll(fixerTasks).ConfigureAwait(false); - - foreach (var addedDoc in addedDocs) - { - var addedText = await addedDoc.GetTextAsync(cancellationToken).ConfigureAwait(false); - var addedVersion = await addedDoc.GetTextVersionAsync(cancellationToken).ConfigureAwait(false); - currentSolution = currentSolution.AddDocument(DocumentInfo.Create( - addedDoc.Id, addedDoc.Name, addedDoc.Folders, - addedDoc.SourceCodeKind, - TextLoader.From(TextAndVersion.Create(addedText, addedVersion, addedDoc.FilePath)), - addedDoc.FilePath)); - } - - foreach (var updatedDoc in updatedDocs) - { - var updatedText = await updatedDoc.GetTextAsync(cancellationToken).ConfigureAwait(false); - currentSolution = currentSolution.WithDocumentText(updatedDoc.Id, updatedText); - } - - return currentSolution; - } - - class CodeFixer - { - private readonly Document document; - private readonly Diagnostic diagnostic; - private readonly ConcurrentBag addedDocs; - private readonly ConcurrentBag updatedDocs; - private readonly Func codeActionFactory; - - public CodeFixer(Document document, Diagnostic diagnostic, ConcurrentBag addedDocs, ConcurrentBag updatedDocs, Func codeActionFactory) - { - this.document = document; - this.diagnostic = diagnostic; - this.addedDocs = addedDocs; - this.updatedDocs = updatedDocs; - this.codeActionFactory = codeActionFactory; - } - - public async Task RunAsync(CancellationToken cancellationToken) - { - // NOTE: stunts don't need to update the source document where the diagnostic - // was reported, so we don't need any of the document updating stuff that - // we need when applying code fixers in the moq/stunt codegen itself on its own - // document. So we just apply the workspace changes and that's it. - var codeAction = codeActionFactory(document, diagnostic); - var operations = await codeAction.GetOperationsAsync(cancellationToken).ConfigureAwait(false); - var applyChanges = operations.OfType().FirstOrDefault(); - if (applyChanges != null) - { - var changes = applyChanges.ChangedSolution.GetChanges(document.Project.Solution); - foreach (var change in changes.GetProjectChanges()) - { - foreach (var addedId in change.GetAddedDocuments()) - { - addedDocs.Add(applyChanges.ChangedSolution.GetDocument(addedId)); - } - foreach (var changedId in change.GetChangedDocuments(true)) - { - updatedDocs.Add(applyChanges.ChangedSolution.GetDocument(changedId)); - } - } - } - } - } - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.CodeFix/Stunts.CodeFix.csproj b/src/Stunts/Stunts.CodeFix/Stunts.CodeFix.csproj deleted file mode 100644 index fae31ce7..00000000 --- a/src/Stunts/Stunts.CodeFix/Stunts.CodeFix.csproj +++ /dev/null @@ -1,65 +0,0 @@ - - - - - netstandard2.0 - Stunts - true - Build - true - - - - - - PrimaryOutputKind=$(PrimaryOutputKind);IncludeApi=false - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - PreserveNewest - $(PrimaryOutputKind) - true - - - PreserveNewest - $(PrimaryOutputKind) - true - - - - - - - .NETStandard,Version=v1.3 - true - - - - - \ No newline at end of file diff --git a/src/Stunts/Stunts.DynamicProxy/AssemblyInfo.cs b/src/Stunts/Stunts.DynamicProxy/AssemblyInfo.cs deleted file mode 100644 index 94110b66..00000000 --- a/src/Stunts/Stunts.DynamicProxy/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Moq.DynamicProxy")] \ No newline at end of file diff --git a/src/Stunts/Stunts.DynamicProxy/DynamicStuntFactory.cs b/src/Stunts/Stunts.DynamicProxy/DynamicStuntFactory.cs deleted file mode 100644 index fb7cac64..00000000 --- a/src/Stunts/Stunts.DynamicProxy/DynamicStuntFactory.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using System.Security.Permissions; -using Castle.DynamicProxy; -using Castle.DynamicProxy.Generators; - -namespace Stunts.Sdk -{ - /// - /// Provides a that creates types at run-time using Castle DynamicProxy. - /// - public class DynamicStuntFactory : IStuntFactory - { - static readonly ProxyGenerator generator; - static readonly ProxyGenerationOptions options; - - static DynamicStuntFactory() - { -#pragma warning disable 618 - AttributesToAvoidReplicating.Add(); -#pragma warning restore 618 - - AttributesToAvoidReplicating.Add(); - AttributesToAvoidReplicating.Add(); - - options = new ProxyGenerationOptions { Hook = new ObjectMethodsHook() }; -#if DEBUG - // This allows invoking generator.ProxyBuilder.ModuleScope.SaveAssembly() for troubleshooting. - generator = new ProxyGenerator(new DefaultProxyBuilder(new ModuleScope(true))); -#else - generator = new ProxyGenerator(); -#endif - } - - /// - public object CreateStunt(Assembly stuntsAssembly, Type baseType, Type[] implementedInterfaces, object[] constructorArguments) - { - var notImplemented = false; - - if (baseType.IsInterface) - { - var fixedInterfaces = new Type[implementedInterfaces.Length + 1]; - fixedInterfaces[0] = baseType; - implementedInterfaces.CopyTo(fixedInterfaces, 1); - implementedInterfaces = fixedInterfaces; - baseType = typeof(object); - notImplemented = true; - } - - if (!implementedInterfaces.Contains(typeof(IStunt))) - { - var fixedInterfaces = new Type[implementedInterfaces.Length + 1]; - fixedInterfaces[0] = typeof(IStunt); - implementedInterfaces.CopyTo(fixedInterfaces, 1); - implementedInterfaces = fixedInterfaces; - } - - if (baseType.BaseType == typeof(MulticastDelegate)) - { - var mixinOptions = new ProxyGenerationOptions(); - mixinOptions.AddDelegateTypeMixin(baseType); - var proxy = CreateProxy(typeof(object), implementedInterfaces, mixinOptions, Array.Empty(), notImplemented); - return Delegate.CreateDelegate(baseType, proxy, proxy.GetType().GetMethod("Invoke")); - } - else - { - return CreateProxy(baseType, implementedInterfaces, options, constructorArguments, notImplemented); - } - } - - /// - /// Creates the proxy with the , adding interceptors to implement its behavior. - /// - protected virtual object CreateProxy(Type baseType, Type[] implementedInterfaces, ProxyGenerationOptions options, object[] constructorArguments, bool notImplemented) - // TODO: bring the approach from https://github.com/moq/moq4/commit/806e9919eab9c1f3879b9e9bda895fa76ecf9d92 for performance. - => generator.CreateClassProxy(baseType, implementedInterfaces, options, constructorArguments, new DynamicStuntInterceptor(notImplemented)); - - /// - /// The used to create proxy types. - /// - protected ProxyGenerator Generator => generator; - } -} diff --git a/src/Stunts/Stunts.DynamicProxy/DynamicStuntInterceptor.cs b/src/Stunts/Stunts.DynamicProxy/DynamicStuntInterceptor.cs deleted file mode 100644 index f704dcc2..00000000 --- a/src/Stunts/Stunts.DynamicProxy/DynamicStuntInterceptor.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using Castle.DynamicProxy; - -namespace Stunts.Sdk -{ - internal class DynamicStuntInterceptor : IInterceptor, IStunt // Implemented to detect breaking changes in Stunts - { - readonly bool notImplemented; - readonly BehaviorPipeline pipeline; - - internal DynamicStuntInterceptor(bool notImplemented) - { - this.notImplemented = notImplemented; - pipeline = new BehaviorPipeline(); - } - - public ObservableCollection Behaviors => pipeline.Behaviors; - - public virtual void Intercept(IInvocation invocation) - { - if (invocation.Method.DeclaringType == typeof(IStunt)) - { - invocation.ReturnValue = Behaviors; - return; - } - - var input = new MethodInvocation(invocation.Proxy, invocation.Method, invocation.Arguments); - var returns = pipeline.Invoke(input, (i, next) => { - try - { - if (notImplemented) - throw new NotImplementedException(); - - invocation.Proceed(); - var returnValue = invocation.ReturnValue; - return input.CreateValueReturn(returnValue, invocation.Arguments); - } - catch (Exception ex) - { - return input.CreateExceptionReturn(ex); - } - }); - - var exception = returns.Exception; - if (exception != null) - throw exception; - - invocation.ReturnValue = returns.ReturnValue; - for (var i = 0; i < returns.Outputs.Count; i++) - { - var name = returns.Outputs.GetInfo(i).Name; - var index = input.Arguments.IndexOf(name); - invocation.SetArgumentValue(index, returns.Outputs[i]); - } - } - } -} diff --git a/src/Stunts/Stunts.DynamicProxy/ObjectMethodsHook.cs b/src/Stunts/Stunts.DynamicProxy/ObjectMethodsHook.cs deleted file mode 100644 index dba27471..00000000 --- a/src/Stunts/Stunts.DynamicProxy/ObjectMethodsHook.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Reflection; -using Castle.DynamicProxy; - -namespace Stunts.Sdk -{ - /// - /// Hook used to tells Castle which methods to proxy in mocked classes. - /// - /// Here we proxy the default methods Castle suggests (everything Object's methods) - /// plus Object.ToString(), so we can give mocks useful default names. - /// - /// This is required to allow Moq to mock ToString on proxy *class* implementations. - /// - [Serializable] - internal class ObjectMethodsHook : AllMethodsHook - { - /// - /// Adds methods to the interception candidates. - /// - public override bool ShouldInterceptMethod(Type type, MethodInfo method) - => base.ShouldInterceptMethod(type, method) || IsObjectMethod(method); - - private static bool IsObjectMethod(MethodInfo method) - => method.DeclaringType == typeof(object) && - (method.Name == nameof(object.ToString) || - method.Name == nameof(object.Equals) || - method.Name == nameof(object.GetHashCode)); - } -} diff --git a/src/Stunts/Stunts.DynamicProxy/Stunts.DynamicProxy.csproj b/src/Stunts/Stunts.DynamicProxy/Stunts.DynamicProxy.csproj deleted file mode 100644 index 9d25c628..00000000 --- a/src/Stunts/Stunts.DynamicProxy/Stunts.DynamicProxy.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - - netstandard2.0 - Stunts.Sdk - - - - - - - - - - - diff --git a/src/Stunts/Stunts.Package/Stunts.Package.msbuildproj b/src/Stunts/Stunts.Package/Stunts.Package.msbuildproj deleted file mode 100644 index a7b1faba..00000000 --- a/src/Stunts/Stunts.Package/Stunts.Package.msbuildproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - netstandard2.0 - PackageReference - Debug;Release - AnyCPU - Stunts - Stunts - "Dynamic proxies" that can run everywhere, including mobile! - Design-time generated classes whose behavior can be configured dynamically at run-time with arbitrary behaviors (a.k.a. "proxies"). - netstandard proxy runtime dynamic - true - - - - - - \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/CodeFixAdapter.cs b/src/Stunts/Stunts.Sdk/CodeFixAdapter.cs deleted file mode 100644 index 5611130c..00000000 --- a/src/Stunts/Stunts.Sdk/CodeFixAdapter.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Immutable; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; - -namespace Stunts -{ - class CodeFixAdapter : ICodeFix - { - public CodeFixAdapter(CodeAction action, ImmutableArray diagnostics, string provider) - { - Action = action; - Diagnostics = diagnostics; - Provider = provider; - } - - public CodeAction Action { get; } - - public ImmutableArray Diagnostics { get; } - - public string Provider { get; } - - public override string ToString() - { - return Action.Title + " from '" + Provider + "'"; - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/DiscoveryExtensions.cs b/src/Stunts/Stunts.Sdk/DiscoveryExtensions.cs deleted file mode 100644 index 3ae024ce..00000000 --- a/src/Stunts/Stunts.Sdk/DiscoveryExtensions.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using CSharp = Microsoft.CodeAnalysis.CSharp.Syntax; -using VisualBasic = Microsoft.CodeAnalysis.VisualBasic.Syntax; -using Stunts.Properties; -using System.Linq; - -namespace Stunts -{ - /// - /// Extension methods on and to discover - /// stunts in use by detecting invocations to methods declared with the - /// . - /// - public static class DiscoveryExtensions - { - /// - /// Discovers the unique set of stunts in use in the given project by searching all - /// documents for invocations to methods declared with the . - /// - /// - /// This method returns a set of arrays since each stunt is actually made of the symbols it - /// inherits/implements. It's a set because that array of symbols the stunt inherits/implements is - /// unique (we don't generate duplicates). A is used to - /// ensure structural equality of the arrays. - /// - public static async Task>> DiscoverStuntsAsync(this Project project, CancellationToken cancellationToken = default(CancellationToken)) - { - var compilation = await project.GetCompilationAsync(cancellationToken); - var stuntGeneratorSymbol = compilation.GetTypeByMetadataName(typeof(StuntGeneratorAttribute).FullName); - if (stuntGeneratorSymbol == null) - throw new ArgumentException(Strings.StuntsRequired(project.Name)); - - Func>>> discoverer; - if (project.Language == LanguageNames.CSharp) - discoverer = DiscoverStuntsAsync; - else if (project.Language == LanguageNames.VisualBasic) - discoverer = DiscoverStuntsAsync; - else - // TODO: F# - return ImmutableHashSet.Create>(); - - var candidates = new HashSet>(StructuralComparer>.Default); - foreach (var document in project.Documents) - { - var discovered = await discoverer(document, stuntGeneratorSymbol, cancellationToken); - foreach (var stunt in discovered) - { - candidates.Add(stunt); - } - } - - return candidates.ToImmutableHashSet(StructuralComparer>.Default); - } - - /// - /// Discovers the unique set of stunts in use in the given document by searching for invocations - /// to methods declared with the . - /// - /// - /// This method returns a set of arrays since each stunt is actually made of the symbols it - /// inherits/implements. It's a set because that array of symbols the stunt inherits/implements is - /// unique (we don't generate duplicates). A is used to - /// ensure structural equality of the arrays. - /// - public static async Task>> DiscoverStuntsAsync(this Document document, CancellationToken cancellationToken = default(CancellationToken)) - { - var compilation = await document.Project.GetCompilationAsync(cancellationToken); - var stuntGeneratorSymbol = compilation.GetTypeByMetadataName(typeof(StuntGeneratorAttribute).FullName); - if (stuntGeneratorSymbol == null) - throw new ArgumentException(Strings.StuntsRequired(document.Project.Name)); - - Func>>> discoverer; - if (document.Project.Language == LanguageNames.CSharp) - discoverer = DiscoverStuntsAsync; - else if (document.Project.Language == LanguageNames.VisualBasic) - discoverer = DiscoverStuntsAsync; - else - // TODO: F# - return ImmutableHashSet.Create>(); - - var discovered = await discoverer(document, stuntGeneratorSymbol, cancellationToken); - - return discovered.ToImmutableHashSet(StructuralComparer>.Default); - } - - static async Task>> DiscoverStuntsAsync(this Document document, ITypeSymbol proxyGeneratorSymbol, CancellationToken cancellationToken = default(CancellationToken)) - where TSyntax : SyntaxNode - { - var stunts = new HashSet>(StructuralComparer>.Default); - var semantic = await document.GetSemanticModelAsync(cancellationToken); - var syntax = await document.GetSyntaxRootAsync(cancellationToken); - cancellationToken.ThrowIfCancellationRequested(); - - foreach (var node in syntax.DescendantNodes().OfType()) - { - var symbol = semantic.GetSymbolInfo(node, cancellationToken); - if (symbol.Symbol?.Kind == SymbolKind.Method) - { - var method = (IMethodSymbol)symbol.Symbol; - if (method.GetAttributes().Any(x => x.AttributeClass == proxyGeneratorSymbol) && - // Skip generic method definitions since they are typically usability overloads - // like Mock.Of(...) - !method.TypeArguments.Any(x => x.Kind == SymbolKind.TypeParameter) && - // TODO: this invalid scenario should be detected by an analyzer that - // generates a compile error. - method.TypeArguments.All(x => x.TypeKind == TypeKind.Class || x.TypeKind == TypeKind.Interface)) - { - var baseType = (INamedTypeSymbol)method.TypeArguments.FirstOrDefault(x => x.TypeKind == TypeKind.Class); - var implementedInterfaces = baseType != null ? method.TypeArguments.Remove(baseType) : method.TypeArguments; - - stunts.Add(implementedInterfaces - .Cast() - .OrderBy(x => x.Name) - .Prepend(baseType) - .ToImmutableArray()); - } - } - } - - return stunts.ToImmutableHashSet(StructuralComparer>.Default); - } - } -} diff --git a/src/Stunts/Stunts.Sdk/DocumentExtensions.cs b/src/Stunts/Stunts.Sdk/DocumentExtensions.cs deleted file mode 100644 index 57b2bbf2..00000000 --- a/src/Stunts/Stunts.Sdk/DocumentExtensions.cs +++ /dev/null @@ -1,156 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Text; -using Stunts; - -namespace Microsoft.CodeAnalysis -{ - /// - /// Extensions methods for to . - /// - public static class DocumentExtensions - { - static Lazy> builtInAnalyzers = new Lazy>(() => - MefHostServices - .DefaultAssemblies - .SelectMany(x => x.GetTypes() - .Where(t => !t.IsAbstract && typeof(DiagnosticAnalyzer).IsAssignableFrom(t))) - .Where(t => t.GetConstructor(Type.EmptyTypes) != null) - .Select(t => (DiagnosticAnalyzer)Activator.CreateInstance(t)) - // Add our own. - .Concat(new[] { new OverridableMembersAnalyzer() }) - .ToImmutableArray()); - - /// - /// Exposes the built-in analyzers, discovered via reflection. - /// - // TODO: see if this should be moved elsewhere. - public static ImmutableArray BuiltInAnalyzers => builtInAnalyzers.Value; - - /// - /// Applies the given named code fix to a document. - /// - public static async Task ApplyCodeFixAsync(this Document document, string codeFixName, ImmutableArray analyzers = default, CancellationToken cancellationToken = default) - { - // If we request and process ALL codefixes at once, we'll get one for each - // diagnostics, which is one per non-implemented member of the interface/abstract - // base class, so we'd be applying unnecessary fixes after the first one. - // So we re-retrieve them after each Apply, which will leave only the remaining - // ones. - var codeFixes = await GetCodeFixes(document, codeFixName, analyzers, cancellationToken); - while (codeFixes.Length != 0) - { - var operations = await codeFixes[0].Action.GetOperationsAsync(cancellationToken); - ApplyChangesOperation operation; - if ((operation = operations.OfType().FirstOrDefault()) != null) - { - // According to https://github.com/DotNetAnalyzers/StyleCopAnalyzers/pull/935 and - // https://github.com/dotnet/roslyn-sdk/issues/140, Sam Harwell mentioned that we should - // be forcing a re-parse of the document syntax tree at this point. - document = await operation.ChangedSolution.GetDocument(document.Id).RecreateDocumentAsync(cancellationToken); - // Retrieve the codefixes for the updated doc again. - codeFixes = await GetCodeFixes(document, codeFixName, analyzers, cancellationToken); - } - else - { - // If we got no applicable code fixes, exit the loop and move on to the next codefix. - break; - } - } - - return document; - } - - /// - /// Forces recreation of the text of a document. - /// - public static async Task RecreateDocumentAsync(this Document document, CancellationToken cancellationToken) - { - var newText = await document.GetTextAsync(cancellationToken); - newText = newText.WithChanges(new TextChange(new TextSpan(0, 0), " ")); - newText = newText.WithChanges(new TextChange(new TextSpan(0, 1), string.Empty)); - return document.WithText(newText); - } - - static async Task> GetCodeFixes( - Document document, string codeFixName, - ImmutableArray analyzers = default, CancellationToken cancellationToken = default) - { - var provider = GetCodeFixProvider(document, codeFixName); - if (provider == null) - return ImmutableArray.Empty; - - var compilation = await document.Project.GetCompilationAsync(cancellationToken); - // TODO: should we allow extending the set of built-in analyzers being added? - if (analyzers.IsDefaultOrEmpty) - analyzers = builtInAnalyzers.Value; - - var supportedAnalyers = analyzers - .Where(a => a.SupportedDiagnostics.Any(d => provider.FixableDiagnosticIds.Contains(d.Id))) - .ToImmutableArray(); - - var allDiagnostics = default(ImmutableArray); - - // This may be a compiler warning/error, not an analyzer-produced one, such as - // the missing abstract method implementations. - if (supportedAnalyers.IsEmpty) - { - allDiagnostics = compilation.GetDiagnostics(cancellationToken); - } - else - { - var analyerCompilation = compilation.WithAnalyzers(supportedAnalyers, cancellationToken: cancellationToken); - allDiagnostics = await analyerCompilation.GetAllDiagnosticsAsync(cancellationToken); - } - - var diagnostics = allDiagnostics - .Where(x => provider.FixableDiagnosticIds.Contains(x.Id)) - // Only consider the diagnostics raised by the target document. - .Where(d => - d.Location.Kind == LocationKind.SourceFile && - d.Location.GetLineSpan().Path == document.FilePath); - - var codeFixes = new List(); - foreach (var diagnostic in diagnostics) - { - await provider.RegisterCodeFixesAsync( - new CodeFixContext(document, diagnostic, - (action, diag) => codeFixes.Add(new CodeFixAdapter(action, diag, codeFixName)), - cancellationToken)); - } - - var finalFixes = new List(); - - // All code actions without equivalence keys must be applied individually. - finalFixes.AddRange(codeFixes.Where(x => x.Action.EquivalenceKey == null)); - // All code actions with the same equivalence key should be applied only once. - finalFixes.AddRange(codeFixes - .Where(x => x.Action.EquivalenceKey != null) - .GroupBy(x => x.Action.EquivalenceKey) - .Select(x => x.First())); - - return finalFixes.ToImmutableArray(); - } - - // Debug view of all available providers and their metadata - // document.Project.Solution.Workspace.Services.HostServices.GetExports>().OrderBy(x => x.Metadata["Name"]?.ToString()).Select(x => $"{x.Metadata["Name"]}: {string.Join(", ", (string[])x.Metadata["Languages"])}" ).ToList() - static CodeFixProvider GetCodeFixProvider(Document document, string codeFixName) - => document.Project.Solution.Workspace.Services.HostServices - .GetExports>() - .Where(x => - x.Metadata.ContainsKey("Languages") && x.Metadata.ContainsKey("Name") && - x.Metadata["Languages"] is string[] languages && - languages.Contains(document.Project.Language) && - x.Metadata["Name"] is string name && name == codeFixName) - .Select(x => x.Value) - .FirstOrDefault(); - } -} diff --git a/src/Stunts/Stunts.Sdk/GlobalSuppressions.cs b/src/Stunts/Stunts.Sdk/GlobalSuppressions.cs deleted file mode 100644 index 36e74184..00000000 --- a/src/Stunts/Stunts.Sdk/GlobalSuppressions.cs +++ /dev/null @@ -1,8 +0,0 @@ - -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "False positives on expression-bodied members.")] - diff --git a/src/Stunts/Stunts.Sdk/HostServicesExtensions.cs b/src/Stunts/Stunts.Sdk/HostServicesExtensions.cs deleted file mode 100644 index ee6aeed5..00000000 --- a/src/Stunts/Stunts.Sdk/HostServicesExtensions.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Reflection; -using Microsoft.CodeAnalysis.Host; - -namespace Microsoft.CodeAnalysis -{ - /// - /// Extension methods for , to allow accessing its MEF exports. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class HostServiceExtensions - { - static readonly ConcurrentDictionary, Delegate> getExportsCache = new ConcurrentDictionary, Delegate>(); - - /// - /// Gets the exports and their metadata. - /// - /// The type of MEF extension to retrieve. - /// The metadata of the exported MEF extension. - public static IEnumerable> GetExports(this HostServices services) - { - var getExports = getExportsCache.GetOrAdd(Tuple.Create(services.GetType(), typeof(TExtension), typeof(TMetadata)), - _ => - { - var method = services.GetType() - .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) - .Where(m => m.Name.EndsWith("GetExports") && - m.IsGenericMethodDefinition && - m.GetGenericArguments().Length == 2) - .FirstOrDefault(); - - Func>> func; - - if (method == null) - { - func = () => Enumerable.Empty>(); - } - else - { - var generic = method.MakeGenericMethod(typeof(TExtension), typeof(TMetadata)); - func = () => (IEnumerable>)generic.Invoke(services, null); - } - - return func; - }); - - return ((Func>>)getExports).Invoke(); - } - } -} diff --git a/src/Stunts/Stunts.Sdk/ICodeFix.cs b/src/Stunts/Stunts.Sdk/ICodeFix.cs deleted file mode 100644 index 74e6ca9b..00000000 --- a/src/Stunts/Stunts.Sdk/ICodeFix.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Immutable; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; - -namespace Stunts -{ - /// - /// A code fix that can be applied to a for - /// the given set of . - /// - interface ICodeFix - { - /// - /// The that applies the fix. - /// - CodeAction Action { get; } - - /// - /// The diagnostics that can be fixed by the . - /// - ImmutableArray Diagnostics { get; } - - /// - /// The name of the . - /// - string Provider { get; } - } -} diff --git a/src/Stunts/Stunts.Sdk/IDocumentProcessor.cs b/src/Stunts/Stunts.Sdk/IDocumentProcessor.cs deleted file mode 100644 index 0e0efcba..00000000 --- a/src/Stunts/Stunts.Sdk/IDocumentProcessor.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; - -namespace Stunts -{ - /// - /// Interface implemented by components that participate in stunt code generation. - /// - public interface IDocumentProcessor - { - /// - /// Gets the languages the document processor supports. - /// - string[] Languages { get; } - - /// - /// Gets the phase at which an acts. - /// - ProcessorPhase Phase { get; } - - /// - /// Processes the stunt document and optionally modifies its source code. - /// - Task ProcessAsync(Document document, CancellationToken cancellationToken = default); - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/OverridableMembersAnalyzer.cs b/src/Stunts/Stunts.Sdk/OverridableMembersAnalyzer.cs deleted file mode 100644 index f65c570d..00000000 --- a/src/Stunts/Stunts.Sdk/OverridableMembersAnalyzer.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System.Collections.Immutable; -using System.ComponentModel; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Stunts -{ - /// - /// Analyzer that flags types that have overridable members as - /// exposed by . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] - public class OverridableMembersAnalyzer : DiagnosticAnalyzer - { - /// - /// The diagnostics identifier exposed by this analyzer, ST999. - /// - public const string DiagnosticId = "ST999"; - /// - /// The category for the diagnostics reported by this analyzer, Build. - /// - public const string Category = "Build"; - - static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( - DiagnosticId, - nameof(OverridableMembersAnalyzer), - nameof(OverridableMembersAnalyzer), - Category, - DiagnosticSeverity.Hidden, isEnabledByDefault: true); - - /// - /// Reports the only supported rule by this analyzer. - /// - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); - - /// - /// Registers the analyzer for both C# and VB class declarations. - /// - /// - public override void Initialize(AnalysisContext context) - { - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, Microsoft.CodeAnalysis.CSharp.SyntaxKind.ClassDeclaration); - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.ClassBlock); - } - - static void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) - { - var symbol = context.Compilation.GetSemanticModel(context.Node.SyntaxTree).GetDeclaredSymbol(context.Node) as INamedTypeSymbol; - if (symbol == null) - return; - - var overridable = RoslynInternals.GetOverridableMembers(symbol, context.CancellationToken); - - if (context.Node.Language == LanguageNames.VisualBasic) - overridable = overridable.Where(x => x.MetadataName != WellKnownMemberNames.DestructorName) - // VB doesn't support overriding events (yet). See https://github.com/dotnet/vblang/issues/63 - .Where(x => x.Kind != SymbolKind.Event) - .ToImmutableArray(); - - if (overridable.Length != 0) - { - var diagnostic = Diagnostic.Create(Rule, context.Node.GetLocation()); - context.ReportDiagnostic(diagnostic); - } - } - } -} diff --git a/src/Stunts/Stunts.Sdk/ProcessorPhase.cs b/src/Stunts/Stunts.Sdk/ProcessorPhase.cs deleted file mode 100644 index ec8ce966..00000000 --- a/src/Stunts/Stunts.Sdk/ProcessorPhase.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; - -namespace Stunts -{ - /// - /// The phase at which an acts. - /// - public enum ProcessorPhase - { - /// - /// Initial stunt generation phase where the basic imports, namespace and - /// blank stunt class declaration and initial base type and implemented interfaces - /// are laid out in the doc. This is typically the phase were additional interfaces - /// can be injected to participate in the subsequent phases automatically. - /// - /// - /// Moq's IMocked interface is registered in this phase, for example. - /// - Prepare, - - /// - /// Phase that generates the basic boilerplate for all abstract and interface members, - /// that typically have default implementations that basically throw . - /// For C# and VB, this is achieved by executing the built-in code fixes for abstract - /// class and interface default implementations. - /// - Scaffold, - - /// - /// Executed right after scaffold, this phase performs the initial stunt implementation rewriting - /// by replacing methods that throw generated during scaffold - /// and invokes the instead for each of them. - /// - Rewrite, - - /// - /// Final phase that allows generators to perform additional generation beyond scaffold - /// and initial stunt rewriting. Members generated in this phase are not rewritten at all - /// to use the and can consist of language-specific fixups - /// or cleanups to make the generated code more idiomatic than the default code fixes may - /// provide. - /// - Fixup, - } -} diff --git a/src/Stunts/Stunts.Sdk/Processors/CSharpCompilerGenerated.cs b/src/Stunts/Stunts.Sdk/Processors/CSharpCompilerGenerated.cs deleted file mode 100644 index f25700e6..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/CSharpCompilerGenerated.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Editing; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace Stunts.Processors -{ - /// - /// Adds a - /// attribute to all generated members, so that it's possible to distinguish user-authored - /// members in a partial class from the generated code. - /// - public class CSharpCompilerGenerated : IDocumentProcessor - { - /// - /// Applies to only. - /// - public string[] Languages { get; } = new[] { LanguageNames.CSharp }; - - /// - /// Runs in the final phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Fixup; - - /// - /// Applies the attribute to all members in the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var syntax = await document.GetSyntaxRootAsync(cancellationToken); - syntax = new CSharpRewriteVisitor(SyntaxGenerator.GetGenerator(document)).Visit(syntax); - - return document.WithSyntaxRoot(syntax); - } - - class CSharpRewriteVisitor : CSharpSyntaxRewriter - { - SyntaxGenerator generator; - - public CSharpRewriteVisitor(SyntaxGenerator generator) => this.generator = generator; - - public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitMethodDeclaration(node); - - return base.VisitMethodDeclaration((MethodDeclarationSyntax)AddAttributes(node)); - } - - public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitPropertyDeclaration(node); - - return base.VisitPropertyDeclaration((PropertyDeclarationSyntax)AddAttributes(node)); - } - - public override SyntaxNode VisitIndexerDeclaration(IndexerDeclarationSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitIndexerDeclaration(node); - - return base.VisitIndexerDeclaration((IndexerDeclarationSyntax)AddAttributes(node)); - } - - public override SyntaxNode VisitEventDeclaration(EventDeclarationSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitEventDeclaration(node); - - return base.VisitEventDeclaration((EventDeclarationSyntax)AddAttributes(node)); - } - - SyntaxNode AddAttributes(SyntaxNode node) - => generator.AddAttributes(node, - Attribute(IdentifierName("CompilerGenerated")), - Attribute(IdentifierName("GeneratedCode"), - AttributeArgumentList(SeparatedList(new[] - { - AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(nameof(Stunts)))), - AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(ThisAssembly.Metadata.PackageVersion))), - }))) - ); - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/Processors/CSharpFileHeader.cs b/src/Stunts/Stunts.Sdk/Processors/CSharpFileHeader.cs deleted file mode 100644 index 9602b7e5..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/CSharpFileHeader.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace Stunts.Processors -{ - /// - /// Adds the auto-generated file header that flags the - /// document as a generated one. - /// - public class CSharpFileHeader : IDocumentProcessor - { - const string header = @"//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -"; - - /// - /// Applies to only. - /// - public string[] Languages { get; } = new[] { LanguageNames.CSharp }; - - /// - /// Runs in the final phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Fixup; - - /// - /// Adds the auto-generated file header to the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var syntax = await document.GetSyntaxRootAsync(cancellationToken); - - return document.WithSyntaxRoot(syntax.WithLeadingTrivia(Comment(header))); - } - } -} diff --git a/src/Stunts/Stunts.Sdk/Processors/CSharpRewrite.cs b/src/Stunts/Stunts.Sdk/Processors/CSharpRewrite.cs deleted file mode 100644 index b51ddd85..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/CSharpRewrite.cs +++ /dev/null @@ -1,199 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Editing; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace Stunts.Processors -{ - /// - /// Rewrites all members so they are implemented through - /// the field added to the - /// class by the . - /// - public class CSharpRewrite : IDocumentProcessor - { - /// - /// Applies to only. - /// - public string[] Languages { get; } = new[] { LanguageNames.CSharp }; - - /// - /// Runs in the third phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Rewrite; - - /// - /// Rewrites all members in the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var syntax = await document.GetSyntaxRootAsync(cancellationToken); - syntax = new CSharpRewriteVisitor(document).Visit(syntax); - - return document.WithSyntaxRoot(syntax); - } - - class CSharpRewriteVisitor : CSharpSyntaxRewriter - { - SyntaxGenerator generator; - Document document; - - public CSharpRewriteVisitor(Document document) - { - this.document = document; - generator = SyntaxGenerator.GetGenerator(document); - } - - public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) - { - // Turn event fields into event declarations. - var events = node.ChildNodes().OfType().ToArray(); - node = node.RemoveNodes(events, SyntaxRemoveOptions.KeepNoTrivia); - - node = node.AddMembers(events - .Select(x => EventDeclaration(x.Declaration.Type, x.Declaration.Variables.First().Identifier) - .WithModifiers(x.Modifiers)) - .ToArray()); - - return node = (ClassDeclarationSyntax)base.VisitClassDeclaration(node); - } - - public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitMethodDeclaration(node); - - var outParams = node.ParameterList.Parameters.Where(x => x.Modifiers.Any(SyntaxKind.OutKeyword)).ToArray(); - var refOutParams = node.ParameterList.Parameters.Where(x => x.Modifiers.Any(SyntaxKind.RefKeyword) || x.Modifiers.Any(SyntaxKind.OutKeyword)).ToArray(); - - if (outParams.Length != 0 || refOutParams.Length != 0) - { - node = (MethodDeclarationSyntax)generator.ImplementMethod(node, node.ReturnType.IsVoid() ? null : node.ReturnType, outParams, refOutParams); - } - else - { - if (node.Body != null) - node = node.RemoveNodes(new SyntaxNode[] { node.Body }, SyntaxRemoveOptions.KeepNoTrivia); - - node = node.WithExpressionBody( - ArrowExpressionClause(ExecutePipeline(node.ReturnType, node.ParameterList.Parameters))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - } - - return base.VisitMethodDeclaration(node); - } - - public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitPropertyDeclaration(node); - - (var canRead, var canWrite) = generator.InspectProperty(node); - canRead = canRead || node.ExpressionBody != null; - - if (node.ExpressionBody != null) - node = node.RemoveNode(node.ExpressionBody, SyntaxRemoveOptions.KeepNoTrivia); - - node = node.WithAccessorList(null); - - if (canRead && !canWrite) - { - node = node - .WithExpressionBody(ArrowExpressionClause(ExecutePipeline(node.Type, Enumerable.Empty()))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - } - else - { - if (canRead) - { - node = node.AddAccessorListAccessors(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) - .WithExpressionBody(ArrowExpressionClause(ExecutePipeline(node.Type, Enumerable.Empty()))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); - } - if (canWrite) - { - node = node.AddAccessorListAccessors(AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) - .WithExpressionBody(ArrowExpressionClause( - // NOTE: we always append the implicit "value" parameter for setters. - ExecutePipeline(null, new[] { Parameter(Identifier("value")).WithType(node.Type) }))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); - } - } - - return base.VisitPropertyDeclaration(node); - } - - public override SyntaxNode VisitIndexerDeclaration(IndexerDeclarationSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitIndexerDeclaration(node); - - var trivia = node.GetTrailingTrivia(); - - // NOTE: Most of this code could be shared with VisitPropertyDeclaration but the mutating With* - // and props like ExpressionBody aren't available in the shared base BasePropertyDeclarationSyntax type :( - var canRead = (node.ExpressionBody != null || node.AccessorList?.Accessors.Any(x => x.IsKind(SyntaxKind.GetAccessorDeclaration)) == true); - var canWrite = node.AccessorList?.Accessors.Any(x => x.IsKind(SyntaxKind.SetAccessorDeclaration)) == true; - if (node.ExpressionBody != null) - node = node.RemoveNode(node.ExpressionBody, SyntaxRemoveOptions.KeepNoTrivia); - if (node.AccessorList?.Accessors.Any() == true) - node = node.RemoveNodes(node.AccessorList.Accessors, SyntaxRemoveOptions.KeepNoTrivia); - - if (canRead && !canWrite) - { - node = node.WithExpressionBody( - ArrowExpressionClause(ExecutePipeline(node.Type, node.ParameterList.Parameters))); - } - else - { - if (canRead) - { - node = node.AddAccessorListAccessors(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) - .WithExpressionBody(ArrowExpressionClause(ExecutePipeline(node.Type, node.ParameterList.Parameters))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); - } - if (canWrite) - { - node = node.AddAccessorListAccessors(AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) - .WithExpressionBody(ArrowExpressionClause( - ExecutePipeline(null, node.ParameterList.Parameters.Concat(new[] { Parameter(Identifier("value")).WithType(node.Type) })))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); - } - } - - return base.VisitIndexerDeclaration(node.WithTrailingTrivia(trivia)); - } - - public override SyntaxNode VisitEventDeclaration(EventDeclarationSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitEventDeclaration(node); - - var parameters = new[] { Parameter(Identifier("value")).WithType(node.Type) }; - node = node.WithAccessorList( - AccessorList( - List(new AccessorDeclarationSyntax[] - { - AccessorDeclaration(SyntaxKind.AddAccessorDeclaration) - .WithExpressionBody( - ArrowExpressionClause(ExecutePipeline(node.Type, parameters))) - .WithSemicolon(), - AccessorDeclaration(SyntaxKind.RemoveAccessorDeclaration) - .WithExpressionBody( - ArrowExpressionClause(ExecutePipeline(node.Type, parameters))) - .WithSemicolon() - }))); - - return base.VisitEventDeclaration(node); - } - - ExpressionSyntax ExecutePipeline(TypeSyntax returnType, IEnumerable parameters) - => (ExpressionSyntax)generator.ExecutePipeline(returnType.IsVoid() ? null : returnType, parameters); - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/Processors/CSharpScaffold.cs b/src/Stunts/Stunts.Sdk/Processors/CSharpScaffold.cs deleted file mode 100644 index 1d7bd19a..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/CSharpScaffold.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editing; - -namespace Stunts.Processors -{ - /// - /// Applies a set of code fixes that scaffold empty implementations - /// of all abstract class, interface and overridable members. - /// - public class CSharpScaffold : IDocumentProcessor - { - /// - /// Default code fixes when no specific fixes are provided. - /// - static readonly string[] DefaultCodeFixNames = - { - CodeFixNames.CSharp.ImplementAbstractClass, - CodeFixNames.CSharp.ImplementInterface, - "OverrideAllMembersCodeFix", - }; - - readonly string[] codeFixNames; - - /// - /// Initializes the scaffold with the . - /// - public CSharpScaffold() : this(DefaultCodeFixNames) { } - - /// - /// Initializes the scaffold with a specific set of code fixes to apply. - /// - public CSharpScaffold(params string[] codeFixNames) => this.codeFixNames = codeFixNames; - - /// - /// Applies to only. - /// - public string[] Languages { get; } = new[] { LanguageNames.CSharp }; - - /// - /// Runs in the second phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Scaffold; - - /// - /// Applies all existing code fixes to the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var generator = SyntaxGenerator.GetGenerator(document); - - foreach (var codeFixName in codeFixNames) - { - document = await document.ApplyCodeFixAsync(codeFixName, cancellationToken: cancellationToken); - } - - return document; - } - } -} diff --git a/src/Stunts/Stunts.Sdk/Processors/CSharpStunt.cs b/src/Stunts/Stunts.Sdk/Processors/CSharpStunt.cs deleted file mode 100644 index 8a3cf302..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/CSharpStunt.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Editing; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace Stunts.Processors -{ - /// - /// Adds the interface implementation. - /// - public class CSharpStunt : IDocumentProcessor - { - /// - /// Applies to only. - /// - public string[] Languages { get; } = new[] { LanguageNames.CSharp }; - - /// - /// Runs in the final phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Fixup; - - /// - /// Adds the interface implementation to the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var syntax = await document.GetSyntaxRootAsync(cancellationToken); - syntax = new CSharpStuntVisitor(document).Visit(syntax); - - return document.WithSyntaxRoot(syntax); - } - - class CSharpStuntVisitor : CSharpSyntaxRewriter - { - SyntaxGenerator generator; - Document document; - - public CSharpStuntVisitor(Document document) - { - this.document = document; - generator = SyntaxGenerator.GetGenerator(document); - } - - public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) - { - node = (ClassDeclarationSyntax)base.VisitClassDeclaration(node); - - if (!generator.GetBaseAndInterfaceTypes(node).Any(x => - x.ToString() == nameof(IStunt) || - x.ToString() == typeof(IStunt).FullName)) - { - // Only add the base type if it isn't already there - node = node.AddBaseListTypes(SimpleBaseType(IdentifierName(nameof(IStunt)))); - } - - if (!generator.GetMembers(node).Any(x => generator.GetName(x) == nameof(IStunt.Behaviors))) - { - node = (ClassDeclarationSyntax)generator.InsertMembers(node, 0, - PropertyDeclaration( - GenericName( - Identifier("ObservableCollection"), - TypeArgumentList(SingletonSeparatedList(IdentifierName(nameof(IStuntBehavior))))), - Identifier(nameof(IStunt.Behaviors))) - .WithExplicitInterfaceSpecifier(ExplicitInterfaceSpecifier(IdentifierName(nameof(IStunt)))) - .WithExpressionBody(ArrowExpressionClause( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("pipeline"), - IdentifierName("Behaviors")))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) - .NormalizeWhitespace() - .WithTrailingTrivia(CarriageReturnLineFeed, CarriageReturnLineFeed) - ); - } - - if (!generator.GetMembers(node).Any(x => generator.GetName(x) == "pipeline")) - { - node = (ClassDeclarationSyntax)generator.InsertMembers(node, 0, - FieldDeclaration( - VariableDeclaration(IdentifierName(Identifier(nameof(BehaviorPipeline)))) - .WithVariables( - SingletonSeparatedList( - VariableDeclarator(Identifier("pipeline")) - .WithInitializer( - EqualsValueClause( - ObjectCreationExpression(IdentifierName(nameof(BehaviorPipeline))) - .WithArgumentList(ArgumentList()))))) - .NormalizeWhitespace() - ).WithModifiers(TokenList(Token(SyntaxKind.ReadOnlyKeyword)))); - } - - return node; - } - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/Processors/CSharpSyntaxExtensions.cs b/src/Stunts/Stunts.Sdk/Processors/CSharpSyntaxExtensions.cs deleted file mode 100644 index 9032e1db..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/CSharpSyntaxExtensions.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace Stunts.Processors -{ - /// - /// Usability overloads for the C# syntax. - /// - static class CSharpSyntaxExtensions - { - public static bool IsVoid(this TypeSyntax typeSyntax) - { - return typeSyntax.IsKind(SyntaxKind.PredefinedType) && - ((PredefinedTypeSyntax)typeSyntax).Keyword.IsKind(SyntaxKind.VoidKeyword); - } - - public static bool IsKind(this SyntaxToken token, SyntaxKind kind) - { - return token.RawKind == (int)kind; - } - - public static bool IsKind(this SyntaxNode node, SyntaxKind kind) - { - return node?.RawKind == (int)kind; - } - - public static AccessorDeclarationSyntax WithSemicolon(this AccessorDeclarationSyntax syntax) => - syntax.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - } -} diff --git a/src/Stunts/Stunts.Sdk/Processors/CodeFixNames.cs b/src/Stunts/Stunts.Sdk/Processors/CodeFixNames.cs deleted file mode 100644 index 30a80942..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/CodeFixNames.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Stunts.Processors -{ - /// - /// Well-known code fixes provided by Roslyn. - /// - /// - /// The CodeFixNames.g.cs is generated by running the CodeFixNamesGenerator ad-hoc test - /// in the Stunts.Tests project, which uses MEF to discover all the available built-in code fix names - /// provided by the version of Roslyn used for compiling. - /// - public static partial class CodeFixNames - { - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/Processors/CodeFixNames.g.cs b/src/Stunts/Stunts.Sdk/Processors/CodeFixNames.g.cs deleted file mode 100644 index 3ed258a5..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/CodeFixNames.g.cs +++ /dev/null @@ -1,193 +0,0 @@ -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member -namespace Stunts.Processors -{ - partial class CodeFixNames - { - public static partial class All - { - public const string AddAwait = "AddAwait"; - public const string AddBraces = "AddBraces"; - public const string AddDocCommentNodes = "AddDocCommentNodes"; - public const string AddImport = "AddImport"; - public const string AddMissingReference = "AddMissingReference"; - public const string AddNew = "AddNew"; - public const string AddOverloads = "AddOverloads"; - public const string AddParameter = "AddParameter"; - public const string AddParenthesesAroundConditionalExpressionInInterpolatedString = "AddParenthesesAroundConditionalExpressionInInterpolatedString"; - public const string AliasAmbiguousType = "AliasAmbiguousType"; - public const string ApplyNamingStyle = "ApplyNamingStyle"; - public const string ChangeReturnType = "ChangeReturnType"; - public const string ChangeToYield = "ChangeToYield"; - public const string ConvertToAsync = "ConvertToAsync"; - public const string ConvertToIterator = "ConvertToIterator"; - public const string CorrectNextControlVariable = "CorrectNextControlVariable"; - public const string CSharpAddObsoleteAttributeCodeFixProvider = "CSharpAddObsoleteAttributeCodeFixProvider"; - public const string CSharpConvertAnonymousTypeToTupleCodeFixProvider = "CSharpConvertAnonymousTypeToTupleCodeFixProvider"; - public const string CSharpUseAutoPropertyCodeFixProvider = "CSharpUseAutoPropertyCodeFixProvider"; - public const string DeclareAsNullable = "DeclareAsNullable"; - public const string FixFormatting = "FixFormatting"; - public const string FixIncorrectExitContinue = "FixIncorrectExitContinue"; - public const string FixIncorrectFunctionReturnType = "FixIncorrectFunctionReturnType"; - public const string FixReturnType = "FixReturnType"; - public const string FullyQualify = "FullyQualify"; - public const string GenerateConstructor = "GenerateConstructor"; - public const string GenerateConversion = "GenerateConversion"; - public const string GenerateDeconstructMethod = "GenerateDeconstructMethod"; - public const string GenerateEndConstruct = "GenerateEndConstruct"; - public const string GenerateEnumMember = "GenerateEnumMember"; - public const string GenerateEvent = "GenerateEvent"; - public const string GenerateMethod = "GenerateMethod"; - public const string GenerateType = "GenerateType"; - public const string GenerateVariable = "GenerateVariable"; - public const string ImplementAbstractClass = "ImplementAbstractClass"; - public const string ImplementInterface = "ImplementInterface"; - public const string InsertMissingCast = "InsertMissingCast"; - public const string InvokeDelegateWithConditionalAccessCodeFixProvider = "InvokeDelegateWithConditionalAccessCodeFixProvider"; - public const string MakeFieldReadonly = "MakeFieldReadonly"; - public const string MakeLocalFunctionStaticCodeFixProvider = "MakeLocalFunctionStaticCodeFixProvider"; - public const string MakeMethodSynchronous = "MakeMethodSynchronous"; - public const string MakeStatementAsynchronous = "MakeStatementAsynchronous"; - public const string MakeStructFieldsWritable = "MakeStructFieldsWritable"; - public const string MoveToTopOfFile = "MoveToTopOfFile"; - public const string PopulateSwitch = "PopulateSwitch"; - public const string PreferFrameworkType = "PreferFrameworkType"; - public const string QualifyMemberAccess = "QualifyMemberAccess"; - public const string RemoveDocCommentNode = "RemoveDocCommentNode"; - public const string RemoveUnnecessaryCast = "RemoveUnnecessaryCast"; - public const string RemoveUnnecessaryImports = "RemoveUnnecessaryImports"; - public const string RemoveUnreachableCode = "RemoveUnreachableCode"; - public const string RemoveUnusedLocalFunction = "RemoveUnusedLocalFunction"; - public const string RemoveUnusedMembers = "RemoveUnusedMembers"; - public const string RemoveUnusedValues = "RemoveUnusedValues"; - public const string RemoveUnusedVariable = "RemoveUnusedVariable"; - public const string ReplaceDefaultLiteral = "ReplaceDefaultLiteral"; - public const string SimplifyNames = "SimplifyNames"; - public const string SimplifyThisOrMe = "SimplifyThisOrMe"; - public const string SpellCheck = "SpellCheck"; - public const string UnsealClass = "UnsealClass"; - public const string UseCollectionInitializer = "UseCollectionInitializer"; - public const string UseExplicitType = "UseExplicitType"; - public const string UseExplicitTypeForConst = "UseExplicitTypeForConst"; - public const string UseImplicitType = "UseImplicitType"; - public const string UseObjectInitializer = "UseObjectInitializer"; - public const string UseSimpleUsingStatementCodeFixProvider = "UseSimpleUsingStatementCodeFixProvider"; - public const string UseThrowExpression = "UseThrowExpression"; - public const string VisualBasicAddObsoleteAttributeCodeFixProvider = "VisualBasicAddObsoleteAttributeCodeFixProvider"; - public const string VisualBasicConvertAnonymousTypeToTupleCodeFixProvider = "VisualBasicConvertAnonymousTypeToTupleCodeFixProvider"; - public const string VisualBasicUseAutoPropertyCodeFixProvider = "VisualBasicUseAutoPropertyCodeFixProvider"; - } - - public static partial class CSharp - { - public const string AddAwait = "AddAwait"; - public const string AddBraces = "AddBraces"; - public const string AddDocCommentNodes = "AddDocCommentNodes"; - public const string AddImport = "AddImport"; - public const string AddMissingReference = "AddMissingReference"; - public const string AddNew = "AddNew"; - public const string AddParameter = "AddParameter"; - public const string AddParenthesesAroundConditionalExpressionInInterpolatedString = "AddParenthesesAroundConditionalExpressionInInterpolatedString"; - public const string AliasAmbiguousType = "AliasAmbiguousType"; - public const string ApplyNamingStyle = "ApplyNamingStyle"; - public const string ChangeReturnType = "ChangeReturnType"; - public const string ChangeToYield = "ChangeToYield"; - public const string ConvertToAsync = "ConvertToAsync"; - public const string CSharpAddObsoleteAttributeCodeFixProvider = "CSharpAddObsoleteAttributeCodeFixProvider"; - public const string CSharpConvertAnonymousTypeToTupleCodeFixProvider = "CSharpConvertAnonymousTypeToTupleCodeFixProvider"; - public const string CSharpUseAutoPropertyCodeFixProvider = "CSharpUseAutoPropertyCodeFixProvider"; - public const string DeclareAsNullable = "DeclareAsNullable"; - public const string FixFormatting = "FixFormatting"; - public const string FixReturnType = "FixReturnType"; - public const string FullyQualify = "FullyQualify"; - public const string GenerateConstructor = "GenerateConstructor"; - public const string GenerateConversion = "GenerateConversion"; - public const string GenerateDeconstructMethod = "GenerateDeconstructMethod"; - public const string GenerateEnumMember = "GenerateEnumMember"; - public const string GenerateMethod = "GenerateMethod"; - public const string GenerateType = "GenerateType"; - public const string GenerateVariable = "GenerateVariable"; - public const string ImplementAbstractClass = "ImplementAbstractClass"; - public const string ImplementInterface = "ImplementInterface"; - public const string InvokeDelegateWithConditionalAccessCodeFixProvider = "InvokeDelegateWithConditionalAccessCodeFixProvider"; - public const string MakeLocalFunctionStaticCodeFixProvider = "MakeLocalFunctionStaticCodeFixProvider"; - public const string MakeMethodSynchronous = "MakeMethodSynchronous"; - public const string MakeStatementAsynchronous = "MakeStatementAsynchronous"; - public const string MakeStructFieldsWritable = "MakeStructFieldsWritable"; - public const string PopulateSwitch = "PopulateSwitch"; - public const string PreferFrameworkType = "PreferFrameworkType"; - public const string QualifyMemberAccess = "QualifyMemberAccess"; - public const string RemoveDocCommentNode = "RemoveDocCommentNode"; - public const string RemoveUnnecessaryCast = "RemoveUnnecessaryCast"; - public const string RemoveUnnecessaryImports = "RemoveUnnecessaryImports"; - public const string RemoveUnreachableCode = "RemoveUnreachableCode"; - public const string RemoveUnusedLocalFunction = "RemoveUnusedLocalFunction"; - public const string RemoveUnusedMembers = "RemoveUnusedMembers"; - public const string RemoveUnusedValues = "RemoveUnusedValues"; - public const string RemoveUnusedVariable = "RemoveUnusedVariable"; - public const string ReplaceDefaultLiteral = "ReplaceDefaultLiteral"; - public const string SimplifyNames = "SimplifyNames"; - public const string SimplifyThisOrMe = "SimplifyThisOrMe"; - public const string SpellCheck = "SpellCheck"; - public const string UnsealClass = "UnsealClass"; - public const string UseCollectionInitializer = "UseCollectionInitializer"; - public const string UseExplicitType = "UseExplicitType"; - public const string UseExplicitTypeForConst = "UseExplicitTypeForConst"; - public const string UseImplicitType = "UseImplicitType"; - public const string UseObjectInitializer = "UseObjectInitializer"; - public const string UseSimpleUsingStatementCodeFixProvider = "UseSimpleUsingStatementCodeFixProvider"; - public const string UseThrowExpression = "UseThrowExpression"; - } - - public static partial class VisualBasic - { - public const string AddAwait = "AddAwait"; - public const string AddImport = "AddImport"; - public const string AddMissingReference = "AddMissingReference"; - public const string AddOverloads = "AddOverloads"; - public const string AddParameter = "AddParameter"; - public const string AliasAmbiguousType = "AliasAmbiguousType"; - public const string ApplyNamingStyle = "ApplyNamingStyle"; - public const string ChangeToYield = "ChangeToYield"; - public const string ConvertToAsync = "ConvertToAsync"; - public const string ConvertToIterator = "ConvertToIterator"; - public const string CorrectNextControlVariable = "CorrectNextControlVariable"; - public const string FixFormatting = "FixFormatting"; - public const string FixIncorrectExitContinue = "FixIncorrectExitContinue"; - public const string FixIncorrectFunctionReturnType = "FixIncorrectFunctionReturnType"; - public const string FullyQualify = "FullyQualify"; - public const string GenerateConstructor = "GenerateConstructor"; - public const string GenerateConversion = "GenerateConversion"; - public const string GenerateEndConstruct = "GenerateEndConstruct"; - public const string GenerateEnumMember = "GenerateEnumMember"; - public const string GenerateEvent = "GenerateEvent"; - public const string GenerateMethod = "GenerateMethod"; - public const string GenerateType = "GenerateType"; - public const string GenerateVariable = "GenerateVariable"; - public const string ImplementAbstractClass = "ImplementAbstractClass"; - public const string ImplementInterface = "ImplementInterface"; - public const string InsertMissingCast = "InsertMissingCast"; - public const string MakeFieldReadonly = "MakeFieldReadonly"; - public const string MakeMethodSynchronous = "MakeMethodSynchronous"; - public const string MoveToTopOfFile = "MoveToTopOfFile"; - public const string PopulateSwitch = "PopulateSwitch"; - public const string PreferFrameworkType = "PreferFrameworkType"; - public const string QualifyMemberAccess = "QualifyMemberAccess"; - public const string RemoveDocCommentNode = "RemoveDocCommentNode"; - public const string RemoveUnnecessaryCast = "RemoveUnnecessaryCast"; - public const string RemoveUnnecessaryImports = "RemoveUnnecessaryImports"; - public const string RemoveUnusedMembers = "RemoveUnusedMembers"; - public const string RemoveUnusedValues = "RemoveUnusedValues"; - public const string RemoveUnusedVariable = "RemoveUnusedVariable"; - public const string SimplifyNames = "SimplifyNames"; - public const string SimplifyThisOrMe = "SimplifyThisOrMe"; - public const string SpellCheck = "SpellCheck"; - public const string UnsealClass = "UnsealClass"; - public const string UseCollectionInitializer = "UseCollectionInitializer"; - public const string UseObjectInitializer = "UseObjectInitializer"; - public const string VisualBasicAddObsoleteAttributeCodeFixProvider = "VisualBasicAddObsoleteAttributeCodeFixProvider"; - public const string VisualBasicConvertAnonymousTypeToTupleCodeFixProvider = "VisualBasicConvertAnonymousTypeToTupleCodeFixProvider"; - public const string VisualBasicUseAutoPropertyCodeFixProvider = "VisualBasicUseAutoPropertyCodeFixProvider"; - } - } -} -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member diff --git a/src/Stunts/Stunts.Sdk/Processors/DefaultImports.cs b/src/Stunts/Stunts.Sdk/Processors/DefaultImports.cs deleted file mode 100644 index e5c44004..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/DefaultImports.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editing; - -namespace Stunts.Processors -{ - /// - /// Adds a set of default imports to a document. - /// - public class DefaultImports : IDocumentProcessor - { - // These namespaces are used by the default stunt code and are always imported. - static readonly string[] DefaultNamespaces = - { - typeof(EventArgs).Namespace, - typeof(GeneratedCodeAttribute).Namespace, - typeof(ObservableCollection<>).Namespace, - typeof(DebuggerDisplayAttribute).Namespace, - typeof(MethodBase).Namespace, - typeof(CompilerGeneratedAttribute).Namespace, - typeof(IStunt).Namespace, - }; - - readonly string[] namespaces; - - /// - /// Initializes the default imports with the . - /// - public DefaultImports() : this(DefaultNamespaces) { } - - /// - /// Initializes the default imports with a specific set of namespaces to add. - /// - public DefaultImports(params string[] namespaces) => this.namespaces = namespaces; - - /// - /// Applies to both and . - /// - public string[] Languages { get; } = new[] { LanguageNames.CSharp, LanguageNames.VisualBasic }; - - /// - /// Runs in the first phase of code gen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Prepare; - - /// - /// Adds the configured set namespaces to the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var generator = SyntaxGenerator.GetGenerator(document); - var root = await document.GetSyntaxRootAsync(); - var imports = generator.GetNamespaceImports(root).Select(generator.GetName); - - var missing = new HashSet(namespaces); - missing.ExceptWith(imports); - - if (missing.Count == 0) - return document; - - return document.WithSyntaxRoot(generator.AddNamespaceImports(root, - missing.Select(generator.NamespaceImportDeclaration))); - } - } -} diff --git a/src/Stunts/Stunts.Sdk/Processors/FixupImports.cs b/src/Stunts/Stunts.Sdk/Processors/FixupImports.cs deleted file mode 100644 index 0c5207b3..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/FixupImports.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.VisualBasic; -using Microsoft.CodeAnalysis.VisualBasic.Syntax; - -namespace Stunts.Processors -{ - /// - /// Removes unnecessary imports and sorts the used ones. - /// - public class FixupImports : IDocumentProcessor - { - /// - /// Applies to both and . - /// - public string[] Languages { get; } = new[] { LanguageNames.CSharp, LanguageNames.VisualBasic }; - - /// - /// Runs in the last phase of code gen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Fixup; - - /// - /// Removes and sorts namespaces. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - // This codefix is available for both C# and VB - //document = await document.ApplyCodeFixAsync(CodeFixNames.All.RemoveUnnecessaryImports); - - var generator = SyntaxGenerator.GetGenerator(document); - var syntax = await document.GetSyntaxRootAsync(); - var imports = generator.GetNamespaceImports(syntax).Select(generator.GetName).ToArray(); - - Array.Sort(imports); - - if (document.Project.Language == LanguageNames.CSharp) - syntax = new CSharpRewriteVisitor().Visit(syntax); - else - syntax = new VisualBasicRewriteVisitor().Visit(syntax); - - return document.WithSyntaxRoot(generator.AddNamespaceImports(syntax, - imports.Select(generator.NamespaceImportDeclaration))); - } - - class CSharpRewriteVisitor : CSharpSyntaxRewriter - { - public override SyntaxNode VisitCompilationUnit(Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax node) - => base.VisitCompilationUnit(node.WithUsings( - Microsoft.CodeAnalysis.CSharp.SyntaxFactory.List())); - } - - class VisualBasicRewriteVisitor : VisualBasicSyntaxRewriter - { - public override SyntaxNode VisitCompilationUnit(Microsoft.CodeAnalysis.VisualBasic.Syntax.CompilationUnitSyntax node) - => base.VisitCompilationUnit(node.WithImports( - Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.List())); - } - } -} diff --git a/src/Stunts/Stunts.Sdk/Processors/SyntaxGeneratorExtensions.cs b/src/Stunts/Stunts.Sdk/Processors/SyntaxGeneratorExtensions.cs deleted file mode 100644 index 9d7b2258..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/SyntaxGeneratorExtensions.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editing; - -namespace Stunts.Processors -{ - /// - /// Language agnostic helper methods for code generation. - /// - static class SyntaxGeneratorExtensions - { - /// - /// Inspects a property to determine if supports read/write. - /// - public static (bool canRead, bool canWrite) InspectProperty(this SyntaxGenerator generator, SyntaxNode property) - { - return ( - generator.GetAccessor(property, DeclarationKind.GetAccessor) != null, - generator.GetAccessor(property, DeclarationKind.SetAccessor) != null - ); - } - - /// - /// Replaces a method's body by invoking the behavior pipeline. - /// - public static SyntaxNode ImplementMethod(this SyntaxGenerator generator, SyntaxNode method, SyntaxNode returnType) - { - if (returnType != null) - { - return generator.WithStatements(method, new[] - { - generator.ReturnStatement(generator.ExecutePipeline(returnType, generator.GetParameters(method))) - }); - } - - return generator.WithStatements(method, new[] - { - generator.ExecutePipeline(returnType, generator.GetParameters(method)) - }); - } - - /// - /// Replaces the implementation of a method with ref/out parameters by invoking the behavior pipeline. - /// - public static SyntaxNode ImplementMethod(this SyntaxGenerator generator, - SyntaxNode method, SyntaxNode returnType, SyntaxNode[] outParams, SyntaxNode[] refOutParams) - { - var statements = outParams.Select(x => generator.AssignmentStatement( - generator.IdentifierName(generator.GetName(x)), - generator.DefaultExpression(generator.GetType(x)))) - .ToList(); - - statements.Add(generator.LocalDeclarationStatement( - generator.IdentifierName(nameof(IMethodReturn)), - "returns", - generator.ExecutePipeline(null, generator.GetParameters(method)))); - - statements.AddRange(refOutParams.Select(x => - generator.AssignmentStatement( - generator.IdentifierName(generator.GetName(x)), - generator.CastExpression( - generator.GetType(x), - generator.ElementAccessExpression( - generator.MemberAccessExpression( - generator.IdentifierName("returns"), - nameof(IMethodReturn.Outputs)), - generator.LiteralExpression(generator.GetName(x)) - ) - ) - ) - )); - - if (returnType != null) - { - statements.Add(generator.ReturnStatement( - generator.CastExpression( - returnType, - generator.MemberAccessExpression( - generator.IdentifierName("returns"), - nameof(IMethodReturn.ReturnValue))))); - } - - return generator.WithStatements(method, statements); - } - - /// - /// Creates the pipeline.Execute method invocation. - /// - public static SyntaxNode ExecutePipeline(this SyntaxGenerator generator, SyntaxNode returnType, IEnumerable parameters) - { - var execute = (returnType == null) ? - generator.IdentifierName("Execute") : - generator.GenericName("Execute", returnType); - - return generator.InvocationExpression( - generator.MemberAccessExpression( - generator.IdentifierName("pipeline"), - execute), - CreateMethodInvocation(generator, parameters) - ); - } - - /// - /// Creates the instance of the passed to the behavior pipeline. - /// - static SyntaxNode CreateMethodInvocation(SyntaxGenerator generator, IEnumerable parameters) => - generator.ObjectCreationExpression( - generator.IdentifierName(nameof(MethodInvocation)), - new[] - { - generator.ThisExpression(), - generator.InvocationExpression( - generator.MemberAccessExpression( - generator.IdentifierName(nameof(MethodBase)), - nameof(MethodBase.GetCurrentMethod))), - } - .Concat(parameters.Select(x => generator.Argument(generator.IdentifierName(generator.GetName(x)))))); - } -} diff --git a/src/Stunts/Stunts.Sdk/Processors/VisualBasicCompilerGenerated.cs b/src/Stunts/Stunts.Sdk/Processors/VisualBasicCompilerGenerated.cs deleted file mode 100644 index ce4f4a45..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/VisualBasicCompilerGenerated.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.VisualBasic; -using Microsoft.CodeAnalysis.VisualBasic.Syntax; -using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory; - -namespace Stunts.Processors -{ - /// - /// Adds a - /// attribute to all generated members, so that it's possible to distinguish user-authored - /// members in a partial class from the generated code. - /// - public class VisualBasicCompilerGenerated : IDocumentProcessor - { - /// - /// Applies to the . - /// - public string[] Languages { get; } = new[] { LanguageNames.VisualBasic }; - - /// - /// Runs in the final phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Fixup; - - /// - /// Applies the attribute to all members in the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var syntax = await document.GetSyntaxRootAsync(cancellationToken); - syntax = new VisualBasicRewriteVisitor(SyntaxGenerator.GetGenerator(document)).Visit(syntax); - - return document.WithSyntaxRoot(syntax); - } - - class VisualBasicRewriteVisitor : VisualBasicSyntaxRewriter - { - SyntaxGenerator generator; - - public VisualBasicRewriteVisitor(SyntaxGenerator generator) => this.generator = generator; - - public override SyntaxNode VisitMethodBlock(MethodBlockSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitMethodBlock(node); - - return base.VisitMethodBlock((MethodBlockSyntax)AddAttributes(node)); - } - - public override SyntaxNode VisitPropertyBlock(PropertyBlockSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitPropertyBlock(node); - - return base.VisitPropertyBlock((PropertyBlockSyntax)AddAttributes(node)); - } - - public override SyntaxNode VisitEventBlock(EventBlockSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitEventBlock(node); - - return base.VisitEventBlock((EventBlockSyntax)AddAttributes(node)); - } - - SyntaxNode AddAttributes(SyntaxNode node) - => generator.AddAttributes(node, - Attribute(IdentifierName("CompilerGenerated")), - Attribute( - null, - IdentifierName("GeneratedCode"), - ArgumentList(SeparatedList(new[] - { - SimpleArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(nameof(Stunts)))), - SimpleArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(ThisAssembly.Metadata.PackageVersion))), - }))) - ); - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/Processors/VisualBasicFileHeader.cs b/src/Stunts/Stunts.Sdk/Processors/VisualBasicFileHeader.cs deleted file mode 100644 index 743bf098..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/VisualBasicFileHeader.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory; - -namespace Stunts.Processors -{ - /// - /// Adds the auto-generated file header that flags the - /// document as a generated one. - /// - public class VisualBasicFileHeader : IDocumentProcessor - { - const string header = @"'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -"; - - /// - /// Applies to only. - /// - public string[] Languages { get; } = new[] { LanguageNames.VisualBasic }; - - /// - /// Runs in the final phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Fixup; - - /// - /// Adds the auto-generated file header to the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var syntax = await document.GetSyntaxRootAsync(cancellationToken); - - return document.WithSyntaxRoot(syntax.WithLeadingTrivia(CommentTrivia(header))); - } - } -} diff --git a/src/Stunts/Stunts.Sdk/Processors/VisualBasicParameterFixup.cs b/src/Stunts/Stunts.Sdk/Processors/VisualBasicParameterFixup.cs deleted file mode 100644 index 65d9a419..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/VisualBasicParameterFixup.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.VisualBasic; -using Microsoft.CodeAnalysis.VisualBasic.Syntax; -using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory; - -namespace Stunts.Processors -{ - /// - /// Fixup for: - /// https://developercommunity.visualstudio.com/content/problem/40204/running-implement-interface-code-action-results-in.html - /// - public class VisualBasicParameterFixup : IDocumentProcessor - { - /// - /// Applies to . - /// - public string[] Languages { get; } = new[] { LanguageNames.VisualBasic }; - - /// - /// Runs in the final phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Fixup; - - /// - /// Applies the fixup for https://developercommunity.visualstudio.com/content/problem/40204/running-implement-interface-code-action-results-in.html - /// to the given document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var syntax = await document.GetSyntaxRootAsync(cancellationToken); - syntax = new VisualBasicParameterFixupVisitor(SyntaxGenerator.GetGenerator(document)).Visit(syntax); - - return document.WithSyntaxRoot(syntax); - } - - class VisualBasicParameterFixupVisitor : VisualBasicSyntaxRewriter - { - Dictionary renamedParameters = new Dictionary(); - SyntaxGenerator generator; - - public VisualBasicParameterFixupVisitor(SyntaxGenerator generator) => this.generator = generator; - - public override SyntaxNode VisitParameterList(ParameterListSyntax node) - { - renamedParameters = new Dictionary(); - return base.VisitParameterList(node); - } - - public override SyntaxNode VisitParameter(ParameterSyntax node) - { - var method = node.FirstAncestorOrSelf(); - var syntax = method?.BlockStatement as MethodStatementSyntax; - if (syntax?.Identifier.GetIdentifierText().Equals(node.Identifier.Identifier.GetIdentifierText(), StringComparison.OrdinalIgnoreCase) == true) - { - renamedParameters[node.Identifier.Identifier.Text] = "_" + node.Identifier.Identifier.Text; - node = node.WithIdentifier(node.Identifier.WithIdentifier(Identifier("_" + node.Identifier.Identifier.Text))); - } - - return base.VisitParameter(node); - } - - public override SyntaxNode VisitSimpleArgument(SimpleArgumentSyntax node) - { - var name = node.ToString(); - if (renamedParameters.ContainsKey(name)) - return base.VisitSimpleArgument(SimpleArgument(IdentifierName(renamedParameters[name]))); - - return base.VisitSimpleArgument(node); - } - } - } -} diff --git a/src/Stunts/Stunts.Sdk/Processors/VisualBasicRewrite.cs b/src/Stunts/Stunts.Sdk/Processors/VisualBasicRewrite.cs deleted file mode 100644 index b5eeacfc..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/VisualBasicRewrite.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.VisualBasic; -using Microsoft.CodeAnalysis.VisualBasic.Syntax; -using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory; - -namespace Stunts.Processors -{ - /// - /// Rewrites all members so they are implemented through - /// the field added to the - /// class by the . - /// - public class VisualBasicRewrite : IDocumentProcessor - { - /// - /// Applies to only. - /// - public string[] Languages { get; } = new[] { LanguageNames.VisualBasic }; - - /// - /// Runs in the third phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Rewrite; - - /// - /// Rewrites all members in the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var syntax = await document.GetSyntaxRootAsync(cancellationToken); - syntax = new VisualBasicRewriteVisitor(SyntaxGenerator.GetGenerator(document)).Visit(syntax); - - return document.WithSyntaxRoot(syntax); - } - - class VisualBasicRewriteVisitor : VisualBasicSyntaxRewriter - { - SyntaxGenerator generator; - - public VisualBasicRewriteVisitor(SyntaxGenerator generator) => this.generator = generator; - - // The namespace for the proxy should be global, just like C# - public override SyntaxNode VisitNamespaceStatement(NamespaceStatementSyntax node) - => node.Name.ToString().StartsWith("Global.", StringComparison.Ordinal) - ? base.VisitNamespaceStatement(node) - : base.VisitNamespaceStatement(node.WithName(ParseName("Global." + node.Name))) - .WithTrailingTrivia(CarriageReturnLineFeed); - - public override SyntaxNode VisitClassBlock(ClassBlockSyntax node) - { - // Turn event fields into event declarations. - var events = node.ChildNodes().OfType().ToArray(); - node = node.RemoveNodes(events, SyntaxRemoveOptions.KeepNoTrivia); - - foreach (var e in events) - { - var valueParam = ParameterList().AddParameters(Parameter(ModifiedIdentifier("value")).WithAsClause(e.AsClause)); - var statements = List(new[] - { - ExpressionStatement((ExpressionSyntax)generator.ExecutePipeline(null, valueParam.Parameters)) - }); - - node = node.AddMembers(new[] - { - EventBlock(e.WithCustomKeyword(Token(SyntaxKind.CustomKeyword)), List(new[] - { - AddHandlerAccessorBlock( - AccessorStatement(SyntaxKind.AddHandlerAccessorStatement, Token(SyntaxKind.AddHandlerKeyword)) - .WithParameterList(valueParam)) - .WithStatements(statements), - RemoveHandlerAccessorBlock( - AccessorStatement(SyntaxKind.RemoveHandlerAccessorStatement, Token(SyntaxKind.RemoveHandlerKeyword)) - .WithParameterList(valueParam)) - .WithStatements(statements), - RaiseEventAccessorBlock( - AccessorStatement(SyntaxKind.RaiseEventAccessorStatement, Token(SyntaxKind.RaiseEventKeyword)) - .WithParameterList(ParameterList().AddParameters( - Parameter(ModifiedIdentifier("sender")).WithAsClause(SimpleAsClause(PredefinedType(Token(SyntaxKind.ObjectKeyword)))), - Parameter(ModifiedIdentifier("args")).WithAsClause(SimpleAsClause(IdentifierName(nameof(EventArgs))))))) - })) - }); - } - - return base.VisitClassBlock(node); - } - - public override SyntaxNode VisitMethodBlock(MethodBlockSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitMethodBlock(node); - - var outParams = node.BlockStatement.ParameterList.Parameters.Where(x => x.Modifiers.Any(SyntaxKind.OutKeyword)).ToArray(); - var refParams = node.BlockStatement.ParameterList.Parameters.Where(x => x.Modifiers.Any(SyntaxKind.ByRefKeyword)).ToArray(); - - if (outParams.Length != 0 || refParams.Length != 0) - node = (MethodBlockSyntax)generator.ImplementMethod(node, generator.GetType(node), outParams, refParams); - else - node = (MethodBlockSyntax)generator.ImplementMethod(node, generator.GetType(node)); - - return base.VisitMethodBlock(node); - } - - public override SyntaxNode VisitPropertyBlock(PropertyBlockSyntax node) - { - if (generator.GetAttributes(node).Any(attr => generator.GetName(attr) == "CompilerGenerated")) - return base.VisitPropertyBlock(node); - - var implements = node.PropertyStatement?.ImplementsClause?.InterfaceMembers.FirstOrDefault(); - (var canRead, var canWrite) = generator.InspectProperty(node); - var type = (TypeSyntax)generator.GetType(node); - if (canRead) - { - node = (PropertyBlockSyntax)generator.WithGetAccessorStatements(node, new[] - { - generator.ReturnStatement(generator.ExecutePipeline(type, generator.GetParameters(node))) - }); - } - if (canWrite) - { - node = (PropertyBlockSyntax)generator.WithSetAccessorStatements(node, new[] - { - generator.ExecutePipeline(null, generator - .GetParameters(node) - .Concat(new [] { Parameter(ModifiedIdentifier("value")).WithAsClause(SimpleAsClause(type)) })) - }); - } - - return base.VisitPropertyBlock(node); - } - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/Processors/VisualBasicScaffold.cs b/src/Stunts/Stunts.Sdk/Processors/VisualBasicScaffold.cs deleted file mode 100644 index 225ca9f7..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/VisualBasicScaffold.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; - -namespace Stunts.Processors -{ - /// - /// Applies a set of code fixes that scaffold empty implementations - /// of all abstract class, interface and overridable members. - /// - public class VisualBasicScaffold : IDocumentProcessor - { - /// - /// Default code fixes when no specific fixes are provided. - /// - static readonly string[] DefaultCodeFixNames = - { - CodeFixNames.VisualBasic.ImplementAbstractClass, - CodeFixNames.VisualBasic.ImplementInterface, - "OverrideAllMembersCodeFix", - CodeFixNames.VisualBasic.AddOverloads, - }; - - readonly string[] codeFixNames; - - /// - /// Initializes the scaffold with the . - /// - public VisualBasicScaffold() : this(DefaultCodeFixNames) { } - - /// - /// Initializes the scaffold with a specific set of code fixes to apply. - /// - public VisualBasicScaffold(params string[] codeFixNames) => this.codeFixNames = codeFixNames; - - /// - /// Applies to only. - /// - public string[] Languages { get; } = new[] { LanguageNames.VisualBasic }; - - /// - /// Runs in the second phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Scaffold; - - /// - /// Applies all existing code fixes to the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - foreach (var codeFixName in codeFixNames) - { - document = await document.ApplyCodeFixAsync(codeFixName, cancellationToken: cancellationToken); - } - - return document; - } - } -} diff --git a/src/Stunts/Stunts.Sdk/Processors/VisualBasicStunt.cs b/src/Stunts/Stunts.Sdk/Processors/VisualBasicStunt.cs deleted file mode 100644 index b3485f7a..00000000 --- a/src/Stunts/Stunts.Sdk/Processors/VisualBasicStunt.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.VisualBasic; -using Microsoft.CodeAnalysis.VisualBasic.Syntax; -using static Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory; - -namespace Stunts.Processors -{ - /// - /// Adds the interface implementation. - /// - public class VisualBasicStunt : IDocumentProcessor - { - /// - /// Applies to only. - /// - public string[] Languages { get; } = new[] { LanguageNames.VisualBasic }; - - /// - /// Runs in the final phase of codegen, . - /// - public ProcessorPhase Phase => ProcessorPhase.Fixup; - - /// - /// Adds the interface implementation to the document. - /// - public async Task ProcessAsync(Document document, CancellationToken cancellationToken = default) - { - var syntax = await document.GetSyntaxRootAsync(cancellationToken); - - syntax = new VisualBasicStuntVisitor(SyntaxGenerator.GetGenerator(document)).Visit(syntax); - - return document.WithSyntaxRoot(syntax); - } - - class VisualBasicStuntVisitor : VisualBasicSyntaxRewriter - { - SyntaxGenerator generator; - - public VisualBasicStuntVisitor(SyntaxGenerator generator) => this.generator = generator; - - public override SyntaxNode VisitCompilationUnit(CompilationUnitSyntax node) - { - if (!node.Options.Any(opt => !opt.ChildTokens().Any(t => t.Kind() == SyntaxKind.StrictKeyword))) - node = node.AddOptions(OptionStatement(Token(SyntaxKind.StrictKeyword), Token(SyntaxKind.OnKeyword))); - - return base.VisitCompilationUnit(node); - } - - public override SyntaxNode VisitClassBlock(ClassBlockSyntax node) - { - var result = base.VisitClassBlock(node); - - if (!generator.GetBaseAndInterfaceTypes(result).Any(x => - x.ToString() == nameof(IStunt) || - x.ToString() == typeof(IStunt).FullName)) - { - // Only add the base type if it isn't already there - result = generator.AddInterfaceType( - result, - generator.IdentifierName(nameof(IStunt))); - } - - if (!generator.GetMembers(result).Any(x => generator.GetName(x) == nameof(IStunt.Behaviors))) - { - var property = (PropertyBlockSyntax)generator.PropertyDeclaration( - nameof(IStunt.Behaviors), - GenericName("ObservableCollection", TypeArgumentList(IdentifierName(nameof(IStuntBehavior)))), - modifiers: DeclarationModifiers.ReadOnly, - getAccessorStatements: new[] - { - generator.ReturnStatement( - generator.MemberAccessExpression( - IdentifierName("pipeline"), - nameof(BehaviorPipeline.Behaviors))) - }); - - property = property.WithPropertyStatement( - property.PropertyStatement.WithImplementsClause( - ImplementsClause(QualifiedName(IdentifierName(nameof(IStunt)), IdentifierName(nameof(IStunt.Behaviors)))))); - - result = generator.InsertMembers(result, 0, property); - } - - if (!generator.GetMembers(result).Any(x => generator.GetName(x) == "pipeline")) - { - var field = generator.FieldDeclaration( - "pipeline", - generator.IdentifierName(nameof(BehaviorPipeline)), - modifiers: DeclarationModifiers.ReadOnly, - initializer: generator.ObjectCreationExpression(generator.IdentifierName(nameof(BehaviorPipeline)))); - - result = generator.InsertMembers(result, 0, field); - } - - return result; - } - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/Properties/AssemblyInfo.cs b/src/Stunts/Stunts.Sdk/Properties/AssemblyInfo.cs deleted file mode 100644 index 73d59e6c..00000000 --- a/src/Stunts/Stunts.Sdk/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Stunts.Generator.Build")] -[assembly: InternalsVisibleTo("Stunts.Generator.Console")] -[assembly: InternalsVisibleTo("Stunts.AcceptanceTests")] -[assembly: InternalsVisibleTo("Stunts.Tests")] \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/Properties/Resources.Designer.cs b/src/Stunts/Stunts.Sdk/Properties/Resources.Designer.cs deleted file mode 100644 index b8110659..00000000 --- a/src/Stunts/Stunts.Sdk/Properties/Resources.Designer.cs +++ /dev/null @@ -1,81 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Stunts.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Stunts.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Only classes and interfaces can be used. Invalid set of symbols: {0}.. - /// - internal static string InvalidStuntTypes { - get { - return ResourceManager.GetString("InvalidStuntTypes", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Project '{0}' does not reference the required Stunts assembly.. - /// - internal static string StuntsRequired { - get { - return ResourceManager.GetString("StuntsRequired", resourceCulture); - } - } - } -} diff --git a/src/Stunts/Stunts.Sdk/Properties/Resources.resx b/src/Stunts/Stunts.Sdk/Properties/Resources.resx deleted file mode 100644 index f761ee1a..00000000 --- a/src/Stunts/Stunts.Sdk/Properties/Resources.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Only classes and interfaces can be used. Invalid set of symbols: {0}. - - - Project '{0}' does not reference the required Stunts assembly. - - \ No newline at end of file diff --git a/src/Stunts/Stunts.Sdk/RoslynInternals.cs b/src/Stunts/Stunts.Sdk/RoslynInternals.cs deleted file mode 100644 index 6e609b6e..00000000 --- a/src/Stunts/Stunts.Sdk/RoslynInternals.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editing; - -namespace Stunts -{ - internal static class RoslynInternals - { - internal static readonly MethodInfo getOverridableMembers = typeof(Workspace).Assembly - .GetType("Microsoft.CodeAnalysis.Shared.Extensions.INamedTypeSymbolExtensions", false) - ?.GetMethod("GetOverridableMembers", BindingFlags.Public | BindingFlags.Static); - - internal static readonly MethodInfo overrideAsync = - // 2.9+ - (typeof(Workspace).Assembly.GetType("Microsoft.CodeAnalysis.Shared.Extensions.ICodeDefinitionFactoryExtensions", false) ?? - // 2.11+ - typeof(Workspace).Assembly.GetType("Microsoft.CodeAnalysis.Shared.Extensions.SyntaxGeneratorExtensions", false)) - ?.GetMethod("OverrideAsync", BindingFlags.Public | BindingFlags.Static); - - internal static readonly MethodInfo addMemberDeclarationsAsync = typeof(Workspace).Assembly - .GetType("Microsoft.CodeAnalysis.CodeGeneration.CodeGenerator", false) - ?.GetMethod("AddMemberDeclarationsAsync", BindingFlags.Public | BindingFlags.Static); - - public static ImmutableArray GetOverridableMembers(INamedTypeSymbol containingType, CancellationToken cancellationToken) - => (ImmutableArray)getOverridableMembers.Invoke(null, new object[] { containingType, cancellationToken }); - - public static Task OverrideAsync(SyntaxGenerator generator, ISymbol symbol, INamedTypeSymbol containingType, Document document, DeclarationModifiers? modifiersOpt = null, CancellationToken cancellationToken = default) - => (Task)overrideAsync.Invoke(null, new object[] { generator, symbol, containingType, document, modifiersOpt, cancellationToken }); - - public static Task AddMemberDeclarationsAsync(Solution solution, INamedTypeSymbol destination, IEnumerable members, CancellationToken cancellationToken = default) - => (Task)addMemberDeclarationsAsync.Invoke(null, new object[] { solution, destination, members, null, cancellationToken }); - } -} diff --git a/src/Stunts/Stunts.Sdk/StructuralComparer.cs b/src/Stunts/Stunts.Sdk/StructuralComparer.cs deleted file mode 100644 index cb718fff..00000000 --- a/src/Stunts/Stunts.Sdk/StructuralComparer.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections; -using System.Collections.Generic; - -namespace Stunts -{ - /// - /// Implements for structural equality comparisons - /// using the . - /// - /// - public class StructuralComparer : IEqualityComparer - { - /// - /// Singleton instance of a comparer for . - /// - public static IEqualityComparer Default { get; } = new StructuralComparer(); - - /// - public bool Equals(T x, T y) => StructuralComparisons.StructuralEqualityComparer.Equals(x, y); - - /// - public int GetHashCode(T obj) => StructuralComparisons.StructuralEqualityComparer.GetHashCode(obj); - } -} diff --git a/src/Stunts/Stunts.Sdk/StuntGenerator.cs b/src/Stunts/Stunts.Sdk/StuntGenerator.cs deleted file mode 100644 index c693a16b..00000000 --- a/src/Stunts/Stunts.Sdk/StuntGenerator.cs +++ /dev/null @@ -1,274 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Dynamic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.Text; -using Microsoft.CodeAnalysis.VisualBasic.Syntax; -using Stunts.Processors; - -namespace Stunts -{ - /// - /// Main code generator. - /// - public class StuntGenerator - { - // The naming conventions to use for determining class and namespace names. - NamingConvention naming; - - // Configured processors, by language, then phase. - Dictionary> processors; - - /// - /// Instantiates the set of default for the generator, - /// used for example when using the default constructor . - /// - public static IDocumentProcessor[] GetDefaultProcessors() => new IDocumentProcessor[] - { - new DefaultImports(), - new CSharpFileHeader(), - new CSharpScaffold(), - new CSharpRewrite(), - new CSharpStunt(), - new CSharpCompilerGenerated(), - new VisualBasicScaffold(), - new VisualBasicRewrite(), - new VisualBasicStunt(), - new VisualBasicParameterFixup(), - new VisualBasicFileHeader(), - new VisualBasicCompilerGenerated(), - new FixupImports(), - }; - - /// - /// Initializes the generator with the default - /// and the default processors. - /// - public StuntGenerator() : this(new NamingConvention(), GetDefaultProcessors()) { } - - /// - /// Initializes the generator with a custom and - /// the default processors. - /// - public StuntGenerator(NamingConvention naming) : this(naming, GetDefaultProcessors()) { } - - /// - /// Initializes the generator with the default - /// and the given set of s. - /// - public StuntGenerator(params IDocumentProcessor[] processors) : this(new NamingConvention(), (IEnumerable)processors) { } - - /// - /// Initializes the generator with the default - /// and the given set of s. - /// - public StuntGenerator(IEnumerable processors) : this(new NamingConvention(), processors) { } - - /// - /// Initializes the generator with a custom and - /// the given set of s. - /// - public StuntGenerator(NamingConvention naming, IEnumerable processors) - { - this.naming = naming; - // Splits the processors by supported language and then by phase. - this.processors = processors - .SelectMany(processor => processor.Languages.Select(lang => new { Processor = processor, Language = lang })) - .GroupBy(proclang => proclang.Language) - .ToDictionary( - bylang => bylang.Key, - bylang => bylang - .GroupBy(proclang => proclang.Processor.Phase) - .ToDictionary( - byphase => byphase.Key, - byphase => byphase.Select(proclang => proclang.Processor).ToArray())); - } - - /// - /// Generates a stunt document that implements the given types. - /// - /// - /// This aggregating method basically invokes - /// followed by . - /// - public async Task GenerateDocumentAsync(Project project, ITypeSymbol[] types, CancellationToken cancellationToken = default) - { - cancellationToken.ThrowIfCancellationRequested(); - - var generator = SyntaxGenerator.GetGenerator(project); - var (name, syntax) = CreateStunt(types.OfType(), generator); - var code = syntax.NormalizeWhitespace().ToFullString(); - - var filePath = Path.GetTempFileName(); -#if DEBUG - // In debug builds, we persist the file so we can inspect the generated code - // for troubleshooting. - File.WriteAllText(filePath, code); - Debug.WriteLine(filePath); -#endif - - Document document; - - EnsureTargetDirectory(project); - - if (project.Solution.Workspace is AdhocWorkspace workspace) - { - document = workspace.AddDocument(DocumentInfo.Create( - DocumentId.CreateNewId(project.Id), - name, - folders: naming.Namespace.Split('.'), - filePath: filePath, - loader: TextLoader.From(TextAndVersion.Create(SourceText.From(code), VersionStamp.Create())))); - } - else - { - document = project.AddDocument( - name, - SourceText.From(code), - folders: naming.Namespace.Split('.'), - filePath: filePath); - } - - document = await ApplyProcessors(document, cancellationToken); - -#if DEBUG - // Update the persisted temp file in debug builds. - File.WriteAllText(filePath, code); - if (Debugger.IsAttached) - Process.Start(filePath); -#endif - - return document; - } - - /// - /// Generates the empty stunt code as a , also returning - /// the resulting class name. It contains just the main compilation unit, namespace - /// imports, namespace declaration and class declaration with the given base type and - /// interfaces, with no class members at all. - /// - public (string name, SyntaxNode syntax) CreateStunt(IEnumerable symbols, SyntaxGenerator generator) - { - var name = naming.GetName(symbols); - var imports = new HashSet(); - var (baseType, implementedInterfaces) = symbols.ValidateGeneratorTypes(); - - AddImports(imports, baseType); - foreach (var iface in implementedInterfaces) - { - AddImports(imports, iface); - } - - var syntax = generator.CompilationUnit(imports - .Select(generator.NamespaceImportDeclaration) - .Concat(new[] - { - generator.NamespaceDeclaration(naming.Namespace, - generator.AddAttributes( - generator.ClassDeclaration(name, - modifiers: DeclarationModifiers.Partial, - baseType: baseType == null ? null : AsSyntaxNode(generator, baseType), - interfaceTypes: implementedInterfaces - .Select(x => AsSyntaxNode(generator, x)) - ) - ) - ) - })); - - return (name, syntax); - } - - void AddImports(HashSet imports, ITypeSymbol symbol) - { - if (symbol != null && symbol.ContainingNamespace != null && symbol.ContainingNamespace.CanBeReferencedByName) - imports.Add(symbol.ContainingNamespace.ToDisplayString()); - - if (symbol is INamedTypeSymbol named && named.IsGenericType) - { - foreach (var typeArgument in named.TypeArguments) - { - AddImports(imports, typeArgument); - } - } - } - - SyntaxNode AsSyntaxNode(SyntaxGenerator generator, ITypeSymbol symbol) - { - var prefix = symbol.ContainingType == null ? "" : symbol.ContainingType.Name + "."; - if (symbol is INamedTypeSymbol named && named.IsGenericType) - return generator.GenericName(prefix + symbol.Name, named.TypeArguments.Select(arg => AsSyntaxNode(generator, arg))); - - return generator.IdentifierName(prefix = symbol.Name); - } - - /// - /// Applies all received s received in the generator constructor. - /// - public async Task ApplyProcessors(Document document, CancellationToken cancellationToken) - { -#if DEBUG - // While debugging the generation itself, don't let the cancellation timeouts - // from tests cause this to fail. - if (Debugger.IsAttached) - cancellationToken = CancellationToken.None; -#endif - - var language = document.Project.Language; - if (!processors.TryGetValue(language, out var supportedProcessors)) - return document; - - if (supportedProcessors.TryGetValue(ProcessorPhase.Prepare, out var prepares)) - { - foreach (var prepare in prepares) - { - document = await prepare.ProcessAsync(document, cancellationToken); - } - } - - if (supportedProcessors.TryGetValue(ProcessorPhase.Scaffold, out var scaffolds)) - { - foreach (var scaffold in scaffolds) - { - document = await scaffold.ProcessAsync(document, cancellationToken); - } - } - - if (supportedProcessors.TryGetValue(ProcessorPhase.Rewrite, out var rewriters)) - { - foreach (var rewriter in rewriters) - { - document = await rewriter.ProcessAsync(document, cancellationToken); - } - } - - if (supportedProcessors.TryGetValue(ProcessorPhase.Fixup, out var fixups)) - { - foreach (var fixup in fixups) - { - document = await fixup.ProcessAsync(document, cancellationToken); - } - } - - return document; - } - - void EnsureTargetDirectory(Project project) - { - var autoCodeFixEnabled = bool.TryParse(Environment.GetEnvironmentVariable("AutoCodeFix"), out var value) && value; - // When running the generator from design-time, ensure the folder exists. - if (!autoCodeFixEnabled) - { - // Ensure target directory exists since a linked file in teh same folder - // may already exist in the project and the file adding fails in that case. - var directory = Path.Combine(Path.GetDirectoryName(project.FilePath), Path.Combine(naming.Namespace.Split('.'))); - Directory.CreateDirectory(directory); - } - } - } -} diff --git a/src/Stunts/Stunts.Sdk/Stunts.Sdk.csproj b/src/Stunts/Stunts.Sdk/Stunts.Sdk.csproj deleted file mode 100644 index abcfd134..00000000 --- a/src/Stunts/Stunts.Sdk/Stunts.Sdk.csproj +++ /dev/null @@ -1,79 +0,0 @@ - - - - - netstandard2.0 - Stunts - true - Build - Lib - true - false - - - - Stunts.Sdk - 1.0.0 - Stunts.Sdk - Allows extending Stunts code analyzers and code fixes to generate custom "Dynamic proxies" that can run everywhere, including mobile! - $(Summary) - netstandard proxy runtime dynamic - - - - - - - - - - - - - - PrimaryOutputKind=$(PrimaryOutputKind) - - - - - - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - - - - - - - <_NonePackageFile Include="@(PackageFile)" Condition="'%(Kind)' == 'None' and '%(ReferenceSourceTarget)' == 'ProjectReference'" /> - - - - - - - - .NETStandard,Version=v1.3 - true - - - - - \ No newline at end of file diff --git a/src/Stunts/Stunts.Tests/ArgumentCollectionTests.cs b/src/Stunts/Stunts.Tests/ArgumentCollectionTests.cs deleted file mode 100644 index 6103b6de..00000000 --- a/src/Stunts/Stunts.Tests/ArgumentCollectionTests.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using Xunit; - -namespace Stunts.Tests -{ - public class ArgumentCollectionTests - { - static readonly MethodInfo testMethod = typeof(ArgumentCollectionTests).GetMethod(nameof(Do), BindingFlags.Static | BindingFlags.Public); - - [Fact] - public void ThrowsIfMismatchValuesLength() - => Assert.Throws(() => new ArgumentCollection(new object[] { 5, "Foo" }, testMethod.GetParameters())); - - [Fact] - public void ThrowsIfGetNameNotFound() - => Assert.Throws(() => new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters())["foo"]); - - [Fact] - public void ThrowsIfSetNameNotFound() - => Assert.Throws(() => new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters())["foo"] = 1); - - [Fact] - public void ThrowsIfGetInfoByNameNotFound() - => Assert.Throws(() => new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()).GetInfo("foo")); - - [Fact] - public void AccessValueByIndex() - { - var arguments = new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()); - - Assert.Equal(5, arguments[0]); - - arguments[0] = 10; - - Assert.Equal(10, arguments[0]); - } - - [Fact] - public void AccessValueByName() - { - var arguments = new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()); - - Assert.Equal(5, arguments["value"]); - - arguments["value"] = 10; - - Assert.Equal(10, arguments["value"]); - } - - [Fact] - public void ContainsByName() - => Assert.True(new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()).Contains("value")); - - [Fact] - public void GetNameFromIndex() - => Assert.Equal("value", new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()).NameOf(0)); - - [Fact] - public void GetIndexFromName() - => Assert.Equal(0, new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()).IndexOf("value")); - - - [Fact] - public void GetInfoFromIndex() - => Assert.NotNull(new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()).GetInfo(0)); - - [Fact] - public void GetInfoFromName() - => Assert.NotNull(new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()).GetInfo("value")); - - [Fact] - public void EnumerateGeneric() - => Assert.Collection(new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()), value => Assert.Equal(5, value)); - - [Fact] - public void Enumerate() - { - IEnumerable arguments = new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()); - foreach (var value in arguments) - { - Assert.Equal(5, value); - } - } - - [Fact] - public void Count() - => Assert.Equal(1, new ArgumentCollection(new object[] { 5 }, testMethod.GetParameters()).Count); - -#pragma warning disable xUnit1013 // Used solely to get test method name and signature - public static void Do(int value) { } - } -} diff --git a/src/Stunts/Stunts.Tests/BehaviorPipelineTests.cs b/src/Stunts/Stunts.Tests/BehaviorPipelineTests.cs deleted file mode 100644 index 839a86da..00000000 --- a/src/Stunts/Stunts.Tests/BehaviorPipelineTests.cs +++ /dev/null @@ -1,348 +0,0 @@ -using System; -using System.Reflection; -using Moq.Sdk; -using Xunit; - -namespace Stunts.Tests -{ - public class BehaviorPipelineTests - { - [Fact] - public void WhenInvokingPipelineWithNoBehaviors_ThenInvokesTarget() - { - var targetCalled = false; - - var pipeline = new BehaviorPipeline(); - - Action a = WhenInvokingPipelineWithNoBehaviors_ThenInvokesTarget; - - pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo()), - new ExecuteDelegate((m, n) => { targetCalled = true; return m.CreateValueReturn(null); })); - - Assert.True(targetCalled); - } - - [Fact] - public void WhenInvokingPipeline_ThenInvokesAllBehaviorsAndTarget() - { - var firstCalled = false; - var secondCalled = false; - var targetCalled = false; - - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => { firstCalled = true; return n().Invoke(m, n); }), - new ExecuteDelegate((m, n) => { secondCalled = true; return n().Invoke(m, n); })); - - Action a = WhenInvokingPipeline_ThenInvokesAllBehaviorsAndTarget; - - pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo()), - new ExecuteDelegate((m, n) => { targetCalled = true; return m.CreateValueReturn(null); })); - - Assert.True(firstCalled); - Assert.True(secondCalled); - Assert.True(targetCalled); - } - - [Fact] - public void WhenInvokingPipelineWithNoApplicableBehaviors_ThenInvokesTarget() - { - var firstCalled = false; - var secondCalled = false; - var targetCalled = false; - - var pipeline = new BehaviorPipeline( - new DelegateStuntBehavior((m, n) => { firstCalled = true; return n().Invoke(m, n); }, m => false), - new DelegateStuntBehavior((m, n) => { secondCalled = true; return n().Invoke(m, n); }, m => false)); - - Action a = WhenInvokingPipelineWithNoApplicableBehaviors_ThenInvokesTarget; - - pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo()), - new ExecuteDelegate((m, n) => { targetCalled = true; return m.CreateValueReturn(null); })); - - Assert.False(firstCalled); - Assert.False(secondCalled); - Assert.True(targetCalled); - } - - [Fact] - public void WhenInvokingPipeline_ThenSkipsNonApplicableBehaviors() - { - var firstCalled = false; - var secondCalled = false; - var targetCalled = false; - - var pipeline = new BehaviorPipeline( - new DelegateStuntBehavior((m, n) => { firstCalled = true; return n().Invoke(m, n); }), - new DelegateStuntBehavior((m, n) => { secondCalled = true; return n().Invoke(m, n); }, m => false)); - - Action a = WhenInvokingPipeline_ThenInvokesAllBehaviorsAndTarget; - - pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo()), - new ExecuteDelegate((m, n) => { targetCalled = true; return m.CreateValueReturn(null); })); - - Assert.True(firstCalled); - Assert.False(secondCalled); - Assert.True(targetCalled); - } - - [Fact] - public void WhenInvokingPipeline_ThenBehaviorCanShortcircuitInvocation() - { - var firstCalled = false; - var secondCalled = false; - var targetCalled = false; - - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => { firstCalled = true; return m.CreateValueReturn(null); }), - new ExecuteDelegate((m, n) => { secondCalled = true; return n().Invoke(m, n); })); - - Action a = WhenInvokingPipeline_ThenBehaviorCanShortcircuitInvocation; - - pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo()), - new ExecuteDelegate((m, n) => { targetCalled = true; return m.CreateValueReturn(null); })); - - Assert.True(firstCalled); - Assert.False(secondCalled); - Assert.False(targetCalled); - } - - [Fact] - public void WhenInvokingPipeline_ThenBehaviorsCanPassDataWithContext() - { - var expected = Guid.NewGuid(); - var actual = Guid.Empty; - - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => { m.Context["guid"] = expected; return n().Invoke(m, n); }), - new ExecuteDelegate((m, n) => { actual = (Guid)m.Context["guid"]; return n().Invoke(m, n); })); - - Action a = WhenInvokingPipeline_ThenBehaviorsCanPassDataWithContext; - - var result = pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo()), - new ExecuteDelegate((m, n) => m.CreateValueReturn(null))); - - Assert.Equal(expected, actual); - Assert.True(result.Context.ContainsKey("guid")); - Assert.Equal(expected, result.Context["guid"]); - } - - [Fact] - public void WhenInvokingPipeline_ThenBehaviorsCanReturnValue() - { - var expected = new object(); - - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => m.CreateValueReturn(expected))); - - Func a = NonVoidMethod; - - var result = pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo()), - new ExecuteDelegate((m, n) => throw new NotImplementedException())); - - Assert.Equal(expected, result.ReturnValue); - } - - [Fact] - public void WhenInvokingPipeline_ThenBehaviorsCanReturnValueWithArg() - { - var expected = new object(); - - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => m.CreateValueReturn(expected, new object()))); - - Func a = NonVoidMethodWithArg; - - var result = pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo(), expected), - new ExecuteDelegate((m, n) => throw new NotImplementedException())); - - Assert.Equal(expected, result.ReturnValue); - } - - [Fact] - public void WhenInvokingPipeline_ThenBehaviorsCanReturnValueWithRef() - { - var expected = new object(); - var output = new object(); - - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => m.CreateValueReturn(expected, new object(), output))); - - NonVoidMethodWithArgRefDelegate a = NonVoidMethodWithArgRef; - - var result = pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo(), expected, output), - new ExecuteDelegate((m, n) => throw new NotImplementedException())); - - Assert.Equal(expected, result.ReturnValue); - Assert.Equal(output, result.Outputs[0]); - } - - [Fact] - public void WhenInvokingPipeline_ThenBehaviorsCanReturnException() - { - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => m.CreateExceptionReturn(new ArgumentException()))); - - Action a = WhenInvokingPipeline_ThenBehaviorsCanReturnException; - - Assert.Throws(() - => pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo()), - new ExecuteDelegate((m, n) => throw new NotImplementedException()), true)); - } - - [Fact] - public void WhenInvokingPipeline_ThenBehaviorsCanReturnValueWithOut() - { - var expected = new object(); - var output = new object(); - - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => m.CreateValueReturn(expected, new object(), output))); - - NonVoidMethodWithArgOutDelegate a = NonVoidMethodWithArgOut; - - var result = pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo(), expected, output), - new ExecuteDelegate((m, n) => throw new NotImplementedException())); - - Assert.Equal(expected, result.ReturnValue); - Assert.Equal(output, result.Outputs[0]); - } - - [Fact] - public void WhenInvokingPipeline_ThenBehaviorsCanReturnValueWithRefOut() - { - var expected = new object(); - var output = new object(); - var byref = new object(); - - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => m.CreateValueReturn(expected, new object(), byref, output))); - - NonVoidMethodWithArgRefOutDelegate a = NonVoidMethodWithArgRefOut; - - var result = pipeline.Invoke(new MethodInvocation(this, a.GetMethodInfo(), expected, byref, output), - new ExecuteDelegate((m, n) => throw new NotImplementedException())); - - Assert.Equal(expected, result.ReturnValue); - Assert.Equal(byref, result.Outputs[0]); - Assert.Equal(output, result.Outputs[1]); - } - - [Fact] - public void CanExecutePipelineResultNoTarget() - { - var value = new object(); - - var pipeline = new BehaviorPipeline(new ExecuteDelegate((m, n) => m.CreateValueReturn(value))); - - Func f = NonVoidMethod; - - Assert.Same(value, pipeline.Execute(new MethodInvocation(this, f.GetMethodInfo()))); - } - - [Fact] - public void CanExecutePipelineResultWithTarget() - { - var value = new object(); - - var pipeline = new BehaviorPipeline(new ExecuteDelegate((m, n) => m.CreateValueReturn(value))); - - Func f = NonVoidMethod; - - Assert.Same(value, pipeline.Execute( - new MethodInvocation(this, f.GetMethodInfo()), - new ExecuteDelegate((m, n) => throw new NotImplementedException()))); - } - - [Fact] - public void CanExecutePipelineWithTarget() - { - var pipeline = new BehaviorPipeline(); - - Action a = CanExecutePipelineWithTarget; - - pipeline.Execute(new MethodInvocation(this, a.GetMethodInfo()), - new ExecuteDelegate((m, n) => m.CreateValueReturn(null))); - } - - [Fact] - public void CanExecutePipelineNoTarget() - { - var pipeline = new BehaviorPipeline(new ExecuteDelegate((m, n) => m.CreateValueReturn(null))); - - Action a = CanExecutePipelineNoTarget; - - pipeline.Execute(new MethodInvocation(this, a.GetMethodInfo())); - } - - [Fact] - public void WhenExecutingPipelineWithNoTarget_ThenThrowsIfNoBehaviorReturns() - { - var pipeline = new BehaviorPipeline(); - - Action a = CanExecutePipelineNoTarget; - - Assert.Throws(() => pipeline.Execute(new MethodInvocation(this, a.GetMethodInfo()))); - } - - [Fact] - public void WhenExecutingPipeline_ThenBehaviorCanThrow() - { - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => m.CreateExceptionReturn(new ArgumentException()))); - - Action a = WhenInvokingPipeline_ThenBehaviorsCanReturnException; - - Assert.Throws(() - => pipeline.Execute(new MethodInvocation(this, a.GetMethodInfo()), - new ExecuteDelegate((m, n) => throw new NotImplementedException()))); - } - - [Fact] - public void WhenExecutingPipelineResult_ThenBehaviorCanThrow() - { - var pipeline = new BehaviorPipeline( - new ExecuteDelegate((m, n) => m.CreateExceptionReturn(new ArgumentException()))); - - Func f = NonVoidMethod; - - Assert.Throws(() - => pipeline.Execute(new MethodInvocation(this, f.GetMethodInfo()), - new ExecuteDelegate((m, n) => throw new NotImplementedException()))); - } - - [Fact] - public void WhenExecutingPipelineResultWithNoTarget_ThenThrowsIfNoResult() - { - var pipeline = new BehaviorPipeline(); - - Func f = NonVoidMethod; - - Assert.Throws(() - => pipeline.Execute(new MethodInvocation(this, f.GetMethodInfo()))); - } - - [Fact] - public void WhenSkippingBehavior_ThenBehaviorIsNotExecuted() - { - var pipeline = new BehaviorPipeline(); - - pipeline.Behaviors.Add(new DefaultValueBehavior()); - - var invocation = new MethodInvocation(new object(), typeof(object).GetMethod("ToString")); - invocation.SkipBehaviors.Add(typeof(DefaultValueBehavior)); - - Assert.Throws(() - => pipeline.Execute(invocation)); - } - - delegate object NonVoidMethodWithArgRefDelegate(object arg1, ref object arg2); - delegate object NonVoidMethodWithArgOutDelegate(object arg1, out object arg2); - delegate object NonVoidMethodWithArgRefOutDelegate(object arg1, ref object arg2, out object arg3); - - object NonVoidMethod() => null; - object NonVoidMethodWithArg(object arg) => null; - object NonVoidMethodWithArgRef(object arg1, ref object arg2) => null; - object NonVoidMethodWithArgOut(object arg1, out object arg2) { arg2 = new object (); return null; } - object NonVoidMethodWithArgRefOut(object arg1, ref object arg2, out object arg3) { arg3 = new object(); return null; } - } -} diff --git a/src/Stunts/Stunts.Tests/DefaultEqualityBehaviorTests.cs b/src/Stunts/Stunts.Tests/DefaultEqualityBehaviorTests.cs deleted file mode 100644 index 100c4a19..00000000 --- a/src/Stunts/Stunts.Tests/DefaultEqualityBehaviorTests.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading.Tasks; -using Xunit; - -namespace Stunts.Tests -{ - public class DefaultEqualityBehaviorTests - { - [Fact] - public void AppliesToGetHashCode() - { - var method = typeof(Foo).GetMethod(nameof(object.GetHashCode)); - var behavior = new DefaultEqualityBehavior(); - - Assert.True(behavior.AppliesTo(new MethodInvocation(new Foo(), method, new object[0]))); - } - - [Fact] - public void AppliesToEquals() - { - var method = typeof(Foo).GetMethod(nameof(object.Equals)); - var behavior = new DefaultEqualityBehavior(); - - Assert.True(behavior.AppliesTo(new MethodInvocation(new Foo(), method, new object[] { new Foo() }))); - } - - [Fact] - public void GetsHashCode() - { - var method = typeof(Foo).GetMethod(nameof(object.GetHashCode)); - var behavior = new DefaultEqualityBehavior(); - var target = new Foo(); - - var expected = target.GetHashCode(); - var actual = (int)behavior.Execute(new MethodInvocation(target, method, new object[0]), () => null).ReturnValue; - - Assert.Equal(expected, actual); - } - - [Fact] - public void EqualsSameInstance() - { - var method = typeof(Foo).GetMethod(nameof(object.Equals)); - var behavior = new DefaultEqualityBehavior(); - var target = new Foo(); - - var actual = (bool)behavior.Execute(new MethodInvocation(target, method, new object[] { target }), () => null).ReturnValue; - - Assert.True(actual); - } - - [Fact] - public void NotEqualsDifferentInstance() - { - var method = typeof(Foo).GetMethod(nameof(object.Equals)); - var behavior = new DefaultEqualityBehavior(); - var target = new Foo(); - - var actual = (bool)behavior.Execute(new MethodInvocation(target, method, new object[] { new Foo() }), () => null).ReturnValue; - - Assert.False(actual); - } - - [Fact] - public void InvokeNextIfNotEqualsOrGetHashCode() - { - var method = typeof(Foo).GetMethod(nameof(Foo.ToString)); - var behavior = new DefaultEqualityBehavior(); - var target = new Foo(); - var nextCalled = false; - - behavior.Execute( - new MethodInvocation(target, method), - () => (m, n) => - { - nextCalled = true; - return m.CreateValueReturn(null); - }); - - Assert.True(nextCalled); - } - - public class Foo - { - public override string ToString() - { - return base.ToString(); - } - - public override int GetHashCode() - { - return base.GetHashCode(); - } - - public override bool Equals(object obj) - { - return base.Equals(obj); - } - } - } -} diff --git a/src/Stunts/Stunts.Tests/DelegateStuntTests.cs b/src/Stunts/Stunts.Tests/DelegateStuntTests.cs deleted file mode 100644 index 0e562f51..00000000 --- a/src/Stunts/Stunts.Tests/DelegateStuntTests.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.ComponentModel; -using Moq.Sdk; -using Xunit; - -namespace Stunts.Tests -{ - public class DelegateStuntTests - { - [Fact] - public void CanCreateDelegateStunt() => Stunt.Of(); - - [Fact] - public void CanVerifyLooseMockDelegateWithNoReturnValue() - { - var recorder = new RecordingBehavior(); - var stunt = Stunt.Of>(); - stunt.AddBehavior(recorder); - stunt.AddBehavior((invocation, next) => invocation.CreateValueReturn(null, invocation.Arguments)); - - stunt(3); - - Assert.Single(recorder.Invocations); - } - } -} diff --git a/src/Stunts/Stunts.Tests/GlobalSuppressions.cs b/src/Stunts/Stunts.Tests/GlobalSuppressions.cs deleted file mode 100644 index 9243c7e4..00000000 --- a/src/Stunts/Stunts.Tests/GlobalSuppressions.cs +++ /dev/null @@ -1,9 +0,0 @@ - -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "False positives")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Potential Code Quality Issues", "RECS0023:Event unsubscription via anonymous delegate is useless", Justification = "Useful for testing interception paths.")] - diff --git a/src/Stunts/Stunts.Tests/ManualStuntTest.cs b/src/Stunts/Stunts.Tests/ManualStuntTest.cs deleted file mode 100644 index 66295fc5..00000000 --- a/src/Stunts/Stunts.Tests/ManualStuntTest.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Sample; -using Xunit; -using Xunit.Abstractions; - -namespace Stunts.Tests -{ - public class ManualStuntTest - { - ITestOutputHelper output; - - public ManualStuntTest(ITestOutputHelper output) => this.output = output; - - [Fact(Skip = "Just an example of the capabilities of a manually coded stunt.")] - public void CanUseManualStunt() - { - var stunt = new CalculatorClassStunt(); - var recorder = new RecordingBehavior(); - stunt.AddBehavior(recorder); - - var isOn = false; - stunt.TurnedOn += (_, __) => isOn = true; - - stunt.TurnOn(); - - Assert.True(isOn); - Assert.Equal(3, stunt.Add(1, 2)); - Assert.Equal(default, stunt.Mode); - - stunt.Store("balance", 100); - Assert.Equal(100, stunt.Recall("balance")); - - stunt.Store(null, 0); - Assert.Equal(0, stunt.Recall(null)); - - var x = 1; - var y = 2; - var z = 0; - Assert.True(stunt.TryAdd(ref x, ref y, out z)); - Assert.Equal(3, z); - - output.WriteLine(recorder.ToString()); - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Tests/MethodInvocationTests.cs b/src/Stunts/Stunts.Tests/MethodInvocationTests.cs deleted file mode 100644 index 6a38d098..00000000 --- a/src/Stunts/Stunts.Tests/MethodInvocationTests.cs +++ /dev/null @@ -1,155 +0,0 @@ -using System; -using System.Reflection; -using Xunit; - -namespace Stunts.Tests -{ -#pragma warning disable xUnit1013 // Public method should be marked as test - public class MethodInvocationTests - { - public void Do() { } - - [Fact] - public void TestDo() - { - var invocation = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(Do))); - - var actual = invocation.ToString(); - - Assert.Equal("void Do()", actual); - } - - public void DoWithInt(int value) { } - - [Fact] - public void TestDoWithInt() - { - var invocation = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoWithInt)), 5); - - var actual = invocation.ToString(); - - Assert.Equal("void DoWithInt(int value = 5)", actual); - } - - [Fact] - public void EqualIfTargetMethodAndArgumentsMatch() - { - var doThis = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(Do))); - var doThiss = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(Do))); - - Assert.Equal((object)doThis, doThiss); - Assert.Equal(doThis, doThiss); - Assert.Equal(doThis.GetHashCode(), doThiss.GetHashCode()); - Assert.True(doThis.Equals(doThiss)); - Assert.True(doThis.Equals((object)doThiss)); - - var doOther = new MethodInvocation(new MethodInvocationTests(), typeof(MethodInvocationTests).GetMethod(nameof(Do))); - - Assert.NotEqual(doThis, doOther); - - var doInt5 = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoWithInt)), 5); - var doInt5s = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoWithInt)), 5); - - Assert.NotEqual(doThis, doInt5); - Assert.Equal(doInt5, doInt5s); - Assert.Equal(doInt5.GetHashCode(), doInt5s.GetHashCode()); - - var doInt6 = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoWithInt)), 6); - - Assert.NotEqual(doInt5, doInt6); - } - - public void DoWithNullableInt(int? value) { } - - [Fact] - public void TestDoWithNullableInt() - { - var invocation = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoWithNullableInt)), 5); - - var actual = invocation.ToString(); - - Assert.Equal("void DoWithNullableInt(int? value = 5)", actual); - } - - public void DoWithNullableIntNull(int? value) { } - - [Fact] - public void TestDoWithNullableIntNull() - { - var invocation = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoWithNullableIntNull)), default(int?)); - - var actual = invocation.ToString(); - - Assert.Equal("void DoWithNullableIntNull(int? value = null)", actual); - } - - public void DoWithString(string value) { } - - [Fact] - public void TestDoWithString() - { - var invocation = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoWithString)), "foo"); - - var actual = invocation.ToString(); - - Assert.Equal("void DoWithString(string value = \"foo\")", actual); - } - - public void DoWithNullString(string value) { } - - [Fact] - public void TestDoWithNullString() - { - var invocation = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoWithNullString)), default(string)); - - var actual = invocation.ToString(); - - Assert.Equal("void DoWithNullString(string value = null)", actual); - } - - public bool DoReturn() => true; - - [Fact] - public void TestDoReturn() - { - var invocation = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoReturn))); - - var actual = invocation.ToString(); - - Assert.Equal("bool DoReturn()", actual); - } - - public void DoRef(ref int i) { } - - [Fact] - public void TestDoRef() - { - var invocation = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoRef)), 5); - - var actual = invocation.ToString(); - - Assert.Equal("void DoRef(ref int i = 5)", actual); - } - - public void DoOut(out int value) { value = 5; } - - [Fact] - public void TestDoOut() - { - var invocation = new MethodInvocation(this, typeof(MethodInvocationTests).GetMethod(nameof(DoOut)), 5); - - var actual = invocation.ToString(); - - Assert.Equal("void DoOut(out int value)", actual); - } - - [Fact] - public void ThrowsIfNullTarget() - => Assert.Throws(() => new MethodInvocation(null, MethodBase.GetCurrentMethod())); - - [Fact] - public void ThrowsIfNullMethodBase() - => Assert.Throws(() => new MethodInvocation(this, null)); - } -#pragma warning restore xUnit1013 // Public method should be marked as test -} diff --git a/src/Stunts/Stunts.Tests/StuntDiscovererTests.Compile.cs b/src/Stunts/Stunts.Tests/StuntDiscovererTests.Compile.cs deleted file mode 100644 index 08da93ac..00000000 --- a/src/Stunts/Stunts.Tests/StuntDiscovererTests.Compile.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using Stunts; - -public class Tests -{ - public void WhenFakingFormatterThenCanInvokeIt() - { - var stunt1 = Stunt.Of(); - var stunt2 = Stunt.Of(); - - var result1 = stunt1.Format("Hello {0}", "World", null); - var result2 = stunt2.Format("Hello {0}", "World", null); - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts.Tests/StuntDiscovererTests.Compile.vb b/src/Stunts/Stunts.Tests/StuntDiscovererTests.Compile.vb deleted file mode 100644 index e25a4d03..00000000 --- a/src/Stunts/Stunts.Tests/StuntDiscovererTests.Compile.vb +++ /dev/null @@ -1,12 +0,0 @@ -Imports System -Imports Stunts - -Public Class Tests - Public Sub WhenFakingFormatterThenCanInvokeIt() - Dim stunt1 As ICustomFormatter = Stunt.Of(Of ICustomFormatter) - Dim stunt2 As ICustomFormatter = Stunt.Of(Of ICustomFormatter) - - Dim result1 As String = stunt1.Format("Hello {0}", "World", Nothing) - Dim result2 As String = stunt2.Format("Hello {0}", "World", Nothing) - End Sub -End Class diff --git a/src/Stunts/Stunts.Tests/StuntDiscovererTests.cs b/src/Stunts/Stunts.Tests/StuntDiscovererTests.cs deleted file mode 100644 index a932b717..00000000 --- a/src/Stunts/Stunts.Tests/StuntDiscovererTests.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.IO; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Xunit; -using Xunit.Abstractions; -using static TestHelpers; - -namespace Stunts.Tests -{ - public class StuntDiscovererTests - { - ITestOutputHelper output; - - public StuntDiscovererTests(ITestOutputHelper output) => this.output = output; - - [InlineData(LanguageNames.CSharp)] - [InlineData(LanguageNames.VisualBasic)] - [Theory] - public async Task CanDiscoverDocumentStunts(string languageName) - { - var (workspace, project) = CreateWorkspaceAndProject(languageName); - - var code = languageName == LanguageNames.CSharp ? - File.ReadAllText(@"StuntDiscovererTests.Compile.cs") : - File.ReadAllText(@"StuntDiscovererTests.Compile.vb"); - - var document = project.AddDocument("test", code); - await AssertCode.NoErrorsAsync(document); - - var stunts = await document.DiscoverStuntsAsync(); - - Assert.Single(stunts); - } - - [InlineData(LanguageNames.CSharp)] - [InlineData(LanguageNames.VisualBasic)] - [Theory] - public async Task CanDiscoverProjectStunts(string languageName) - { - var (workspace, project) = CreateWorkspaceAndProject(languageName); - - var code = languageName == LanguageNames.CSharp ? - File.ReadAllText(@"StuntDiscovererTests.Compile.cs") : - File.ReadAllText(@"StuntDiscovererTests.Compile.vb"); - - var document = project.AddDocument("test", code); - await AssertCode.NoErrorsAsync(document); - - var stunts = await document.Project.DiscoverStuntsAsync(); - - Assert.Single(stunts); - } - } -} diff --git a/src/Stunts/Stunts.Tests/StuntExtensionsTests.cs b/src/Stunts/Stunts.Tests/StuntExtensionsTests.cs deleted file mode 100644 index b1e50ec0..00000000 --- a/src/Stunts/Stunts.Tests/StuntExtensionsTests.cs +++ /dev/null @@ -1,251 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using Xunit; - -namespace Stunts.Tests -{ - public class StuntExtensionsTests - { - [Fact] - public void WhenAddingStuntBehavior_ThenCanAddLambda() - { - var stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null); - - Assert.Single(stunt.Behaviors); - } - - [Fact] - public void WhenAddingStuntBehavior_ThenCanCustom() - { - IStunt stunt = new TestStunt(); - - stunt.AddBehavior(new TestStuntBehavior()); - - Assert.Single(stunt.Behaviors); - } - - [Fact] - public void WhenAddingStuntBehavior_ThenCanAddLambdaWithAppliesTo() - { - var stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null, m => true); - - Assert.True(stunt.Behaviors[0].AppliesTo(null)); - } - - [Fact] - public void WhenAddingStuntBehavior_ThenCanAddLambdaWithAppliesToNamed() - { - var stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null, m => true, "true"); - ((IStunt)stunt).AddBehavior((m, n) => null, m => false, "false"); - - Assert.Contains("true", stunt.Behaviors[0].ToString()); - Assert.Contains("false", stunt.Behaviors[1].ToString()); - } - - [Fact] - public void WhenAddingStuntBehavior_ThenCanAddInterface() - { - var stunt = new TestStunt(); - - stunt.AddBehavior(new TestStuntBehavior()); - - Assert.Single(stunt.Behaviors); - } - - [Fact] - public void WhenAddingStuntBehaviorToObject_ThenCanAddLambda() - { - object stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null); - - Assert.Single(((IStunt)stunt).Behaviors); - } - - [Fact] - public void WhenAddingStuntBehaviorToObject_ThenCanAddLambdaWithAppliesTo() - { - object stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null, m => true); - - Assert.True(((IStunt)stunt).Behaviors[0].AppliesTo(null)); - } - - [Fact] - public void WhenAddingStuntBehaviorToObject_ThenCanAddLambdaWithAppliesToNamed() - { - object stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null, m => true, "true"); - ((IStunt)stunt).AddBehavior((m, n) => null, m => false, "false"); - - Assert.Contains("true", ((IStunt)stunt).Behaviors[0].ToString()); - Assert.Contains("false", ((IStunt)stunt).Behaviors[1].ToString()); - } - - [Fact] - public void WhenAddingStuntBehaviorToObject_ThenCanAddInterface() - { - object stunt = new TestStunt(); - - stunt.AddBehavior(new TestStuntBehavior()); - - Assert.Single(((IStunt)stunt).Behaviors); - } - - [Fact] - public void WhenInsertingStuntBehavior_ThenCanAddLambda() - { - var stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null); - stunt.InsertBehavior(0, (m, n) => throw new NotImplementedException()); - - Assert.Equal(2, stunt.Behaviors.Count); - Assert.Throws(() => stunt.Behaviors[0].Execute(null, null)); - } - - [Fact] - public void WhenInsertingStuntBehavior_ThenCanCustom() - { - IStunt stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null); - stunt.InsertBehavior(0, new TestStuntBehavior()); - - Assert.Equal(2, stunt.Behaviors.Count); - Assert.IsType(stunt.Behaviors[0]); - } - - [Fact] - public void WhenInsertingStuntBehavior_ThenCanAddLambdaWithAppliesTo() - { - var stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null); - stunt.InsertBehavior(0, (m, n) => throw new NotImplementedException(), m => true); - stunt.InsertBehavior(0, (m, n) => throw new ArgumentException(), m => false); - - Assert.Equal(3, stunt.Behaviors.Count); - Assert.False(stunt.Behaviors[0].AppliesTo(null)); - Assert.True(stunt.Behaviors[1].AppliesTo(null)); - Assert.Throws(() => stunt.Behaviors[1].Execute(null, null)); - } - - [Fact] - public void WhenInsertingStuntBehavior_ThenCanAddLambdaWithAppliesToNamed() - { - var stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null); - stunt.InsertBehavior(0, (m, n) => throw new NotImplementedException(), m => true, "true"); - ((IStunt)stunt).InsertBehavior(0, (m, n) => throw new ArgumentException(), m => false, "false"); - - Assert.Equal(3, stunt.Behaviors.Count); - Assert.Contains("false", stunt.Behaviors[0].ToString()); - Assert.Contains("true", stunt.Behaviors[1].ToString()); - } - - [Fact] - public void WhenInsertingStuntBehavior_ThenCanAddInterface() - { - var stunt = new TestStunt(); - var behavior = new TestStuntBehavior(); - - stunt.AddBehavior((m, n) => null); - stunt.InsertBehavior(0, behavior); - - Assert.Equal(2, stunt.Behaviors.Count); - Assert.Same(behavior, stunt.Behaviors[0]); - } - - [Fact] - public void WhenInsertingStuntBehaviorToObject_ThenCanAddLambda() - { - object stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null); - stunt.InsertBehavior(0, (m, n) => throw new NotImplementedException()); - - Assert.Equal(2, ((IStunt)stunt).Behaviors.Count); - Assert.Throws(() => ((IStunt)stunt).Behaviors[0].Execute(null, null)); - } - - [Fact] - public void WhenInsertingStuntBehaviorToObject_ThenCanAddLambdaWithAppliesTo() - { - object stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null); - stunt.InsertBehavior(0, (m, n) => throw new NotImplementedException(), m => true); - stunt.InsertBehavior(0, (m, n) => throw new ArgumentException(), m => false); - - Assert.Equal(3, ((IStunt)stunt).Behaviors.Count); - Assert.False(((IStunt)stunt).Behaviors[0].AppliesTo(null)); - Assert.True(((IStunt)stunt).Behaviors[1].AppliesTo(null)); - Assert.Throws(() => ((IStunt)stunt).Behaviors[1].Execute(null, null)); - } - - [Fact] - public void WhenInsertingStuntBehaviorToObject_ThenCanAddLambdaWithAppliesToNamed() - { - object stunt = new TestStunt(); - - stunt.AddBehavior((m, n) => null); - stunt.InsertBehavior(0, (m, n) => throw new NotImplementedException(), m => true, "true"); - ((IStunt)stunt).InsertBehavior(0, (m, n) => throw new ArgumentException(), m => false, "false"); - - Assert.Equal(3, ((IStunt)stunt).Behaviors.Count); - Assert.Contains("false", ((IStunt)stunt).Behaviors[0].ToString()); - Assert.Contains("true", ((IStunt)stunt).Behaviors[1].ToString()); - } - - [Fact] - public void WhenInsertingStuntBehaviorToObject_ThenCanAddInterface() - { - object stunt = new TestStunt(); - var behavior = new TestStuntBehavior(); - - stunt.AddBehavior((m, n) => null); - stunt.InsertBehavior(0, behavior); - - Assert.Equal(2, ((IStunt)stunt).Behaviors.Count); - Assert.Same(behavior, ((IStunt)stunt).Behaviors[0]); - } - - [Fact] - public void WhenAddingStuntBehaviorToObjectWithLambda_ThenThrowsIfNotStunt() => - Assert.Throws(() => new object().AddBehavior((m, n) => null)); - - [Fact] - public void WhenAddingStuntBehaviorToObjectWithInterface_ThenThrowsIfNotStunt() => - Assert.Throws(() => new object().AddBehavior(new TestStuntBehavior())); - - [Fact] - public void WhenInsertingStuntBehaviorToObjectWithLambda_ThenThrowsIfNotStunt() => - Assert.Throws(() => new object().InsertBehavior(0, (m, n) => null)); - - [Fact] - public void WhenInsertingStuntBehaviorToObjectWithInterface_ThenThrowsIfNotStunt() => - Assert.Throws(() => new object().InsertBehavior(0, new TestStuntBehavior())); - - class TestStuntBehavior : IStuntBehavior - { - public bool AppliesTo(IMethodInvocation invocation) => true; - - public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) => null; - } - - class TestStunt : IStunt - { - public ObservableCollection Behaviors { get; } = new ObservableCollection(); - } - } -} diff --git a/src/Stunts/Stunts.Tests/StuntFactoryTests.cs b/src/Stunts/Stunts.Tests/StuntFactoryTests.cs deleted file mode 100644 index 05a05a49..00000000 --- a/src/Stunts/Stunts.Tests/StuntFactoryTests.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Reflection; -using Stunts.Sdk; -using Xunit; - -namespace Stunts.Tests -{ - public class StuntFactoryTests - { - static StuntFactoryTests() - { - if (StuntFactory.Default == null) - StuntFactory.Default = new DynamicStuntFactory(); - } - - [Fact] - public void CanCreateStuntFromCallingAssemblyWithNamingConvention() - { - var stunt = StuntFactory.Default.CreateStunt( - Assembly.GetExecutingAssembly(), - typeof(IStuntFactory), - new[] { typeof(IDisposable) }, - Array.Empty()); - - Assert.IsType(stunt); - } - - [Fact] - public void CanReplaceDefaultFactory() - { - var existing = StuntFactory.Default; - var factory = new IDisposableIStuntFactoryStunt(); - StuntFactory.Default = factory; - - Assert.Same(factory, StuntFactory.Default); - - StuntFactory.Default = existing; - } - } -} - -namespace Stunts -{ - public class IDisposableIStuntFactoryStunt : IStuntFactory, IDisposable - { - public object CreateStunt(Assembly stuntsAssembly, Type baseType, Type[] implementedInterfaces, object[] constructorArguments) - => throw new NotImplementedException(); - - public void Dispose() => throw new NotImplementedException(); - } -} diff --git a/src/Stunts/Stunts.Tests/StuntNamingTests.cs b/src/Stunts/Stunts.Tests/StuntNamingTests.cs deleted file mode 100644 index 480b3499..00000000 --- a/src/Stunts/Stunts.Tests/StuntNamingTests.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using Xunit; - -namespace Stunts.Tests -{ - public class StuntNamingTests - { - [Theory] - [InlineData("StuntFactoryIDisposableIServiceProvider" + StuntNaming.DefaultSuffix, typeof(StuntFactory), typeof(IServiceProvider), typeof(IDisposable))] - [InlineData("IEnumerableOfIDisposableIServiceProvider" + StuntNaming.DefaultSuffix, typeof(IEnumerable), typeof(IServiceProvider))] - public void GetNameOrdersTypes(string expectedName, Type baseType, params Type[] implementedInterfaces) - => Assert.Equal(expectedName, StuntNaming.GetName(baseType, implementedInterfaces)); - - [Theory] - [InlineData(StuntNaming.DefaultNamespace + ".StuntFactoryIDisposableIServiceProvider" + StuntNaming.DefaultSuffix, typeof(StuntFactory), typeof(IServiceProvider), typeof(IDisposable))] - [InlineData(StuntNaming.DefaultNamespace + ".IEnumerableOfIDisposableIServiceProvider" + StuntNaming.DefaultSuffix, typeof(IEnumerable), typeof(IServiceProvider))] - public void GetFullNameOrdersTypes(string expectedName, Type baseType, params Type[] implementedInterfaces) - => Assert.Equal(expectedName, StuntNaming.GetFullName(baseType, implementedInterfaces)); - } -} diff --git a/src/Stunts/Stunts.Tests/Stunts.Tests.csproj b/src/Stunts/Stunts.Tests/Stunts.Tests.csproj deleted file mode 100644 index a8ec84be..00000000 --- a/src/Stunts/Stunts.Tests/Stunts.Tests.csproj +++ /dev/null @@ -1,74 +0,0 @@ - - - - - netcoreapp3.0 - net472 - Latest - true - - - - - - - - - - - - - - - - - - PreserveNewest - - - - PreserveNewest - - - - - - <_Parameter1>MSBuildBinPath - <_Parameter2>$(MSBuildBinPath) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Stunts/Stunts/ArgumentCollection.cs b/src/Stunts/Stunts/ArgumentCollection.cs deleted file mode 100644 index 85657e72..00000000 --- a/src/Stunts/Stunts/ArgumentCollection.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System.Linq; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System; -using System.Diagnostics; -using TypeNameFormatter; - -namespace Stunts -{ - [DebuggerTypeProxy(typeof(DebugView))] - [DebuggerDisplay("Count = {Count}")] - class ArgumentCollection : IArgumentCollection - { - List infos; - List values; - - public ArgumentCollection(object[] values, ParameterInfo[] infos) - : this((IEnumerable)values, (IEnumerable)infos) { } - - public ArgumentCollection(IEnumerable values, IEnumerable infos) - { - this.infos = infos.ToList(); - this.values = values.ToList(); - - if (this.infos.Count != this.values.Count) - throw new ArgumentException("Number of arguments must match number of parameters."); - } - - public object this[int index] - { - get => values[index]; - set => values[index] = value; - } - - public object this[string name] - { - get => values[ValidIndexOf(name)]; - set => values[ValidIndexOf(name)] = value; - } - - public int Count => infos.Count; - - public bool Contains(string name) => IndexOf(name) != -1; - - public IEnumerator GetEnumerator() => values.GetEnumerator(); - - public ParameterInfo GetInfo(string name) => infos[ValidIndexOf(name)]; - - public ParameterInfo GetInfo(int index) => infos[index]; - - public string NameOf(int index) => infos[index].Name; - - public int IndexOf(string name) - { - for (var i = 0; i < infos.Count; ++i) - { - if (infos[i].Name == name) - return i; - } - - return -1; - } - - public override string ToString() => string - .Join(", ", infos - .Select((p, i) => - (p.IsOut ? p.ParameterType.GetFormattedName().Replace("ref ", "out ") : p.ParameterType.GetFormattedName()) + - " " + p.Name + - (p.IsOut ? "" : - (" = " + - ((IsString(p.ParameterType) && values[i] != null) ? "\"" + values[i] + "\"" : - (values[i] ?? "null")) - ) - ) - ) - ); - - int ValidIndexOf(string name) - { - var index = IndexOf(name); - if (index == -1) - throw new KeyNotFoundException(name); - - return index; - } - - static bool IsString(Type type) => type == typeof(string) || - (type.IsByRef && type.HasElementType && type.GetElementType() == typeof(string)); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - [DebuggerNonUserCode] - class DebugView - { - ArgumentCollection arguments; - public DebugView(ArgumentCollection arguments) => this.arguments = arguments; - - [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] - public KeyValuePair[] Items => arguments.infos - .Select((info, index) => new KeyValuePair(info, arguments.values[index])) - .ToArray(); - } - } -} diff --git a/src/Stunts/Stunts/AssemblyInfo.cs b/src/Stunts/Stunts/AssemblyInfo.cs deleted file mode 100644 index fd6eca17..00000000 --- a/src/Stunts/Stunts/AssemblyInfo.cs +++ /dev/null @@ -1,5 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Stunts.Dynamic")] -[assembly: InternalsVisibleTo("Stunts.Tests")] -[assembly: InternalsVisibleTo("Stunts.Sdk.Tests")] \ No newline at end of file diff --git a/src/Stunts/Stunts/BehaviorPipeline.cs b/src/Stunts/Stunts/BehaviorPipeline.cs deleted file mode 100644 index 93abe223..00000000 --- a/src/Stunts/Stunts/BehaviorPipeline.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace Stunts -{ - /// - /// Encapsulates a list of s - /// and manages calling them in the proper order with the right inputs. - /// - public class BehaviorPipeline - { - /// - /// Creates a new with the given set of - /// delegates. - /// - /// Behaviors to add to the pipeline. - public BehaviorPipeline(params ExecuteDelegate[] behaviors) - : this((IEnumerable)behaviors) - { - } - - /// - /// Creates a new with the given set of - /// delegates. - /// - /// Behaviors to add to the pipeline. - public BehaviorPipeline(IEnumerable behaviors) - : this(behaviors.Select(behavior => new DelegateStuntBehavior(behavior))) - { - } - - /// - /// Creates a new with the given set of s. - /// - /// Behaviors to add to the pipeline. - public BehaviorPipeline(params IStuntBehavior[] behaviors) - : this((IEnumerable)behaviors) - { - } - - /// - /// Creates a new with the given set of s. - /// - /// Behaviors to add to the pipeline. - public BehaviorPipeline(IEnumerable behaviors) - { - Behaviors = new ObservableCollection(behaviors); - } - - /// - /// Creates a new . - /// - public BehaviorPipeline() - { - Behaviors = new ObservableCollection(); - } - - /// - /// Gets the collection of behaviors applied to this instance. - /// - public ObservableCollection Behaviors { get; } - - /// - /// Invoke the pipeline with the given input. - /// - /// Input to the method call. - /// The ultimate target of the call. - /// Whether to throw the if it has a value after running - /// the behaviors. - /// Return value from the pipeline. - public IMethodReturn Invoke(IMethodInvocation invocation, ExecuteDelegate target, bool throwOnException = false) - { - if (Behaviors.Count == 0) - return target(invocation, null); - - // We convert to array so that the collection of behaviors can potentially - // be modified by behaviors themselves for a subsequent pipeline execution. - // The current pipeline execution, once started, cannot be modified, though. - var behaviors = Behaviors.ToArray(); - - var index = -1; - for (var i = 0; i < behaviors.Length; i++) - { - if (!invocation.SkipBehaviors.Contains(behaviors[i].GetType()) && behaviors[i].AppliesTo(invocation)) - { - index = i; - break; - } - } - - if (index == -1) - return target(invocation, null); - - var result = behaviors[index].Execute(invocation, () => - { - for (index++; index < behaviors.Length; index++) - { - if (!invocation.SkipBehaviors.Contains(behaviors[index].GetType()) && behaviors[index].AppliesTo(invocation)) - break; - } - - return (index < behaviors.Length) ? - behaviors[index].Execute : - target; - }); - - if (throwOnException && result.Exception != null) - throw result.Exception; - - return result; - } - } -} diff --git a/src/Stunts/Stunts/BehaviorPipelineExtensions.cs b/src/Stunts/Stunts/BehaviorPipelineExtensions.cs deleted file mode 100644 index 3c6923a2..00000000 --- a/src/Stunts/Stunts/BehaviorPipelineExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.ComponentModel; - -namespace Stunts -{ - /// - /// Provides the Execute usability overloads. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class BehaviorPipelineExtensions - { - /// - /// Since no is provided as a target, this - /// defaults to throwing a if no - /// behavior returns before reaching the target. - /// - public static IMethodReturn Execute(this BehaviorPipeline pipeline, IMethodInvocation invocation) - => pipeline.Invoke(invocation, (input, next) => throw new NotImplementedException(), true); - - /// - /// Since no is provided as a target, and a value is required to - /// return, this defaults to throwing a if no - /// behavior returns before reaching the target. - /// - public static T Execute(this BehaviorPipeline pipeline, IMethodInvocation invocation) - => (T)pipeline.Invoke(invocation, (input, next) => throw new NotImplementedException(), true).ReturnValue; - - /// - /// Since a value is required to return, this executes the pipeline and requests to throw on - /// exceptions. - /// - public static T Execute(this BehaviorPipeline pipeline, IMethodInvocation invocation, ExecuteDelegate target) - => (T)pipeline.Invoke(invocation, target, true).ReturnValue; - - /// - /// Executes and forces an exception, for void methods. - /// - public static void Execute(this BehaviorPipeline pipeline, IMethodInvocation invocation, ExecuteDelegate target) - => pipeline.Invoke(invocation, target, true); - } -} diff --git a/src/Stunts/Stunts/DefaultEqualityBehavior.cs b/src/Stunts/Stunts/DefaultEqualityBehavior.cs deleted file mode 100644 index fe7428c2..00000000 --- a/src/Stunts/Stunts/DefaultEqualityBehavior.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace Stunts -{ - /// - /// A that implements a stunt's - /// GetHashCode and Equals using - /// and respectively. - /// - public class DefaultEqualityBehavior : IStuntBehavior - { - /// - /// Always returns - /// - public bool AppliesTo(IMethodInvocation invocation) - => invocation.MethodBase.Name == nameof(GetHashCode) || invocation.MethodBase.Name == nameof(Equals); - - /// - /// Implements the and - /// methods. - /// - public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) - { - if (invocation.MethodBase.Name == nameof(GetHashCode)) - return invocation.CreateValueReturn(RuntimeHelpers.GetHashCode(invocation.Target)); - if (invocation.MethodBase.Name == nameof(Equals)) - return invocation.CreateValueReturn(object.ReferenceEquals(invocation.Target, invocation.Arguments[0])); - - return next().Invoke(invocation, next); - } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts/DelegateStuntBehavior.cs b/src/Stunts/Stunts/DelegateStuntBehavior.cs deleted file mode 100644 index 2eaa0703..00000000 --- a/src/Stunts/Stunts/DelegateStuntBehavior.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Diagnostics; - -namespace Stunts -{ - /// - /// A general purpose that invokes the provided - /// delegates for the - /// (via a ) and - /// (via a ) - /// interface methods. - /// - public class DelegateStuntBehavior : IStuntBehavior - { - AppliesToDelegate appliesTo; - ExecuteDelegate behavior; - string name; - - /// - /// Creates the behavior from the given delegates. - /// - public DelegateStuntBehavior(ExecuteDelegate behavior, AppliesToDelegate appliesTo = null, string name = null) - { - this.behavior = behavior; - this.appliesTo = appliesTo ?? new AppliesToDelegate(invocation => true); - this.name = name; - } - - /// - /// Executes the provided provided in the constructor. - /// - public bool AppliesTo(IMethodInvocation invocation) => appliesTo(invocation); - - /// - /// Executes the provided provided in the constructor. - /// - public IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next) => - behavior(invocation, next); - - /// - /// Gets a friendly representation of the object. - /// - /// - /// We don't want to optimize code coverage for this since it's a debugger aid only. - /// Annotating this method with DebuggerNonUserCode achieves that. - /// No actual behavior depends on these strings. - /// - [DebuggerNonUserCode] - public override string ToString() => name ?? ""; - } -} diff --git a/src/Stunts/Stunts/GlobalSuppressions.cs b/src/Stunts/Stunts/GlobalSuppressions.cs deleted file mode 100644 index 754b9c28..00000000 --- a/src/Stunts/Stunts/GlobalSuppressions.cs +++ /dev/null @@ -1,8 +0,0 @@ - -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "False positives")] - diff --git a/src/Stunts/Stunts/HashCode.cs b/src/Stunts/Stunts/HashCode.cs deleted file mode 100644 index a6ddcdd2..00000000 --- a/src/Stunts/Stunts/HashCode.cs +++ /dev/null @@ -1,280 +0,0 @@ -// Adapted from https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/HashCode.cs - -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/* - -The xxHash32 implementation is based on the code published by Yann Collet: -https://raw.githubusercontent.com/Cyan4973/xxHash/5c174cfa4e45a42f94082dc0d4539b39696afea1/xxhash.c - - xxHash - Fast Hash algorithm - Copyright (C) 2012-2016, Yann Collet - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - xxHash homepage: http://www.xxhash.com - - xxHash source repository : https://github.com/Cyan4973/xxHash - -*/ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace Stunts -{ - // xxHash32 is used for the hash code. - // https://github.com/Cyan4973/xxHash - /// - /// Hashing helper class from corefx. - /// - public struct HashCode - { - private static readonly uint s_seed = (uint)new Random().Next(); - - private const uint Prime1 = 2654435761U; - private const uint Prime2 = 2246822519U; - private const uint Prime3 = 3266489917U; - private const uint Prime4 = 668265263U; - private const uint Prime5 = 374761393U; - - private uint _v1, _v2, _v3, _v4; - private uint _queue1, _queue2, _queue3; - private uint _length; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint Rol(uint value, int count) - => (value << count) | (value >> (32 - count)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4) - { - v1 = s_seed + Prime1 + Prime2; - v2 = s_seed + Prime2; - v3 = s_seed; - v4 = s_seed - Prime1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint Round(uint hash, uint input) - { - hash += input * Prime2; - hash = Rol(hash, 13); - hash *= Prime1; - return hash; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint QueueRound(uint hash, uint queuedValue) - { - hash += queuedValue * Prime3; - return Rol(hash, 17) * Prime4; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint MixState(uint v1, uint v2, uint v3, uint v4) - { - return Rol(v1, 1) + Rol(v2, 7) + Rol(v3, 12) + Rol(v4, 18); - } - - private static uint MixEmptyState() - { - return s_seed + Prime5; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint MixFinal(uint hash) - { - hash ^= hash >> 15; - hash *= Prime2; - hash ^= hash >> 13; - hash *= Prime3; - hash ^= hash >> 16; - return hash; - } - - /// - /// Adds the given values to the hash. - /// - public HashCode AddRange(IEnumerable values) - { - foreach (var value in values) - { - Add(value); - } - - return this; - } - - /// - /// Adds the given values to the hash. - /// - public HashCode AddRange(params object[] values) => AddRange((IEnumerable)values); - - /// - /// Adds the given value to the hash. - /// - public HashCode Add(T value) - { - Combine(value?.GetHashCode() ?? 0); - return this; - } - - /// - /// Combines the current hash with the given hash code. - /// - public HashCode Combine(int hashCode) - { - // The original xxHash works as follows: - // 0. Initialize immediately. We can't do this in a struct (no - // default ctor). - // 1. Accumulate blocks of length 16 (4 uints) into 4 accumulators. - // 2. Accumulate remaining blocks of length 4 (1 uint) into the - // hash. - // 3. Accumulate remaining blocks of length 1 into the hash. - - // There is no need for #3 as this type only accepts ints. _queue1, - // _queue2 and _queue3 are basically a buffer so that when - // ToHashCode is called we can execute #2 correctly. - - // We need to initialize the xxHash32 state (_v1 to _v4) lazily (see - // #0) nd the last place that can be done if you look at the - // original code is just before the first block of 16 bytes is mixed - // in. The xxHash32 state is never used for streams containing fewer - // than 16 bytes. - - // To see what's really going on here, have a look at the Combine - // methods. - - var val = (uint)hashCode; - - // Storing the value of _length locally shaves of quite a few bytes - // in the resulting machine code. - uint previousLength = _length++; - uint position = previousLength % 4; - - // Switch can't be inlined. - - if (position == 0) - _queue1 = val; - else if (position == 1) - _queue2 = val; - else if (position == 2) - _queue3 = val; - else // position == 3 - { - if (previousLength == 3) - Initialize(out _v1, out _v2, out _v3, out _v4); - - _v1 = Round(_v1, _queue1); - _v2 = Round(_v2, _queue2); - _v3 = Round(_v3, _queue3); - _v4 = Round(_v4, val); - } - - return this; - } - - /// - /// Converts the hash code to an . - /// - /// - public int ToHashCode() - { - // Storing the value of _length locally shaves of quite a few bytes - // in the resulting machine code. - uint length = _length; - - // position refers to the *next* queue position in this method, so - // position == 1 means that _queue1 is populated; _queue2 would have - // been populated on the next call to Add. - uint position = length % 4; - - // If the length is less than 4, _v1 to _v4 don't contain anything - // yet. xxHash32 treats this differently. - - uint hash = length < 4 ? MixEmptyState() : MixState(_v1, _v2, _v3, _v4); - - // _length is incremented once per Add(Int32) and is therefore 4 - // times too small (xxHash length is in bytes, not ints). - - hash += length * 4; - - // Mix what remains in the queue - - // Switch can't be inlined right now, so use as few branches as - // possible by manually excluding impossible scenarios (position > 1 - // is always false if position is not > 0). - if (position > 0) - { - hash = QueueRound(hash, _queue1); - if (position > 1) - { - hash = QueueRound(hash, _queue2); - if (position > 2) - hash = QueueRound(hash, _queue3); - } - } - - hash = MixFinal(hash); - return (int)hash; - } - -#pragma warning disable 0809 - // Obsolete member 'memberA' overrides non-obsolete member 'memberB'. - // Disallowing GetHashCode and Equals is by design - - // * We decided to not override GetHashCode() to produce the hash code - // as this would be weird, both naming-wise as well as from a - // behavioral standpoint (GetHashCode() should return the object's - // hash code, not the one being computed). - - // * Even though ToHashCode() can be called safely multiple times on - // this implementation, it is not part of the contract. If the - // implementation has to change in the future we don't want to worry - // about people who might have incorrectly used this type. - - /// - /// Obsolete member, replaced with . - /// - [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.", error: true)] - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => throw new NotSupportedException(); - - /// - /// Obsolete member, replaced with comparisons. - /// - [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", error: true)] - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => throw new NotSupportedException(); -#pragma warning restore 0809 - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts/IArgumentCollection.cs b/src/Stunts/Stunts/IArgumentCollection.cs deleted file mode 100644 index 617ee2f8..00000000 --- a/src/Stunts/Stunts/IArgumentCollection.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Collections.Generic; -using System.Reflection; - -namespace Stunts -{ - /// - /// Represents the arguments of a method invocation. - /// - public interface IArgumentCollection : IEnumerable, IFluentInterface - { - /// - /// Whether the collection contains a parameter with the - /// given name (based on the s - /// for the collection, rather than the actual values, since - /// they could be null/missing. - /// - /// - /// - bool Contains(string name); - - /// - /// Count s in the collection. - /// - int Count { get; } - - /// - /// Get the at the given index. - /// - ParameterInfo GetInfo(int index); - - /// - /// Gets the with the given name. - /// - ParameterInfo GetInfo(string name); - - /// - /// Gets the index of the parameter with the given name or -1 - /// if it's not found. - /// - int IndexOf(string name); - - /// - /// Gets the name of the parameter at the given index. - /// - string NameOf(int index); - - /// - /// Gets or sets the value of the argument with the given name. - /// - object this[string name] { get; set; } - - /// - /// Gets or sets the value of the argument at the given index. - /// - object this[int index] { get; set; } - } -} diff --git a/src/Stunts/Stunts/IMethodInvocation.cs b/src/Stunts/Stunts/IMethodInvocation.cs deleted file mode 100644 index 06065f88..00000000 --- a/src/Stunts/Stunts/IMethodInvocation.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace Stunts -{ - /// - /// Represents a method invocation. - /// - public interface IMethodInvocation : IEquatable, IFluentInterface - { - /// - /// The arguments of the method invocation. - /// - IArgumentCollection Arguments { get; } - - /// - /// An arbitrary property bag used during the invocation. - /// - IDictionary Context { get; } - - /// - /// The runtime method being invoked. - /// - MethodBase MethodBase { get; } - - /// - /// The ultimate target of the method invocation, typically - /// a stunt object. - /// - object Target { get; } - - /// - /// Behaviors in the pipeline that should be skipped during this invocation. - /// - HashSet SkipBehaviors { get; } - - /// - /// Creates the method invocation return that ends the - /// current invocation. - /// - /// Optional return value from the method invocation. for methods. - /// Ordered list of all arguments to the method invocation, including ref/out arguments. - /// The for the current invocation. - IMethodReturn CreateValueReturn(object returnValue, params object[] allArguments); - - /// - /// Creates a method invocation return that represents - /// a thrown exception. - /// - /// The exception to throw from the method invocation. - /// The for the current invocation. - IMethodReturn CreateExceptionReturn(Exception exception); - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts/IMethodReturn.cs b/src/Stunts/Stunts/IMethodReturn.cs deleted file mode 100644 index 435bc106..00000000 --- a/src/Stunts/Stunts/IMethodReturn.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Stunts -{ - /// - /// Represents the result of invoking a method. - /// - public interface IMethodReturn : IFluentInterface - { - /// - /// An arbitrary property bag used during the invocation. - /// - IDictionary Context { get; } - - /// - /// Optional exception if the method invocation results in - /// an exception being thrown. - /// - Exception Exception { get; } - - /// - /// Collection of out/ref arguments. - /// - IArgumentCollection Outputs { get; } - - /// - /// The value being returned for a non-void method if no exception - /// was thrown. - /// - object ReturnValue { get; } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts/IStunt.cs b/src/Stunts/Stunts/IStunt.cs deleted file mode 100644 index 10cb5fdd..00000000 --- a/src/Stunts/Stunts/IStunt.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.CodeDom.Compiler; -using System.Collections.ObjectModel; -using System.Runtime.CompilerServices; - -namespace Stunts -{ - /// - /// Interface implemented by all stunts. - /// - // These attributes prevent registering the "Implement through behavior pipeline" codefix. - // See CustomMockCodeFixProvider and its base class CustomStuntCodeFixProvider. - [GeneratedCode("Stunts", ThisAssembly.Metadata.Version)] - [CompilerGenerated] - public interface IStunt - { - /// - /// Behaviors configured for the stunt. - /// - ObservableCollection Behaviors { get; } - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts/IStuntBehavior.cs b/src/Stunts/Stunts/IStuntBehavior.cs deleted file mode 100644 index 2e4845c7..00000000 --- a/src/Stunts/Stunts/IStuntBehavior.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace Stunts -{ - /// - /// A configured behavior for an . - /// - public interface IStuntBehavior - { - /// - /// Determines whether the behavior applies to the given - /// . - /// - /// The invocation to evaluate the - /// behavior against. - bool AppliesTo(IMethodInvocation invocation); - - /// - /// Executes the behavior for the given method invocation. - /// - /// The current method invocation. - /// Delegate to invoke the next behavior in the pipeline. - /// The result of the method invocation. - IMethodReturn Execute(IMethodInvocation invocation, GetNextBehavior next); - } - - /// - /// Method signature for getting the next behavior in a pipeline. - /// - /// The delegate to invoke the next behavior in a pipeline. - public delegate ExecuteDelegate GetNextBehavior(); - - /// - /// Method signature for invoking the next behavior in a pipeline. - /// - /// The current method invocation. - /// Delegate to invoke the next behavior in the pipeline. - /// The result of the method invocation. - public delegate IMethodReturn ExecuteDelegate(IMethodInvocation invocation, GetNextBehavior next); - - /// - /// Method signature of for use in - /// for anonymous behaviors. - /// - public delegate bool AppliesToDelegate(IMethodInvocation invocation); -} \ No newline at end of file diff --git a/src/Stunts/Stunts/IStuntFactory.cs b/src/Stunts/Stunts/IStuntFactory.cs deleted file mode 100644 index d0c15e8c..00000000 --- a/src/Stunts/Stunts/IStuntFactory.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Reflection; - -namespace Stunts -{ - /// - /// Interface implemented by stunt factories. - /// - public interface IStuntFactory - { - /// - /// Creates a stunt with the given parameters. - /// - /// Assembly where compile-time generated stunts exist. - /// The base type (or main interface) of the stunt. - /// Additional interfaces implemented by the stunt, or an empty array. - /// - /// Constructor arguments if the is a class, rather than an interface, or an empty array. - /// - /// A stunt that implements in addition to the specified interfaces (if any). - object CreateStunt(Assembly stuntsAssembly, Type baseType, Type[] implementedInterfaces, object[] constructorArguments); - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts/MethodInvocation.cs b/src/Stunts/Stunts/MethodInvocation.cs deleted file mode 100644 index 422c75af..00000000 --- a/src/Stunts/Stunts/MethodInvocation.cs +++ /dev/null @@ -1,161 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using System.Linq; -using System.Runtime.CompilerServices; -using TypeNameFormatter; -using System.Diagnostics; - -namespace Stunts -{ - /// - /// Default implementation of . - /// - public class MethodInvocation : IEquatable, IMethodInvocation - { - /// - /// Initializes the with the given parameters. - /// - /// The target object where the invocation is being performed. - /// The method being invoked. - /// The optional arguments passed to the method invocation. - public MethodInvocation(object target, MethodBase method, params object[] arguments) - { - // TODO: validate that arguments length and type match the method info? - Target = target ?? throw new ArgumentNullException(nameof(target)); - MethodBase = method ?? throw new ArgumentNullException(nameof(method)); - Arguments = new ArgumentCollection(arguments, method.GetParameters()); - Context = new Dictionary(); - } - - /// - public IArgumentCollection Arguments { get; } - - /// - public IDictionary Context { get; } - - /// - public MethodBase MethodBase { get; } - - /// - public object Target { get; } - - /// - public HashSet SkipBehaviors { get; } = new HashSet(); - - /// - public IMethodReturn CreateExceptionReturn(Exception exception) - => new MethodReturn(this, exception); - - /// - public IMethodReturn CreateValueReturn(object returnValue, params object[] allArguments) - => new MethodReturn(this, returnValue, allArguments); - - /// - /// Gets a friendly representation of the invocation. - /// - /// - /// We don't want to optimize code coverage for this since it's a debugger aid only. - /// Annotating this method with DebuggerNonUserCode achieves that. - /// No actual behavior depends on these strings. - /// - [DebuggerNonUserCode] - public override string ToString() - { - var result = new StringBuilder(); - if (MethodBase is MethodInfo info) - { - if (info.ReturnType != typeof(void)) - result.AppendFormattedName(info.ReturnType).Append(" "); - else - result.Append("void "); - } - - if (MethodBase.IsSpecialName) - { - if (MethodBase.Name.StartsWith("get_", StringComparison.Ordinal)) - { - result.Append(MethodBase.Name.Substring(4)); - } - else if(MethodBase.Name.StartsWith("set_", StringComparison.Ordinal)) - { - result.Append(MethodBase.Name.Substring(4)); - result.Append(" = ").Append(Arguments[0]?.ToString() ?? "null"); - } - else if (MethodBase.Name.StartsWith("add_", StringComparison.Ordinal)) - { - result.Append(MethodBase.Name.Substring(4) + " += "); - } - else if (MethodBase.Name.StartsWith("remove_", StringComparison.Ordinal)) - { - result.Append(MethodBase.Name.Substring(7) + " -= "); - } - } - else - { - result.Append(MethodBase.Name); - } - - if (MethodBase.IsGenericMethod) - { - var generic = ((MethodInfo)MethodBase).GetGenericMethodDefinition(); - result - .Append("<") - .Append(string.Join(", ", generic.GetGenericArguments().Select(t => t.Name))) - .Append(">"); - } - - // TODO: render indexer arguments? - if (!MethodBase.IsSpecialName) - { - return result - .Append("(") - .Append(Arguments.ToString()) - .Append(")") - .ToString(); - } - - return result.ToString(); - } - - #region Equality - - /// - /// Tests the current invocation against another for equality, taking into account the target object - /// for reference equality, the object equality of both and the sequence and - /// equality for all . - /// - /// The invocation to compare against. - /// if the invocations are equal, otherwise. - public bool Equals(IMethodInvocation other) - => other != null && object.ReferenceEquals(Target, other.Target) && MethodBase.Equals(other.MethodBase) && Arguments.SequenceEqual(other.Arguments); - - /// - /// Tests the current invocation against another for equality, taking into account the target object - /// for reference equality, the object equality of both and the sequence and - /// equality for all . - /// - /// if the invocations are equal, otherwise. - public bool Equals(MethodInvocation other) - => Equals((IMethodInvocation)other); - - /// - /// Tests the current invocation against another for equality, taking into account the target object - /// for reference equality, the object equality of both and the sequence and - /// equality for all . - /// - /// if the invocations are equal, otherwise. - public override bool Equals(object obj) - => Equals(obj as IMethodInvocation); - - /// - /// Gets the hash code for the current invocation, including the , - /// and . - /// - public override int GetHashCode() - => new HashCode().Combine(RuntimeHelpers.GetHashCode(Target)).Add(MethodBase).AddRange(Arguments).ToHashCode(); - - #endregion - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts/MethodInvocationExtensions.cs b/src/Stunts/Stunts/MethodInvocationExtensions.cs deleted file mode 100644 index 9688af16..00000000 --- a/src/Stunts/Stunts/MethodInvocationExtensions.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.ComponentModel; - -namespace Stunts -{ - /// - /// Extension methods to detect various invocation patterns based on - /// the . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class MethodInvocationExtensions - { - /// - /// Gets whether the invocation represents a property getter access. - /// - public static bool IsGetAccessor(this IMethodInvocation invocation) - => invocation.MethodBase.IsSpecialName && invocation.MethodBase.Name.StartsWith("get_", StringComparison.Ordinal); - - /// - /// Gets whether the invocation represents a property setter access. - /// - public static bool IsSetAccessor(this IMethodInvocation invocation) - => invocation.MethodBase.IsSpecialName && invocation.MethodBase.Name.StartsWith("set_", StringComparison.Ordinal); - - /// - /// Gets whether the invocation represents an indexer access. - /// - public static bool IsIndexerAccessor(this IMethodInvocation invocation) - { - var parameterCount = invocation.MethodBase.GetParameters().Length; - return (invocation.IsGetAccessor() && parameterCount > 0) - || (invocation.IsSetAccessor() && parameterCount > 1); - } - - /// - /// Gets whether the invocation represents a property access, either get or set. - /// - public static bool IsPropertyAccessor(this IMethodInvocation invocation) - { - var parameterCount = invocation.MethodBase.GetParameters().Length; - return (invocation.IsGetAccessor() && parameterCount == 0) - || (invocation.IsSetAccessor() && parameterCount == 1); - } - - // NOTE: The following two methods used to first check whether `method.IsSpecialName` was set - // as a quick guard against non-event accessor methods. This was removed in commit 44070a90 - // to "increase compatibility with F# and COM". More specifically: - // - // 1. COM does not really have events. Some COM interop assemblies define events, but do not - // mark those with the IL `specialname` flag. See: - // - https://code.google.com/archive/p/moq/issues/226 - // - the `Microsoft.Office.Interop.Word.ApplicationEvents4_Event` interface in Office PIA - // - // 2. F# does not mark abstract events' accessors with the IL `specialname` flag. See: - // - https://github.com/Microsoft/visualfsharp/issues/5834 - // - https://code.google.com/archive/p/moq/issues/238 - // - the unit tests in `FSharpCompatibilityFixture` - - /// - /// Gets whether the invocation represents an event subscription (+=). - /// - public static bool IsEventAddAccessor(this IMethodInvocation invocation) - => invocation.MethodBase.Name.StartsWith("add_", StringComparison.Ordinal); - - /// - /// Gets whether the invocation represents an event unsubscription (-=). - /// - public static bool IsEventRemoveAccessor(this IMethodInvocation invocation) - => invocation.MethodBase.Name.StartsWith("remove_", StringComparison.Ordinal); - - /// - /// Gets whether the invocation represents an event unsubscription (-=). - /// - public static bool IsEventAccessor(this IMethodInvocation invocation) - => invocation.IsEventAddAccessor() || invocation.IsEventRemoveAccessor(); - } -} diff --git a/src/Stunts/Stunts/MethodReturn.cs b/src/Stunts/Stunts/MethodReturn.cs deleted file mode 100644 index afd1655b..00000000 --- a/src/Stunts/Stunts/MethodReturn.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Text; -using TypeNameFormatter; - -namespace Stunts -{ - /// - /// Default implementation of . - /// - class MethodReturn : IMethodReturn - { - IMethodInvocation invocation; - object[] allArguments; - - public MethodReturn(IMethodInvocation invocation, object returnValue, object[] allArguments) - { - this.invocation = invocation; - this.allArguments = allArguments; - - ReturnValue = returnValue; - - var outputArgs = new List(); - var outputInfos = new List(); - var allInfos = invocation.MethodBase.GetParameters(); - - for (var i = 0; i < allInfos.Length; i++) - { - var info = allInfos[i]; - if (info.ParameterType.IsByRef) - { - outputArgs.Add(allArguments[i]); - outputInfos.Add(info); - } - } - - Outputs = new ArgumentCollection(outputArgs, outputInfos); - } - - public MethodReturn(IMethodInvocation invocation, Exception exception) - { - Outputs = new ArgumentCollection(new object[0], new ParameterInfo[0]); - Exception = exception; - } - - /// - /// The collection of output parameters. If the method has no output - /// parameters, this is a zero-length list (never null). - /// - public IArgumentCollection Outputs { get; } - - public object ReturnValue { get; } - - public Exception Exception { get; } - - public IDictionary Context { get => invocation.Context; } - - /// - /// Gets a friendly representation of the object. - /// - /// - /// We don't want to optimize code coverage for this since it's a debugger aid only. - /// Annotating this method with DebuggerNonUserCode achieves that. - /// No actual behavior depends on these strings. - /// - [DebuggerNonUserCode] - public override string ToString() - { - var result = new StringBuilder(); - if (invocation.MethodBase is MethodInfo info) - { - if (info.ReturnType != typeof(void)) - result.AppendFormattedName(info.ReturnType).Append(" "); - else - result.Append("void "); - } - - result.Append(invocation.MethodBase.Name); - if (invocation.MethodBase.IsGenericMethod) - { - var generic = ((MethodInfo)invocation.MethodBase).GetGenericMethodDefinition(); - result - .Append("<") - .Append(string.Join(", ", generic.GetGenericArguments().Select(t => t.Name))) - .Append(">"); - } - - result - .Append("(") - .Append(new ArgumentCollection(allArguments, invocation.MethodBase.GetParameters()).ToString()) - .Append(")"); - - if (Exception != null) - result.Append($" => throw new {Exception.GetType().Name}(\"{Exception.Message}\")"); - else if (invocation.MethodBase is MethodInfo r && r.ReturnType != typeof(void)) - result.Append(" => ") - .Append(ReturnValue == null ? "null" : (r.ReturnType == typeof(string) ? $"\"{ReturnValue}\"" : ReturnValue)); - - return result.ToString(); - } - } -} diff --git a/src/Stunts/Stunts/StuntExtensions.cs b/src/Stunts/Stunts/StuntExtensions.cs deleted file mode 100644 index aeb8dd6a..00000000 --- a/src/Stunts/Stunts/StuntExtensions.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System; -using System.ComponentModel; - -namespace Stunts -{ - /// - /// Usability functions for working with stunts. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class StuntExtensions - { - /// - /// Gets the behavior configuration for the given instance. - /// - public static IStunt Stunt(T instance) where T : class - => (instance is MulticastDelegate @delegate ? - @delegate.Target as IStunt : - instance as IStunt) ?? throw new ArgumentException(nameof(instance)); - - /// - /// Adds a behavior to a stunt. - /// - /// The stunt to add the behavior to. - /// (invocation, next) => .... Implements a behavior based on the received invocation. - /// Optionally calls the next behavior with: next().Invoke(invocation, next). - /// - /// invocation => [bool]. Optionally applies a condition to the execution based on the received invocation. - /// Optionally names the behavior for easier troubleshooting when debugging. - public static IStunt AddBehavior(this IStunt stunt, ExecuteDelegate behavior, AppliesToDelegate appliesTo = null, string name = null) - { - stunt.Behaviors.Add(new DelegateStuntBehavior(behavior, appliesTo, name)); - return stunt; - } - - /// - /// Adds a behavior to a stunt. - /// - public static IStunt AddBehavior(this IStunt stunt, IStuntBehavior behavior) - { - stunt.Behaviors.Add(behavior); - return stunt; - } - - /// - /// Adds a behavior to a stunt. - /// - /// The stunt to add the behavior to. - /// (invocation, next) => .... Implements a behavior based on the received invocation. - /// Optionally calls the next behavior with: next().Invoke(invocation, next). - /// - /// invocation => [bool]. Optionally applies a condition to the execution based on the received invocation. - /// Optionally names the behavior for easier troubleshooting when debugging. - public static TStunt AddBehavior(this TStunt stunt, ExecuteDelegate behavior, AppliesToDelegate appliesTo = null, string name = null) where TStunt: class - { - Stunt(stunt).Behaviors.Add(new DelegateStuntBehavior(behavior, appliesTo, name)); - return stunt; - } - - /// - /// Adds a behavior to a stunt. - /// - public static TStunt AddBehavior(this TStunt stunt, IStuntBehavior behavior) where TStunt: class - { - Stunt(stunt).Behaviors.Add(behavior); - return stunt; - } - - /// - /// Inserts a behavior into the stunt behavior pipeline at the specified - /// index. - /// - /// The stunt to insert the behavior to. - /// The index to insert the behavior at. - /// (invocation, next) => .... Implements a behavior based on the received invocation. - /// Optionally calls the next behavior with: next().Invoke(invocation, next). - /// - /// invocation => [bool]. Optionally applies a condition to the execution based on the received invocation. - /// Optionally names the behavior for easier troubleshooting when debugging. - public static IStunt InsertBehavior(this IStunt stunt, int index, ExecuteDelegate behavior, AppliesToDelegate appliesTo = null, string name = null) - { - stunt.Behaviors.Insert(index, new DelegateStuntBehavior(behavior, appliesTo, name)); - return stunt; - } - - /// - /// Inserts a behavior into the stunt behavior pipeline at the specified - /// index. - /// - public static IStunt InsertBehavior(this IStunt stunt, int index, IStuntBehavior behavior) - { - stunt.Behaviors.Insert(index, behavior); - return stunt; - } - - /// - /// Inserts a behavior into the stunt behavior pipeline at the specified - /// index. - /// - /// The stunt to insert the behavior to. - /// The index to insert the behavior at. - /// (invocation, next) => .... Implements a behavior based on the received invocation. - /// Optionally calls the next behavior with: next().Invoke(invocation, next). - /// - /// invocation => [bool]. Optionally applies a condition to the execution based on the received invocation. - /// Optionally names the behavior for easier troubleshooting when debugging. - public static TStunt InsertBehavior(this TStunt stunt, int index, ExecuteDelegate behavior, AppliesToDelegate appliesTo = null, string name = null) where TStunt: class - { - Stunt(stunt).Behaviors.Insert(index, new DelegateStuntBehavior(behavior, appliesTo, name)); - return stunt; - } - - /// - /// Inserts a behavior into the stunt behavior pipeline at the specified - /// index. - /// - public static TStunt InsertBehavior(this TStunt stunt, int index, IStuntBehavior behavior) where TStunt: class - { - Stunt(stunt).Behaviors.Insert(index, behavior); - return stunt; - } - } -} diff --git a/src/Stunts/Stunts/StuntFactory.cs b/src/Stunts/Stunts/StuntFactory.cs deleted file mode 100644 index ff0bb229..00000000 --- a/src/Stunts/Stunts/StuntFactory.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Reflection; - -namespace Stunts -{ - /// - /// Allows accessing the default to use to - /// create stunts. - /// - public class StuntFactory : IStuntFactory - { - /// - /// Gets or sets the default to use - /// to create stunts. - /// - public static IStuntFactory Default { get; set; } = new StuntFactory(); - - private StuntFactory() { } - - /// - /// See - /// - public object CreateStunt(Assembly stuntsAssembly, Type baseType, Type[] implementedInterfaces, object[] constructorArguments) - { - var name = StuntNaming.GetFullName(baseType, implementedInterfaces); - var type = stuntsAssembly.GetType(name, true, false); - - return Activator.CreateInstance(type, constructorArguments); - } - } -} diff --git a/src/Stunts/Stunts/StuntGeneratorAttribute.cs b/src/Stunts/Stunts/StuntGeneratorAttribute.cs deleted file mode 100644 index 97e4b8e0..00000000 --- a/src/Stunts/Stunts/StuntGeneratorAttribute.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace Stunts -{ - /// - /// Annotates a method that is a factory for stunts, so that a - /// compile-time or design-time generator can generate them ahead of time. - /// - [AttributeUsage(AttributeTargets.Method)] - public class StuntGeneratorAttribute : Attribute - { - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts/StuntNaming.cs b/src/Stunts/Stunts/StuntNaming.cs deleted file mode 100644 index 3ef0b791..00000000 --- a/src/Stunts/Stunts/StuntNaming.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Stunts -{ - /// - /// Exposes the naming conventions for stunt generation and instantiation. - /// - public static class StuntNaming - { - /// - /// The default namespace where generated stunts are declared. - /// - public const string DefaultNamespace = "Stunts"; - - /// - /// The default suffix added to stunt type names. - /// - public const string DefaultSuffix = "Stunt"; - - /// - /// Gets the runtime stunt name from its base type and optional additional - /// interfaces, using the . - /// - public static string GetName(Type baseType, params Type[] additionalInterfaces) - => GetName(DefaultSuffix, baseType, additionalInterfaces); - - /// - /// Gets the runtime stunt name from its base type and optional additional interfaces - /// and the given appended to the type name. - /// - public static string GetName(string suffix, Type baseType, params Type[] additionalInterfaces) - { - if (baseType.IsClass) - { - return new StringBuilder() - .AddName(baseType) - .AddNames(additionalInterfaces.OrderBy(x => x.Name, StringComparer.Ordinal)) - .Append(suffix) - .ToString(); - } - else - { - return new StringBuilder() - .AddNames(new[] { baseType } - .Concat(additionalInterfaces) - .OrderBy(x => x.Name, StringComparer.Ordinal)) - .Append(suffix) - .ToString(); - } - } - - /// - /// Gets the runtime stunt full name from its base type and optional additional interfaces, - /// using the and . - /// - public static string GetFullName(Type baseType, params Type[] additionalInterfaces) - => GetFullName(DefaultNamespace, DefaultSuffix, baseType, additionalInterfaces); - - /// - /// Gets the runtime stunt full name from its base type and implemented interfaces. - /// - public static string GetFullName(string @namespace, Type baseType, params Type[] additionalInterfaces) - => GetFullName(@namespace, DefaultSuffix, baseType, additionalInterfaces); - - /// - /// Gets the runtime stunt full name from its base type and implemented interfaces. - /// - public static string GetFullName(string @namespace, string suffix, Type baseType, params Type[] additionalInterfaces) - => @namespace + "." + GetName(suffix, baseType, additionalInterfaces); - } - - internal static class StringBuilderExtensions - { - public static StringBuilder AddNames(this StringBuilder builder, IEnumerable types) - { - foreach (var type in types) - { - builder.AddName(type); - if (type.IsConstructedGenericType) - { - builder.Append("Of").AddNames(type.GenericTypeArguments); - } - } - return builder; - } - - public static StringBuilder AddName(this StringBuilder builder, Type type) - => type.IsGenericType ? builder.Append(type.Name.Substring(0, type.Name.IndexOf('`'))) : builder.Append(type.Name); - } -} diff --git a/src/Stunts/Stunts/Stunts.csproj b/src/Stunts/Stunts/Stunts.csproj deleted file mode 100644 index 651a16d5..00000000 --- a/src/Stunts/Stunts/Stunts.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - - netstandard2.0 - - - Stunts.Core - false - true - $(IncludeApi) - None - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Stunts/Stunts/build/Stunts.props b/src/Stunts/Stunts/build/Stunts.props deleted file mode 100644 index eb57d7d1..00000000 --- a/src/Stunts/Stunts/build/Stunts.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - true - - - - - - - false - - - - - \ No newline at end of file diff --git a/src/Stunts/Stunts/contentFiles/cs/netstandard1.3/Stunts/Stunt.cs b/src/Stunts/Stunts/contentFiles/cs/netstandard1.3/Stunts/Stunt.cs deleted file mode 100644 index 8e474dd8..00000000 --- a/src/Stunts/Stunts/contentFiles/cs/netstandard1.3/Stunts/Stunt.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace Stunts -{ - using System; - using System.CodeDom.Compiler; - using System.Reflection; - - /// - /// Instantiates stunts for the specified types. - /// - [GeneratedCode("Stunts", "5.0")] - internal partial class Stunt - { - static Stunt() => StuntFactory.Default = new Sdk.DynamicStuntFactory(); - - private static T Create(object[] constructorArgs, params Type[] interfaces) => - (T)StuntFactory.Default.CreateStunt(typeof(Stunt).GetTypeInfo().Assembly, typeof(T), interfaces, constructorArgs); - - /// - /// Gets the configuration and introspection for the given mocked instance. - /// - public static IStunt Get(T instance) where T : class => StuntExtensions.Stunt(instance); - - /// - /// Creates a stunt that inherits or implements the type . - /// - [StuntGenerator] - public static T Of(params object[] constructorArgs) => Create(constructorArgs); - - [StuntGenerator] - public static T Of(params object[] constructorArgs) => Create(constructorArgs, typeof(T1)); - - [StuntGenerator] - public static T Of(params object[] constructorArgs) => Create(constructorArgs, typeof(T1), typeof(T2)); - - [StuntGenerator] - public static T Of(params object[] constructorArgs) => Create(constructorArgs, typeof(T1), typeof(T2), typeof(T3)); - - [StuntGenerator] - public static T Of(params object[] constructorArgs) => Create(constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4)); - - [StuntGenerator] - public static T Of(params object[] constructorArgs) => Create(constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5)); - - [StuntGenerator] - public static T Of(params object[] constructorArgs) => Create(constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6)); - - [StuntGenerator] - public static T Of(params object[] constructorArgs) => Create(constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7)); - - [StuntGenerator] - public static T Of(params object[] constructorArgs) => Create(constructorArgs, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8)); - } -} \ No newline at end of file diff --git a/src/Stunts/Stunts/contentFiles/vb/netstandard1.3/Stunts/Stunt.vb b/src/Stunts/Stunts/contentFiles/vb/netstandard1.3/Stunts/Stunt.vb deleted file mode 100644 index ce1bf80c..00000000 --- a/src/Stunts/Stunts/contentFiles/vb/netstandard1.3/Stunts/Stunt.vb +++ /dev/null @@ -1,62 +0,0 @@ -Imports System -Imports System.CodeDom.Compiler -Imports System.Reflection - -Namespace Global.Stunts - - - Partial Friend Class Stunt - Private Shared Sub New() - StuntFactory.[Default] = New Sdk.DynamicStuntFactory() - End Sub - - Private Shared Function Create(Of T)(ByVal constructorArgs As Object(), ParamArray interfaces As Type()) As T - Return DirectCast(StuntFactory.[Default].CreateStunt(GetType(Stunt).GetTypeInfo().Assembly, GetType(T), interfaces, constructorArgs), T) - End Function - - - Public Shared Function [Of](Of T)(ParamArray constructorArgs As Object()) As T - Return Create(Of T)(constructorArgs) - End Function - - - Public Shared Function [Of](Of T, T1)(ParamArray constructorArgs As Object()) As T - Return Create(Of T)(constructorArgs, GetType(T1)) - End Function - - - Public Shared Function [Of](Of T, T1, T2)(ParamArray constructorArgs As Object()) As T - Return Create(Of T)(constructorArgs, GetType(T1), GetType(T2)) - End Function - - - Public Shared Function [Of](Of T, T1, T2, T3)(ParamArray constructorArgs As Object()) As T - Return Create(Of T)(constructorArgs, GetType(T1), GetType(T2), GetType(T3)) - End Function - - - Public Shared Function [Of](Of T, T1, T2, T3, T4)(ParamArray constructorArgs As Object()) As T - Return Create(Of T)(constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4)) - End Function - - - Public Shared Function [Of](Of T, T1, T2, T3, T4, T5)(ParamArray constructorArgs As Object()) As T - Return Create(Of T)(constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5)) - End Function - - - Public Shared Function [Of](Of T, T1, T2, T3, T4, T5, T6)(ParamArray constructorArgs As Object()) As T - Return Create(Of T)(constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5), GetType(T6)) - End Function - - - Public Shared Function [Of](Of T, T1, T2, T3, T4, T5, T6, T7)(ParamArray constructorArgs As Object()) As T - Return Create(Of T)(constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5), GetType(T6), GetType(T7)) - End Function - - - Public Shared Function [Of](Of T, T1, T2, T3, T4, T5, T6, T7, T8)(ParamArray constructorArgs As Object()) As T - Return Create(Of T)(constructorArgs, GetType(T1), GetType(T2), GetType(T3), GetType(T4), GetType(T5), GetType(T6), GetType(T7), GetType(T8)) - End Function - End Class -End Namespace \ No newline at end of file diff --git a/src/build/PackageReference.CopyLocal.targets b/src/build/PackageReference.CopyLocal.targets deleted file mode 100644 index 3fd29248..00000000 --- a/src/build/PackageReference.CopyLocal.targets +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - <_CopyLocalPackageId>@(CopyLocalPackageId) - - - - true - - - - - - - - - - - - - - - - - diff --git a/src/build/PackageReferences.targets b/src/build/PackageReferences.targets deleted file mode 100644 index 8d5ce213..00000000 --- a/src/build/PackageReferences.targets +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/build/Packaging.props b/src/build/Packaging.props deleted file mode 100644 index d86908d4..00000000 --- a/src/build/Packaging.props +++ /dev/null @@ -1,20 +0,0 @@ - - - - Debug - bin\$(Configuration)\ - false - false - - - - true - false - false - true - - - - - - \ No newline at end of file diff --git a/src/build/Packaging.targets b/src/build/Packaging.targets deleted file mode 100644 index 805c6897..00000000 --- a/src/build/Packaging.targets +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - <_PrimaryOutputRelatedFile Update="@(_PrimaryOutputRelatedFile)" - Condition=" - $([MSBuild]::ValueOrDefault('%(_PrimaryOutputRelatedFile.PackageName)', '').StartsWith('Microsoft.CodeAnalysis')) or - $([MSBuild]::ValueOrDefault('%(_PrimaryOutputRelatedFile.PackageName)', '').StartsWith('Microsoft.Build'))"> - all - - - - - \ No newline at end of file diff --git a/src/build/Settings.Tests.props b/src/build/Settings.Tests.props deleted file mode 100644 index c925bc84..00000000 --- a/src/build/Settings.Tests.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - 1701;1702;1705;0436 - - true - - true - true - true - - - true - - - \ No newline at end of file diff --git a/src/build/Settings.Tests.targets b/src/build/Settings.Tests.targets deleted file mode 100644 index 3f33424c..00000000 --- a/src/build/Settings.Tests.targets +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/build/Settings.props b/src/build/Settings.props deleted file mode 100644 index f7d12d2d..00000000 --- a/src/build/Settings.props +++ /dev/null @@ -1,74 +0,0 @@ - - - - false - true - - - - kzu - kzu - - - 42 - 42 - 42 - 0 - 42.42.42 - - https://github.com/moq/moq/ - https://github.com/moq/moq/blob/master/LICENSE - Copyright © 2017 Daniel Cazzulino and Contributors - - $(MSBuildThisFileDirectory)\..\..\out - - - - - - true - None - preview - - - false - - false - - $(AllowedReferenceRelatedFileExtensions);*.pdb;*.xml - false - - $(DefaultExcludeItems);*.binlog - true - - $([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)..\..')) - - - true - - - true - - - - - - - - - - true - - - - - - - - - - - - \ No newline at end of file diff --git a/src/build/Settings.targets b/src/build/Settings.targets deleted file mode 100644 index 5eaa3892..00000000 --- a/src/build/Settings.targets +++ /dev/null @@ -1,48 +0,0 @@ - - - - false - - $(OutputPath)$(AssemblyName).xml - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/build/Version.targets b/src/build/Version.targets deleted file mode 100644 index 5f574926..00000000 --- a/src/build/Version.targets +++ /dev/null @@ -1,93 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - true - true - - - - SetVersions;$(GenerateNuspecDependsOn) - SetVersions;$(GetPackageVersionDependsOn) - - - - $(SYSTEM_PULLREQUEST_TARGETBRANCH) - $(BUILD_SOURCEBRANCHNAME) - - - - - - - - - - - $(GitBranch.Replace('/', '_')) - - - - - - - - - - - - - - @(VersionMetadata -> '%(Identity)', '-') - +$(VersionMetadataLabel) - - @(LabelMetadata -> '%(Identity)', '-') - -$(LabelMetadata) - $(GitSemVerDashLabel).$(GitCommits) - - $(GitBaseVersionMajor).$(GitBaseVersionMinor).$(GitBaseVersionPatch)$(GitSemVerDashLabel)$(VersionMetadataPlusLabel) - - - $(GitBaseVersionMajor).$(GitBaseVersionMinor).$(GitBaseVersionPatch) - $(GitBaseVersionMajor).$(GitBaseVersionMinor).$(GitBaseVersionPatch)$(GitSemVerDashLabel)$(VersionMetadataPlusLabel) - $(BuildVersion) - - - - - <_Parameter1>Version - <_Parameter2>$(Version) - - - <_Parameter1>PackageVersion - <_Parameter2>$(PackageVersion) - - - - - - - - - <_Parameter1>AssemblyVersion - <_Parameter2>$(AssemblyVersion) - - - <_Parameter1>FileVersion - <_Parameter2>$(FileVersion) - - - <_Parameter1>InformationalVersion - <_Parameter2>$(InformationalVersion) - - - - - \ No newline at end of file