From a2469ef84da4a4748bb5e6572485058416b8a954 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Tue, 31 Jan 2006 16:25:25 +0000 Subject: [PATCH] Added code coverage addin - supports NCover. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1057 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../image/BitmapResources/BitmapResources.res | 3 + .../CodeCoverage.Icons.16x16.File.png | Bin 0 -> 580 bytes .../CodeCoverage.Icons.16x16.Pad.png | Bin 0 -> 619 bytes .../CodeCoverage.Icons.16x16.Run.png | Bin 0 -> 167 bytes src/AddIns/Misc/CodeCoverage/CodeCoverage.sln | 68 +++++ .../CodeCoverage/Project/CodeCoverage.addin | 106 +++++++ .../CodeCoverage/Project/CodeCoverage.csproj | 111 +++++++ .../Project/Configuration/AssemblyInfo.cs | 35 +++ .../CodeCoverage/Project/PostBuildEvent.proj | 11 + .../Resources/CodeCoverageOptionsPanel.xfrm | 142 +++++++++ .../CodeCoverageProjectOptionsPanel.xfrm | 23 ++ .../CodeCoverageRunnerNotFoundForm.xfrm | 50 +++ ...AbstractRunTestsWithCodeCoverageCommand.cs | 287 ++++++++++++++++++ .../Project/Src/CodeCoverageClassTreeNode.cs | 32 ++ .../Project/Src/CodeCoverageControl.cs | 158 ++++++++++ .../Project/Src/CodeCoverageDisplayItem.cs | 85 ++++++ .../Project/Src/CodeCoverageException.cs | 27 ++ .../Project/Src/CodeCoverageHighlighter.cs | 107 +++++++ .../Project/Src/CodeCoverageMethod.cs | 104 +++++++ .../Project/Src/CodeCoverageMethodTreeNode.cs | 54 ++++ .../Project/Src/CodeCoverageModule.cs | 64 ++++ .../Project/Src/CodeCoverageModuleTreeNode.cs | 126 ++++++++ .../Src/CodeCoverageNamespaceTreeNode.cs | 21 ++ .../Project/Src/CodeCoverageOptions.cs | 123 ++++++++ .../Project/Src/CodeCoverageOptionsPanel.cs | 137 +++++++++ .../Project/Src/CodeCoveragePad.cs | 89 ++++++ .../Src/CodeCoverageProjectOptionsPanel.cs | 69 +++++ .../Project/Src/CodeCoverageResults.cs | 102 +++++++ .../Src/CodeCoverageRunnerNotFoundForm.cs | 33 ++ .../Project/Src/CodeCoverageSequencePoint.cs | 67 ++++ .../Project/Src/CodeCoverageService.cs | 150 +++++++++ .../Project/Src/CodeCoverageTextMarker.cs | 49 +++ .../Project/Src/CodeCoverageTreeNode.cs | 83 +++++ .../Project/Src/CodeCoverageTreeView.cs | 29 ++ .../Project/Src/ColorPickerComboBox.cs | 144 +++++++++ .../Project/Src/LineReceivedEventArgs.cs | 32 ++ .../CodeCoverage/Project/Src/MbUnitResults.cs | 113 +++++++ .../Project/Src/NCoverExitEventArgs.cs | 58 ++++ .../CodeCoverage/Project/Src/NCoverRunner.cs | 255 ++++++++++++++++ .../Project/Src/NCoverRunnerSingleton.cs | 36 +++ .../Project/Src/NCoverSettings.cs | 97 ++++++ .../CodeCoverage/Project/Src/OutputReader.cs | 98 ++++++ .../CodeCoverage/Project/Src/ProcessRunner.cs | 266 ++++++++++++++++ .../Project/Src/ProcessRunnerException.cs | 23 ++ ...unMbUnitPadTestsWithCodeCoverageCommand.cs | 37 +++ .../RunTestFixtureWithCodeCoverageCommand.cs | 47 +++ .../Src/RunTestWithCodeCoverageCommand.cs | 46 +++ .../Project/Src/ToggleCodeCoverageCommand.cs | 25 ++ .../Test/AddCodeCoverageMarkersTestFixture.cs | 144 +++++++++ .../Misc/CodeCoverage/Test/AssemblyInfo.cs | 27 ++ .../Test/CodeCoverage.Tests.csproj | 83 +++++ ...ageMarkersCoverMultipleLinesTestFixture.cs | 89 ++++++ ...CoverageMarkersCoverTwoLinesTestFixture.cs | 118 +++++++ ...erageMarkersInvalidEndColumnTestFixture.cs | 64 ++++ ...overageMarkersInvalidEndLineTestFixture.cs | 65 ++++ ...ageMarkersInvalidStartColumnTestFixture.cs | 63 ++++ ...erageMarkersInvalidStartLineTestFixture.cs | 62 ++++ .../Test/CodeCoverageResultsTestFixture.cs | 148 +++++++++ .../Test/CodeCoverageTreeViewTestFixture.cs | 166 ++++++++++ ...GetSequencePointsForFileNameTestFixture.cs | 78 +++++ .../Test/MbUnitResultsTestFixture.cs | 121 ++++++++ .../Misc/CodeCoverage/Test/MockDocument.cs | 276 +++++++++++++++++ .../ModuleVisitedSequencePointsTestFixture.cs | 75 +++++ .../Test/NCoverSettingsTestFixture.cs | 49 +++ .../RemoveCodeCoverageMarkersTestFixture.cs | 97 ++++++ .../Misc/CodeCoverage/Test/Strings.resources | Bin 0 -> 358 bytes src/AddIns/Misc/MbUnitPad/MbUnitPad.sln | 14 +- .../Misc/MbUnitPad/Project/Src/MbUnitPad.cs | 6 + .../MbUnitPad/Project/Src/TestTreeView.cs | 14 + .../Resources/BitmapResources.resources | Bin 554869 -> 556847 bytes src/SharpDevelop.sln | 9 +- 71 files changed, 5587 insertions(+), 3 deletions(-) create mode 100644 data/resources/image/BitmapResources/CodeCoverageIcons/CodeCoverage.Icons.16x16.File.png create mode 100644 data/resources/image/BitmapResources/CodeCoverageIcons/CodeCoverage.Icons.16x16.Pad.png create mode 100644 data/resources/image/BitmapResources/CodeCoverageIcons/CodeCoverage.Icons.16x16.Run.png create mode 100644 src/AddIns/Misc/CodeCoverage/CodeCoverage.sln create mode 100644 src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.addin create mode 100644 src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.csproj create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Configuration/AssemblyInfo.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/PostBuildEvent.proj create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageOptionsPanel.xfrm create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageProjectOptionsPanel.xfrm create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageRunnerNotFoundForm.xfrm create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/AbstractRunTestsWithCodeCoverageCommand.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageControl.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageDisplayItem.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageException.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageHighlighter.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethod.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethodTreeNode.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModule.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModuleTreeNode.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageNamespaceTreeNode.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageOptions.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageOptionsPanel.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoveragePad.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageProjectOptionsPanel.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageResults.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageRunnerNotFoundForm.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageSequencePoint.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageService.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTextMarker.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeNode.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeView.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/ColorPickerComboBox.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/LineReceivedEventArgs.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/MbUnitResults.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/NCoverExitEventArgs.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/NCoverRunner.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/NCoverRunnerSingleton.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/NCoverSettings.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/OutputReader.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/ProcessRunner.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/ProcessRunnerException.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/RunMbUnitPadTestsWithCodeCoverageCommand.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/RunTestFixtureWithCodeCoverageCommand.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/RunTestWithCodeCoverageCommand.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/ToggleCodeCoverageCommand.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/AddCodeCoverageMarkersTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/AssemblyInfo.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj create mode 100644 src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersCoverMultipleLinesTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersCoverTwoLinesTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidEndColumnTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidEndLineTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidStartColumnTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidStartLineTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/CodeCoverageResultsTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/CodeCoverageTreeViewTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/GetSequencePointsForFileNameTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/MbUnitResultsTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/MockDocument.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/ModuleVisitedSequencePointsTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/NCoverSettingsTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/RemoveCodeCoverageMarkersTestFixture.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/Strings.resources diff --git a/data/resources/image/BitmapResources/BitmapResources.res b/data/resources/image/BitmapResources/BitmapResources.res index a38078b97e..ffb82aa8ab 100644 --- a/data/resources/image/BitmapResources/BitmapResources.res +++ b/data/resources/image/BitmapResources/BitmapResources.res @@ -479,4 +479,7 @@ NAntAddIn.Icons.16x16.RunNAnt = NAntIcons\NAntAddIn.Icons.16x16.RunNA NAntAddIn.Icons.16x16.RunNAntClean = NAntIcons\NAntAddIn.Icons.16x16.RunNAntClean.png NAntAddIn.Icons.16x16.StopNAnt = NAntIcons\NAntAddIn.Icons.16x16.StopNAnt.png +CodeCoverage.Icons.16x16.Pad = CodeCoverageIcons\CodeCoverage.Icons.16x16.Pad.png +CodeCoverage.Icons.16x16.File = CodeCoverageIcons\CodeCoverage.Icons.16x16.File.png +CodeCoverage.Icons.16x16.Run = CodeCoverageIcons\CodeCoverage.Icons.16x16.Run.png diff --git a/data/resources/image/BitmapResources/CodeCoverageIcons/CodeCoverage.Icons.16x16.File.png b/data/resources/image/BitmapResources/CodeCoverageIcons/CodeCoverage.Icons.16x16.File.png new file mode 100644 index 0000000000000000000000000000000000000000..80b12316fc4bdc9cb330b0f4452e5ff8592c368e GIT binary patch literal 580 zcmV-K0=xZ*P)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy2XskIMF-Rj84?#CIg%3^kF5QRE5WPj=YjoXpg;4~eWmJ~o zMN)~Dr73C7Ig90xS((G}I25e@eM%wp9J^@4VqdLqt$**I@gf!!#FteLx19d z&U6Ef@fw@^HmG+kSYAJbY^Ko`L8bmF>b3fT@_QGhN*Beq4%T$1Skap0AqGo8G&AEf z>4}W_mkx5}wrFOWom(6Z(avlu7=W3l!9h{rFy-Vhxx-;%iNm;x>jM~sX3d@dp5-TsRE@o5lHj!C3$!gJZ@tR zxT7)vwf>yy3X;DtHcxL6kpZmg%m`8{o6|>$o;XY8;l6K>u?|P5279n3Jpy}OR#$2d zSc41y2!Q8jP8X#*!gXAQ>bMNl$XJE-t_F*@D&2rBMsHPx#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy2XskIMF-Rj8V?aWR-q$m0000NbVXQnQ*UN;cVTj608n9RZgehA zMN}YmGA=c|hspi`00FZ}L_t(IPpy+lFGFDzhW!H@3IBo(D^^x^R&3ZHkw_$1V1Yzp zNZ8oeuplWSh8WV+)R+@f1Z}BH+f=Kgs+Q`V`?}xPR(!+|+~llo&hxzQ$-NmF|MB!s z1<^h3N5`lKt-~%f4mwdcU`I{A4VAqd$~vtmZL^@H#f0Lf6BN}SqoDQ>c~$$M{yq)R zHReP6hzHF>ZZuGUg90jgIFxr@Fo41oAU6%rE$)Lns+xc#C%}sd#CQdd&k7<>GVY@? zf?*lHkciu$1Xn!lvI6!v!eecE&d5Nv#;lu=qR-FIIHlD=}xAziK1YU*(RHIG={;` L)z4*}Q$iB}At*5l literal 0 HcmV?d00001 diff --git a/src/AddIns/Misc/CodeCoverage/CodeCoverage.sln b/src/AddIns/Misc/CodeCoverage/CodeCoverage.sln new file mode 100644 index 0000000000..c00d9c5866 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/CodeCoverage.sln @@ -0,0 +1,68 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# SharpDevelop 2.0.0.960 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCoverage", "Project\CodeCoverage.csproj", "{B7F1A068-01F5-49E7-83EF-05DE281B09FD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCoverage.Tests", "Test\CodeCoverage.Tests.csproj", "{A5C0E8F8-9D04-46ED-91D6-1DEF1575313B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MbUnitPad", "..\MbUnitPad\Project\MbUnitPad.csproj", "{B1CE28A0-04E8-490D-8256-E0C4D52C93C8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TextEditor", "..\..\..\Libraries\ICSharpCode.TextEditor\Project\ICSharpCode.TextEditor.csproj", "{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "nunit.framework.dll", "..\..\..\Libraries\NUnit.Framework\nunit.framework.dll.csproj", "{83DD7E12-A705-4DBA-9D71-09C8973D9382}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinFormsUI", "..\..\..\Libraries\DockPanel_Src\WinFormsUI\WinFormsUI.csproj", "{D3C782BA-178E-4235-A3BA-8C11DEBB6BEE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core", "..\..\..\Main\Core\Project\ICSharpCode.Core.csproj", "{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop", "..\..\..\Main\Base\Project\ICSharpCode.SharpDevelop.csproj", "{2748AD25-9C63-4E12-877B-4DCE96FBED54}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "..\..\..\Libraries\NRefactory\Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B7F1A068-01F5-49E7-83EF-05DE281B09FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7F1A068-01F5-49E7-83EF-05DE281B09FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B7F1A068-01F5-49E7-83EF-05DE281B09FD}.Release|Any CPU.Build.0 = Release|Any CPU + {B7F1A068-01F5-49E7-83EF-05DE281B09FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5C0E8F8-9D04-46ED-91D6-1DEF1575313B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5C0E8F8-9D04-46ED-91D6-1DEF1575313B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5C0E8F8-9D04-46ED-91D6-1DEF1575313B}.Release|Any CPU.Build.0 = Release|Any CPU + {A5C0E8F8-9D04-46ED-91D6-1DEF1575313B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B1CE28A0-04E8-490D-8256-E0C4D52C93C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1CE28A0-04E8-490D-8256-E0C4D52C93C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B1CE28A0-04E8-490D-8256-E0C4D52C93C8}.Release|Any CPU.Build.0 = Release|Any CPU + {B1CE28A0-04E8-490D-8256-E0C4D52C93C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Any CPU.Build.0 = Release|Any CPU + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83DD7E12-A705-4DBA-9D71-09C8973D9382}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83DD7E12-A705-4DBA-9D71-09C8973D9382}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83DD7E12-A705-4DBA-9D71-09C8973D9382}.Release|Any CPU.Build.0 = Release|Any CPU + {83DD7E12-A705-4DBA-9D71-09C8973D9382}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3C782BA-178E-4235-A3BA-8C11DEBB6BEE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3C782BA-178E-4235-A3BA-8C11DEBB6BEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3C782BA-178E-4235-A3BA-8C11DEBB6BEE}.Release|Any CPU.Build.0 = Release|Any CPU + {D3C782BA-178E-4235-A3BA-8C11DEBB6BEE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Any CPU.Build.0 = Release|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|Any CPU.Build.0 = Release|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|Any CPU.Build.0 = Release|Any CPU + {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F6A02431-167E-4347-BC43-65532C31CDB7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F6A02431-167E-4347-BC43-65532C31CDB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F6A02431-167E-4347-BC43-65532C31CDB7}.Release|Any CPU.Build.0 = Release|Any CPU + {F6A02431-167E-4347-BC43-65532C31CDB7}.Release|Any CPU.ActiveCfg = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.addin b/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.addin new file mode 100644 index 0000000000..143630bdfe --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.addin @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.csproj b/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.csproj new file mode 100644 index 0000000000..39196ba579 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.csproj @@ -0,0 +1,111 @@ + + + Library + ICSharpCode.CodeCoverage + CodeCoverage + Debug + AnyCPU + {B7F1A068-01F5-49E7-83EF-05DE281B09FD} + False + False + False + Auto + 4194304 + AnyCPU + 4096 + 4 + false + + + ..\..\..\..\..\AddIns\AddIns\Misc\CodeCoverage\ + False + DEBUG;TRACE + true + Full + True + + + ..\..\..\..\..\AddIns\AddIns\Misc\CodeCoverage\ + True + TRACE + false + None + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + + {2748AD25-9C63-4E12-877B-4DCE96FBED54} + ICSharpCode.SharpDevelop + False + + + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C} + ICSharpCode.Core + False + + + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} + ICSharpCode.TextEditor + False + + + {B1CE28A0-04E8-490D-8256-E0C4D52C93C8} + MbUnitPad + False + + + + + + \ No newline at end of file diff --git a/src/AddIns/Misc/CodeCoverage/Project/Configuration/AssemblyInfo.cs b/src/AddIns/Misc/CodeCoverage/Project/Configuration/AssemblyInfo.cs new file mode 100644 index 0000000000..c833700cbb --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Configuration/AssemblyInfo.cs @@ -0,0 +1,35 @@ +// +// +// +// +// $Revision$ +// + + +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly: AssemblyTitle("CodeCoverage AddIn")] +[assembly: AssemblyDescription("CodeCoverage AddIn for SharpDevelop 2.0")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("ic#code")] +[assembly: AssemblyProduct("SharpDevelop")] +[assembly: AssemblyCopyright("2005-2006 AlphaSierraPapa")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly: AssemblyVersion("2.0.0.1")] + diff --git a/src/AddIns/Misc/CodeCoverage/Project/PostBuildEvent.proj b/src/AddIns/Misc/CodeCoverage/Project/PostBuildEvent.proj new file mode 100644 index 0000000000..fc90a12e77 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/PostBuildEvent.proj @@ -0,0 +1,11 @@ + + + $(PrepareForRunDependsOn);MyPostBuildTarget + + + + + + diff --git a/src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageOptionsPanel.xfrm b/src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageOptionsPanel.xfrm new file mode 100644 index 0000000000..814f35a34b --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageOptionsPanel.xfrm @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageProjectOptionsPanel.xfrm b/src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageProjectOptionsPanel.xfrm new file mode 100644 index 0000000000..da111d5b70 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageProjectOptionsPanel.xfrm @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageRunnerNotFoundForm.xfrm b/src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageRunnerNotFoundForm.xfrm new file mode 100644 index 0000000000..236976677f --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Resources/CodeCoverageRunnerNotFoundForm.xfrm @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/AbstractRunTestsWithCodeCoverageCommand.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/AbstractRunTestsWithCodeCoverageCommand.cs new file mode 100644 index 0000000000..f45c6cab2a --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/AbstractRunTestsWithCodeCoverageCommand.cs @@ -0,0 +1,287 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Project; +using System; +using System.IO; +using System.Reflection; +using System.Text; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Base class that provides an NCover runner to run tests + /// with code coverage + /// + public abstract class AbstractRunTestsWithCodeCoverageCommand : AbstractMenuCommand + { + static MessageViewCategory category; + static NCoverRunner runner; + + public AbstractRunTestsWithCodeCoverageCommand() + { + if (runner == null) { + runner = NCoverRunnerSingleton.Runner; + runner.NCoverExited += new NCoverExitEventHandler(NCoverExited); + runner.OutputLineReceived += new LineReceivedEventHandler(OutputLineReceived); + } + } + + public override void Run() + { + if (IsBuildRunning) { + throw new CodeCoverageException(); + } + + string ncoverFileName = GetNCoverFileName(); + if (ncoverFileName != null) { + SetNCoverRunnerProperties(ncoverFileName); + RunNCover(); + } else { + using (CodeCoverageRunnerNotFoundForm form = new CodeCoverageRunnerNotFoundForm()) { + form.ShowDialog(); + } + } + } + + /// + /// Returns the full filename of the assembly being tested. + /// + /// + protected virtual string GetTestAssemblyFileName() + { + return String.Empty; + } + + /// + /// Returns the project containing the tests. + /// + protected virtual IProject GetProject() + { + return null; + } + + bool IsBuildRunning { + get { + return runner.IsRunning; + } + } + + /// + /// Gets the message view output window. + /// + MessageViewCategory Category { + get { + if (category == null) { + category = new MessageViewCategory("Code Coverage"); + CompilerMessageView cmv = (CompilerMessageView)WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView)).PadContent; + cmv.AddCategory(category); + } + return category; + } + } + + /// + /// Writes a line of text to the output window. + /// + void CategoryWriteLine(string message) + { + Category.AppendText(String.Concat(message, Environment.NewLine)); + } + + /// + /// Brings output pad to the front. + /// + void ShowOutputPad() + { + WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView)).BringPadToFront(); + } + + bool FileNameExists(string fileName) + { + return fileName.Length > 0 && File.Exists(fileName); + } + + void SetNCoverRunnerProperties(string ncoverFileName) + { + IProject project = GetProject(); + string ncoverOutputDirectory = GetNCoverOutputDirectory(project); + runner.NCoverFileName = ncoverFileName; + runner.ProfiledApplicationCommand = GetMbUnitConsoleFileName(); + runner.ProfiledApplicationCommandLineArguments = GetMbUnitConsoleCommandLineArguments(ncoverOutputDirectory); + runner.WorkingDirectory = Path.GetDirectoryName(GetTestAssemblyFileName()); + runner.CoverageResultsFileName = Path.Combine(ncoverOutputDirectory, "Coverage.Xml"); + runner.LogFileName = Path.Combine(ncoverOutputDirectory, "Coverage.log"); + runner.AssemblyList = GetAssemblyList(project); + } + + void RunNCover() + { + CodeCoverageService.ClearResults(); + + Category.ClearText(); + TaskService.ClearExceptCommentTasks(); + ShowOutputPad(); + + // Remove existing coverage results file. + if (File.Exists(runner.CoverageResultsFileName)) { + File.Delete(runner.CoverageResultsFileName); + } + + // Create NCover output directory. + if (!Directory.Exists(Path.GetDirectoryName(runner.CoverageResultsFileName))) { + Directory.CreateDirectory(Path.GetDirectoryName(runner.CoverageResultsFileName)); + } + + CategoryWriteLine(StringParser.Parse("Running NCover...")); + CategoryWriteLine(runner.CommandLine); + + runner.Start(); + } + + /// + /// Displays the output from NCover after it has exited. + /// + /// The event source. + /// The NCover exit event arguments. + void NCoverExited(object sender, NCoverExitEventArgs e) + { + System.Diagnostics.Debug.Assert(e.Error.Length == 0); + + string ncoverOutputDirectory = Path.GetDirectoryName(runner.CoverageResultsFileName); + string mbunitResultsFileName = Path.Combine(ncoverOutputDirectory, "mbunit.xml"); + DisplayMbUnitResults(mbunitResultsFileName); + DisplayCoverageResults(runner.CoverageResultsFileName); + + if (TaskService.SomethingWentWrong) { + ShowErrorList(); + } + } + + void OutputLineReceived(object sender, LineReceivedEventArgs e) + { + CategoryWriteLine(e.Line); + } + + void DisplayCoverageResults(string fileName) + { + if (!File.Exists(fileName)) { + Task task = new Task(String.Empty, String.Concat("No code coverage results file generated: ", fileName), 0, 0, TaskType.Error); + WorkbenchSingleton.SafeThreadAsyncCall(typeof(TaskService), "Add", new object[] {task}); + return; + } + + CodeCoverageResults results = new CodeCoverageResults(fileName); + WorkbenchSingleton.SafeThreadAsyncCall(typeof(CodeCoverageService), "ShowResults", new object[] {results}); + } + + void DisplayMbUnitResults(string fileName) + { + if (!File.Exists(fileName)) { + Task task = new Task(String.Empty, String.Concat("No MbUnit results file generated: ", fileName), 0, 0, TaskType.Error); + WorkbenchSingleton.SafeThreadAsyncCall(typeof(TaskService), "Add", new object[] {task}); + return; + } + + MbUnitResults results = new MbUnitResults(fileName); + foreach (Task task in results.Tasks) { + WorkbenchSingleton.SafeThreadAsyncCall(typeof(TaskService), "Add", new object[] {task}); + } + } + + /// + /// Returns the full path to the NCover console application if it + /// exists. + /// + string GetNCoverFileName() + { + string ncoverFileName = CodeCoverageOptions.NCoverFileName; + if (FileNameExists(ncoverFileName)) { + return ncoverFileName; + } else { + ncoverFileName = GetDefaultNCoverFileName(); + if (FileNameExists(ncoverFileName)) { + return ncoverFileName; + } + } + return null; + } + + /// + /// Returns the default full path to the NCover console application. + /// + /// + string GetDefaultNCoverFileName() + { + string programFilesPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + return Path.Combine(programFilesPath, @"NCover\NCover.Console.exe"); + } + + void ShowErrorList() + { + PadDescriptor padDescriptor = WorkbenchSingleton.Workbench.GetPad(typeof(ErrorListPad)); + if (padDescriptor != null) { + WorkbenchSingleton.SafeThreadAsyncCall(padDescriptor, "BringPadToFront"); + } + } + + /// + /// Reads the list of assemblies to be profiled from the project's + /// NCover settings. + /// + string GetAssemblyList(IProject project) + { + if (project == null) { + return String.Empty; + } + + string ncoverSettingsFileName = NCoverSettings.GetFileName(project); + if (File.Exists(ncoverSettingsFileName)) { + NCoverSettings settings = new NCoverSettings(ncoverSettingsFileName); + return settings.AssemblyList; + } + return String.Empty; + } + + string GetNCoverOutputDirectory(IProject project) + { + return Path.Combine(project.Directory, "NCover"); + } + + /// + /// Gets the assembly folder where this add-in was loaded from. + /// + /// The assembly folder where this add-in was loaded. + string GetAssemblyFolder() + { + Assembly assembly = GetType().Assembly; + string assemblyFilename = assembly.CodeBase.Replace("file:///", String.Empty); + return Path.GetDirectoryName(assemblyFilename); + } + + string GetMbUnitConsoleFileName() + { + return Path.GetFullPath(Path.Combine(GetAssemblyFolder(), + @"..\..\..\..\bin\Tools\MbUnit\MbUnit.Cons.exe")); + } + + string GetMbUnitConsoleCommandLineArguments(string reportFolder) + { + StringBuilder commandLine = new StringBuilder(); + + commandLine.Append("/report-name-format:mbunit "); + commandLine.Append("/report-type:Xml "); + commandLine.AppendFormat("/report-folder:\"{0}\" ", reportFolder); + commandLine.AppendFormat("\"{0}\"", GetTestAssemblyFileName()); + + return commandLine.ToString(); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs new file mode 100644 index 0000000000..970c37383e --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs @@ -0,0 +1,32 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using System; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageClassTreeNode : CodeCoverageTreeNode + { + public CodeCoverageClassTreeNode(string name) : base(name) + { + ImageIndex = ClassBrowserIconService.ClassIndex; + SelectedImageIndex = ImageIndex; + } + + public override void ActivateItem() + { + if (Nodes.Count > 0) { + CodeCoverageMethodTreeNode methodNode = (CodeCoverageMethodTreeNode)Nodes[0]; + if (methodNode.Method.SequencePoints.Count > 0) { + FileService.OpenFile(methodNode.Method.SequencePoints[0].Document); + } + } + } + + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageControl.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageControl.cs new file mode 100644 index 0000000000..de612446d8 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageControl.cs @@ -0,0 +1,158 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageControl : UserControl + { + CodeCoverageTreeView treeView; + ListView listView; + SplitContainer splitContainer; + ColumnHeader visitCountColumnHeader; + ColumnHeader startLineColumnHeader; + ColumnHeader endLineColumnHeader; + ColumnHeader startColumnColumnHeader; + ColumnHeader endColumnColumnHeader; + ToolStrip toolStrip; + + public CodeCoverageControl() + { + // TreeView + treeView = new CodeCoverageTreeView(); + treeView.Dock = DockStyle.Fill; + treeView.ImageList = ClassBrowserIconService.ImageList; + treeView.AfterSelect += CodeCoverageTreeViewAfterSelect; + + // ListView + listView = new ListView(); + listView.View = View.Details; + listView.Dock = DockStyle.Fill; + listView.FullRowSelect = true; + listView.HideSelection = false; + listView.ItemActivate += ListViewItemActivate; + + visitCountColumnHeader = new ColumnHeader(); + visitCountColumnHeader.Text = "Visit Count"; + visitCountColumnHeader.Width = 80; + + startLineColumnHeader = new ColumnHeader(); + startLineColumnHeader.Text = "Line"; + startLineColumnHeader.Width = 80; + + startColumnColumnHeader = new ColumnHeader(); + startColumnColumnHeader.Text = "Column"; + startColumnColumnHeader.Width = 80; + + endLineColumnHeader = new ColumnHeader(); + endLineColumnHeader.Text = "End Line"; + endLineColumnHeader.Width = 80; + + endColumnColumnHeader = new ColumnHeader(); + endColumnColumnHeader.Text = "End Column"; + endColumnColumnHeader.Width = 80; + + listView.Columns.AddRange(new ColumnHeader[] {visitCountColumnHeader, + startLineColumnHeader, + startColumnColumnHeader, + endLineColumnHeader, + endColumnColumnHeader}); + + // SplitContainer. + splitContainer = new SplitContainer(); + splitContainer.SplitterWidth = 2; + splitContainer.Dock = DockStyle.Fill; + splitContainer.Panel1.Controls.Add(treeView); + splitContainer.Panel2.Controls.Add(listView); + + Controls.Add(splitContainer); + + // Toolstrip + toolStrip = ToolbarService.CreateToolStrip(this, "/SharpDevelop/Pads/CodeCoveragePad/Toolbar"); + toolStrip.GripStyle = ToolStripGripStyle.Hidden; + Controls.Add(toolStrip); + } + + public void UpdateToolbar() + { + ToolbarService.UpdateToolbar(toolStrip); + toolStrip.Refresh(); + } + + public void AddModules(List modules) + { + LoggingService.Debug("AddModules..."); + treeView.AddModules(modules); + } + + public void Clear() + { + treeView.Clear(); + listView.Items.Clear(); + } + + void CodeCoverageTreeViewAfterSelect(object sender, TreeViewEventArgs e) + { + UpdateListView((CodeCoverageTreeNode)e.Node); + } + + void UpdateListView(CodeCoverageTreeNode node) + { + listView.BeginUpdate(); + try { + listView.Items.Clear(); + if (node is CodeCoverageClassTreeNode) { + AddClass((CodeCoverageClassTreeNode)node); + } else if (node is CodeCoverageMethodTreeNode) { + AddMethod((CodeCoverageMethodTreeNode)node); + } + } finally { + listView.EndUpdate(); + } + } + + void AddClass(CodeCoverageClassTreeNode node) + { + foreach (CodeCoverageMethodTreeNode method in node.Nodes) { + AddMethod(method); + } + } + + void AddMethod(CodeCoverageMethodTreeNode node) + { + foreach (CodeCoverageSequencePoint sequencePoint in node.Method.SequencePoints) { + AddSequencePoint(sequencePoint); + } + } + + void AddSequencePoint(CodeCoverageSequencePoint sequencePoint) + { + ListViewItem item = new ListViewItem(sequencePoint.VisitCount.ToString()); + item.SubItems.Add(sequencePoint.Line.ToString()); + item.SubItems.Add(sequencePoint.Column.ToString()); + item.SubItems.Add(sequencePoint.EndLine.ToString()); + item.SubItems.Add(sequencePoint.EndColumn.ToString()); + item.Tag = sequencePoint; + + listView.Items.Add(item); + } + + void ListViewItemActivate(object sender, EventArgs e) + { + if (listView.SelectedItems.Count > 0) { + CodeCoverageSequencePoint sequencePoint = (CodeCoverageSequencePoint)listView.SelectedItems[0].Tag; + if (sequencePoint.Document.Length > 0) { + FileService.JumpToFilePosition(sequencePoint.Document, sequencePoint.Line - 1, sequencePoint.Column - 1); + } + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageDisplayItem.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageDisplayItem.cs new file mode 100644 index 0000000000..51b1a597f4 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageDisplayItem.cs @@ -0,0 +1,85 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Drawing; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Represents a code coverage display item that can have its colour customised + /// (e.g. Visited code and Not visited code. + /// + public class CodeCoverageDisplayItem + { + string item = String.Empty; + string itemBackColorPropertyName = String.Empty; + string itemForeColorPropertyName = String.Empty; + Color backColor; + Color foreColor; + bool changed; + + public CodeCoverageDisplayItem(string item, string itemBackColorPropertyName, Color backColor, string itemForeColorPropertyName, Color foreColor) + { + this.item = item; + this.backColor = backColor; + this.foreColor = foreColor; + this.itemBackColorPropertyName = itemBackColorPropertyName; + this.itemForeColorPropertyName = itemForeColorPropertyName; + } + + /// + /// Gets whether any of the colours has changed from their origina values. + /// + public bool HasChanged { + get { + return changed; + } + } + + public override string ToString() + { + return item; + } + + public string BackColorPropertyName { + get { + return itemBackColorPropertyName; + } + } + + public Color BackColor { + get { + return backColor; + } + set { + if (backColor != value) { + backColor = value; + changed = true; + } + } + } + + public string ForeColorPropertyName { + get { + return itemForeColorPropertyName; + } + } + + public Color ForeColor { + get { + return foreColor; + } + set { + if (foreColor != null) { + foreColor = value; + changed = true; + } + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageException.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageException.cs new file mode 100644 index 0000000000..76a20ad11b --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageException.cs @@ -0,0 +1,27 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// The exception that is thrown when a non-fatal + /// error occurs in the code coverage add-in. + /// + public class CodeCoverageException : ApplicationException + { + public CodeCoverageException() + { + } + + public CodeCoverageException(string message) + : base(message) + { + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageHighlighter.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageHighlighter.cs new file mode 100644 index 0000000000..02ac80b2a6 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageHighlighter.cs @@ -0,0 +1,107 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.TextEditor.Document; +using System; +using System.Collections.Generic; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Highlights the covered and not covered code in the text editor. + /// + public class CodeCoverageHighlighter + { + public CodeCoverageHighlighter() + { + } + + /// + /// Adds text markers for the code coverage sequence points. + /// + /// The sequence points are added to the marker strategy even + /// if they are not all for the same document. + public void AddMarkers(MarkerStrategy markerStrategy, List sequencePoints) + { + foreach (CodeCoverageSequencePoint sequencePoint in sequencePoints) { + AddMarker(markerStrategy, sequencePoint); + } + } + + public void AddMarker(MarkerStrategy markerStrategy, CodeCoverageSequencePoint sequencePoint) + { + if (!IsValidSequencePoint(markerStrategy.Document, sequencePoint)) { + return; + } + + if (sequencePoint.EndLine == sequencePoint.Line) { + LineSegment lineSegment = markerStrategy.Document.GetLineSegment(sequencePoint.Line - 1); + markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset + sequencePoint.Column, sequencePoint)); + } else { + // Sequence point spread across lines. + for (int line = sequencePoint.Line; line <= sequencePoint.EndLine; ++line) { + LineSegment lineSegment = markerStrategy.Document.GetLineSegment(line - 1); + if (line == sequencePoint.Line) { + // First line. + markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset + sequencePoint.Column, lineSegment.Length - (lineSegment.DelimiterLength - 1) - sequencePoint.Column, sequencePoint)); + } else if (line == sequencePoint.EndLine) { + // Last line. + markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset, sequencePoint.EndColumn - 1, sequencePoint)); + } else { + markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset, lineSegment.Length - (lineSegment.DelimiterLength - 1), sequencePoint)); + } + } + } + } + + /// + /// Removes all CodeCoverageMarkers from the marker strategy. + /// + public void RemoveMarkers(MarkerStrategy markerStrategy) + { + markerStrategy.RemoveAll(IsCodeCoverageTextMarkerMatch); + } + + bool IsCodeCoverageTextMarkerMatch(TextMarker marker) + { + if (marker is CodeCoverageTextMarker) { + return true; + } + return false; + } + + /// + /// Checks whether the sequence point can be added to the document. + /// + /// + /// Checks for invalid start lines, start columns, end columns and end + /// lines that cannot fit in the document. + bool IsValidSequencePoint(IDocument document, CodeCoverageSequencePoint sequencePoint) + { + if (sequencePoint.Line <= 0 || sequencePoint.EndLine <= 0 || sequencePoint.Column <= 0 || sequencePoint.EndColumn <= 0) { + return false; + } else if (sequencePoint.Line > document.TotalNumberOfLines) { + return false; + } else if (sequencePoint.EndLine > document.TotalNumberOfLines) { + return false; + } else if (sequencePoint.Line == sequencePoint.EndLine && sequencePoint.Column > sequencePoint.EndColumn) { + return false; + } else { + // Check the columns exist on the line. + LineSegment lineSegment = document.GetLineSegment(sequencePoint.Line - 1); + if (sequencePoint.Column > lineSegment.Length) { + return false; + } + LineSegment endLineSegment = document.GetLineSegment(sequencePoint.EndLine - 1); + if (sequencePoint.EndColumn > endLineSegment.Length + 1) { + return false; + } + } + return true; + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethod.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethod.cs new file mode 100644 index 0000000000..ca9542634e --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethod.cs @@ -0,0 +1,104 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using System; +using System.Collections.Generic; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageMethod + { + string name = String.Empty; + string className = String.Empty; + string fullClassName = String.Empty; + string classNamespace = String.Empty; + List sequencePoints = new List(); + + public CodeCoverageMethod(string name, string className) + { + this.name = name; + this.fullClassName = className; + + int index = fullClassName.LastIndexOf('.'); + this.classNamespace = fullClassName.Substring(0, index); + + index = fullClassName.LastIndexOf('.'); + if (index > 0) { + this.className = fullClassName.Substring(index + 1); + } else { + this.className = fullClassName; + } + } + + public string Name { + get { + return name; + } + } + + public string ClassName { + get { + return className; + } + } + + public string FullClassName { + get { + return fullClassName; + } + } + + public string ClassNamespace { + get { + return classNamespace; + } + } + + public List SequencePoints { + get { + return sequencePoints; + } + } + + public int VisitedSequencePointsCount { + get { + int count = 0; + foreach (CodeCoverageSequencePoint sequencePoint in sequencePoints) { + if (sequencePoint.VisitCount > 0) { + count++; + } + } + return count; + } + } + + public int NotVisitedSequencePointsCount { + get { + int count = 0; + foreach (CodeCoverageSequencePoint sequencePoint in sequencePoints) { + if (sequencePoint.VisitCount == 0) { + count++; + } + } + return count; + } + } + + public List GetSequencePoints(string fileName) + { + List matchedSequencePoints = new List(); + foreach (CodeCoverageSequencePoint sequencePoint in sequencePoints) { + if (FileUtility.IsEqualFileName(fileName, sequencePoint.Document)) { + matchedSequencePoints.Add(sequencePoint); + } + } + return matchedSequencePoints; + } + + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethodTreeNode.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethodTreeNode.cs new file mode 100644 index 0000000000..14f1fe8bd4 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethodTreeNode.cs @@ -0,0 +1,54 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Gui; +using System; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageMethodTreeNode : CodeCoverageTreeNode + { + CodeCoverageMethod method; + + public CodeCoverageMethodTreeNode(CodeCoverageMethod method) : base(method.Name, method.VisitedSequencePointsCount, method.NotVisitedSequencePointsCount) + { + ImageIndex = ClassBrowserIconService.MethodIndex; + SelectedImageIndex = ImageIndex; + this.method = method; + } + + public CodeCoverageMethod Method { + get { + return method; + } + } + + public override void ActivateItem() + { + if (method != null && method.SequencePoints.Count > 0) { + CodeCoverageSequencePoint firstSequencePoint = method.SequencePoints[0]; + int line = firstSequencePoint.Line; + int column = firstSequencePoint.Column; + + for (int i = 1; i < method.SequencePoints.Count; ++i) { + CodeCoverageSequencePoint sequencePoint = method.SequencePoints[0]; + if (line > sequencePoint.Line) { + line = sequencePoint.Line; + column = sequencePoint.Column; + } + } + + FileService.JumpToFilePosition(firstSequencePoint.Document, line - 1, column - 1); + + } else if (Parent != null) { + ((ExtTreeNode)Parent).ActivateItem(); + } + } + + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModule.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModule.cs new file mode 100644 index 0000000000..d153547978 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModule.cs @@ -0,0 +1,64 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageModule + { + string name = String.Empty; + List methods = new List(); + + public CodeCoverageModule(string name) + { + this.name = name; + } + + public string Name { + get { + return name; + } + } + + public List Methods { + get { + return methods; + } + } + + public int VisitedSequencePointsCount { + get { + int count = 0; + foreach (CodeCoverageMethod method in methods) { + count += method.VisitedSequencePointsCount; + } + return count; + } + } + + public int NotVisitedSequencePointsCount { + get { + int count = 0; + foreach (CodeCoverageMethod method in methods) { + count += method.NotVisitedSequencePointsCount; + } + return count; + } + } + + public List GetSequencePoints(string fileName) + { + List sequencePoints = new List(); + foreach (CodeCoverageMethod method in methods) { + sequencePoints.AddRange(method.GetSequencePoints(fileName)); + } + return sequencePoints; + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModuleTreeNode.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModuleTreeNode.cs new file mode 100644 index 0000000000..5f5d8550ed --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModuleTreeNode.cs @@ -0,0 +1,126 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Gui; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageModuleTreeNode : CodeCoverageTreeNode + { + public CodeCoverageModuleTreeNode(CodeCoverageModule module) : base(module.Name, module.VisitedSequencePointsCount, module.NotVisitedSequencePointsCount) + { + ImageIndex = 2; + SelectedImageIndex = ImageIndex; + + foreach (CodeCoverageMethod method in module.Methods) { + AddMethod(method); + } + + // Update percentage totals for namespace nodes. + UpdateNamespacePercentages(Nodes); + } + + void AddMethod(CodeCoverageMethod method) + { + ExtTreeNode parentNode = GetParentNamespaceNode(method.ClassNamespace); + + // Add class node. + ExtTreeNode classNode = FindNode(parentNode.Nodes, method.ClassName); + if (classNode == null) { + classNode = new CodeCoverageClassTreeNode(method.ClassName); + classNode.AddTo(parentNode); + } + + // Add method node. + CodeCoverageMethodTreeNode methodNode = new CodeCoverageMethodTreeNode(method); + methodNode.AddTo(classNode); + } + + ExtTreeNode GetParentNamespaceNode(string classNamespace) + { + string[] treePath = classNamespace.Split('.'); + + ExtTreeNode node = this; + ExtTreeNode currentNode = node; + + foreach (string path in treePath) { + if (currentNode != null) { + currentNode = FindNode(currentNode.Nodes, path); + } + + if (currentNode == null) { + CodeCoverageNamespaceTreeNode newNode = new CodeCoverageNamespaceTreeNode(path); + newNode.AddTo(node); + node = newNode; + } else { + node = currentNode; + } + } + + return node; + } + + ExtTreeNode FindNode(TreeNodeCollection nodes, string name) + { + foreach (ExtTreeNode node in nodes) { + if (node.Text == name) { + return node; + } + } + return null; + } + + void UpdateNamespacePercentages(TreeNodeCollection nodes) + { + foreach (ExtTreeNode node in nodes) { + CodeCoverageNamespaceTreeNode namespaceNode = node as CodeCoverageNamespaceTreeNode; + if (namespaceNode != null) { + SumVisits(namespaceNode); + } + } + } + + void SumVisits(CodeCoverageNamespaceTreeNode parentNode) + { + int visitedCount = 0; + int notVisitedCount = 0; + + foreach (CodeCoverageTreeNode node in parentNode.Nodes) { + CodeCoverageNamespaceTreeNode namespaceNode = node as CodeCoverageNamespaceTreeNode; + CodeCoverageClassTreeNode classNode = node as CodeCoverageClassTreeNode; + if (namespaceNode != null) { + SumVisits(namespaceNode); + } else if (classNode != null) { + SumVisits(classNode); + } + + visitedCount += node.VisitedCount; + notVisitedCount += node.NotVisitedCount; + } + + parentNode.VisitedCount = visitedCount; + parentNode.NotVisitedCount = notVisitedCount; + } + + void SumVisits(CodeCoverageClassTreeNode parentNode) + { + int visitedCount = 0; + int notVisitedCount = 0; + + foreach (CodeCoverageTreeNode node in parentNode.Nodes) { + visitedCount += node.VisitedCount; + notVisitedCount += node.NotVisitedCount; + } + + parentNode.VisitedCount = visitedCount; + parentNode.NotVisitedCount = notVisitedCount; + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageNamespaceTreeNode.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageNamespaceTreeNode.cs new file mode 100644 index 0000000000..4a387cf87e --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageNamespaceTreeNode.cs @@ -0,0 +1,21 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using System; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageNamespaceTreeNode : CodeCoverageTreeNode + { + public CodeCoverageNamespaceTreeNode(string name) : base(name) + { + ImageIndex = ClassBrowserIconService.NamespaceIndex; + SelectedImageIndex = ImageIndex; + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageOptions.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageOptions.cs new file mode 100644 index 0000000000..256812c817 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageOptions.cs @@ -0,0 +1,123 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using System; +using System.Drawing; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageOptions + { + public static readonly string OptionsProperty = "CodeCoverage.Options"; + + #region Property names + public static readonly string VisitedColorProperty = "VisitedColor"; + public static readonly string VisitedForeColorProperty = "VisitedForeColor"; + public static readonly string NotVisitedColorProperty = "NotVisitedColor"; + public static readonly string NotVisitedForeColorProperty = "NotVisitedForeColor"; + public static readonly string NCoverFileNameProperty = "NCoverFileName"; + public static readonly string CodeCoverageHighlightedProperty = "CodeCoverageHighlighted"; + #endregion + + static Properties properties; + + static CodeCoverageOptions() + { + properties = PropertyService.Get(OptionsProperty, new Properties()); + } + + public static Properties Properties { + get { + return properties; + } + } + + /// + /// The full path to the NCover console executable. + /// + public static string NCoverFileName { + get { + return Properties.Get(NCoverFileNameProperty, String.Empty); + } + set { + Properties.Set(NCoverFileNameProperty, value); + } + } + + /// + /// Enables/disables code coverage highlighting. + /// + public static bool CodeCoverageHighlighted { + get { + return Properties.Get(CodeCoverageHighlightedProperty, false); + } + set { + Properties.Set(CodeCoverageHighlightedProperty, value); + } + } + + /// + /// Gets the colour that will be used when highlighting visited code. + /// + public static Color VisitedColor + { + get { + return Properties.Get(VisitedColorProperty, Color.Lime); + } + + set { + Properties.Set(VisitedColorProperty, value); + } + } + + /// + /// Gets the foreground colour that will be used when highlighting + /// visited code. + /// + public static Color VisitedForeColor + { + get { + return Properties.Get(VisitedForeColorProperty, Color.Black); + } + + set { + Properties.Set(VisitedForeColorProperty, value); + } + } + + /// + /// Gets the colour that will be used when highlighting code that has not + /// been visited. + /// + public static Color NotVisitedColor + { + get { + return Properties.Get(NotVisitedColorProperty, Color.Red); + } + + set { + Properties.Set(NotVisitedColorProperty, value); + } + } + + /// + /// Gets the foreground colour that will be used when highlighting + /// code that has not been visited. + /// + public static Color NotVisitedForeColor + { + get { + return Properties.Get(NotVisitedForeColorProperty, Color.White); + } + + set { + Properties.Set(NotVisitedForeColorProperty, value); + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageOptionsPanel.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageOptionsPanel.cs new file mode 100644 index 0000000000..eccefc3c1d --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageOptionsPanel.cs @@ -0,0 +1,137 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Gui; +using System; +using System.Collections; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageOptionsPanel : AbstractOptionPanel + { + static readonly string foregroundCustomColourButtonName = "foregroundCustomColourButton"; + static readonly string backgroundCustomColourButtonName = "backgroundCustomColourButton"; + static readonly string foregroundColourComboBoxName = "foregroundColorPickerComboBox"; + static readonly string backgroundColourComboBoxName = "backgroundColorPickerComboBox"; + static readonly string displayItemsListBoxName = "displayItemsListBox"; + static readonly string sampleTextLabelName = "sampleTextLabel"; + static readonly string browseButtonName = "browseButton"; + static readonly string commandTextBoxName = "commandTextBox"; + + ColorPickerComboBox foregroundColorPickerComboBox; + ColorPickerComboBox backgroundColorPickerComboBox; + ListBox displayItemsListBox; + Label sampleTextLabel; + TextBox commandTextBox; + + public override void LoadPanelContents() + { + SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("ICSharpCode.CodeCoverage.Resources.CodeCoverageOptionsPanel.xfrm")); + + ControlDictionary[foregroundCustomColourButtonName].Click += new EventHandler(ForegroundCustomColourButtonClick); + ControlDictionary[backgroundCustomColourButtonName].Click += new EventHandler(BackgroundCustomColourButtonClick); + ControlDictionary[browseButtonName].Click += new EventHandler(BrowseButtonClick); + + foregroundColorPickerComboBox = (ColorPickerComboBox)ControlDictionary[foregroundColourComboBoxName]; + foregroundColorPickerComboBox.SelectedIndexChanged += ForegroundColorPickerComboBoxSelectedIndexChanged; + + backgroundColorPickerComboBox = (ColorPickerComboBox)ControlDictionary[backgroundColourComboBoxName]; + backgroundColorPickerComboBox.SelectedIndexChanged += BackgroundColorPickerComboBoxSelectedIndexChanged; + + sampleTextLabel = (Label)ControlDictionary[sampleTextLabelName]; + + commandTextBox = (TextBox)ControlDictionary[commandTextBoxName]; + commandTextBox.Text = CodeCoverageOptions.NCoverFileName; + + displayItemsListBox = (ListBox)ControlDictionary[displayItemsListBoxName]; + displayItemsListBox.Items.Add(new CodeCoverageDisplayItem("Code Covered", CodeCoverageOptions.VisitedColorProperty, CodeCoverageOptions.VisitedColor, CodeCoverageOptions.VisitedForeColorProperty, CodeCoverageOptions.VisitedForeColor)); + displayItemsListBox.Items.Add(new CodeCoverageDisplayItem("Code Not Covered", CodeCoverageOptions.NotVisitedColorProperty, CodeCoverageOptions.NotVisitedColor, CodeCoverageOptions.NotVisitedForeColorProperty, CodeCoverageOptions.NotVisitedForeColor)); + displayItemsListBox.SelectedIndexChanged += DisplayItemsListBoxSelectedIndexChanged; + displayItemsListBox.SelectedIndex = 0; + } + + public override bool StorePanelContents() + { + bool codeCoverageColorsChanged = false; + + foreach (CodeCoverageDisplayItem item in displayItemsListBox.Items) { + CodeCoverageOptions.Properties.Set(item.ForeColorPropertyName, item.ForeColor); + CodeCoverageOptions.Properties.Set(item.BackColorPropertyName, item.BackColor); + if (item.HasChanged) { + codeCoverageColorsChanged = true; + } + } + + if (codeCoverageColorsChanged) { + CodeCoverageService.RefreshCodeCoverageHighlights(); + } + + CodeCoverageOptions.NCoverFileName = commandTextBox.Text; + + return true; + } + + void ForegroundCustomColourButtonClick(object sender, EventArgs e) + { + SelectCustomColour(foregroundColorPickerComboBox); + } + + void BackgroundCustomColourButtonClick(object sender, EventArgs e) + { + SelectCustomColour(backgroundColorPickerComboBox); + } + + void SelectCustomColour(ColorPickerComboBox comboBox) + { + using (ColorDialog colorDialog = new ColorDialog()) { + colorDialog.FullOpen = true; + if (colorDialog.ShowDialog() == DialogResult.OK) { + comboBox.SelectedColor = colorDialog.Color; + } + } + } + + void DisplayItemsListBoxSelectedIndexChanged(object sender, EventArgs e) + { + CodeCoverageDisplayItem item = (CodeCoverageDisplayItem)displayItemsListBox.SelectedItem; + sampleTextLabel.BackColor = item.BackColor; + sampleTextLabel.ForeColor = item.ForeColor; + foregroundColorPickerComboBox.SelectedColor = item.ForeColor; + backgroundColorPickerComboBox.SelectedColor = item.BackColor; + } + + void ForegroundColorPickerComboBoxSelectedIndexChanged(object sender, EventArgs e) + { + CodeCoverageDisplayItem item = (CodeCoverageDisplayItem)displayItemsListBox.SelectedItem; + sampleTextLabel.ForeColor = foregroundColorPickerComboBox.SelectedColor; + item.ForeColor = foregroundColorPickerComboBox.SelectedColor; + } + + void BackgroundColorPickerComboBoxSelectedIndexChanged(object sender, EventArgs e) + { + CodeCoverageDisplayItem item = (CodeCoverageDisplayItem)displayItemsListBox.SelectedItem; + sampleTextLabel.BackColor = backgroundColorPickerComboBox.SelectedColor; + item.BackColor = backgroundColorPickerComboBox.SelectedColor; + } + + void BrowseButtonClick(object sender, EventArgs e) + { + using (OpenFileDialog openFileDialog = new OpenFileDialog()) { + openFileDialog.CheckFileExists = true; + openFileDialog.Filter = StringParser.Parse("${res:SharpDevelop.FileFilter.ExecutableFiles}|*.exe|${res:SharpDevelop.FileFilter.AllFiles}|*.*"); + if (openFileDialog.ShowDialog() == DialogResult.OK) { + ControlDictionary[commandTextBoxName].Text = openFileDialog.FileName; + } + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoveragePad.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoveragePad.cs new file mode 100644 index 0000000000..81390de988 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoveragePad.cs @@ -0,0 +1,89 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Gui; +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoveragePad : AbstractPadContent + { + static CodeCoveragePad instance; + bool disposed; + CodeCoverageControl codeCoverageControl; + + public CodeCoveragePad() + { + instance = this; + + codeCoverageControl = new CodeCoverageControl(); + if (CodeCoverageService.Results != null) { + codeCoverageControl.AddModules(CodeCoverageService.Results.Modules); + } + codeCoverageControl.UpdateToolbar(); + + ProjectService.SolutionClosed += SolutionClosed; + ProjectService.SolutionLoaded += SolutionLoaded; + } + + public static CodeCoveragePad Instance { + get { + return instance; + } + } + + public override Control Control { + get { + return codeCoverageControl; + } + } + + /// + /// Cleans up all used resources + /// + public override void Dispose() + { + if (!disposed) { + disposed = true; + ProjectService.SolutionClosed -= SolutionClosed; + ProjectService.SolutionLoaded -= SolutionLoaded; + codeCoverageControl.Dispose(); + } + } + + public void UpdateToolbar() + { + codeCoverageControl.UpdateToolbar(); + } + + public void ShowResults(CodeCoverageResults results) + { + codeCoverageControl.Clear(); + if (results != null) { + codeCoverageControl.AddModules(results.Modules); + } + } + + public void ClearCodeCoverageResults() + { + codeCoverageControl.Clear(); + } + + void SolutionLoaded(object sender, EventArgs e) + { + codeCoverageControl.UpdateToolbar(); + } + + void SolutionClosed(object sender, EventArgs e) + { + codeCoverageControl.UpdateToolbar(); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageProjectOptionsPanel.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageProjectOptionsPanel.cs new file mode 100644 index 0000000000..cbd4dee52f --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageProjectOptionsPanel.cs @@ -0,0 +1,69 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Gui.OptionPanels; +using ICSharpCode.SharpDevelop.Project; +using System; +using System.IO; +using System.Windows.Forms; +using System.Xml; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageProjectOptionsPanel : AbstractProjectOptionPanel + { + static readonly string AssemblyListTextBoxName = "assemblyListTextBox"; + + TextBox assemblyListTextBox; + + public CodeCoverageProjectOptionsPanel() + { + } + + public override void LoadPanelContents() + { + SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("ICSharpCode.CodeCoverage.Resources.CodeCoverageProjectOptionsPanel.xfrm")); + InitializeHelper(); + + assemblyListTextBox = (TextBox)ControlDictionary[AssemblyListTextBoxName]; + + ReadNCoverSettings(); + + assemblyListTextBox.TextChanged += AssemblyListTextBoxTextChanged; + } + + public override bool StorePanelContents() + { + SaveNCoverSettings(); + IsDirty = false; + return true; + } + + void AssemblyListTextBoxTextChanged(object sender, EventArgs e) + { + IsDirty = true; + } + + void SaveNCoverSettings() + { + NCoverSettings settings = new NCoverSettings(); + settings.AssemblyList = assemblyListTextBox.Text; + settings.Save(NCoverSettings.GetFileName(project)); + } + + void ReadNCoverSettings() + { + string settingsFileName = NCoverSettings.GetFileName(project); + if (File.Exists(settingsFileName)) { + NCoverSettings settings = new NCoverSettings(settingsFileName); + assemblyListTextBox.Text = settings.AssemblyList; + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageResults.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageResults.cs new file mode 100644 index 0000000000..270e755f96 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageResults.cs @@ -0,0 +1,102 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageResults + { + List modules = new List(); + + public CodeCoverageResults(string fileName) : this(new StreamReader(fileName, true)) + { + } + + public CodeCoverageResults(XmlReader reader) + { + ReadResults(reader); + } + + public CodeCoverageResults(TextReader reader) : this(new XmlTextReader(reader)) + { + } + + public List GetSequencePoints(string fileName) + { + List sequencePoints = new List(); + foreach (CodeCoverageModule module in modules) { + sequencePoints.AddRange(module.GetSequencePoints(fileName)); + } + return sequencePoints; + } + + public List Modules { + get { + return modules; + } + } + + void ReadResults(XmlReader reader) + { + CodeCoverageModule currentModule = null; + CodeCoverageMethod currentMethod = null; + + while (reader.Read()) { + switch (reader.NodeType) { + case XmlNodeType.Element: + if (reader.Name == "module") { + currentModule = AddModule(reader); + } else if (reader.Name == "method" && currentModule != null) { + currentMethod = AddMethod(currentModule, reader); + } else if (reader.Name == "seqpnt" && currentMethod != null) { + AddSequencePoint(currentMethod, reader); + } + break; + } + } + reader.Close(); + } + + CodeCoverageModule AddModule(XmlReader reader) + { + CodeCoverageModule module = new CodeCoverageModule(reader.GetAttribute("assembly")); + modules.Add(module); + return module; + } + + CodeCoverageMethod AddMethod(CodeCoverageModule module, XmlReader reader) + { + CodeCoverageMethod method = new CodeCoverageMethod(reader.GetAttribute("name"), reader.GetAttribute("class")); + module.Methods.Add(method); + return method; + } + + void AddSequencePoint(CodeCoverageMethod method, XmlReader reader) + { + CodeCoverageSequencePoint sequencePoint = new CodeCoverageSequencePoint(reader.GetAttribute("document"), + GetInteger(reader.GetAttribute("visitcount")), + GetInteger(reader.GetAttribute("line")), + GetInteger(reader.GetAttribute("column")), + GetInteger(reader.GetAttribute("endline")), + GetInteger(reader.GetAttribute("endcolumn"))); + method.SequencePoints.Add(sequencePoint); + } + + int GetInteger(string s) + { + int val; + if (Int32.TryParse(s, out val)) { + return val; + } + return 0; + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageRunnerNotFoundForm.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageRunnerNotFoundForm.cs new file mode 100644 index 0000000000..44b3165fb4 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageRunnerNotFoundForm.cs @@ -0,0 +1,33 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Gui.XmlForms; +using System; +using System.Diagnostics; +using System.Windows.Forms; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageRunnerNotFoundForm : XmlForm + { + public CodeCoverageRunnerNotFoundForm() + { + SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("ICSharpCode.CodeCoverage.Resources.CodeCoverageRunnerNotFoundForm.xfrm")); + + ((Label)ControlDictionary["messageLabel"]).Text = "Unable to locate the NCover console application.\n\nIf NCover is installed, please specify the location of the application in the Code Coverage options."; + ((PictureBox)ControlDictionary["iconPictureBox"]).Image = ResourceService.GetBitmap("Icons.32x32.Information"); + ((LinkLabel)ControlDictionary["linkLabel"]).Click += LinkLabelClicked; + } + + void LinkLabelClicked(object sender, EventArgs e) + { + Process.Start("http://ncover.org"); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageSequencePoint.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageSequencePoint.cs new file mode 100644 index 0000000000..f7b7cc99f2 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageSequencePoint.cs @@ -0,0 +1,67 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageSequencePoint + { + string document = String.Empty; + int visitCount = 0; + int line = 0; + int column = 0; + int endLine = 0; + int endColumn = 0; + + public CodeCoverageSequencePoint(string document, int visitCount, int line, int column, int endLine, int endColumn) + { + this.document = document; + this.visitCount = visitCount; + this.line = line; + this.column = column; + this.endLine = endLine; + this.endColumn = endColumn; + } + + public string Document { + get { + return document; + } + } + + public int VisitCount { + get { + return visitCount; + } + } + + public int Line { + get { + return line; + } + } + + public int Column { + get { + return column; + } + } + + public int EndLine { + get { + return endLine; + } + } + + public int EndColumn { + get { + return endColumn; + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageService.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageService.cs new file mode 100644 index 0000000000..2808e7e261 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageService.cs @@ -0,0 +1,150 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Project; +using System; +using System.Collections.Generic; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageService + { + static CodeCoverageResults results; + static CodeCoverageHighlighter codeCoverageHighlighter = new CodeCoverageHighlighter(); + + CodeCoverageService() + { + } + + static CodeCoverageService() + { + WorkbenchSingleton.Workbench.ViewOpened += ViewOpened; + } + + /// + /// Shows/hides the code coverage in the source code. + /// + public static bool CodeCoverageHighlighted { + get { + return CodeCoverageOptions.CodeCoverageHighlighted; + } + set { + CodeCoveragePad pad = CodeCoveragePad.Instance; + if (pad != null) { + pad.UpdateToolbar(); + } + if (CodeCoverageOptions.CodeCoverageHighlighted != value) { + CodeCoverageOptions.CodeCoverageHighlighted = value; + if (CodeCoverageResultsExist) { + if (CodeCoverageOptions.CodeCoverageHighlighted) { + ShowCodeCoverage(); + } else { + HideCodeCoverage(); + } + } + } + } + } + + /// + /// Gets the results from the last code coverage run. + /// + public static CodeCoverageResults Results { + get { + return results; + } + } + + /// + /// Clears any code coverage results currently on display. + /// + public static void ClearResults() + { + CodeCoveragePad pad = CodeCoveragePad.Instance; + if (pad != null) { + pad.ClearCodeCoverageResults(); + } + HideCodeCoverage(); + results = null; + } + + /// + /// Shows the code coverage results in the code coverage pad and + /// highlights any source code files that have been profiled. + /// + public static void ShowResults(CodeCoverageResults results) + { + CodeCoverageService.results = results; + CodeCoveragePad pad = CodeCoveragePad.Instance; + if (pad != null) { + pad.ShowResults(results); + } + if (results != null) { + RefreshCodeCoverageHighlights(); + } + } + + /// + /// Updates the highlighted code coverage text to reflect any changes + /// in the configured colours. + /// + public static void RefreshCodeCoverageHighlights() + { + if (CodeCoverageOptions.CodeCoverageHighlighted && CodeCoverageResultsExist) { + HideCodeCoverage(); + ShowCodeCoverage(); + } + } + + static void ShowCodeCoverage() + { + // Highlight any open files. + foreach (IViewContent view in WorkbenchSingleton.Workbench.ViewContentCollection) { + ShowCodeCoverage(view); + } + } + + static void HideCodeCoverage() + { + foreach (IViewContent view in WorkbenchSingleton.Workbench.ViewContentCollection) { + TextEditorDisplayBindingWrapper textEditor = view as TextEditorDisplayBindingWrapper; + if (textEditor != null) { + codeCoverageHighlighter.RemoveMarkers(textEditor.textAreaControl.Document.MarkerStrategy); + textEditor.textAreaControl.Refresh(); + } + } + } + + static void ViewOpened(object sender, ViewContentEventArgs e) + { + if (CodeCoverageOptions.CodeCoverageHighlighted && CodeCoverageResultsExist) { + ShowCodeCoverage(e.Content); + } + } + + static void ShowCodeCoverage(IViewContent view) + { + TextEditorDisplayBindingWrapper textEditor = view as TextEditorDisplayBindingWrapper; + if (textEditor != null && view.FileName != null) { + List sequencePoints = results.GetSequencePoints(view.FileName); + if (sequencePoints.Count > 0) { + codeCoverageHighlighter.AddMarkers(textEditor.textAreaControl.Document.MarkerStrategy, sequencePoints); + textEditor.textAreaControl.Refresh(); + } + } + } + + static bool CodeCoverageResultsExist { + get { + return results != null; + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTextMarker.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTextMarker.cs new file mode 100644 index 0000000000..d2a1a18b41 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTextMarker.cs @@ -0,0 +1,49 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.TextEditor.Document; +using System; +using System.Drawing; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Custom text marker used when highlighting code coverage lines. + /// + public class CodeCoverageTextMarker : TextMarker + { + public CodeCoverageTextMarker(int offset, CodeCoverageSequencePoint sequencePoint) : this(offset, GetSequencePointLength(sequencePoint), sequencePoint) + { + } + + public CodeCoverageTextMarker(int offset, int length, CodeCoverageSequencePoint sequencePoint) : base(offset, length, TextMarkerType.SolidBlock, GetSequencePointColor(sequencePoint), GetSequencePointForeColor(sequencePoint)) + { + } + + public static int GetSequencePointLength(CodeCoverageSequencePoint sequencePoint) + { + return sequencePoint.EndColumn - sequencePoint.Column; + } + + public static Color GetSequencePointColor(CodeCoverageSequencePoint sequencePoint) + { + if (sequencePoint.VisitCount > 0) { + return CodeCoverageOptions.VisitedColor; + } + return CodeCoverageOptions.NotVisitedColor; + } + + public static Color GetSequencePointForeColor(CodeCoverageSequencePoint sequencePoint) + { + if (sequencePoint.VisitCount > 0) { + return CodeCoverageOptions.VisitedForeColor; + } + return CodeCoverageOptions.NotVisitedForeColor; + } + + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeNode.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeNode.cs new file mode 100644 index 0000000000..f392a519ab --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeNode.cs @@ -0,0 +1,83 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.SharpDevelop.Gui; +using System; +using System.Drawing; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageTreeNode : ExtTreeNode + { + public static readonly Color PartialCoverageTextColor = Color.Red; + + int visitedCount; + int notVisitedCount; + + public CodeCoverageTreeNode(string name) : this(name, 0, 0) + { + } + + public CodeCoverageTreeNode(string name, int visitedCount, int notVisitedCount) + { + this.visitedCount = visitedCount; + this.notVisitedCount = notVisitedCount; + + Name = name; + SetText(); + } + + public int VisitedCount { + get { + return visitedCount; + } + set { + visitedCount = value; + SetText(); + } + } + + public int NotVisitedCount { + get { + return notVisitedCount; + } + set { + notVisitedCount = value; + SetText(); + } + } + + static string GetPercentage(int visitedCount, int totalCount) + { + int percentage = (visitedCount * 100) / totalCount; + return percentage.ToString(); + } + + static string GetNodeText(string name, int visitedCount, int totalCount) + { + if (totalCount > 0) { + return String.Concat(name, " (", GetPercentage(visitedCount, totalCount), "%)"); + } + return name; + } + + void SetText() + { + int total = visitedCount + notVisitedCount; + + // Change the text color for partial coverage. + if (total != visitedCount) { + ForeColor = PartialCoverageTextColor; + } + + // Get the text for the node. + Text = GetNodeText(Name, visitedCount, total); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeView.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeView.cs new file mode 100644 index 0000000000..c958e0dc79 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeView.cs @@ -0,0 +1,29 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Gui; +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace ICSharpCode.CodeCoverage +{ + public class CodeCoverageTreeView : ExtTreeView + { + public CodeCoverageTreeView() + { + } + + public void AddModules(List modules) + { + foreach (CodeCoverageModule module in modules) { + Nodes.Add(new CodeCoverageModuleTreeNode(module)); + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/ColorPickerComboBox.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/ColorPickerComboBox.cs new file mode 100644 index 0000000000..d879ba05a5 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/ColorPickerComboBox.cs @@ -0,0 +1,144 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; + +namespace ICSharpCode.CodeCoverage +{ + public class ColorPickerComboBox : System.Windows.Forms.ComboBox + { + Color customColor = Color.Empty; + int ColorRectangleLeftOffset = 4; + int ColorRectangleTopOffset = 2; + + public ColorPickerComboBox() + { + base.DropDownStyle = ComboBoxStyle.DropDownList; + DrawMode = DrawMode.OwnerDrawFixed; + AddBasicColors(); + } + + public Color SelectedColor { + get { + if (SelectedItem != null) { + return (Color)SelectedItem; + } + return Color.Empty; + } + set { + if (Items.Contains(value)) { + SelectedItem = value; + } else if (CustomColorExists) { + UpdateCustomColor(value); + } else { + AddCustomColor(value); + } + } + } + + protected override void OnDrawItem(DrawItemEventArgs e) + { + if (e.Index >= 0) { + e.DrawBackground(); + Graphics g = e.Graphics; + Color color = (Color)Items[e.Index]; + Rectangle colorRectangle = GetColorRectangle(e.Bounds.Top); + g.FillRectangle(new SolidBrush(color), colorRectangle); + g.DrawRectangle(Pens.Black, colorRectangle); + int textOffset = (2 * colorRectangle.Left) + colorRectangle.Width; + SolidBrush brush = GetTextBrush(IsSelected(e.State)); + g.DrawString(GetColorName(color), e.Font, brush, new Rectangle(textOffset, e.Bounds.Top, e.Bounds.Width - textOffset, ItemHeight)); + } + base.OnDrawItem(e); + } + + bool CustomColorExists { + get { + return customColor != Color.Empty; + } + } + + void AddBasicColors() + { + Items.Add(Color.Black); + Items.Add(Color.White); + Items.Add(Color.Maroon); + Items.Add(Color.Green); + Items.Add(Color.Olive); + Items.Add(Color.Navy); + Items.Add(Color.Purple); + Items.Add(Color.Teal); + Items.Add(Color.Silver); + Items.Add(Color.Gray); + Items.Add(Color.Red); + Items.Add(Color.Lime); + Items.Add(Color.Yellow); + Items.Add(Color.Blue); + Items.Add(Color.Magenta); + Items.Add(Color.Cyan); + SelectedIndex = 0; + } + + void AddCustomColor(Color color) + { + customColor = color; + SelectedIndex = Items.Add(color); + } + + void UpdateCustomColor(Color color) + { + int index = Items.IndexOf(customColor); + if (index >= 0) { + customColor = color; + Items[index] = color; + SelectedIndex = index; + } else { + AddCustomColor(color); + } + } + + Rectangle GetColorRectangle(int y) + { + int colorRectangleHeight = ItemHeight - (2 * ColorRectangleTopOffset); + return new Rectangle(ColorRectangleLeftOffset, y + ColorRectangleTopOffset, colorRectangleHeight, colorRectangleHeight); + } + + string GetColorName(Color color) + { + if (CustomColorExists && color == customColor) { + return "Custom"; + } + return color.Name; + } + + SolidBrush GetTextBrush(bool selected) + { + if (selected) { + return new SolidBrush(Color.White); + } + return new SolidBrush(ForeColor); + } + + bool IsSelected(DrawItemState state) + { + return (state & DrawItemState.Selected) == DrawItemState.Selected; + } + + protected override void OnDropDownStyleChanged(EventArgs e) + { + if (DropDownStyle != ComboBoxStyle.DropDownList) { + DropDownStyle = ComboBoxStyle.DropDownList; + } + base.OnDropDownStyleChanged(e); + } + + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/LineReceivedEventArgs.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/LineReceivedEventArgs.cs new file mode 100644 index 0000000000..2ac07988a5 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/LineReceivedEventArgs.cs @@ -0,0 +1,32 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.CodeCoverage +{ + public delegate void LineReceivedEventHandler(object sender, LineReceivedEventArgs e); + + /// + /// The arguments for the event. + /// + public class LineReceivedEventArgs : EventArgs + { + string line = String.Empty; + + public LineReceivedEventArgs(string line) + { + this.line = line; + } + + public string Line { + get { + return line; + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/MbUnitResults.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/MbUnitResults.cs new file mode 100644 index 0000000000..610a4cc677 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/MbUnitResults.cs @@ -0,0 +1,113 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Gui; +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Reads the MbUnit results file. + /// + public class MbUnitResults + { + static readonly string RunElementName = "run"; + static readonly string MessageElementName = "message"; + static readonly string StackTraceElementName= "stack-trace"; + + List tasks = new List(); + + public MbUnitResults(string fileName) : this(new StreamReader(fileName, true)) + { + } + + public MbUnitResults(XmlTextReader reader) + { + ReadResults(reader); + } + + public MbUnitResults(TextReader reader) : this(new XmlTextReader(reader)) + { + } + + public List Tasks { + get { + return tasks; + } + } + + void ReadResults(XmlTextReader reader) + { + using (reader) { + while (reader.Read()) { + if (reader.NodeType == XmlNodeType.Element) { + if (IsRunFailureElement(reader)) { + ReadErrorTask(reader); + } + } + } + } + } + + bool IsRunFailureElement(XmlReader reader) + { + if (reader.Name == RunElementName) { + string result = reader.GetAttribute("result"); + if (result != null && result == "failure") { + return true; + } + } + return false; + } + + void ReadErrorTask(XmlReader reader) + { + string testCase = reader.GetAttribute("name"); + string message = String.Empty; + + while (reader.Read()) { + if (reader.NodeType == XmlNodeType.Element) { + if (reader.Name == MessageElementName) { + message = reader.ReadElementString(); + } else if (reader.Name == StackTraceElementName) { + string stackTrace = reader.ReadElementString(); + AddTask(GetDescription(testCase, message), stackTrace); + return; + } + } + } + } + + /// + /// Gets task error description. + /// + string GetDescription(string testCase, string message) + { + return StringParser.Parse("${res:NUnitPad.NUnitPadContent.TestTreeView.TestFailedMessage}", new string[,] { + {"TestCase", testCase}, + {"Message", message} + }); + } + + void AddTask(string description, string stackTrace) + { + FileLineReference lineRef = OutputTextLineParser.GetNUnitOutputFileLineReference(stackTrace, true); + if (lineRef != null) { + Task task = new Task(Path.GetFullPath(lineRef.FileName), + description, + lineRef.Column, + lineRef.Line, + TaskType.Error); + tasks.Add(task); + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverExitEventArgs.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverExitEventArgs.cs new file mode 100644 index 0000000000..6ff17347f2 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverExitEventArgs.cs @@ -0,0 +1,58 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Represents the method that will handle the + /// event. + /// + public delegate void NCoverExitEventHandler(object sender, NCoverExitEventArgs e); + + /// + /// The event arguments. + /// + public class NCoverExitEventArgs : EventArgs + { + string output; + int exitCode; + string error; + + public NCoverExitEventArgs(string output, string error, int exitCode) + { + this.output = output; + this.error = error; + this.exitCode = exitCode; + } + + /// + /// Gets the command line output from NAnt. + /// + public string Output { + get { + return output; + } + } + + public string Error { + get { + return error; + } + } + + /// + /// Gets the exit code. + /// + public int ExitCode { + get { + return exitCode; + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverRunner.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverRunner.cs new file mode 100644 index 0000000000..0b8b2f3c1a --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverRunner.cs @@ -0,0 +1,255 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Diagnostics; +using System.Text; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Runs NCover. + /// + public class NCoverRunner + { + string ncoverFileName = String.Empty; + string workingDirectory = String.Empty; + string coverageResultsFileName = String.Empty; + string profiledApplicationCommand = String.Empty; + string profiledApplicationCommandLineArguments = String.Empty; + string assemblyList = String.Empty; + string logFileName = String.Empty; + ProcessRunner runner; + + /// + /// Triggered when NCover exits. + /// + public event NCoverExitEventHandler NCoverExited; + + /// + /// The NCover runner was started. + /// + public event EventHandler NCoverStarted; + + /// + /// The NCover runner was stopped. Being stopped is not the + /// same as NCover exiting. + /// + public event EventHandler NCoverStopped; + + /// + /// Triggered when an output line is received from NCover. + /// + public event LineReceivedEventHandler OutputLineReceived; + + public NCoverRunner() + { + } + + /// + /// Gets or sets the NCover executable path. + /// + public string NCoverFileName { + get { + return ncoverFileName; + } + set { + ncoverFileName = value; + } + } + + public string WorkingDirectory { + get { + return workingDirectory; + } + set { + workingDirectory = value; + } + } + + /// + /// The list of assemblies that will be profiled. + /// + public string AssemblyList { + get { + return assemblyList; + } + set { + // Remove any spaces from the assembly list since + // NCover will ignore any items after the space. + assemblyList = value.Replace(" ", String.Empty); + } + } + + /// + /// Gets the full NCover command line that will be used by + /// the runner. + /// + public string CommandLine { + get { + return String.Concat(ncoverFileName, " ", GetArguments()); + } + } + + /// + /// Gets whether the NCover runner is currently running. + /// + public bool IsRunning { + get { + if (runner != null) { + return runner.IsRunning; + } + return false; + } + } + + /// + /// Coverage output results file. + /// + public string CoverageResultsFileName { + get { + return coverageResultsFileName; + } + set { + coverageResultsFileName = value; + } + } + + /// + /// Profiler log file. + /// + public string LogFileName { + get { + return logFileName; + } + set { + logFileName = value; + } + } + + /// + /// Gets or sets the command that will be used to run the + /// profiled application. + /// + public string ProfiledApplicationCommand { + get { + return profiledApplicationCommand; + } + set { + profiledApplicationCommand = value; + } + } + + /// + /// The arguments that will be used with the profiled application. + /// + public string ProfiledApplicationCommandLineArguments { + get { + return profiledApplicationCommandLineArguments; + } + set { + profiledApplicationCommandLineArguments = value; + } + } + + public void Start() + { + string arguments = GetArguments(); + + runner = new ProcessRunner(); + runner.WorkingDirectory = workingDirectory; + runner.ProcessExited += new EventHandler(ProcessExited); + + if (OutputLineReceived != null) { + runner.OutputLineReceived += new LineReceivedEventHandler(OnOutputLineReceived); + } + runner.Start(ncoverFileName, arguments); + OnNCoverStarted(); + } + + /// + /// Stops the currently running NCover instance. + /// + public void Stop() + { + if (runner != null) { + runner.Kill(); + OnNCoverStopped(); + } + } + + protected void OnNCoverExited(string output, string error, int exitCode) + { + if (NCoverExited != null) { + NCoverExited(this, new NCoverExitEventArgs(output, error, exitCode)); + } + } + + protected void OnNCoverStarted() + { + if (NCoverStarted != null) { + NCoverStarted(this, new EventArgs()); + } + } + + protected void OnNCoverStopped() + { + if (NCoverStopped != null) { + NCoverStopped(this, new EventArgs()); + } + } + + /// + /// Raises the event. + /// + /// The event source. + /// The event arguments. + protected void OnOutputLineReceived(object sender, LineReceivedEventArgs e) + { + if (OutputLineReceived != null) { + OutputLineReceived(this, e); + } + } + + /// + /// Handles the NCover process exit event. + /// + /// The event source. + /// The event arguments. + void ProcessExited(object sender, EventArgs e) + { + ProcessRunner runner = (ProcessRunner)sender; + OnNCoverExited(runner.StandardOutput, runner.StandardError, runner.ExitCode); + } + + /// + /// Adds extra command line arguments to those specified + /// by the user in the string. + /// + string GetArguments() + { + StringBuilder ncoverArguments = new StringBuilder(); + + if (coverageResultsFileName.Length > 0) { + ncoverArguments.AppendFormat("//x \"{0}\" ", coverageResultsFileName); + } + + if (assemblyList.Length > 0) { + ncoverArguments.AppendFormat("//a \"{0}\" ", assemblyList); + } + + if (logFileName.Length > 0) { + ncoverArguments.AppendFormat("//l \"{0}\" ", logFileName); + } + + ncoverArguments.AppendFormat("\"{0}\" ", profiledApplicationCommand); + ncoverArguments.Append(profiledApplicationCommandLineArguments); + + return ncoverArguments.ToString(); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverRunnerSingleton.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverRunnerSingleton.cs new file mode 100644 index 0000000000..b08c7f94c6 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverRunnerSingleton.cs @@ -0,0 +1,36 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Single NCover runner that is used by all commands. + /// + /// + public class NCoverRunnerSingleton + { + static NCoverRunner runner; + + NCoverRunnerSingleton() + { + } + + /// + /// Gets the instance. + /// + public static NCoverRunner Runner { + get { + if (runner == null) { + runner = new NCoverRunner(); + } + return runner; + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverSettings.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverSettings.cs new file mode 100644 index 0000000000..04f4095db8 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/NCoverSettings.cs @@ -0,0 +1,97 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.SharpDevelop.Project; +using System; +using System.IO; +using System.Text; +using System.Xml; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Settings for NCover. + /// + public class NCoverSettings + { + static readonly string RootElementName = "ProfilerSettings"; + static readonly string AssembliesElementName = "Assemblies"; + + string assemblyList = String.Empty; + + public NCoverSettings() + { + } + + public NCoverSettings(string fileName) : this(new StreamReader(fileName, true)) + { + } + + public NCoverSettings(XmlReader reader) + { + ReadSettings(reader); + } + + public NCoverSettings(TextReader reader) : this(new XmlTextReader(reader)) + { + } + + /// + /// Gets the NCover settings filename for the specified project. + /// + public static string GetFileName(IProject project) + { + return Path.ChangeExtension(project.FileName, "NCover.Settings"); + } + + /// + /// A semi-colon delimited list of assemblies. + /// + public string AssemblyList { + get { + return assemblyList; + } + set { + assemblyList = value; + } + } + + public void Save(TextWriter writer) + { + Save(new XmlTextWriter(writer)); + } + + public void Save(string fileName) + { + Save(new StreamWriter(fileName, false, Encoding.UTF8)); + } + + public void Save(XmlTextWriter writer) + { + writer.Formatting = Formatting.Indented; + + using (writer) { + writer.WriteStartElement(RootElementName); + writer.WriteElementString(AssembliesElementName, assemblyList); + writer.WriteEndElement(); + } + } + + void ReadSettings(XmlReader reader) + { + using (reader) { + while (reader.Read()) { + if (reader.NodeType == XmlNodeType.Element) { + if (reader.Name == AssembliesElementName) { + assemblyList = reader.ReadString(); + } + } + } + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/OutputReader.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/OutputReader.cs new file mode 100644 index 0000000000..a05f7e14d7 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/OutputReader.cs @@ -0,0 +1,98 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Threading; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// A threaded or + /// reader. + /// + public class OutputReader + { + StreamReader reader; + string output = String.Empty; + Thread thread; + + public event LineReceivedEventHandler LineReceived; + + public OutputReader(StreamReader reader) + { + this.reader = reader; + } + + /// + /// Starts reading the output stream. + /// + public void Start() + { + thread = new Thread(new ThreadStart(ReadOutput)); + thread.Start(); + } + + /// + /// Gets the text output read from the reader. + /// + public string Output { + get { + return output; + } + } + + /// + /// Waits for the reader to finish. + /// + public void WaitForFinish() + { + if (thread != null) { + thread.Join(); + } + } + + /// + /// Raises the event. + /// + /// + protected void OnLineReceived(string line) + { + if (LineReceived != null) { + LineReceived(this, new LineReceivedEventArgs(line)); + } + } + + /// + /// Reads the output stream on a different thread. + /// + void ReadOutput() + { + //output = reader.ReadToEnd(); + output = String.Empty; + StringBuilder outputBuilder = new StringBuilder(); + + bool endOfStream = false; + while(!endOfStream) + { + string line = reader.ReadLine(); + + if (line != null) { + outputBuilder.Append(line); + outputBuilder.Append(Environment.NewLine); + OnLineReceived(line); + } else { + endOfStream = true; + } + } + + output = outputBuilder.ToString(); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/ProcessRunner.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/ProcessRunner.cs new file mode 100644 index 0000000000..e424b19aa4 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/ProcessRunner.cs @@ -0,0 +1,266 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Runs a process that sends output to standard output and to + /// standard error. + /// + public class ProcessRunner : IDisposable + { + Process process; + string standardOutput = String.Empty; + string workingDirectory = String.Empty; + OutputReader standardOutputReader; + OutputReader standardErrorReader; + + /// + /// Triggered when the process has exited. + /// + public event EventHandler ProcessExited; + + /// + /// Triggered when a line of text is read from the standard output. + /// + public event LineReceivedEventHandler OutputLineReceived; + + /// + /// Triggered when a line of text is read from the standard error. + /// + public event LineReceivedEventHandler ErrorLineReceived; + + /// + /// Creates a new instance of the . + /// + public ProcessRunner() + { + } + + /// + /// Gets or sets the process's working directory. + /// + public string WorkingDirectory { + get { + return workingDirectory; + } + + set { + workingDirectory = value; + } + } + + /// + /// Gets the standard output returned from the process. + /// + public string StandardOutput { + get { + string output = String.Empty; + if (standardOutputReader != null) { + output = standardOutputReader.Output; + } + return output; + } + } + + /// + /// Gets the standard error output returned from the process. + /// + public string StandardError { + get { + string output = String.Empty; + if (standardErrorReader != null) { + output = standardErrorReader.Output; + } + return output; + } + } + + /// + /// Releases resources held by the + /// + public void Dispose() + { + } + + /// + /// Gets the process exit code. + /// + public int ExitCode { + get { + int exitCode = 0; + if (process != null) { + exitCode = process.ExitCode; + } + return exitCode; + } + } + + /// + /// Waits for the process to exit. + /// + public void WaitForExit() + { + WaitForExit(Int32.MaxValue); + } + + /// + /// Waits for the process to exit. + /// + /// A timeout in milliseconds. + /// if the associated process has + /// exited; otherwise, + public bool WaitForExit(int timeout) + { + if (process == null) { + throw new ProcessRunnerException(StringParser.Parse("${res:ICSharpCode.NAntAddIn.ProcessRunner.NoProcessRunningErrorText}")); + } + + bool exited = process.WaitForExit(timeout); + + if (exited) { + standardOutputReader.WaitForFinish(); + standardErrorReader.WaitForFinish(); + } + + return exited; + } + + public bool IsRunning { + get { + bool isRunning = false; + + if (process != null) { + isRunning = !process.HasExited; + } + + return isRunning; + } + } + + /// + /// Starts the process. + /// + /// The process filename. + /// The command line arguments to + /// pass to the command. + public void Start(string command, string arguments) + { + process = new Process(); + process.StartInfo.CreateNoWindow = true; + process.StartInfo.FileName = command; + process.StartInfo.WorkingDirectory = workingDirectory; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + process.StartInfo.UseShellExecute = false; + process.StartInfo.Arguments = arguments; + + if (ProcessExited != null) { + process.EnableRaisingEvents = true; + process.Exited += new EventHandler(OnProcessExited); + } + + process.Start(); + + standardOutputReader = new OutputReader(process.StandardOutput); + if (OutputLineReceived != null) { + standardOutputReader.LineReceived += new LineReceivedEventHandler(OnOutputLineReceived); + } + + standardOutputReader.Start(); + + standardErrorReader = new OutputReader(process.StandardError); + if (ErrorLineReceived != null) { + standardErrorReader.LineReceived += new LineReceivedEventHandler(OnErrorLineReceived); + } + + standardErrorReader.Start(); + } + + /// + /// Starts the process. + /// + /// The process filename. + public void Start(string command) + { + Start(command, String.Empty); + } + + /// + /// Kills the running process. + /// + public void Kill() + { + if (process != null) { + if (!process.HasExited) { + process.Kill(); + process.Close(); + process.Dispose(); + process = null; + standardOutputReader.WaitForFinish(); + standardErrorReader.WaitForFinish(); + } else { + process = null; + } + } + // Control-C does not seem to work. + //GenerateConsoleCtrlEvent((int)ConsoleEvent.ControlC, 0); + } + + /// + /// Raises the event. + /// + protected void OnProcessExited(object sender, EventArgs e) + { + if (ProcessExited != null) { + + standardOutputReader.WaitForFinish(); + standardErrorReader.WaitForFinish(); + + ProcessExited(this, e); + } + } + + /// + /// Raises the event. + /// + /// The event source. + /// The line received event arguments. + protected void OnOutputLineReceived(object sender, LineReceivedEventArgs e) + { + if (OutputLineReceived != null) { + OutputLineReceived(this, e); + } + } + + /// + /// Raises the event. + /// + /// The event source. + /// The line received event arguments. + protected void OnErrorLineReceived(object sender, LineReceivedEventArgs e) + { + if (ErrorLineReceived != null) { + ErrorLineReceived(this, e); + } + } + + enum ConsoleEvent + { + ControlC = 0, + ControlBreak = 1 + }; + + [DllImport("kernel32.dll", SetLastError=true)] + static extern int GenerateConsoleCtrlEvent(int dwCtrlEvent, int dwProcessGroupId); + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/ProcessRunnerException.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/ProcessRunnerException.cs new file mode 100644 index 0000000000..a5603a3d1b --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/ProcessRunnerException.cs @@ -0,0 +1,23 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// An exception thrown by a + /// instance. + /// + public class ProcessRunnerException : ApplicationException + { + public ProcessRunnerException(string message) + : base(message) + { + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/RunMbUnitPadTestsWithCodeCoverageCommand.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/RunMbUnitPadTestsWithCodeCoverageCommand.cs new file mode 100644 index 0000000000..634ffa479c --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/RunMbUnitPadTestsWithCodeCoverageCommand.cs @@ -0,0 +1,37 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.MbUnitPad; +using System; + +namespace ICSharpCode.CodeCoverage +{ + public class RunMbUnitPadTestsWithCodeCoverageCommand : AbstractRunTestsWithCodeCoverageCommand + { + protected override string GetTestAssemblyFileName() + { + return MbUnitPadContent.Instance.SelectedAssemblyFileName; + } + + protected override IProject GetProject() + { + return GetSelectedProject(GetTestAssemblyFileName()); + } + + IProject GetSelectedProject(string outputAssemblyFileName) + { + foreach (IProject project in ProjectService.OpenSolution.Projects) { + if (FileUtility.IsEqualFileName(outputAssemblyFileName, project.OutputAssemblyFullPath)) { + return project; + } + } + return null; + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/RunTestFixtureWithCodeCoverageCommand.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/RunTestFixtureWithCodeCoverageCommand.cs new file mode 100644 index 0000000000..04b8a895a5 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/RunTestFixtureWithCodeCoverageCommand.cs @@ -0,0 +1,47 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.MbUnitPad; +using System; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Menu command selected after right clicking a test fixture in the text editor + /// to run tests with code coverage. + /// + public class RunTestFixtureWithCodeCoverageCommand : AbstractRunTestsWithCodeCoverageCommand + { + IProject project; + + public override void Run() + { + IMember m = MbUnitTestableCondition.GetMember(Owner); + IClass c = (m != null) ? m.DeclaringType : MbUnitTestableCondition.GetClass(Owner); + project = c.ProjectContent.Project; + if (project != null) { + base.Run(); + } else { + MessageService.ShowMessage("Unable to determine project."); + } + } + + protected override IProject GetProject() + { + return project; + } + + protected override string GetTestAssemblyFileName() + { + return project.OutputAssemblyFullPath; + } + } +} + diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/RunTestWithCodeCoverageCommand.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/RunTestWithCodeCoverageCommand.cs new file mode 100644 index 0000000000..8369827c7f --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/RunTestWithCodeCoverageCommand.cs @@ -0,0 +1,46 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.MbUnitPad; +using System; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Menu command selected after right clicking a test method in the text editor + /// to run tests with code coverage. + /// + public class RunTestWithCodeCoverageCommand : AbstractRunTestsWithCodeCoverageCommand + { + IProject project; + + public override void Run() + { + IMember m = MbUnitTestableCondition.GetMember(Owner); + IClass c = (m != null) ? m.DeclaringType : MbUnitTestableCondition.GetClass(Owner); + project = c.ProjectContent.Project; + if (project != null) { + base.Run(); + } else { + MessageService.ShowMessage("Unable to determine project."); + } + } + + protected override IProject GetProject() + { + return project; + } + + protected override string GetTestAssemblyFileName() + { + return project.OutputAssemblyFullPath; + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/ToggleCodeCoverageCommand.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/ToggleCodeCoverageCommand.cs new file mode 100644 index 0000000000..e3c21b2587 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/ToggleCodeCoverageCommand.cs @@ -0,0 +1,25 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop; +using System; + +namespace ICSharpCode.CodeCoverage +{ + public class ToggleCodeCoverageCommand : AbstractCheckableMenuCommand + { + public override bool IsChecked { + get { + return CodeCoverageService.CodeCoverageHighlighted; + } + set { + CodeCoverageService.CodeCoverageHighlighted = value; + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/AddCodeCoverageMarkersTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/AddCodeCoverageMarkersTestFixture.cs new file mode 100644 index 0000000000..ae6ca041de --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/AddCodeCoverageMarkersTestFixture.cs @@ -0,0 +1,144 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.CodeCoverage; +using ICSharpCode.TextEditor.Document; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class AddCodeCoverageMarkersTestFixture + { + MarkerStrategy markerStrategy; + CodeCoverageTextMarker markerOne; + CodeCoverageTextMarker markerTwo; + CodeCoverageTextMarker markerThree; + MockDocument document; + + [TestFixtureSetUp] + public void SetUpFixture() + { + try { + string configFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NCoverAddIn.Tests"); + PropertyService.InitializeService(configFolder, Path.Combine(configFolder, "data"), "NCoverAddIn.Tests"); + } catch (Exception) {} + + document = new MockDocument(); + string code = "\t\t{\r\n" + + "\t\t\tint count = 0;\r\n" + + "\t\t}\r\n"; + document.AddLines(code); + markerStrategy = new MarkerStrategy(document); + + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + CodeCoverageResults results = new CodeCoverageResults(new StringReader(xml)); + CodeCoverageMethod method = results.Modules[0].Methods[0]; + CodeCoverageHighlighter highlighter = new CodeCoverageHighlighter(); + highlighter.AddMarkers(markerStrategy, method.SequencePoints); + + foreach (CodeCoverageTextMarker marker in markerStrategy.TextMarker) { + if (markerOne == null) { + markerOne = marker; + } else if (markerTwo == null) { + markerTwo = marker; + } else if (markerThree == null) { + markerThree = marker; + } + } + } + + [Test] + public void MarkerCount() + { + int count = 0; + foreach (CodeCoverageTextMarker marker in markerStrategy.TextMarker) { + count++; + } + + Assert.AreEqual(3, count); + } + + [Test] + public void MarkerOneOffset() + { + Assert.AreEqual(3, markerOne.Offset); + } + + [Test] + public void MarkerOneLength() + { + Assert.AreEqual(1, markerOne.Length); + } + + [Test] + public void MarkerOneType() + { + Assert.AreEqual(TextMarkerType.SolidBlock, markerOne.TextMarkerType); + } + + [Test] + public void MarkerOneForeColor() + { + Assert.AreEqual(CodeCoverageOptions.VisitedForeColor, markerOne.ForeColor); + } + + [Test] + public void MarkerOneColor() + { + Assert.AreEqual(CodeCoverageOptions.VisitedColor, markerOne.Color); + } + + [Test] + public void MarkerTwoOffset() + { + Assert.AreEqual(9, markerTwo.Offset); + } + + [Test] + public void MarkerTwoLength() + { + Assert.AreEqual(14, markerTwo.Length); + } + + [Test] + public void MarkerThreeForeColor() + { + Assert.AreEqual(CodeCoverageOptions.NotVisitedForeColor, markerThree.ForeColor); + } + + [Test] + public void MarkerThreeColor() + { + Assert.AreEqual(CodeCoverageOptions.NotVisitedColor, markerThree.Color); + } + + [Test] + public void MarkerThreeOffset() + { + Assert.AreEqual(27, markerThree.Offset); + } + + [Test] + public void MarkerThreeLength() + { + Assert.AreEqual(1, markerThree.Length); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/AssemblyInfo.cs b/src/AddIns/Misc/CodeCoverage/Test/AssemblyInfo.cs new file mode 100644 index 0000000000..906720da13 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly: AssemblyVersion("1.0.*")] + diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj new file mode 100644 index 0000000000..53ad7a1104 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj @@ -0,0 +1,83 @@ + + + Library + ICSharpCode.CodeCoverage.Tests + CodeCoverage.Tests + Debug + AnyCPU + {A5C0E8F8-9D04-46ED-91D6-1DEF1575313B} + False + False + False + Auto + 4194304 + AnyCPU + 4096 + 4 + false + + + ..\..\..\..\..\bin\UnitTests\ + False + DEBUG;TRACE + true + Full + True + + + ..\..\..\..\..\bin\UnitTests\ + True + TRACE + false + None + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2748AD25-9C63-4E12-877B-4DCE96FBED54} + ICSharpCode.SharpDevelop + + + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C} + ICSharpCode.Core + + + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} + ICSharpCode.TextEditor + + + {83DD7E12-A705-4DBA-9D71-09C8973D9382} + nunit.framework.dll + + + {B7F1A068-01F5-49E7-83EF-05DE281B09FD} + CodeCoverageAddIn + + + + \ No newline at end of file diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersCoverMultipleLinesTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersCoverMultipleLinesTestFixture.cs new file mode 100644 index 0000000000..58451f69b7 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersCoverMultipleLinesTestFixture.cs @@ -0,0 +1,89 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.CodeCoverage; +using ICSharpCode.TextEditor.Document; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class CodeCoverageMarkersCoverMultipleLinesTestFixture + { + List markers; + [TestFixtureSetUp] + public void SetUpFixture() + { + try { + string configFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NCoverAddIn.Tests"); + PropertyService.InitializeService(configFolder, Path.Combine(configFolder, "data"), "NCoverAddIn.Tests"); + } catch (Exception) {} + + MockDocument document = new MockDocument(); + string code = "\t\t{\r\n" + + "\t\t\treturn \"\\r\\n\" +\r\n" + + "\t\t\t\t\"\\r\\n\" +\r\n" + + "\t\t\t\t\"\\r\\n\" +\r\n" + + "\t\t\t\t\"\\r\\n\" +\r\n" + + "\t\t\t\t\"\";\r\n" + + "\t\t}\r\n"; + document.AddLines(code); + MarkerStrategy markerStrategy = new MarkerStrategy(document); + + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + + CodeCoverageResults results = new CodeCoverageResults(new StringReader(xml)); + CodeCoverageMethod method = results.Modules[0].Methods[0]; + CodeCoverageHighlighter highlighter = new CodeCoverageHighlighter(); + highlighter.AddMarkers(markerStrategy, method.SequencePoints); + + markers = new List(); + foreach (CodeCoverageTextMarker marker in markerStrategy.TextMarker) { + markers.Add(marker); + } + } + + [Test] + public void MarkerCount() + { + Assert.AreEqual(10, markers.Count); + } + + [Test] + public void MarkerThreeOffset() + { + Assert.AreEqual(48, markers[2].Offset); + } + + [Test] + public void MarkerFourOffset() + { + Assert.AreEqual(118, markers[3].Offset); + } + + [Test] + public void MarkerNineOffset() + { + Assert.AreEqual(338, markers[8].Offset); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersCoverTwoLinesTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersCoverTwoLinesTestFixture.cs new file mode 100644 index 0000000000..2eedca5db3 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersCoverTwoLinesTestFixture.cs @@ -0,0 +1,118 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.CodeCoverage; +using ICSharpCode.TextEditor.Document; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class CodeCoverageMarkersCoverTwoLinesTestFixture + { + CodeCoverageTextMarker markerOne; + CodeCoverageTextMarker markerTwo; + CodeCoverageTextMarker markerThree; + CodeCoverageTextMarker markerFour; + + [TestFixtureSetUp] + public void SetUpFixture() + { + try { + string configFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NCoverAddIn.Tests"); + PropertyService.InitializeService(configFolder, Path.Combine(configFolder, "data"), "NCoverAddIn.Tests"); + } catch (Exception) {} + + MockDocument document = new MockDocument(); + string code = "\t\t{\r\n" + + "\t\t\tAssert.AreEqual(0, childElementCompletionData.Length, \"\" +\r\n" + + "\t\t\t \"Not expecting any child elements.\");\r\n" + + "\t\t}\r\n"; + document.AddLines(code); + MarkerStrategy markerStrategy = new MarkerStrategy(document); + + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + + CodeCoverageResults results = new CodeCoverageResults(new StringReader(xml)); + CodeCoverageMethod method = results.Modules[0].Methods[0]; + CodeCoverageHighlighter highlighter = new CodeCoverageHighlighter(); + highlighter.AddMarkers(markerStrategy, method.SequencePoints); + + foreach (CodeCoverageTextMarker marker in markerStrategy.TextMarker) { + if (markerOne == null) { + markerOne = marker; + } else if (markerTwo == null) { + markerTwo = marker; + } else if (markerThree == null) { + markerThree = marker; + } else if (markerFour == null) { + markerFour = marker; + } + } + } + + [Test] + public void MarkerOneOffset() + { + Assert.AreEqual(3, markerOne.Offset); + } + + [Test] + public void MarkerOneLength() + { + Assert.AreEqual(1, markerOne.Length); + } + + [Test] + public void MarkerTwoOffset() + { + Assert.AreEqual(9, markerTwo.Offset); + } + + [Test] + public void MarkerTwoLength() + { + Assert.AreEqual(56, markerTwo.Length); + } + + [Test] + public void MarkerThreeOffset() + { + Assert.AreEqual(68, markerThree.Offset); + } + + [Test] + public void MarkerThreeLength() + { + Assert.AreEqual(56, markerThree.Length); + } + + [Test] + public void MarkerFourLength() + { + Assert.AreEqual(1, markerFour.Length); + } + + [Test] + public void MarkerFourOffset() + { + Assert.AreEqual(129, markerFour.Offset); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidEndColumnTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidEndColumnTestFixture.cs new file mode 100644 index 0000000000..b87d9796af --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidEndColumnTestFixture.cs @@ -0,0 +1,64 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.CodeCoverage; +using ICSharpCode.TextEditor.Document; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class CodeCoverageMarkersInvalidEndColumnTestFixture + { + List markers; + + [SetUp] + public void Init() + { + try { + string configFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NCoverAddIn.Tests"); + PropertyService.InitializeService(configFolder, Path.Combine(configFolder, "data"), "NCoverAddIn.Tests"); + } catch (Exception) {} + + MockDocument document = new MockDocument(); + document.AddLines("abcdefg\r\nabc"); + MarkerStrategy markerStrategy = new MarkerStrategy(document); + + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + + CodeCoverageResults results = new CodeCoverageResults(new StringReader(xml)); + CodeCoverageMethod method = results.Modules[0].Methods[0]; + CodeCoverageHighlighter highlighter = new CodeCoverageHighlighter(); + highlighter.AddMarkers(markerStrategy, method.SequencePoints); + + markers = new List(); + foreach (CodeCoverageTextMarker marker in markerStrategy.TextMarker) { + markers.Add(marker); + } + } + + [Test] + public void NoMarkersAdded() + { + Assert.AreEqual(0, markers.Count, + "Should not be any markers added since all sequence point end columns are invalid."); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidEndLineTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidEndLineTestFixture.cs new file mode 100644 index 0000000000..ffa7271f83 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidEndLineTestFixture.cs @@ -0,0 +1,65 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.CodeCoverage; +using ICSharpCode.TextEditor.Document; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class CodeCoverageMarkersInvalidEndLineTestFixture + { + List markers; + + [SetUp] + public void Init() + { + try { + string configFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NCoverAddIn.Tests"); + PropertyService.InitializeService(configFolder, Path.Combine(configFolder, "data"), "NCoverAddIn.Tests"); + } catch (Exception) {} + + MockDocument document = new MockDocument(); + // Give doc 3 lines (end line seems to be counted as an extra line). + document.AddLines("abc\r\ndef"); + MarkerStrategy markerStrategy = new MarkerStrategy(document); + + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + + CodeCoverageResults results = new CodeCoverageResults(new StringReader(xml)); + CodeCoverageMethod method = results.Modules[0].Methods[0]; + CodeCoverageHighlighter highlighter = new CodeCoverageHighlighter(); + highlighter.AddMarkers(markerStrategy, method.SequencePoints); + + markers = new List(); + foreach (CodeCoverageTextMarker marker in markerStrategy.TextMarker) { + markers.Add(marker); + } + } + + [Test] + public void NoMarkersAdded() + { + Assert.AreEqual(0, markers.Count, + "Should not be any markers added since all sequence point end lines are invalid."); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidStartColumnTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidStartColumnTestFixture.cs new file mode 100644 index 0000000000..3289b27af3 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidStartColumnTestFixture.cs @@ -0,0 +1,63 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.CodeCoverage; +using ICSharpCode.TextEditor.Document; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class CodeCoverageMarkersInvalidStartColumnTestFixture + { + List markers; + + [SetUp] + public void Init() + { + try { + string configFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NCoverAddIn.Tests"); + PropertyService.InitializeService(configFolder, Path.Combine(configFolder, "data"), "NCoverAddIn.Tests"); + } catch (Exception) {} + + MockDocument document = new MockDocument(); + document.AddLines("abcdefg\r\nabcdefg"); + MarkerStrategy markerStrategy = new MarkerStrategy(document); + + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + + CodeCoverageResults results = new CodeCoverageResults(new StringReader(xml)); + CodeCoverageMethod method = results.Modules[0].Methods[0]; + CodeCoverageHighlighter highlighter = new CodeCoverageHighlighter(); + highlighter.AddMarkers(markerStrategy, method.SequencePoints); + + markers = new List(); + foreach (CodeCoverageTextMarker marker in markerStrategy.TextMarker) { + markers.Add(marker); + } + } + + [Test] + public void NoMarkersAdded() + { + Assert.AreEqual(0, markers.Count, + "Should not be any markers added since all sequence point start columns are invalid."); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidStartLineTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidStartLineTestFixture.cs new file mode 100644 index 0000000000..37d8e004e5 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageMarkersInvalidStartLineTestFixture.cs @@ -0,0 +1,62 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.CodeCoverage; +using ICSharpCode.TextEditor.Document; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class CodeCoverageMarkersInvalidStartLineTestFixture + { + List markers; + + [SetUp] + public void Init() + { + try { + string configFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NCoverAddIn.Tests"); + PropertyService.InitializeService(configFolder, Path.Combine(configFolder, "data"), "NCoverAddIn.Tests"); + } catch (Exception) {} + + MockDocument document = new MockDocument(); + MarkerStrategy markerStrategy = new MarkerStrategy(document); + + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + + CodeCoverageResults results = new CodeCoverageResults(new StringReader(xml)); + CodeCoverageMethod method = results.Modules[0].Methods[0]; + CodeCoverageHighlighter highlighter = new CodeCoverageHighlighter(); + highlighter.AddMarkers(markerStrategy, method.SequencePoints); + + markers = new List(); + foreach (CodeCoverageTextMarker marker in markerStrategy.TextMarker) { + markers.Add(marker); + } + } + + [Test] + public void NoMarkersAdded() + { + Assert.AreEqual(0, markers.Count, + "Should not be any markers added since all sequence point start lines are invalid."); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageResultsTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageResultsTestFixture.cs new file mode 100644 index 0000000000..2612745ea9 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageResultsTestFixture.cs @@ -0,0 +1,148 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.CodeCoverage; +using NUnit.Framework; +using System; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class CodeCoverageResultsTestFixture + { + CodeCoverageModule module; + CodeCoverageResults results; + CodeCoverageMethod method; + CodeCoverageSequencePoint point1; + CodeCoverageSequencePoint point2; + CodeCoverageSequencePoint point3; + + [TestFixtureSetUp] + public void SetUpFixture() + { + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + results = new CodeCoverageResults(new StringReader(xml)); + module = results.Modules[0]; + method = module.Methods[0]; + + point1 = method.SequencePoints[0]; + point2 = method.SequencePoints[1]; + point3 = method.SequencePoints[2]; + } + + [Test] + public void AssemblyName() + { + Assert.AreEqual("Foo.Tests", module.Name); + } + + [Test] + public void ModuleCount() + { + Assert.AreEqual(1, results.Modules.Count); + } + + [Test] + public void MethodCount() + { + Assert.AreEqual(1, module.Methods.Count); + } + + [Test] + public void MethodName() + { + Assert.AreEqual("SimpleTest", method.Name); + } + + [Test] + public void FullClassName() + { + Assert.AreEqual("Foo.Tests.FooTestFixture", method.FullClassName); + } + + [Test] + public void ClassName() + { + Assert.AreEqual("FooTestFixture", method.ClassName); + } + + [Test] + public void ClassNamespace() + { + Assert.AreEqual("Foo.Tests", method.ClassNamespace); + } + + [Test] + public void SequencePointCount() + { + Assert.AreEqual(3, method.SequencePoints.Count); + } + + [Test] + public void SequencePointDocument() + { + Assert.AreEqual("c:\\Projects\\Foo\\FooTestFixture.cs", point1.Document); + } + + [Test] + public void SequencePoint1VisitCount() + { + Assert.AreEqual(1, point1.VisitCount); + } + + [Test] + public void SequencePoint3VisitCount() + { + Assert.AreEqual(0, point3.VisitCount); + } + + [Test] + public void SequencePoint1Line() + { + Assert.AreEqual(20, point1.Line); + } + + [Test] + public void SequencePoint1Column() + { + Assert.AreEqual(3, point1.Column); + } + + [Test] + public void SequencePoint1EndLine() + { + Assert.AreEqual(20, point1.EndLine); + } + + [Test] + public void SequencePoint1EndColumn() + { + Assert.AreEqual(4, point1.EndColumn); + } + + [Test] + public void MethodVisitedCount() + { + Assert.AreEqual(2, method.VisitedSequencePointsCount); + } + + [Test] + public void MethodNotVisitedCount() + { + Assert.AreEqual(1, method.NotVisitedSequencePointsCount); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageTreeViewTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageTreeViewTestFixture.cs new file mode 100644 index 0000000000..648ba8bf98 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverageTreeViewTestFixture.cs @@ -0,0 +1,166 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.CodeCoverage; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class CodeCoverageTreeViewTestFixture + { + TreeNodeCollection nodes; + CodeCoverageModuleTreeNode fooModuleNode; + CodeCoverageModuleTreeNode barModuleNode; + CodeCoverageClassTreeNode class1TreeNode; + CodeCoverageMethodTreeNode method1TreeNode; + CodeCoverageMethodTreeNode method2TreeNode; + CodeCoverageNamespaceTreeNode namespace1TreeNode; + CodeCoverageNamespaceTreeNode namespace2TreeNode; + + [TestFixtureSetUp] + public void SetUpFixture() + { + List modules = new List(); + CodeCoverageModule m1 = new CodeCoverageModule("Foo.Tests"); + CodeCoverageMethod method1 = new CodeCoverageMethod("Test1", "Foo.Tests.TestFixture1"); + method1.SequencePoints.Add(new CodeCoverageSequencePoint("c:\\Projects\\Foo\\TestFixture1.cs", 1, 1, 0, 2, 1)); + method1.SequencePoints.Add(new CodeCoverageSequencePoint("c:\\Projects\\Foo\\TestFixture1.cs", 0, 2, 2, 3, 4)); + CodeCoverageMethod method2 = new CodeCoverageMethod("Test2", "Foo.Tests.TestFixture1"); + + m1.Methods.Add(method1); + m1.Methods.Add(method2); + + CodeCoverageModule m2 = new CodeCoverageModule("Bar.Tests"); + + modules.Add(m1); + modules.Add(m2); + + using (CodeCoverageTreeView treeView = new CodeCoverageTreeView()) { + treeView.AddModules(modules); + treeView.ExpandAll(); + nodes = treeView.Nodes; + } + + fooModuleNode = (CodeCoverageModuleTreeNode)nodes[0]; + barModuleNode = (CodeCoverageModuleTreeNode)nodes[1]; + + namespace1TreeNode = (CodeCoverageNamespaceTreeNode)fooModuleNode.Nodes[0]; + namespace2TreeNode = (CodeCoverageNamespaceTreeNode)namespace1TreeNode.Nodes[0]; + + class1TreeNode = (CodeCoverageClassTreeNode)namespace2TreeNode.Nodes[0]; + method1TreeNode = (CodeCoverageMethodTreeNode)class1TreeNode.Nodes[0]; + method2TreeNode = (CodeCoverageMethodTreeNode)class1TreeNode.Nodes[1]; + } + + [Test] + public void RootNodesCount() + { + Assert.AreEqual(2, nodes.Count); + } + + [Test] + public void FooModuleTreeNodeText() + { + Assert.AreEqual("Foo.Tests (50%)", fooModuleNode.Text); + } + + [Test] + public void FooModuleTreeNodeForeColor() + { + Assert.AreEqual(CodeCoverageTreeNode.PartialCoverageTextColor, fooModuleNode.ForeColor); + } + + [Test] + public void FooModuleChildNodesCount() + { + Assert.AreEqual(1, fooModuleNode.Nodes.Count); + } + + [Test] + public void FooModuleTreeNodeName() + { + Assert.AreEqual("Foo.Tests", fooModuleNode.Name); + } + + [Test] + public void BarModuleTreeNodeText() + { + Assert.AreEqual("Bar.Tests", barModuleNode.Text); + } + + [Test] + public void Class1TreeNodeName() + { + Assert.AreEqual("TestFixture1", class1TreeNode.Name); + } + + [Test] + public void Class1TreeNodeText() + { + Assert.AreEqual("TestFixture1 (50%)", class1TreeNode.Text); + } + + [Test] + public void Namespace1TreeNodeName() + { + Assert.AreEqual("Foo", namespace1TreeNode.Name); + } + + [Test] + public void Namespace2TreeNodeName() + { + Assert.AreEqual("Tests", namespace2TreeNode.Name); + } + + [Test] + public void Namespace1TreeNodeText() + { + Assert.AreEqual("Foo (50%)", namespace1TreeNode.Text); + } + + [Test] + public void Namespace2TreeNodeText() + { + Assert.AreEqual("Tests (50%)", namespace2TreeNode.Text); + } + + [Test] + public void Method1TreeNodeName() + { + Assert.AreEqual("Test1", method1TreeNode.Name); + } + + [Test] + public void Method1TreeNodeText() + { + Assert.AreEqual("Test1 (50%)", method1TreeNode.Text); + } + + [Test] + public void Method2TreeNodeText() + { + Assert.AreEqual("Test2", method2TreeNode.Name); + } + + [Test] + public void Class1TreeNodeChildNodesCount() + { + Assert.AreEqual(2, class1TreeNode.Nodes.Count); + } + + [Test] + public void Namespace2TreeNodeChildNodesCount() + { + Assert.AreEqual(1, namespace2TreeNode.Nodes.Count); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/GetSequencePointsForFileNameTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/GetSequencePointsForFileNameTestFixture.cs new file mode 100644 index 0000000000..76d9a40a4f --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/GetSequencePointsForFileNameTestFixture.cs @@ -0,0 +1,78 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.CodeCoverage; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class GetSequencePointsForFileNameTestFixture + { + CodeCoverageResults results; + List fooTestFixtureSequencePoints; + List barTestFixtureSequencePoints; + List simpleTestFixtureSequencePoints; + List nonExistentFileNameSequencePoints; + + [SetUp] + public void SetUpFixture() + { + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + + results = new CodeCoverageResults(new StringReader(xml)); + fooTestFixtureSequencePoints = results.GetSequencePoints(@"c:\Projects\Foo\FooTestFixture.cs"); + barTestFixtureSequencePoints = results.GetSequencePoints(@"c:\Projects\Foo\BarTestFixture.cs"); + simpleTestFixtureSequencePoints = results.GetSequencePoints(@"c:\Projects\Foo\SimpleTestFixture.cs"); + nonExistentFileNameSequencePoints = results.GetSequencePoints(@"c:\Projects\Foo\NoSuchTestFixture.cs"); + } + + [Test] + public void FooTestFixtureHasSequencePoint() + { + Assert.AreEqual(1, fooTestFixtureSequencePoints.Count); + } + + [Test] + public void BarTestFixtureHasSequencePoint() + { + Assert.AreEqual(1, barTestFixtureSequencePoints.Count); + } + + [Test] + public void SimpleTestFixtureHasSequencePoints() + { + Assert.AreEqual(2, simpleTestFixtureSequencePoints.Count); + } + + [Test] + public void NonExistentFileNameHasNoSequencePoints() + { + Assert.AreEqual(0, nonExistentFileNameSequencePoints.Count); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/MbUnitResultsTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/MbUnitResultsTestFixture.cs new file mode 100644 index 0000000000..c3c88e051e --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/MbUnitResultsTestFixture.cs @@ -0,0 +1,121 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.CodeCoverage; +using NUnit.Framework; +using System; +using System.IO; +using System.Resources; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class MbUnitResultsTestFixture + { + Task errorTask; + + [SetUp] + public void Init() + { + // Add NUnitPad TestFailedMessage string resource since this resource + // contains a format string that has parameters that are otherwise not + // set. + ResourceManager resourceManager = new ResourceManager("ICSharpCode.CodeCoverage.Tests.Strings", GetType().Assembly); + ResourceService.RegisterNeutralStrings(resourceManager); + + MbUnitResults results = new MbUnitResults(new StringReader(GetMbUnitResultsXml())); + errorTask = results.Tasks[0]; + } + + [Test] + public void IsErrorTask() + { + Assert.AreEqual(TaskType.Error, errorTask.TaskType); + } + + [Test] + public void ErrorTaskFileName() + { + Assert.IsTrue(FileUtility.IsEqualFileName(@"c:\test\NunitFoo\NunitFoo.Tests\FooTest.cs", errorTask.FileName)); + } + + [Test] + public void ErrorTaskLine() + { + Assert.AreEqual(21, errorTask.Line); + } + + [Test] + public void ErrorTaskColumn() + { + Assert.AreEqual(0, errorTask.Column); + } + + [Test] + public void TaskDescription() + { + string description = StringParser.Parse("${res:NUnitPad.NUnitPadContent.TestTreeView.TestFailedMessage}", new string[,] { + {"TestCase", "FooTest.Foo"}, + {"Message", "Foo failed"} + }); + + Assert.AreEqual(description, errorTask.Description); + } + + string GetMbUnitResultsXml() + { + return "\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " Foo failed\r\n" + + " nunit.framework\r\n" + + " at NUnit.Framework.Assert.Fail(String message, Object[] args)\r\n" + + " at NUnit.Framework.Assert.Fail(String message)\r\n" + + " at NunitFoo.Tests.FooTest.Foo() in c:\\test\\NunitFoo\\NunitFoo.Tests\\FooTest.cs:line 22\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + ""; + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/MockDocument.cs b/src/AddIns/Misc/CodeCoverage/Test/MockDocument.cs new file mode 100644 index 0000000000..c05c41ce81 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/MockDocument.cs @@ -0,0 +1,276 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.TextEditor.Document; +using System; +using System.Collections.Generic; + +namespace ICSharpCode.CodeCoverage.Tests +{ + /// + /// Helper class that implements the Text Editor library's IDocument interface. + /// + public class MockDocument : IDocument + { + List lineSegments = new List(); + + public MockDocument() + { + } + + public event EventHandler UpdateCommited; + + public event DocumentEventHandler DocumentAboutToBeChanged; + + public event DocumentEventHandler DocumentChanged; + + public event EventHandler TextContentChanged; + + public void AddLines(string code) + { + int offset = 0; + string[] lines = code.Split('\n'); + foreach (string line in lines) { + int delimiterLength = 1; + if (line.Length > 0 && line[line.Length - 1] == '\r') { + delimiterLength = 2; + } + LineSegment lineSegment = new LineSegment(offset, offset + line.Length, delimiterLength); + lineSegments.Add(lineSegment); + offset += line.Length + lineSegment.DelimiterLength - 1; + } + } + + public ITextEditorProperties TextEditorProperties { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public ICSharpCode.TextEditor.Undo.UndoStack UndoStack { + get { + throw new NotImplementedException(); + } + } + + public bool ReadOnly { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public IFormattingStrategy FormattingStrategy { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public ITextBufferStrategy TextBufferStrategy { + get { + throw new NotImplementedException(); + } + } + + public FoldingManager FoldingManager { + get { + throw new NotImplementedException(); + } + } + + public IHighlightingStrategy HighlightingStrategy { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public BookmarkManager BookmarkManager { + get { + throw new NotImplementedException(); + } + } + + public ICustomLineManager CustomLineManager { + get { + throw new NotImplementedException(); + } + } + + public MarkerStrategy MarkerStrategy { + get { + throw new NotImplementedException(); + } + } + + public System.Collections.Generic.List LineSegmentCollection { + get { + return lineSegments; + } + } + + public int TotalNumberOfLines { + get { + if (lineSegments.Count == 0) { + return 1; + } + + return ((LineSegment)lineSegments[lineSegments.Count - 1]).DelimiterLength > 0 ? lineSegments.Count + 1 : lineSegments.Count; + } + } + + public string TextContent { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } + + public int TextLength { + get { + throw new NotImplementedException(); + } + } + + public System.Collections.Generic.List UpdateQueue { + get { + throw new NotImplementedException(); + } + } + + public void UpdateSegmentListOnDocumentChange(System.Collections.Generic.List list, DocumentEventArgs e) where T : ISegment + { + throw new NotImplementedException(); + } + + public int GetLineNumberForOffset(int offset) + { + throw new NotImplementedException(); + } + + public LineSegment GetLineSegmentForOffset(int offset) + { + throw new NotImplementedException(); + } + + public LineSegment GetLineSegment(int lineNumber) + { + return lineSegments[lineNumber]; + } + + public int GetFirstLogicalLine(int lineNumber) + { + throw new NotImplementedException(); + } + + public int GetLastLogicalLine(int lineNumber) + { + throw new NotImplementedException(); + } + + public int GetVisibleLine(int lineNumber) + { + throw new NotImplementedException(); + } + + public int GetNextVisibleLineAbove(int lineNumber, int lineCount) + { + throw new NotImplementedException(); + } + + public int GetNextVisibleLineBelow(int lineNumber, int lineCount) + { + throw new NotImplementedException(); + } + + public void Insert(int offset, string text) + { + throw new NotImplementedException(); + } + + public void Remove(int offset, int length) + { + throw new NotImplementedException(); + } + + public void Replace(int offset, int length, string text) + { + throw new NotImplementedException(); + } + + public char GetCharAt(int offset) + { + throw new NotImplementedException(); + } + + public string GetText(int offset, int length) + { + throw new NotImplementedException(); + } + + public string GetText(ISegment segment) + { + throw new NotImplementedException(); + } + + public System.Drawing.Point OffsetToPosition(int offset) + { + throw new NotImplementedException(); + } + + public int PositionToOffset(System.Drawing.Point p) + { + throw new NotImplementedException(); + } + + public void RequestUpdate(ICSharpCode.TextEditor.TextAreaUpdate update) + { + throw new NotImplementedException(); + } + + public void CommitUpdate() + { + throw new NotImplementedException(); + } + + void OnUpdateCommited() + { + if (UpdateCommited != null) { + } + } + + void OnDocumentAboutToBeChanged() + { + if (DocumentAboutToBeChanged != null) { + } + } + + void OnDocumentChanged() + { + if (DocumentChanged != null) { + } + } + + void OnTextContentChanged() + { + if (TextContentChanged != null) { + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/ModuleVisitedSequencePointsTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/ModuleVisitedSequencePointsTestFixture.cs new file mode 100644 index 0000000000..566cb720a1 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/ModuleVisitedSequencePointsTestFixture.cs @@ -0,0 +1,75 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.CodeCoverage; +using NUnit.Framework; +using System; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class ModuleVisitedSequencePointsTestFixture + { + CodeCoverageModule fooModule; + CodeCoverageModule barModule; + CodeCoverageResults results; + + [TestFixtureSetUp] + public void SetUpFixture() + { + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + results = new CodeCoverageResults(new StringReader(xml)); + fooModule = results.Modules[0]; + barModule = results.Modules[1]; + } + + [Test] + public void FooModuleVisitedCount() + { + Assert.AreEqual(4, fooModule.VisitedSequencePointsCount); + } + + [Test] + public void FooModuleNotVisitedCount() + { + Assert.AreEqual(2, fooModule.NotVisitedSequencePointsCount); + } + + [Test] + public void BarModuleVisitedCount() + { + Assert.AreEqual(2, barModule.VisitedSequencePointsCount); + } + + [Test] + public void BarModuleNotVisitedCount() + { + Assert.AreEqual(1, barModule.NotVisitedSequencePointsCount); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/NCoverSettingsTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/NCoverSettingsTestFixture.cs new file mode 100644 index 0000000000..1f4fa44821 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/NCoverSettingsTestFixture.cs @@ -0,0 +1,49 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.CodeCoverage; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Project; +using NUnit.Framework; +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class NCoverSettingsTestFixture + { + NCoverSettings settings; + NCoverSettings savedSettings; + + [SetUp] + public void Init() + { + settings = new NCoverSettings(); + settings.AssemblyList = "MyNamespace.Foo; MyNamespace.Bar"; + StringBuilder savedSettingsXml = new StringBuilder(); + settings.Save(new StringWriter(savedSettingsXml)); + savedSettings = new NCoverSettings(new StringReader(savedSettingsXml.ToString())); + } + + [Test] + public void IsAssemblyListSaved() + { + Assert.AreEqual(settings.AssemblyList, savedSettings.AssemblyList); + } + + [Test] + public void NCoverSettingsFileName() + { + MSBuildProject project = new MSBuildProject(); + project.FileName = @"C:\temp\test.csproj"; + + Assert.AreEqual(@"C:\temp\test.NCover.Settings", NCoverSettings.GetFileName(project)); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/RemoveCodeCoverageMarkersTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/RemoveCodeCoverageMarkersTestFixture.cs new file mode 100644 index 0000000000..5c58d56013 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/RemoveCodeCoverageMarkersTestFixture.cs @@ -0,0 +1,97 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core; +using ICSharpCode.CodeCoverage; +using ICSharpCode.TextEditor.Document; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.CodeCoverage.Tests +{ + [TestFixture] + public class RemoveCodeCoverageMarkersTestFixture + { + MarkerStrategy markerStrategy; + + [TestFixtureSetUp] + public void SetUpTestFixture() + { + try { + string configFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NCoverAddIn.Tests"); + PropertyService.InitializeService(configFolder, Path.Combine(configFolder, "data"), "NCoverAddIn.Tests"); + } catch (Exception) {} + + MockDocument document = new MockDocument(); + string code = "\t\t{\r\n" + + "\t\t\tint count = 0;\r\n" + + "\t\t}\r\n"; + document.AddLines(code); + markerStrategy = new MarkerStrategy(document); + + string xml = "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + CodeCoverageResults results = new CodeCoverageResults(new StringReader(xml)); + CodeCoverageMethod method = results.Modules[0].Methods[0]; + CodeCoverageHighlighter highlighter = new CodeCoverageHighlighter(); + highlighter.AddMarkers(markerStrategy, method.SequencePoints); + + // Add non-code coverage markers. + markerStrategy.AddMarker(new TextMarker(0, 2, TextMarkerType.Underlined)); + markerStrategy.AddMarker(new TextMarker(4, 5, TextMarkerType.Underlined)); + } + + [Test] + public void RemoveCodeCoverageMarkers() + { + // Check that code coverage markers exist. + Assert.IsTrue(ContainsCodeCoverageMarkers(markerStrategy)); + + // Remove code coverage markers. + CodeCoverageHighlighter highlighter = new CodeCoverageHighlighter(); + highlighter.RemoveMarkers(markerStrategy); + + // Check that code coverage markers have been removed. + Assert.IsFalse(ContainsCodeCoverageMarkers(markerStrategy)); + + // Check that non-code coverage markers still exist. + Assert.IsTrue(ContainsNonCodeCoverageMarkers(markerStrategy)); + } + + static bool ContainsCodeCoverageMarkers(MarkerStrategy markerStrategy) + { + foreach (TextMarker marker in markerStrategy.TextMarker) { + if (marker is CodeCoverageTextMarker) { + return true; + } + } + return false; + } + + static bool ContainsNonCodeCoverageMarkers(MarkerStrategy markerStrategy) + { + int count = 0; + foreach (TextMarker marker in markerStrategy.TextMarker) { + if (marker is CodeCoverageTextMarker) { + return false; + } + count++; + } + return count > 0; + } + + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/Strings.resources b/src/AddIns/Misc/CodeCoverage/Test/Strings.resources new file mode 100644 index 0000000000000000000000000000000000000000..33d565fcc1365ad79e65d2acfc3650c44ea30533 GIT binary patch literal 358 zcmZWj%}N6?5T5l(0t&q>YyH{Q3VVBUAdWH0d7ASl4xfn<}Z*-T76?)RnR;R@{ zWiIMyLiAW!jKNEjizaqPt6SW(?h$R(O{cO{<>X{`c8=qV+2Q`MXoDVbH+_lWfR{?k zrD(3M)5+f6KNCG>-QK}HSkMrl0SP@6@L#FH@rwZXTMK9z5%U&2BZL)qBRp~E&bi^A yG#FNUm~$mg32R0vva&@ALP 0; diff --git a/src/Main/StartUp/Project/Resources/BitmapResources.resources b/src/Main/StartUp/Project/Resources/BitmapResources.resources index e611ece9f720fcb2404f71052445411a58557f5c..a40799485316899b7a9b5aa96d9c5052979b7014 100644 GIT binary patch delta 7967 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 diff --git a/src/SharpDevelop.sln b/src/SharpDevelop.sln index d6117812ce..a3b5374d34 100644 --- a/src/SharpDevelop.sln +++ b/src/SharpDevelop.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 9.00 -# SharpDevelop 2.0.0.1020 +# SharpDevelop 2.0.0.960 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddIns", "AddIns", "{14A277EE-7DF1-4529-B639-7D1EF334C1C5}" ProjectSection(SolutionItems) = postProject EndProjectSection @@ -44,6 +44,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{CE5B42B7-6 ProjectSection(SolutionItems) = postProject EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCoverage", "AddIns\Misc\CodeCoverage\Project\CodeCoverage.csproj", "{08ce9972-283b-44f4-82fa-966f7dfa6b7a}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpQuery", "AddIns\Misc\SharpQuery\SharpQuery.csproj", "{BDD03ECD-42AE-4B50-9805-9C19090A264F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoReflectionLoader", "AddIns\Misc\MonoReflectionLoader\Project\MonoReflectionLoader.csproj", "{8C52FFA5-35AF-4E28-8498-2DC2F168A241}" @@ -274,6 +276,10 @@ Global {0F784A65-33B4-43EB-A49A-50A15EEF9829}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0F784A65-33B4-43EB-A49A-50A15EEF9829}.Release|Any CPU.Build.0 = Release|Any CPU {0F784A65-33B4-43EB-A49A-50A15EEF9829}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08CE9972-283B-44F4-82FA-966F7DFA6B7A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08CE9972-283B-44F4-82FA-966F7DFA6B7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08CE9972-283B-44F4-82FA-966F7DFA6B7A}.Release|Any CPU.Build.0 = Release|Any CPU + {08CE9972-283B-44F4-82FA-966F7DFA6B7A}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -309,6 +315,7 @@ Global {082DCD64-EE32-4151-A50F-E139CF754CC0} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} {8C52FFA5-35AF-4E28-8498-2DC2F168A241} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} {BDD03ECD-42AE-4B50-9805-9C19090A264F} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {08ce9972-283b-44f4-82fa-966f7dfa6b7a} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} {B08385CD-F0CC-488C-B4F4-EEB34B6D2688} = {6604365C-C702-4C10-9BA8-637F1E3D4D0D} {1D18D788-F7EE-4585-A23B-34DC8EC63CB8} = {6604365C-C702-4C10-9BA8-637F1E3D4D0D} {EC06F96A-AEEC-49D6-B03D-AB87C6EB674C} = {6604365C-C702-4C10-9BA8-637F1E3D4D0D}