diff --git a/.nuget/NuGet.targets b/.nuget/NuGet.targets deleted file mode 100644 index f9438127..00000000 --- a/.nuget/NuGet.targets +++ /dev/null @@ -1,144 +0,0 @@ - - - - $(MSBuildProjectDirectory)\..\ - - - false - - - false - - - true - - - false - - - - - - - - - - - $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) - - - - - $(SolutionDir).nuget - - - - $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config - $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config - - - - $(MSBuildProjectDirectory)\packages.config - $(PackagesProjectConfig) - - - - - $(NuGetToolsPath)\NuGet.exe - @(PackageSource) - - "$(NuGetExePath)" - mono --runtime=v4.0.30319 $(NuGetExePath) - - $(TargetDir.Trim('\\')) - - -RequireConsent - -NonInteractive - - "$(SolutionDir) " - "$(SolutionDir)" - - - $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) - $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols - - - - RestorePackages; - $(BuildDependsOn); - - - - - $(BuildDependsOn); - BuildPackage; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CodeContracts.sln b/CodeContracts.sln index d0f4f7e5..d192902d 100644 --- a/CodeContracts.sln +++ b/CodeContracts.sln @@ -296,13 +296,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeContractsForRoslyn", "M EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CCDocGenAttributes", "microsoft.research\ManagedContract.Setup\CCDocGenAttributes\CCDocGenAttributes.csproj", "{449B96DF-2C90-4495-B081-D97D4F02620E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Adornments", "Microsoft.Research\VSAdornments\VS2010\Adornments.csproj", "{784AA6A9-013E-4D8E-82D6-934571CF1357}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Adornments", "Microsoft.Research\VSAdornments\Adornments.csproj", "{784AA6A9-013E-4D8E-82D6-934571CF1357}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Adornments11", "Microsoft.Research\VSAdornments\VS2012\Adornments11.csproj", "{235196BB-603A-470A-AF8E-EF6C8D01C4DC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContractAdornments", "Microsoft.Research\ContractAdornments\VS2010\ContractAdornments.csproj", "{D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContractAdornments11", "Microsoft.Research\ContractAdornments\VS2012\ContractAdornments11.csproj", "{5982130C-B0DD-4E10-82F7-A23F40A16315}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContractAdornments", "Microsoft.Research\ContractAdornments\Extension\ContractAdornments.csproj", "{D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BLResults", "Microsoft.Research\CCTools\BLResults\BLResults.csproj", "{6603246B-9D29-485C-BC38-E8E03F737BC4}" EndProject @@ -318,6 +314,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParseStats", "Microsoft.Res EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RevisedSimplexMethod", "Microsoft.Research\RevisedSimplexMethod\RevisedSimplexMethod\RevisedSimplexMethod.csproj", "{52B1843A-04C6-48A8-A8F7-C11392C44E7F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContractAdornments.CSharp.10", "Microsoft.Research\ContractAdornments\CSharp\ContractAdornments.CSharp.10.csproj", "{233B4116-291E-446E-9C44-04B7FBC514FF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContractAdornments.CSharp.11", "Microsoft.Research\ContractAdornments\CSharp\ContractAdornments.CSharp.11.csproj", "{A73F8AEB-7D31-4D67-9D94-853D1BB597A6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContractAdornments.CSharp.12", "Microsoft.Research\ContractAdornments\CSharp\ContractAdornments.CSharp.12.csproj", "{9C55B970-24B3-4623-9BA2-2D0F070E31A0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContractAdornments.CSharp.14", "Microsoft.Research\ContractAdornments\CSharp.Roslyn\ContractAdornments.CSharp.14.csproj", "{7FB60D9A-CF16-46C0-8154-696D85F8D451}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContractAdornments.Interfaces", "Microsoft.Research\ContractAdornments\Interfaces\ContractAdornments.Interfaces.csproj", "{B0C91C82-C1D8-4697-B07E-18E17D11EB41}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -2099,6 +2105,7 @@ Global {449B96DF-2C90-4495-B081-D97D4F02620E}.Release|Win32.ActiveCfg = Release|Any CPU {449B96DF-2C90-4495-B081-D97D4F02620E}.Release|x86.ActiveCfg = Release|Any CPU {784AA6A9-013E-4D8E-82D6-934571CF1357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {784AA6A9-013E-4D8E-82D6-934571CF1357}.Debug|Any CPU.Build.0 = Debug|Any CPU {784AA6A9-013E-4D8E-82D6-934571CF1357}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {784AA6A9-013E-4D8E-82D6-934571CF1357}.Debug|Win32.ActiveCfg = Debug|Any CPU {784AA6A9-013E-4D8E-82D6-934571CF1357}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -2118,28 +2125,8 @@ Global {784AA6A9-013E-4D8E-82D6-934571CF1357}.Release|Mixed Platforms.Build.0 = Release|Any CPU {784AA6A9-013E-4D8E-82D6-934571CF1357}.Release|Win32.ActiveCfg = Release|Any CPU {784AA6A9-013E-4D8E-82D6-934571CF1357}.Release|x86.ActiveCfg = Release|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Debug|Win32.ActiveCfg = Debug|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Debug|x86.ActiveCfg = Debug|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Devlab9|Any CPU.ActiveCfg = Devlab9|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Devlab9|Mixed Platforms.ActiveCfg = Devlab9|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Devlab9|Mixed Platforms.Build.0 = Devlab9|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Devlab9|Win32.ActiveCfg = Devlab9|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Devlab9|x86.ActiveCfg = Devlab9|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Internal9|Any CPU.ActiveCfg = Internal9|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Internal9|Mixed Platforms.ActiveCfg = Internal9|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Internal9|Mixed Platforms.Build.0 = Internal9|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Internal9|Win32.ActiveCfg = Internal9|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Internal9|x86.ActiveCfg = Internal9|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Release|Any CPU.Build.0 = Release|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Release|Win32.ActiveCfg = Release|Any CPU - {235196BB-603A-470A-AF8E-EF6C8D01C4DC}.Release|x86.ActiveCfg = Release|Any CPU {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C}.Debug|Win32.ActiveCfg = Debug|Any CPU {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -2158,26 +2145,6 @@ Global {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C}.Release|Mixed Platforms.Build.0 = Release|Any CPU {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C}.Release|Win32.ActiveCfg = Release|Any CPU {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C}.Release|x86.ActiveCfg = Release|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Debug|Win32.ActiveCfg = Debug|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Debug|x86.ActiveCfg = Debug|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Devlab9|Any CPU.ActiveCfg = Devlab9|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Devlab9|Mixed Platforms.ActiveCfg = Devlab9|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Devlab9|Mixed Platforms.Build.0 = Devlab9|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Devlab9|Win32.ActiveCfg = Devlab9|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Devlab9|x86.ActiveCfg = Devlab9|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Internal9|Any CPU.ActiveCfg = Internal9|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Internal9|Mixed Platforms.ActiveCfg = Internal9|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Internal9|Mixed Platforms.Build.0 = Internal9|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Internal9|Win32.ActiveCfg = Internal9|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Internal9|x86.ActiveCfg = Internal9|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Release|Win32.ActiveCfg = Release|Any CPU - {5982130C-B0DD-4E10-82F7-A23F40A16315}.Release|x86.ActiveCfg = Release|Any CPU {6603246B-9D29-485C-BC38-E8E03F737BC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6603246B-9D29-485C-BC38-E8E03F737BC4}.Debug|Any CPU.Build.0 = Debug|Any CPU {6603246B-9D29-485C-BC38-E8E03F737BC4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -2334,6 +2301,116 @@ Global {52B1843A-04C6-48A8-A8F7-C11392C44E7F}.Release|Mixed Platforms.Build.0 = Devlab64|Any CPU {52B1843A-04C6-48A8-A8F7-C11392C44E7F}.Release|Win32.ActiveCfg = Devlab64|Any CPU {52B1843A-04C6-48A8-A8F7-C11392C44E7F}.Release|x86.ActiveCfg = Devlab64|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Debug|Win32.ActiveCfg = Debug|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Debug|x86.ActiveCfg = Debug|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Devlab9|Any CPU.ActiveCfg = Devlab9|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Devlab9|Mixed Platforms.ActiveCfg = Devlab9|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Devlab9|Mixed Platforms.Build.0 = Devlab9|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Devlab9|Win32.ActiveCfg = Devlab9|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Devlab9|x86.ActiveCfg = Devlab9|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Internal9|Any CPU.ActiveCfg = Internal9|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Internal9|Mixed Platforms.ActiveCfg = Internal9|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Internal9|Mixed Platforms.Build.0 = Internal9|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Internal9|Win32.ActiveCfg = Internal9|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Internal9|x86.ActiveCfg = Internal9|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Release|Any CPU.Build.0 = Release|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Release|Win32.ActiveCfg = Release|Any CPU + {233B4116-291E-446E-9C44-04B7FBC514FF}.Release|x86.ActiveCfg = Release|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Debug|Win32.ActiveCfg = Debug|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Debug|x86.ActiveCfg = Debug|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Devlab9|Any CPU.ActiveCfg = Devlab9|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Devlab9|Mixed Platforms.ActiveCfg = Devlab9|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Devlab9|Mixed Platforms.Build.0 = Devlab9|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Devlab9|Win32.ActiveCfg = Devlab9|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Devlab9|x86.ActiveCfg = Devlab9|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Internal9|Any CPU.ActiveCfg = Internal9|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Internal9|Mixed Platforms.ActiveCfg = Internal9|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Internal9|Mixed Platforms.Build.0 = Internal9|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Internal9|Win32.ActiveCfg = Internal9|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Internal9|x86.ActiveCfg = Internal9|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Release|Any CPU.Build.0 = Release|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Release|Win32.ActiveCfg = Release|Any CPU + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6}.Release|x86.ActiveCfg = Release|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Debug|Win32.ActiveCfg = Debug|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Debug|x86.ActiveCfg = Debug|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Devlab9|Any CPU.ActiveCfg = Devlab9|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Devlab9|Mixed Platforms.ActiveCfg = Devlab9|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Devlab9|Mixed Platforms.Build.0 = Devlab9|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Devlab9|Win32.ActiveCfg = Devlab9|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Devlab9|x86.ActiveCfg = Devlab9|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Internal9|Any CPU.ActiveCfg = Internal9|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Internal9|Mixed Platforms.ActiveCfg = Internal9|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Internal9|Mixed Platforms.Build.0 = Internal9|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Internal9|Win32.ActiveCfg = Internal9|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Internal9|x86.ActiveCfg = Internal9|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Release|Any CPU.Build.0 = Release|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Release|Win32.ActiveCfg = Release|Any CPU + {9C55B970-24B3-4623-9BA2-2D0F070E31A0}.Release|x86.ActiveCfg = Release|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Debug|Win32.ActiveCfg = Debug|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Debug|x86.ActiveCfg = Debug|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Devlab9|Any CPU.ActiveCfg = Devlab9|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Devlab9|Mixed Platforms.ActiveCfg = Devlab9|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Devlab9|Mixed Platforms.Build.0 = Devlab9|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Devlab9|Win32.ActiveCfg = Devlab9|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Devlab9|x86.ActiveCfg = Devlab9|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Internal9|Any CPU.ActiveCfg = Internal9|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Internal9|Mixed Platforms.ActiveCfg = Internal9|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Internal9|Mixed Platforms.Build.0 = Internal9|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Internal9|Win32.ActiveCfg = Internal9|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Internal9|x86.ActiveCfg = Internal9|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Release|Any CPU.Build.0 = Release|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Release|Win32.ActiveCfg = Release|Any CPU + {7FB60D9A-CF16-46C0-8154-696D85F8D451}.Release|x86.ActiveCfg = Release|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Debug|Win32.ActiveCfg = Debug|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Debug|x86.ActiveCfg = Debug|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Devlab9|Any CPU.ActiveCfg = Devlab9|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Devlab9|Mixed Platforms.ActiveCfg = Devlab9|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Devlab9|Mixed Platforms.Build.0 = Devlab9|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Devlab9|Win32.ActiveCfg = Devlab9|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Devlab9|x86.ActiveCfg = Devlab9|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Internal9|Any CPU.ActiveCfg = Internal9|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Internal9|Mixed Platforms.ActiveCfg = Internal9|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Internal9|Mixed Platforms.Build.0 = Internal9|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Internal9|Win32.ActiveCfg = Internal9|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Internal9|x86.ActiveCfg = Internal9|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Release|Any CPU.Build.0 = Release|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Release|Win32.ActiveCfg = Release|Any CPU + {B0C91C82-C1D8-4697-B07E-18E17D11EB41}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2425,9 +2502,7 @@ Global {F9E1200C-C624-498A-BCB5-7E55CA1335F4} = {6468A140-0BAF-4813-A1EF-094DD7854C64} {449B96DF-2C90-4495-B081-D97D4F02620E} = {7CD8B829-346E-4FA0-ADDD-87152DDC5DDE} {784AA6A9-013E-4D8E-82D6-934571CF1357} = {7A308E8B-00AB-4ACF-8563-BF457A379EF1} - {235196BB-603A-470A-AF8E-EF6C8D01C4DC} = {7A308E8B-00AB-4ACF-8563-BF457A379EF1} {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C} = {7A308E8B-00AB-4ACF-8563-BF457A379EF1} - {5982130C-B0DD-4E10-82F7-A23F40A16315} = {7A308E8B-00AB-4ACF-8563-BF457A379EF1} {6603246B-9D29-485C-BC38-E8E03F737BC4} = {8C9BFE1D-90BD-4F88-B58E-89FF1DA325B8} {CC40F8DC-AA1F-4816-8E2D-18AC2B02E847} = {21B40F99-9AB5-4E2D-AA6E-B9687F5C865A} {407EF6D9-A736-4FEE-A522-789C64E74509} = {8C9BFE1D-90BD-4F88-B58E-89FF1DA325B8} @@ -2435,6 +2510,11 @@ Global {4CDCA734-7AA6-4283-B915-F9EB13A23D7F} = {8C9BFE1D-90BD-4F88-B58E-89FF1DA325B8} {9A6A7CB1-138C-4342-B630-93C04FF48317} = {8C9BFE1D-90BD-4F88-B58E-89FF1DA325B8} {52B1843A-04C6-48A8-A8F7-C11392C44E7F} = {C6F8F507-B843-4D08-8E4B-FF4AF23FC864} + {233B4116-291E-446E-9C44-04B7FBC514FF} = {7A308E8B-00AB-4ACF-8563-BF457A379EF1} + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6} = {7A308E8B-00AB-4ACF-8563-BF457A379EF1} + {9C55B970-24B3-4623-9BA2-2D0F070E31A0} = {7A308E8B-00AB-4ACF-8563-BF457A379EF1} + {7FB60D9A-CF16-46C0-8154-696D85F8D451} = {7A308E8B-00AB-4ACF-8563-BF457A379EF1} + {B0C91C82-C1D8-4697-B07E-18E17D11EB41} = {7A308E8B-00AB-4ACF-8563-BF457A379EF1} EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = CodeContracts10.vsmdi diff --git a/Microsoft.Research/Clousot.Cache/Clousot.Cache.csproj b/Microsoft.Research/Clousot.Cache/Clousot.Cache.csproj index 06ff85a4..6aba7359 100644 --- a/Microsoft.Research/Clousot.Cache/Clousot.Cache.csproj +++ b/Microsoft.Research/Clousot.Cache/Clousot.Cache.csproj @@ -17,7 +17,6 @@ v4.0 512 ..\..\ - true true @@ -181,13 +180,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Contracts/CSharpToCCIHelper.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Contracts/CSharpToCCIHelper.cs new file mode 100644 index 00000000..d3bb88e5 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Contracts/CSharpToCCIHelper.cs @@ -0,0 +1,402 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using Microsoft.Cci; +using Microsoft.CodeAnalysis; + +namespace ContractAdornments { + /// + /// A helper class for the Visual Studio semantic CSharp model. This helper is aware of cci. + /// + /// + /// All methods in this class are [Pure], meaning they are side-effect free. + /// + public static class CSharpToCCIHelper { + /// + /// Gets the CCI CallingConventions for a semantic member. The calling convention for a CSharp method is "Defualt" (always) and "Generic" (if it is generic) and/or "HasThis" (if it is non-static). + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static CallingConvention GetCallingConventionFor(ISymbol semanticMember) { + Contract.Requires(semanticMember != null); + + var callingConvention = CallingConvention.Default; + IMethodSymbol methodSymbol = semanticMember as IMethodSymbol; + if (methodSymbol != null && methodSymbol.IsGenericMethod) + callingConvention = callingConvention | CallingConvention.Generic; + if (!semanticMember.IsStatic) + callingConvention = callingConvention | CallingConvention.HasThis; + return callingConvention; + } + /// + /// Gets the CCI PrimitiveTypeCode for a semantic type. If the semantic type isn't a primitive type, the PrimitiveTypeCode "NotPrimitive" is used. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static PrimitiveTypeCode GetPrimitiveTypeCode(ITypeSymbol type) { + Contract.Requires(type != null); + Contract.Ensures(Contract.Result() != PrimitiveTypeCode.Pointer && + Contract.Result() != PrimitiveTypeCode.Reference && + Contract.Result() != PrimitiveTypeCode.Invalid, + "These types aren't checked for; all others are."); + if(type.Name == null || String.IsNullOrEmpty(type.Name)) throw new IllFormedSemanticModelException("A CSharpType was found with a null or empty 'Name' field.", type); + switch (type.Name) { + case "Boolean": return PrimitiveTypeCode.Boolean; + case "Char": return PrimitiveTypeCode.Char; + case "SByte": return PrimitiveTypeCode.Int8; + case "Single": return PrimitiveTypeCode.Float32; + case "Double": return PrimitiveTypeCode.Float64; + case "Int16": return PrimitiveTypeCode.Int16; + case "Int32": return PrimitiveTypeCode.Int32; + case "Int64": return PrimitiveTypeCode.Int64; + case "IntPtr": return PrimitiveTypeCode.IntPtr; + case "String": return PrimitiveTypeCode.String; + case "Byte": return PrimitiveTypeCode.UInt8; + case "UInt16": return PrimitiveTypeCode.UInt32; + case "UInt32": return PrimitiveTypeCode.UInt64; + case "UIntPtr": return PrimitiveTypeCode.UIntPtr; + case "Void": return PrimitiveTypeCode.Void; + default: return PrimitiveTypeCode.NotPrimitive; + } + } + /// + /// Checks if two enumerables are equivalent. + /// + [Pure] + public static bool EnumerablesAreEquivalent(IEnumerable list1, IEnumerable list2, Func comparison) { + Contract.Requires(list1 != null); + Contract.Requires(list2 != null); + Contract.Requires(comparison != null); + + var list1Enum = list1.GetEnumerator(); + var list2Enum = list2.GetEnumerator(); + bool list1Moved = list1Enum.MoveNext(); + bool list2Moved = list2Enum.MoveNext(); + if (list1Moved ^ list2Moved) + return false; + while (list1Moved && list2Moved) { + var item1 = list1Enum.Current; + var item2 = list2Enum.Current; + if (!comparison(item1, item2)) + return false; + list1Moved = list1Enum.MoveNext(); + list2Moved = list2Enum.MoveNext(); + if (list1Moved ^ list2Moved) + return false; + } + return true; + } + /// + /// Checks if two semantic methods are equivalent. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool MembersAreEquivalent(ISymbol member1, ISymbol member2) { + Contract.Requires(member1 != null); + Contract.Requires(member2 != null); + #region Check kind + if (member1.Kind != member2.Kind) return false; + if (member1.MethodKind() != member2.MethodKind()) return false; + if (member1.IsIndexer() ^ member2.IsIndexer()) return false; + #endregion + #region Check name + if (member1.Name == null ^ member2.Name == null) return false; + if (member1.Name!= null && member2.Name != null + && !member1.Name.Equals(member2.Name)) return false; + #endregion + #region Check explicit interface implementation + if (member1.ExplicitInterfaceImplementation() != null ^ member2.ExplicitInterfaceImplementation() != null) return false; + if (member1.ExplicitInterfaceImplementation() != null && member2.ExplicitInterfaceImplementation() != null + && !TypesAreEquivalent(member1.ExplicitInterfaceImplementation(), member2.ExplicitInterfaceImplementation())) return false; + #endregion + #region Check parameters + if (member1.Parameters().IsDefault ^ member2.Parameters().IsDefault) return false; + if (!member1.Parameters().IsDefault && !member2.Parameters().IsDefault + && !ParameterListsAreEquivalent(member1.Parameters(), member2.Parameters())) return false; + #endregion + #region Check return type + if (member1.ReturnType() == null) throw new IllFormedSemanticModelException("A CSharpMember (member) was found with a null 'ReturnType' field.", member1); + if (member2.ReturnType() == null) throw new IllFormedSemanticModelException("A CSharpMember (member) was found with a null 'ReturnType' field.", member2); + if (!TypesAreEquivalent(member1.ReturnType(), member2.ReturnType())) return false; + #endregion + return true; + } + /// + /// Checks if two parameters are equivalent. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool ParametersAreEquivalent(IParameterSymbol param1, IParameterSymbol param2) { + Contract.Requires(param1 != null); + Contract.Requires(param2 != null); + //return param1.Equals(param2); //Doesn't work for our purposes. + if (param1.Type == null) throw new IllFormedSemanticModelException("A CSharpParameter was found with a null 'Type' field.", param1); + if (param2.Type == null) throw new IllFormedSemanticModelException("A CSharpParameter was found with a null 'Type' field.", param2); + if (!TypesAreEquivalent(param1.Type, param2.Type)) return false; + if ((param1.RefKind == RefKind.Out) ^ (param2.RefKind == RefKind.Out)) return false; + if (param1.IsParams ^ param2.IsParams) return false; + if ((param1.RefKind == RefKind.Ref) ^ (param2.RefKind == RefKind.Ref)) return false; + if (param1.IsThis ^ param2.IsThis) return false; + return true; + } + /// + /// Checks if two parameter lists are equivalent. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool ParameterListsAreEquivalent(IEnumerable paramList1, IEnumerable paramList2) { + Contract.Requires(paramList1 != null); + Contract.Requires(paramList2 != null); + return EnumerablesAreEquivalent(paramList1, paramList2, (p1, p2) => ParametersAreEquivalent(p1, p2)); + } + /// + /// Crawls upward in the semantic tree looking for the first base method this method inherits from. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool TryGetBaseMember(ISymbol member, out ISymbol baseMember) { + Contract.Requires(member != null); + Contract.Ensures(!Contract.Result() || + member.Kind == Contract.ValueAtReturn(out baseMember).Kind); + + baseMember = null; + + if (member.ContainingType == null) throw new IllFormedSemanticModelException("A CSharpMember (method) was found with a null 'ContainingType' field.", member); + if (member.ContainingType.TypeKind != TypeKind.Class) return false; + var containingType = member.ContainingType; + var baseClass = containingType.BaseType; + while (baseClass != null) { + if (TryGetMemberWithSameSignatureFromType(baseClass, member, out baseMember)) + { + Contract.Assume(member.Kind == baseMember.Kind); + return true; + } + baseClass = baseClass.BaseType; + } + return false; + } + /// + /// + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool TryGetMemberWithSameSignatureFromType(ITypeSymbol type, ISymbol memberToMatch, out ISymbol member) { + Contract.Requires(type != null); + Contract.Requires(memberToMatch != null); + Contract.Ensures(!Contract.Result() || Contract.ValueAtReturn(out member) != null); + + member = null; + var members = type.GetMembers(); + foreach (var m in members) { + if (m == null) throw new IllFormedSemanticModelException("An null 'member' was found in a CSharpType's 'Members' field.", type); + if (MembersAreEquivalent(m, memberToMatch)) { + member = m; + return true; + } + } + return false; + } + /// + /// Crawls upward in the semantic tree looking for the first interface method that this method implements. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool TryGetInterfaceMember(ISymbol member, out ISymbol interfaceMethod) { + Contract.Requires(member != null); + Contract.Ensures(!Contract.Result() || + Contract.ValueAtReturn(out interfaceMethod) != null); + + interfaceMethod = null; + + if (member.ExplicitInterfaceImplementation() != null) + if (TryGetMemberWithSameSignatureFromType(member.ExplicitInterfaceImplementation(), member, out interfaceMethod)) + { + return true; + } + + if (member.ContainingType == null || member.ContainingType.AllInterfaces.IsDefault) + { + return false; + } + + foreach (var i in member.ContainingType.AllInterfaces) + { + if (i == null) continue; + if (TryGetMemberWithSameSignatureFromType(i, member, out interfaceMethod)) + { + return true; + } + } + return false; + } + /// + /// Checks if two types are equivalent. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool TypesAreEquivalent(ITypeSymbol type1, ITypeSymbol type2) { + if (type1 == null && type2 == null) return true; + if (type1 == null) return false; + if (type2 == null) return false; + + #region Check if type parameter + if ((type1.TypeKind == TypeKind.TypeParameter) != (type2.TypeKind == TypeKind.TypeParameter)) + return false; + if (type1.TypeKind == TypeKind.TypeParameter) { + ITypeParameterSymbol typeParameter1 = (ITypeParameterSymbol)type1; + ITypeParameterSymbol typeParameter2 = (ITypeParameterSymbol)type2; + if (typeParameter1.HasReferenceTypeConstraint ^ typeParameter2.HasReferenceTypeConstraint) return false; + if (typeParameter1.HasValueTypeConstraint ^ typeParameter2.HasValueTypeConstraint) return false; + return true; + } + #endregion + //return type1.Equals(type2); //TODO: Can we use this? Doesn't seem to work for generic types like 'List' + #region Check name + //if (type1.Name == null) throw new IllFormedSemanticModelException("A CSharpType was founded with a null 'Name' field.", type1); + //if (type2.Name == null) throw new IllFormedSemanticModelException("A CSharpType was founded with a null 'Name' field.", type2); + //It seems array types always have null names + if (type1.Name != null ^ type2.Name != null) return false; + if (type1.Name != null && type2.Name != null && + !type1.Name.Equals(type2.Name)) return false; + #endregion + #region Check containing type and namespace + if (type1.ContainingType != null ^ type2.ContainingType != null) return false; + if (type1.ContainingType != null && type2.ContainingType != null) { + if (!TypesAreEquivalent(type1.ContainingType, type2.ContainingType)) return false; + } else { + if (type1.ContainingNamespace != null ^ type2.ContainingNamespace != null) return false; + if (type1.ContainingNamespace != null && type2.ContainingNamespace != null && + !type1.ContainingNamespace.Equals(type2.ContainingNamespace)) return false; + } + #endregion + #region Check type parameters + if (!type1.TypeParameters().IsDefault ^ !type2.TypeParameters().IsDefault) return false; + if (!type1.TypeParameters().IsDefault && !type2.TypeParameters().IsDefault && + type1.TypeParameters().Length != type2.TypeParameters().Length) return false; + #endregion + #region Check type arguments + + if (!type1.TypeArguments().IsDefault ^ !type2.TypeArguments().IsDefault) return false; + if (!type1.TypeArguments().IsDefault && !type2.TypeArguments().IsDefault && + !TypeListsAreEquivalent(type1.TypeArguments(), type2.TypeArguments())) return false; + #endregion + #region Check array + if ((type1.TypeKind == TypeKind.Array) ^ (type2.TypeKind == TypeKind.Array)) return false; + if ((type1.TypeKind == TypeKind.Array) && (type2.TypeKind == TypeKind.Array)) + return TypesAreEquivalent(type1.ElementType(), type2.ElementType()); + #endregion + #region Check pointer + if ((type1.TypeKind == TypeKind.Pointer) ^ (type2.TypeKind == TypeKind.Pointer)) return false; + if ((type1.TypeKind == TypeKind.Pointer) && (type2.TypeKind == TypeKind.Pointer)) + return TypesAreEquivalent(type1.ElementType(), type2.ElementType()); + #endregion + if ((type1.TypeKind == TypeKind.Class) != (type2.TypeKind == TypeKind.Class) + || (type1.TypeKind == TypeKind.Struct) != (type2.TypeKind == TypeKind.Struct) + || type1.IsStatic != type2.IsStatic + || type1.IsValueType != type2.IsValueType) + return false; + return true; + } + /// + /// Checks if two type lists are equivalent. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool TypeListsAreEquivalent(IEnumerable typeList1, IEnumerable typeList2) { + Contract.Requires(typeList1 != null); + Contract.Requires(typeList2 != null); + return EnumerablesAreEquivalent(typeList1, typeList2, (t1, t2) => TypesAreEquivalent(t1, t2)); + } + [Pure] + public static ISymbol Uninstantiate(this ISymbol member) { + Contract.Requires(member != null); + Contract.Ensures(Contract.Result() != null); + Contract.Ensures(member.Kind == Contract.Result().Kind); + + var uninstantiatedMember = member.OriginalDefinition; + + Contract.Assume(member.Kind == uninstantiatedMember.Kind); + return uninstantiatedMember; + } + [Pure] + public static ITypeSymbol Uninstantiate(this ITypeSymbol type) { + Contract.Requires(type != null); + Contract.Ensures(Contract.Result() != null); + + var uninstantiatedType = type.OriginalDefinition; + + return uninstantiatedType; + } + } + + [Serializable] + public class IllFormedSemanticModelException : Exception { + public ISymbol BadMember { get; private set; } + public ITypeSymbol BadType { get; private set; } + public IParameterSymbol BadParameter { get; private set; } + public INamespaceSymbol BadNamespace { get; private set; } + public CSharpKind Kind { get; private set; } + + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant((BadMember != null) == (Kind == CSharpKind.CSharpMember)); + Contract.Invariant((BadType != null) == (Kind == CSharpKind.CSharpType)); + Contract.Invariant((BadParameter != null) == (Kind == CSharpKind.CSharpParameter)); + Contract.Invariant((BadNamespace != null) == (Kind == CSharpKind.CSharpNamespace)); + } + + public IllFormedSemanticModelException() { } + public IllFormedSemanticModelException(string message) : base(message) { } + public IllFormedSemanticModelException(string message, Exception inner) : base(message, inner) { } + public IllFormedSemanticModelException(string message, ITypeSymbol badType) : base(message) { + Contract.Requires(badType != null); + + BadType = badType; + Kind = CSharpKind.CSharpType; + } + public IllFormedSemanticModelException(string message, ISymbol badMember) : base(message) { + Contract.Requires(badMember != null); + + BadMember = badMember; + Kind = CSharpKind.CSharpMember; + } + public IllFormedSemanticModelException(string message, IParameterSymbol badParameter) : base(message) { + Contract.Requires(badParameter != null); + + BadParameter = badParameter; + Kind = CSharpKind.CSharpParameter; + } + public IllFormedSemanticModelException(string message, INamespaceSymbol badNamespace) : base(message) { + Contract.Requires(badNamespace != null); + + BadNamespace = badNamespace; + Kind = CSharpKind.CSharpNamespace; + } + protected IllFormedSemanticModelException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base(info, context) { } + } + + public enum CSharpKind { + None, + CSharpMember, + CSharpType, + CSharpParameter, + CSharpNamespace + } +} \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Contracts/ContractsProvider.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Contracts/ContractsProvider.cs new file mode 100644 index 00000000..3cde68b1 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Contracts/ContractsProvider.cs @@ -0,0 +1,806 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.IO; +using ContractAdornments.Interfaces; +using Microsoft.Cci; +using Microsoft.Cci.Contracts; +using Microsoft.Cci.MutableContracts; +using Microsoft.CodeAnalysis; +using AssemblyIdentity = Microsoft.Cci.AssemblyIdentity; + +namespace ContractAdornments { + public class ContractsProvider : IContractsProvider { + readonly IProjectTracker _projectTracker; + INonlockingHost Host { + get { + Contract.Requires(_projectTracker.Host != null); + Contract.Ensures(Contract.Result() != null); + + return _projectTracker.Host; + } + } + + readonly Dictionary _semanticMembersToCCIMethods; + readonly Dictionary _semanticTypesToCCITypes; + readonly Dictionary _semanticAssemblysToCCIAssemblys; + readonly Dictionary> _semanticPropertiesToCCIAccessorMethods; + + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(_semanticAssemblysToCCIAssemblys != null); + Contract.Invariant(_semanticMembersToCCIMethods != null); + Contract.Invariant(_semanticTypesToCCITypes != null); + Contract.Invariant(_semanticPropertiesToCCIAccessorMethods != null); + Contract.Invariant(_projectTracker != null); + Contract.Invariant(Host != null); + } + + public ContractsProvider(IProjectTracker projectTracker) { + Contract.Requires(projectTracker != null); + + //Grab a pointer back to our project tracker + _projectTracker = projectTracker; + + //Initialize our caches + _semanticMembersToCCIMethods = new Dictionary(); + _semanticTypesToCCITypes = new Dictionary(); + _semanticAssemblysToCCIAssemblys = new Dictionary(); + _semanticPropertiesToCCIAccessorMethods = new Dictionary>(); + } + + public void Clear() { + //host = null; + ContractsPackageAccessor.Current.Logger.WriteToLog("Clearing all caches in ContractsProvider."); + + //Clear caches + _semanticAssemblysToCCIAssemblys.Clear(); + _semanticMembersToCCIMethods.Clear(); + _semanticTypesToCCITypes.Clear(); + _semanticPropertiesToCCIAccessorMethods.Clear(); + } + //int counter = 0; + [ContractVerification(true)] + public bool TryGetAssemblyReference(IAssemblySymbol semanticAssembly, out IAssemblyReference cciAssembly) { + Contract.Ensures(!Contract.Result() || Contract.ValueAtReturn(out cciAssembly) != null); + + cciAssembly = null; + + #region Check input + if (semanticAssembly == null) { + return false; + } + #endregion + #region Check cache + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) + if (_semanticAssemblysToCCIAssemblys.TryGetValue(semanticAssembly, out cciAssembly)) + return cciAssembly != Dummy.AssemblyReference && cciAssembly != null; + #endregion + // distinguish between the AssemblyName and the ProjectName + + var semanticAssemblyFileName = (semanticAssembly.Name == null) ? null : semanticAssembly.Name; + if (string.IsNullOrWhiteSpace(semanticAssemblyFileName)) return false; + var semanticAssemblyName = Path.GetFileName(semanticAssemblyFileName); + if (semanticAssemblyName.EndsWith(".dll") || semanticAssemblyName.EndsWith(".exe")) + semanticAssemblyName = semanticAssemblyName.Remove(semanticAssemblyName.Length - 4, 4); + + #region Try to get assembly from previously loaded assemblies from host + foreach (var unit in Host.LoadedUnits) { + if (unit == null) continue; + if (unit is Dummy) continue; + if (unit.Name.Value == semanticAssemblyName) { + cciAssembly = (IAssemblyReference)unit; + if (cciAssembly.ResolvedAssembly.Location == semanticAssemblyFileName) + { + goto ReturnTrue; + } + } + } + #endregion + #region Check if assembly is the same as the current project's output assembly + if (_projectTracker.AssemblyIdentity != null && _projectTracker.AssemblyIdentity.Name != null) { + if (semanticAssemblyName.Equals(_projectTracker.AssemblyIdentity.Name.Value, StringComparison.OrdinalIgnoreCase) || semanticAssemblyName.Equals(_projectTracker.ProjectName, StringComparison.OrdinalIgnoreCase)) { + cciAssembly = new Microsoft.Cci.Immutable.AssemblyReference(this.Host, _projectTracker.AssemblyIdentity); + Host.AddLibPath(Path.Combine(Path.GetDirectoryName(semanticAssemblyFileName), "CodeContracts")); + Host.AddLibPath(Path.Combine(Path.GetDirectoryName(semanticAssemblyFileName), @"..\Debug\CodeContracts")); + goto ReturnTrue; + } + } else + ContractsPackageAccessor.Current.Logger.WriteToLog("Assembly identity for the project: " + _projectTracker.ProjectName + " was null."); + #endregion + #region Build assembly reference + if (semanticAssembly.Name == null || string.IsNullOrWhiteSpace(semanticAssembly.Name)) goto ReturnFalseNoOutput; // because we have no name. + var projectName = Path.GetFileName(semanticAssembly.Name); + if (projectName.EndsWith(".dll") || projectName.EndsWith(".exe")) + projectName = projectName.Remove(projectName.Length - 4, 4); + var references = _projectTracker.References; + VSLangProj.Reference reference = null; + for (int i = 1, refcount = references == null ? 0 : references.Count; i <= refcount; i++) + { + var tempRef = references.Item(i); + if (tempRef == null) continue; + string refName = tempRef.Name;//Path.GetFileNameWithoutExtension(tempRef.Name); + if (refName == null) continue; + if (refName.Equals(projectName, StringComparison.OrdinalIgnoreCase)) { + reference = tempRef; + break; + } + } + if (reference != null) { + IName iName = Host.NameTable.GetNameFor(Path.GetFileNameWithoutExtension(reference.Path)); + string culture = reference.Culture ?? "en"; + Version version = new Version(reference.MajorVersion, reference.MinorVersion, reference.BuildNumber, reference.RevisionNumber); + string location = reference.Path; + if (!string.IsNullOrEmpty(location)) + { + Host.AddLibPath(Path.Combine(location.Substring(0, location.Length - Path.GetFileName(location).Length), "CodeContracts")); + var assemblyIdentity = new AssemblyIdentity(iName, culture, version, Enumerable.Empty, location); + cciAssembly = new Microsoft.Cci.Immutable.AssemblyReference(this.Host, assemblyIdentity); + goto ReturnTrue; + } + } + goto ReturnFalse; + #endregion + #region ReturnTrue: + ReturnTrue: + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) + _semanticAssemblysToCCIAssemblys[semanticAssembly] = cciAssembly; + EnsureAssemblyIsLoaded(semanticAssembly, ref cciAssembly); + return true; + #endregion + #region ReturnFalse: + ReturnFalse: + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to build assembly reference for: " + semanticAssembly.Name); + ReturnFalseNoOutput: + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) + _semanticAssemblysToCCIAssemblys[semanticAssembly] = Dummy.AssemblyReference; + return false; + #endregion + } + public bool TryGetPropertyContract(ISymbol semanticMember, out IMethodContract getterContract, out IMethodContract setterContract) + { + Contract.Requires(semanticMember == null || semanticMember.Kind == SymbolKind.Property); + + getterContract = null; + setterContract = null; + + #region Check input + if (semanticMember == null) + { + return false; + } + #endregion + IMethodReference getter, setter; + if (!TryGetPropertyAccessorReferences(semanticMember, out getter, out setter)) { return false; } + + var success = false; + if (getter != null) + { + success |= TryGetMethodContract(getter, out getterContract); + } + if (setter != null) + { + success |= TryGetMethodContract(setter, out setterContract); + } + return success; + } + public bool TryGetMethodContract(ISymbol semanticMethod, out IMethodContract methodContract) + { + Contract.Requires(semanticMethod == null || semanticMethod.Kind == SymbolKind.Method); + Contract.Ensures(!Contract.Result() || (Contract.ValueAtReturn(out methodContract) != null)); + + methodContract = null; + + #region Check input + if (semanticMethod == null) { + return false; + } + #endregion + + #region Try get the reference then check for contracts + IMethodReference cciMethod; + if (TryGetMethodReference(semanticMethod, out cciMethod)) { + if (TryGetMethodContract(cciMethod, out methodContract)) { + return true; + } else { + //No need, detailed logs are written at all code paths in "TryGetMethodContract" + //ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get method contracts for: " + cciMethod.Name); + } + } else { + methodContract = null; + if (semanticMethod.Name != null) + { + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get CCI reference for: " + semanticMethod.Name); + } + } + return false; + #endregion + } + public bool TryGetMethodContract(IMethodReference method, out IMethodContract methodContract) { + Contract.Ensures(!Contract.Result() || (Contract.ValueAtReturn(out methodContract) != null)); + + methodContract = null; + + #region Check input + if (method == null) { + return false; + } + #endregion + try { + // Resolving the method works *only* if the unit it is defined in has already been loaded. + // That should have happened as part of creating the IMethodReference. + var resolvedMethod = method.ResolvedMethod; + if (resolvedMethod != Dummy.Method) { + methodContract = ContractHelper.GetMethodContractForIncludingInheritedContracts(Host, resolvedMethod); + if (methodContract == null) { + methodContract = ContractDummy.MethodContract; + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Did not find any method contract(s) for '{0}'", method.Name)); + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog( + String.Format("Got method contract(s) for '{0}': {1} preconditions, {2} postconditions", + method.Name, + Microsoft.Cci.IteratorHelper.EnumerableCount(methodContract.Preconditions), + Microsoft.Cci.IteratorHelper.EnumerableCount(methodContract.Postconditions))); + } + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Method '{0}' resolved to dummy", method.Name)); + } + } catch (NullReferenceException) { + methodContract = null; + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("NullReferenceException thrown when getting contracts for '{0}'", method.Name)); + } + return methodContract != null; + } + public bool TryGetMethodContractSafe(ISymbol semanticMehod, out IMethodContract methodContract) { + Contract.Requires(semanticMehod == null || semanticMehod.Kind == SymbolKind.Method); + Contract.Ensures(!Contract.Result() || (Contract.ValueAtReturn(out methodContract) != null)); + + methodContract = null; + + #region Check input + if (semanticMehod == null) { + return false; + } + #endregion + #region Call TryGetMethodContract cautiously + try { + //Can we get contracts? + if (!TryGetMethodContract(semanticMehod, out methodContract)) + return false; + } + #endregion + #region Abort on exception + //Give up on our contracts if we get an exception + catch (IllFormedSemanticModelException) { + return false; + } catch (InvalidOperationException e) { + if (!e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) + throw e; + else + return false; + } catch (System.Runtime.InteropServices.COMException e) { + if (!e.Message.Contains(ContractsPackageAccessor.COMExceptionMessage_BindingFailed)) + throw e; + else + return false; + } + #endregion + + return methodContract != null; + } + public bool TryGetMethodReference(ISymbol semanticMethod, out IMethodReference cciMethod) { + Contract.Requires(semanticMethod == null || semanticMethod.Kind == SymbolKind.Method); + Contract.Ensures(!Contract.Result() || Contract.ValueAtReturn(out cciMethod) != null); + + cciMethod = null; + + #region Check input + if (semanticMethod == null) { + return false; + } + #endregion + #region Check cache + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) + if (_semanticMembersToCCIMethods.TryGetValue(semanticMethod, out cciMethod)) + return (!(cciMethod is Dummy)) && cciMethod != null; + #endregion + #region Set up our working cci method + var workingCciMethod = new Microsoft.Cci.MutableCodeModel.MethodReference(); + #endregion + #region Set the intern factory + workingCciMethod.InternFactory = Host.InternFactory; + #endregion + #region Get calling conventions + workingCciMethod.CallingConvention = CSharpToCCIHelper.GetCallingConventionFor(semanticMethod); + #endregion + #region Get containing type reference + ITypeReference containingType; + if (!TryGetTypeReference(semanticMethod.ContainingType, out containingType)) + goto ReturnFalse; + workingCciMethod.ContainingType = containingType; + #endregion + #region Get return type reference + if (semanticMethod.IsConstructor()) + workingCciMethod.Type = this.Host.PlatformType.SystemVoid; + else { + ITypeReference returnType; + if (!TryGetTypeReference(semanticMethod.ReturnType(), out returnType)) + goto ReturnFalse; + workingCciMethod.Type = returnType; + } + #endregion + #region Get name + if (!semanticMethod.IsConstructor() && semanticMethod.Name == null) goto ReturnFalse; + workingCciMethod.Name = Host.NameTable.GetNameFor(semanticMethod.IsConstructor()?".ctor":semanticMethod.Name); + #endregion + #region Get generic param count + if (semanticMethod.TypeParameters().IsDefault) + workingCciMethod.GenericParameterCount = 0; + else + workingCciMethod.GenericParameterCount = (ushort)semanticMethod.TypeParameters().Length; + #endregion + #region Get parameter references + List cciParameters; + if (semanticMethod.Parameters().IsDefault) goto ReturnFalse; + Contract.Assume(semanticMethod.Parameters().Length <= ushort.MaxValue, "Should be a postcondition?"); + if (!TryGetParametersList(semanticMethod.Parameters(), out cciParameters)) + goto ReturnFalse; + workingCciMethod.Parameters = cciParameters; + #endregion + #region Get the assembly reference (this also ensures the assembly gets loaded properly) + IAssemblyReference assemblyReference; + TryGetAssemblyReference(semanticMethod.ContainingAssembly, out assemblyReference); + #endregion + cciMethod = workingCciMethod; + return true; + #region ReturnFalse: + ReturnFalse: + cciMethod = Dummy.MethodReference; + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) + _semanticMembersToCCIMethods[semanticMethod] = cciMethod; + return false; + #endregion + } + public bool TryGetNamespaceReference(INamespaceSymbol semanticNamespace, IAssemblyReference cciAssembly, out IUnitNamespaceReference cciNamespace) { + Contract.Ensures(!Contract.Result() || (Contract.ValueAtReturn(out cciNamespace) != null)); + + cciNamespace = null; + + #region Check input + if (semanticNamespace == null || cciAssembly == null) { + return false; + } + #endregion + #region If root + try { + if (semanticNamespace.IsGlobalNamespace) { + cciNamespace = new Microsoft.Cci.MutableCodeModel.RootUnitNamespaceReference() { Unit = cciAssembly }; + goto ReturnTrue; + } + } catch (InvalidOperationException e) { //For some reason, an InvalidOperationException may get thrown. + if (e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) + goto ReturnFalse; + else + throw e; + } + #endregion + #region If nested + if (semanticNamespace.ContainingNamespace != null) { + IUnitNamespaceReference parentNs; + if (!TryGetNamespaceReference(semanticNamespace.ContainingNamespace, cciAssembly, out parentNs)) + goto ReturnFalse; + if (semanticNamespace.Name == null) goto ReturnFalse; + cciNamespace = new Microsoft.Cci.Immutable.NestedUnitNamespaceReference(parentNs, Host.NameTable.GetNameFor(semanticNamespace.Name)); + goto ReturnTrue; + } + #endregion + Contract.Assert(cciNamespace == null); + goto ReturnFalse; + + #region ReturnTrue: + ReturnTrue: + return true; + #endregion + #region ReturnFalse: + ReturnFalse: + return false; + #endregion + } + public bool TryGetParametersList(IList semanticParameters, out List cciParameters, ushort indexOffset = 0) { + Contract.Requires(semanticParameters != null); + Contract.Ensures(!Contract.Result() || Contract.ValueAtReturn(out cciParameters) != null); + cciParameters = null; + + #region Check input + if (semanticParameters == null || semanticParameters.Count + indexOffset > ushort.MaxValue) { + return false; + } + #endregion + #region Get parameter count + var paramCount = semanticParameters.Count; + #endregion + #region Initialize our parameter list + cciParameters = new List(paramCount); + #endregion + #region Populate the parameter list + for (ushort i = 0; i < paramCount; i++) { + var semanticParam = semanticParameters[i]; + Contract.Assume(semanticParam != null); + IParameterTypeInformation cciParam; + if (!TryGetParameterReference(semanticParam, (ushort)(i + indexOffset), out cciParam)) + goto ReturnFalse; + cciParameters.Add(cciParam); + } + #endregion + return true; + #region ReturnFalse: + ReturnFalse: + return false; + #endregion + } + public bool TryGetParameterReference(IParameterSymbol semanticParameter, ushort index, out IParameterTypeInformation cciParameter) { + + cciParameter = null; + + #region Check input + if (semanticParameter == null) { + return false; + } + #endregion + #region Set up our working cci parameter + Microsoft.Cci.MutableCodeModel.ParameterTypeInformation workingParameter = null; + cciParameter = workingParameter = new Microsoft.Cci.MutableCodeModel.ParameterTypeInformation(); + #endregion + #region Get our parameter type + ITypeReference paramType; + if (!TryGetTypeReference(semanticParameter.Type, out paramType)) + goto ReturnFalse; + workingParameter.Type = paramType; + #endregion + #region Get our index + workingParameter.Index = index; + #endregion + #region Get our reference status + workingParameter.IsByReference = semanticParameter.RefKind == RefKind.Out || semanticParameter.RefKind == RefKind.Ref; + #endregion + #region ReturnTrue: + //ReturnTrue: + return cciParameter != Dummy.ParameterTypeInformation; + #endregion + #region ReturnFalse: + ReturnFalse: + if (semanticParameter.Name != null) + { + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to build parameter reference for: " + semanticParameter.Name); + } + return false; + #endregion + } + public bool TryGetPropertyAccessorReferences(ISymbol semanticProperty, out IMethodReference getter, out IMethodReference setter) { + Contract.Requires(semanticProperty == null || semanticProperty.Kind == SymbolKind.Property); + + getter = setter = null; + + #region Check input + if (semanticProperty == null) { + return false; + } + #endregion + #region Check cache + Tuple cacheOutput; + if (_semanticPropertiesToCCIAccessorMethods.TryGetValue(semanticProperty, out cacheOutput)) { + Contract.Assume(cacheOutput != null, "Non-null only dictionary"); + getter = cacheOutput.Item1; + setter = cacheOutput.Item2; + return (getter != null && getter != Dummy.MethodReference) || (setter != null && setter != Dummy.MethodReference); + } + #endregion + #region Get calling conventions + var callingConventions = CSharpToCCIHelper.GetCallingConventionFor(semanticProperty); + #endregion + #region get containing type + ITypeReference containingType; + if (!TryGetTypeReference(semanticProperty.ContainingType, out containingType)) + goto ReturnFalse; + #endregion + #region Get return type + ITypeReference returnType; + if (!TryGetTypeReference(semanticProperty.ReturnType(), out returnType)) + goto ReturnFalse; + #endregion + #region Get the property's name + string propertyName; + if (semanticProperty.IsIndexer()) + propertyName = "Item"; + else + { + if (semanticProperty.Name == null) goto ReturnFalse; + propertyName = semanticProperty.Name; + } + #endregion + #region Get the parameters + List getterParams; + if (!semanticProperty.Parameters().IsDefault) { + if (!TryGetParametersList(semanticProperty.Parameters(), out getterParams)) + goto ReturnFalse; + } else + getterParams = new List(); + + List setterParams; + if (!semanticProperty.Parameters().IsDefault) { + if (!TryGetParametersList(semanticProperty.Parameters(), out setterParams, 1)) + goto ReturnFalse; + #region Append the "value" param + var valParam = new Microsoft.Cci.MutableCodeModel.ParameterTypeInformation() { + Type = returnType, + Index = 0, + IsByReference = false + }; + setterParams.Insert(0, valParam); + #endregion + } else + setterParams = new List(); + #endregion + #region Build the getter + getter = new Microsoft.Cci.MutableCodeModel.MethodReference() { + InternFactory = Host.InternFactory, + CallingConvention = callingConventions, + ContainingType = containingType, + Type = returnType, + Name = Host.NameTable.GetNameFor("get_" + propertyName), + GenericParameterCount = 0, + Parameters = getterParams + }; + #endregion + #region Build the setter + setter = new Microsoft.Cci.MutableCodeModel.MethodReference() { + InternFactory = Host.InternFactory, + CallingConvention = callingConventions, + ContainingType = containingType, + Type = Host.PlatformType.SystemVoid, + Name = Host.NameTable.GetNameFor("set_" + propertyName), + GenericParameterCount = 0, + Parameters = setterParams + }; + #endregion + #region Get the assembly reference (this also ensures the assembly gets loaded properly) + IAssemblyReference assemblyReference; + TryGetAssemblyReference(semanticProperty.ContainingAssembly, out assemblyReference); + #endregion + #region ReturnTrue: + //ReturnTrue: + _semanticPropertiesToCCIAccessorMethods[semanticProperty] = new Tuple(getter, setter); + return true; + #endregion + #region ReturnFalse: + ReturnFalse: + if (semanticProperty.Name != null) + { + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to build accessor references for: " + semanticProperty.Name); + } + _semanticPropertiesToCCIAccessorMethods[semanticProperty] = new Tuple(Dummy.MethodReference, Dummy.MethodReference); + return false; + #endregion + } + public bool TryGetTypeReference(ITypeSymbol semanticType, IAssemblyReference cciAssembly, out ITypeReference cciType) { + Contract.Ensures(!Contract.Result() || (Contract.ValueAtReturn(out cciType) != null)); + + cciType = null; + + #region Check input + if (semanticType == null || cciAssembly == null) { + return false; + } + #endregion + #region Check cache + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) + if (_semanticTypesToCCITypes.TryGetValue(semanticType, out cciType)) + return cciType != null && cciType != Dummy.TypeReference; + #endregion + #region If generic + if (!semanticType.TypeArguments().IsDefault && semanticType.TypeArguments().Length > 0) { + var genericArguments = new List(); + foreach (var semanticTypeArg in semanticType.TypeArguments()) { + if (semanticTypeArg == null) goto ReturnFalse; + ITypeReference cciTypeArg = null; + if (TryGetTypeReference(semanticTypeArg, out cciTypeArg)) { + genericArguments.Add(cciTypeArg); + } else { + goto ReturnFalse; + } + } + ITypeReference genericType = null; + if (!TryGetTypeReference(semanticType.ContainingType, out genericType)) { + goto ReturnFalse; + } + cciType = new Microsoft.Cci.MutableCodeModel.GenericTypeInstanceReference() { + InternFactory = this.Host.InternFactory, + GenericArguments = genericArguments, + GenericType = (INamedTypeReference) genericType, + }; + goto ReturnTrue; + } + #endregion + #region If array + if (semanticType.TypeKind == TypeKind.Array) { + ITypeReference eleType; + if (!TryGetTypeReference(semanticType.ElementType(), out eleType)) + goto ReturnFalse; + if (semanticType.ElementType().TypeKind == TypeKind.Array) { + Contract.Assume(((IArrayTypeSymbol)semanticType).Rank > 0); + cciType = new Microsoft.Cci.MutableCodeModel.MatrixTypeReference() { + ElementType = eleType, + InternFactory = this.Host.InternFactory, + Rank = (uint)((IArrayTypeSymbol)semanticType).Rank + }; + goto ReturnTrue; + } else { + cciType = new Microsoft.Cci.MutableCodeModel.VectorTypeReference() { + ElementType = eleType, + InternFactory = this.Host.InternFactory, + }; + goto ReturnTrue; + } + } + #endregion + #region If type parameter + if (semanticType.TypeKind == TypeKind.TypeParameter) { + if (semanticType.ContainingSymbol != null && semanticType.ContainingSymbol.Kind == SymbolKind.Method) { + cciType = new Microsoft.Cci.MutableCodeModel.GenericMethodParameterReference() { + Index = (ushort)(!semanticType.ContainingSymbol.TypeParameters().IsDefault ? semanticType.ContainingSymbol.TypeParameters().IndexOf((ITypeParameterSymbol)semanticType) : 0), + InternFactory = this.Host.InternFactory, + Name = Host.NameTable.GetNameFor(semanticType.Name != null ? semanticType.Name : "T"), + }; + goto ReturnTrue; + } else if (semanticType.ContainingType != null) { + ITypeReference cciDefiningType; + if (!TryGetTypeReference(semanticType.ContainingType, out cciDefiningType)) + goto ReturnFalse; + cciType = new Microsoft.Cci.MutableCodeModel.GenericTypeParameterReference() { + DefiningType = cciDefiningType, + Index = (ushort)(semanticType.ContainingType.TypeParameters != null ? semanticType.ContainingType.TypeParameters.IndexOf((ITypeParameterSymbol)semanticType) : 0), + InternFactory = this.Host.InternFactory, + Name = Host.NameTable.GetNameFor(semanticType.Name != null ? semanticType.Name : "T"), + }; + goto ReturnTrue; + } + } + #endregion + #region If namespace type + if (semanticType.ContainingType == null) + { + IUnitNamespaceReference cciNamespace; + var namespaceName = semanticType.ContainingNamespace; + if (namespaceName == null || !TryGetNamespaceReference(namespaceName, cciAssembly, out cciNamespace)) + { + cciNamespace = new Microsoft.Cci.MutableCodeModel.RootUnitNamespaceReference() { Unit = cciAssembly }; + } + if (semanticType.ContainingType == null) + { + if (semanticType.Name == null || semanticType.Name == null) goto ReturnFalse; + cciType = new Microsoft.Cci.MutableCodeModel.NamespaceTypeReference() + { + ContainingUnitNamespace = cciNamespace, + GenericParameterCount = (ushort) (semanticType.TypeParameters().IsDefault ? 0 : semanticType.TypeParameters().Length), + InternFactory = Host.InternFactory, + IsValueType = semanticType.IsValueType, + IsEnum = semanticType.TypeKind == TypeKind.Enum, + Name = Host.NameTable.GetNameFor(semanticType.Name), + TypeCode = CSharpToCCIHelper.GetPrimitiveTypeCode(semanticType), + }; + goto ReturnTrue; + } + } + #endregion + #region If nested type + if (semanticType.ContainingType != null) { + ITypeReference containingType; + if (!TryGetTypeReference(semanticType.ContainingType, cciAssembly, out containingType)) + goto ReturnFalse; + if (semanticType.Name == null || semanticType.Name == null) goto ReturnFalse; + cciType = new Microsoft.Cci.MutableCodeModel.NestedTypeReference() + { + ContainingType = containingType, + GenericParameterCount = (ushort)(semanticType.TypeParameters().IsDefault ? 0 : semanticType.TypeParameters().Length), + InternFactory = this.Host.InternFactory, + MangleName = true, + Name = Host.NameTable.GetNameFor(semanticType.Name) + }; + goto ReturnTrue; + } + #endregion + #region ReturnTrue: + ReturnTrue: + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) + _semanticTypesToCCITypes[semanticType] = cciType; + return true; + #endregion + #region ReturnFalse: + ReturnFalse: + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to build type reference for: " + (semanticType.Name != null ? semanticType.Name : semanticType.ToString())); + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) + _semanticTypesToCCITypes[semanticType] = Dummy.TypeReference; + return false; + #endregion + } + public bool TryGetTypeReference(ITypeSymbol semanticType, out ITypeReference cciType) { + Contract.Ensures(!Contract.Result() || Contract.ValueAtReturn(out cciType) != null && semanticType != null); + + cciType = null; + + #region Check input + if (semanticType == null) { + return false; + } + #endregion + #region Check cache + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) + if (_semanticTypesToCCITypes.TryGetValue(semanticType, out cciType)) + return cciType != null && cciType != Dummy.TypeReference; + #endregion + #region Get assembly reference + IAssemblyReference cciAssembly; + if (!TryGetAssemblyReference(semanticType.ContainingAssembly, out cciAssembly)) + goto ReturnFalse; + #endregion + return TryGetTypeReference(semanticType, cciAssembly, out cciType); + #region ReturnFalse: + ReturnFalse: + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) + _semanticTypesToCCITypes[semanticType] = Dummy.TypeReference; + return false; + #endregion + } + + [ContractVerification(true)] + void EnsureAssemblyIsLoaded(IAssemblySymbol semanticAssembly, ref IAssemblyReference assemblyReference) { + Contract.Ensures(assemblyReference != null || Contract.OldValue(assemblyReference) == null); + #region Check input + if (semanticAssembly == null || assemblyReference == null) { + return; + } + #endregion + + var assembly = assemblyReference as IAssembly; + if (assembly == null) { + assembly = Host.FindAssembly(assemblyReference.AssemblyIdentity); + if (assembly == Dummy.Assembly) { + var location = assemblyReference.AssemblyIdentity.Location; + if (File.Exists(location)) { + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Calling LoadUnitFrom on assembly '{0}' for future resolution.", location)); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("core assembly: '{0}'", Host.CoreAssemblySymbolicIdentity.ToString())); + assembly = Host.LoadUnitFrom(location) as IAssembly; + if (assembly != null){ + assemblyReference = assembly; + if(ContractsPackageAccessor.Current.VSOptionsPage.Caching) + _semanticAssemblysToCCIAssemblys[semanticAssembly] = assembly; + } + else{ + ContractsPackageAccessor.Current.Logger.WriteToLog("Warning: Found a unit at '" + location + "', but it wasn't an assembly!"); + } + } else{ + ContractsPackageAccessor.Current.Logger.WriteToLog("Assembly not found at: '" + location + "'. This could be because the assembly hasn't been built yet."); + } + } else { + assemblyReference = assembly; + if(ContractsPackageAccessor.Current.VSOptionsPage.Caching) + _semanticAssemblysToCCIAssemblys[semanticAssembly] = assembly; + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Extensions.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Extensions.cs new file mode 100644 index 00000000..035c1516 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Extensions.cs @@ -0,0 +1,118 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System.Diagnostics.Contracts; +using Adornments; +using ContractAdornments.Interfaces; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; + +namespace ContractAdornments { + static class HelperExtensions { + public static string GetFileName(this ITextView @this) { + Contract.Requires(@this != null); + + if (@this.TextBuffer == null) return null; + return @this.TextBuffer.GetFileName(); + } + public static string GetFileName(this ITextBuffer @this) { + Contract.Requires(@this != null); + ITextDocument doc; + if (@this.Properties == null) return null; + if (@this.Properties.TryGetProperty(typeof(ITextDocument), out doc)) { + Contract.Assume(doc != null); + if (doc.FilePath == null) { return null; } + return doc.FilePath.ToLower(); + } + return null; + } + + public static SnapshotSpan Convert(this LinePositionSpan span, ITextSnapshot snapshot) { + Contract.Requires(snapshot != null); + var startIndex = snapshot.GetPositionFromLineColumn(span.Start.Line, span.Start.Character); + var endIndex = snapshot.GetPositionFromLineColumn(span.End.Line, span.End.Character); + // still need to do range check: have seen this be too long + var len = endIndex - startIndex; + var maxLen = snapshot.Length - startIndex; + var usableLength = len > maxLen ? maxLen : len; // min(len,maxLen) + return new SnapshotSpan(snapshot, startIndex, usableLength); + } + + public static LinePosition Convert(this ITrackingPoint point, ITextSnapshot snapshot) { + Contract.Requires(point != null); + + var snapshotPoint = point.GetPoint(snapshot); + var line = snapshotPoint.GetContainingLine(); + if (line == null) return default(LinePosition); + int lineIndex = line.LineNumber; + int charIndex = snapshotPoint.Position - line.Start.Position; + return new LinePosition(lineIndex, charIndex); + } + + public static int GetPositionFromLineColumn(this ITextSnapshot snapshot, int line, int column) { + Contract.Requires(snapshot != null); + + var textline = snapshot.GetLineFromLineNumber(line); + if (textline == null) return 0; + return textline.Start.Position + column; + } + + public static string GetName(this PropertyDeclarationSyntax @this, ITextSnapshot snapshot) { + Contract.Requires(@this != null); + Contract.Requires(snapshot != null); + return @this.Identifier.ValueText; + } + + public static string GetName(this MethodDeclarationSyntax @this, ITextSnapshot snapshot) { + Contract.Requires(@this != null); + Contract.Requires(snapshot != null); + return @this.Identifier.ValueText; + } + + public static string GetName(this BaseTypeDeclarationSyntax @this, ITextSnapshot snapshot) { + Contract.Requires(@this != null); + Contract.Requires(snapshot != null); + return @this.Identifier.ValueText; + } + + public static bool IsModelReady(this SyntaxTree parseTree) { + Contract.Requires(parseTree != null); + SyntaxNode ignored; + return parseTree.TryGetRoot(out ignored); + } + } + public static class AdornmentOptionsHelper { + public static AdornmentOptions GetAdornmentOptions(IContractOptionsPage options) { + var result = AdornmentOptions.None; + + if (options == null) + return result; + + if (options.SmartFormatting) + result = result | AdornmentOptions.SmartFormatting; + + if (options.SyntaxColoring) + result = result | AdornmentOptions.SyntaxColoring; + + if (options.CollapseMetadataContracts) + { + result = result | AdornmentOptions.CollapseWithRegion; + } + return result; + } + } +} \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/CSharp.Roslyn/ISymbolExtensions.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/ISymbolExtensions.cs new file mode 100644 index 00000000..92d34899 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/ISymbolExtensions.cs @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments +{ + using System; + using System.Collections.Immutable; + using System.Linq; + using Microsoft.CodeAnalysis; + + internal static class ISymbolExtensions + { + public static MethodKind? MethodKind(this ISymbol symbol) + { + IMethodSymbol methodSymbol = symbol as IMethodSymbol; + if (methodSymbol == null) + return null; + + return methodSymbol.MethodKind; + } + + public static bool IsConstructor(this ISymbol symbol) + { + return symbol.MethodKind() == Microsoft.CodeAnalysis.MethodKind.Constructor; + } + + public static bool IsIndexer(this ISymbol symbol) + { + IPropertySymbol propertySymbol = symbol as IPropertySymbol; + if (propertySymbol == null) + return false; + + return propertySymbol.IsIndexer; + } + + public static ITypeSymbol ReturnType(this ISymbol symbol) + { + switch (symbol.Kind) + { + case SymbolKind.Property: + return ((IPropertySymbol)symbol).Type; + + case SymbolKind.Method: + return ((IMethodSymbol)symbol).ReturnType; + + default: + return null; + } + } + + public static ImmutableArray TypeArguments(this ITypeSymbol symbol) + { + INamedTypeSymbol namedTypeSymbol = symbol as INamedTypeSymbol; + if (namedTypeSymbol == null) + return default(ImmutableArray); + + return namedTypeSymbol.TypeArguments; + } + + public static ITypeSymbol ElementType(this ITypeSymbol symbol) + { + switch (symbol.TypeKind) + { + case TypeKind.Array: + return ((IArrayTypeSymbol)symbol).ElementType; + + case TypeKind.Pointer: + return ((IPointerTypeSymbol)symbol).PointedAtType; + + default: + return null; + } + } + + public static ImmutableArray TypeParameters(this ISymbol symbol) + { + switch (symbol.Kind) + { + case SymbolKind.Method: + return ((IMethodSymbol)symbol).TypeParameters; + + case SymbolKind.NamedType: + return ((INamedTypeSymbol)symbol).TypeParameters; + + default: + return ImmutableArray.Empty; + } + } + + public static ImmutableArray Parameters(this ISymbol symbol) + { + switch (symbol.Kind) + { + case SymbolKind.Property: + return ((IPropertySymbol)symbol).Parameters; + + case SymbolKind.Method: + return ((IMethodSymbol)symbol).Parameters; + + default: + throw new NotSupportedException(); + } + } + + public static ITypeSymbol ExplicitInterfaceImplementation(this ISymbol symbol) + { + switch (symbol.Kind) + { + case SymbolKind.Property: + IPropertySymbol firstProperty = ((IPropertySymbol)symbol).ExplicitInterfaceImplementations.FirstOrDefault(); + return firstProperty != null ? firstProperty.ContainingType : null; + + case SymbolKind.Method: + IMethodSymbol firstMethod = ((IMethodSymbol)symbol).ExplicitInterfaceImplementations.FirstOrDefault(); + return firstMethod != null ? firstMethod.ContainingType : null; + + case SymbolKind.Event: + IEventSymbol firstEvent = ((IEventSymbol)symbol).ExplicitInterfaceImplementations.FirstOrDefault(); + return firstEvent != null ? firstEvent.ContainingType : null; + + default: + throw new NotSupportedException(); + } + } + } +} diff --git a/Microsoft.Research/ContractAdornments/Sources/Inheritance/InheritanceTracker.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Inheritance/InheritanceTracker.cs similarity index 65% rename from Microsoft.Research/ContractAdornments/Sources/Inheritance/InheritanceTracker.cs rename to Microsoft.Research/ContractAdornments/CSharp.Roslyn/Inheritance/InheritanceTracker.cs index 296544fd..ded19ecc 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Inheritance/InheritanceTracker.cs +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Inheritance/InheritanceTracker.cs @@ -73,7 +73,7 @@ private InheritanceTracker(TextViewTracker textViewTracker) { Contract.Requires(textViewTracker != null); Contract.Requires(textViewTracker.TextView != null); if (!AdornmentManager.TryGetAdornmentManager(textViewTracker.TextView, "InheritanceAdornments", out _adornmentManager)) { - VSServiceProvider.Current.Logger.WriteToLog("Inheritance adornment layer not instantiated."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Inheritance adornment layer not instantiated."); throw new InvalidOperationException("Inheritance adornment layer not instantiated."); } @@ -96,7 +96,7 @@ void OnClosed(object sender, EventArgs e) { } void OnBuildDone() { - VSServiceProvider.Current.Logger.WriteToLog("Removing all old adornments because of a new build for text file: " + _textViewTracker.FileName); + ContractsPackageAccessor.Current.Logger.WriteToLog("Removing all old adornments because of a new build for text file: " + _textViewTracker.FileName); _adornmentManager.Adornments.Clear(); _methodsNeedingContractLookup.Clear(); _propertiesNeedingContractLookup.Clear(); @@ -110,10 +110,10 @@ void OnLatestSourceFileChanged(object sender, LatestSourceFileChangedEventArgs e if (e.WasLatestSourceFileStale == true) { //Revaluate the inheritance adornments on the text view when we next have focus - if (VSServiceProvider.Current.VSOptionsPage.InheritanceOnMethods) - VSServiceProvider.Current.QueueWorkItem(() => RevaluateMethodInheritanceAdornments(this), () => _textViewTracker.TextView.HasAggregateFocus); - if (VSServiceProvider.Current.VSOptionsPage.InheritanceOnProperties) - VSServiceProvider.Current.QueueWorkItem(() => RevaluatePropertyInheritanceAdornments(this), () => _textViewTracker.TextView.HasAggregateFocus); + if (ContractsPackageAccessor.Current.VSOptionsPage.InheritanceOnMethods) + ContractsPackageAccessor.Current.QueueWorkItem(() => RevaluateMethodInheritanceAdornments(this), () => _textViewTracker.TextView.HasAggregateFocus); + if (ContractsPackageAccessor.Current.VSOptionsPage.InheritanceOnProperties) + ContractsPackageAccessor.Current.QueueWorkItem(() => RevaluatePropertyInheritanceAdornments(this), () => _textViewTracker.TextView.HasAggregateFocus); } } void OnLatestCompilationChanged(object sender, LatestCompilationChangedEventArgs e) { @@ -121,19 +121,19 @@ void OnLatestCompilationChanged(object sender, LatestCompilationChangedEventArgs Contract.Requires(e.LatestCompilation != null); //Do any methods need their contract information looked up? - if (VSServiceProvider.Current.VSOptionsPage.InheritanceOnMethods && _methodsNeedingContractLookup.Count > 0) { + if (ContractsPackageAccessor.Current.VSOptionsPage.InheritanceOnMethods && _methodsNeedingContractLookup.Count > 0) { //Recursively look up the needed contract information - VSServiceProvider.Current.Logger.WriteToLog("Attempting to lookup contracts for " + _methodsNeedingContractLookup.Count + " methods."); - VSServiceProvider.Current.QueueWorkItem(() => RecursivelyLookupContractsForMethods(this), () => _textViewTracker.TextView.HasAggregateFocus); + ContractsPackageAccessor.Current.Logger.WriteToLog("Attempting to lookup contracts for " + _methodsNeedingContractLookup.Count + " methods."); + ContractsPackageAccessor.Current.QueueWorkItem(() => RecursivelyLookupContractsForMethods(this), () => _textViewTracker.TextView.HasAggregateFocus); } //Do any properties need their contract information looked up? - if (VSServiceProvider.Current.VSOptionsPage.InheritanceOnProperties && _propertiesNeedingContractLookup.Count > 0) { + if (ContractsPackageAccessor.Current.VSOptionsPage.InheritanceOnProperties && _propertiesNeedingContractLookup.Count > 0) { //Recursively look up the needed contract information - VSServiceProvider.Current.Logger.WriteToLog("Attempting to lookup contracts for " + _propertiesNeedingContractLookup.Count + " properties."); - VSServiceProvider.Current.QueueWorkItem(() => RecursivelyLookupContractsForProperties(this), () => _textViewTracker.TextView.HasAggregateFocus); + ContractsPackageAccessor.Current.Logger.WriteToLog("Attempting to lookup contracts for " + _propertiesNeedingContractLookup.Count + " properties."); + ContractsPackageAccessor.Current.QueueWorkItem(() => RecursivelyLookupContractsForProperties(this), () => _textViewTracker.TextView.HasAggregateFocus); } } @@ -144,9 +144,9 @@ static void RevaluateMethodInheritanceAdornments(InheritanceTracker @this) { //Check if model is ready var parseTree = @this._textViewTracker.LatestSourceFile == null ? null : @this._textViewTracker.LatestSourceFile.GetParseTree(); - if (parseTree == null || !VSServiceProvider.IsModelReady(parseTree)) { + if (parseTree == null || !parseTree.IsModelReady()) { @this._textViewTracker.IsLatestSourceFileStale = true; - Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); return; } @@ -157,41 +157,41 @@ static void RevaluateMethodInheritanceAdornments(InheritanceTracker @this) { //Calculate which methods are new var newKeys = new List(methods.Keys.Where((k) => !@this._methodKeys.Contains(k))); - VSServiceProvider.Current.Logger.WriteToLog(String.Format("Found {0} new methods.", newKeys.Count)); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Found {0} new methods.", newKeys.Count)); //Update our method keys @this._methodKeys.Clear(); @this._methodKeys.AddAll(methods.Keys); - VSServiceProvider.Current.QueueWorkItem(() => { + ContractsPackageAccessor.Current.QueueWorkItem(() => { if (@this._textViewTracker.TextView.IsClosed) return; var adornmentKeys = new List(@this._adornmentManager.Adornments.Keys); foreach (var key in adornmentKeys) { var keyAsString = key as string; if (keyAsString == null) { - VSServiceProvider.Current.Logger.WriteToLog("Unexpected: A key in the AdornmentManager wasn't a string! key: " + key.ToString()); + ContractsPackageAccessor.Current.Logger.WriteToLog("Unexpected: A key in the AdornmentManager wasn't a string! key: " + key.ToString()); continue; } if (!@this._methodKeys.Contains(key) && keyAsString.EndsWith(MethodCollector.MethodTagSuffix)) { @this._adornmentManager.RemoveAdornment(key); - VSServiceProvider.Current.Logger.WriteToLog("Removing obsolete method adornment with tag: " + keyAsString); + ContractsPackageAccessor.Current.Logger.WriteToLog("Removing obsolete method adornment with tag: " + keyAsString); } } }, () => @this._textViewTracker.TextView.IsClosed || @this._textViewTracker.TextView.HasAggregateFocus); //Create placeholder adornments for our new methods and queue them for contract lookup - VSServiceProvider.Current.QueueWorkItem(() => { + ContractsPackageAccessor.Current.QueueWorkItem(() => { foreach (var key in newKeys) { MethodDeclarationNode method; if (methods.TryGetValue(key, out method)) { - VSServiceProvider.Current.Logger.WriteToLog("Creating placeholder adornment and enqueueing for future contract lookup for: " + key.ToString()); + ContractsPackageAccessor.Current.Logger.WriteToLog("Creating placeholder adornment and enqueueing for future contract lookup for: " + key.ToString()); #region Create placeholder adornment //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text var snapshotSpan = new SnapshotSpan(method.GetSpan().Convert(workingSnapshot).Start, 1); var trackingSpan = workingSnapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); - var ops = AdornmentOptionsHelper.GetAdornmentOptions(VSServiceProvider.Current.VSOptionsPage); - @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, VSServiceProvider.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), key); + var ops = AdornmentOptionsHelper.GetAdornmentOptions(ContractsPackageAccessor.Current.VSOptionsPage); + @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, ContractsPackageAccessor.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), key); #endregion @this._methodsNeedingContractLookup.Enqueue(new KeyValuePair(key, method)); } @@ -199,10 +199,10 @@ static void RevaluateMethodInheritanceAdornments(InheritanceTracker @this) { }); //Most likely we've changed something (and this is a pretty cheap call), so let's ask for a refresh - Utilities.Delay(() => VSServiceProvider.Current.QueueWorkItem(@this._adornmentManager.QueueRefreshLineTransformer), DelayAfterMembersRevalutation); + Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(@this._adornmentManager.QueueRefreshLineTransformer), DelayAfterMembersRevalutation); //Ask for the new VS model so we can look up contracts - Utilities.Delay(() => VSServiceProvider.Current.QueueWorkItem(VSServiceProvider.Current.AskForNewVSModel), DelayAfterMembersRevalutation); + Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(ContractsPackageAccessor.Current.AskForNewVSModel), DelayAfterMembersRevalutation); } static void RevaluatePropertyInheritanceAdornments(InheritanceTracker @this) { Contract.Requires(@this != null); @@ -211,9 +211,9 @@ static void RevaluatePropertyInheritanceAdornments(InheritanceTracker @this) { //Check if model is ready var parseTree = @this._textViewTracker.LatestSourceFile == null ? null : @this._textViewTracker.LatestSourceFile.GetParseTree(); - if (parseTree == null || !VSServiceProvider.IsModelReady(parseTree)) { + if (parseTree == null || !parseTree.IsModelReady()) { @this._textViewTracker.IsLatestSourceFileStale = true; - Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); return; } @@ -234,31 +234,31 @@ static void RevaluatePropertyInheritanceAdornments(InheritanceTracker @this) { newTuples.Add(tuple); } - VSServiceProvider.Current.Logger.WriteToLog(String.Format("Found {0} new properties.", newTuples.Count)); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Found {0} new properties.", newTuples.Count)); //Update our property keys @this._propertyKeys.Clear(); @this._propertyKeys.AddAll(keys); - VSServiceProvider.Current.QueueWorkItem(() => { + ContractsPackageAccessor.Current.QueueWorkItem(() => { if (@this._textViewTracker.TextView.IsClosed) return; var adornmentKeys = new List(@this._adornmentManager.Adornments.Keys); foreach (var key in adornmentKeys) { var keyAsString = key as string; if (keyAsString == null) { - VSServiceProvider.Current.Logger.WriteToLog("Unexpected: A key in the AdornmentManager wasn't a string! key: " + key.ToString()); + ContractsPackageAccessor.Current.Logger.WriteToLog("Unexpected: A key in the AdornmentManager wasn't a string! key: " + key.ToString()); continue; } if (!@this._propertyKeys.Contains(key) && keyAsString.EndsWith(PropertyCollector.PropertyTagSuffix)) { @this._adornmentManager.RemoveAdornment(key); - VSServiceProvider.Current.Logger.WriteToLog("Removing obsolete property adornment with tag: " + keyAsString); + ContractsPackageAccessor.Current.Logger.WriteToLog("Removing obsolete property adornment with tag: " + keyAsString); } } }, () => @this._textViewTracker.TextView.IsClosed || @this._textViewTracker.TextView.HasAggregateFocus); //Create placeholder adornments for our new properties and queue them for contract lookup - VSServiceProvider.Current.QueueWorkItem(() => { + ContractsPackageAccessor.Current.QueueWorkItem(() => { foreach (var tuple in newTuples) { PropertyDeclarationNode property; if (properties.TryGetValue(tuple, out property)) { @@ -266,31 +266,31 @@ static void RevaluatePropertyInheritanceAdornments(InheritanceTracker @this) { property.GetAccessorDeclaration.GetSpan().Start.Line == property.SetAccessorDeclaration.GetSpan().Start.Line) { // set and get on same line, don't add adornment - VSServiceProvider.Current.Logger.WriteToLog("Skipping adornments for " + property.GetName(workingSnapshot) + " because get and set are on same line"); + ContractsPackageAccessor.Current.Logger.WriteToLog("Skipping adornments for " + property.GetName(workingSnapshot) + " because get and set are on same line"); } else { - VSServiceProvider.Current.Logger.WriteToLog("Creating placeholder adornment and enqueueing for future contract lookup for: " + property.GetName(workingSnapshot)); + ContractsPackageAccessor.Current.Logger.WriteToLog("Creating placeholder adornment and enqueueing for future contract lookup for: " + property.GetName(workingSnapshot)); if (tuple.Item1 != null) { #region Create getter placeholder adornment - VSServiceProvider.Current.Logger.WriteToLog(String.Format("\t(Creating getter placeholder with tag {0})", tuple.Item1)); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("\t(Creating getter placeholder with tag {0})", tuple.Item1)); //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text var snapshotSpan = new SnapshotSpan(property.GetAccessorDeclaration.GetSpan().Convert(workingSnapshot).Start, 1); var trackingSpan = workingSnapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); - var ops = AdornmentOptionsHelper.GetAdornmentOptions(VSServiceProvider.Current.VSOptionsPage); - @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, VSServiceProvider.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), tuple.Item1); + var ops = AdornmentOptionsHelper.GetAdornmentOptions(ContractsPackageAccessor.Current.VSOptionsPage); + @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, ContractsPackageAccessor.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), tuple.Item1); #endregion } if (tuple.Item2 != null) { #region Create setter placeholder adornment - VSServiceProvider.Current.Logger.WriteToLog(String.Format("\t(Creating setter placeholder with tag {0})", tuple.Item2)); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("\t(Creating setter placeholder with tag {0})", tuple.Item2)); //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text var snapshotSpan = new SnapshotSpan(property.SetAccessorDeclaration.GetSpan().Convert(workingSnapshot).Start, 1); var trackingSpan = workingSnapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); - var ops = AdornmentOptionsHelper.GetAdornmentOptions(VSServiceProvider.Current.VSOptionsPage); - @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, VSServiceProvider.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), tuple.Item2); + var ops = AdornmentOptionsHelper.GetAdornmentOptions(ContractsPackageAccessor.Current.VSOptionsPage); + @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, ContractsPackageAccessor.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), tuple.Item2); #endregion } @this._propertiesNeedingContractLookup.Enqueue(new KeyValuePair, PropertyDeclarationNode>(tuple, property)); @@ -300,10 +300,10 @@ static void RevaluatePropertyInheritanceAdornments(InheritanceTracker @this) { }); //Most likely we've changed something (and this is a pretty cheap call), so let's ask for a refresh - Utilities.Delay(() => VSServiceProvider.Current.QueueWorkItem(@this._adornmentManager.QueueRefreshLineTransformer, () => @this._textViewTracker.TextView.HasAggregateFocus), DelayAfterMembersRevalutation); + Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(@this._adornmentManager.QueueRefreshLineTransformer, () => @this._textViewTracker.TextView.HasAggregateFocus), DelayAfterMembersRevalutation); //Ask for the new VS model so we can look up contracts - Utilities.Delay(() => VSServiceProvider.Current.QueueWorkItem(VSServiceProvider.Current.AskForNewVSModel, () => @this._textViewTracker.TextView.HasAggregateFocus), DelayAfterMembersRevalutation); + Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(ContractsPackageAccessor.Current.AskForNewVSModel, () => @this._textViewTracker.TextView.HasAggregateFocus), DelayAfterMembersRevalutation); } static void RecursivelyLookupContractsForMethods(InheritanceTracker @this) { @@ -317,12 +317,12 @@ static void RecursivelyLookupContractsForMethods(InheritanceTracker @this) { var tag = methodPair.Key; #endregion try { - VSServiceProvider.Current.Logger.WriteToLog(String.Format("Attempting to lookup contracts for '{0}'", tag.ToString())); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Attempting to lookup contracts for '{0}'", tag.ToString())); var comp = @this._textViewTracker.LatestCompilation; if (comp == null) { - VSServiceProvider.Current.Logger.WriteToLog("No LatestCompilation, waiting for a new semantic model."); + ContractsPackageAccessor.Current.Logger.WriteToLog("No LatestCompilation, waiting for a new semantic model."); @this._textViewTracker.IsLatestCompilationStale = true; - Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); @this.semanticModelsFetchedCounter++; goto RequeueAndAbort; } @@ -331,13 +331,13 @@ static void RecursivelyLookupContractsForMethods(InheritanceTracker @this) { semanticMethod = comp.GetMemberForMethodDeclaration(method); if (semanticMethod == null) { if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 3) { - VSServiceProvider.Current.Logger.WriteToLog("Failed to get semantic method from syntactic method, waiting for a new semantic model."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic method from syntactic method, waiting for a new semantic model."); @this._textViewTracker.IsLatestCompilationStale = true; - Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); @this.semanticModelsFetchedCounter++; goto RequeueAndAbort; } else { - VSServiceProvider.Current.Logger.WriteToLog("Failed to get semantic method from syntactic method. Too many semantic models have already been fetched, skipping this method..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic method from syntactic method. Too many semantic models have already been fetched, skipping this method..."); goto Continue; } } @@ -358,17 +358,17 @@ static void RecursivelyLookupContractsForMethods(InheritanceTracker @this) { #endregion #region Try get method contracts and update adornment IMethodContract contracts = null; - if (@this._textViewTracker.ProjectTracker.ContractsProvider.TryGetMethodContract(inheritedFromMethod, out contracts)) { + if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(inheritedFromMethod, out contracts)) { var possibleAdornment = @this._adornmentManager.GetAdornment(tag); if (possibleAdornment != null) { var adornment = possibleAdornment as ContractAdornment; if (adornment != null) { adornment.SetContracts(contracts, toolTip); } else { - VSServiceProvider.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping method..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping method..."); } } else { - VSServiceProvider.Current.Logger.WriteToLog("Placeholder adornment not found, skipping method..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment not found, skipping method..."); } } #endregion @@ -376,39 +376,39 @@ static void RecursivelyLookupContractsForMethods(InheritanceTracker @this) { #region Exception handeling catch (IllFormedSemanticModelException e) { if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 2) { - VSServiceProvider.Current.Logger.WriteToLog("Error: An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Asking for a new semantic model..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Error: An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Asking for a new semantic model..."); @this._textViewTracker.IsLatestCompilationStale = true; - VSServiceProvider.Current.AskForNewVSModel(); + ContractsPackageAccessor.Current.AskForNewVSModel(); @this.semanticModelsFetchedCounter++; goto RequeueAndAbort; } else { - VSServiceProvider.Current.Logger.WriteToLog("An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Too many semantic models have been fetched, skipping this method..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Too many semantic models have been fetched, skipping this method..."); goto Continue; } } catch (InvalidOperationException e) { - if (e.Message.Contains(VSServiceProvider.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) { + if (e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) { if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) { - VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); @this._textViewTracker.IsLatestCompilationStale = true; - VSServiceProvider.Current.AskForNewVSModel(); + ContractsPackageAccessor.Current.AskForNewVSModel(); @this.semanticModelsFetchedCounter++; goto RequeueAndAbort; } else { - VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this method..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this method..."); goto Continue; } } else throw e; } catch (COMException e) { - if (e.Message.Contains(VSServiceProvider.COMExceptionMessage_BindingFailed)) { + if (e.Message.Contains(ContractsPackageAccessor.COMExceptionMessage_BindingFailed)) { if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) { - VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); @this._textViewTracker.IsLatestCompilationStale = true; - VSServiceProvider.Current.AskForNewVSModel(); + ContractsPackageAccessor.Current.AskForNewVSModel(); @this.semanticModelsFetchedCounter++; goto RequeueAndAbort; } else { - VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this method..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this method..."); goto Continue; } } else @@ -416,7 +416,7 @@ static void RecursivelyLookupContractsForMethods(InheritanceTracker @this) { } #endregion Continue: - VSServiceProvider.Current.QueueWorkItem(() => RecursivelyLookupContractsForMethods(@this)); + ContractsPackageAccessor.Current.QueueWorkItem(() => RecursivelyLookupContractsForMethods(@this)); return; RequeueAndAbort: @this._methodsNeedingContractLookup.Enqueue(methodPair); @@ -435,9 +435,9 @@ static void RecursivelyLookupContractsForProperties(InheritanceTracker @this) { try { var comp = @this._textViewTracker.LatestCompilation; if (comp == null) { - VSServiceProvider.Current.Logger.WriteToLog("No LatestCompilation, waiting for a new semantic model."); + ContractsPackageAccessor.Current.Logger.WriteToLog("No LatestCompilation, waiting for a new semantic model."); @this._textViewTracker.IsLatestCompilationStale = true; - Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); @this.semanticModelsFetchedCounter++; goto RequeueAndAbort; } @@ -446,13 +446,13 @@ static void RecursivelyLookupContractsForProperties(InheritanceTracker @this) { semanticProperty = comp.GetMemberForPropertyDeclaration(property); if (semanticProperty == null) { if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 3) { - VSServiceProvider.Current.Logger.WriteToLog("Failed to get semantic property from syntactic property, waiting for a new semantic model."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic property from syntactic property, waiting for a new semantic model."); @this._textViewTracker.IsLatestCompilationStale = true; - Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); @this.semanticModelsFetchedCounter++; goto RequeueAndAbort; } else { - VSServiceProvider.Current.Logger.WriteToLog("Failed to get semantic property from syntactic property. Too many semantic models have already been fetched, skipping this property..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic property from syntactic property. Too many semantic models have already been fetched, skipping this property..."); goto Continue; } } @@ -474,80 +474,80 @@ static void RecursivelyLookupContractsForProperties(InheritanceTracker @this) { #region Try get accessor contracts and update adornment IMethodReference getterReference = null; IMethodReference setterReference = null; - if (@this._textViewTracker.ProjectTracker.ContractsProvider.TryGetPropertyAccessorReferences(inheritedFromProperty, out getterReference, out setterReference)) { + if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetPropertyAccessorReferences(inheritedFromProperty, out getterReference, out setterReference)) { if (tagTuple.Item1 != null && getterReference != null) { IMethodContract getterContracts; - if (@this._textViewTracker.ProjectTracker.ContractsProvider.TryGetMethodContract(getterReference, out getterContracts)) { + if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(getterReference, out getterContracts)) { var possibleAdornment = @this._adornmentManager.GetAdornment(tagTuple.Item1); if (possibleAdornment != null) { var adornment = possibleAdornment as ContractAdornment; if (adornment != null) { adornment.SetContracts(getterContracts, toolTip); } else { - VSServiceProvider.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping getter..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping getter..."); } } else { - VSServiceProvider.Current.Logger.WriteToLog("Placeholder adornment not found, skipping getter..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment not found, skipping getter..."); } } } if (tagTuple.Item2 != null && setterReference != null) { IMethodContract setterContracts; - if (@this._textViewTracker.ProjectTracker.ContractsProvider.TryGetMethodContract(setterReference, out setterContracts)) { + if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(setterReference, out setterContracts)) { var possibleAdornment = @this._adornmentManager.GetAdornment(tagTuple.Item2); if (possibleAdornment != null) { var adornment = possibleAdornment as ContractAdornment; if (adornment != null) { adornment.SetContracts(setterContracts, toolTip); } else { - VSServiceProvider.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping setter..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping setter..."); } } else { - VSServiceProvider.Current.Logger.WriteToLog("Placeholder adornment not found, skipping setter..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment not found, skipping setter..."); } } } } else { - VSServiceProvider.Current.Logger.WriteToLog("Failed to get CCI reference for: " + inheritedFromProperty.Name.Text); + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get CCI reference for: " + inheritedFromProperty.Name.Text); } #endregion } #region Exception handeling catch (IllFormedSemanticModelException e) { if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 2) { - VSServiceProvider.Current.Logger.WriteToLog("Error: An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Asking for a new semantic model..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Error: An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Asking for a new semantic model..."); @this._textViewTracker.IsLatestCompilationStale = true; - VSServiceProvider.Current.AskForNewVSModel(); + ContractsPackageAccessor.Current.AskForNewVSModel(); @this.semanticModelsFetchedCounter++; goto RequeueAndAbort; } else { - VSServiceProvider.Current.Logger.WriteToLog("An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Too many semantic models have been fetched, skipping this property..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Too many semantic models have been fetched, skipping this property..."); goto Continue; } } catch (InvalidOperationException e) { - if (e.Message.Contains(VSServiceProvider.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) { + if (e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) { if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) { - VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); @this._textViewTracker.IsLatestCompilationStale = true; - VSServiceProvider.Current.AskForNewVSModel(); + ContractsPackageAccessor.Current.AskForNewVSModel(); @this.semanticModelsFetchedCounter++; goto RequeueAndAbort; } else { - VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this property..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this property..."); goto Continue; } } else throw e; } catch (COMException e) { - if (e.Message.Contains(VSServiceProvider.COMExceptionMessage_BindingFailed)) { + if (e.Message.Contains(ContractsPackageAccessor.COMExceptionMessage_BindingFailed)) { if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) { - VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); @this._textViewTracker.IsLatestCompilationStale = true; - VSServiceProvider.Current.AskForNewVSModel(); + ContractsPackageAccessor.Current.AskForNewVSModel(); @this.semanticModelsFetchedCounter++; goto RequeueAndAbort; } else { - VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this property..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this property..."); goto Continue; } } else @@ -555,7 +555,7 @@ static void RecursivelyLookupContractsForProperties(InheritanceTracker @this) { } #endregion Continue: - VSServiceProvider.Current.QueueWorkItem(() => RecursivelyLookupContractsForProperties(@this)); + ContractsPackageAccessor.Current.QueueWorkItem(() => RecursivelyLookupContractsForProperties(@this)); return; RequeueAndAbort: @this._propertiesNeedingContractLookup.Enqueue(propertyPair); @@ -572,7 +572,7 @@ static bool TryGetIheritedFromMember(CSharpMember semanticMember, TypeDeclaratio inheritedFromMember = null; #region If member is from struct, ignore it if (semanticMember.ContainingType.IsValueType || semanticMember.ContainingType.IsStruct) { - VSServiceProvider.Current.Logger.WriteToLog("Member is struct or value type, skipping member..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Member is struct or value type, skipping member..."); return false; } #endregion @@ -594,14 +594,14 @@ static bool TryGetIheritedFromMember(CSharpMember semanticMember, TypeDeclaratio } } if (ignoreIt) { - VSServiceProvider.Current.Logger.WriteToLog("Member has 'ContractClassForAttribute', skipping member..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Member has 'ContractClassForAttribute', skipping member..."); return false; } #endregion // If member is override, get base member if (semanticMember.IsOverride) { if (!CSharpToCCIHelper.TryGetBaseMember(semanticMember, out inheritedFromMember)) { - VSServiceProvider.Current.Logger.WriteToLog("Member is an override but we can't get its base member, skipping member..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Member is an override but we can't get its base member, skipping member..."); return false; //If we can't get the base member, we don't want to keep going with this member. } } @@ -614,7 +614,7 @@ static bool TryGetIheritedFromMember(CSharpMember semanticMember, TypeDeclaratio { if (!CSharpToCCIHelper.TryGetInterfaceMember(semanticMember, out inheritedFromMember)) { - VSServiceProvider.Current.Logger.WriteToLog("Member isn't override, abstract, in an interface or an interface member, skipping member..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Member isn't override, abstract, in an interface or an interface member, skipping member..."); return false; //If we can't get the interface member, we don't want to keep going with this member. } } diff --git a/Microsoft.Research/ContractAdornments/Sources/Inheritance/MethodCollector.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Inheritance/MethodCollector.cs similarity index 94% rename from Microsoft.Research/ContractAdornments/Sources/Inheritance/MethodCollector.cs rename to Microsoft.Research/ContractAdornments/CSharp.Roslyn/Inheritance/MethodCollector.cs index 7aa748e1..5acd8e4b 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Inheritance/MethodCollector.cs +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Inheritance/MethodCollector.cs @@ -50,14 +50,14 @@ public override void VisitMethodDeclarationNode(MethodDeclarationNode node) { //We can't get a proper tag from this (likely ill-formed) method, so we'll skip it for now. var name = node.GetName(_snapshot); - VSServiceProvider.Current.Logger.WriteToLog("Can't form a proper tag (likely ill-formed), ignoring member '" + name == null ? "" : name + "' for now..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Can't form a proper tag (likely ill-formed), ignoring member '" + name == null ? "" : name + "' for now..."); return; } if (_methods.ContainsKey(key)) { //For some reason, we have two methods with the same signature. There is //nothing we can do in this case so we just throw out the second method. - VSServiceProvider.Current.Logger.WriteToLog("Two methods where found to have the exact same signature, ignoring second method for now..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Two methods where found to have the exact same signature, ignoring second method for now..."); return; } _methods.Add(key, node); diff --git a/Microsoft.Research/ContractAdornments/Sources/Inheritance/PropertyCollector.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Inheritance/PropertyCollector.cs similarity index 95% rename from Microsoft.Research/ContractAdornments/Sources/Inheritance/PropertyCollector.cs rename to Microsoft.Research/ContractAdornments/CSharp.Roslyn/Inheritance/PropertyCollector.cs index 9c8f93b2..417bea1d 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Inheritance/PropertyCollector.cs +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Inheritance/PropertyCollector.cs @@ -47,13 +47,13 @@ public override void VisitPropertyDeclarationNode(PropertyDeclarationNode node) if (keys == null) { //We can't get a proper tag from this (likely ill-formed) property, so we'll skip it for now. var name = node.GetName(_snapshot); - VSServiceProvider.Current.Logger.WriteToLog("Can't form a proper tag (likely ill-formed), ignoring member '" + name == null ? "" : name + "' for now..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Can't form a proper tag (likely ill-formed), ignoring member '" + name == null ? "" : name + "' for now..."); return; } if (_properties.ContainsKey(keys)) { //For some reason, we have two properties with the same signature. There is //nothing we can do in this case so we just throw out the second property. - VSServiceProvider.Current.Logger.WriteToLog("Two properties where found to have the exact same signature, ignoring second property for now..."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Two properties where found to have the exact same signature, ignoring second property for now..."); return; } _properties.Add(keys, node); diff --git a/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Intellisense/IntellisenseContractsHelper.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Intellisense/IntellisenseContractsHelper.cs new file mode 100644 index 00000000..6c12ff60 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Intellisense/IntellisenseContractsHelper.cs @@ -0,0 +1,395 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Diagnostics.Contracts; +using System.Linq; +using System.Text; +using Microsoft.Cci; +using Microsoft.Cci.Contracts; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Text; +using UtilitiesNamespace; + +namespace ContractAdornments { + public static class IntellisenseContractsHelper { + + public static ISymbol GetSemanticMember(this SyntaxNode parseTreeNode, Workspace comp, Document sourceFile) { + Contract.Requires(parseTreeNode != null); + Contract.Requires(comp != null); + Contract.Requires(sourceFile != null); + Contract.Ensures(Contract.Result() == null || + Contract.Result().Kind == SymbolKind.Method || + Contract.Result().Kind == SymbolKind.Property); + + // The CSharp model can throw internal exceptions at unexpected moments, so we filter them here: + try + { + SemanticModel semanticModel = ThreadHelper.JoinableTaskFactory.Run(() => sourceFile.GetSemanticModelAsync()); + + ISymbol semanticMember = semanticModel.GetDeclaredSymbol(parseTreeNode); + if (semanticMember != null) + goto Success; + + //Can we get our expression tree? + semanticMember = semanticModel.GetSymbolInfo(parseTreeNode).Symbol; + if (semanticMember == null) + return null; + + Success: + //Is our semanticMember a method? + if (semanticMember == null || !(semanticMember.Kind == SymbolKind.Method || semanticMember.Kind == SymbolKind.Property)) + return null; + + //Unistantiate + semanticMember = semanticMember.Uninstantiate(); + + return semanticMember; + } + catch (ArgumentException) + { + return null; + } + } + public static SyntaxNode GetAnyCallNodeAboveTriggerPoint(ITrackingPoint triggerPoint, ITextSnapshot snapshot, SyntaxTree parseTree) { + Contract.Requires(snapshot != null); + Contract.Requires(parseTree != null); + Contract.Requires(triggerPoint != null); + + SyntaxNode syntaxRoot; + if (!parseTree.TryGetRoot(out syntaxRoot)) + return null; + + var leafNode = syntaxRoot.FindToken(triggerPoint.GetPosition(snapshot), false); + if (leafNode.IsKind(SyntaxKind.None)) + return null; + + //Is anyone in our ancestry a call node? + var nodeInQuestion = leafNode.Parent; + SyntaxNode ptn = null; + + while (nodeInQuestion != null) { + //Is the node in question a node call? + var asCall = nodeInQuestion as InvocationExpressionSyntax; + if (asCall != null) { + ptn = asCall; + break; + } + + var asCtorCall = nodeInQuestion as ObjectCreationExpressionSyntax; + if (asCtorCall != null) { + ptn = asCtorCall; + break; + } + + //Climb higher up our ancestry for the next iteration + nodeInQuestion = nodeInQuestion.Parent; + } + + //Did we successfully find a call node? + return ptn; + } + public static SyntaxNode GetTargetAtTriggerPoint(ITrackingPoint triggerPoint, ITextSnapshot snapshot, SyntaxTree parseTree) + { + Contract.Requires(snapshot != null); + Contract.Requires(parseTree != null); + Contract.Requires(triggerPoint != null); + + SyntaxNode syntaxRoot; + if (!parseTree.TryGetRoot(out syntaxRoot)) + return null; + + var leafToken = syntaxRoot.FindToken(triggerPoint.GetPosition(snapshot), false); + if (leafToken.IsKind(SyntaxKind.None)) + return null; + + var leafNode = leafToken.Parent; + + var asPropDecl = leafNode as PropertyDeclarationSyntax; + if (asPropDecl != null) + { + return asPropDecl; + } + + //Is our leaf node a name? + var asName = leafNode as IdentifierNameSyntax; + if (asName == null) + return null; + + //Is anyone in our ancestry a call node? + var nodeInQuestion = leafNode; + var lastNonBinaryOperatorNode = leafNode; + var lastNode = leafNode; + while (nodeInQuestion != null) { + + //Is the node in question a node call? + var asCall = nodeInQuestion as InvocationExpressionSyntax; + if (asCall != null) { + + //Make sure we aren't on the right side of the call + MemberAccessExpressionSyntax memberAccessExpression = asCall.Expression as MemberAccessExpressionSyntax; + if (memberAccessExpression == null || memberAccessExpression.Name == leafNode) + return null; + + return asCall; + } + + var asProp = nodeInQuestion as MemberAccessExpressionSyntax; + if (asProp != null) + { + //Make sure we aren't on the left side of the dot + if (asProp.Name == lastNode && asProp.Name is IdentifierNameSyntax) + { + return asProp; + } + } + + var asCtorCall = nodeInQuestion as ObjectCreationExpressionSyntax; + if (asCtorCall != null) + { + return asCtorCall; + } + + var declNode = nodeInQuestion as MemberDeclarationSyntax; + if (declNode != null) + { + if (lastNode == leafNode) { return declNode; } + return null; + } + +#warning What exactly is this doing? +#if false + NamedAssignmentNode na = nodeInQuestion as NamedAssignmentNode; + if (na != null) + { + if (na.Identifier == asName) + { + return na; + } + } +#endif + + //Is our parent a binary operator? + var asBinaryOperator = nodeInQuestion as BinaryExpressionSyntax; + if (asBinaryOperator != null) { + + //Make sure we are always on the rightmost of any binary operator + if (asBinaryOperator.Right != lastNonBinaryOperatorNode) + return null; + + } else + lastNonBinaryOperatorNode = nodeInQuestion; + + //Climb higher up our ancestry for the next iteration + lastNode = nodeInQuestion; + nodeInQuestion = nodeInQuestion.Parent; + } + + //Did we successfully find a call node? + if (nodeInQuestion == null) + return null; + if (nodeInQuestion.Kind() != SyntaxKind.InvocationExpression) + return null; + var callNode = nodeInQuestion as InvocationExpressionSyntax; + + return callNode; + } + + public static string FormatContracts(IMethodContract methodContracts) { + + //Did we get proper contracts? + if (methodContracts == null) { + + //Return a message saying we failed to get contracts + return "(Failed to properly get contracts)"; + } + + //Do we have any contracts? + if (IsEmptyContract(methodContracts)) + { + //Return a message saying we don't have any contracts + return null; + } + + //Initialize our string builder + var sb = new StringBuilder(); + + //Append the 'Contracts' header + sb.Append("Contracts: "); + sb.Append('\n'); + + //Append purity + if (methodContracts.IsPure) { + sb.Append(" "); + sb.Append("[Pure]"); + sb.Append('\n'); + } + + FormatPrePostThrows(methodContracts, sb); + + //Can we get our result from the string builder? + var result = sb.ToString(); + + //Trim the new lines from the end + result = result.TrimEnd('\n'); + + result = SmartFormat(result); + + //Return our result + return result; + } + + private static bool IsEmptyContract(IMethodContract methodContracts) + { + Contract.Ensures(Contract.Result() || methodContracts != null); + + return methodContracts == null + || (methodContracts == ContractDummy.MethodContract) + || (!methodContracts.IsPure + && methodContracts.Preconditions.Count() < 1 + && methodContracts.Postconditions.Count() < 1 + && methodContracts.ThrownExceptions.Count() < 1); + } + + static string IndentString = Environment.NewLine + " "; + + private static void FormatPrePostThrows(IMethodContract methodContracts, StringBuilder sb) + { + Contract.Requires(methodContracts != null); + Contract.Requires(sb != null); + + if (methodContracts.Postconditions != null) + { + //Append our preconditions + foreach (var pre in methodContracts.Preconditions) + { + if (pre == null) continue; + if (pre.OriginalSource == null) continue; + sb.Append(" "); + sb.Append("requires "); + sb.Append(pre.OriginalSource.Replace(Environment.NewLine, IndentString)); + sb.Append('\n'); + } + } + + if (methodContracts.Postconditions != null) + { + //Append our postconditions + foreach (var post in methodContracts.Postconditions) + { + if (post == null) continue; + if (post.OriginalSource == null) continue; + sb.Append(" "); + sb.Append("ensures "); + sb.Append(post.OriginalSource.Replace(Environment.NewLine, IndentString)); + sb.Append('\n'); + } + } + + if (methodContracts.ThrownExceptions != null) + { + //Append our on throw conditions + foreach (var onThrow in methodContracts.ThrownExceptions) + { + if (onThrow == null) continue; + if (onThrow.ExceptionType == null) continue; + if (onThrow.Postcondition == null) continue; + if (onThrow.Postcondition.OriginalSource == null) continue; + + sb.Append(" "); + sb.Append("ensures on throw of "); + var onThrowType = TypeHelper.GetTypeName(onThrow.ExceptionType, NameFormattingOptions.OmitContainingType | NameFormattingOptions.OmitContainingNamespace); + sb.Append(onThrowType); + sb.Append(" that "); + sb.Append(onThrow.Postcondition.OriginalSource.Replace(Environment.NewLine, IndentString)); + sb.Append('\n'); + } + } + } + + private static string SmartFormat(string result) + { + if (string.IsNullOrEmpty(result)) return result; + if (ContractsPackageAccessor.Current.VSOptionsPage != null && ContractsPackageAccessor.Current.VSOptionsPage.SmartFormatting) + { + var startTime = DateTime.Now; + + var trySmartReplace = result; + + try + { + //Simplify how contracts look + trySmartReplace = trySmartReplace.SmartReplace("Contract.OldValue<{0}>({1})", "old({1})"); + trySmartReplace = trySmartReplace.SmartReplace("Contract.OldValue({0})", "old({0})"); + trySmartReplace = trySmartReplace.SmartReplace("Contract.Result<{0}>()", "result"); + trySmartReplace = trySmartReplace.SmartReplace("Contract.ValueAtReturn<{0}>({1})", "out({1})"); + trySmartReplace = trySmartReplace.SmartReplace("Contract.ValueAtReturn({0})", "out({0})"); + trySmartReplace = trySmartReplace.SmartReplace("Contract.ForAll<{0}>({1})", "forall({1})"); + trySmartReplace = trySmartReplace.SmartReplace("Contract.ForAll({0})", "forall({0})"); + } + catch (Exception) + { + trySmartReplace = null; + ContractsPackageAccessor.Current.Logger.WriteToLog("Error: Smart formatting failed!"); + ContractsPackageAccessor.Current.Logger.WriteToLog(result); + } + + if (trySmartReplace != null) + result = trySmartReplace; + + var elapsedTime = DateTime.Now - startTime; + ContractsPackageAccessor.Current.Logger.WriteToLog("\t(Smart formatting took " + elapsedTime.Milliseconds + "ms)"); + } + return result; + } + + internal static string FormatPropertyContracts(IMethodContract getter, IMethodContract setter) + { + //Initialize our string builder + var sb = new StringBuilder(); + + //Append the 'Contracts' header + //sb.Append("Contracts: "); + //sb.Append('\n'); + + if (!IsEmptyContract(getter)) + { + sb.Append("get "); + sb.Append('\n'); + FormatPrePostThrows(getter, sb); + } + if (!IsEmptyContract(setter)) + { + sb.Append("set "); + sb.Append('\n'); + FormatPrePostThrows(setter, sb); + } + //Can we get our result from the string builder? + var result = sb.ToString(); + + if (result == "") return null; + + //Trim the new lines from the end + result = result.TrimEnd('\n'); + + result = SmartFormat(result); + + //Return our result + return result; + } + } +} diff --git a/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Intellisense/QuickInfo.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Intellisense/QuickInfo.cs new file mode 100644 index 00000000..72560bd0 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Intellisense/QuickInfo.cs @@ -0,0 +1,182 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using ContractAdornments.Interfaces; +using Microsoft.Cci.Contracts; +using Microsoft.CodeAnalysis; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; + +namespace ContractAdornments { + class QuickInfoSource : IQuickInfoSource { + readonly ITextBuffer _textBuffer; + readonly TextViewTracker _textViewTracker; + + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(_textBuffer != null); + Contract.Invariant(_textViewTracker != null); + } + + public QuickInfoSource(ITextBuffer textBuffer, ITextViewTracker textViewTracker) { + Contract.Requires(textBuffer != null); + Contract.Requires(textViewTracker != null); + + _textBuffer = textBuffer; + _textViewTracker = (TextViewTracker)textViewTracker; + } + + public void AugmentQuickInfoSession(IQuickInfoSession session, IList quickInfoContent, out ITrackingSpan applicableToSpan) { + + if (session == null) + { + applicableToSpan = null; + return; + } + + var span = applicableToSpan = session.ApplicableToSpan; + if (quickInfoContent == null) return; + + //Wrap our method body in a safty net that checks for exceptions + ContractsPackageAccessor.Current.Logger.PublicEntry(() => { + + //Record our start time for preformance considerations + var startTime = DateTime.Now; + + //Is our session valid? + if (session == null) + return; + + //Can we get our trigger point? + var triggerPoint = session.GetTriggerPoint(_textBuffer); + if (triggerPoint == null) + return; + + //Can we get our snapshot? + var workingSnapshot = _textBuffer.CurrentSnapshot; + if (workingSnapshot == null) + return; + + //Can we get our SourceFile? + var sourceFile = _textViewTracker.LatestSourceFile; + if (sourceFile == null) + return; + + //Can we get our ParseTree? + SyntaxTree parseTree; + if (!sourceFile.TryGetSyntaxTree(out parseTree)) + return; + + //Can we get our compilation? + var comp = _textViewTracker.LatestCompilation; + if (comp == null) + return; + + //Is the model ready? + if (!parseTree.IsModelReady() || _textViewTracker.IsLatestCompilationStale || _textViewTracker.IsLatestSourceFileStale) { + + //Ask for a new model + ContractsPackageAccessor.Current.AskForNewVSModel(_textBuffer); + + //Return a message saying we aren't ready yet + ContractsPackageAccessor.Current.Logger.WriteToLog("The VS model is out of date! Aborting contract lookup."); + return;//"(VS isn't ready for possible contract lookup yet. Please try again in a few seconds.)"; + } + + //Proceed cautiously + string formattedContracts; + try { + + //Can we get a call node? + var targetNode = IntellisenseContractsHelper.GetTargetAtTriggerPoint(triggerPoint, workingSnapshot, parseTree); + if (targetNode == null) + return; + + //Can we get our semantic member? + var semanticMember = IntellisenseContractsHelper.GetSemanticMember(targetNode, comp, sourceFile); + if (semanticMember == null) + return; + + //Can we get our contracts? + formattedContracts = GetFormattedContracts(semanticMember); + if (formattedContracts == null) + return; + + if (span == null) + { + span = workingSnapshot.CreateTrackingSpan(triggerPoint.GetPosition(workingSnapshot), 1, SpanTrackingMode.EdgeInclusive); + } + //Give up on our contracts if we get an exception + } catch (IllFormedSemanticModelException) { + return; + } catch (InvalidOperationException e) { + if (!e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) + throw e; + else + { + this._textViewTracker.IsLatestCompilationStale = true; + return; + } + } catch (System.Runtime.InteropServices.COMException e) { + // various reasons for ComExceptions: + // - binding failed + // - project unavailable + if (e.Message.EndsWith("out of date")) + { + this._textViewTracker.IsLatestCompilationStale = true; + } + return; + } + + //Append our formatted contract info + quickInfoContent.Add(formattedContracts); + //Print our elapsed time for preformance considerations + var elapseTime = DateTime.Now - startTime; + ContractsPackageAccessor.Current.Logger.WriteToLog("Time to compute quickinfo: " + elapseTime.Milliseconds + "ms"); + }, "AugmentQuickInfoSession"); + + if (span != null) { applicableToSpan = span; } + } + + private string GetFormattedContracts(ISymbol semanticMember) + { + Contract.Requires(semanticMember != null); + Contract.Requires(semanticMember.Kind == SymbolKind.Method || semanticMember.Kind == SymbolKind.Property); + + if (semanticMember.Kind == SymbolKind.Property) + { + IMethodContract setter, getter; + if (!((ContractsProvider)_textViewTracker.ProjectTracker.ContractsProvider).TryGetPropertyContract(semanticMember, out getter, out setter)) + { + return null; + } + return IntellisenseContractsHelper.FormatPropertyContracts(getter, setter); + } + + //Can we get our contracts? + IMethodContract methodContracts; + if (!((ContractsProvider)_textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(semanticMember, out methodContracts)) + return null; + + //Can we get our formatted contracts? + return IntellisenseContractsHelper.FormatContracts(methodContracts); + } + public void Dispose() { + //TODO: Dispose? + } + } +} \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Intellisense/SignatureHelp.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Intellisense/SignatureHelp.cs new file mode 100644 index 00000000..3123b1ec --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Intellisense/SignatureHelp.cs @@ -0,0 +1,481 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics.Contracts; +using ContractAdornments.Interfaces; +using Microsoft.Cci.Contracts; +using Microsoft.CodeAnalysis; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.TextManager.Interop; + +namespace ContractAdornments { + class SignatureHelpSource : ISignatureHelpSource { + bool _disposed = false; + readonly ITextBuffer _textBuffer; + readonly TextViewTracker _textViewTracker; + + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(_textBuffer != null); + Contract.Invariant(_textViewTracker != null); + } + + public SignatureHelpSource(ITextBuffer textBuffer, ITextViewTracker textViewTracker) { + Contract.Requires(textBuffer != null); + Contract.Requires(textViewTracker != null); + + _textBuffer = textBuffer; + _textViewTracker = (TextViewTracker)textViewTracker; + } + + public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList signatures) { + ContractsPackageAccessor.Current.Logger.PublicEntry(() => { + + //Record our start time for preformance considerations + var startTime = DateTime.Now; + + //Do we have signatures? + if (signatures == null || signatures.Count < 1) + return; + + //Do we have a well-formed session? + if (session == null || session.TextView == null || session.TextView.TextBuffer == null) + return; + + //Can we get our trigger point? + var triggerPoint = session.GetTriggerPoint(_textBuffer); + if (triggerPoint == null) + return; + + //Can we get our snapshot? + var workingSnapshot = _textBuffer.CurrentSnapshot; + if (workingSnapshot == null) + return; + + //Can we get our SourceFile? + var sourceFile = _textViewTracker.LatestSourceFile; + if (sourceFile == null) + return; + + //Can we get our ParseTree? + SyntaxTree parseTree; + if (!sourceFile.TryGetSyntaxTree(out parseTree)) + return; + + //Can we get our compilation? + var comp = _textViewTracker.LatestCompilation; + if (comp == null) + return; + + //Is the model ready? + if (!parseTree.IsModelReady() || _textViewTracker.IsLatestCompilationStale || _textViewTracker.IsLatestSourceFileStale) { + + //Ask for a new model + ContractsPackageAccessor.Current.AskForNewVSModel(_textBuffer); + + //Return a message saying we aren't ready yet + ContractsPackageAccessor.Current.Logger.WriteToLog("The VS model is out of date! Aborting contract lookup."); + return;//"(VS isn't ready for possible contract lookup yet. Please try again in a few seconds.)"; + } + + string[] contractContents = null; + + //Proceed cautiously + try + { + + //Can we get a call node? + var callNode = IntellisenseContractsHelper.GetAnyCallNodeAboveTriggerPoint(triggerPoint, workingSnapshot, parseTree); + if (callNode == null || comp == null || sourceFile == null) + return; + + //Can we get our semantic member? + var semanticMember = IntellisenseContractsHelper.GetSemanticMember(callNode, comp, sourceFile); + if (semanticMember == null) + return; + + var declType = semanticMember.ContainingType; + // find all members of the same name (virt/non-virt) + + var overloads = GetSignatureOverloads(declType, signatures, semanticMember); + + contractContents = GetContractsForOverloads(overloads); + + + //Give up on our contracts if we get an exception + } + catch (IllFormedSemanticModelException) + { + return; + } + catch (InvalidOperationException e) + { + if (!e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) + throw e; + else + { + this._textViewTracker.IsLatestCompilationStale = true; + return; + } + } + catch (System.Runtime.InteropServices.COMException) + { + // various reasons for COMException + // - binding failed + // - project unavailable + // - ... + return; + } + + //Enumerate the signatures and append our custom content + for (int i = 0; i < signatures.Count; i++) { + var sig = signatures[i]; + + if (contractContents != null && !String.IsNullOrEmpty(contractContents[i])) + { + signatures[i] = new SignatureWithContracts(sig, contractContents[i]); + } + } + + //Print our elapsed time for preformance considerations + var elapseTime = DateTime.Now - startTime; + ContractsPackageAccessor.Current.Logger.WriteToLog("Time to compute quickinfo: " + elapseTime.Milliseconds + "ms"); + + }, "AugmentSignatureHelpSession"); + } + + private string[] GetContractsForOverloads(ISymbol[] overloads) + { + Contract.Requires(overloads != null); + Contract.Requires(Contract.ForAll(overloads, o => o == null || o.Kind == SymbolKind.Method || o.Kind == SymbolKind.Property)); + + var result = new string[overloads.Length]; + + for (int i = 0; i < overloads.Length; i++) + { + var mem = overloads[i]; + //Can we get our contracts? + if (mem == null) continue; + + if (mem.Kind == SymbolKind.Method) + { + IMethodContract methodContracts; + if (!((ContractsProvider)_textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(mem, out methodContracts)) + continue; + + result[i] = IntellisenseContractsHelper.FormatContracts(methodContracts); + } + else if (mem.Kind == SymbolKind.Property) + { + IMethodContract getter, setter; + + if (!((ContractsProvider)_textViewTracker.ProjectTracker.ContractsProvider).TryGetPropertyContract(mem, out getter, out setter)) + continue; + + result[i] = IntellisenseContractsHelper.FormatPropertyContracts(getter, setter); + } + } + return result; + } + + private ISymbol[] GetSignatureOverloads(ITypeSymbol declType, IList signatures, ISymbol semanticMember) + { + Contract.Requires(signatures != null); + Contract.Requires(declType != null); + Contract.Requires(semanticMember != null); + + if (signatures.Count == 1 || declType.GetMembers().IsDefault) + { + return new[] { semanticMember }; + } + var result = new ISymbol[signatures.Count]; + for (int i = 0; i < declType.GetMembers().Length; i++) + { + var mem = declType.GetMembers()[i]; + if (mem == null || !(mem.Kind == SymbolKind.Method || mem.IsIndexer())) continue; + if (mem.Name != semanticMember.Name) continue; + if (mem.IsStatic != semanticMember.IsStatic) continue; + + FuzzyIdentifySignature(mem, result, signatures); + } + + return result; + } + + private void FuzzyIdentifySignature(ISymbol mem, ISymbol[] result, [Pure] IList signatures) + { + Contract.Requires(signatures != null); + Contract.Requires(result != null); + Contract.Requires(result.Length >= signatures.Count); + Contract.Requires(mem != null); + + for (int i = 0; i < signatures.Count; i++) + { + if (result[i] != null) continue; + var sig = signatures[i]; + if (sig == null) continue; + if (sig.Parameters == null) continue; + if (mem.Parameters().IsDefault) continue; + if (sig.Parameters.Count != mem.Parameters().Length) continue; + + var match = true; + for (int j = 0; j < mem.Parameters().Length; j++) + { + var p = mem.Parameters()[j]; + var s = sig.Parameters[j]; + if (p == null || p.Name == null || s == null || p.Name != s.Name) { match = false; break; } + // need to compare types, but how. Sig doesn't seem to give it to us + } + if (!match) continue; + + result[i] = mem; + break; + } + } + + /// + /// Ideally, we wouldn't have to implement this: the underlying signature help provider would do this. + /// But because we replace the signatures in the session with our own type, the underlying provider + /// tries to downcast them to its internal type. That fails (of course) and then it returns null. So + /// we have to mimic its behavior which is done here by reaching into the session's properties to get + /// the same data as the underlying signature help provider sees. So we ask for the current method + /// that is selected and return our signature for the corresponding method. + /// + /// + /// + public ISignature GetBestMatch(ISignatureHelpSession session) { + return ContractsPackageAccessor.Current.Logger.PublicEntry(() => { + IVsMethodData methodData = null; + IVsMethodTipWindow3 tipWindow; + int hr; + if (session.Properties.TryGetProperty(typeof(IVsMethodTipWindow3), out tipWindow)) { + hr = tipWindow.GetMethodData(out methodData); + if (hr != 0 || methodData == null) { + return null; // failed + } + } else { + return null; // failed + } + int sigIndex = methodData.GetCurMethod(); + + if ((sigIndex >= 0) && (sigIndex < session.Signatures.Count)) { + return (session.Signatures[sigIndex]); + } + return null; + }, "GetBestMatch"); + } + + public void Dispose() { + //Public Entry + if (!_disposed) { + /* Not sure why we do this, this is taken from a walkthrough on MSDN + * found here: http://msdn.microsoft.com/en-us/library/ee334194(v=VS.100).aspx + */ + GC.SuppressFinalize(this); + _disposed = true; + } + } + } + + + class SignatureWithContracts : ISignature + { + readonly ISignature underlying; + readonly string contracts; + + [ContractInvariantMethod] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Required for code contracts.")] + private void ObjectInvariant() + { + Contract.Invariant(this.underlying != null); + Contract.Invariant(!String.IsNullOrEmpty(this.contracts)); + } + + public SignatureWithContracts(ISignature original, string contracts) + { + Contract.Requires(original != null); + Contract.Requires(!String.IsNullOrEmpty(contracts)); + + this.underlying = original; + this.contracts = contracts; + } + + public ITrackingSpan ApplicableToSpan + { + get { return this.underlying.ApplicableToSpan; } + } + + public string Content + { + get { return underlying.Content; } + } + + public IParameter CurrentParameter + { + get { return underlying.CurrentParameter; } + } + + public event EventHandler CurrentParameterChanged + { + add { this.underlying.CurrentParameterChanged += value; } + remove { this.underlying.CurrentParameterChanged -= value; } + } + + public string Documentation + { + get { return this.underlying.Documentation + "\n" + this.contracts; } + } + + public ReadOnlyCollection Parameters + { + get { return this.underlying.Parameters; } + } + + public string PrettyPrintedContent + { + get { return this.underlying.PrettyPrintedContent; } + } + } + +#if false + class ParameterWithNewSignature : IParameter { + public string Documentation { get; private set; } + public Span Locus { get; private set; } + public string Name { get; private set; } + public ISignature Signature { get; private set; } + public Span PrettyPrintedLocus { get; private set; } + + public ParameterWithNewSignature(IParameter original, ISignature newSignature) { + Documentation = original.Documentation; + Locus = original.Locus; + Name = original.Name; + Signature = newSignature; + PrettyPrintedLocus = original.PrettyPrintedLocus; + } + } + class SignatureAppendedWithContracts : ISignature { + readonly ITextBuffer _textBuffer; + + public ITrackingSpan ApplicableToSpan { get { return _applicableToSpan; } } + readonly ITrackingSpan _applicableToSpan; + + public string Content { get { return _content; } } + readonly string _content; + + public IParameter CurrentParameter { + get { return _currentParameter; } + private set { + if (_currentParameter != value) { + if (CurrentParameterChanged != null) + CurrentParameterChanged(this, new CurrentParameterChangedEventArgs(_currentParameter, value)); + _currentParameter = value; + } + } + } + IParameter _currentParameter; + + public event EventHandler CurrentParameterChanged; + + public string Documentation { get { return _documentation; } } + readonly string _documentation; + + public ReadOnlyCollection Parameters { + get { return _parameters; } + internal set { _parameters = value; } + } + ReadOnlyCollection _parameters; + + public string PrettyPrintedContent { get { return _prettyPrintedContent; } } + readonly string _prettyPrintedContent; + + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(_textBuffer != null); + Contract.Invariant(ApplicableToSpan != null); + Contract.Invariant(Parameters != null); + } + + public SignatureAppendedWithContracts(ISignature original, ITextBuffer textBuffer, string contracts) { + Contract.Requires(original != null); + Contract.Requires(textBuffer != null); + Contract.Requires(!String.IsNullOrEmpty(contracts)); + + _textBuffer = textBuffer; + _applicableToSpan = original.ApplicableToSpan; + _content = original.Content; + _currentParameter = original.CurrentParameter; + _documentation = original.Documentation + "\n" + contracts; + _prettyPrintedContent = original.PrettyPrintedContent; + _parameters = original.Parameters; + +#if false + _textBuffer.Changed += OnTextBufferChanged; + var newParameters = new List(); + foreach (var param in original.Parameters) + newParameters.Add(new ParameterWithNewSignature(param, this)); + _parameters = newParameters.AsReadOnly(); + + CalculateCurrentParameter(); +#endif + } + +#if false + void OnTextBufferChanged(object sender, TextContentChangedEventArgs e) { + ContractsPackageAccessor.Current.Logger.PublicEntry(() => { + CalculateCurrentParameter(); + }, "OnTextBufferChanged"); + } + + void CalculateCurrentParameter() { +// Contract.Requires(method != null); + // Contract.Requires(method != null); + + /* Taken from a walkthrough on MSDN found here: + * http://msdn.microsoft.com/en-us/library/ee334194(v=VS.100).aspx + */ + + if (Parameters.Count == 0) { + CurrentParameter = null; + return; + } + + //the number of commas in the string is the index of the current parameter + var sigText = ApplicableToSpan.GetText(_textBuffer.CurrentSnapshot); + + int currentIndex = 0; + int commaCount = 0; + while (currentIndex < sigText.Length) { + int commaIndex = sigText.IndexOf(',', currentIndex); + if (commaIndex == -1) { + break; + } + commaCount++; + currentIndex = commaIndex + 1; + } + + if (commaCount < Parameters.Count) { + CurrentParameter = Parameters[commaCount]; + } else { + //too many commas, so use the last parameter as the current one. + CurrentParameter = Parameters[Parameters.Count - 1]; + } + } +#endif + } +#endif +} diff --git a/Microsoft.Research/ContractAdornments/VS2010/Properties/AssemblyInfo.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Properties/AssemblyInfo.cs similarity index 93% rename from Microsoft.Research/ContractAdornments/VS2010/Properties/AssemblyInfo.cs rename to Microsoft.Research/ContractAdornments/CSharp.Roslyn/Properties/AssemblyInfo.cs index 1b43c17c..8d1a741e 100644 --- a/Microsoft.Research/ContractAdornments/VS2010/Properties/AssemblyInfo.cs +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/Properties/AssemblyInfo.cs @@ -18,11 +18,11 @@ using System.Resources; using System.Runtime.InteropServices; -[assembly: AssemblyTitle("CodeContractsEditorExtensions")] +[assembly: AssemblyTitle("ContractAdornments.CSharp")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] //[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("CodeContractsEditorExtensions")] +[assembly: AssemblyProduct("ContractAdornments.CSharp")] //[assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Microsoft.Research/ContractAdornments/CSharp.Roslyn/TextView/TextViewTracker.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/TextView/TextViewTracker.cs new file mode 100644 index 00000000..7cf03d91 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/TextView/TextViewTracker.cs @@ -0,0 +1,219 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Diagnostics.Contracts; +using System.Timers; +using Adornments; +using ContractAdornments.Interfaces; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; + +namespace ContractAdornments { + internal sealed class TextViewTracker : ITextViewTracker { + public static readonly object TextViewTrackerKey = TextViewTrackerAccessor.TextViewTrackerKey; + public const double DelayOnTextViewOpened = 2000d; + public const double DelayOnTextViewChanged = 5000d; + + public readonly IWpfTextView TextView; + readonly IProjectTracker _projectTracker; + public IProjectTracker ProjectTracker + { + get + { + Contract.Ensures(Contract.Result() != null); + return this._projectTracker; + } + } + public readonly DocumentId FileName; + readonly Timer _textBufferChangedTimer; + public VSTextProperties VSTextProperties; + + public Document LatestSourceFile { get; private set; } + public bool IsLatestSourceFileStale { get; set; } + public event EventHandler LatestSourceFileChanged; + + public Workspace LatestCompilation { get; private set; } + public bool IsLatestCompilationStale { get; set; } + public event EventHandler LatestCompilationChanged; + + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(TextView != null); + Contract.Invariant(_projectTracker != null); + Contract.Invariant(_textBufferChangedTimer != null); + } + + internal TextViewTracker(IWpfTextView textView, IProjectTracker projectTracker, VSTextProperties vsTextProperties) + : base() { + Contract.Requires(textView != null); + Contract.Requires(projectTracker != null); + + ContractsPackageAccessor.Current.ExtensionFailed += OnFailed; + this.TextView = textView; + if (textView.TextBuffer != null) + { + textView.TextBuffer.Changed += OnTextBufferChanged; + } + TextView.Closed += OnClosed; + this._projectTracker = projectTracker; + projectTracker.BuildDone += OnBuildDone; +// ContractsPackageAccessor.Current.NewSourceFile += OnNewSourceFile; + ContractsPackageAccessor.Current.NewCompilation += OnNewComilation; + + //Timer + _textBufferChangedTimer = new System.Timers.Timer(); + _textBufferChangedTimer.AutoReset = false; + _textBufferChangedTimer.Elapsed += OnTextViewSettled; + _textBufferChangedTimer.Interval = DelayOnTextViewOpened; //Wait two seconds before attempting to fetch any syntactic/semantic information. This gives VS a chance to properly initialize everything. + _textBufferChangedTimer.Start(); + + //Set the text properties + VSTextProperties = vsTextProperties; + ContractsPackageAccessor.Current.QueueWorkItem((() => { VSTextProperties.LineHeight = TextView.LineHeight; })); + + //Set the file name + Document document = TextView.TextSnapshot.GetOpenDocumentInCurrentContextWithChanges(); + FileName = document.Id; + } + + void OnClosed(object sender, EventArgs e) { + UnsubscribeFromEvents(); + } + void OnFailed() { + UnsubscribeFromEvents(); + } + void UnsubscribeFromEvents() { + //Halt the timer + _textBufferChangedTimer.Enabled = false; + _textBufferChangedTimer.Elapsed -= OnTextViewSettled; + _textBufferChangedTimer.Close(); + + ProjectTracker.BuildDone -= OnBuildDone; + if (TextView.TextBuffer != null) + { + TextView.TextBuffer.Changed -= OnTextBufferChanged; + } + ContractsPackageAccessor.Current.NewCompilation -= OnNewComilation; +// ContractsPackageAccessor.Current.NewSourceFile -= OnNewSourceFile; + ContractsPackageAccessor.Current.ExtensionFailed -= OnFailed; + ContractsPackageAccessor.Current.Logger.WriteToLog("TextViewTracker for '" + FileName + "' unsubscribed from all events."); + } + + void OnBuildDone() { + + IsLatestSourceFileStale = true; + IsLatestCompilationStale = true; + ContractsPackageAccessor.Current.AskForNewVSModel(TextView.TextBuffer); + } + + void OnTextBufferChanged(object sender, TextContentChangedEventArgs e) { + + try + {// PublicEntry + #region Start timer + this._textBufferChangedTimer.Interval = DelayOnTextViewChanged; + this._textBufferChangedTimer.Enabled = true; + #endregion + } catch (Exception exn) { + ContractsPackageAccessor.Current.Logger.PublicEntryException(exn, "OnTextBufferChanged"); + } + } + void OnTextViewSettled(object sender, System.Timers.ElapsedEventArgs e) { + + ContractsPackageAccessor.Current.Logger.PublicEntry(() => { + + ContractsPackageAccessor.Current.Logger.WriteToLog("Timer elapsed. Waiting for new syntactic info."); + + ContractsPackageAccessor.Current.AskForNewVSModel(TextView.TextBuffer); + + IsLatestCompilationStale = true; + IsLatestSourceFileStale = true; + }, "OnTextViewSettled"); + } + + void OnNewSourceFile(Document sourceFile) { + Contract.Requires(sourceFile != null); + + // BUGBUG: Foxtrot1 extractor gets confused and a style-checker error is issued thinking there is code in the contract section. + //Contract.Requires(sourceFile != null); + //Contract.Requires(sourceFile.FileName != null); + + //Is this source file relevant to us? + if (FileName == sourceFile.Id) { + //Update our latest source file info + LatestSourceFile = sourceFile; + + //Save and update our staleness + var wasLatestSourceFileStale = IsLatestSourceFileStale; + IsLatestSourceFileStale = false; + + //Report our latest source file + if (LatestSourceFileChanged != null) + LatestSourceFileChanged(this, new LatestSourceFileChangedEventArgs(wasLatestSourceFileStale, IsLatestSourceFileStale, LatestSourceFile)); + } + } + void OnNewComilation(object compilationObject) { + Contract.Requires(compilationObject != null); + Workspace comp = (Workspace)compilationObject; + + //Is this compilation relevant to us? + Document sourceFile = comp.CurrentSolution.GetDocument(FileName); + if (sourceFile != null) + { + // Update source file + LatestSourceFile = sourceFile; + //Save and update our staleness + var wasLatestSourceFileStale = IsLatestSourceFileStale; + IsLatestSourceFileStale = false; + + //Updated our latest compilation info + LatestCompilation = comp; + + //Save and update our staleness + var wasLatestCompilationStale = IsLatestCompilationStale; + IsLatestCompilationStale = false; + + //Report our latest compilation + if (LatestCompilationChanged != null) + LatestCompilationChanged(this, new LatestCompilationChangedEventArgs(wasLatestCompilationStale, IsLatestCompilationStale, LatestCompilation)); + } + } + + } + public class LatestCompilationChangedEventArgs : EventArgs { + public bool WasLatestCompilationStale { get; private set; } + public bool IsLatestCompilationStale { get; private set; } + public Workspace LatestCompilation { get; private set; } + + public LatestCompilationChangedEventArgs(bool wasLatestCompilationStale, bool isLatestCompilationStale, Workspace latestCompilation) { + WasLatestCompilationStale = wasLatestCompilationStale; + IsLatestCompilationStale = isLatestCompilationStale; + LatestCompilation = latestCompilation; + } + } + public class LatestSourceFileChangedEventArgs : EventArgs { + public bool WasLatestSourceFileStale { get; private set; } + public bool IsLatestSourceFileStale { get; private set; } + public Document LatestSourceFile { get; private set; } + + public LatestSourceFileChangedEventArgs(bool wasLatestSourceFileStale, bool isLatestSourceFileStale, Document latestSourceFile) { + WasLatestSourceFileStale = wasLatestSourceFileStale; + IsLatestSourceFileStale = isLatestSourceFileStale; + LatestSourceFile = latestSourceFile; + } + } +} diff --git a/Microsoft.Research/ContractAdornments/CSharp.Roslyn/VersionedServicesFactory.cs b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/VersionedServicesFactory.cs new file mode 100644 index 00000000..272bb03b --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/VersionedServicesFactory.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.CSharp +{ + using System.Collections.Generic; + using Adornments; + using ContractAdornments.Interfaces; + using Microsoft.CodeAnalysis.Text; + using Microsoft.VisualStudio.Language.Intellisense; + using Microsoft.VisualStudio.Text; + using Microsoft.VisualStudio.Text.Editor; + + internal sealed class VersionedServicesFactory : IVersionedServicesFactory + { + public ICompilerHost CreateCompilerHost() + { + return new RoslynCompilerHost(); + } + + public ITextViewTracker CreateTextViewTracker(IWpfTextView textView, IProjectTracker projectTracker, VSTextProperties vsTextProperties) + { + return new TextViewTracker(textView, projectTracker, vsTextProperties); + } + + public IContractsProvider CreateContractsProvider(IProjectTracker projectTracker) + { + return new ContractsProvider(projectTracker); + } + + public IQuickInfoSource CreateQuickInfoSource(ITextBuffer textBuffer, ITextViewTracker textViewTracker) + { + return new QuickInfoSource(textBuffer, textViewTracker); + } + + public ISignatureHelpSource CreateSignatureHelpSource(ITextBuffer textBuffer, ITextViewTracker textViewTracker) + { + return new SignatureHelpSource(textBuffer, textViewTracker); + } + + private sealed class RoslynCompilerHost : ICompilerHost + { + public IEnumerable Compilers + { + get + { + yield return new RoslynCompiler(); + } + } + } + + private sealed class RoslynCompiler : ICompiler + { + public object GetCompilation(ITextBuffer textBuffer) + { + return textBuffer.GetWorkspace(); + } + } + } +} diff --git a/Microsoft.Research/ContractAdornments/CSharp.Roslyn/packages.ContractAdornments.CSharp.14.config b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/packages.ContractAdornments.CSharp.14.config new file mode 100644 index 00000000..a3344659 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp.Roslyn/packages.ContractAdornments.CSharp.14.config @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/VS2010/ContractAdornments.csproj b/Microsoft.Research/ContractAdornments/CSharp/ContractAdornments.CSharp.10.csproj similarity index 64% rename from Microsoft.Research/ContractAdornments/VS2010/ContractAdornments.csproj rename to Microsoft.Research/ContractAdornments/CSharp/ContractAdornments.CSharp.10.csproj index ed79059a..74d44523 100644 --- a/Microsoft.Research/ContractAdornments/VS2010/ContractAdornments.csproj +++ b/Microsoft.Research/ContractAdornments/CSharp/ContractAdornments.CSharp.10.csproj @@ -1,37 +1,25 @@  - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Common.CodeContracts.props)) - - - Debug AnyCPU 10.0.20506 2.0 - {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C} + {233B4116-291E-446E-9C44-04B7FBC514FF} Library Properties - ContractAdornments - CodeContractsHelper + ContractAdornments.CSharp + ContractAdornments.CSharp.10 v4.0 512 - true - 12.0 - - - - - 4.0 + obj\2010\ true full false - bin\Debug\ + bin\2010\Debug\ DEBUG;TRACE prompt 4 @@ -45,14 +33,14 @@ pdbonly true - bin\Release\ + bin\2010\Release\ TRACE prompt 4 true - bin\Devlab9\ + bin\2010\Devlab9\ full @@ -66,7 +54,7 @@ true - bin\Academic9\ + bin\2010\Academic9\ true full AnyCPU @@ -77,7 +65,7 @@ true - bin\Internal9\ + bin\2010\Internal9\ full @@ -91,7 +79,7 @@ true - bin\Devlab9ro\ + bin\2010\Devlab9ro\ true full AnyCPU @@ -100,14 +88,62 @@ prompt AllRules.ruleset + + true + bin\2010\Debug64\ + DEBUG;TRACE + full + AnyCPU + bin\2010\Debug\ContractAdornments.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + + + bin\2010\Internal64\ + TRACE + true + pdbonly + AnyCPU + bin\2010\Release\ContractAdornments.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + true + bin\2010\Devlab64\ + DEBUG;TRACE + full + AnyCPU + bin\2010\Debug\ContractAdornments.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + false + - - True + False + ..\..\..\packages\VSSDK.DTE.7.0.4\lib\net20\envdte.dll + False - - True + False + ..\..\..\packages\VSSDK.DTE.8.8.0.4\lib\net20\envdte80.dll + False False @@ -172,247 +208,153 @@ ..\..\ImportedCCI2\Microsoft.Cci.SourceModel.dll - - False - References\Microsoft.VisualStudio.CSharp.Services.Language.Interop.dll + + ..\..\..\packages\VSSDK.Language.CallHierarchy.10.10.0.4\lib\net40\Microsoft.VisualStudio.CallHierarchy.Package.Definitions.dll + False - True + ..\..\..\packages\VSSDK.CoreUtility.10.0.4\lib\net40\Microsoft.VisualStudio.CoreUtility.dll + False + + + ..\..\..\packages\VSSDK.Language.CSharp.10.10.0.4\lib\net40\Microsoft.VisualStudio.CSharp.Services.Language.dll + False - - References\Microsoft.VisualStudio.CSharp.Services.Language.dll + + ..\..\..\packages\VSSDK.Language.CSharp.10.10.0.4\lib\net40\Microsoft.VisualStudio.CSharp.Services.Language.Interop.dll False + False - - True + + ..\..\..\packages\VSSDK.Language.CallHierarchy.10.10.0.4\lib\net40\Microsoft.VisualStudio.Language.CallHierarchy.dll + False - False + ..\..\..\packages\VSSDK.Language.10.0.4\lib\net40\Microsoft.VisualStudio.Language.Intellisense.dll + False + + + ..\..\..\packages\VSSDK.Language.10.0.4\lib\net40\Microsoft.VisualStudio.Language.StandardClassification.dll + False + + + ..\..\..\packages\VSSDK.OLE.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.OLE.Interop.dll + False + + + ..\..\..\packages\VSSDK.Shell.10.10.0.4\lib\net40\Microsoft.VisualStudio.Shell.10.0.dll + False - - - - True + + ..\..\..\packages\VSSDK.Shell.Immutable.10.10.0.4\lib\net40\Microsoft.VisualStudio.Shell.Immutable.10.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.dll + False + + + ..\..\..\packages\VSSDK.Shell.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.8.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Interop.9.9.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.9.0.dll + False - - - True + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.Data.dll + False - True + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.Logic.dll + False - True + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.UI.dll + False - True + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.UI.Wpf.dll + False + + + ..\..\..\packages\VSSDK.TextManager.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.dll + False - - - False + ..\..\..\packages\VSSDK.TextManager.Interop.10.10.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.10.0.dll + False + + + ..\..\..\packages\VSSDK.TextManager.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.8.0.dll + False + + + ..\..\..\packages\VSSDK.TextManager.Interop.9.9.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.9.0.dll + False + + False + ..\..\..\packages\VSSDK.DTE.7.0.4\lib\net20\stdole.dll + False + + + False + ..\..\..\packages\VSSDK.VSLangProj.7.0.4\lib\net20\VSLangProj.dll + False - - False - - + False + ..\..\..\packages\VSSDK.VSLangProj.7.0.4\lib\net20\VSLangProj2.dll + False - - Always - true - License\AdornmentsEULA.docx - - - Always - true - AdornmentsEULA.rtf - - - Inheritance\PropertyCollector.cs - - - Inheritance\MethodCollector.cs - - - Inheritance\InheritanceTracker.cs - - - Contracts\CSharpToCCIHelper.cs - - - Intellisense\IntellisenseContractsHelper.cs - - - Intellisense\SignatureHelp.cs - - - Intellisense\SignatureHelpProvider.cs - - - - - - - Metadata\MetadataTracker.cs - - - Intellisense\QuickInfo.cs - - - Intellisense\QuickInfoProvider.cs - - - TextView\TextViewTracker.cs - - - TextView\TextViewProvider.cs - Version\version.cs - - VSServiceProvider\GlobalSuppressions.cs - - - VSServiceProvider\Guids.cs - - - Contracts\ContractsProvider.cs - - - - - VSServiceProvider\NonLockingHost.cs - - - VSServiceProvider\OptionsPage\OptionsPage.cs - - - VSServiceProvider\ProjectTracker.cs - - - VSServiceProvider\VSServiceProvider.cs - - - - - - - - - - Never - Images\ContractAdornments_Large.png - - - Never - Images\ContractAdornments_Small.png - - - Never - Images\Inheritance_Small.png - - - Always - true - QuickInfo_Large.png - - - - - VSServiceProvider\OptionsPage\OptionsResources.resx - + + + + + + + + + + + + + - + {784aa6a9-013e-4d8e-82d6-934571cf1357} Adornments + + {b0c91c82-c1d8-4697-b07e-18e17d11eb41} + ContractAdornments.Interfaces + {E47A869B-4B78-41B3-AF6E-1D51B2D1AD3B} Utilities - - - true - true - - - true - bin\Debug64\ - DEBUG;TRACE - full - AnyCPU - bin\Debug\CodeContractsHelper.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - false - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - false - - - bin\Internal64\ - TRACE - true - pdbonly - AnyCPU - bin\Release\CodeContractsHelper.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - - - true - bin\Devlab64\ - DEBUG;TRACE - full - AnyCPU - bin\Debug\CodeContractsHelper.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - false - false - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - Debug AnyCPU 10.0.20506 2.0 - {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {5982130C-B0DD-4E10-82F7-A23F40A16315} + {A73F8AEB-7D31-4D67-9D94-853D1BB597A6} Library Properties - ContractAdornments - CodeContractsHelper11 - true - true - - true - true + ContractAdornments.CSharp + ContractAdornments.CSharp.11 v4.5 512 - 11.0 - - - - - 4.0 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true + obj\2012\ true full false - bin\Debug\ + bin\2012\Debug\ DEBUG;TRACE prompt 4 @@ -59,22 +27,20 @@ False C:\Users\a-darylz\Documents\CCI\Microsoft.Research\ContractAdornments - True - false + False + true pdbonly true - bin\Release\ + bin\2012\Release\ TRACE prompt 4 - false - False true - bin\Devlab9\ + bin\2012\Devlab9\ full @@ -84,12 +50,11 @@ prompt true AllRules.ruleset - false False true - bin\Academic9\ + bin\2012\Academic9\ true full AnyCPU @@ -97,12 +62,10 @@ GlobalSuppressions.cs prompt AllRules.ruleset - false - False true - bin\Internal9\ + bin\2012\Internal9\ full @@ -112,12 +75,11 @@ prompt true AllRules.ruleset - false False true - bin\Devlab9ro\ + bin\2012\Devlab9ro\ true full AnyCPU @@ -125,17 +87,63 @@ GlobalSuppressions.cs prompt AllRules.ruleset - false - False + + + true + bin\2012\Debug64\ + DEBUG;TRACE + full + AnyCPU + bin\2012\Debug\ContractAdornments.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + + + bin\2012\Internal64\ + TRACE + true + pdbonly + AnyCPU + bin\2012\Release\ContractAdornments.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + true + bin\2012\Devlab64\ + DEBUG;TRACE + full + AnyCPU + bin\2012\Debug\ContractAdornments.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + false - - True + False + ..\..\..\packages\VSSDK.DTE.7.0.4\lib\net20\envdte.dll + False - - True + False + ..\..\..\packages\VSSDK.DTE.8.8.0.4\lib\net20\envdte80.dll + False False @@ -152,8 +160,7 @@ ..\..\ImportedCCI2\Microsoft.Cci.ContractExtractor.dll - - False + ..\..\ImportedCCI2\Microsoft.Cci.CSharpSourceEmitter.dll @@ -184,277 +191,191 @@ False ..\..\ImportedCCI2\Microsoft.Cci.PdbReader.dll + + False + ..\..\ImportedCCI2\Microsoft.Cci.PdbWriter.dll + False ..\..\ImportedCCI2\Microsoft.Cci.PEReader.dll + + False + ..\..\ImportedCCI2\Microsoft.Cci.PeWriter.dll + False ..\..\ImportedCCI2\Microsoft.Cci.SourceModel.dll - - - References\Microsoft.VisualStudio.CSharp.Services.Language.dll - - - References\Microsoft.VisualStudio.CSharp.Services.Language.Interop.dll - - - - - - - - + + ..\..\..\packages\VSSDK.Language.CallHierarchy.11.11.0.4\lib\net45\Microsoft.VisualStudio.CallHierarchy.Package.Definitions.dll + False + + + ..\..\..\packages\VSSDK.CoreUtility.11.0.4\lib\net45\Microsoft.VisualStudio.CoreUtility.dll + False + + + ..\..\..\packages\VSSDK.Language.CSharp.11.11.0.4\lib\net45\Microsoft.VisualStudio.CSharp.Services.Language.dll + False + + + ..\..\..\packages\VSSDK.Language.CSharp.11.11.0.4\lib\net45\Microsoft.VisualStudio.CSharp.Services.Language.Interop.dll + False + False + + + ..\..\..\packages\VSSDK.GraphModel.11.0.4\lib\net45\Microsoft.VisualStudio.GraphModel.dll + False + + + ..\..\..\packages\VSSDK.Language.CallHierarchy.11.11.0.4\lib\net45\Microsoft.VisualStudio.Language.CallHierarchy.dll + False + + + ..\..\..\packages\VSSDK.Language.11.0.4\lib\net45\Microsoft.VisualStudio.Language.Intellisense.dll + False + + + ..\..\..\packages\VSSDK.Language.11.0.4\lib\net45\Microsoft.VisualStudio.Language.StandardClassification.dll + False + + + ..\..\..\packages\VSSDK.OLE.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.OLE.Interop.dll + False + + + ..\..\..\packages\VSSDK.Shell.11.11.0.4\lib\net45\Microsoft.VisualStudio.Shell.11.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Immutable.10.10.0.4\lib\net40\Microsoft.VisualStudio.Shell.Immutable.10.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Immutable.11.11.0.4\lib\net45\Microsoft.VisualStudio.Shell.Immutable.11.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.dll + False + False + ..\..\..\packages\VSSDK.Shell.Interop.10.10.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.10.0.dll + False False + ..\..\..\packages\VSSDK.Shell.Interop.11.11.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.11.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.8.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Interop.9.9.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.9.0.dll + False + + + ..\..\..\packages\VSSDK.Text.11.0.4\lib\net45\Microsoft.VisualStudio.Text.Data.dll + False + + + ..\..\..\packages\VSSDK.Text.11.0.4\lib\net45\Microsoft.VisualStudio.Text.Logic.dll + False + + + ..\..\..\packages\VSSDK.Text.11.0.4\lib\net45\Microsoft.VisualStudio.Text.UI.dll + False + + + ..\..\..\packages\VSSDK.Text.11.0.4\lib\net45\Microsoft.VisualStudio.Text.UI.Wpf.dll + False + + + ..\..\..\packages\VSSDK.TextManager.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.dll + False - - - - - - - False + ..\..\..\packages\VSSDK.TextManager.Interop.10.10.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.10.0.dll + False + + + ..\..\..\packages\VSSDK.TextManager.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.8.0.dll + False + + + ..\..\..\packages\VSSDK.TextManager.Interop.9.9.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.9.0.dll + False + + False + ..\..\..\packages\VSSDK.DTE.7.0.4\lib\net20\stdole.dll + False + + + + + + False + ..\..\..\packages\VSSDK.VSLangProj.7.0.4\lib\net20\VSLangProj.dll + False - - False - - + False + ..\..\..\packages\VSSDK.VSLangProj.7.0.4\lib\net20\VSLangProj2.dll + False - - Always - true - License\AdornmentsEULA.docx - - - Always - true - AdornmentsEULA.rtf - - - Inheritance\PropertyCollector.cs - - - Inheritance\MethodCollector.cs - - - Inheritance\InheritanceTracker.cs - - - Contracts\CSharpToCCIHelper.cs - - - Intellisense\IntellisenseContractsHelper.cs - - - Intellisense\SignatureHelp.cs - - - Intellisense\SignatureHelpProvider.cs - - - - - - - Metadata\MetadataTracker.cs - - - Intellisense\QuickInfo.cs - - - Intellisense\QuickInfoProvider.cs - - - TextView\TextViewTracker.cs - - - TextView\TextViewProvider.cs - Version\version.cs - - VSServiceProvider\GlobalSuppressions.cs - - - VSServiceProvider\Guids.cs - - - Contracts\ContractsProvider.cs - - - - - VSServiceProvider\NonLockingHost.cs - - - VSServiceProvider\OptionsPage\OptionsPage.cs - - - VSServiceProvider\ProjectTracker.cs - - - VSServiceProvider\VSServiceProvider.cs - - - - - - + + + + + + + + + + + + + - - Never - Images\ContractAdornments_Large.png - - - Never - Images\ContractAdornments_Small.png - - - Never - Images\Inheritance_Small.png - - - Always - true - QuickInfo_Large.png - - - - - VSServiceProvider\OptionsPage\OptionsResources.resx - - - - - {235196bb-603a-470a-af8e-ef6c8d01c4dc} - Adornments11 + + {784aa6a9-013e-4d8e-82d6-934571cf1357} + Adornments + + + {b0c91c82-c1d8-4697-b07e-18e17d11eb41} + ContractAdornments.Interfaces {E47A869B-4B78-41B3-AF6E-1D51B2D1AD3B} Utilities - - Program - $(DevEnvDir)devenv.exe - /rootsuffix Exp - - - 12.0 - 11.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - False - Microsoft .NET Framework 4.5 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - - - true - true - - - true - bin\Debug64\ - DEBUG;TRACE - full - AnyCPU - bin\Debug\CodeContractsHelper.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - false - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - false - false - False - - - bin\Internal64\ - TRACE - true - pdbonly - AnyCPU - bin\Release\CodeContractsHelper.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - false - False - - - true - bin\Devlab64\ - DEBUG;TRACE - full - AnyCPU - bin\Debug\CodeContractsHelper.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - false - false - false - False - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - + \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/Sources/Contracts/CSharpToCCIHelper.cs b/Microsoft.Research/ContractAdornments/CSharp/Contracts/CSharpToCCIHelper.cs similarity index 98% rename from Microsoft.Research/ContractAdornments/Sources/Contracts/CSharpToCCIHelper.cs rename to Microsoft.Research/ContractAdornments/CSharp/Contracts/CSharpToCCIHelper.cs index 3537b995..18db1a99 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Contracts/CSharpToCCIHelper.cs +++ b/Microsoft.Research/ContractAdornments/CSharp/Contracts/CSharpToCCIHelper.cs @@ -1,433 +1,433 @@ -// CodeContracts -// -// Copyright (c) Microsoft Corporation -// -// All rights reserved. -// -// MIT License -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Linq; -using Microsoft.Cci; -using Microsoft.RestrictedUsage.CSharp.Semantics; -using Microsoft.RestrictedUsage.CSharp.Compiler; -using Microsoft.RestrictedUsage.CSharp.Core; -using Microsoft.RestrictedUsage.CSharp.Extensions; -using Microsoft.RestrictedUsage.CSharp.Syntax; -using Microsoft.RestrictedUsage.CSharp.Utilities; -using System; - -namespace ContractAdornments { - /// - /// A helper class for the Visual Studio semantic CSharp model. This helper is aware of cci. - /// - /// - /// All methods in this class are [Pure], meaning they are side-effect free. - /// - public static class CSharpToCCIHelper { - /// - /// Gets the CCI CallingConventions for a semantic member. The calling convention for a CSharp method is "Defualt" (always) and "Generic" (if it is generic) and/or "HasThis" (if it is non-static). - /// - /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. - [Pure] - public static CallingConvention GetCallingConventionFor(CSharpMember semanticMember) { - Contract.Requires(semanticMember != null); - - var callingConvention = CallingConvention.Default; - if (semanticMember.IsMethod) { - if (semanticMember.TypeParameters != null && semanticMember.TypeParameters.Count > 0) - callingConvention = callingConvention | CallingConvention.Generic; - } - if (!semanticMember.IsStatic) - callingConvention = callingConvention | CallingConvention.HasThis; - return callingConvention; - } - /// - /// Gets the CCI PrimitiveTypeCode for a semantic type. If the semantic type isn't a primitive type, the PrimitiveTypeCode "NotPrimitive" is used. - /// - /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. - [Pure] - public static PrimitiveTypeCode GetPrimitiveTypeCode(CSharpType type) { - Contract.Requires(type != null); - Contract.Ensures(Contract.Result() != PrimitiveTypeCode.Pointer && - Contract.Result() != PrimitiveTypeCode.Reference && - Contract.Result() != PrimitiveTypeCode.Invalid, - "These types aren't checked for; all others are."); - if(type.Name == null || String.IsNullOrEmpty(type.Name.Text)) throw new IllFormedSemanticModelException("A CSharpType was found with a null or empty 'Name' field.", type); - switch (type.Name.Text) { - case "Boolean": return PrimitiveTypeCode.Boolean; - case "Char": return PrimitiveTypeCode.Char; - case "SByte": return PrimitiveTypeCode.Int8; - case "Single": return PrimitiveTypeCode.Float32; - case "Double": return PrimitiveTypeCode.Float64; - case "Int16": return PrimitiveTypeCode.Int16; - case "Int32": return PrimitiveTypeCode.Int32; - case "Int64": return PrimitiveTypeCode.Int64; - case "IntPtr": return PrimitiveTypeCode.IntPtr; - case "String": return PrimitiveTypeCode.String; - case "Byte": return PrimitiveTypeCode.UInt8; - case "UInt16": return PrimitiveTypeCode.UInt32; - case "UInt32": return PrimitiveTypeCode.UInt64; - case "UIntPtr": return PrimitiveTypeCode.UIntPtr; - case "Void": return PrimitiveTypeCode.Void; - default: return PrimitiveTypeCode.NotPrimitive; - } - } - /// - /// Checks if two enumerables are equivalent. - /// - [Pure] - public static bool EnumerablesAreEquivalent(IEnumerable list1, IEnumerable list2, Func comparison) { - Contract.Requires(list1 != null); - Contract.Requires(list2 != null); - Contract.Requires(comparison != null); - - var list1Enum = list1.GetEnumerator(); - var list2Enum = list2.GetEnumerator(); - bool list1Moved = list1Enum.MoveNext(); - bool list2Moved = list2Enum.MoveNext(); - if (list1Moved ^ list2Moved) - return false; - while (list1Moved && list2Moved) { - var item1 = list1Enum.Current; - var item2 = list2Enum.Current; - if (!comparison(item1, item2)) - return false; - list1Moved = list1Enum.MoveNext(); - list2Moved = list2Enum.MoveNext(); - if (list1Moved ^ list2Moved) - return false; - } - return true; - } - /// - /// Checks if two semantic methods are equivalent. - /// - /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. - [Pure] - public static bool MembersAreEquivalent(CSharpMember member1, CSharpMember member2) { - Contract.Requires(member1 != null); - Contract.Requires(member2 != null); - #region Check kind - if (member1.IsProperty ^ member2.IsProperty) return false; - if (member1.IsMethod ^ member2.IsMethod) return false; - if (member1.IsField ^ member2.IsField) return false; - if (member1.IsIndexer ^ member2.IsIndexer) return false; - #endregion - #region Check name - if (member1.Name == null ^ member2.Name == null) return false; - if (member1.Name!= null && member2.Name != null - && !member1.Name.Equals(member2.Name)) return false; - #endregion - #region Check explicit interface implementation - if (member1.ExplicitInterfaceImplementation != null ^ member2.ExplicitInterfaceImplementation != null) return false; - if (member1.ExplicitInterfaceImplementation != null && member2.ExplicitInterfaceImplementation != null - && !TypesAreEquivalent(member1.ExplicitInterfaceImplementation, member2.ExplicitInterfaceImplementation)) return false; - #endregion - #region Check parameters - if (member1.Parameters == null ^ member2.Parameters == null) return false; - if (member1.Parameters != null && member2.Parameters != null - && !ParameterListsAreEquivalent(member1.Parameters, member2.Parameters)) return false; - #endregion - #region Check return type - if (member1.ReturnType == null) throw new IllFormedSemanticModelException("A CSharpMember (member) was found with a null 'ReturnType' field.", member1); - if (member2.ReturnType == null) throw new IllFormedSemanticModelException("A CSharpMember (member) was found with a null 'ReturnType' field.", member2); - if (!TypesAreEquivalent(member1.ReturnType, member2.ReturnType)) return false; - #endregion - return true; - } - /// - /// Checks if two parameters are equivalent. - /// - /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. - [Pure] - public static bool ParametersAreEquivalent(CSharpParameter param1, CSharpParameter param2) { - Contract.Requires(param1 != null); - Contract.Requires(param2 != null); - //return param1.Equals(param2); //Doesn't work for our purposes. - if (param1.Type == null) throw new IllFormedSemanticModelException("A CSharpParameter was found with a null 'Type' field.", param1); - if (param2.Type == null) throw new IllFormedSemanticModelException("A CSharpParameter was found with a null 'Type' field.", param2); - if (!TypesAreEquivalent(param1.Type, param2.Type)) return false; - if (param1.IsOut ^ param2.IsOut) return false; - if (param1.IsParams ^ param2.IsParams) return false; - if (param1.IsRef ^ param2.IsRef) return false; - if (param1.IsThis ^ param2.IsThis) return false; - return true; - } - /// - /// Checks if two parameter lists are equivalent. - /// - /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. - [Pure] - public static bool ParameterListsAreEquivalent(IEnumerable paramList1, IEnumerable paramList2) { - Contract.Requires(paramList1 != null); - Contract.Requires(paramList2 != null); - return EnumerablesAreEquivalent(paramList1, paramList2, (p1, p2) => ParametersAreEquivalent(p1, p2)); - } - /// - /// Crawls upward in the semantic tree looking for the first base method this method inherits from. - /// - /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. - [Pure] - public static bool TryGetBaseMember(CSharpMember member, out CSharpMember baseMember) { - Contract.Requires(member != null); - Contract.Ensures(!Contract.Result() || - member.IsMethod == Contract.ValueAtReturn(out baseMember).IsMethod - && member.IsProperty == Contract.ValueAtReturn(out baseMember).IsProperty - && member.IsIndexer == Contract.ValueAtReturn(out baseMember).IsIndexer - && member.IsField == Contract.ValueAtReturn(out baseMember).IsField); - - baseMember = null; - - if (member.ContainingType == null) throw new IllFormedSemanticModelException("A CSharpMember (method) was found with a null 'ContainingType' field.", member); - if (!member.ContainingType.IsClass) return false; - var containingType = member.ContainingType; - var baseClass = containingType.BaseClass; - while (baseClass != null) { - if (TryGetMemberWithSameSignatureFromType(baseClass, member, out baseMember)) - { - Contract.Assume( - member.IsMethod == baseMember.IsMethod - && member.IsProperty == baseMember.IsProperty - && member.IsIndexer == baseMember.IsIndexer - && member.IsField == baseMember.IsField); - return true; - } - baseClass = baseClass.BaseClass; - } - return false; - } - /// - /// - /// - /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. - [Pure] - public static bool TryGetMemberWithSameSignatureFromType(CSharpType type, CSharpMember memberToMatch, out CSharpMember member) { - Contract.Requires(type != null); - Contract.Requires(memberToMatch != null); - Contract.Ensures(!Contract.Result() || Contract.ValueAtReturn(out member) != null); - - member = null; - var members = type.Members; - if (members == null) throw new IllFormedSemanticModelException("A CSharpType was found with a null 'Members' field.", type); - foreach (var m in members) { - if (m == null) throw new IllFormedSemanticModelException("An null 'member' was found in a CSharpType's 'Members' field.", type); - if (MembersAreEquivalent(m, memberToMatch)) { - member = m; - return true; - } - } - return false; - } - /// - /// Crawls upward in the semantic tree looking for the first interface method that this method implements. - /// - /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. - [Pure] - public static bool TryGetInterfaceMember(CSharpMember member, out CSharpMember interfaceMethod) { - Contract.Requires(member != null); - Contract.Ensures(!Contract.Result() || - Contract.ValueAtReturn(out interfaceMethod) != null); - - interfaceMethod = null; - - if (member.ExplicitInterfaceImplementation != null) - if (TryGetMemberWithSameSignatureFromType(member.ExplicitInterfaceImplementation, member, out interfaceMethod)) - { - return true; - } - - if (member.ContainingType == null || member.ContainingType.BaseInterfaces == null) - { - return false; - } - - foreach (var i in member.ContainingType.BaseInterfaces) - { - if (i == null) continue; - if (TryGetMemberWithSameSignatureFromType(i, member, out interfaceMethod)) - { - return true; - } - } - return false; - } - /// - /// Checks if two types are equivalent. - /// - /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. - [Pure] - public static bool TypesAreEquivalent(CSharpType type1, CSharpType type2) { - if (type1 == null && type2 == null) return true; - if (type1 == null) return false; - if (type2 == null) return false; - - #region Check if type parameter - if (type1.IsTypeParameter ^ type2.IsTypeParameter) return false; - if (type1.IsTypeParameter && type2.IsTypeParameter) { - if (type1.HasReferenceTypeConstraint ^ type2.HasReferenceTypeConstraint) return false; - if (type1.HasValueTypeConstraint ^ type2.HasValueTypeConstraint) return false; - return true; - } - #endregion - //return type1.Equals(type2); //TODO: Can we use this? Doesn't seem to work for generic types like 'List' - #region Check name - //if (type1.Name == null) throw new IllFormedSemanticModelException("A CSharpType was founded with a null 'Name' field.", type1); - //if (type2.Name == null) throw new IllFormedSemanticModelException("A CSharpType was founded with a null 'Name' field.", type2); - //It seems array types always have null names - if (type1.Name != null ^ type2.Name != null) return false; - if (type1.Name != null && type2.Name != null && - !type1.Name.Equals(type2.Name)) return false; - #endregion - #region Check containing type and namespace - if (type1.ContainingType != null ^ type2.ContainingType != null) return false; - if (type1.ContainingType != null && type2.ContainingType != null) { - if (!TypesAreEquivalent(type1.ContainingType, type2.ContainingType)) return false; - } else { - if (type1.ContainingNamespace != null ^ type2.ContainingNamespace != null) return false; - if (type1.ContainingNamespace != null && type2.ContainingNamespace != null && - !type1.ContainingNamespace.Equals(type2.ContainingNamespace)) return false; - } - #endregion - #region Check type parameters - if (type1.TypeParameters != null ^ type2.TypeParameters != null) return false; - if (type1.TypeParameters != null && type2.TypeParameters != null && - type1.TypeParameters.Count != type2.TypeParameters.Count) return false; - #endregion - #region Check type arguments - - if (type1.TypeArguments != null ^ type2.TypeArguments != null) return false; - if (type1.TypeArguments != null && type2.TypeArguments != null && - !TypeListsAreEquivalent(type1.TypeArguments, type2.TypeArguments)) return false; - #endregion - #region Check array - if (type1.IsArray ^ type2.IsArray) return false; - if (type1.IsArray && type2.IsArray) - return TypesAreEquivalent(type1.ElementType, type2.ElementType); - #endregion - #region Check pointer - if (type1.IsPointer ^ type2.IsPointer) return false; - if (type1.IsPointer && type2.IsPointer) - return TypesAreEquivalent(type1.ElementType, type2.ElementType); - #endregion - if (type1.IsClass != type2.IsClass - || type1.IsStruct != type2.IsStruct - || type1.IsStatic != type2.IsStatic - || type1.IsValueType != type2.IsValueType) - return false; - return true; - } - /// - /// Checks if two type lists are equivalent. - /// - /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. - [Pure] - public static bool TypeListsAreEquivalent(IEnumerable typeList1, IEnumerable typeList2) { - Contract.Requires(typeList1 != null); - Contract.Requires(typeList2 != null); - return EnumerablesAreEquivalent(typeList1, typeList2, (t1, t2) => TypesAreEquivalent(t1, t2)); - } - [Pure] - public static CSharpMember Uninstantiate(this CSharpMember member) { - Contract.Requires(member != null); - Contract.Ensures(Contract.Result() != null); - Contract.Ensures(member.IsMethod == Contract.Result().IsMethod); - Contract.Ensures(member.IsConstructor == Contract.Result().IsConstructor); - Contract.Ensures(member.IsProperty == Contract.Result().IsProperty); - Contract.Ensures(member.IsIndexer == Contract.Result().IsIndexer); - - var uninstantiatedMember = member; - - var definingMember = member.DefiningMember; - while (definingMember != null) { - uninstantiatedMember = definingMember; - definingMember = definingMember.DefiningMember; - } - - Contract.Assume(member.IsMethod == uninstantiatedMember.IsMethod); - Contract.Assume(member.IsConstructor == uninstantiatedMember.IsConstructor); - Contract.Assume(member.IsProperty == uninstantiatedMember.IsProperty); - Contract.Assume(member.IsIndexer == uninstantiatedMember.IsIndexer); - return uninstantiatedMember; - } - [Pure] - public static CSharpType Uninstantiate(this CSharpType type) { - Contract.Requires(type != null); - Contract.Ensures(Contract.Result() != null); - - var uninstantiatedType = type; - - var definingType = type.DefiningType; - while (definingType != null) { - uninstantiatedType = definingType; - definingType = definingType.DefiningType; - } - - return uninstantiatedType; - } - } - - [Serializable] - public class IllFormedSemanticModelException : Exception { - public CSharpMember BadMember { get; private set; } - public CSharpType BadType { get; private set; } - public CSharpParameter BadParameter { get; private set; } - public CSharpNamespace BadNamespace { get; private set; } - public CSharpKind Kind { get; private set; } - - [ContractInvariantMethod] - void ObjectInvariant() { - Contract.Invariant((BadMember != null) == (Kind == CSharpKind.CSharpMember)); - Contract.Invariant((BadType != null) == (Kind == CSharpKind.CSharpType)); - Contract.Invariant((BadParameter != null) == (Kind == CSharpKind.CSharpParameter)); - Contract.Invariant((BadNamespace != null) == (Kind == CSharpKind.CSharpNamespace)); - } - - public IllFormedSemanticModelException() { } - public IllFormedSemanticModelException(string message) : base(message) { } - public IllFormedSemanticModelException(string message, Exception inner) : base(message, inner) { } - public IllFormedSemanticModelException(string message, CSharpType badType) : base(message) { - Contract.Requires(badType != null); - - BadType = badType; - Kind = CSharpKind.CSharpType; - } - public IllFormedSemanticModelException(string message, CSharpMember badMember) : base(message) { - Contract.Requires(badMember != null); - - BadMember = badMember; - Kind = CSharpKind.CSharpMember; - } - public IllFormedSemanticModelException(string message, CSharpParameter badParameter) : base(message) { - Contract.Requires(badParameter != null); - - BadParameter = badParameter; - Kind = CSharpKind.CSharpParameter; - } - public IllFormedSemanticModelException(string message, CSharpNamespace badNamespace) : base(message) { - Contract.Requires(badNamespace != null); - - BadNamespace = badNamespace; - Kind = CSharpKind.CSharpNamespace; - } - protected IllFormedSemanticModelException( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) - : base(info, context) { } - } - - public enum CSharpKind { - None, - CSharpMember, - CSharpType, - CSharpParameter, - CSharpNamespace - } +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Linq; +using Microsoft.Cci; +using Microsoft.RestrictedUsage.CSharp.Semantics; +using Microsoft.RestrictedUsage.CSharp.Compiler; +using Microsoft.RestrictedUsage.CSharp.Core; +using Microsoft.RestrictedUsage.CSharp.Extensions; +using Microsoft.RestrictedUsage.CSharp.Syntax; +using Microsoft.RestrictedUsage.CSharp.Utilities; +using System; + +namespace ContractAdornments { + /// + /// A helper class for the Visual Studio semantic CSharp model. This helper is aware of cci. + /// + /// + /// All methods in this class are [Pure], meaning they are side-effect free. + /// + public static class CSharpToCCIHelper { + /// + /// Gets the CCI CallingConventions for a semantic member. The calling convention for a CSharp method is "Defualt" (always) and "Generic" (if it is generic) and/or "HasThis" (if it is non-static). + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static CallingConvention GetCallingConventionFor(CSharpMember semanticMember) { + Contract.Requires(semanticMember != null); + + var callingConvention = CallingConvention.Default; + if (semanticMember.IsMethod) { + if (semanticMember.TypeParameters != null && semanticMember.TypeParameters.Count > 0) + callingConvention = callingConvention | CallingConvention.Generic; + } + if (!semanticMember.IsStatic) + callingConvention = callingConvention | CallingConvention.HasThis; + return callingConvention; + } + /// + /// Gets the CCI PrimitiveTypeCode for a semantic type. If the semantic type isn't a primitive type, the PrimitiveTypeCode "NotPrimitive" is used. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static PrimitiveTypeCode GetPrimitiveTypeCode(CSharpType type) { + Contract.Requires(type != null); + Contract.Ensures(Contract.Result() != PrimitiveTypeCode.Pointer && + Contract.Result() != PrimitiveTypeCode.Reference && + Contract.Result() != PrimitiveTypeCode.Invalid, + "These types aren't checked for; all others are."); + if(type.Name == null || String.IsNullOrEmpty(type.Name.Text)) throw new IllFormedSemanticModelException("A CSharpType was found with a null or empty 'Name' field.", type); + switch (type.Name.Text) { + case "Boolean": return PrimitiveTypeCode.Boolean; + case "Char": return PrimitiveTypeCode.Char; + case "SByte": return PrimitiveTypeCode.Int8; + case "Single": return PrimitiveTypeCode.Float32; + case "Double": return PrimitiveTypeCode.Float64; + case "Int16": return PrimitiveTypeCode.Int16; + case "Int32": return PrimitiveTypeCode.Int32; + case "Int64": return PrimitiveTypeCode.Int64; + case "IntPtr": return PrimitiveTypeCode.IntPtr; + case "String": return PrimitiveTypeCode.String; + case "Byte": return PrimitiveTypeCode.UInt8; + case "UInt16": return PrimitiveTypeCode.UInt32; + case "UInt32": return PrimitiveTypeCode.UInt64; + case "UIntPtr": return PrimitiveTypeCode.UIntPtr; + case "Void": return PrimitiveTypeCode.Void; + default: return PrimitiveTypeCode.NotPrimitive; + } + } + /// + /// Checks if two enumerables are equivalent. + /// + [Pure] + public static bool EnumerablesAreEquivalent(IEnumerable list1, IEnumerable list2, Func comparison) { + Contract.Requires(list1 != null); + Contract.Requires(list2 != null); + Contract.Requires(comparison != null); + + var list1Enum = list1.GetEnumerator(); + var list2Enum = list2.GetEnumerator(); + bool list1Moved = list1Enum.MoveNext(); + bool list2Moved = list2Enum.MoveNext(); + if (list1Moved ^ list2Moved) + return false; + while (list1Moved && list2Moved) { + var item1 = list1Enum.Current; + var item2 = list2Enum.Current; + if (!comparison(item1, item2)) + return false; + list1Moved = list1Enum.MoveNext(); + list2Moved = list2Enum.MoveNext(); + if (list1Moved ^ list2Moved) + return false; + } + return true; + } + /// + /// Checks if two semantic methods are equivalent. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool MembersAreEquivalent(CSharpMember member1, CSharpMember member2) { + Contract.Requires(member1 != null); + Contract.Requires(member2 != null); + #region Check kind + if (member1.IsProperty ^ member2.IsProperty) return false; + if (member1.IsMethod ^ member2.IsMethod) return false; + if (member1.IsField ^ member2.IsField) return false; + if (member1.IsIndexer ^ member2.IsIndexer) return false; + #endregion + #region Check name + if (member1.Name == null ^ member2.Name == null) return false; + if (member1.Name!= null && member2.Name != null + && !member1.Name.Equals(member2.Name)) return false; + #endregion + #region Check explicit interface implementation + if (member1.ExplicitInterfaceImplementation != null ^ member2.ExplicitInterfaceImplementation != null) return false; + if (member1.ExplicitInterfaceImplementation != null && member2.ExplicitInterfaceImplementation != null + && !TypesAreEquivalent(member1.ExplicitInterfaceImplementation, member2.ExplicitInterfaceImplementation)) return false; + #endregion + #region Check parameters + if (member1.Parameters == null ^ member2.Parameters == null) return false; + if (member1.Parameters != null && member2.Parameters != null + && !ParameterListsAreEquivalent(member1.Parameters, member2.Parameters)) return false; + #endregion + #region Check return type + if (member1.ReturnType == null) throw new IllFormedSemanticModelException("A CSharpMember (member) was found with a null 'ReturnType' field.", member1); + if (member2.ReturnType == null) throw new IllFormedSemanticModelException("A CSharpMember (member) was found with a null 'ReturnType' field.", member2); + if (!TypesAreEquivalent(member1.ReturnType, member2.ReturnType)) return false; + #endregion + return true; + } + /// + /// Checks if two parameters are equivalent. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool ParametersAreEquivalent(CSharpParameter param1, CSharpParameter param2) { + Contract.Requires(param1 != null); + Contract.Requires(param2 != null); + //return param1.Equals(param2); //Doesn't work for our purposes. + if (param1.Type == null) throw new IllFormedSemanticModelException("A CSharpParameter was found with a null 'Type' field.", param1); + if (param2.Type == null) throw new IllFormedSemanticModelException("A CSharpParameter was found with a null 'Type' field.", param2); + if (!TypesAreEquivalent(param1.Type, param2.Type)) return false; + if (param1.IsOut ^ param2.IsOut) return false; + if (param1.IsParams ^ param2.IsParams) return false; + if (param1.IsRef ^ param2.IsRef) return false; + if (param1.IsThis ^ param2.IsThis) return false; + return true; + } + /// + /// Checks if two parameter lists are equivalent. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool ParameterListsAreEquivalent(IEnumerable paramList1, IEnumerable paramList2) { + Contract.Requires(paramList1 != null); + Contract.Requires(paramList2 != null); + return EnumerablesAreEquivalent(paramList1, paramList2, (p1, p2) => ParametersAreEquivalent(p1, p2)); + } + /// + /// Crawls upward in the semantic tree looking for the first base method this method inherits from. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool TryGetBaseMember(CSharpMember member, out CSharpMember baseMember) { + Contract.Requires(member != null); + Contract.Ensures(!Contract.Result() || + member.IsMethod == Contract.ValueAtReturn(out baseMember).IsMethod + && member.IsProperty == Contract.ValueAtReturn(out baseMember).IsProperty + && member.IsIndexer == Contract.ValueAtReturn(out baseMember).IsIndexer + && member.IsField == Contract.ValueAtReturn(out baseMember).IsField); + + baseMember = null; + + if (member.ContainingType == null) throw new IllFormedSemanticModelException("A CSharpMember (method) was found with a null 'ContainingType' field.", member); + if (!member.ContainingType.IsClass) return false; + var containingType = member.ContainingType; + var baseClass = containingType.BaseClass; + while (baseClass != null) { + if (TryGetMemberWithSameSignatureFromType(baseClass, member, out baseMember)) + { + Contract.Assume( + member.IsMethod == baseMember.IsMethod + && member.IsProperty == baseMember.IsProperty + && member.IsIndexer == baseMember.IsIndexer + && member.IsField == baseMember.IsField); + return true; + } + baseClass = baseClass.BaseClass; + } + return false; + } + /// + /// + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool TryGetMemberWithSameSignatureFromType(CSharpType type, CSharpMember memberToMatch, out CSharpMember member) { + Contract.Requires(type != null); + Contract.Requires(memberToMatch != null); + Contract.Ensures(!Contract.Result() || Contract.ValueAtReturn(out member) != null); + + member = null; + var members = type.Members; + if (members == null) throw new IllFormedSemanticModelException("A CSharpType was found with a null 'Members' field.", type); + foreach (var m in members) { + if (m == null) throw new IllFormedSemanticModelException("An null 'member' was found in a CSharpType's 'Members' field.", type); + if (MembersAreEquivalent(m, memberToMatch)) { + member = m; + return true; + } + } + return false; + } + /// + /// Crawls upward in the semantic tree looking for the first interface method that this method implements. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool TryGetInterfaceMember(CSharpMember member, out CSharpMember interfaceMethod) { + Contract.Requires(member != null); + Contract.Ensures(!Contract.Result() || + Contract.ValueAtReturn(out interfaceMethod) != null); + + interfaceMethod = null; + + if (member.ExplicitInterfaceImplementation != null) + if (TryGetMemberWithSameSignatureFromType(member.ExplicitInterfaceImplementation, member, out interfaceMethod)) + { + return true; + } + + if (member.ContainingType == null || member.ContainingType.BaseInterfaces == null) + { + return false; + } + + foreach (var i in member.ContainingType.BaseInterfaces) + { + if (i == null) continue; + if (TryGetMemberWithSameSignatureFromType(i, member, out interfaceMethod)) + { + return true; + } + } + return false; + } + /// + /// Checks if two types are equivalent. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool TypesAreEquivalent(CSharpType type1, CSharpType type2) { + if (type1 == null && type2 == null) return true; + if (type1 == null) return false; + if (type2 == null) return false; + + #region Check if type parameter + if (type1.IsTypeParameter ^ type2.IsTypeParameter) return false; + if (type1.IsTypeParameter && type2.IsTypeParameter) { + if (type1.HasReferenceTypeConstraint ^ type2.HasReferenceTypeConstraint) return false; + if (type1.HasValueTypeConstraint ^ type2.HasValueTypeConstraint) return false; + return true; + } + #endregion + //return type1.Equals(type2); //TODO: Can we use this? Doesn't seem to work for generic types like 'List' + #region Check name + //if (type1.Name == null) throw new IllFormedSemanticModelException("A CSharpType was founded with a null 'Name' field.", type1); + //if (type2.Name == null) throw new IllFormedSemanticModelException("A CSharpType was founded with a null 'Name' field.", type2); + //It seems array types always have null names + if (type1.Name != null ^ type2.Name != null) return false; + if (type1.Name != null && type2.Name != null && + !type1.Name.Equals(type2.Name)) return false; + #endregion + #region Check containing type and namespace + if (type1.ContainingType != null ^ type2.ContainingType != null) return false; + if (type1.ContainingType != null && type2.ContainingType != null) { + if (!TypesAreEquivalent(type1.ContainingType, type2.ContainingType)) return false; + } else { + if (type1.ContainingNamespace != null ^ type2.ContainingNamespace != null) return false; + if (type1.ContainingNamespace != null && type2.ContainingNamespace != null && + !type1.ContainingNamespace.Equals(type2.ContainingNamespace)) return false; + } + #endregion + #region Check type parameters + if (type1.TypeParameters != null ^ type2.TypeParameters != null) return false; + if (type1.TypeParameters != null && type2.TypeParameters != null && + type1.TypeParameters.Count != type2.TypeParameters.Count) return false; + #endregion + #region Check type arguments + + if (type1.TypeArguments != null ^ type2.TypeArguments != null) return false; + if (type1.TypeArguments != null && type2.TypeArguments != null && + !TypeListsAreEquivalent(type1.TypeArguments, type2.TypeArguments)) return false; + #endregion + #region Check array + if (type1.IsArray ^ type2.IsArray) return false; + if (type1.IsArray && type2.IsArray) + return TypesAreEquivalent(type1.ElementType, type2.ElementType); + #endregion + #region Check pointer + if (type1.IsPointer ^ type2.IsPointer) return false; + if (type1.IsPointer && type2.IsPointer) + return TypesAreEquivalent(type1.ElementType, type2.ElementType); + #endregion + if (type1.IsClass != type2.IsClass + || type1.IsStruct != type2.IsStruct + || type1.IsStatic != type2.IsStatic + || type1.IsValueType != type2.IsValueType) + return false; + return true; + } + /// + /// Checks if two type lists are equivalent. + /// + /// Thrown if the semantic member/type has fields that are null or empty and are required to not be so for the proper operation of this method. + [Pure] + public static bool TypeListsAreEquivalent(IEnumerable typeList1, IEnumerable typeList2) { + Contract.Requires(typeList1 != null); + Contract.Requires(typeList2 != null); + return EnumerablesAreEquivalent(typeList1, typeList2, (t1, t2) => TypesAreEquivalent(t1, t2)); + } + [Pure] + public static CSharpMember Uninstantiate(this CSharpMember member) { + Contract.Requires(member != null); + Contract.Ensures(Contract.Result() != null); + Contract.Ensures(member.IsMethod == Contract.Result().IsMethod); + Contract.Ensures(member.IsConstructor == Contract.Result().IsConstructor); + Contract.Ensures(member.IsProperty == Contract.Result().IsProperty); + Contract.Ensures(member.IsIndexer == Contract.Result().IsIndexer); + + var uninstantiatedMember = member; + + var definingMember = member.DefiningMember; + while (definingMember != null) { + uninstantiatedMember = definingMember; + definingMember = definingMember.DefiningMember; + } + + Contract.Assume(member.IsMethod == uninstantiatedMember.IsMethod); + Contract.Assume(member.IsConstructor == uninstantiatedMember.IsConstructor); + Contract.Assume(member.IsProperty == uninstantiatedMember.IsProperty); + Contract.Assume(member.IsIndexer == uninstantiatedMember.IsIndexer); + return uninstantiatedMember; + } + [Pure] + public static CSharpType Uninstantiate(this CSharpType type) { + Contract.Requires(type != null); + Contract.Ensures(Contract.Result() != null); + + var uninstantiatedType = type; + + var definingType = type.DefiningType; + while (definingType != null) { + uninstantiatedType = definingType; + definingType = definingType.DefiningType; + } + + return uninstantiatedType; + } + } + + [Serializable] + public class IllFormedSemanticModelException : Exception { + public CSharpMember BadMember { get; private set; } + public CSharpType BadType { get; private set; } + public CSharpParameter BadParameter { get; private set; } + public CSharpNamespace BadNamespace { get; private set; } + public CSharpKind Kind { get; private set; } + + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant((BadMember != null) == (Kind == CSharpKind.CSharpMember)); + Contract.Invariant((BadType != null) == (Kind == CSharpKind.CSharpType)); + Contract.Invariant((BadParameter != null) == (Kind == CSharpKind.CSharpParameter)); + Contract.Invariant((BadNamespace != null) == (Kind == CSharpKind.CSharpNamespace)); + } + + public IllFormedSemanticModelException() { } + public IllFormedSemanticModelException(string message) : base(message) { } + public IllFormedSemanticModelException(string message, Exception inner) : base(message, inner) { } + public IllFormedSemanticModelException(string message, CSharpType badType) : base(message) { + Contract.Requires(badType != null); + + BadType = badType; + Kind = CSharpKind.CSharpType; + } + public IllFormedSemanticModelException(string message, CSharpMember badMember) : base(message) { + Contract.Requires(badMember != null); + + BadMember = badMember; + Kind = CSharpKind.CSharpMember; + } + public IllFormedSemanticModelException(string message, CSharpParameter badParameter) : base(message) { + Contract.Requires(badParameter != null); + + BadParameter = badParameter; + Kind = CSharpKind.CSharpParameter; + } + public IllFormedSemanticModelException(string message, CSharpNamespace badNamespace) : base(message) { + Contract.Requires(badNamespace != null); + + BadNamespace = badNamespace; + Kind = CSharpKind.CSharpNamespace; + } + protected IllFormedSemanticModelException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base(info, context) { } + } + + public enum CSharpKind { + None, + CSharpMember, + CSharpType, + CSharpParameter, + CSharpNamespace + } } \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/Sources/Contracts/ContractsProvider.cs b/Microsoft.Research/ContractAdornments/CSharp/Contracts/ContractsProvider.cs similarity index 90% rename from Microsoft.Research/ContractAdornments/Sources/Contracts/ContractsProvider.cs rename to Microsoft.Research/ContractAdornments/CSharp/Contracts/ContractsProvider.cs index a173f94d..50297ae9 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Contracts/ContractsProvider.cs +++ b/Microsoft.Research/ContractAdornments/CSharp/Contracts/ContractsProvider.cs @@ -27,11 +27,12 @@ using System.Diagnostics; using System.Linq; using Microsoft.Cci.MutableContracts; +using ContractAdornments.Interfaces; namespace ContractAdornments { - public class ContractsProvider { - readonly ProjectTracker _projectTracker; - CodeContractAwareHostEnvironment Host { + public class ContractsProvider : IContractsProvider { + readonly IProjectTracker _projectTracker; + INonlockingHost Host { get { Contract.Requires(_projectTracker.Host != null); Contract.Ensures(Contract.Result() != null); @@ -55,7 +56,7 @@ void ObjectInvariant() { Contract.Invariant(Host != null); } - public ContractsProvider(ProjectTracker projectTracker) { + public ContractsProvider(IProjectTracker projectTracker) { Contract.Requires(projectTracker != null); //Grab a pointer back to our project tracker @@ -70,7 +71,7 @@ public ContractsProvider(ProjectTracker projectTracker) { public void Clear() { //host = null; - VSServiceProvider.Current.Logger.WriteToLog("Clearing all caches in ContractsProvider."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Clearing all caches in ContractsProvider."); //Clear caches _semanticAssemblysToCCIAssemblys.Clear(); @@ -91,7 +92,7 @@ public bool TryGetAssemblyReference(CSharpAssembly semanticAssembly, out IAssemb } #endregion #region Check cache - if (VSServiceProvider.Current.VSOptionsPage.Caching) + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) if (_semanticAssemblysToCCIAssemblys.TryGetValue(semanticAssembly, out cciAssembly)) return cciAssembly != Dummy.AssemblyReference && cciAssembly != null; #endregion @@ -125,7 +126,7 @@ public bool TryGetAssemblyReference(CSharpAssembly semanticAssembly, out IAssemb goto ReturnTrue; } } else - VSServiceProvider.Current.Logger.WriteToLog("Assembly identity for the project: " + _projectTracker.ProjectName + " was null."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Assembly identity for the project: " + _projectTracker.ProjectName + " was null."); #endregion #region Build assembly reference if (semanticAssembly.Name == null || string.IsNullOrWhiteSpace(semanticAssembly.Name.Text)) goto ReturnFalseNoOutput; // because we have no name. @@ -162,16 +163,16 @@ public bool TryGetAssemblyReference(CSharpAssembly semanticAssembly, out IAssemb #endregion #region ReturnTrue: ReturnTrue: - if (VSServiceProvider.Current.VSOptionsPage.Caching) + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) _semanticAssemblysToCCIAssemblys[semanticAssembly] = cciAssembly; EnsureAssemblyIsLoaded(semanticAssembly, ref cciAssembly); return true; #endregion #region ReturnFalse: ReturnFalse: - VSServiceProvider.Current.Logger.WriteToLog("Failed to build assembly reference for: " + semanticAssembly.Name.Text); + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to build assembly reference for: " + semanticAssembly.Name.Text); ReturnFalseNoOutput: - if (VSServiceProvider.Current.VSOptionsPage.Caching) + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) _semanticAssemblysToCCIAssemblys[semanticAssembly] = Dummy.AssemblyReference; return false; #endregion @@ -223,13 +224,13 @@ public bool TryGetMethodContract(CSharpMember semanticMethod, out IMethodContrac return true; } else { //No need, detailed logs are written at all code paths in "TryGetMethodContract" - //VSServiceProvider.Current.Logger.WriteToLog("Failed to get method contracts for: " + cciMethod.Name); + //ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get method contracts for: " + cciMethod.Name); } } else { methodContract = null; if (semanticMethod.Name != null) { - VSServiceProvider.Current.Logger.WriteToLog("Failed to get CCI reference for: " + semanticMethod.Name.Text); + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get CCI reference for: " + semanticMethod.Name.Text); } } return false; @@ -253,20 +254,20 @@ public bool TryGetMethodContract(IMethodReference method, out IMethodContract me methodContract = ContractHelper.GetMethodContractForIncludingInheritedContracts(Host, resolvedMethod); if (methodContract == null) { methodContract = ContractDummy.MethodContract; - VSServiceProvider.Current.Logger.WriteToLog(String.Format("Did not find any method contract(s) for '{0}'", method.Name)); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Did not find any method contract(s) for '{0}'", method.Name)); } else { - VSServiceProvider.Current.Logger.WriteToLog( + ContractsPackageAccessor.Current.Logger.WriteToLog( String.Format("Got method contract(s) for '{0}': {1} preconditions, {2} postconditions", method.Name, Microsoft.Cci.IteratorHelper.EnumerableCount(methodContract.Preconditions), Microsoft.Cci.IteratorHelper.EnumerableCount(methodContract.Postconditions))); } } else { - VSServiceProvider.Current.Logger.WriteToLog(String.Format("Method '{0}' resolved to dummy", method.Name)); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Method '{0}' resolved to dummy", method.Name)); } } catch (NullReferenceException) { methodContract = null; - VSServiceProvider.Current.Logger.WriteToLog(String.Format("NullReferenceException thrown when getting contracts for '{0}'", method.Name)); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("NullReferenceException thrown when getting contracts for '{0}'", method.Name)); } return methodContract != null; } @@ -293,12 +294,12 @@ public bool TryGetMethodContractSafe(CSharpMember semanticMehod, out IMethodCont catch (IllFormedSemanticModelException) { return false; } catch (InvalidOperationException e) { - if (!e.Message.Contains(VSServiceProvider.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) + if (!e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) throw e; else return false; } catch (System.Runtime.InteropServices.COMException e) { - if (!e.Message.Contains(VSServiceProvider.COMExceptionMessage_BindingFailed)) + if (!e.Message.Contains(ContractsPackageAccessor.COMExceptionMessage_BindingFailed)) throw e; else return false; @@ -319,7 +320,7 @@ public bool TryGetMethodReference(CSharpMember semanticMethod, out IMethodRefere } #endregion #region Check cache - if (VSServiceProvider.Current.VSOptionsPage.Caching) + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) if (_semanticMembersToCCIMethods.TryGetValue(semanticMethod, out cciMethod)) return (!(cciMethod is Dummy)) && cciMethod != null; #endregion @@ -375,7 +376,7 @@ public bool TryGetMethodReference(CSharpMember semanticMethod, out IMethodRefere #region ReturnFalse: ReturnFalse: cciMethod = Dummy.MethodReference; - if (VSServiceProvider.Current.VSOptionsPage.Caching) + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) _semanticMembersToCCIMethods[semanticMethod] = cciMethod; return false; #endregion @@ -397,7 +398,7 @@ public bool TryGetNamespaceReference(CSharpNamespace semanticNamespace, IAssembl goto ReturnTrue; } } catch (InvalidOperationException e) { //For some reason, an InvalidOperationException may get thrown. - if (e.Message.Contains(VSServiceProvider.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) + if (e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) goto ReturnFalse; else throw e; @@ -490,7 +491,7 @@ public bool TryGetParameterReference(CSharpParameter semanticParameter, ushort i ReturnFalse: if (semanticParameter.Name != null) { - VSServiceProvider.Current.Logger.WriteToLog("Failed to build parameter reference for: " + semanticParameter.Name.Text); + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to build parameter reference for: " + semanticParameter.Name.Text); } return false; #endregion @@ -595,7 +596,7 @@ public bool TryGetPropertyAccessorReferences(CSharpMember semanticProperty, out ReturnFalse: if (semanticProperty.Name != null) { - VSServiceProvider.Current.Logger.WriteToLog("Failed to build accessor references for: " + semanticProperty.Name.Text); + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to build accessor references for: " + semanticProperty.Name.Text); } _semanticPropertiesToCCIAccessorMethods[semanticProperty] = new Tuple(Dummy.MethodReference, Dummy.MethodReference); return false; @@ -612,7 +613,7 @@ public bool TryGetTypeReference(CSharpType semanticType, IAssemblyReference cciA } #endregion #region Check cache - if (VSServiceProvider.Current.VSOptionsPage.Caching) + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) if (_semanticTypesToCCITypes.TryGetValue(semanticType, out cciType)) return cciType != null && cciType != Dummy.TypeReference; #endregion @@ -730,14 +731,14 @@ public bool TryGetTypeReference(CSharpType semanticType, IAssemblyReference cciA #endregion #region ReturnTrue: ReturnTrue: - if (VSServiceProvider.Current.VSOptionsPage.Caching) + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) _semanticTypesToCCITypes[semanticType] = cciType; return true; #endregion #region ReturnFalse: ReturnFalse: - VSServiceProvider.Current.Logger.WriteToLog("Failed to build type reference for: " + (semanticType.Name != null ? semanticType.Name.Text : semanticType.ToString())); - if (VSServiceProvider.Current.VSOptionsPage.Caching) + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to build type reference for: " + (semanticType.Name != null ? semanticType.Name.Text : semanticType.ToString())); + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) _semanticTypesToCCITypes[semanticType] = Dummy.TypeReference; return false; #endregion @@ -753,7 +754,7 @@ public bool TryGetTypeReference(CSharpType semanticType, out ITypeReference cciT } #endregion #region Check cache - if (VSServiceProvider.Current.VSOptionsPage.Caching) + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) if (_semanticTypesToCCITypes.TryGetValue(semanticType, out cciType)) return cciType != null && cciType != Dummy.TypeReference; #endregion @@ -765,7 +766,7 @@ public bool TryGetTypeReference(CSharpType semanticType, out ITypeReference cciT return TryGetTypeReference(semanticType, cciAssembly, out cciType); #region ReturnFalse: ReturnFalse: - if (VSServiceProvider.Current.VSOptionsPage.Caching) + if (ContractsPackageAccessor.Current.VSOptionsPage.Caching) _semanticTypesToCCITypes[semanticType] = Dummy.TypeReference; return false; #endregion @@ -786,23 +787,23 @@ void EnsureAssemblyIsLoaded(CSharpAssembly semanticAssembly, ref IAssemblyRefere if (assembly == Dummy.Assembly) { var location = assemblyReference.AssemblyIdentity.Location; if (File.Exists(location)) { - VSServiceProvider.Current.Logger.WriteToLog(String.Format("Calling LoadUnitFrom on assembly '{0}' for future resolution.", location)); - VSServiceProvider.Current.Logger.WriteToLog(String.Format("core assembly: '{0}'", Host.CoreAssemblySymbolicIdentity.ToString())); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Calling LoadUnitFrom on assembly '{0}' for future resolution.", location)); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("core assembly: '{0}'", Host.CoreAssemblySymbolicIdentity.ToString())); assembly = Host.LoadUnitFrom(location) as IAssembly; if (assembly != null){ assemblyReference = assembly; - if(VSServiceProvider.Current.VSOptionsPage.Caching) + if(ContractsPackageAccessor.Current.VSOptionsPage.Caching) _semanticAssemblysToCCIAssemblys[semanticAssembly] = assembly; } else{ - VSServiceProvider.Current.Logger.WriteToLog("Warning: Found a unit at '" + location + "', but it wasn't an assembly!"); + ContractsPackageAccessor.Current.Logger.WriteToLog("Warning: Found a unit at '" + location + "', but it wasn't an assembly!"); } } else{ - VSServiceProvider.Current.Logger.WriteToLog("Assembly not found at: '" + location + "'. This could be because the assembly hasn't been built yet."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Assembly not found at: '" + location + "'. This could be because the assembly hasn't been built yet."); } } else { assemblyReference = assembly; - if(VSServiceProvider.Current.VSOptionsPage.Caching) + if(ContractsPackageAccessor.Current.VSOptionsPage.Caching) _semanticAssemblysToCCIAssemblys[semanticAssembly] = assembly; } } diff --git a/Microsoft.Research/ContractAdornments/Sources/Extensions.cs b/Microsoft.Research/ContractAdornments/CSharp/Extensions.cs similarity index 86% rename from Microsoft.Research/ContractAdornments/Sources/Extensions.cs rename to Microsoft.Research/ContractAdornments/CSharp/Extensions.cs index 60512772..5767ec47 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Extensions.cs +++ b/Microsoft.Research/ContractAdornments/CSharp/Extensions.cs @@ -12,18 +12,16 @@ // // THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -using Microsoft.VisualStudio.Text; -using Microsoft.RestrictedUsage.CSharp.Core; -using Microsoft.VisualStudio.Text.Editor; -using Microsoft.RestrictedUsage.CSharp.Syntax; -using Microsoft.RestrictedUsage.CSharp.Extensions; -using System.Diagnostics.Contracts; using System; -using System.Linq; -using System.Collections.Generic; -using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; using Adornments; -using ContractAdornments.OptionsPage; +using ContractAdornments.Interfaces; +using Microsoft.RestrictedUsage.CSharp.Core; +using Microsoft.RestrictedUsage.CSharp.Extensions; +using Microsoft.RestrictedUsage.CSharp.Syntax; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; namespace ContractAdornments { static class HelperExtensions { @@ -75,15 +73,6 @@ public static int GetPositionFromLineColumn(this ITextSnapshot snapshot, int lin return textline.Start.Position + column; } - public static void RefreshLineTransformer(this ITextView textView) { - Contract.Requires(textView != null); - - if (textView.TextViewLines == null) return; - var line = textView.TextViewLines.FirstVisibleLine; - if (line == null) return; - textView.DisplayTextLineContainingBufferPosition(line.Start, line.Top - textView.ViewportTop, ViewRelativePosition.Top); - } - public static string GetName(this PropertyDeclarationNode @this, ITextSnapshot snapshot) { Contract.Requires(@this != null); Contract.Requires(snapshot != null); @@ -123,9 +112,32 @@ public static string GetName(this TypeBaseNode @this, ITextSnapshot snapshot) } return null; } + public static bool IsModelReady(this ParseTree parseTree) { + Contract.Requires(parseTree != null); + + try { + if (parseTree == null) + return false; + + var rootNode = parseTree.RootNode; + + } catch (InvalidOperationException e) { + if (e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) + return false; + else + throw e; + } catch (COMException e) { + if (e.Message.Contains(ContractsPackageAccessor.COMExceptionMessage_BindingFailed)) + return false; + else + throw e; + } + + return true; + } } public static class AdornmentOptionsHelper { - public static AdornmentOptions GetAdornmentOptions(ContractOptionsPage options) { + public static AdornmentOptions GetAdornmentOptions(IContractOptionsPage options) { var result = AdornmentOptions.None; if (options == null) diff --git a/Microsoft.Research/ContractAdornments/CSharp/Inheritance/InheritanceTracker.cs b/Microsoft.Research/ContractAdornments/CSharp/Inheritance/InheritanceTracker.cs new file mode 100644 index 00000000..ded19ecc --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp/Inheritance/InheritanceTracker.cs @@ -0,0 +1,625 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Linq; +using System.Text; +using Microsoft.RestrictedUsage.CSharp; +using Microsoft.RestrictedUsage.CSharp.Compiler; +using Microsoft.RestrictedUsage.CSharp.Extensions; +using Microsoft.RestrictedUsage.CSharp.Semantics; +using Microsoft.RestrictedUsage.CSharp.Syntax; +using Microsoft.Cci.Contracts; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Outlining; +using Adornments; +using Microsoft.Cci; +using System.Threading.Tasks; +using System.Threading; +using System.Runtime.InteropServices; +using UtilitiesNamespace; +using System.Collections.ObjectModel; + +namespace ContractAdornments { + internal sealed class InheritanceTracker { + public const string InheritanceTrackerKey = "InheritanceTracker"; + public const double DelayOnVSModelFailedBeforeTryingAgain = 500d; + public const double DelayAfterMembersRevalutation = 500d; + + readonly TextViewTracker _textViewTracker; + readonly AdornmentManager _adornmentManager; + + readonly Queue> _methodsNeedingContractLookup; + readonly Queue, PropertyDeclarationNode>> _propertiesNeedingContractLookup; + readonly ISet _methodKeys; + readonly ISet _propertyKeys; + + int semanticModelsFetchedCounter = 0; + bool trackingNumberOfFetchedSemanticModels = false; + + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(_textViewTracker != null); + Contract.Invariant(_adornmentManager != null); + Contract.Invariant(_methodsNeedingContractLookup != null); + Contract.Invariant(_propertiesNeedingContractLookup != null); + Contract.Invariant(_methodKeys != null); + Contract.Invariant(_propertyKeys != null); + } + + #region Static getters + [ContractVerification(false)] + public static InheritanceTracker GetOrCreateAdornmentTracker(TextViewTracker textViewTracker) { + Contract.Requires(textViewTracker != null); + Contract.Ensures(Contract.Result() != null); + return textViewTracker.TextView.Properties.GetOrCreateSingletonProperty(InheritanceTrackerKey, delegate { return new InheritanceTracker(textViewTracker); }); + } + #endregion + + private InheritanceTracker(TextViewTracker textViewTracker) { + Contract.Requires(textViewTracker != null); + Contract.Requires(textViewTracker.TextView != null); + if (!AdornmentManager.TryGetAdornmentManager(textViewTracker.TextView, "InheritanceAdornments", out _adornmentManager)) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Inheritance adornment layer not instantiated."); + throw new InvalidOperationException("Inheritance adornment layer not instantiated."); + } + + _methodsNeedingContractLookup = new Queue>(); + _propertiesNeedingContractLookup = new Queue, PropertyDeclarationNode>>(); + _methodKeys = new HashSet(); + _propertyKeys = new HashSet(); + + _textViewTracker = textViewTracker; + _textViewTracker.LatestCompilationChanged += OnLatestCompilationChanged; + _textViewTracker.LatestSourceFileChanged += OnLatestSourceFileChanged; + _textViewTracker.ProjectTracker.BuildDone += OnBuildDone; + _textViewTracker.TextView.Closed += OnClosed; + } + + void OnClosed(object sender, EventArgs e) { + _textViewTracker.ProjectTracker.BuildDone -= OnBuildDone; + _textViewTracker.LatestSourceFileChanged -= OnLatestSourceFileChanged; + _textViewTracker.LatestCompilationChanged -= OnLatestCompilationChanged; + } + + void OnBuildDone() { + ContractsPackageAccessor.Current.Logger.WriteToLog("Removing all old adornments because of a new build for text file: " + _textViewTracker.FileName); + _adornmentManager.Adornments.Clear(); + _methodsNeedingContractLookup.Clear(); + _propertiesNeedingContractLookup.Clear(); + _methodKeys.Clear(); + _propertyKeys.Clear(); + } + + void OnLatestSourceFileChanged(object sender, LatestSourceFileChangedEventArgs e) { + + //Is the source file change significant? + if (e.WasLatestSourceFileStale == true) { + + //Revaluate the inheritance adornments on the text view when we next have focus + if (ContractsPackageAccessor.Current.VSOptionsPage.InheritanceOnMethods) + ContractsPackageAccessor.Current.QueueWorkItem(() => RevaluateMethodInheritanceAdornments(this), () => _textViewTracker.TextView.HasAggregateFocus); + if (ContractsPackageAccessor.Current.VSOptionsPage.InheritanceOnProperties) + ContractsPackageAccessor.Current.QueueWorkItem(() => RevaluatePropertyInheritanceAdornments(this), () => _textViewTracker.TextView.HasAggregateFocus); + } + } + void OnLatestCompilationChanged(object sender, LatestCompilationChangedEventArgs e) { + + Contract.Requires(e.LatestCompilation != null); + + //Do any methods need their contract information looked up? + if (ContractsPackageAccessor.Current.VSOptionsPage.InheritanceOnMethods && _methodsNeedingContractLookup.Count > 0) { + + //Recursively look up the needed contract information + ContractsPackageAccessor.Current.Logger.WriteToLog("Attempting to lookup contracts for " + _methodsNeedingContractLookup.Count + " methods."); + ContractsPackageAccessor.Current.QueueWorkItem(() => RecursivelyLookupContractsForMethods(this), () => _textViewTracker.TextView.HasAggregateFocus); + } + + //Do any properties need their contract information looked up? + if (ContractsPackageAccessor.Current.VSOptionsPage.InheritanceOnProperties && _propertiesNeedingContractLookup.Count > 0) { + + //Recursively look up the needed contract information + ContractsPackageAccessor.Current.Logger.WriteToLog("Attempting to lookup contracts for " + _propertiesNeedingContractLookup.Count + " properties."); + ContractsPackageAccessor.Current.QueueWorkItem(() => RecursivelyLookupContractsForProperties(this), () => _textViewTracker.TextView.HasAggregateFocus); + } + } + + static void RevaluateMethodInheritanceAdornments(InheritanceTracker @this) { + Contract.Requires(@this != null); + + var workingSnapshot = @this._textViewTracker.TextView.TextSnapshot; //Save the current snapshot so it doesn't change while you work, we assume that the snapshot is the same as the source file. + + //Check if model is ready + var parseTree = @this._textViewTracker.LatestSourceFile == null ? null : @this._textViewTracker.LatestSourceFile.GetParseTree(); + if (parseTree == null || !parseTree.IsModelReady()) { + @this._textViewTracker.IsLatestSourceFileStale = true; + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + return; + } + + //Collect all the methods in this text view + var methodCollector = new MethodCollector(workingSnapshot); + methodCollector.Visit(parseTree.RootNode); + var methods = methodCollector.GetMethods(); + + //Calculate which methods are new + var newKeys = new List(methods.Keys.Where((k) => !@this._methodKeys.Contains(k))); + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Found {0} new methods.", newKeys.Count)); + + //Update our method keys + @this._methodKeys.Clear(); + @this._methodKeys.AddAll(methods.Keys); + + ContractsPackageAccessor.Current.QueueWorkItem(() => { + if (@this._textViewTracker.TextView.IsClosed) + return; + var adornmentKeys = new List(@this._adornmentManager.Adornments.Keys); + foreach (var key in adornmentKeys) { + var keyAsString = key as string; + if (keyAsString == null) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Unexpected: A key in the AdornmentManager wasn't a string! key: " + key.ToString()); + continue; + } + if (!@this._methodKeys.Contains(key) && keyAsString.EndsWith(MethodCollector.MethodTagSuffix)) { + @this._adornmentManager.RemoveAdornment(key); + ContractsPackageAccessor.Current.Logger.WriteToLog("Removing obsolete method adornment with tag: " + keyAsString); + } + } + }, () => @this._textViewTracker.TextView.IsClosed || @this._textViewTracker.TextView.HasAggregateFocus); + + //Create placeholder adornments for our new methods and queue them for contract lookup + ContractsPackageAccessor.Current.QueueWorkItem(() => { + foreach (var key in newKeys) { + MethodDeclarationNode method; + if (methods.TryGetValue(key, out method)) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Creating placeholder adornment and enqueueing for future contract lookup for: " + key.ToString()); + #region Create placeholder adornment + //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text + var snapshotSpan = new SnapshotSpan(method.GetSpan().Convert(workingSnapshot).Start, 1); + var trackingSpan = workingSnapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); + var ops = AdornmentOptionsHelper.GetAdornmentOptions(ContractsPackageAccessor.Current.VSOptionsPage); + @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, ContractsPackageAccessor.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), key); + #endregion + @this._methodsNeedingContractLookup.Enqueue(new KeyValuePair(key, method)); + } + } + }); + + //Most likely we've changed something (and this is a pretty cheap call), so let's ask for a refresh + Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(@this._adornmentManager.QueueRefreshLineTransformer), DelayAfterMembersRevalutation); + + //Ask for the new VS model so we can look up contracts + Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(ContractsPackageAccessor.Current.AskForNewVSModel), DelayAfterMembersRevalutation); + } + static void RevaluatePropertyInheritanceAdornments(InheritanceTracker @this) { + Contract.Requires(@this != null); + + var workingSnapshot = @this._textViewTracker.TextView.TextSnapshot; //Save the current snapshot so it doesn't change while you work, we assume that the snapshot is the same as the source file. + + //Check if model is ready + var parseTree = @this._textViewTracker.LatestSourceFile == null ? null : @this._textViewTracker.LatestSourceFile.GetParseTree(); + if (parseTree == null || !parseTree.IsModelReady()) { + @this._textViewTracker.IsLatestSourceFileStale = true; + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + return; + } + + //Collect all the properties in this text view + var propertyCollector = new PropertyCollector(workingSnapshot); + propertyCollector.Visit(parseTree.RootNode); + var properties = propertyCollector.GetProperties(); + + //Get our property keys + var keys = new List(); + var newTuples = new List>(); + foreach (var tuple in properties.Keys) { + if (tuple.Item1 != null) + keys.Add(tuple.Item1); + if (tuple.Item2 != null) + keys.Add(tuple.Item2); + if (!(@this._propertyKeys.Contains(tuple.Item1) && @this._propertyKeys.Contains(tuple.Item1))) + newTuples.Add(tuple); + } + + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Found {0} new properties.", newTuples.Count)); + + //Update our property keys + @this._propertyKeys.Clear(); + @this._propertyKeys.AddAll(keys); + + ContractsPackageAccessor.Current.QueueWorkItem(() => { + if (@this._textViewTracker.TextView.IsClosed) + return; + var adornmentKeys = new List(@this._adornmentManager.Adornments.Keys); + foreach (var key in adornmentKeys) { + var keyAsString = key as string; + if (keyAsString == null) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Unexpected: A key in the AdornmentManager wasn't a string! key: " + key.ToString()); + continue; + } + if (!@this._propertyKeys.Contains(key) && keyAsString.EndsWith(PropertyCollector.PropertyTagSuffix)) { + @this._adornmentManager.RemoveAdornment(key); + ContractsPackageAccessor.Current.Logger.WriteToLog("Removing obsolete property adornment with tag: " + keyAsString); + } + } + }, () => @this._textViewTracker.TextView.IsClosed || @this._textViewTracker.TextView.HasAggregateFocus); + + //Create placeholder adornments for our new properties and queue them for contract lookup + ContractsPackageAccessor.Current.QueueWorkItem(() => { + foreach (var tuple in newTuples) { + PropertyDeclarationNode property; + if (properties.TryGetValue(tuple, out property)) { + if (tuple.Item1 != null && tuple.Item2 != null && + property.GetAccessorDeclaration.GetSpan().Start.Line == property.SetAccessorDeclaration.GetSpan().Start.Line) + { + // set and get on same line, don't add adornment + ContractsPackageAccessor.Current.Logger.WriteToLog("Skipping adornments for " + property.GetName(workingSnapshot) + " because get and set are on same line"); + } + else + { + ContractsPackageAccessor.Current.Logger.WriteToLog("Creating placeholder adornment and enqueueing for future contract lookup for: " + property.GetName(workingSnapshot)); + if (tuple.Item1 != null) + { + #region Create getter placeholder adornment + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("\t(Creating getter placeholder with tag {0})", tuple.Item1)); + //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text + var snapshotSpan = new SnapshotSpan(property.GetAccessorDeclaration.GetSpan().Convert(workingSnapshot).Start, 1); + var trackingSpan = workingSnapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); + var ops = AdornmentOptionsHelper.GetAdornmentOptions(ContractsPackageAccessor.Current.VSOptionsPage); + @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, ContractsPackageAccessor.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), tuple.Item1); + #endregion + } + if (tuple.Item2 != null) + { + #region Create setter placeholder adornment + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("\t(Creating setter placeholder with tag {0})", tuple.Item2)); + //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text + var snapshotSpan = new SnapshotSpan(property.SetAccessorDeclaration.GetSpan().Convert(workingSnapshot).Start, 1); + var trackingSpan = workingSnapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); + var ops = AdornmentOptionsHelper.GetAdornmentOptions(ContractsPackageAccessor.Current.VSOptionsPage); + @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, ContractsPackageAccessor.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), tuple.Item2); + #endregion + } + @this._propertiesNeedingContractLookup.Enqueue(new KeyValuePair, PropertyDeclarationNode>(tuple, property)); + } + } + } + }); + + //Most likely we've changed something (and this is a pretty cheap call), so let's ask for a refresh + Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(@this._adornmentManager.QueueRefreshLineTransformer, () => @this._textViewTracker.TextView.HasAggregateFocus), DelayAfterMembersRevalutation); + + //Ask for the new VS model so we can look up contracts + Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(ContractsPackageAccessor.Current.AskForNewVSModel, () => @this._textViewTracker.TextView.HasAggregateFocus), DelayAfterMembersRevalutation); + } + + static void RecursivelyLookupContractsForMethods(InheritanceTracker @this) { + Contract.Requires(@this != null); + + #region Dequeue + if (@this._methodsNeedingContractLookup.Count < 1) + return; + var methodPair = @this._methodsNeedingContractLookup.Dequeue(); + var method = methodPair.Value; + var tag = methodPair.Key; + #endregion + try { + ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Attempting to lookup contracts for '{0}'", tag.ToString())); + var comp = @this._textViewTracker.LatestCompilation; + if (comp == null) { + ContractsPackageAccessor.Current.Logger.WriteToLog("No LatestCompilation, waiting for a new semantic model."); + @this._textViewTracker.IsLatestCompilationStale = true; + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + @this.semanticModelsFetchedCounter++; + goto RequeueAndAbort; + } + #region Get semantic method from syntactic method + CSharpMember semanticMethod = null; + semanticMethod = comp.GetMemberForMethodDeclaration(method); + if (semanticMethod == null) { + if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 3) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic method from syntactic method, waiting for a new semantic model."); + @this._textViewTracker.IsLatestCompilationStale = true; + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + @this.semanticModelsFetchedCounter++; + goto RequeueAndAbort; + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic method from syntactic method. Too many semantic models have already been fetched, skipping this method..."); + goto Continue; + } + } + #endregion + #region Try get the method that this method is inherited from + CSharpMember inheritedFromMethod; + if (!TryGetIheritedFromMember(semanticMethod, method.Parent as TypeDeclarationNode, out inheritedFromMethod)) { + goto Continue; + } + #endregion + #region Uninstantiated method + semanticMethod = semanticMethod.Uninstantiate(); + #endregion + #region Get our tool tip + var toolTip = ""; + if (!semanticMethod.IsAbstract && !semanticMethod.ContainingType.IsInterface) + toolTip = String.Format("Contracts inherited from {0}.", inheritedFromMethod.ContainingType.Name.Text); + #endregion + #region Try get method contracts and update adornment + IMethodContract contracts = null; + if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(inheritedFromMethod, out contracts)) { + var possibleAdornment = @this._adornmentManager.GetAdornment(tag); + if (possibleAdornment != null) { + var adornment = possibleAdornment as ContractAdornment; + if (adornment != null) { + adornment.SetContracts(contracts, toolTip); + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping method..."); + } + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment not found, skipping method..."); + } + } + #endregion + } + #region Exception handeling + catch (IllFormedSemanticModelException e) { + if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 2) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Error: An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Asking for a new semantic model..."); + @this._textViewTracker.IsLatestCompilationStale = true; + ContractsPackageAccessor.Current.AskForNewVSModel(); + @this.semanticModelsFetchedCounter++; + goto RequeueAndAbort; + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Too many semantic models have been fetched, skipping this method..."); + goto Continue; + } + } catch (InvalidOperationException e) { + if (e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) { + if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) { + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); + @this._textViewTracker.IsLatestCompilationStale = true; + ContractsPackageAccessor.Current.AskForNewVSModel(); + @this.semanticModelsFetchedCounter++; + goto RequeueAndAbort; + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this method..."); + goto Continue; + } + } else + throw e; + } catch (COMException e) { + if (e.Message.Contains(ContractsPackageAccessor.COMExceptionMessage_BindingFailed)) { + if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) { + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); + @this._textViewTracker.IsLatestCompilationStale = true; + ContractsPackageAccessor.Current.AskForNewVSModel(); + @this.semanticModelsFetchedCounter++; + goto RequeueAndAbort; + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this method..."); + goto Continue; + } + } else + throw e; + } + #endregion + Continue: + ContractsPackageAccessor.Current.QueueWorkItem(() => RecursivelyLookupContractsForMethods(@this)); + return; + RequeueAndAbort: + @this._methodsNeedingContractLookup.Enqueue(methodPair); + return; + } + static void RecursivelyLookupContractsForProperties(InheritanceTracker @this) { + Contract.Requires(@this != null); + + #region Dequeue + if (@this._propertiesNeedingContractLookup.Count < 1) + return; + var propertyPair = @this._propertiesNeedingContractLookup.Dequeue(); + var property = propertyPair.Value; + var tagTuple = propertyPair.Key; + #endregion + try { + var comp = @this._textViewTracker.LatestCompilation; + if (comp == null) { + ContractsPackageAccessor.Current.Logger.WriteToLog("No LatestCompilation, waiting for a new semantic model."); + @this._textViewTracker.IsLatestCompilationStale = true; + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + @this.semanticModelsFetchedCounter++; + goto RequeueAndAbort; + } + #region Get semantic property from syntactic property + CSharpMember semanticProperty = null; + semanticProperty = comp.GetMemberForPropertyDeclaration(property); + if (semanticProperty == null) { + if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 3) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic property from syntactic property, waiting for a new semantic model."); + @this._textViewTracker.IsLatestCompilationStale = true; + Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); + @this.semanticModelsFetchedCounter++; + goto RequeueAndAbort; + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic property from syntactic property. Too many semantic models have already been fetched, skipping this property..."); + goto Continue; + } + } + #endregion + #region Try get the property that this property is inherited from + CSharpMember inheritedFromProperty; + if (!TryGetIheritedFromMember(semanticProperty, property.Parent as TypeDeclarationNode, out inheritedFromProperty)) { + goto Continue; + } + #endregion + #region Uninstantiated property + semanticProperty = semanticProperty.Uninstantiate(); + #endregion + #region Get our tool tip + var toolTip = ""; + if (!semanticProperty.IsAbstract && !semanticProperty.ContainingType.IsInterface) + toolTip = String.Format("Contracts inherited from {0}.", inheritedFromProperty.ContainingType.Name.Text); + #endregion + #region Try get accessor contracts and update adornment + IMethodReference getterReference = null; + IMethodReference setterReference = null; + if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetPropertyAccessorReferences(inheritedFromProperty, out getterReference, out setterReference)) { + if (tagTuple.Item1 != null && getterReference != null) { + IMethodContract getterContracts; + if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(getterReference, out getterContracts)) { + var possibleAdornment = @this._adornmentManager.GetAdornment(tagTuple.Item1); + if (possibleAdornment != null) { + var adornment = possibleAdornment as ContractAdornment; + if (adornment != null) { + adornment.SetContracts(getterContracts, toolTip); + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping getter..."); + } + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment not found, skipping getter..."); + } + } + } + if (tagTuple.Item2 != null && setterReference != null) { + IMethodContract setterContracts; + if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(setterReference, out setterContracts)) { + var possibleAdornment = @this._adornmentManager.GetAdornment(tagTuple.Item2); + if (possibleAdornment != null) { + var adornment = possibleAdornment as ContractAdornment; + if (adornment != null) { + adornment.SetContracts(setterContracts, toolTip); + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping setter..."); + } + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment not found, skipping setter..."); + } + } + } + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get CCI reference for: " + inheritedFromProperty.Name.Text); + } + #endregion + } + #region Exception handeling + catch (IllFormedSemanticModelException e) { + if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 2) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Error: An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Asking for a new semantic model..."); + @this._textViewTracker.IsLatestCompilationStale = true; + ContractsPackageAccessor.Current.AskForNewVSModel(); + @this.semanticModelsFetchedCounter++; + goto RequeueAndAbort; + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Too many semantic models have been fetched, skipping this property..."); + goto Continue; + } + } catch (InvalidOperationException e) { + if (e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) { + if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) { + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); + @this._textViewTracker.IsLatestCompilationStale = true; + ContractsPackageAccessor.Current.AskForNewVSModel(); + @this.semanticModelsFetchedCounter++; + goto RequeueAndAbort; + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this property..."); + goto Continue; + } + } else + throw e; + } catch (COMException e) { + if (e.Message.Contains(ContractsPackageAccessor.COMExceptionMessage_BindingFailed)) { + if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) { + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation..."); + @this._textViewTracker.IsLatestCompilationStale = true; + ContractsPackageAccessor.Current.AskForNewVSModel(); + @this.semanticModelsFetchedCounter++; + goto RequeueAndAbort; + } else { + ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this property..."); + goto Continue; + } + } else + throw e; + } + #endregion + Continue: + ContractsPackageAccessor.Current.QueueWorkItem(() => RecursivelyLookupContractsForProperties(@this)); + return; + RequeueAndAbort: + @this._propertiesNeedingContractLookup.Enqueue(propertyPair); + return; + } + + static bool TryGetIheritedFromMember(CSharpMember semanticMember, TypeDeclarationNode syntacticParentType, out CSharpMember inheritedFromMember) { + Contract.Requires(semanticMember != null); + Contract.Requires(semanticMember.IsMethod); + Contract.Ensures(!Contract.Result() || + Contract.ValueAtReturn(out inheritedFromMember) != null && + Contract.ValueAtReturn(out inheritedFromMember).IsMethod); + + inheritedFromMember = null; + #region If member is from struct, ignore it + if (semanticMember.ContainingType.IsValueType || semanticMember.ContainingType.IsStruct) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Member is struct or value type, skipping member..."); + return false; + } + #endregion + #region If member is from a contract class, ignore it + //TODO: Get proper attributes from semantic model! Bug in semantic model, custom attributes don't seem to work right. + bool ignoreIt = false; + var containingType = semanticMember.ContainingType; + if (containingType.IsClass) { + if (syntacticParentType != null) { + foreach (var attributeSection in syntacticParentType.Attributes) { + foreach (var attribute in attributeSection.AttributeList) { + var attributeName = attribute.AttributeName as IdentifierNode; + if (attributeName != null) { + if (attributeName.Name.Text.Contains("ContractClassFor")) + ignoreIt = true; + } + } + } + } + } + if (ignoreIt) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Member has 'ContractClassForAttribute', skipping member..."); + return false; + } + #endregion + // If member is override, get base member + if (semanticMember.IsOverride) { + if (!CSharpToCCIHelper.TryGetBaseMember(semanticMember, out inheritedFromMember)) { + ContractsPackageAccessor.Current.Logger.WriteToLog("Member is an override but we can't get its base member, skipping member..."); + return false; //If we can't get the base member, we don't want to keep going with this member. + } + } + else if (semanticMember.ContainingType.IsInterface || semanticMember.IsAbstract) + { + inheritedFromMember = semanticMember; + } + #region Else member implements an interface or it doesn't have inherited contracts, get interface member + else + { + if (!CSharpToCCIHelper.TryGetInterfaceMember(semanticMember, out inheritedFromMember)) + { + ContractsPackageAccessor.Current.Logger.WriteToLog("Member isn't override, abstract, in an interface or an interface member, skipping member..."); + return false; //If we can't get the interface member, we don't want to keep going with this member. + } + } + #endregion + return inheritedFromMember != null; + } + } +} \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/CSharp/Inheritance/MethodCollector.cs b/Microsoft.Research/ContractAdornments/CSharp/Inheritance/MethodCollector.cs new file mode 100644 index 00000000..5acd8e4b --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp/Inheritance/MethodCollector.cs @@ -0,0 +1,175 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using Microsoft.RestrictedUsage.CSharp.Syntax; +using Microsoft.RestrictedUsage.CSharp.Extensions; +using System; +using Microsoft.VisualStudio.Text; +using System.Linq; +using ContractAdornments; +using Microsoft.RestrictedUsage.CSharp.Core; +using System.Text; +using System.Diagnostics.Contracts; + +namespace ContractAdornments { + public class MethodCollector : ParseTreeVisitor { + public const string MethodTagSuffix = "KIND:METHOD!"; + + readonly IDictionary _methods; + ITextSnapshot _snapshot; + + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(_methods != null); + } + + public MethodCollector(ITextSnapshot snapshot) + : base() { + _snapshot = snapshot; + _methods = new Dictionary(); + } + + public override void VisitMethodDeclarationNode(MethodDeclarationNode node) + { + if (_snapshot == null) return; + base.VisitMethodDeclarationNode(node); + var key = GenerateTag(node, _snapshot); + if (key == null) + { + //We can't get a proper tag from this (likely ill-formed) method, so we'll skip it for now. + var name = node.GetName(_snapshot); + ContractsPackageAccessor.Current.Logger.WriteToLog("Can't form a proper tag (likely ill-formed), ignoring member '" + name == null ? "" : name + "' for now..."); + return; + } + if (_methods.ContainsKey(key)) + { + //For some reason, we have two methods with the same signature. There is + //nothing we can do in this case so we just throw out the second method. + ContractsPackageAccessor.Current.Logger.WriteToLog("Two methods where found to have the exact same signature, ignoring second method for now..."); + return; + } + _methods.Add(key, node); + } + + public IDictionary GetMethods() { + Contract.Ensures(Contract.Result>() != null); + + return new Dictionary(_methods); + } + + public void Clear() { + _methods.Clear(); + _snapshot = null; + } + + public static object GenerateTag(MethodDeclarationNode method, ITextSnapshot snapshot) { + Contract.Requires(method != null); + Contract.Requires(snapshot != null); + + var sb = new StringBuilder(); + + //Append our name + var name = method.GetName(snapshot); + if (name == null) + return null; + sb.Append(name); + sb.Append('!'); + + //Append our return type + if (method.ReturnType != null) { + var rn = method.ReturnType.GetName(snapshot); + if (rn == null) + rn = "NONAME"; + sb.Append(rn); + sb.Append('!'); + } + + //Append parameters + if (method.FormalParameterList != null) { + foreach (var param in method.FormalParameterList) { + + //AppendParamter nameS + if (param.Identifier != null && param.Identifier.Name != null) { + sb.Append(param.Identifier.Name.Text); + sb.Append('!'); + } + + //Append parameter type + if (param.Type != null) { + var tn = param.Type.GetName(snapshot); + if (tn != null) { + sb.Append(tn); + sb.Append('!'); + } + } + + //Append attributes? + if (param.Attributes != null && param.Attributes.Count > 0) { + } + + //Append flags + if (param.Flags != default(NodeFlags)) { + sb.Append(param.Flags); + sb.Append('!'); + } + } + } + + //var snapshotSpan = method.GetSpan().Convert(snapshot); + //var methodText = snapshotSpan.GetText(); + //string methodHeader; + //if (methodText.Contains('{')) { + // methodHeader = methodText.Substring(0, methodText.IndexOf('{')).Trim(); + //} else if (methodText.Contains(';')) { + // methodHeader = methodText.Substring(0, methodText.IndexOf(';')).Trim(); + //} else + // return null; + //sb.Append(methodHeader); + //sb.Append('!'); + + //Apend parent information + var containingType = method.Parent; + while (containingType != null) { + var asClass = containingType.AsClass(); + if (asClass != null) { + sb.Append(asClass.Identifier.Name.Text); + sb.Append('!'); + goto EndOfLoop; + } + var asInterface = containingType.AsInterface(); + if (asInterface != null) { + sb.Append(asInterface.Identifier.Name.Text); + sb.Append('!'); + goto EndOfLoop; + } + /*Note: there is nothing we can do about the namespace, we can't seem to get namespace name info from the syntactic model. + */ + EndOfLoop: + containingType = containingType.Parent; + } + + //Append flags + if (method.Flags != default(NodeFlags)) { + sb.Append(method.Flags); + sb.Append('!'); + } + + //Append what kind of node we are + sb.Append(MethodTagSuffix); + + return sb.ToString(); + } + } +} diff --git a/Microsoft.Research/ContractAdornments/CSharp/Inheritance/PropertyCollector.cs b/Microsoft.Research/ContractAdornments/CSharp/Inheritance/PropertyCollector.cs new file mode 100644 index 00000000..417bea1d --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp/Inheritance/PropertyCollector.cs @@ -0,0 +1,169 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using Microsoft.RestrictedUsage.CSharp.Syntax; +using Microsoft.RestrictedUsage.CSharp.Extensions; +using System; +using Microsoft.VisualStudio.Text; +using System.Linq; +using ContractAdornments; +using Microsoft.RestrictedUsage.CSharp.Core; +using System.Text; +using System.Diagnostics.Contracts; + +namespace ContractAdornments { + public class PropertyCollector : ParseTreeVisitor { + public const string PropertyTagSuffix = "KIND:PROPERTY!"; + + readonly IDictionary, PropertyDeclarationNode> _properties; + readonly ITextSnapshot _snapshot; + + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(_properties != null); + } + + public PropertyCollector(ITextSnapshot snapshot) + : base() { + _snapshot = snapshot; + _properties = new Dictionary, PropertyDeclarationNode>(); + } + + public override void VisitPropertyDeclarationNode(PropertyDeclarationNode node) { + base.VisitPropertyDeclarationNode(node); + var keys = GenerateTag(node, _snapshot); + if (keys == null) { + //We can't get a proper tag from this (likely ill-formed) property, so we'll skip it for now. + var name = node.GetName(_snapshot); + ContractsPackageAccessor.Current.Logger.WriteToLog("Can't form a proper tag (likely ill-formed), ignoring member '" + name == null ? "" : name + "' for now..."); + return; + } + if (_properties.ContainsKey(keys)) { + //For some reason, we have two properties with the same signature. There is + //nothing we can do in this case so we just throw out the second property. + ContractsPackageAccessor.Current.Logger.WriteToLog("Two properties where found to have the exact same signature, ignoring second property for now..."); + return; + } + _properties.Add(keys, node); + } + + public IDictionary, PropertyDeclarationNode> GetProperties() { + Contract.Ensures(Contract.Result, PropertyDeclarationNode>>() != null); + Contract.Ensures(Contract.ForAll(Contract.Result, PropertyDeclarationNode>>(), (kvp) => + (kvp.Key.Item1 == null) == (kvp.Value.GetAccessorDeclaration == null) + && (kvp.Key.Item2 == null) == (kvp.Value.SetAccessorDeclaration == null) + )); + + return new Dictionary, PropertyDeclarationNode>(_properties); + } + + public static Tuple GenerateTag(PropertyDeclarationNode property, ITextSnapshot snapshot) { + Contract.Requires(property != null); + Contract.Requires(snapshot != null); + Contract.Ensures((property.GetAccessorDeclaration == null) || (Contract.Result>().Item1 != null)); + Contract.Ensures((property.SetAccessorDeclaration == null) || (Contract.Result>().Item2 != null)); + + var sb = new StringBuilder(); + + //Append our name + var name = property.GetName(snapshot); + if (name != null) { + sb.Append(name); + sb.Append('!'); + } + + //Append our return type + if (property.Type != null) { + var tn = property.Type.GetName(snapshot); + if (tn != null) { + sb.Append(tn); + sb.Append('!'); + } + } + + //Append parameters + if (property.FormalParameterList != null) { + foreach (var param in property.FormalParameterList) { + + //AppendParamter nameS + if (param.Identifier != null && param.Identifier.Name != null) { + sb.Append(param.Identifier.Name.Text); + sb.Append('!'); + } + + //Append parameter type + if (param.Type != null) { + var tn = param.Type.GetName(snapshot); + if (tn != null) { + sb.Append(tn); + sb.Append('!'); + } + } + + //Append attributes? + if (param.Attributes != null && param.Attributes.Count > 0) { + } + + //Append flags? + if (param.Flags != default(NodeFlags)) { + sb.Append(param.Flags); + sb.Append('!'); + } + } + } + + //Append parent information + var containingType = property.Parent; + while (containingType != null) { + var asClass = containingType.AsClass(); + if (asClass != null) { + sb.Append(asClass.Identifier.Name.Text); + sb.Append('!'); + goto EndOfLoop; + } + var asInterface = containingType.AsInterface(); + if (asInterface != null) { + sb.Append(asInterface.Identifier.Name.Text); + sb.Append('!'); + goto EndOfLoop; + } + /*Note: there is nothing we can do about the namespace, we can't seem to get namespace name info from the syntactic model. + */ + EndOfLoop: + containingType = containingType.Parent; + } + + //Append our flags + if (property.Flags != default(NodeFlags)) { + sb.Append(property.Flags); + sb.Append('!'); + } + + //Append what kind of node we are + sb.Append(PropertyTagSuffix); + + object getterTag = null; + object setterTag = null; + + if (property.GetAccessorDeclaration != null) + getterTag = "GETTER!" + sb.ToString(); + if (property.SetAccessorDeclaration != null) + setterTag = "SETTER!" + sb.ToString(); + + //return + return new Tuple(getterTag, setterTag); + } + } +} diff --git a/Microsoft.Research/ContractAdornments/Sources/Intellisense/IntellisenseContractsHelper.cs b/Microsoft.Research/ContractAdornments/CSharp/Intellisense/IntellisenseContractsHelper.cs similarity index 97% rename from Microsoft.Research/ContractAdornments/Sources/Intellisense/IntellisenseContractsHelper.cs rename to Microsoft.Research/ContractAdornments/CSharp/Intellisense/IntellisenseContractsHelper.cs index b3e13a94..64fed7f6 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Intellisense/IntellisenseContractsHelper.cs +++ b/Microsoft.Research/ContractAdornments/CSharp/Intellisense/IntellisenseContractsHelper.cs @@ -371,7 +371,7 @@ private static void FormatPrePostThrows(IMethodContract methodContracts, StringB private static string SmartFormat(string result) { if (string.IsNullOrEmpty(result)) return result; - if (VSServiceProvider.Current.VSOptionsPage != null && VSServiceProvider.Current.VSOptionsPage.SmartFormatting) + if (ContractsPackageAccessor.Current.VSOptionsPage != null && ContractsPackageAccessor.Current.VSOptionsPage.SmartFormatting) { var startTime = DateTime.Now; @@ -391,15 +391,15 @@ private static string SmartFormat(string result) catch (Exception) { trySmartReplace = null; - VSServiceProvider.Current.Logger.WriteToLog("Error: Smart formatting failed!"); - VSServiceProvider.Current.Logger.WriteToLog(result); + ContractsPackageAccessor.Current.Logger.WriteToLog("Error: Smart formatting failed!"); + ContractsPackageAccessor.Current.Logger.WriteToLog(result); } if (trySmartReplace != null) result = trySmartReplace; var elapsedTime = DateTime.Now - startTime; - VSServiceProvider.Current.Logger.WriteToLog("\t(Smart formatting took " + elapsedTime.Milliseconds + "ms)"); + ContractsPackageAccessor.Current.Logger.WriteToLog("\t(Smart formatting took " + elapsedTime.Milliseconds + "ms)"); } return result; } diff --git a/Microsoft.Research/ContractAdornments/Sources/Intellisense/QuickInfo.cs b/Microsoft.Research/ContractAdornments/CSharp/Intellisense/QuickInfo.cs similarity index 85% rename from Microsoft.Research/ContractAdornments/Sources/Intellisense/QuickInfo.cs rename to Microsoft.Research/ContractAdornments/CSharp/Intellisense/QuickInfo.cs index 9b6ce40f..2adf762f 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Intellisense/QuickInfo.cs +++ b/Microsoft.Research/ContractAdornments/CSharp/Intellisense/QuickInfo.cs @@ -27,6 +27,7 @@ using Microsoft.RestrictedUsage.CSharp.Compiler; using Microsoft.Cci.Contracts; using Microsoft.Cci; +using ContractAdornments.Interfaces; namespace ContractAdornments { class QuickInfoSource : IQuickInfoSource { @@ -39,12 +40,12 @@ void ObjectInvariant() { Contract.Invariant(_textViewTracker != null); } - public QuickInfoSource(ITextBuffer textBuffer, TextViewTracker textViewTracker) { + public QuickInfoSource(ITextBuffer textBuffer, ITextViewTracker textViewTracker) { Contract.Requires(textBuffer != null); Contract.Requires(textViewTracker != null); _textBuffer = textBuffer; - _textViewTracker = textViewTracker; + _textViewTracker = (TextViewTracker)textViewTracker; } public void AugmentQuickInfoSession(IQuickInfoSession session, IList quickInfoContent, out ITrackingSpan applicableToSpan) { @@ -59,7 +60,7 @@ public void AugmentQuickInfoSession(IQuickInfoSession session, IList qui if (quickInfoContent == null) return; //Wrap our method body in a safty net that checks for exceptions - VSServiceProvider.Current.Logger.PublicEntry(() => { + ContractsPackageAccessor.Current.Logger.PublicEntry(() => { //Record our start time for preformance considerations var startTime = DateTime.Now; @@ -94,13 +95,13 @@ public void AugmentQuickInfoSession(IQuickInfoSession session, IList qui return; //Is the model ready? - if (!VSServiceProvider.IsModelReady(parseTree) || _textViewTracker.IsLatestCompilationStale || _textViewTracker.IsLatestSourceFileStale) { + if (!parseTree.IsModelReady() || _textViewTracker.IsLatestCompilationStale || _textViewTracker.IsLatestSourceFileStale) { //Ask for a new model - VSServiceProvider.Current.AskForNewVSModel(); + ContractsPackageAccessor.Current.AskForNewVSModel(_textBuffer); //Return a message saying we aren't ready yet - VSServiceProvider.Current.Logger.WriteToLog("The VS model is out of date! Aborting contract lookup."); + ContractsPackageAccessor.Current.Logger.WriteToLog("The VS model is out of date! Aborting contract lookup."); return;//"(VS isn't ready for possible contract lookup yet. Please try again in a few seconds.)"; } @@ -131,7 +132,7 @@ public void AugmentQuickInfoSession(IQuickInfoSession session, IList qui } catch (IllFormedSemanticModelException) { return; } catch (InvalidOperationException e) { - if (!e.Message.Contains(VSServiceProvider.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) + if (!e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) throw e; else { @@ -153,7 +154,7 @@ public void AugmentQuickInfoSession(IQuickInfoSession session, IList qui quickInfoContent.Add(formattedContracts); //Print our elapsed time for preformance considerations var elapseTime = DateTime.Now - startTime; - VSServiceProvider.Current.Logger.WriteToLog("Time to compute quickinfo: " + elapseTime.Milliseconds + "ms"); + ContractsPackageAccessor.Current.Logger.WriteToLog("Time to compute quickinfo: " + elapseTime.Milliseconds + "ms"); }, "AugmentQuickInfoSession"); if (span != null) { applicableToSpan = span; } @@ -167,7 +168,7 @@ private string GetFormattedContracts(CSharpMember semanticMember) if (semanticMember.IsProperty || semanticMember.IsIndexer) { IMethodContract setter, getter; - if (!_textViewTracker.ProjectTracker.ContractsProvider.TryGetPropertyContract(semanticMember, out getter, out setter)) + if (!((ContractsProvider)_textViewTracker.ProjectTracker.ContractsProvider).TryGetPropertyContract(semanticMember, out getter, out setter)) { return null; } @@ -176,7 +177,7 @@ private string GetFormattedContracts(CSharpMember semanticMember) //Can we get our contracts? IMethodContract methodContracts; - if (!_textViewTracker.ProjectTracker.ContractsProvider.TryGetMethodContract(semanticMember, out methodContracts)) + if (!((ContractsProvider)_textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(semanticMember, out methodContracts)) return null; //Can we get our formatted contracts? diff --git a/Microsoft.Research/ContractAdornments/Sources/Intellisense/SignatureHelp.cs b/Microsoft.Research/ContractAdornments/CSharp/Intellisense/SignatureHelp.cs similarity index 92% rename from Microsoft.Research/ContractAdornments/Sources/Intellisense/SignatureHelp.cs rename to Microsoft.Research/ContractAdornments/CSharp/Intellisense/SignatureHelp.cs index a3ed828f..441cac84 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Intellisense/SignatureHelp.cs +++ b/Microsoft.Research/ContractAdornments/CSharp/Intellisense/SignatureHelp.cs @@ -22,6 +22,7 @@ using System.Diagnostics.Contracts; using Microsoft.Cci.Contracts; using Microsoft.VisualStudio.TextManager.Interop; +using ContractAdornments.Interfaces; namespace ContractAdornments { class SignatureHelpSource : ISignatureHelpSource { @@ -35,16 +36,16 @@ void ObjectInvariant() { Contract.Invariant(_textViewTracker != null); } - public SignatureHelpSource(ITextBuffer textBuffer, TextViewTracker textViewTracker) { + public SignatureHelpSource(ITextBuffer textBuffer, ITextViewTracker textViewTracker) { Contract.Requires(textBuffer != null); Contract.Requires(textViewTracker != null); _textBuffer = textBuffer; - _textViewTracker = textViewTracker; + _textViewTracker = (TextViewTracker)textViewTracker; } public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList signatures) { - VSServiceProvider.Current.Logger.PublicEntry(() => { + ContractsPackageAccessor.Current.Logger.PublicEntry(() => { //Record our start time for preformance considerations var startTime = DateTime.Now; @@ -83,13 +84,13 @@ public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList /// public ISignature GetBestMatch(ISignatureHelpSession session) { - return VSServiceProvider.Current.Logger.PublicEntry(() => { + return ContractsPackageAccessor.Current.Logger.PublicEntry(() => { IVsMethodData methodData = null; IVsMethodTipWindow3 tipWindow; int hr; @@ -436,7 +437,7 @@ public SignatureAppendedWithContracts(ISignature original, ITextBuffer textBuffe #if false void OnTextBufferChanged(object sender, TextContentChangedEventArgs e) { - VSServiceProvider.Current.Logger.PublicEntry(() => { + ContractsPackageAccessor.Current.Logger.PublicEntry(() => { CalculateCurrentParameter(); }, "OnTextBufferChanged"); } diff --git a/Microsoft.Research/ContractAdornments/VS2012/Properties/AssemblyInfo.cs b/Microsoft.Research/ContractAdornments/CSharp/Properties/AssemblyInfo.cs similarity index 93% rename from Microsoft.Research/ContractAdornments/VS2012/Properties/AssemblyInfo.cs rename to Microsoft.Research/ContractAdornments/CSharp/Properties/AssemblyInfo.cs index 1b43c17c..8d1a741e 100644 --- a/Microsoft.Research/ContractAdornments/VS2012/Properties/AssemblyInfo.cs +++ b/Microsoft.Research/ContractAdornments/CSharp/Properties/AssemblyInfo.cs @@ -18,11 +18,11 @@ using System.Resources; using System.Runtime.InteropServices; -[assembly: AssemblyTitle("CodeContractsEditorExtensions")] +[assembly: AssemblyTitle("ContractAdornments.CSharp")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] //[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("CodeContractsEditorExtensions")] +[assembly: AssemblyProduct("ContractAdornments.CSharp")] //[assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Microsoft.Research/ContractAdornments/Sources/TextView/TextViewTracker.cs b/Microsoft.Research/ContractAdornments/CSharp/TextView/TextViewTracker.cs similarity index 76% rename from Microsoft.Research/ContractAdornments/Sources/TextView/TextViewTracker.cs rename to Microsoft.Research/ContractAdornments/CSharp/TextView/TextViewTracker.cs index 1795b660..0ecc76a0 100644 --- a/Microsoft.Research/ContractAdornments/Sources/TextView/TextViewTracker.cs +++ b/Microsoft.Research/ContractAdornments/CSharp/TextView/TextViewTracker.cs @@ -24,20 +24,21 @@ using System.Windows.Media; using Adornments; using System.Timers; +using ContractAdornments.Interfaces; namespace ContractAdornments { - internal sealed class TextViewTracker { - public const string TextViewTrackerKey = "TextViewTracker"; + internal sealed class TextViewTracker : ITextViewTracker { + public static readonly object TextViewTrackerKey = TextViewTrackerAccessor.TextViewTrackerKey; public const double DelayOnTextViewOpened = 2000d; public const double DelayOnTextViewChanged = 5000d; public readonly IWpfTextView TextView; - readonly ProjectTracker _projectTracker; - public ProjectTracker ProjectTracker + readonly IProjectTracker _projectTracker; + public IProjectTracker ProjectTracker { get { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return this._projectTracker; } } @@ -60,30 +61,12 @@ void ObjectInvariant() { Contract.Invariant(_textBufferChangedTimer != null); } - #region Static getters - [ContractVerification(false)] - public static TextViewTracker GetOrCreateTextViewTracker(IWpfTextView textView, ProjectTracker projectTracker, VSTextProperties vsTextProperties) { - Contract.Requires(textView != null); - Contract.Requires(projectTracker != null); - Contract.Ensures(Contract.Result() != null); - return textView.TextBuffer.Properties.GetOrCreateSingletonProperty(TextViewTrackerKey, delegate { return new TextViewTracker(textView, projectTracker, vsTextProperties); }); - } - public static bool TryGetTextViewTracker(ITextBuffer textBuffer, out TextViewTracker textViewTracker) { - Contract.Requires(textBuffer != null); - if (textBuffer.Properties == null) { - textViewTracker = null; - return false; - } - return textBuffer.Properties.TryGetProperty(TextViewTrackerKey, out textViewTracker); - } - #endregion - - private TextViewTracker(IWpfTextView textView, ProjectTracker projectTracker, VSTextProperties vsTextProperties) + internal TextViewTracker(IWpfTextView textView, IProjectTracker projectTracker, VSTextProperties vsTextProperties) : base() { Contract.Requires(textView != null); Contract.Requires(projectTracker != null); - VSServiceProvider.Current.ExtensionFailed += OnFailed; + ContractsPackageAccessor.Current.ExtensionFailed += OnFailed; this.TextView = textView; if (textView.TextBuffer != null) { @@ -92,8 +75,8 @@ private TextViewTracker(IWpfTextView textView, ProjectTracker projectTracker, VS TextView.Closed += OnClosed; this._projectTracker = projectTracker; projectTracker.BuildDone += OnBuildDone; -// VSServiceProvider.Current.NewSourceFile += OnNewSourceFile; - VSServiceProvider.Current.NewCompilation += OnNewComilation; +// ContractsPackageAccessor.Current.NewSourceFile += OnNewSourceFile; + ContractsPackageAccessor.Current.NewCompilation += OnNewComilation; //Timer _textBufferChangedTimer = new System.Timers.Timer(); @@ -104,7 +87,7 @@ private TextViewTracker(IWpfTextView textView, ProjectTracker projectTracker, VS //Set the text properties VSTextProperties = vsTextProperties; - VSServiceProvider.Current.QueueWorkItem((() => { VSTextProperties.LineHeight = TextView.LineHeight; })); + ContractsPackageAccessor.Current.QueueWorkItem((() => { VSTextProperties.LineHeight = TextView.LineHeight; })); //Set the file name var fn = TextView.GetFileName(); @@ -129,17 +112,17 @@ void UnsubscribeFromEvents() { { TextView.TextBuffer.Changed -= OnTextBufferChanged; } - VSServiceProvider.Current.NewCompilation -= OnNewComilation; -// VSServiceProvider.Current.NewSourceFile -= OnNewSourceFile; - VSServiceProvider.Current.ExtensionFailed -= OnFailed; - VSServiceProvider.Current.Logger.WriteToLog("TextViewTracker for '" + FileName.Value + "' unsubscribed from all events."); + ContractsPackageAccessor.Current.NewCompilation -= OnNewComilation; +// ContractsPackageAccessor.Current.NewSourceFile -= OnNewSourceFile; + ContractsPackageAccessor.Current.ExtensionFailed -= OnFailed; + ContractsPackageAccessor.Current.Logger.WriteToLog("TextViewTracker for '" + FileName.Value + "' unsubscribed from all events."); } void OnBuildDone() { IsLatestSourceFileStale = true; IsLatestCompilationStale = true; - VSServiceProvider.Current.AskForNewVSModel(); + ContractsPackageAccessor.Current.AskForNewVSModel(TextView.TextBuffer); } void OnTextBufferChanged(object sender, TextContentChangedEventArgs e) { @@ -151,16 +134,16 @@ void OnTextBufferChanged(object sender, TextContentChangedEventArgs e) { this._textBufferChangedTimer.Enabled = true; #endregion } catch (Exception exn) { - VSServiceProvider.Current.Logger.PublicEntryException(exn, "OnTextBufferChanged"); + ContractsPackageAccessor.Current.Logger.PublicEntryException(exn, "OnTextBufferChanged"); } } void OnTextViewSettled(object sender, System.Timers.ElapsedEventArgs e) { - VSServiceProvider.Current.Logger.PublicEntry(() => { + ContractsPackageAccessor.Current.Logger.PublicEntry(() => { - VSServiceProvider.Current.Logger.WriteToLog("Timer elapsed. Waiting for new syntactic info."); + ContractsPackageAccessor.Current.Logger.WriteToLog("Timer elapsed. Waiting for new syntactic info."); - VSServiceProvider.Current.AskForNewVSModel(); + ContractsPackageAccessor.Current.AskForNewVSModel(TextView.TextBuffer); IsLatestCompilationStale = true; IsLatestSourceFileStale = true; @@ -189,9 +172,9 @@ void OnNewSourceFile(SourceFile sourceFile) { LatestSourceFileChanged(this, new LatestSourceFileChangedEventArgs(wasLatestSourceFileStale, IsLatestSourceFileStale, LatestSourceFile)); } } - void OnNewComilation(Compilation comp) { - - Contract.Requires(comp != null); + void OnNewComilation(object compilationObject) { + Contract.Requires(compilationObject != null); + Compilation comp = (Compilation)compilationObject; //Is this compilation relevant to us? SourceFile sourceFile; diff --git a/Microsoft.Research/ContractAdornments/CSharp/VersionedServicesFactory.cs b/Microsoft.Research/ContractAdornments/CSharp/VersionedServicesFactory.cs new file mode 100644 index 00000000..d8383792 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp/VersionedServicesFactory.cs @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.CSharp +{ + using System.Collections.Generic; + using System.Linq; + using Adornments; + using ContractAdornments.Interfaces; + using Microsoft.RestrictedUsage.CSharp.Compiler; + using Microsoft.RestrictedUsage.CSharp.Compiler.IDE; + using Microsoft.VisualStudio.Language.Intellisense; + using Microsoft.VisualStudio.Text; + using Microsoft.VisualStudio.Text.Editor; + + internal sealed class VersionedServicesFactory : IVersionedServicesFactory + { + public ICompilerHost CreateCompilerHost() + { + return new CompilerHostShim(new IDECompilerHost()); + } + + public ITextViewTracker CreateTextViewTracker(IWpfTextView textView, IProjectTracker projectTracker, VSTextProperties vsTextProperties) + { + return new TextViewTracker(textView, projectTracker, vsTextProperties); + } + + public IContractsProvider CreateContractsProvider(IProjectTracker projectTracker) + { + return new ContractsProvider(projectTracker); + } + + + public IQuickInfoSource CreateQuickInfoSource(ITextBuffer textBuffer, ITextViewTracker textViewTracker) + { + return new QuickInfoSource(textBuffer, textViewTracker); + } + + public ISignatureHelpSource CreateSignatureHelpSource(ITextBuffer textBuffer, ITextViewTracker textViewTracker) + { + return new SignatureHelpSource(textBuffer, textViewTracker); + } + + private class CompilerHostShim : ICompilerHost + { + private readonly IDECompilerHost _compilerHost; + + public CompilerHostShim(IDECompilerHost compilerHost) + { + _compilerHost = compilerHost; + } + + public IEnumerable Compilers + { + get + { + return _compilerHost.Compilers.Select(i => new CompilerShim(i)); + } + } + } + + private class CompilerShim : ICompiler + { + private readonly Compiler _compiler; + + public CompilerShim(Compiler compiler) + { + _compiler = compiler; + } + + public object GetCompilation(ITextBuffer textBuffer) + { + return _compiler.GetCompilation(); + } + } + } +} diff --git a/Microsoft.Research/ContractAdornments/CSharp/packages.ContractAdornments.CSharp.10.config b/Microsoft.Research/ContractAdornments/CSharp/packages.ContractAdornments.CSharp.10.config new file mode 100644 index 00000000..879f5526 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp/packages.ContractAdornments.CSharp.10.config @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/CSharp/packages.ContractAdornments.CSharp.11.config b/Microsoft.Research/ContractAdornments/CSharp/packages.ContractAdornments.CSharp.11.config new file mode 100644 index 00000000..20dcc12a --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp/packages.ContractAdornments.CSharp.11.config @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/CSharp/packages.ContractAdornments.CSharp.12.config b/Microsoft.Research/ContractAdornments/CSharp/packages.ContractAdornments.CSharp.12.config new file mode 100644 index 00000000..4251438c --- /dev/null +++ b/Microsoft.Research/ContractAdornments/CSharp/packages.ContractAdornments.CSharp.12.config @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/Sources/AdornmentSource.cs b/Microsoft.Research/ContractAdornments/Extension/AdornmentSource.cs similarity index 100% rename from Microsoft.Research/ContractAdornments/Sources/AdornmentSource.cs rename to Microsoft.Research/ContractAdornments/Extension/AdornmentSource.cs diff --git a/Microsoft.Research/ContractAdornments/Extension/ContractAdornments.csproj b/Microsoft.Research/ContractAdornments/Extension/ContractAdornments.csproj new file mode 100644 index 00000000..4424ce53 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Extension/ContractAdornments.csproj @@ -0,0 +1,457 @@ + + + + + + + + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Common.CodeContracts.props)) + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {D3F9BE8B-BA9F-4919-87CE-EE1878EDA40C} + Library + Properties + ContractAdornments + CodeContractsHelper + v4.0 + 512 + true + + + + Program + $(DevEnvDir)\devenv.exe + /rootSuffix Exp + + + + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\VSSDK\Microsoft.VsSDK.targets + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\VSSDK\Microsoft.VsSDK.targets + + + + $(VisualStudioVersion) + + + + False + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + False + C:\Users\a-darylz\Documents\CCI\Microsoft.Research\ContractAdornments + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\Devlab9\ + + + full + AnyCPU + true + GlobalSuppressions.cs + prompt + true + AllRules.ruleset + + + true + bin\Academic9\ + true + full + AnyCPU + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + true + bin\Internal9\ + + + full + AnyCPU + true + GlobalSuppressions.cs + prompt + true + AllRules.ruleset + + + true + bin\Devlab9ro\ + true + full + AnyCPU + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + + False + ..\..\..\packages\VSSDK.DTE.7.0.4\lib\net20\envdte.dll + False + + + False + ..\..\ImportedCCI2\Microsoft.Cci.Analysis.ControlAndDataFlowGraph.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.CodeModel.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.CodeModelToIL.dll + + + ..\..\ImportedCCI2\Microsoft.Cci.ContractExtractor.dll + + + ..\..\ImportedCCI2\Microsoft.Cci.CSharpSourceEmitter.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.ILGenerator.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.MetadataHelper.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.MetadataModel.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.MutableCodeModel.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.MutableMetadataModel.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.NewILToCodeModel.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.PdbReader.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.PdbWriter.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.PEReader.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.PeWriter.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.SourceModel.dll + + + + ..\..\..\packages\VSSDK.CoreUtility.10.0.4\lib\net40\Microsoft.VisualStudio.CoreUtility.dll + False + + + ..\..\..\packages\VSSDK.Language.10.0.4\lib\net40\Microsoft.VisualStudio.Language.Intellisense.dll + False + + + ..\..\..\packages\VSSDK.Language.10.0.4\lib\net40\Microsoft.VisualStudio.Language.StandardClassification.dll + False + + + ..\..\..\packages\VSSDK.OLE.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.OLE.Interop.dll + False + + + ..\..\..\packages\VSSDK.Shell.10.10.0.4\lib\net40\Microsoft.VisualStudio.Shell.10.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Immutable.10.10.0.4\lib\net40\Microsoft.VisualStudio.Shell.Immutable.10.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.dll + False + + + False + ..\..\..\packages\VSSDK.Shell.Interop.10.10.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.10.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.8.0.dll + False + + + ..\..\..\packages\VSSDK.Shell.Interop.9.9.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.9.0.dll + False + + + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.Data.dll + False + + + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.Logic.dll + False + + + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.UI.dll + False + + + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.UI.Wpf.dll + False + + + ..\..\..\packages\VSSDK.TextManager.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.dll + False + + + ..\..\..\packages\VSSDK.TextManager.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.8.0.dll + False + + + + + False + ..\..\..\packages\VSSDK.DTE.7.0.4\lib\net20\stdole.dll + False + + + + + + + + + + + + False + ..\..\..\packages\VSSDK.VSLangProj.7.0.4\lib\net20\VSLangProj.dll + False + + + False + ..\..\..\packages\VSSDK.VSLangProj.7.0.4\lib\net20\VSLangProj2.dll + False + + + + + + Version\version.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + Never + Images\ContractAdornments_Large.png + + + Never + Images\ContractAdornments_Small.png + + + Never + Images\Inheritance_Small.png + + + Always + true + QuickInfo_Large.png + + + Always + true + License\AdornmentsEULA.docx + + + Always + true + AdornmentsEULA.rtf + + + + + + + + {784aa6a9-013e-4d8e-82d6-934571cf1357} + Adornments + + + {233b4116-291e-446e-9c44-04b7fbc514ff} + ContractAdornments.CSharp.10 + false + + + {a73f8aeb-7d31-4d67-9d94-853d1bb597a6} + ContractAdornments.CSharp.11 + false + + + {9c55b970-24b3-4623-9ba2-2d0f070e31a0} + ContractAdornments.CSharp.12 + false + + + {7fb60d9a-cf16-46c0-8154-696d85f8d451} + ContractAdornments.CSharp.14 + false + + + {b0c91c82-c1d8-4697-b07e-18e17d11eb41} + ContractAdornments.Interfaces + + + {E47A869B-4B78-41B3-AF6E-1D51B2D1AD3B} + Utilities + + + + + true + true + + + true + bin\Debug64\ + DEBUG;TRACE + full + AnyCPU + bin\Debug\CodeContractsHelper.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + + + bin\Internal64\ + TRACE + true + pdbonly + AnyCPU + bin\Release\CodeContractsHelper.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + true + bin\Devlab64\ + DEBUG;TRACE + full + AnyCPU + bin\Debug\CodeContractsHelper.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + false + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/Extension/Extensions.cs b/Microsoft.Research/ContractAdornments/Extension/Extensions.cs new file mode 100644 index 00000000..203cdb4a --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Extension/Extensions.cs @@ -0,0 +1,75 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using System.Diagnostics.Contracts; +using System; +using System.Linq; +using System.Collections.Generic; +using System.Diagnostics; +using Adornments; +using ContractAdornments.Interfaces; +using System.Runtime.InteropServices; + +namespace ContractAdornments { + static class HelperExtensions { + public static string GetFileName(this ITextView @this) { + Contract.Requires(@this != null); + + if (@this.TextBuffer == null) return null; + return @this.TextBuffer.GetFileName(); + } + public static string GetFileName(this ITextBuffer @this) { + Contract.Requires(@this != null); + ITextDocument doc; + if (@this.Properties == null) return null; + if (@this.Properties.TryGetProperty(typeof(ITextDocument), out doc)) { + Contract.Assume(doc != null); + if (doc.FilePath == null) { return null; } + return doc.FilePath.ToLower(); + } + return null; + } + + public static void RefreshLineTransformer(this ITextView textView) { + Contract.Requires(textView != null); + + if (textView.TextViewLines == null) return; + var line = textView.TextViewLines.FirstVisibleLine; + if (line == null) return; + textView.DisplayTextLineContainingBufferPosition(line.Start, line.Top - textView.ViewportTop, ViewRelativePosition.Top); + } + } + public static class AdornmentOptionsHelper { + public static AdornmentOptions GetAdornmentOptions(IContractOptionsPage options) { + var result = AdornmentOptions.None; + + if (options == null) + return result; + + if (options.SmartFormatting) + result = result | AdornmentOptions.SmartFormatting; + + if (options.SyntaxColoring) + result = result | AdornmentOptions.SyntaxColoring; + + if (options.CollapseMetadataContracts) + { + result = result | AdornmentOptions.CollapseWithRegion; + } + return result; + } + } +} \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/Sources/Intellisense/QuickInfoProvider.cs b/Microsoft.Research/ContractAdornments/Extension/Intellisense/QuickInfoProvider.cs similarity index 88% rename from Microsoft.Research/ContractAdornments/Sources/Intellisense/QuickInfoProvider.cs rename to Microsoft.Research/ContractAdornments/Extension/Intellisense/QuickInfoProvider.cs index fef24497..bf750ddf 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Intellisense/QuickInfoProvider.cs +++ b/Microsoft.Research/ContractAdornments/Extension/Intellisense/QuickInfoProvider.cs @@ -12,15 +12,12 @@ // // THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.ComponentModel.Composition; -using Microsoft.VisualStudio.Utilities; +using System.Diagnostics.Contracts; +using ContractAdornments.Interfaces; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text; -using System.Diagnostics.Contracts; +using Microsoft.VisualStudio.Utilities; namespace ContractAdornments { [Export(typeof(IQuickInfoSourceProvider))] @@ -41,9 +38,9 @@ public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer) { if (VSServiceProvider.Current.VSOptionsPage != null && !VSServiceProvider.Current.VSOptionsPage.QuickInfo) return null; - TextViewTracker textViewTracker; - if (TextViewTracker.TryGetTextViewTracker(textBuffer, out textViewTracker)) { - return new QuickInfoSource(textBuffer, textViewTracker); + ITextViewTracker textViewTracker; + if (TextViewTrackerAccessor.TryGetTextViewTracker(textBuffer, out textViewTracker)) { + return VSServiceProvider.Current.GetVersionedServicesFactory().CreateQuickInfoSource(textBuffer, textViewTracker); } else return null; }, "TryCreateQuickInfoSession"); diff --git a/Microsoft.Research/ContractAdornments/Sources/Intellisense/SignatureHelpProvider.cs b/Microsoft.Research/ContractAdornments/Extension/Intellisense/SignatureHelpProvider.cs similarity index 88% rename from Microsoft.Research/ContractAdornments/Sources/Intellisense/SignatureHelpProvider.cs rename to Microsoft.Research/ContractAdornments/Extension/Intellisense/SignatureHelpProvider.cs index 13b15595..71b083ce 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Intellisense/SignatureHelpProvider.cs +++ b/Microsoft.Research/ContractAdornments/Extension/Intellisense/SignatureHelpProvider.cs @@ -12,16 +12,12 @@ // // THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.ComponentModel.Composition; -using Microsoft.VisualStudio.Utilities; -using Microsoft.VisualStudio.Language.Intellisense; -using Microsoft.VisualStudio.Shell; using System.Diagnostics.Contracts; +using ContractAdornments.Interfaces; +using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Utilities; namespace ContractAdornments { [Export(typeof(ISignatureHelpSourceProvider))] @@ -45,9 +41,9 @@ public ISignatureHelpSource TryCreateSignatureHelpSource(ITextBuffer textBuffer) return null; //Can we get the TextViewTracker? - TextViewTracker textViewTracker; - if (TextViewTracker.TryGetTextViewTracker(textBuffer, out textViewTracker)) - return new SignatureHelpSource(textBuffer, textViewTracker); + ITextViewTracker textViewTracker; + if (TextViewTrackerAccessor.TryGetTextViewTracker(textBuffer, out textViewTracker)) + return VSServiceProvider.Current.GetVersionedServicesFactory().CreateSignatureHelpSource(textBuffer, textViewTracker); else return null; diff --git a/Microsoft.Research/ContractAdornments/Sources/LineTransformer.cs b/Microsoft.Research/ContractAdornments/Extension/LineTransformer.cs similarity index 100% rename from Microsoft.Research/ContractAdornments/Sources/LineTransformer.cs rename to Microsoft.Research/ContractAdornments/Extension/LineTransformer.cs diff --git a/Microsoft.Research/ContractAdornments/Sources/Metadata/MetadataTracker.cs b/Microsoft.Research/ContractAdornments/Extension/Metadata/MetadataTracker.cs similarity index 100% rename from Microsoft.Research/ContractAdornments/Sources/Metadata/MetadataTracker.cs rename to Microsoft.Research/ContractAdornments/Extension/Metadata/MetadataTracker.cs diff --git a/Microsoft.Research/ContractAdornments/Extension/Properties/AssemblyInfo.cs b/Microsoft.Research/ContractAdornments/Extension/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..eab4bc6e --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Extension/Properties/AssemblyInfo.cs @@ -0,0 +1,39 @@ +// CodeContracts +// +// Copyright (c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Diagnostics.Contracts; +using System.Reflection; +using System.Resources; +using System.Runtime.InteropServices; +using ContractAdornments; + +[assembly: AssemblyTitle("CodeContractsEditorExtensions")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +//[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CodeContractsEditorExtensions")] +//[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: CLSCompliant(false)] +[assembly: NeutralResourcesLanguage("en-US")] +//[assembly: AssemblyVersion("1.0.0812.6")] +//[assembly: AssemblyFileVersion("1.0.0812.6")] + +//[assembly:ContractVerification(false)] + +[assembly: Guid("E9F4EE90-7314-4A63-B4F5-432E039D6A19")] +[assembly: ProvideBindingPath] diff --git a/Microsoft.Research/ContractAdornments/Sources/TextView/TextViewProvider.cs b/Microsoft.Research/ContractAdornments/Extension/TextView/TextViewProvider.cs similarity index 96% rename from Microsoft.Research/ContractAdornments/Sources/TextView/TextViewProvider.cs rename to Microsoft.Research/ContractAdornments/Extension/TextView/TextViewProvider.cs index c6421caa..4344030f 100644 --- a/Microsoft.Research/ContractAdornments/Sources/TextView/TextViewProvider.cs +++ b/Microsoft.Research/ContractAdornments/Extension/TextView/TextViewProvider.cs @@ -12,21 +12,16 @@ // // THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +using System; using System.ComponentModel.Composition; +using System.Diagnostics.Contracts; +using System.IO; +using System.Linq; +using Adornments; using Microsoft.VisualStudio.Text.Classification; using Microsoft.VisualStudio.Text.Editor; -using Microsoft.VisualStudio.Text.Formatting; using Microsoft.VisualStudio.Text.Outlining; using Microsoft.VisualStudio.Utilities; -using Adornments; -using System.IO; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Diagnostics.Contracts; -using System.Diagnostics; -using System.Windows.Media; namespace ContractAdornments { [Export(typeof(IWpfTextViewCreationListener))] @@ -119,7 +114,7 @@ public void TextViewCreated(IWpfTextView textView) { #endregion if (IsEditableCodeFile) { textView.GotAggregateFocus += NewFocus; - var textViewTracker = TextViewTracker.GetOrCreateTextViewTracker(textView, projectTracker, vsTextProperties); + var textViewTracker = TextViewTrackerAccessor.GetOrCreateTextViewTracker(textView, projectTracker, vsTextProperties); //if (VSServiceProvider.Current.VSOptionsPage != null && (VSServiceProvider.Current.VSOptionsPage.InheritanceOnMethods || VSServiceProvider.Current.VSOptionsPage.InheritanceOnProperties)) { // //var inheritanceAdornmentManager = AdornmentManager.GetOrCreateAdornmentManager(textView, "InheritanceAdornments", outliningManager, VSServiceProvider.Current.Logger); // //var inheritanceTracker = InheritanceTracker.GetOrCreateAdornmentTracker(textViewTracker); diff --git a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/GlobalSuppressions.cs b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/GlobalSuppressions.cs similarity index 100% rename from Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/GlobalSuppressions.cs rename to Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/GlobalSuppressions.cs diff --git a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/Guids.cs b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/Guids.cs similarity index 100% rename from Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/Guids.cs rename to Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/Guids.cs diff --git a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/NonlockingHost.cs b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/NonlockingHost.cs similarity index 98% rename from Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/NonlockingHost.cs rename to Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/NonlockingHost.cs index aa57c912..37a1c75c 100644 --- a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/NonlockingHost.cs +++ b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/NonlockingHost.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Diagnostics.Contracts; using System.IO; +using ContractAdornments.Interfaces; using Microsoft.Cci; using Microsoft.Cci.MutableContracts; @@ -23,7 +24,7 @@ namespace ContractAdornments { /// /// A custom host enviornment that makes sure all openned resources can be disposed. This is needed so that this host doesn't interfere with VS's build process. /// - public class NonlockingHost : CodeContractAwareHostEnvironment { + public class NonlockingHost : CodeContractAwareHostEnvironment, INonlockingHost { readonly Dictionary _locationsToAssemblyReferences; private string[] _originalLibpaths; diff --git a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/OptionsPage/OptionsPage.cs b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/OptionsPage/OptionsPage.cs similarity index 96% rename from Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/OptionsPage/OptionsPage.cs rename to Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/OptionsPage/OptionsPage.cs index 18efd51b..6ebdb18b 100644 --- a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/OptionsPage/OptionsPage.cs +++ b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/OptionsPage/OptionsPage.cs @@ -13,19 +13,16 @@ // THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; -using System.Globalization; -using System.Diagnostics; using System.ComponentModel; +using System.IO; using System.Runtime.InteropServices; +using ContractAdornments.Interfaces; using MSVSIP = Microsoft.VisualStudio.Shell; -using System.Windows.Forms; -using System.IO; -using System.Diagnostics.Contracts; namespace ContractAdornments.OptionsPage { [Guid(GuidList.guidOptionsPageGeneralString)] [System.ComponentModel.DesignerCategoryAttribute("code")] - public class ContractOptionsPage : MSVSIP.DialogPage + public class ContractOptionsPage : MSVSIP.DialogPage, IContractOptionsPage { #if false [Category("Contracts")] diff --git a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/OptionsPage/OptionsResources.Designer.cs b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/OptionsPage/OptionsResources.Designer.cs similarity index 100% rename from Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/OptionsPage/OptionsResources.Designer.cs rename to Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/OptionsPage/OptionsResources.Designer.cs diff --git a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/OptionsPage/OptionsResources.resx b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/OptionsPage/OptionsResources.resx similarity index 100% rename from Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/OptionsPage/OptionsResources.resx rename to Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/OptionsPage/OptionsResources.resx diff --git a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/ProjectTracker.cs b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/ProjectTracker.cs similarity index 96% rename from Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/ProjectTracker.cs rename to Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/ProjectTracker.cs index f84721a9..85fc1d88 100644 --- a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/ProjectTracker.cs +++ b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/ProjectTracker.cs @@ -16,23 +16,24 @@ using System.Diagnostics.Contracts; using System.IO; using System.Runtime.InteropServices; +using ContractAdornments.Interfaces; using Microsoft.Cci; using VSLangProj; namespace ContractAdornments { - public class ProjectTracker { + public class ProjectTracker : IProjectTracker { public const string COMExceptionMessage_ProjectUnavailable = "Project unavailable."; readonly VSLangProj.VSProject VS_Project; readonly EnvDTE.Project EnvDTE_Project; - private readonly ContractsProvider _contractsProvider; + private readonly IContractsProvider _contractsProvider; - public ContractsProvider ContractsProvider + public IContractsProvider ContractsProvider { get { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return this._contractsProvider; } } @@ -52,12 +53,20 @@ public NonlockingHost Host return this._host; } } + INonlockingHost IProjectTracker.Host + { + get + { + return Host; + } + } + public AssemblyIdentity AssemblyIdentity { get; private set; } int _assemblyIdentityRevaluations = 0; const int _maxAssemblyIdentityRevaluations = 5; public readonly string UniqueProjectName; - public readonly string ProjectName; + public string ProjectName { get; private set; } public event Action BuildBegin; public event Action BuildDone; @@ -134,7 +143,7 @@ private ProjectTracker(VSProject vsProject) { AssemblyIdentity = GetAssemblyIdentity(EnvDTE_Project, Host); //Set the contracts provider - _contractsProvider = new ContractsProvider(this); + _contractsProvider = VSServiceProvider.Current.GetVersionedServicesFactory().CreateContractsProvider(this); } public void OnProjectConfigChange() diff --git a/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/ProvideBindingPathAttribute.cs b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/ProvideBindingPathAttribute.cs new file mode 100644 index 00000000..4c4a1694 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/ProvideBindingPathAttribute.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments +{ + using System; + using System.Reflection; + using System.Runtime.InteropServices; + using Microsoft.VisualStudio.Shell; + + /// + /// This attribute registers a path that should be probed for candidate assemblies at assembly load time. + /// + /// For example: + /// [...\VisualStudio\10.0\BindingPaths\{5C48C732-5C7F-40f0-87A7-05C4F15BC8C3}] + /// "$PackageFolder$"="" + /// + /// This would register the "PackageFolder" (i.e. the location of the pkgdef file) as a directory to be probed + /// for assemblies to load. + /// + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = false)] + internal sealed class ProvideBindingPathAttribute : RegistrationAttribute + { + private static string GetPathToKey(RegistrationContext context) + { + Guid componentGuid = GetAssemblyGuid(context.CodeBase); + return string.Concat(@"BindingPaths\", componentGuid.ToString("B").ToUpperInvariant()); + } + + private static Guid GetAssemblyGuid(string codeBase) + { + string assemblyFile = new Uri(codeBase).LocalPath; + Assembly assembly = Assembly.LoadFrom(codeBase); + object[] attributesData = assembly.GetCustomAttributes(typeof(GuidAttribute), false); + if (attributesData.Length == 0) + throw new ArgumentException("The specified assembly did not contain a [Guid] attribute."); + + return new Guid(((GuidAttribute)attributesData[0]).Value); + } + + public override void Register(RegistrationContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + + using (Key childKey = context.CreateKey(GetPathToKey(context))) + { + childKey.SetValue(context.ComponentPath, string.Empty); + } + } + + public override void Unregister(RegistrationContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + + context.RemoveKey(GetPathToKey(context)); + } + } +} diff --git a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/VSServiceProvider.cs b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/VSServiceProvider.cs similarity index 95% rename from Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/VSServiceProvider.cs rename to Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/VSServiceProvider.cs index 68b1a373..e6a4ae9e 100644 --- a/Microsoft.Research/ContractAdornments/Sources/VSServiceProvider/VSServiceProvider.cs +++ b/Microsoft.Research/ContractAdornments/Extension/VSServiceProvider/VSServiceProvider.cs @@ -14,25 +14,22 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.IO; +using System.Reflection; using System.Runtime.InteropServices; using System.Text; +using ContractAdornments.Interfaces; +using ContractAdornments.OptionsPage; using EnvDTE; -using EnvDTE80; -using Microsoft.RestrictedUsage.CSharp.Compiler; -using Microsoft.RestrictedUsage.CSharp.Compiler.IDE; -using Microsoft.RestrictedUsage.CSharp.Syntax; using Microsoft.VisualStudio; using Microsoft.VisualStudio.OLE.Interop; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Text; using UtilitiesNamespace; using VSLangProj; -using System.Timers; -using ContractAdornments.OptionsPage; -using System.Diagnostics; -using System.Reflection; namespace ContractAdornments { @@ -46,7 +43,7 @@ namespace ContractAdornments { [Guid(GuidList.guidVSServiceProviderString)] [ProvideAutoLoad("ADFC4E64-0397-11D1-9F4E-00A0C911004F")] #endregion - public sealed class VSServiceProvider : Package, IVsSolutionEvents, IVsUpdateSolutionEvents2, IOleComponent + public sealed class VSServiceProvider : Package, IContractsPackage, IVsSolutionEvents, IVsUpdateSolutionEvents2, IOleComponent { public const string InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate = "The snapshot is out of date"; public const string COMExceptionMessage_BindingFailed = "Binding failed because IntelliSense for source file"; @@ -54,12 +51,11 @@ public sealed class VSServiceProvider : Package, IVsSolutionEvents, IVsUpdateSol public const int LeaderBoardMask = LeaderBoardToolId << 12; const string CrashMailRecepients = "ccixfb@microsoft.com"; - private static VSServiceProvider current; public static VSServiceProvider Current { get { Contract.Ensures(Contract.Result() != null); - return current; + return (VSServiceProvider)ContractsPackageAccessor.Current; } } public readonly Logger logger; @@ -74,7 +70,7 @@ public Logger Logger } public bool InBuild { get; private set; } - IDECompilerHost _compilerHost; + ICompilerHost _compilerHost; DTE _dte; uint _componentID; bool _solutionLoaded = false; @@ -114,7 +110,15 @@ public ContractOptionsPage VSOptionsPage } } - public event Action NewCompilation; + IContractOptionsPage IContractsPackage.VSOptionsPage + { + get + { + return VSOptionsPage; + } + } + + public event Action NewCompilation; public event Action BuildDone; public event Action BuildBegin; public event Action ExtensionFailed; @@ -133,7 +137,7 @@ void Invariants() { /// Sets VSSeriviceProvider.Current. /// public VSServiceProvider() { - current = this; + ContractsPackageAccessor.Current = this; _startTime = DateTime.Now; #if false @@ -262,6 +266,13 @@ public VSProject GetProjectForFile(string fileName) { return null; } + public IVersionedServicesFactory GetVersionedServicesFactory() { + int vsMajorVersion = typeof(ErrorHandler).Assembly.GetName().Version.Major; + string assemblyName = "ContractAdornments.CSharp." + vsMajorVersion; + Assembly assembly = Assembly.Load(assemblyName); + return (IVersionedServicesFactory)assembly.CreateInstance("ContractAdornments.CSharp.VersionedServicesFactory"); + } + NonlockingHost CreateHost(Version version) { string[] libpaths = null; @@ -534,7 +545,7 @@ void AskToReportError(Exception exn) { void SolutionOpened() { Logger.PublicEntry(() => { try { - this._compilerHost = new IDECompilerHost(); + this._compilerHost = GetVersionedServicesFactory().CreateCompilerHost(); } catch { this._compilerHost = null; } @@ -606,13 +617,13 @@ public void QueueWorkItem(Action action) { _workItems.Enqueue(action); } - public void AskForNewVSModel() { + public void AskForNewVSModel(ITextBuffer textBuffer) { if (!_isGettingVSModel) { - QueueWorkItem(GetNewModel); + QueueWorkItem(() => GetNewModel(textBuffer)); _isGettingVSModel = true; } } - void GetNewModel() { + void GetNewModel(ITextBuffer textBuffer) { _isGettingVSModel = false; if (InBuild || _compilerHost == null || _compilerHost.Compilers == null) { // AskForNewVSModel(); @@ -637,7 +648,7 @@ void GetNewModel() { } } #endif - var compilation = compiler.GetCompilation(); + var compilation = compiler.GetCompilation(textBuffer); var reportNewCompilation = this.NewCompilation; if (reportNewCompilation != null) { @@ -652,7 +663,7 @@ void GetNewModel() { { //For some reason, occasionaly InvalidOperationExceptions can be thrown when operating on the semantic tree. Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception, it's snapshot is out of date."); - AskForNewVSModel(); + AskForNewVSModel(textBuffer); return; } else @@ -666,7 +677,7 @@ void GetNewModel() { { //For some reason, occasionaly InvalidOperationExceptions can be thrown when operating on the semantic tree. Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception, it's snapshot is out of date."); - AskForNewVSModel(); + AskForNewVSModel(textBuffer); return; } else @@ -705,30 +716,6 @@ public int FDoIdle(uint grfidlef) { return 0; } - static public bool IsModelReady(ParseTree parseTree) { - Contract.Requires(parseTree != null); - - try { - if (parseTree == null) - return false; - - var rootNode = parseTree.RootNode; - - } catch (InvalidOperationException e) { - if (e.Message.Contains(InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) - return false; - else - throw e; - } catch (COMException e) { - if (e.Message.Contains(COMExceptionMessage_BindingFailed)) - return false; - else - throw e; - } - - return true; - } - #if false /// /// Don't call this!!! diff --git a/Microsoft.Research/ContractAdornments/Extension/packages.config b/Microsoft.Research/ContractAdornments/Extension/packages.config new file mode 100644 index 00000000..a07ab7cf --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Extension/packages.config @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/Extension/source.extension.vsixmanifest b/Microsoft.Research/ContractAdornments/Extension/source.extension.vsixmanifest new file mode 100644 index 00000000..b652a6f2 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Extension/source.extension.vsixmanifest @@ -0,0 +1,50 @@ + + + + Code Contracts Editor Extensions + Microsoft Research + 1.8.10107.10 + Displays Code Contracts (when editing C#) in code, IntelliSense, and in metadata files. + +Inheritance: +Displays contracts on methods with inherited contracts, or on interface/abstract methods + +Metadata: +Displays contracts on metadata files. + +Quick Info: +Displays contracts in Quick Info tool tips. + +Signature Help: +Displays contracts in Signature Help tool tips. + 1033 + http://visualstudiogallery.msdn.microsoft.com/1ec7db13-3363-46c9-851f-1ce455f66970 + AdornmentsEULA.rtf + QuickInfo_Large.png + QuickInfo_Large.png + + + Pro + VST_All + + + Pro + VST_All + + + Pro + VST_All + + + Pro + VST_All + + + + + + + |%CurrentProject%| + |%CurrentProject%| + + diff --git a/Microsoft.Research/ContractAdornments/Interfaces/ContractAdornments.Interfaces.csproj b/Microsoft.Research/ContractAdornments/Interfaces/ContractAdornments.Interfaces.csproj new file mode 100644 index 00000000..cecfc896 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/ContractAdornments.Interfaces.csproj @@ -0,0 +1,298 @@ + + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {B0C91C82-C1D8-4697-B07E-18E17D11EB41} + Library + Properties + ContractAdornments.Interfaces + CodeContractsHelper.Interfaces + v4.0 + 512 + obj\ + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + False + C:\Users\a-darylz\Documents\CCI\Microsoft.Research\ContractAdornments + False + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\Devlab9\ + + + full + AnyCPU + true + GlobalSuppressions.cs + prompt + true + AllRules.ruleset + False + + + true + bin\Academic9\ + true + full + AnyCPU + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + true + bin\Internal9\ + + + full + AnyCPU + true + GlobalSuppressions.cs + prompt + true + AllRules.ruleset + False + + + true + bin\Devlab9ro\ + true + full + AnyCPU + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + + + true + bin\Debug64\ + DEBUG;TRACE + full + AnyCPU + bin\Debug\CodeContractsHelper.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + + + bin\Internal64\ + TRACE + true + pdbonly + AnyCPU + bin\Release\CodeContractsHelper.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + true + bin\Devlab64\ + DEBUG;TRACE + full + AnyCPU + bin\Debug\CodeContractsHelper.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + false + + + + False + ..\..\..\packages\VSSDK.DTE.7.0.4\lib\net20\envdte.dll + False + + + False + ..\..\ImportedCCI2\Microsoft.Cci.Analysis.ControlAndDataFlowGraph.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.CodeModel.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.CodeModelToIL.dll + + + ..\..\ImportedCCI2\Microsoft.Cci.ContractExtractor.dll + + + ..\..\ImportedCCI2\Microsoft.Cci.CSharpSourceEmitter.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.ILGenerator.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.MetadataHelper.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.MetadataModel.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.MutableCodeModel.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.MutableMetadataModel.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.NewILToCodeModel.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.PdbReader.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.PdbWriter.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.PEReader.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.PeWriter.dll + + + False + ..\..\ImportedCCI2\Microsoft.Cci.SourceModel.dll + + + + ..\..\..\packages\VSSDK.CoreUtility.10.0.4\lib\net40\Microsoft.VisualStudio.CoreUtility.dll + False + + + ..\..\..\packages\VSSDK.Language.10.0.4\lib\net40\Microsoft.VisualStudio.Language.Intellisense.dll + False + + + ..\..\..\packages\VSSDK.Language.10.0.4\lib\net40\Microsoft.VisualStudio.Language.StandardClassification.dll + False + + + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.Data.dll + False + + + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.Logic.dll + False + + + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.UI.dll + False + + + ..\..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.UI.Wpf.dll + False + + + + + False + ..\..\..\packages\VSSDK.DTE.7.0.4\lib\net20\stdole.dll + False + + + + + + + + + + False + ..\..\..\packages\VSSDK.VSLangProj.7.0.4\lib\net20\VSLangProj.dll + False + + + False + ..\..\..\packages\VSSDK.VSLangProj.7.0.4\lib\net20\VSLangProj2.dll + False + + + + + + Version\version.cs + + + + + + + + + + + + + + + + + + + + {784aa6a9-013e-4d8e-82d6-934571cf1357} + Adornments + + + {E47A869B-4B78-41B3-AF6E-1D51B2D1AD3B} + Utilities + + + + + \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/Interfaces/ICompiler.cs b/Microsoft.Research/ContractAdornments/Interfaces/ICompiler.cs new file mode 100644 index 00000000..5e4cfb9e --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/ICompiler.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.Interfaces +{ + using Microsoft.VisualStudio.Text; + + public interface ICompiler + { + object GetCompilation(ITextBuffer textBuffer); + } +} diff --git a/Microsoft.Research/ContractAdornments/Interfaces/ICompilerHost.cs b/Microsoft.Research/ContractAdornments/Interfaces/ICompilerHost.cs new file mode 100644 index 00000000..bcf4822e --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/ICompilerHost.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.Interfaces +{ + using System.Collections.Generic; + + public interface ICompilerHost + { + IEnumerable Compilers + { + get; + } + } +} diff --git a/Microsoft.Research/ContractAdornments/Interfaces/IContractOptionsPage.cs b/Microsoft.Research/ContractAdornments/Interfaces/IContractOptionsPage.cs new file mode 100644 index 00000000..450f7ed6 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/IContractOptionsPage.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.Interfaces +{ + public interface IContractOptionsPage + { + bool SmartFormatting + { + get; + } + + bool SyntaxColoring + { + get; + } + + bool CollapseMetadataContracts + { + get; + } + + bool Caching + { + get; + } + +#if false + bool InheritanceOnMethods + { + get; + } + + bool InheritanceOnProperties + { + get; + } +#endif + } +} diff --git a/Microsoft.Research/ContractAdornments/Interfaces/IContractsPackage.cs b/Microsoft.Research/ContractAdornments/Interfaces/IContractsPackage.cs new file mode 100644 index 00000000..4daa2161 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/IContractsPackage.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.Interfaces +{ + using System; + using Microsoft.VisualStudio.Text; + using UtilitiesNamespace; + + public interface IContractsPackage + { + event Action NewCompilation; + event Action ExtensionFailed; + + Logger Logger + { + get; + } + + IContractOptionsPage VSOptionsPage + { + get; + } + + IVersionedServicesFactory GetVersionedServicesFactory(); + + void QueueWorkItem(Action action, Func condition, bool requeueIfConditionIsntMet = true); + + void QueueWorkItem(Action action); + + void AskForNewVSModel(ITextBuffer textBuffer); + } +} diff --git a/Microsoft.Research/ContractAdornments/Interfaces/IContractsProvider.cs b/Microsoft.Research/ContractAdornments/Interfaces/IContractsProvider.cs new file mode 100644 index 00000000..cd6f297d --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/IContractsProvider.cs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.Interfaces +{ + public interface IContractsProvider + { + void Clear(); + } +} diff --git a/Microsoft.Research/ContractAdornments/Interfaces/INonlockingHost.cs b/Microsoft.Research/ContractAdornments/Interfaces/INonlockingHost.cs new file mode 100644 index 00000000..1824b0cc --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/INonlockingHost.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.Interfaces +{ + using Microsoft.Cci.Contracts; + + public interface INonlockingHost : IContractAwareHost + { + void AddLibPath(string path); + } +} diff --git a/Microsoft.Research/ContractAdornments/Interfaces/IProjectTracker.cs b/Microsoft.Research/ContractAdornments/Interfaces/IProjectTracker.cs new file mode 100644 index 00000000..0508fbe8 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/IProjectTracker.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.Interfaces +{ + using System; + using Microsoft.Cci; + using VSLangProj; + + public interface IProjectTracker + { + event Action BuildBegin; + event Action BuildDone; + + string ProjectName + { + get; + } + + AssemblyIdentity AssemblyIdentity + { + get; + } + + INonlockingHost Host + { + get; + } + + References References + { + get; + } + + IContractsProvider ContractsProvider + { + get; + } + } +} diff --git a/Microsoft.Research/ContractAdornments/Interfaces/ITextViewTracker.cs b/Microsoft.Research/ContractAdornments/Interfaces/ITextViewTracker.cs new file mode 100644 index 00000000..14da11cb --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/ITextViewTracker.cs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.Interfaces +{ + public interface ITextViewTracker + { + } +} diff --git a/Microsoft.Research/ContractAdornments/Interfaces/IVersionedServicesFactory.cs b/Microsoft.Research/ContractAdornments/Interfaces/IVersionedServicesFactory.cs new file mode 100644 index 00000000..6a6ef37e --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/IVersionedServicesFactory.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments.Interfaces +{ + using Adornments; + using Microsoft.VisualStudio.Language.Intellisense; + using Microsoft.VisualStudio.Text; + using Microsoft.VisualStudio.Text.Editor; + + public interface IVersionedServicesFactory + { + ICompilerHost CreateCompilerHost(); + + ITextViewTracker CreateTextViewTracker(IWpfTextView textView, IProjectTracker projectTracker, VSTextProperties vsTextProperties); + + IContractsProvider CreateContractsProvider(IProjectTracker projectTracker); + + IQuickInfoSource CreateQuickInfoSource(ITextBuffer textBuffer, ITextViewTracker textViewTracker); + + ISignatureHelpSource CreateSignatureHelpSource(ITextBuffer textBuffer, ITextViewTracker textViewTracker); + } +} diff --git a/Microsoft.Research/ContractAdornments/Sources/Delegates.cs b/Microsoft.Research/ContractAdornments/Interfaces/Properties/AssemblyInfo.cs similarity index 63% rename from Microsoft.Research/ContractAdornments/Sources/Delegates.cs rename to Microsoft.Research/ContractAdornments/Interfaces/Properties/AssemblyInfo.cs index 80ba2fef..b44cfdb5 100644 --- a/Microsoft.Research/ContractAdornments/Sources/Delegates.cs +++ b/Microsoft.Research/ContractAdornments/Interfaces/Properties/AssemblyInfo.cs @@ -12,13 +12,23 @@ // // THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -using Microsoft.RestrictedUsage.CSharp.Compiler; +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.InteropServices; -namespace ContractAdornments { +[assembly: AssemblyTitle("ContractAdornments.Interfaces")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +//[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ContractAdornments.Interfaces")] +//[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: CLSCompliant(false)] +[assembly: NeutralResourcesLanguage("en-US")] +//[assembly: AssemblyVersion("1.0.0812.6")] +//[assembly: AssemblyFileVersion("1.0.0812.6")] - public delegate void NewSyntacticInfo(SourceFile tree, string sourceFileName); - public delegate void NewSemanticInfo(Compilation comp); - public delegate void BuildBegin(string project); - public delegate void WriteAction(string message); - -} \ No newline at end of file +//[assembly:ContractVerification(false)] \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/Interfaces/VSServiceProvider/ContractsPackageAccessor.cs b/Microsoft.Research/ContractAdornments/Interfaces/VSServiceProvider/ContractsPackageAccessor.cs new file mode 100644 index 00000000..859b74d8 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/VSServiceProvider/ContractsPackageAccessor.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments +{ + using ContractAdornments.Interfaces; + + public static class ContractsPackageAccessor + { + public const string InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate = "The snapshot is out of date"; + public const string COMExceptionMessage_BindingFailed = "Binding failed because IntelliSense for source file"; + + public static IContractsPackage Current + { + get; + set; + } + } +} diff --git a/Microsoft.Research/ContractAdornments/Interfaces/VSServiceProvider/TextViewTrackerAccessor.cs b/Microsoft.Research/ContractAdornments/Interfaces/VSServiceProvider/TextViewTrackerAccessor.cs new file mode 100644 index 00000000..1c1fdd2a --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/VSServiceProvider/TextViewTrackerAccessor.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ContractAdornments +{ + using System.Diagnostics.Contracts; + using Adornments; + using ContractAdornments.Interfaces; + using Microsoft.VisualStudio.Text; + using Microsoft.VisualStudio.Text.Editor; + + public static class TextViewTrackerAccessor + { + public static readonly object TextViewTrackerKey = typeof(ITextViewTracker); + + [ContractVerification(false)] + public static ITextViewTracker GetOrCreateTextViewTracker(IWpfTextView textView, IProjectTracker projectTracker, VSTextProperties vsTextProperties) + { + Contract.Requires(textView != null); + Contract.Requires(projectTracker != null); + Contract.Ensures(Contract.Result() != null); + return textView.TextBuffer.Properties.GetOrCreateSingletonProperty(TextViewTrackerAccessor.TextViewTrackerKey, delegate + { + return ContractsPackageAccessor.Current.GetVersionedServicesFactory().CreateTextViewTracker(textView, projectTracker, vsTextProperties); + }); + } + + public static bool TryGetTextViewTracker(ITextBuffer textBuffer, out ITextViewTracker textViewTracker) + { + Contract.Requires(textBuffer != null); + if (textBuffer.Properties == null) + { + textViewTracker = null; + return false; + } + + return textBuffer.Properties.TryGetProperty(TextViewTrackerAccessor.TextViewTrackerKey, out textViewTracker); + } + } +} diff --git a/Microsoft.Research/ContractAdornments/Interfaces/packages.config b/Microsoft.Research/ContractAdornments/Interfaces/packages.config new file mode 100644 index 00000000..2806c6b2 --- /dev/null +++ b/Microsoft.Research/ContractAdornments/Interfaces/packages.config @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/VS2010/References/Microsoft.VisualStudio.CSharp.Services.Language.Interop.dll b/Microsoft.Research/ContractAdornments/VS2010/References/Microsoft.VisualStudio.CSharp.Services.Language.Interop.dll deleted file mode 100644 index 02c892cb..00000000 Binary files a/Microsoft.Research/ContractAdornments/VS2010/References/Microsoft.VisualStudio.CSharp.Services.Language.Interop.dll and /dev/null differ diff --git a/Microsoft.Research/ContractAdornments/VS2010/References/Microsoft.VisualStudio.CSharp.Services.Language.dll b/Microsoft.Research/ContractAdornments/VS2010/References/Microsoft.VisualStudio.CSharp.Services.Language.dll deleted file mode 100644 index 52527b23..00000000 Binary files a/Microsoft.Research/ContractAdornments/VS2010/References/Microsoft.VisualStudio.CSharp.Services.Language.dll and /dev/null differ diff --git a/Microsoft.Research/ContractAdornments/VS2010/source.extension.vsixmanifest b/Microsoft.Research/ContractAdornments/VS2010/source.extension.vsixmanifest deleted file mode 100644 index 5723a6b5..00000000 --- a/Microsoft.Research/ContractAdornments/VS2010/source.extension.vsixmanifest +++ /dev/null @@ -1,38 +0,0 @@ - - - - Code Contracts Editor Extensions VS2010 - Microsoft Research - 1.9.0629.42 - Displays Code Contracts (when editing C#) in code, Intellisense, and in metadata files. - -Inheritance: -Displays contract information on methods with inherited contract information, or on interface/abstract methods - -Metadata: -Displays contract information in metadata files. - -Quick Info: -Displays contract information in Quick Info tool tips. - -Signature Help: -Displays contract information in Signature Help tool tips. - 1033 - http://research.microsoft.com/contracts - AdornmentsEULA.rtf - QuickInfo_Large.png - QuickInfo_Large.png - - - Pro - VST_All - - - - - - - CodeContractsHelper_Package.pkgdef - CodeContractsHelper.dll - - \ No newline at end of file diff --git a/Microsoft.Research/ContractAdornments/VS2012/References/Microsoft.VisualStudio.CSharp.Services.Language.Interop.dll b/Microsoft.Research/ContractAdornments/VS2012/References/Microsoft.VisualStudio.CSharp.Services.Language.Interop.dll deleted file mode 100644 index 2887545f..00000000 Binary files a/Microsoft.Research/ContractAdornments/VS2012/References/Microsoft.VisualStudio.CSharp.Services.Language.Interop.dll and /dev/null differ diff --git a/Microsoft.Research/ContractAdornments/VS2012/References/Microsoft.VisualStudio.CSharp.Services.Language.dll b/Microsoft.Research/ContractAdornments/VS2012/References/Microsoft.VisualStudio.CSharp.Services.Language.dll deleted file mode 100644 index 936123e8..00000000 Binary files a/Microsoft.Research/ContractAdornments/VS2012/References/Microsoft.VisualStudio.CSharp.Services.Language.dll and /dev/null differ diff --git a/Microsoft.Research/ContractAdornments/VS2012/source.extension.vsixmanifest b/Microsoft.Research/ContractAdornments/VS2012/source.extension.vsixmanifest deleted file mode 100644 index f65c1817..00000000 --- a/Microsoft.Research/ContractAdornments/VS2012/source.extension.vsixmanifest +++ /dev/null @@ -1,38 +0,0 @@ - - - - - Code Contracts Editor Extensions VS2012 - Displays Code Contracts (when editing C#) in code, Intellisense, and in metadata files. - -Inheritance: -Displays contracts on methods with inherited contracts, or on interface/abstract methods - -Metadata: -Displays contracts on metadata files. - -Quick Info: -Displays contracts in Quick Info tool tips. - -Signature Help: -Displays contracts in Signature Help tool tips. - http://visualstudiogallery.msdn.microsoft.com/1ec7db13-3363-46c9-851f-1ce455f66970 - AdornmentsEULA.rtf - QuickInfo_Large.png - QuickInfo_Large.png - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Microsoft.Research/ManagedContract.Setup/buildMSI.bat b/Microsoft.Research/ManagedContract.Setup/buildMSI.bat index 5108958b..57cc43ba 100644 --- a/Microsoft.Research/ManagedContract.Setup/buildMSI.bat +++ b/Microsoft.Research/ManagedContract.Setup/buildMSI.bat @@ -1,4 +1,8 @@ @echo off + +rem Make sure NuGet packages are restored before proceeding with the build +..\..\.nuget\NuGet.exe restore ..\..\CodeContracts.sln + if "%2" == "" goto nonetlabel echo Build %2 version (%1) diff --git a/Microsoft.Research/ManagedContract.Setup/buildMSI10.xml b/Microsoft.Research/ManagedContract.Setup/buildMSI10.xml index f2a0f796..b85554e8 100644 --- a/Microsoft.Research/ManagedContract.Setup/buildMSI10.xml +++ b/Microsoft.Research/ManagedContract.Setup/buildMSI10.xml @@ -216,13 +216,7 @@ Namespaces="$(Vsix10Namespace)" Query="//vsx:Identifier/vsx:Version" Value="$(CCNetLabel)" - XmlInputPath="..\ContractAdornments\VS2010\source.extension.vsixmanifest" /> - - + XmlInputPath="..\ContractAdornments\Extension\source.extension.vsixmanifest" /> + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Common.CodeContracts.props)) @@ -140,6 +140,8 @@ False + ..\..\packages\VSSDK.DTE.7.0.4\lib\net20\envdte.dll + False False @@ -151,8 +153,23 @@ 3.5 - - + + ..\..\packages\VSSDK.OLE.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.OLE.Interop.dll + False + + + ..\..\packages\VSSDK.Shell.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.dll + False + + + ..\..\packages\VSSDK.TextManager.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.dll + False + + + False + ..\..\packages\VSSDK.DTE.7.0.4\lib\net20\stdole.dll + False + @@ -166,6 +183,7 @@ Contracts.snk + diff --git a/Microsoft.Research/MsBuildCodeContracts/packages.config b/Microsoft.Research/MsBuildCodeContracts/packages.config new file mode 100644 index 00000000..de327549 --- /dev/null +++ b/Microsoft.Research/MsBuildCodeContracts/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Research/VSAdornments/Sources/AdornmentManager.cs b/Microsoft.Research/VSAdornments/AdornmentManager.cs similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/AdornmentManager.cs rename to Microsoft.Research/VSAdornments/AdornmentManager.cs diff --git a/Microsoft.Research/VSAdornments/VS2010/Adornments.csproj b/Microsoft.Research/VSAdornments/Adornments.csproj similarity index 80% rename from Microsoft.Research/VSAdornments/VS2010/Adornments.csproj rename to Microsoft.Research/VSAdornments/Adornments.csproj index 5688328a..3b68702e 100644 --- a/Microsoft.Research/VSAdornments/VS2010/Adornments.csproj +++ b/Microsoft.Research/VSAdornments/Adornments.csproj @@ -1,4 +1,4 @@ - + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Common.CodeContracts.props)) @@ -133,25 +133,48 @@ False - ..\..\ImportedCCI2\Microsoft.Cci.CodeModel.dll + ..\ImportedCCI2\Microsoft.Cci.CodeModel.dll False - ..\..\ImportedCCI2\Microsoft.Cci.MetadataHelper.dll + ..\ImportedCCI2\Microsoft.Cci.MetadataHelper.dll False - ..\..\ImportedCCI2\Microsoft.Cci.MetadataModel.dll + ..\ImportedCCI2\Microsoft.Cci.MetadataModel.dll + + + ..\..\packages\VSSDK.CoreUtility.10.0.4\lib\net40\Microsoft.VisualStudio.CoreUtility.dll + False + + + ..\..\packages\VSSDK.Language.10.0.4\lib\net40\Microsoft.VisualStudio.Language.Intellisense.dll + False + + + ..\..\packages\VSSDK.Language.10.0.4\lib\net40\Microsoft.VisualStudio.Language.StandardClassification.dll + False + + + ..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.Data.dll + False + + + ..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.Logic.dll + False + + + ..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.UI.dll + False + + + ..\..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.UI.Wpf.dll + False - - - - - - + @@ -165,26 +188,29 @@ version.cs - - - - - - - + + ContractAdornment.xaml - - + + + + + + + - + Designer MSBuild:Compile - + + + + {E47A869B-4B78-41B3-AF6E-1D51B2D1AD3B} Utilities diff --git a/Microsoft.Research/VSAdornments/Sources/ContractAdornment.xaml b/Microsoft.Research/VSAdornments/ContractAdornment.xaml similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/ContractAdornment.xaml rename to Microsoft.Research/VSAdornments/ContractAdornment.xaml diff --git a/Microsoft.Research/VSAdornments/Sources/ContractAdornment.xaml.cs b/Microsoft.Research/VSAdornments/ContractAdornment.xaml.cs similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/ContractAdornment.xaml.cs rename to Microsoft.Research/VSAdornments/ContractAdornment.xaml.cs diff --git a/Microsoft.Research/VSAdornments/Sources/IAdornment.cs b/Microsoft.Research/VSAdornments/IAdornment.cs similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/IAdornment.cs rename to Microsoft.Research/VSAdornments/IAdornment.cs diff --git a/Microsoft.Research/VSAdornments/Sources/IStaticAdornment.cs b/Microsoft.Research/VSAdornments/IStaticAdornment.cs similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/IStaticAdornment.cs rename to Microsoft.Research/VSAdornments/IStaticAdornment.cs diff --git a/Microsoft.Research/VSAdornments/Sources/InheritanceContractAdornment.cs b/Microsoft.Research/VSAdornments/InheritanceContractAdornment.cs similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/InheritanceContractAdornment.cs rename to Microsoft.Research/VSAdornments/InheritanceContractAdornment.cs diff --git a/Microsoft.Research/VSAdornments/Sources/Logger.cs b/Microsoft.Research/VSAdornments/Logger.cs similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/Logger.cs rename to Microsoft.Research/VSAdornments/Logger.cs diff --git a/Microsoft.Research/VSAdornments/Sources/MetadataContractAdornment.cs b/Microsoft.Research/VSAdornments/MetadataContractAdornment.cs similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/MetadataContractAdornment.cs rename to Microsoft.Research/VSAdornments/MetadataContractAdornment.cs diff --git a/Microsoft.Research/VSAdornments/Sources/Properties/AssemblyInfo.cs b/Microsoft.Research/VSAdornments/Properties/AssemblyInfo.cs similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/Properties/AssemblyInfo.cs rename to Microsoft.Research/VSAdornments/Properties/AssemblyInfo.cs diff --git a/Microsoft.Research/VSAdornments/Sources/PurityAdornment.cs b/Microsoft.Research/VSAdornments/PurityAdornment.cs similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/PurityAdornment.cs rename to Microsoft.Research/VSAdornments/PurityAdornment.cs diff --git a/Microsoft.Research/VSAdornments/VS2012/Adornments11.csproj b/Microsoft.Research/VSAdornments/VS2012/Adornments11.csproj deleted file mode 100644 index 3599a1cc..00000000 --- a/Microsoft.Research/VSAdornments/VS2012/Adornments11.csproj +++ /dev/null @@ -1,210 +0,0 @@ - - - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Common.CodeContracts.props)) - - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {235196BB-603A-470A-AF8E-EF6C8D01C4DC} - Library - Properties - Adornments - AdornmentManager - v4.5 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - true - bin\Devlab9\ - - - full - AnyCPU - true - GlobalSuppressions.cs - prompt - true - AllRules.ruleset - false - - - true - bin\Academic9\ - true - full - AnyCPU - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - false - - - true - bin\Internal9\ - - - full - AnyCPU - true - GlobalSuppressions.cs - prompt - true - AllRules.ruleset - false - - - true - bin\Devlab9ro\ - true - full - AnyCPU - true - GlobalSuppressions.cs - prompt - AllRules.ruleset - false - - - true - bin\Debug64\ - DEBUG;TRACE - full - AnyCPU - bin\Debug\AdornmentManager.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - false - false - false - - - bin\Internal64\ - TRACE - true - pdbonly - AnyCPU - bin\Release\AdornmentManager.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - false - - - true - bin\Devlab64\ - DEBUG;TRACE - full - AnyCPU - bin\Debug\AdornmentManager.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - false - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - false - - - - False - ..\..\ImportedCCI2\Microsoft.Cci.CodeModel.dll - - - False - ..\..\ImportedCCI2\Microsoft.Cci.MetadataHelper.dll - - - False - ..\..\ImportedCCI2\Microsoft.Cci.MetadataModel.dll - - - - - - - - - - - - - - - - - - - - - - version.cs - - - - - - - - - ContractAdornment.xaml - - - - - - - Designer - MSBuild:Compile - - - - - {E47A869B-4B78-41B3-AF6E-1D51B2D1AD3B} - Utilities - - - - - diff --git a/Microsoft.Research/VSAdornments/Sources/VSTextPropertiesProvider.cs b/Microsoft.Research/VSAdornments/VSTextPropertiesProvider.cs similarity index 100% rename from Microsoft.Research/VSAdornments/Sources/VSTextPropertiesProvider.cs rename to Microsoft.Research/VSAdornments/VSTextPropertiesProvider.cs diff --git a/Microsoft.Research/VSAdornments/packages.config b/Microsoft.Research/VSAdornments/packages.config new file mode 100644 index 00000000..9a528c51 --- /dev/null +++ b/Microsoft.Research/VSAdornments/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file