├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ ├── ci.yml
│ └── pr.yml
├── .gitignore
├── Directory.Build.props
├── LICENSE
├── NuGet.Config
├── README.md
├── ReferenceTrimmer.sln
├── examples
└── BuildWithReferenceTrimmer.cmd
├── global.json
├── src
├── Analyzer
│ ├── ReferenceTrimmer.Analyzer.csproj
│ └── ReferenceTrimmerAnalyzer.cs
├── Loggers
│ ├── MSVC
│ │ ├── CentralLogger.cs
│ │ ├── ForwardingLogger.cs
│ │ └── UnusedLibsCustomBuildEventArgs.cs
│ └── ReferenceTrimmer.Loggers.csproj
├── Package
│ ├── ReferenceTrimmer.Package.csproj
│ ├── build
│ │ ├── ReferenceTrimmer.props
│ │ └── ReferenceTrimmer.targets
│ ├── buildMultiTargeting
│ │ ├── ReferenceTrimmer.props
│ │ └── ReferenceTrimmer.targets
│ └── tools
│ │ ├── install.ps1
│ │ └── uninstall.ps1
├── Shared
│ ├── DeclaredReferences.cs
│ └── NetStandardPolyfills.cs
├── Tasks
│ ├── CollectDeclaredReferencesTask.cs
│ └── ReferenceTrimmer.Tasks.csproj
└── Tests
│ ├── E2ETests.cs
│ ├── MsvcLoggerTests.cs
│ ├── ReferenceTrimmer.Tests.csproj
│ └── TestData
│ ├── AbsoluteIntermediateOutputPath
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── BuildExtensions
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── BuildPackageReference
│ └── Library
│ │ └── Library.csproj
│ ├── Directory.Build.props
│ ├── Directory.Build.targets
│ ├── LegacyStyleProject
│ └── Library
│ │ ├── Class1.cs
│ │ ├── Library.csproj
│ │ └── Properties
│ │ └── AssemblyInfo.cs
│ ├── MissingReferenceSourceTarget
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── NoTargets
│ └── Project.csproj
│ ├── NuGet.Config
│ ├── PackageReferenceWithFakeBuildFile
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── PlatformPackageConflictResolution
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── ReferenceInPackage
│ └── Tests
│ │ ├── FooTests.cs
│ │ └── Tests.csproj
│ ├── ReferenceTrimmerDisabled
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── TargetFrameworkWithOs
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedCppDelayLoadLibrary
│ ├── App
│ │ ├── App.cpp
│ │ └── App.vcxproj
│ └── Dll
│ │ ├── DLL.vcxproj
│ │ ├── dllmain.cpp
│ │ ├── framework.h
│ │ ├── pch.cpp
│ │ └── pch.h
│ ├── UnusedCppLibrary
│ ├── App
│ │ ├── App.cpp
│ │ └── App.vcxproj
│ └── Library
│ │ ├── Library.cpp
│ │ └── Library.vcxproj
│ ├── UnusedDirectAndTransitiveProjectReference
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ ├── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ └── TransitiveDependency
│ │ ├── TransitiveDependency.cs
│ │ └── TransitiveDependency.csproj
│ ├── UnusedPackageReference
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedPackageReferenceDocDisabled
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedPackageReferenceNoWarn
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedPackageReferenceTreatAsUsed
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedProjectReference
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedProjectReferenceNoReferenceAssembly
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedProjectReferenceNoWarn
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedProjectReferenceProduceReferenceAssembly
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedProjectReferenceSuppressed
│ ├── .globalconfig
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedProjectReferenceTreatAsUsed
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedReferenceFromGac
│ ├── Class1.cs
│ ├── Library.csproj
│ └── Properties
│ │ └── AssemblyInfo.cs
│ ├── UnusedReferenceHintPath
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedReferenceHintPathNoWarn
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedReferenceHintPathTreatAsUsed
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedReferenceItemSpec
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedReferenceItemSpecNoWarn
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedReferenceItemSpecTreatAsUsed
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UnusedTransitiveProjectReference
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ ├── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ └── TransitiveDependency
│ │ ├── TransitiveDependency.cs
│ │ └── TransitiveDependency.csproj
│ ├── UnusedWinSdkImportLibrary
│ └── App
│ │ ├── App.cpp
│ │ ├── App.vcxproj
│ │ └── util.cpp
│ ├── UsedIndirectPackageReference
│ └── WebHost
│ │ ├── Program.cs
│ │ └── WebHost.csproj
│ ├── UsedPackageReference
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UsedProjectReference
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UsedProjectReferenceNoReferenceAssembly
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UsedProjectReferenceProduceReferenceAssembly
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UsedReferenceFromGac
│ ├── Class1.cs
│ ├── Library.csproj
│ └── Properties
│ │ └── AssemblyInfo.cs
│ ├── UsedReferenceHintPath
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ ├── UsedReferenceItemSpec
│ ├── Dependency
│ │ ├── Dependency.cs
│ │ └── Dependency.csproj
│ └── Library
│ │ ├── Library.cs
│ │ └── Library.csproj
│ └── WpfApp
│ ├── Dependency
│ ├── Dependency.cs
│ └── Dependency.csproj
│ └── WpfApp
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── AssemblyInfo.cs
│ ├── MainWindow.xaml
│ ├── MainWindow.xaml.cs
│ └── WpfApp.csproj
└── version.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Build and Test - CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | tags:
8 | - "v*"
9 | # Allow manually triggering
10 | workflow_dispatch:
11 |
12 | jobs:
13 | build:
14 | # TODO: Add ubuntu-latest
15 | runs-on: windows-latest
16 | steps:
17 | - uses: actions/checkout@v4
18 | with:
19 | fetch-depth: 0 # Git Versioning requires a non-shallow clone
20 |
21 | - name: Setup .NET
22 | uses: actions/setup-dotnet@v3
23 |
24 | - name: Run vcvarsall.bat on Windows for MSVC testing
25 | uses: ilammy/msvc-dev-cmd@v1
26 |
27 | - name: Restore
28 | run: dotnet restore -bl:logs/restore.binlog
29 |
30 | - name: Build
31 | run: dotnet build --configuration Release --no-restore -bl:logs/build.binlog
32 |
33 | - name: Test
34 | run: dotnet test --configuration Release --no-build --logger trx --results-directory TestResults --collect:"Code Coverage;Format=Cobertura"
35 |
36 | # - name: Upload coverage to Codecov
37 | # uses: codecov/codecov-action@v4
38 | # with:
39 | # directory: ./TestResults
40 | # files: "*.cobertura.xml"
41 |
42 | - name: Upload test results
43 | uses: actions/upload-artifact@v4
44 | with:
45 | name: test-results
46 | path: ./TestResults
47 | if: ${{ always() }} # Always run this step even on failure
48 |
49 | - name: Upload logs
50 | uses: actions/upload-artifact@v4
51 | with:
52 | name: logs
53 | path: ./logs
54 | if: ${{ always() }} # Always run this step even on failure
55 |
56 | - name: Upload artifacts
57 | uses: actions/upload-artifact@v4
58 | with:
59 | name: artifacts
60 | path: ./artifacts
61 | if: ${{ always() }} # Always run this step even on failure
62 |
63 | - name: Push NuGet package
64 | run: dotnet nuget push artifacts\*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }} --skip-duplicate
65 | if: startsWith(github.ref, 'refs/tags/v')
66 |
--------------------------------------------------------------------------------
/.github/workflows/pr.yml:
--------------------------------------------------------------------------------
1 | name: Build and Test
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | build:
10 | strategy:
11 | matrix:
12 | os: [windows-latest, ubuntu-latest]
13 | runs-on: ${{ matrix.os }}
14 | steps:
15 | - uses: actions/checkout@v4
16 | with:
17 | fetch-depth: 0 # Git Versioning requires a non-shallow clone
18 |
19 | - name: Setup .NET
20 | uses: actions/setup-dotnet@v3
21 |
22 | - name: Run vcvarsall.bat on Windows for MSVC testing
23 | uses: ilammy/msvc-dev-cmd@v1
24 |
25 | - name: Restore
26 | run: dotnet restore -bl:logs/restore.binlog
27 |
28 | - name: Build
29 | run: dotnet build --configuration Release --no-restore -bl:logs/build.binlog
30 |
31 | - name: Test
32 | run: dotnet test --configuration Release --no-build --logger trx --results-directory TestResults --collect:"Code Coverage;Format=Cobertura"
33 |
34 | # - name: Upload coverage to Codecov
35 | # uses: codecov/codecov-action@v4
36 | # with:
37 | # directory: ./TestResults
38 | # files: "*.cobertura.xml"
39 |
40 | - name: Upload test results
41 | uses: actions/upload-artifact@v4
42 | with:
43 | name: test-results-${{ matrix.os }}
44 | path: ./TestResults
45 | if: ${{ always() }} # Always run this step even on failure
46 |
47 | - name: Upload logs
48 | uses: actions/upload-artifact@v4
49 | with:
50 | name: logs-${{ matrix.os }}
51 | path: ./logs
52 | if: ${{ always() }} # Always run this step even on failure
53 |
54 | - name: Upload artifacts
55 | uses: actions/upload-artifact@v4
56 | with:
57 | name: artifacts-${{ matrix.os }}
58 | path: ./artifacts
59 | if: ${{ always() }} # Always run this step even on failure
60 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.binlog
70 | *.vspscc
71 | *.vssscc
72 | .builds
73 | *.pidb
74 | *.svclog
75 | *.scc
76 |
77 | # Chutzpah Test files
78 | _Chutzpah*
79 |
80 | # Visual C++ cache files
81 | ipch/
82 | *.aps
83 | *.ncb
84 | *.opendb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 | *.VC.db
89 | *.VC.VC.opendb
90 |
91 | # Visual Studio profiler
92 | *.psess
93 | *.vsp
94 | *.vspx
95 | *.sap
96 |
97 | # TFS 2012 Local Workspace
98 | $tf/
99 |
100 | # Guidance Automation Toolkit
101 | *.gpState
102 |
103 | # ReSharper is a .NET coding add-in
104 | _ReSharper*/
105 | *.[Rr]e[Ss]harper
106 | *.DotSettings.user
107 |
108 | # JustCode is a .NET coding add-in
109 | .JustCode
110 |
111 | # TeamCity is a build add-in
112 | _TeamCity*
113 |
114 | # DotCover is a Code Coverage Tool
115 | *.dotCover
116 |
117 | # Visual Studio code coverage results
118 | *.coverage
119 | *.coveragexml
120 |
121 | # NCrunch
122 | _NCrunch_*
123 | .*crunch*.local.xml
124 | nCrunchTemp_*
125 |
126 | # MightyMoose
127 | *.mm.*
128 | AutoTest.Net/
129 |
130 | # Web workbench (sass)
131 | .sass-cache/
132 |
133 | # Installshield output folder
134 | [Ee]xpress/
135 |
136 | # DocProject is a documentation generator add-in
137 | DocProject/buildhelp/
138 | DocProject/Help/*.HxT
139 | DocProject/Help/*.HxC
140 | DocProject/Help/*.hhc
141 | DocProject/Help/*.hhk
142 | DocProject/Help/*.hhp
143 | DocProject/Help/Html2
144 | DocProject/Help/html
145 |
146 | # Click-Once directory
147 | publish/
148 |
149 | # Publish Web Output
150 | *.[Pp]ublish.xml
151 | *.azurePubxml
152 | # TODO: Comment the next line if you want to checkin your web deploy settings
153 | # but database connection strings (with potential passwords) will be unencrypted
154 | *.pubxml
155 | *.publishproj
156 |
157 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
158 | # checkin your Azure Web App publish settings, but sensitive information contained
159 | # in these scripts will be unencrypted
160 | PublishScripts/
161 |
162 | # NuGet Packages
163 | *.nupkg
164 | # The packages folder can be ignored because of Package Restore
165 | **/packages/*
166 | # except build/, which is used as an MSBuild target.
167 | !**/packages/build/
168 | # Uncomment if necessary however generally it will be regenerated when needed
169 | #!**/packages/repositories.config
170 | # NuGet v3's project.json files produces more ignorable files
171 | *.nuget.props
172 | *.nuget.targets
173 |
174 | # Microsoft Azure Build Output
175 | csx/
176 | *.build.csdef
177 |
178 | # Microsoft Azure Emulator
179 | ecf/
180 | rcf/
181 |
182 | # Windows Store app package directories and files
183 | AppPackages/
184 | BundleArtifacts/
185 | Package.StoreAssociation.xml
186 | _pkginfo.txt
187 |
188 | # Visual Studio cache files
189 | # files ending in .cache can be ignored
190 | *.[Cc]ache
191 | # but keep track of directories ending in .cache
192 | !*.[Cc]ache/
193 |
194 | # Others
195 | ClientBin/
196 | ~$*
197 | *~
198 | *.dbmdl
199 | *.dbproj.schemaview
200 | *.jfm
201 | *.pfx
202 | *.publishsettings
203 | orleans.codegen.cs
204 |
205 | # Since there are multiple workflows, uncomment next line to ignore bower_components
206 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
207 | #bower_components/
208 |
209 | # RIA/Silverlight projects
210 | Generated_Code/
211 |
212 | # Backup & report files from converting an old project file
213 | # to a newer Visual Studio version. Backup files are not needed,
214 | # because we have git ;-)
215 | _UpgradeReport_Files/
216 | Backup*/
217 | UpgradeLog*.XML
218 | UpgradeLog*.htm
219 |
220 | # SQL Server files
221 | *.mdf
222 | *.ldf
223 | *.ndf
224 |
225 | # Business Intelligence projects
226 | *.rdl.data
227 | *.bim.layout
228 | *.bim_*.settings
229 |
230 | # Microsoft Fakes
231 | FakesAssemblies/
232 |
233 | # GhostDoc plugin setting file
234 | *.GhostDoc.xml
235 |
236 | # Node.js Tools for Visual Studio
237 | .ntvs_analysis.dat
238 | node_modules/
239 |
240 | # Typescript v1 declaration files
241 | typings/
242 |
243 | # Visual Studio 6 build log
244 | *.plg
245 |
246 | # Visual Studio 6 workspace options file
247 | *.opt
248 |
249 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
250 | *.vbw
251 |
252 | # Visual Studio LightSwitch build output
253 | **/*.HTMLClient/GeneratedArtifacts
254 | **/*.DesktopClient/GeneratedArtifacts
255 | **/*.DesktopClient/ModelManifest.xml
256 | **/*.Server/GeneratedArtifacts
257 | **/*.Server/ModelManifest.xml
258 | _Pvt_Extensions
259 |
260 | # Paket dependency manager
261 | .paket/paket.exe
262 | paket-files/
263 |
264 | # FAKE - F# Make
265 | .fake/
266 |
267 | # JetBrains Rider
268 | .idea/
269 | *.sln.iml
270 |
271 | # CodeRush
272 | .cr/
273 |
274 | # Python Tools for Visual Studio (PTVS)
275 | __pycache__/
276 | *.pyc
277 |
278 | # Cake - Uncomment if you are using it
279 | # tools/**
280 | # !tools/packages.config
281 |
282 | # Telerik's JustMock configuration file
283 | *.jmconfig
284 |
285 | # BizTalk build output
286 | *.btp.cs
287 | *.btm.cs
288 | *.odx.cs
289 | *.xsd.cs
290 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 | $(MSBuildThisFileDirectory.TrimEnd('\\'))
12 | Enable
13 |
14 |
15 | true
16 | true
17 |
18 |
19 | true
20 | true
21 | Recommended
22 |
23 |
24 | true
25 |
26 |
27 | Enable
28 |
29 | Latest
30 |
31 |
32 | embedded
33 |
34 |
38 | false
39 |
40 |
41 |
42 |
43 | David Federman
44 | © David Federman. All rights reserved.
45 | Easily identify which dependencies can be removed from an MSBuild project.
46 | https://github.com/dfederm/ReferenceTrimmer
47 | https://github.com/dfederm/ReferenceTrimmer.git
48 | MIT
49 |
50 |
51 |
52 |
53 | true
54 | true
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 David Federman
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ReferenceTrimmer
2 | [](https://www.nuget.org/packages/ReferenceTrimmer)
3 | [](https://www.nuget.org/packages/ReferenceTrimmer)
4 |
5 | Easily identify which C# dependencies can be removed from an MSBuild project, and expose MSVC output to show unused libraries and delay-load DLLs at link time. Removing project dependencies flattens your build dependency graph which can improve build parallelism and reduce end-to-end build time.
6 |
7 | ## Rules
8 | The following warnings are generated by this package:
9 |
10 | | Id | Description |
11 | |--------|-------------|
12 | | RT0000 | Enable documentation generation for accuracy of used references detection |
13 | | RT0001 | Unnecessary reference |
14 | | RT0002 | Unnecessary project reference |
15 | | RT0003 | Unnecessary package reference |
16 |
17 | ## How to use
18 | Add a package reference to the [ReferenceTrimmer](https://www.nuget.org/packages/ReferenceTrimmer) package in your projects, or as a common package reference in the repo's [`Directory.Packages.props`](./Directory.Build.props).
19 |
20 | If you're using [Central Package Management](https://learn.microsoft.com/en-us/nuget/consume-packages/Central-Package-Management), you can use it as a `GlobalPackageReference` in your `Directory.Packages.props` to apply it to the entire repo.
21 |
22 | ```xml
23 |
24 |
25 |
26 | ```
27 |
28 | ### C#
29 | You'll need to enable C# documentation XML generation to ensure good analysis results. If your repo is not already using docxml globally, this can introduce a large number of errors and warnings specific to docxml. Additionally, turning on docxml adds additional output I/O that can slow down large repos.
30 |
31 | You can turn off specific docxml related warnings and errors while defaulting ReferenceTrimmer to off using a block of code like this in your `Directory.Build.props`. Turn on the ReferenceTrimmer build by setting `/p:EnableReferenceTrimmer=true` on the MSBuild command line or setting the same property value as an environment variable. You could create a separate build pipeline for your repo to run ReferenceTrimmer builds.
32 |
33 | ```xml
34 |
35 |
36 | false
37 |
38 |
39 |
40 | true
41 |
42 |
51 | $(NoWarn);419;1570;1573;1574;1584;1591;SA1602
52 |
53 | ```
54 |
55 | Note: To get better results, enable the [`IDE0005`](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005) unnecessary `using` rule. This avoids the C# compiler seeing a false positive assembly usage from unneeded `using` directives causing it to miss a removable dependency. See also the note for why IDE0005 code analysis rule requires `` property to be enabled. Documentation generation is also required for accuracy of used references detection (based on https://github.com/dotnet/roslyn/issues/66188).
56 |
57 | ### C++ (.vcxproj projects)
58 | ReferenceTrimmer for C++ is an MSBuild [distributed logger](https://learn.microsoft.com/en-us/visualstudio/msbuild/logging-in-a-multi-processor-environment?view=vs-2022). It writes guidance to the MSBuild stdout stream (not to the MSBuild internal logger at this time) and writes `ReferenceTrimmerUnusedMSVCLibraries.json.log` to the build working directory.
59 |
60 | The distributed logger requires configuration at the MSBuild command line using the `-distributedlogger` parameter. See the [BuildWithReferenceTrimmer example script](./examples/BuildWithReferenceTrimmer.cmd) for how to orchestrate pulling and using the package's loggers.
61 |
62 | Use `msbuild -restore` or `msbuild /t:Restore` instead of `dotnet restore` to ensure .vcxproj restore will work to add the ReferenceTrimmer props and targets to your build. *NOTE*: If you are seeing a `Sequence contains no elements` exception from MSBuild, see https://github.com/dotnet/NuGet.BuildTasks/issues/154 for a workaround or status on a fix.
63 |
64 | The current implementation turns on MSVC `link.exe` flags `/VERBOSE:UNUSEDLIBS` and `/VERBOSE:UNUSEDDELAYLOAD`. These flags tell the linker to print out unused .lib files and delay-load DLLs to stdout. This will include .lib files containing code bundles as well as import libraries for DLLs. Removing these libraries reduces I/O and memory usage by the linker. Here's an example of the linker output:
65 |
66 | ```text
67 | Unused libraries:
68 | C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\um\x64\gdi32.lib
69 | C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\um\x64\winspool.lib
70 | C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\um\x64\comdlg32.lib
71 | ```
72 |
73 | ReferenceTrimmer reads this output and splits the resulting libraries into two sets:
74 |
75 | #### Windows SDK import libraries
76 | The Microsoft C++ SDK for MSBuild includes in the `AdditionalDependencies` property a default list of Win32 import libraries like kernel32.lib and user32.lib. You can find the default list in your local VS installation by searching:
77 |
78 | ```cmd
79 | findstr /s CoreLibraryDependencies "\Program Files"\*props
80 | ```
81 |
82 | To disable these, modify the vcxproj `` property to just the list of SDK .lib files needed for the project, and do not add `%(AdditionalDependencies)` to the property to avoid the default list. Example:
83 |
84 | ```xml
85 |
86 |
87 | kernel32.lib;shlwapi.lib;ws2_32.lib
88 |
89 |
90 | ```
91 |
92 | Not all SDK .lib files can be removed this way. You might need to use `` as well:
93 |
94 | ```xml
95 |
96 |
97 | OLDNAMES.lib;%(IgnoreSpecificDefaultLibraries)
98 |
99 |
100 | ```
101 |
102 | #### Package or Project libraries
103 | If you find an unused .lib that is created by a .vcxproj in your repo, you should be able to remove the `ProjectReference` to that vcxproj to improve your build dependency graph and allow greater parallelism during build.
104 |
105 | If you find an unused .lib that is from a package, remove the reference to that .lib from your project to speed up linking.
106 |
107 | ## Disabling a rule on a reference
108 | To turn off a rule on a specific project or package reference, add the relevant RTxxxx code to a NoWarn metadata attribute. For example:
109 |
110 | ```xml
111 |
112 | ```
113 |
114 | ## Configuration
115 | `$(EnableReferenceTrimmer)` - Controls whether the build logic should run for a given project. Defaults to `true`.
116 |
117 | `$(ReferenceTrimmerEnableVcxproj)` - Controls whether MSVC link flags are set up to print out unused libraries and delay-load DLLs. Defaults to `true`.
118 |
119 | ## How does it work?
120 |
121 | ### C#
122 | There are two main pieces to C# support. First there is an MSBuild task which collects all references passed to the compiler. There is also a Roslyn Analyzer which uses the [`GetUsedAssemblyReferences`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.compilation.getusedassemblyreferences) analyzer API which is available starting with Roslyn compiler that shipped with Visual Studio 2019 version 16.10, .NET 5. (see https://github.com/dotnet/roslyn/blob/main/docs/wiki/NuGet-packages.md#versioning). This is the compiler telling us exactly what references were needed as part of compilation. The analyzer then compares the set of references the Task gathered with the references the compiler says were used.
123 |
124 | ### C++ (.vcxproj projects)
125 | ReferenceTrimmer enables the MSVC `link.exe` flags noted above, then parses output coming from the `Link` MSBuild task. It categorizes the outputs and emits them into the MSBuild console output and the JSON output file noted above. It does not issue MSBuild warnings at this time.
126 |
127 | ## Future development
128 | The outcome of https://github.com/dotnet/sdk/issues/10414 may be of use for `ReferenceTrimmer` future updates.
129 |
--------------------------------------------------------------------------------
/ReferenceTrimmer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31903.59
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8ED5F7AF-CA4B-4D0E-B5C0-5AF98E065315}"
7 | ProjectSection(SolutionItems) = preProject
8 | .editorconfig = .editorconfig
9 | .gitignore = .gitignore
10 | Directory.Build.props = Directory.Build.props
11 | Directory.Build.rsp = Directory.Build.rsp
12 | global.json = global.json
13 | LICENSE = LICENSE
14 | NuGet.Config = NuGet.Config
15 | README.md = README.md
16 | version.json = version.json
17 | EndProjectSection
18 | EndProject
19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{49A2BF83-6DB4-4DB9-9B49-4237731A6627}"
20 | EndProject
21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReferenceTrimmer.Tasks", "src\Tasks\ReferenceTrimmer.Tasks.csproj", "{70B8B49A-03B2-48DE-ACB4-C801F1201C1E}"
22 | EndProject
23 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReferenceTrimmer.Analyzer", "src\Analyzer\ReferenceTrimmer.Analyzer.csproj", "{6E7F5033-F180-4A47-9552-96C3DC3FDA06}"
24 | EndProject
25 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReferenceTrimmer.Tests", "src\Tests\ReferenceTrimmer.Tests.csproj", "{3099F4D8-0CFA-4819-A6A7-2BDFED107FFA}"
26 | EndProject
27 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReferenceTrimmer.Package", "src\Package\ReferenceTrimmer.Package.csproj", "{4C15C9AF-25D5-4725-BFB9-5C04533420AB}"
28 | EndProject
29 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReferenceTrimmer.Loggers", "src\Loggers\ReferenceTrimmer.Loggers.csproj", "{CE532C1F-579C-402C-A408-51713A54E879}"
30 | EndProject
31 | Global
32 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
33 | Debug|Any CPU = Debug|Any CPU
34 | Debug|x64 = Debug|x64
35 | Release|Any CPU = Release|Any CPU
36 | Release|x64 = Release|x64
37 | EndGlobalSection
38 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
39 | {70B8B49A-03B2-48DE-ACB4-C801F1201C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 | {70B8B49A-03B2-48DE-ACB4-C801F1201C1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 | {70B8B49A-03B2-48DE-ACB4-C801F1201C1E}.Debug|x64.ActiveCfg = Debug|Any CPU
42 | {70B8B49A-03B2-48DE-ACB4-C801F1201C1E}.Debug|x64.Build.0 = Debug|Any CPU
43 | {70B8B49A-03B2-48DE-ACB4-C801F1201C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
44 | {70B8B49A-03B2-48DE-ACB4-C801F1201C1E}.Release|Any CPU.Build.0 = Release|Any CPU
45 | {70B8B49A-03B2-48DE-ACB4-C801F1201C1E}.Release|x64.ActiveCfg = Release|Any CPU
46 | {70B8B49A-03B2-48DE-ACB4-C801F1201C1E}.Release|x64.Build.0 = Release|Any CPU
47 | {6E7F5033-F180-4A47-9552-96C3DC3FDA06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
48 | {6E7F5033-F180-4A47-9552-96C3DC3FDA06}.Debug|Any CPU.Build.0 = Debug|Any CPU
49 | {6E7F5033-F180-4A47-9552-96C3DC3FDA06}.Debug|x64.ActiveCfg = Debug|Any CPU
50 | {6E7F5033-F180-4A47-9552-96C3DC3FDA06}.Debug|x64.Build.0 = Debug|Any CPU
51 | {6E7F5033-F180-4A47-9552-96C3DC3FDA06}.Release|Any CPU.ActiveCfg = Release|Any CPU
52 | {6E7F5033-F180-4A47-9552-96C3DC3FDA06}.Release|Any CPU.Build.0 = Release|Any CPU
53 | {6E7F5033-F180-4A47-9552-96C3DC3FDA06}.Release|x64.ActiveCfg = Release|Any CPU
54 | {6E7F5033-F180-4A47-9552-96C3DC3FDA06}.Release|x64.Build.0 = Release|Any CPU
55 | {3099F4D8-0CFA-4819-A6A7-2BDFED107FFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
56 | {3099F4D8-0CFA-4819-A6A7-2BDFED107FFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
57 | {3099F4D8-0CFA-4819-A6A7-2BDFED107FFA}.Debug|x64.ActiveCfg = Debug|x64
58 | {3099F4D8-0CFA-4819-A6A7-2BDFED107FFA}.Debug|x64.Build.0 = Debug|x64
59 | {3099F4D8-0CFA-4819-A6A7-2BDFED107FFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 | {3099F4D8-0CFA-4819-A6A7-2BDFED107FFA}.Release|Any CPU.Build.0 = Release|Any CPU
61 | {3099F4D8-0CFA-4819-A6A7-2BDFED107FFA}.Release|x64.ActiveCfg = Release|x64
62 | {3099F4D8-0CFA-4819-A6A7-2BDFED107FFA}.Release|x64.Build.0 = Release|x64
63 | {4C15C9AF-25D5-4725-BFB9-5C04533420AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
64 | {4C15C9AF-25D5-4725-BFB9-5C04533420AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
65 | {4C15C9AF-25D5-4725-BFB9-5C04533420AB}.Debug|x64.ActiveCfg = Debug|Any CPU
66 | {4C15C9AF-25D5-4725-BFB9-5C04533420AB}.Debug|x64.Build.0 = Debug|Any CPU
67 | {4C15C9AF-25D5-4725-BFB9-5C04533420AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
68 | {4C15C9AF-25D5-4725-BFB9-5C04533420AB}.Release|Any CPU.Build.0 = Release|Any CPU
69 | {4C15C9AF-25D5-4725-BFB9-5C04533420AB}.Release|x64.ActiveCfg = Release|Any CPU
70 | {4C15C9AF-25D5-4725-BFB9-5C04533420AB}.Release|x64.Build.0 = Release|Any CPU
71 | {CE532C1F-579C-402C-A408-51713A54E879}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
72 | {CE532C1F-579C-402C-A408-51713A54E879}.Debug|Any CPU.Build.0 = Debug|Any CPU
73 | {CE532C1F-579C-402C-A408-51713A54E879}.Debug|x64.ActiveCfg = Debug|Any CPU
74 | {CE532C1F-579C-402C-A408-51713A54E879}.Debug|x64.Build.0 = Debug|Any CPU
75 | {CE532C1F-579C-402C-A408-51713A54E879}.Release|Any CPU.ActiveCfg = Release|Any CPU
76 | {CE532C1F-579C-402C-A408-51713A54E879}.Release|Any CPU.Build.0 = Release|Any CPU
77 | {CE532C1F-579C-402C-A408-51713A54E879}.Release|x64.ActiveCfg = Release|Any CPU
78 | {CE532C1F-579C-402C-A408-51713A54E879}.Release|x64.Build.0 = Release|Any CPU
79 | EndGlobalSection
80 | GlobalSection(SolutionProperties) = preSolution
81 | HideSolutionNode = FALSE
82 | EndGlobalSection
83 | GlobalSection(NestedProjects) = preSolution
84 | {70B8B49A-03B2-48DE-ACB4-C801F1201C1E} = {49A2BF83-6DB4-4DB9-9B49-4237731A6627}
85 | {6E7F5033-F180-4A47-9552-96C3DC3FDA06} = {49A2BF83-6DB4-4DB9-9B49-4237731A6627}
86 | {3099F4D8-0CFA-4819-A6A7-2BDFED107FFA} = {49A2BF83-6DB4-4DB9-9B49-4237731A6627}
87 | {4C15C9AF-25D5-4725-BFB9-5C04533420AB} = {49A2BF83-6DB4-4DB9-9B49-4237731A6627}
88 | {CE532C1F-579C-402C-A408-51713A54E879} = {49A2BF83-6DB4-4DB9-9B49-4237731A6627}
89 | EndGlobalSection
90 | GlobalSection(ExtensibilityGlobals) = postSolution
91 | SolutionGuid = {1E4FD4B2-8674-4378-AAC7-9C14865D333A}
92 | EndGlobalSection
93 | EndGlobal
94 |
--------------------------------------------------------------------------------
/examples/BuildWithReferenceTrimmer.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | @rem Builds with ReferenceTrimmer C# and C++ modes
3 | @rem Assumes RefTrim is wired into Directory.Build.props or Directory.Packages.props as a global package reference.
4 | @rem Usage: BuildWithReferenceTrimmer [msbuild args]
5 | setlocal EnableDelayedExpansion
6 |
7 | @rem Explicitly turn on in case the repo is defaulting to false.
8 | set EnableReferenceTrimmer=true
9 |
10 | @echo Restoring with ReferenceTrimmer enabled
11 | call msbuild /t:Restore
12 |
13 | @rem Find the RefTrim latest package in the package store.
14 | set NuGetPkgBase=%NUGET_PACKAGES%
15 | if "%NuGetPkgBase%"=="" set NuGetPkgBase=%USERPROFILE%\.nuget\packages
16 | set RefTrimPkgBase=%NuGetPkgBase%\ReferenceTrimmer
17 | for /d %%d in (%RefTrimPkgBase%\*) do set RefTrimPkg=%%d
18 | set MSBuildLoggerParam=-distributedlogger:CentralLogger,%RefTrimPkg%\build\ReferenceTrimmer.Loggers.dll*ForwardingLogger,%RefTrimPkg%\build\ReferenceTrimmer.Loggers.dll
19 |
20 | @echo Building with ReferenceTrimmer C# and C++ logger.
21 | set cmd=msbuild %MSBuildLoggerParam% %*
22 | echo %cmd%
23 | call %cmd%
24 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "msbuild-sdks": {
3 | "Microsoft.Build.NoTargets": "3.7.56",
4 | "MSTest.Sdk": "3.6.0"
5 | }
6 | }
--------------------------------------------------------------------------------
/src/Analyzer/ReferenceTrimmer.Analyzer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | false
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Analyzer/ReferenceTrimmerAnalyzer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using Microsoft.CodeAnalysis;
3 | using Microsoft.CodeAnalysis.Diagnostics;
4 | using ReferenceTrimmer.Shared;
5 |
6 | namespace ReferenceTrimmer.Analyzer;
7 |
8 | [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
9 | public class ReferenceTrimmerAnalyzer : DiagnosticAnalyzer
10 | {
11 | private const string DeclaredReferencesFileName = "_ReferenceTrimmer_DeclaredReferences.tsv";
12 | private const string UsedReferencesFileName = "_ReferenceTrimmer_UsedReferences.log";
13 | private const string UnusedReferencesFileName = "_ReferenceTrimmer_UnusedReferences.log";
14 |
15 | private static readonly DiagnosticDescriptor RT0000Descriptor = new(
16 | "RT0000",
17 | "Enable documentation generation for accuracy of used references detection",
18 | "Enable /doc parameter or in MSBuild set true for accuracy of used references detection",
19 | "ReferenceTrimmer",
20 | DiagnosticSeverity.Warning,
21 | isEnabledByDefault: true);
22 |
23 | private static readonly DiagnosticDescriptor RT0001Descriptor = new(
24 | "RT0001",
25 | "Unnecessary reference",
26 | "Reference {0} can be removed",
27 | "ReferenceTrimmer",
28 | DiagnosticSeverity.Warning,
29 | isEnabledByDefault: true);
30 |
31 | private static readonly DiagnosticDescriptor RT0002Descriptor = new(
32 | "RT0002",
33 | "Unnecessary project reference",
34 | "ProjectReference {0} can be removed",
35 | "ReferenceTrimmer",
36 | DiagnosticSeverity.Warning,
37 | isEnabledByDefault: true);
38 |
39 | private static readonly DiagnosticDescriptor RT0003Descriptor = new(
40 | "RT0003",
41 | "Unnecessary package reference",
42 | "PackageReference {0} can be removed",
43 | "ReferenceTrimmer",
44 | DiagnosticSeverity.Warning,
45 | isEnabledByDefault: true);
46 |
47 | ///
48 | /// The supported diagnostics.
49 | ///
50 | public override ImmutableArray SupportedDiagnostics
51 | => ImmutableArray.Create(
52 | RT0000Descriptor,
53 | RT0001Descriptor,
54 | RT0002Descriptor,
55 | RT0003Descriptor);
56 |
57 | ///
58 | public override void Initialize(AnalysisContext context)
59 | {
60 | context.EnableConcurrentExecution();
61 | context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
62 | context.RegisterCompilationAction(DumpUsedReferences);
63 | }
64 |
65 | private static void DumpUsedReferences(CompilationAnalysisContext context)
66 | {
67 | string? declaredReferencesPath = GetDeclaredReferencesPath(context);
68 | if (declaredReferencesPath == null)
69 | {
70 | // Reference Trimmer is disabled
71 | return;
72 | }
73 |
74 | DeclaredReferences declaredReferences = DeclaredReferences.ReadFromFile(declaredReferencesPath);
75 | Compilation compilation = context.Compilation;
76 | if (compilation.SyntaxTrees.FirstOrDefault()?.Options.DocumentationMode == DocumentationMode.None)
77 | {
78 | context.ReportDiagnostic(Diagnostic.Create(RT0000Descriptor, Location.None));
79 | }
80 |
81 | if (!compilation.Options.Errors.IsEmpty)
82 | {
83 | return;
84 | }
85 |
86 | HashSet usedReferences = new(StringComparer.OrdinalIgnoreCase);
87 | foreach (MetadataReference metadataReference in compilation.GetUsedAssemblyReferences())
88 | {
89 | if (metadataReference.Display != null)
90 | {
91 | usedReferences.Add(metadataReference.Display);
92 | }
93 | }
94 |
95 | var globalOptions = context.Options.AnalyzerConfigOptionsProvider.GlobalOptions;
96 | if (globalOptions.TryGetValue("build_property.EnableReferenceTrimmerDiagnostics", out string? enableDiagnostics)
97 | && string.Equals(enableDiagnostics, "true", StringComparison.OrdinalIgnoreCase))
98 | {
99 | HashSet unusedReferences = new(StringComparer.OrdinalIgnoreCase);
100 | foreach (MetadataReference metadataReference in compilation.References)
101 | {
102 | if (metadataReference.Display != null && !usedReferences.Contains(metadataReference.Display))
103 | {
104 | unusedReferences.Add(metadataReference.Display);
105 | }
106 | }
107 |
108 | DumpReferencesInfo(usedReferences, unusedReferences, declaredReferencesPath);
109 | }
110 |
111 | Dictionary> packageAssembliesDict = new(StringComparer.OrdinalIgnoreCase);
112 | foreach (DeclaredReference declaredReference in declaredReferences.References)
113 | {
114 | switch (declaredReference.Kind)
115 | {
116 | case DeclaredReferenceKind.Reference:
117 | {
118 | if (!usedReferences.Contains(declaredReference.AssemblyPath))
119 | {
120 | context.ReportDiagnostic(Diagnostic.Create(RT0001Descriptor, Location.None, declaredReference.Spec));
121 | }
122 |
123 | break;
124 | }
125 | case DeclaredReferenceKind.ProjectReference:
126 | {
127 | if (!usedReferences.Contains(declaredReference.AssemblyPath))
128 | {
129 | context.ReportDiagnostic(Diagnostic.Create(RT0002Descriptor, Location.None, declaredReference.Spec));
130 | }
131 |
132 | break;
133 | }
134 | case DeclaredReferenceKind.PackageReference:
135 | {
136 | if (!packageAssembliesDict.TryGetValue(declaredReference.Spec, out List packageAssemblies))
137 | {
138 | packageAssemblies = new List();
139 | packageAssembliesDict.Add(declaredReference.Spec, packageAssemblies);
140 | }
141 |
142 | packageAssemblies.Add(declaredReference.AssemblyPath);
143 | break;
144 | }
145 | }
146 | }
147 |
148 | // Do a second pass for package assemblies since if any assembly in the package is used, the package is used.
149 | foreach (KeyValuePair> kvp in packageAssembliesDict)
150 | {
151 | string packageName = kvp.Key;
152 | List packageAssemblies = kvp.Value;
153 | if (!packageAssemblies.Any(usedReferences.Contains))
154 | {
155 | context.ReportDiagnostic(Diagnostic.Create(RT0003Descriptor, Location.None, packageName));
156 | }
157 | }
158 | }
159 |
160 | private static void DumpReferencesInfo(HashSet usedReferences, HashSet unusedReferences, string declaredReferencesPath)
161 | {
162 | string dir = Path.GetDirectoryName(declaredReferencesPath);
163 | string filePath = Path.Combine(dir, UsedReferencesFileName);
164 | string text = string.Join(Environment.NewLine, usedReferences.OrderBy(s => s));
165 | WriteFile(filePath, text);
166 | filePath = Path.Combine(dir, UnusedReferencesFileName);
167 | text = string.Join(Environment.NewLine, unusedReferences.OrderBy(s => s));
168 | WriteFile(filePath, text);
169 | }
170 |
171 | private static void WriteFile(string filePath, string text)
172 | {
173 | try
174 | {
175 | if (File.Exists(filePath))
176 | {
177 | string oldText = File.ReadAllText(filePath);
178 | if (string.Equals(text, oldText, StringComparison.OrdinalIgnoreCase))
179 | {
180 | return;
181 | }
182 | }
183 |
184 | File.WriteAllText(filePath, text);
185 | }
186 | catch
187 | {
188 | }
189 | }
190 |
191 | private static string? GetDeclaredReferencesPath(CompilationAnalysisContext context)
192 | {
193 | foreach (AdditionalText additionalText in context.Options.AdditionalFiles)
194 | {
195 | if (Path.GetFileName(additionalText.Path).Equals(DeclaredReferencesFileName, StringComparison.Ordinal))
196 | {
197 | return additionalText.Path;
198 | }
199 | }
200 |
201 | return null;
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/src/Loggers/MSVC/CentralLogger.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Build.Framework;
2 | using Microsoft.Build.Utilities;
3 |
4 | namespace ReferenceTrimmer.Loggers.MSVC;
5 |
6 | ///
7 | /// Central logger instance run in the main MSBuild process.
8 | ///
9 | public sealed class CentralLogger : Logger
10 | {
11 | private readonly object _jsonLogWriteLock = new();
12 | private Lazy? _lazyJsonLogFileStreamWriter;
13 | private bool _firstEvent = true;
14 | private string? _jsonLogFilePath;
15 |
16 | internal const string JsonLogFileName = ForwardingLogger.HelpKeyword + ".json.log";
17 |
18 | ///
19 | public override void Initialize(IEventSource eventSource)
20 | {
21 | _jsonLogFilePath = Path.Combine(Directory.GetCurrentDirectory(), JsonLogFileName);
22 | if (File.Exists(_jsonLogFilePath))
23 | {
24 | File.Delete(_jsonLogFilePath);
25 | }
26 |
27 | _lazyJsonLogFileStreamWriter = new Lazy(() =>
28 | {
29 | try
30 | {
31 | var writer = new StreamWriter(_jsonLogFilePath);
32 |
33 | // Begin JSON array as text.
34 | writer.WriteLine("[");
35 |
36 | return writer;
37 | }
38 | catch (Exception ex)
39 | {
40 | throw new LoggerException($"Failed to create JSON log file for ReferenceTrimmer for MSVC: {ex.Message}");
41 | }
42 | });
43 |
44 | eventSource.CustomEventRaised += CustomEventHandler;
45 | }
46 |
47 | ///
48 | public override void Shutdown()
49 | {
50 | lock (_jsonLogWriteLock)
51 | {
52 | if (_lazyJsonLogFileStreamWriter is not null && _lazyJsonLogFileStreamWriter.IsValueCreated)
53 | {
54 | _lazyJsonLogFileStreamWriter.Value.WriteLine();
55 | _lazyJsonLogFileStreamWriter.Value.WriteLine("]");
56 | _lazyJsonLogFileStreamWriter.Value.Dispose();
57 | }
58 | }
59 | }
60 |
61 | private void CustomEventHandler(object sender, CustomBuildEventArgs e)
62 | {
63 | if (e is not UnusedLibsCustomBuildEventArgs unusedLibsEvent || unusedLibsEvent.UnusedLibraryPathsJson.Length == 0)
64 | {
65 | return;
66 | }
67 |
68 | Console.WriteLine(unusedLibsEvent.Message + Environment.NewLine + $" * JSON version of this information added to {_jsonLogFilePath}");
69 |
70 | lock (_jsonLogWriteLock)
71 | {
72 | StreamWriter sw = _lazyJsonLogFileStreamWriter!.Value;
73 | if (_firstEvent)
74 | {
75 | _firstEvent = false;
76 | }
77 | else
78 | {
79 | // Separate JSON objects with a comma.
80 | sw.WriteLine(',');
81 | }
82 |
83 | sw.Write(unusedLibsEvent.UnusedLibraryPathsJson);
84 | sw.Flush();
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Loggers/MSVC/ForwardingLogger.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Concurrent;
2 | using System.Text;
3 | using Microsoft.Build.Framework;
4 |
5 | namespace ReferenceTrimmer.Loggers.MSVC;
6 |
7 | ///
8 | /// Forwarding logger that runs in each MSBuild worker node outside of the primary node.
9 | ///
10 | public sealed class ForwardingLogger : IForwardingLogger
11 | {
12 | private const string LinkTaskName = "Link";
13 |
14 | // Default library list in $(CoreLibraryDependencies) used as a default list for $(AdditionalDependencies)
15 | // in the MSVC MSBuild SDK. To update with current lib list:
16 | // findstr /s CoreLibraryDependencies "\Program Files"\*props
17 | // Ignores WindowsApp.lib for the WindowsAppContainer case.
18 | private static readonly HashSet DefaultWin32DllImportLibraries = new(StringComparer.OrdinalIgnoreCase)
19 | {
20 | "advapi32.lib",
21 | "comdlg32.lib",
22 | "gdi32.lib",
23 | "kernel32.lib",
24 | "odbc32.lib",
25 | "odbccp32.lib",
26 | "ole32.lib",
27 | "oleaut32.lib",
28 | "shell32.lib",
29 | "user32.lib",
30 | "uuid.lib",
31 | "winspool.lib",
32 | };
33 |
34 | private enum State
35 | {
36 | LinkStarted,
37 | UnusedLibsStarted,
38 | UnusedLibsEnded,
39 | }
40 |
41 | private enum LibType
42 | {
43 | DefaultImportLib,
44 | PackageOrDependencyLib,
45 | }
46 |
47 | private sealed class ProjectStateLibs
48 | {
49 | public State ProjectState { get; set; }
50 | public SortedSet UnusedProjectLibPaths { get; } = new(StringComparer.OrdinalIgnoreCase);
51 | }
52 |
53 | private IEventSource? _eventSource;
54 | private readonly ConcurrentDictionary _projects = new(StringComparer.OrdinalIgnoreCase);
55 |
56 | public const string HelpKeyword = "ReferenceTrimmerUnusedMSVCLibraries";
57 |
58 | ///
59 | /// Gets or sets the level of detail to show in the event log.
60 | ///
61 | public LoggerVerbosity Verbosity { get; set; }
62 |
63 | ///
64 | /// The logger takes a single parameter to suppress the output of the errors
65 | /// and warnings summary at the end of a build.
66 | ///
67 | public string? Parameters { get; set; }
68 |
69 | ///
70 | /// This property is set by the build engine to allow node loggers to forward messages to the
71 | /// central logger.
72 | ///
73 | public IEventRedirector? BuildEventRedirector { get; set; }
74 |
75 | ///
76 | /// The identifier of the node.
77 | ///
78 | public int NodeId { get; set; }
79 |
80 | ///
81 | /// Signs up the logger for all build events.
82 | ///
83 | public void Initialize(IEventSource eventSource, int nodeCount)
84 | {
85 | Initialize(eventSource);
86 | }
87 |
88 | ///
89 | /// Signs up the logger for all build events.
90 | ///
91 | public void Initialize(IEventSource eventSource)
92 | {
93 | _eventSource = eventSource;
94 |
95 | eventSource.TaskStarted += OnTaskStarted;
96 | eventSource.TaskFinished += OnTaskFinished;
97 | eventSource.MessageRaised += OnMessageRaised;
98 | }
99 |
100 | ///
101 | /// Called when Engine is done with this logger
102 | ///
103 | public void Shutdown()
104 | {
105 | if (_eventSource is null)
106 | {
107 | return;
108 | }
109 |
110 | _eventSource.TaskStarted -= OnTaskStarted;
111 | _eventSource.TaskFinished -= OnTaskFinished;
112 | _eventSource.MessageRaised -= OnMessageRaised;
113 | }
114 |
115 | private void OnTaskStarted(object sender, TaskStartedEventArgs e)
116 | {
117 | if (!string.IsNullOrEmpty(e.ProjectFile) && e.TaskName.Equals(LinkTaskName, StringComparison.OrdinalIgnoreCase))
118 | {
119 | _projects[e.ProjectFile] = new ProjectStateLibs { ProjectState = State.LinkStarted };
120 | }
121 | }
122 |
123 | private void OnTaskFinished(object sender, TaskFinishedEventArgs e)
124 | {
125 | if (string.IsNullOrEmpty(e.ProjectFile) || e.TaskName != LinkTaskName || !e.Succeeded)
126 | {
127 | return;
128 | }
129 |
130 | string projectFilePath = e.ProjectFile;
131 |
132 | // Project state present in map if the Link task was detected running in OnTaskStarted.
133 | if (!_projects.TryGetValue(projectFilePath, out ProjectStateLibs projState))
134 | {
135 | return;
136 | }
137 |
138 | if (projState.ProjectState is State.UnusedLibsStarted or State.UnusedLibsEnded &&
139 | projState.UnusedProjectLibPaths.Count > 0)
140 | {
141 | // Hack the output JSON format to avoid importing Newtonsoft or System.Text.Json that could collide with
142 | // versions in the current MSBuild process.
143 | var jsonSb = new StringBuilder(256);
144 | jsonSb.AppendLine(" {");
145 | jsonSb.AppendLine($" \"{EscapeJsonChars(projectFilePath)}\": [");
146 |
147 | // Classify the libraries.
148 | var defaultImportLibraries = new List();
149 | var otherLibraries = new List();
150 | var implicitlyUsedImportLibraries = new HashSet(DefaultWin32DllImportLibraries, StringComparer.OrdinalIgnoreCase);
151 | bool first = true;
152 | foreach (string libPath in projState.UnusedProjectLibPaths)
153 | {
154 | if (first)
155 | {
156 | first = false;
157 | }
158 | else
159 | {
160 | jsonSb.AppendLine(",");
161 | }
162 |
163 | jsonSb.AppendLine(" {")
164 | .AppendLine($" \"LibPath\": \"{EscapeJsonChars(libPath)}\",");
165 |
166 | string libFileName = Path.GetFileName(libPath);
167 | LibType type;
168 | if (DefaultWin32DllImportLibraries.Contains(libFileName))
169 | {
170 | defaultImportLibraries.Add(libPath);
171 | implicitlyUsedImportLibraries.Remove(libFileName);
172 | type = LibType.DefaultImportLib;
173 | }
174 | else
175 | {
176 | otherLibraries.Add(libPath);
177 | type = LibType.PackageOrDependencyLib;
178 | }
179 |
180 | jsonSb.AppendLine($" \"LibType\": \"{type}\"")
181 | .Append(" }");
182 | }
183 |
184 | jsonSb.AppendLine();
185 | jsonSb.AppendLine(" ]");
186 | jsonSb.Append(" }");
187 |
188 | var sb = new StringBuilder($" Unused MSVC libraries detected in project {projectFilePath}:", 256);
189 | sb.AppendLine();
190 |
191 | if (defaultImportLibraries.Count > 0)
192 | {
193 | var implicitlyUsedImportLibrariesSorted = new List(implicitlyUsedImportLibraries);
194 | implicitlyUsedImportLibrariesSorted.Sort(StringComparer.OrdinalIgnoreCase);
195 | sb.Append(" * Default Windows SDK import libraries:");
196 | if (implicitlyUsedImportLibrariesSorted.Count > 0)
197 | {
198 | sb.AppendLine().Append($" - Libraries needed: {string.Join(";", implicitlyUsedImportLibrariesSorted)} (set in $(AdditionalDependencies) without %(AdditionalDependencies))");
199 | }
200 |
201 | sb.AppendLine().Append($" - Unneeded: {string.Join(", ", defaultImportLibraries.Select(Path.GetFileName))} (remove from $(AdditionalDependencies))");
202 | }
203 |
204 | if (otherLibraries.Count > 0)
205 | {
206 | sb.AppendLine().Append(
207 | " * Other libraries - if a lib from a project in this repo, remove the related ProjectReference to improve your build dependency graph; " +
208 | "if a package lib, remove from $(AdditionalDependencies):");
209 | foreach (string lib in otherLibraries)
210 | {
211 | sb.AppendLine().Append($" - {lib}");
212 | }
213 | }
214 |
215 | BuildEventRedirector!.ForwardEvent(
216 | new UnusedLibsCustomBuildEventArgs(
217 | message: sb.ToString(),
218 | projectFilePath,
219 | jsonSb.ToString()));
220 | }
221 |
222 | _projects.TryRemove(projectFilePath, out _);
223 | }
224 |
225 | private static string EscapeJsonChars(string str)
226 | {
227 | return str.Replace("\\", "\\\\").Replace("\"", "\\\"");
228 | }
229 |
230 | private void OnMessageRaised(object sender, BuildMessageEventArgs e)
231 | {
232 | string? projectFilePath = e.ProjectFile;
233 | string? message = e.Message;
234 |
235 | if (string.IsNullOrEmpty(projectFilePath) || message is null)
236 | {
237 | return;
238 | }
239 |
240 | if (!_projects.TryGetValue(projectFilePath, out ProjectStateLibs? projState))
241 | {
242 | return;
243 | }
244 |
245 | // The 'Unused libraries' message is at the tail of Link's stdout.
246 | // Once found, assume the rest of the output is the list of unused libs.
247 | switch (projState.ProjectState)
248 | {
249 | case State.LinkStarted:
250 | if (message!.IndexOf("Unused libraries:", StringComparison.OrdinalIgnoreCase) != -1)
251 | {
252 | projState.ProjectState = State.UnusedLibsStarted;
253 | }
254 | break;
255 |
256 | case State.UnusedLibsStarted:
257 | string lib = message!.Trim();
258 | if (lib.Length > 0)
259 | {
260 | try
261 | {
262 | lib = Path.GetFullPath(lib);
263 | }
264 | finally
265 | {
266 | projState.UnusedProjectLibPaths.Add(lib);
267 | }
268 | }
269 | else
270 | {
271 | projState.ProjectState = State.UnusedLibsEnded;
272 | }
273 | break;
274 |
275 | // Avoid parsing any other text after the usual empty line emitted after the unused libs list.
276 | // Allow to fall through.
277 | case State.UnusedLibsEnded:
278 |
279 | default:
280 | break;
281 | }
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/src/Loggers/MSVC/UnusedLibsCustomBuildEventArgs.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Build.Framework;
2 |
3 | namespace ReferenceTrimmer.Loggers.MSVC;
4 |
5 | ///
6 | /// Passes the unused library information from to
7 | /// . Note that the MSBuild binary logger will serialize this event in its
8 | /// entirety, so to aid complete debugging fully analyzed information is passed here.
9 | ///
10 | [Serializable]
11 | internal sealed class UnusedLibsCustomBuildEventArgs : CustomBuildEventArgs
12 | {
13 | public UnusedLibsCustomBuildEventArgs()
14 | {
15 | ProjectPath = string.Empty;
16 | UnusedLibraryPathsJson = string.Empty;
17 | }
18 |
19 | public UnusedLibsCustomBuildEventArgs(
20 | string message,
21 | string projectPath,
22 | string unusedLibraryPathsJson)
23 | : base(message, ForwardingLogger.HelpKeyword, senderName: projectPath)
24 | {
25 | ProjectPath = projectPath;
26 | UnusedLibraryPathsJson = unusedLibraryPathsJson;
27 | }
28 |
29 | public string ProjectPath { get; set; }
30 | public string UnusedLibraryPathsJson { get; set; }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Loggers/ReferenceTrimmer.Loggers.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Package/ReferenceTrimmer.Package.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | true
5 | true
6 | ReferenceTrimmer
7 | true
8 | true
9 | $(TargetsForTfmSpecificContentInPackage);GetMyPackageFiles
10 | false
11 | $(RepoRoot)\artifacts
12 | README.md
13 |
14 |
15 | true
16 |
17 |
18 |
21 |
24 |
27 |
28 |
29 |
30 | true
31 | build
32 |
33 |
34 | true
35 | buildMultiTargeting
36 |
37 |
38 | true
39 | tools
40 |
41 |
42 | true
43 | \
44 |
45 |
46 |
47 |
48 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/Package/build/ReferenceTrimmer.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildThisFileDirectory)ReferenceTrimmer.Tasks.dll
5 |
6 |
7 |
8 |
9 |
21 | /VERBOSE:UNUSEDLIBS /VERBOSE:UNUSEDDELAYLOAD %(AdditionalOptions)
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Package/build/ReferenceTrimmer.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | $(CoreCompileDependsOn);CollectDeclaredReferences
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | <_ReferenceTrimmerDeclaredReferencesFile>$(IntermediateOutputPath)\_ReferenceTrimmer_DeclaredReferences.tsv
15 | <_ReferenceTrimmerUsedReferencesFile>$(IntermediateOutputPath)\_ReferenceTrimmer_UsedReferences.log
16 | <_ReferenceTrimmerUnusedReferencesFile>$(IntermediateOutputPath)\_ReferenceTrimmer_UnusedReferences.log
17 |
18 |
19 |
23 | <_ReferenceTrimmerReferences Include="@(Reference)" />
24 | <_ReferenceTrimmerReferences Remove="@(_NETStandardLibraryNETFrameworkLib -> '%(FileName)')" />
25 |
26 | <_ReferenceTrimmerResolvedReferences Include="@(ReferencePathWithRefAssemblies)" Condition="'%(ReferencePathWithRefAssemblies.ReferenceSourceTarget)' == 'ResolveAssemblyReference'"/>
27 |
28 | <_ReferenceTrimmerProjectReferences Include="@(ReferencePathWithRefAssemblies)" Condition="'%(ReferencePathWithRefAssemblies.ReferenceSourceTarget)' == 'ProjectReference'" />
29 |
30 |
31 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/Package/buildMultiTargeting/ReferenceTrimmer.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/Package/buildMultiTargeting/ReferenceTrimmer.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/Package/tools/install.ps1:
--------------------------------------------------------------------------------
1 | param($installPath, $toolsPath, $package, $project)
2 |
3 | if($project.Object.SupportsPackageDependencyResolution)
4 | {
5 | if($project.Object.SupportsPackageDependencyResolution())
6 | {
7 | # Do not install analyzers via install.ps1, instead let the project system handle it.
8 | return
9 | }
10 | }
11 |
12 | $analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve
13 |
14 | foreach($analyzersPath in $analyzersPaths)
15 | {
16 | if (Test-Path $analyzersPath)
17 | {
18 | # Install the language agnostic analyzers.
19 | foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll)
20 | {
21 | if($project.Object.AnalyzerReferences)
22 | {
23 | $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName)
24 | }
25 | }
26 | }
27 | }
28 |
29 | # $project.Type gives the language name like (C# or VB.NET)
30 | $languageFolder = ""
31 | if($project.Type -eq "C#")
32 | {
33 | $languageFolder = "cs"
34 | }
35 | if($project.Type -eq "VB.NET")
36 | {
37 | $languageFolder = "vb"
38 | }
39 | if($languageFolder -eq "")
40 | {
41 | return
42 | }
43 |
44 | foreach($analyzersPath in $analyzersPaths)
45 | {
46 | # Install language specific analyzers.
47 | $languageAnalyzersPath = join-path $analyzersPath $languageFolder
48 | if (Test-Path $languageAnalyzersPath)
49 | {
50 | foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll)
51 | {
52 | if($project.Object.AnalyzerReferences)
53 | {
54 | $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName)
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/src/Package/tools/uninstall.ps1:
--------------------------------------------------------------------------------
1 | param($installPath, $toolsPath, $package, $project)
2 |
3 | if($project.Object.SupportsPackageDependencyResolution)
4 | {
5 | if($project.Object.SupportsPackageDependencyResolution())
6 | {
7 | # Do not uninstall analyzers via uninstall.ps1, instead let the project system handle it.
8 | return
9 | }
10 | }
11 |
12 | $analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve
13 |
14 | foreach($analyzersPath in $analyzersPaths)
15 | {
16 | # Uninstall the language agnostic analyzers.
17 | if (Test-Path $analyzersPath)
18 | {
19 | foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll)
20 | {
21 | if($project.Object.AnalyzerReferences)
22 | {
23 | $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName)
24 | }
25 | }
26 | }
27 | }
28 |
29 | # $project.Type gives the language name like (C# or VB.NET)
30 | $languageFolder = ""
31 | if($project.Type -eq "C#")
32 | {
33 | $languageFolder = "cs"
34 | }
35 | if($project.Type -eq "VB.NET")
36 | {
37 | $languageFolder = "vb"
38 | }
39 | if($languageFolder -eq "")
40 | {
41 | return
42 | }
43 |
44 | foreach($analyzersPath in $analyzersPaths)
45 | {
46 | # Uninstall language specific analyzers.
47 | $languageAnalyzersPath = join-path $analyzersPath $languageFolder
48 | if (Test-Path $languageAnalyzersPath)
49 | {
50 | foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll)
51 | {
52 | if($project.Object.AnalyzerReferences)
53 | {
54 | try
55 | {
56 | $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName)
57 | }
58 | catch
59 | {
60 |
61 | }
62 | }
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/src/Shared/DeclaredReferences.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 |
3 | namespace ReferenceTrimmer.Shared;
4 |
5 | internal record DeclaredReferences(IReadOnlyList References)
6 | {
7 | private const char FieldDelimiter = '\t';
8 |
9 | private static readonly char[] FieldDelimiters = new[] { FieldDelimiter };
10 |
11 | private static readonly Dictionary KindEnumToString = new()
12 | {
13 | { DeclaredReferenceKind.Reference, nameof(DeclaredReferenceKind.Reference) },
14 | { DeclaredReferenceKind.ProjectReference, nameof(DeclaredReferenceKind.ProjectReference) },
15 | { DeclaredReferenceKind.PackageReference, nameof(DeclaredReferenceKind.PackageReference) },
16 | };
17 |
18 | private static readonly Dictionary KindStringToEnum = new()
19 | {
20 | { nameof(DeclaredReferenceKind.Reference), DeclaredReferenceKind.Reference },
21 | { nameof(DeclaredReferenceKind.ProjectReference), DeclaredReferenceKind.ProjectReference },
22 | { nameof(DeclaredReferenceKind.PackageReference), DeclaredReferenceKind.PackageReference },
23 | };
24 |
25 | public void SaveToFile(string filePath)
26 | {
27 | StringBuilder writer = new();
28 | foreach (DeclaredReference reference in References)
29 | {
30 | writer.Append(reference.AssemblyPath);
31 | writer.Append(FieldDelimiter);
32 | writer.Append(KindEnumToString[reference.Kind]);
33 | writer.Append(FieldDelimiter);
34 | writer.Append(reference.Spec);
35 | writer.AppendLine();
36 | }
37 |
38 | string newContent = writer.ToString();
39 | if (File.Exists(filePath))
40 | {
41 | string existing = File.ReadAllText(filePath);
42 | if (string.Equals(existing, newContent, StringComparison.OrdinalIgnoreCase))
43 | {
44 | return;
45 | }
46 | }
47 |
48 | File.WriteAllText(filePath, newContent);
49 | }
50 |
51 | public static DeclaredReferences ReadFromFile(string filePath)
52 | {
53 | List references = new();
54 |
55 | using FileStream stream = File.OpenRead(filePath);
56 | using StreamReader reader = new(stream);
57 |
58 | string? line;
59 | while ((line = reader.ReadLine()) != null)
60 | {
61 | string[] parts = line.Split(FieldDelimiters, 3);
62 | if (parts.Length != 3)
63 | {
64 | throw new InvalidDataException($"File '{filePath}' is invalid. Line: {references.Count + 1}");
65 | }
66 |
67 | string assemblyName = parts[0];
68 | DeclaredReferenceKind kind = KindStringToEnum[parts[1]];
69 | string spec = parts[2];
70 | DeclaredReference reference = new(assemblyName, kind, spec);
71 | references.Add(reference);
72 | }
73 |
74 | return new DeclaredReferences(references);
75 | }
76 | }
77 |
78 | internal record DeclaredReference(string AssemblyPath, DeclaredReferenceKind Kind, string Spec);
79 |
80 | internal enum DeclaredReferenceKind { Reference, ProjectReference, PackageReference }
--------------------------------------------------------------------------------
/src/Shared/NetStandardPolyfills.cs:
--------------------------------------------------------------------------------
1 | namespace System.Runtime.CompilerServices;
2 |
3 | internal sealed class IsExternalInit { }
--------------------------------------------------------------------------------
/src/Tasks/CollectDeclaredReferencesTask.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Xml.Linq;
3 | using Microsoft.Build.Framework;
4 | using NuGet.Common;
5 | using NuGet.Frameworks;
6 | using NuGet.ProjectModel;
7 | using ReferenceTrimmer.Shared;
8 | using MSBuildTask = Microsoft.Build.Utilities.Task;
9 |
10 | namespace ReferenceTrimmer.Tasks;
11 |
12 | public sealed class CollectDeclaredReferencesTask : MSBuildTask
13 | {
14 | private static readonly HashSet NugetAssemblies = new(StringComparer.OrdinalIgnoreCase)
15 | {
16 | // Direct dependency
17 | "NuGet.ProjectModel",
18 |
19 | // Indirect dependencies
20 | "NuGet.Common",
21 | "NuGet.Frameworks",
22 | "NuGet.Packaging",
23 | "NuGet.Versioning",
24 | };
25 |
26 | private const string NoWarn = "NoWarn";
27 | private const string TreatAsUsed = "TreatAsUsed";
28 |
29 | [Required]
30 | public string? OutputFile { get; set; }
31 |
32 | [Required]
33 | public string? MSBuildProjectFile { get; set; }
34 |
35 | public ITaskItem[]? References { get; set; }
36 |
37 | public ITaskItem[]? ResolvedReferences { get; set; }
38 |
39 | public ITaskItem[]? ProjectReferences { get; set; }
40 |
41 | public ITaskItem[]? PackageReferences { get; set; }
42 |
43 | public string? ProjectAssetsFile { get; set; }
44 |
45 | public string? TargetFrameworkMoniker { get; set; }
46 |
47 | public string? TargetPlatformMoniker { get; set; }
48 |
49 | public string? RuntimeIdentifier { get; set; }
50 |
51 | public string? NuGetRestoreTargets { get; set; }
52 |
53 | public ITaskItem[]? TargetFrameworkDirectories { get; set; }
54 |
55 | public string? NuGetPackageRoot { get; set; }
56 |
57 | public override bool Execute()
58 | {
59 | AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
60 | try
61 | {
62 | List declaredReferences = new();
63 |
64 | if (References != null)
65 | {
66 | HashSet targetFrameworkAssemblies = GetTargetFrameworkAssemblyNames();
67 | foreach (ITaskItem reference in References)
68 | {
69 | // Ignore implicitly defined references (references which are SDK-provided)
70 | if (reference.GetMetadata("IsImplicitlyDefined").Equals("true", StringComparison.OrdinalIgnoreCase))
71 | {
72 | continue;
73 | }
74 |
75 | // During the _HandlePackageFileConflicts target (ResolvePackageFileConflicts task), assembly conflicts may be
76 | // resolved with an assembly from the target framework instead of a package. The package may be an indirect dependency,
77 | // so the resulting reference would be unavoidable.
78 | if (targetFrameworkAssemblies.Contains(reference.ItemSpec))
79 | {
80 | continue;
81 | }
82 |
83 | // Ignore references from packages. Those as handled later.
84 | if (reference.GetMetadata("NuGetPackageId").Length != 0)
85 | {
86 | continue;
87 | }
88 |
89 | // Ignore suppressions
90 | if (IsSuppressed(reference, "RT0001"))
91 | {
92 | continue;
93 | }
94 |
95 | var referenceSpec = reference.ItemSpec;
96 | var referenceHintPath = reference.GetMetadata("HintPath");
97 |
98 | string? referencePath;
99 | if (!string.IsNullOrEmpty(referenceHintPath) && File.Exists(referenceHintPath))
100 | {
101 | referencePath = Path.GetFullPath(referenceHintPath);
102 | }
103 | else if (File.Exists(referenceSpec))
104 | {
105 | referencePath = Path.GetFullPath(referenceSpec);
106 | }
107 | else
108 | {
109 | var resolvedReference = ResolvedReferences.SingleOrDefault(rr => string.Equals(rr.GetMetadata("OriginalItemSpec"), referenceSpec, StringComparison.OrdinalIgnoreCase));
110 | referencePath = resolvedReference is null ? null : resolvedReference.ItemSpec;
111 | }
112 |
113 | // If the reference is under the nuget package root, it's likely a Reference added in a package's props or targets.
114 | if (NuGetPackageRoot != null && referencePath != null)
115 | {
116 | if (referencePath.StartsWith(NuGetPackageRoot, StringComparison.OrdinalIgnoreCase))
117 | {
118 | continue;
119 | }
120 | }
121 |
122 | if (referencePath is not null)
123 | {
124 | declaredReferences.Add(new DeclaredReference(referencePath, DeclaredReferenceKind.Reference, referenceSpec));
125 | }
126 | }
127 | }
128 |
129 | if (ProjectReferences != null)
130 | {
131 | foreach (ITaskItem projectReference in ProjectReferences)
132 | {
133 | // Ignore suppressions
134 | if (IsSuppressed(projectReference, "RT0002"))
135 | {
136 | continue;
137 | }
138 |
139 | // Weirdly, NuGet restore is actually how transitive project references are determined and they're
140 | // added to to project.assets.json and collected via the IncludeTransitiveProjectReferences target.
141 | // This also adds the NuGetPackageId metadata, so use that as a signal that it's transitive.
142 | bool isTransitiveDependency = !string.IsNullOrEmpty(projectReference.GetMetadata("NuGetPackageId"));
143 | if (isTransitiveDependency)
144 | {
145 | // Ignore transitive project references since the project doesn't have direct control over them.
146 | continue;
147 | }
148 |
149 | string projectReferenceAssemblyPath = Path.GetFullPath(projectReference.ItemSpec);
150 | string referenceProjectFile = projectReference.GetMetadata("OriginalProjectReferenceItemSpec");
151 |
152 | declaredReferences.Add(new DeclaredReference(projectReferenceAssemblyPath, DeclaredReferenceKind.ProjectReference, referenceProjectFile));
153 | }
154 | }
155 |
156 | if (PackageReferences != null)
157 | {
158 | Dictionary packageInfos = GetPackageInfos();
159 | foreach (ITaskItem packageReference in PackageReferences)
160 | {
161 | // Ignore suppressions
162 | if (IsSuppressed(packageReference, "RT0003"))
163 | {
164 | continue;
165 | }
166 |
167 | if (!packageInfos.TryGetValue(packageReference.ItemSpec, out PackageInfo packageInfo))
168 | {
169 | // These are likely Analyzers, tools, etc.
170 | continue;
171 | }
172 |
173 | // Ignore packages with build logic as we cannot easily evaluate whether the build logic is necessary or not.
174 | if (packageInfo.BuildFiles.Count > 0)
175 | {
176 | continue;
177 | }
178 |
179 | foreach (string assemblyPath in packageInfo.CompileTimeAssemblies)
180 | {
181 | declaredReferences.Add(new DeclaredReference(assemblyPath, DeclaredReferenceKind.PackageReference, packageReference.ItemSpec));
182 | }
183 | }
184 | }
185 |
186 | if (OutputFile is not null)
187 | {
188 | new DeclaredReferences(declaredReferences).SaveToFile(OutputFile);
189 | }
190 | }
191 | finally
192 | {
193 | AppDomain.CurrentDomain.AssemblyResolve -= ResolveAssembly;
194 | }
195 |
196 | return !Log.HasLoggedErrors;
197 | }
198 |
199 | private Dictionary GetPackageInfos()
200 | {
201 | var packageInfoBuilders = new Dictionary(StringComparer.OrdinalIgnoreCase);
202 |
203 | var lockFile = LockFileUtilities.GetLockFile(ProjectAssetsFile, NullLogger.Instance);
204 | var packageFolders = lockFile.PackageFolders.Select(item => item.Path).ToList();
205 |
206 | LockFileTarget? nugetTarget = null;
207 | if (!string.IsNullOrEmpty(TargetFrameworkMoniker))
208 | {
209 | var nugetFramework = NuGetFramework.ParseComponents(TargetFrameworkMoniker!, TargetPlatformMoniker);
210 | nugetTarget = lockFile.GetTarget(nugetFramework, RuntimeIdentifier);
211 | }
212 |
213 | List nugetLibraries;
214 | if (nugetTarget?.Libraries is not null)
215 | {
216 | nugetLibraries = nugetTarget.Libraries
217 | .Where(nugetLibrary => string.Equals(nugetLibrary.Type, "Package", StringComparison.OrdinalIgnoreCase))
218 | .ToList();
219 | }
220 | else
221 | {
222 | nugetLibraries = new List();
223 | }
224 |
225 | // Compute the hierarchy of packages.
226 | // Keys are packages and values are packages which depend on that package.
227 | var nugetDependents = new Dictionary>(StringComparer.OrdinalIgnoreCase);
228 | foreach (LockFileTargetLibrary nugetLibrary in nugetLibraries)
229 | {
230 | string? packageId = nugetLibrary.Name;
231 | if (packageId is null)
232 | {
233 | continue;
234 | }
235 |
236 | foreach (var dependency in nugetLibrary.Dependencies)
237 | {
238 | if (!nugetDependents.TryGetValue(dependency.Id, out var parents))
239 | {
240 | parents = new List();
241 | nugetDependents.Add(dependency.Id, parents);
242 | }
243 |
244 | parents.Add(packageId);
245 | }
246 | }
247 |
248 | // Get the transitive closure of assemblies included by each package
249 | foreach (LockFileTargetLibrary nugetLibrary in nugetLibraries)
250 | {
251 | if (nugetLibrary.Name is null)
252 | {
253 | continue;
254 | }
255 |
256 | string nugetLibraryRelativePath = lockFile.GetLibrary(nugetLibrary.Name, nugetLibrary.Version).Path;
257 | string? nugetLibraryAbsolutePath = packageFolders
258 | .Select(packageFolder => Path.Combine(packageFolder, nugetLibraryRelativePath))
259 | .FirstOrDefault(Directory.Exists);
260 | if (nugetLibraryAbsolutePath is null)
261 | {
262 | // This can happen if the project has a stale lock file.
263 | // Just ignore it as NuGet itself will likely error.
264 | continue;
265 | }
266 |
267 | List nugetLibraryAssemblies = nugetLibrary.CompileTimeAssemblies
268 | .Select(item => item.Path)
269 | .Where(IsValidFile)
270 | .Select(path =>
271 | {
272 | var fullPath = Path.Combine(nugetLibraryAbsolutePath, path);
273 | return Path.GetFullPath(fullPath);
274 | })
275 | .ToList();
276 |
277 | List buildFiles = nugetLibrary.Build
278 | .Select(item => item.Path)
279 | .Where(IsValidFile)
280 | .Select(path => Path.Combine(nugetLibraryAbsolutePath, path))
281 | .ToList();
282 |
283 | // Add this package's assets, if there are any
284 | if (nugetLibraryAssemblies.Count > 0 || buildFiles.Count > 0)
285 | {
286 | // Walk up to add assets to all packages which directly or indirectly depend on this one.
287 | var seenDependents = new HashSet(StringComparer.OrdinalIgnoreCase);
288 | var queue = new Queue();
289 | queue.Enqueue(nugetLibrary.Name);
290 | while (queue.Count > 0)
291 | {
292 | var packageId = queue.Dequeue();
293 |
294 | if (!packageInfoBuilders.TryGetValue(packageId, out PackageInfoBuilder packageInfoBuilder))
295 | {
296 | packageInfoBuilder = new PackageInfoBuilder();
297 | packageInfoBuilders.Add(packageId, packageInfoBuilder);
298 | }
299 |
300 | packageInfoBuilder.AddCompileTimeAssemblies(nugetLibraryAssemblies);
301 | packageInfoBuilder.AddBuildFiles(buildFiles);
302 |
303 | // Recurse though dependents
304 | if (nugetDependents.TryGetValue(packageId, out var dependents))
305 | {
306 | foreach (var dependent in dependents)
307 | {
308 | if (seenDependents.Add(dependent))
309 | {
310 | queue.Enqueue(dependent);
311 | }
312 | }
313 | }
314 | }
315 | }
316 | }
317 |
318 | // Create the final collection
319 | var packageInfos = new Dictionary(packageInfoBuilders.Count, StringComparer.OrdinalIgnoreCase);
320 | foreach (KeyValuePair packageInfoBuilder in packageInfoBuilders)
321 | {
322 | packageInfos.Add(packageInfoBuilder.Key, packageInfoBuilder.Value.ToPackageInfo());
323 | }
324 |
325 | return packageInfos;
326 | }
327 |
328 | private static bool IsValidFile(string path) => !path.EndsWith("_._", StringComparison.Ordinal);
329 |
330 | private HashSet GetTargetFrameworkAssemblyNames()
331 | {
332 | HashSet targetFrameworkAssemblyNames = new();
333 |
334 | // This follows the same logic as FrameworkListReader.
335 | // See: https://github.com/dotnet/sdk/blob/main/src/Tasks/Common/ConflictResolution/FrameworkListReader.cs
336 | if (TargetFrameworkDirectories != null)
337 | {
338 | foreach (ITaskItem targetFrameworkDirectory in TargetFrameworkDirectories)
339 | {
340 | string frameworkListPath = Path.Combine(targetFrameworkDirectory.ItemSpec, "RedistList", "FrameworkList.xml");
341 | if (!File.Exists(frameworkListPath))
342 | {
343 | continue;
344 | }
345 |
346 | XDocument frameworkList = XDocument.Load(frameworkListPath);
347 | if (frameworkList.Root is not null)
348 | {
349 | foreach (XElement file in frameworkList.Root.Elements("File"))
350 | {
351 | string? type = file.Attribute("Type")?.Value;
352 | if (type?.Equals("Analyzer", StringComparison.OrdinalIgnoreCase) ?? false)
353 | {
354 | continue;
355 | }
356 |
357 | string? assemblyName = file.Attribute("AssemblyName")?.Value;
358 | if (!string.IsNullOrEmpty(assemblyName))
359 | {
360 | targetFrameworkAssemblyNames.Add(assemblyName!);
361 | }
362 | }
363 | }
364 | }
365 | }
366 |
367 | return targetFrameworkAssemblyNames;
368 | }
369 |
370 | ///
371 | /// Assembly resolution needed for parsing the lock file, needed if the version the task depends on is a different version than MSBuild's
372 | ///
373 | private Assembly? ResolveAssembly(object sender, ResolveEventArgs args)
374 | {
375 | AssemblyName assemblyName = new(args.Name);
376 |
377 | if (NugetAssemblies.Contains(assemblyName.Name))
378 | {
379 | string nugetProjectModelFile = Path.Combine(Path.GetDirectoryName(NuGetRestoreTargets)!, assemblyName.Name + ".dll");
380 | if (File.Exists(nugetProjectModelFile))
381 | {
382 | return Assembly.LoadFrom(nugetProjectModelFile);
383 | }
384 | }
385 |
386 | return null;
387 | }
388 |
389 | private static bool IsSuppressed(ITaskItem item, string warningId)
390 | {
391 | ReadOnlySpan warningIdSpan = warningId.AsSpan();
392 | ReadOnlySpan remainingNoWarn = item.GetMetadata(NoWarn).AsSpan();
393 | while (!remainingNoWarn.IsEmpty)
394 | {
395 | ReadOnlySpan currentNoWarn;
396 | int idx = remainingNoWarn.IndexOf(';');
397 | if (idx == -1)
398 | {
399 | currentNoWarn = remainingNoWarn;
400 | remainingNoWarn = ReadOnlySpan.Empty;
401 | }
402 | else
403 | {
404 | currentNoWarn = remainingNoWarn.Slice(0, idx);
405 | remainingNoWarn = remainingNoWarn.Slice(idx + 1);
406 | }
407 |
408 | if (currentNoWarn.Trim().Equals(warningIdSpan, StringComparison.OrdinalIgnoreCase))
409 | {
410 | return true;
411 | }
412 | }
413 |
414 | if (item.GetMetadata(TreatAsUsed).Equals("True", StringComparison.OrdinalIgnoreCase))
415 | {
416 | return true;
417 | }
418 |
419 | return false;
420 | }
421 |
422 | private sealed class PackageInfoBuilder
423 | {
424 | private List? _compileTimeAssemblies;
425 | private List? _buildFiles;
426 |
427 | public void AddCompileTimeAssemblies(List compileTimeAssemblies)
428 | {
429 | if (compileTimeAssemblies.Count == 0)
430 | {
431 | return;
432 | }
433 |
434 | _compileTimeAssemblies ??= new(compileTimeAssemblies.Count);
435 | _compileTimeAssemblies.AddRange(compileTimeAssemblies);
436 | }
437 |
438 | public void AddBuildFiles(List buildFiles)
439 | {
440 | if (buildFiles.Count == 0)
441 | {
442 | return;
443 | }
444 |
445 | _buildFiles ??= new(buildFiles.Count);
446 | _buildFiles.AddRange(buildFiles);
447 | }
448 |
449 | public PackageInfo ToPackageInfo()
450 | => new(
451 | (IReadOnlyCollection?)_compileTimeAssemblies ?? Array.Empty(),
452 | (IReadOnlyCollection?)_buildFiles ?? Array.Empty());
453 | }
454 |
455 | private readonly record struct PackageInfo(
456 | IReadOnlyCollection CompileTimeAssemblies,
457 | IReadOnlyCollection BuildFiles);
458 | }
459 |
--------------------------------------------------------------------------------
/src/Tasks/ReferenceTrimmer.Tasks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/MsvcLoggerTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Build.Framework;
2 | using ReferenceTrimmer.Loggers.MSVC;
3 |
4 | #pragma warning disable CA1707 // Underscores in test names
5 |
6 | namespace ReferenceTrimmer.Tests;
7 |
8 | [TestClass]
9 | public sealed class MsvcLoggerTests
10 | {
11 | private sealed class MockEventSource : IEventSource
12 | {
13 | public event BuildMessageEventHandler? MessageRaised;
14 | public event BuildErrorEventHandler? ErrorRaised;
15 | public event BuildWarningEventHandler? WarningRaised;
16 | public event BuildStartedEventHandler? BuildStarted;
17 | public event BuildFinishedEventHandler? BuildFinished;
18 | public event ProjectStartedEventHandler? ProjectStarted;
19 | public event ProjectFinishedEventHandler? ProjectFinished;
20 | public event TargetStartedEventHandler? TargetStarted;
21 | public event TargetFinishedEventHandler? TargetFinished;
22 | public event TaskStartedEventHandler? TaskStarted;
23 | public event TaskFinishedEventHandler? TaskFinished;
24 | public event CustomBuildEventHandler? CustomEventRaised;
25 | public event BuildStatusEventHandler? StatusEventRaised;
26 | public event AnyEventHandler? AnyEventRaised;
27 |
28 | public void AssertExpectedForwardingEventSubscriptions()
29 | {
30 | Assert.IsNotNull(MessageRaised);
31 | Assert.IsNotNull(TaskStarted);
32 | Assert.IsNotNull(TaskFinished);
33 | }
34 |
35 | public void AssertExpectedCentralLoggerEventSubscriptions()
36 | {
37 | Assert.IsNotNull(CustomEventRaised);
38 | }
39 |
40 | public void SendTaskStarted(TaskStartedEventArgs e)
41 | {
42 | TaskStarted?.Invoke(this, e);
43 | }
44 |
45 | public void SendTaskFinished(TaskFinishedEventArgs e)
46 | {
47 | TaskFinished?.Invoke(this, e);
48 | }
49 |
50 | public void SendMessageRaised(BuildMessageEventArgs e)
51 | {
52 | MessageRaised?.Invoke(this, e);
53 | }
54 |
55 | public void SendCustomEvent(CustomBuildEventArgs e)
56 | {
57 | CustomEventRaised?.Invoke(this, e);
58 | }
59 | }
60 |
61 | private sealed class MockEventRedirector : IEventRedirector
62 | {
63 | public List Events { get; } = new();
64 |
65 | public void ForwardEvent(BuildEventArgs buildEvent)
66 | {
67 | Events.Add(buildEvent);
68 | }
69 | }
70 |
71 | private sealed class NonUnusedLibCustomEventArgs : CustomBuildEventArgs
72 | {
73 | }
74 |
75 | [TestMethod]
76 | public void ForwardingLoggerInitShutdown()
77 | {
78 | var eventRedirector = new MockEventRedirector();
79 | var forwardingLogger = new ForwardingLogger
80 | {
81 | BuildEventRedirector = eventRedirector,
82 | NodeId = 1,
83 | Verbosity = LoggerVerbosity.Normal
84 | };
85 |
86 | var eventSource = new MockEventSource();
87 | forwardingLogger.Initialize(eventSource, nodeCount: 2);
88 | eventSource.AssertExpectedForwardingEventSubscriptions();
89 | forwardingLogger.Shutdown();
90 | }
91 |
92 | [TestMethod]
93 | public void ForwardingLogger_ForwardsNothingIfLinkTaskNotStarted()
94 | {
95 | var eventSource = new MockEventSource();
96 | var eventRedirector = new MockEventRedirector();
97 | var logger = new ForwardingLogger { BuildEventRedirector = eventRedirector };
98 | logger.Initialize(eventSource);
99 | try
100 | {
101 | eventSource.AssertExpectedForwardingEventSubscriptions();
102 | eventSource.SendTaskStarted(new TaskStartedEventArgs(message: "Not Link!", helpKeyword: "NotLink", projectFile: "a.proj", taskFile: "a.proj", taskName: "NotLink"));
103 | Assert.AreEqual(0, eventRedirector.Events.Count);
104 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: "a non-link message", helpKeyword: "NotLink", senderName: "NotLink", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
105 | Assert.AreEqual(0, eventRedirector.Events.Count);
106 | eventSource.SendTaskFinished(new TaskFinishedEventArgs(message: "Not Link!", helpKeyword: "NotLink", projectFile: "a.proj", taskFile: "a.proj", taskName: "NotLink", succeeded: true));
107 | Assert.AreEqual(0, eventRedirector.Events.Count);
108 | }
109 | finally
110 | {
111 | logger.Shutdown();
112 | }
113 | }
114 |
115 | [TestMethod]
116 | public void ForwardingLogger_ForwardsNothingIfLinkTaskGetsNoUnusedLibMessages()
117 | {
118 | var eventSource = new MockEventSource();
119 | var eventRedirector = new MockEventRedirector();
120 | var logger = new ForwardingLogger { BuildEventRedirector = eventRedirector };
121 | logger.Initialize(eventSource);
122 | try
123 | {
124 | eventSource.AssertExpectedForwardingEventSubscriptions();
125 | eventSource.SendTaskStarted(new TaskStartedEventArgs(message: "Link starting", helpKeyword: "Link", projectFile: "a.proj", taskFile: "a.proj", taskName: "Link"));
126 | Assert.AreEqual(0, eventRedirector.Events.Count);
127 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: "Generic link message", helpKeyword: "Link", senderName: "Link", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
128 | Assert.AreEqual(0, eventRedirector.Events.Count);
129 | eventSource.SendTaskFinished(new TaskFinishedEventArgs(message: "Link finished", helpKeyword: "Link", projectFile: "a.proj", taskFile: "a.proj", taskName: "Link", succeeded: true));
130 | Assert.AreEqual(0, eventRedirector.Events.Count);
131 | }
132 | finally
133 | {
134 | logger.Shutdown();
135 | }
136 | }
137 |
138 | [TestMethod]
139 | public void ForwardingLogger_ForwardsNothingIfLinkTaskGetsUnusedLibHeaderOnly()
140 | {
141 | var eventSource = new MockEventSource();
142 | var eventRedirector = new MockEventRedirector();
143 | var logger = new ForwardingLogger { BuildEventRedirector = eventRedirector };
144 | logger.Initialize(eventSource);
145 | try
146 | {
147 | eventSource.AssertExpectedForwardingEventSubscriptions();
148 | eventSource.SendTaskStarted(new TaskStartedEventArgs(message: "Link starting", helpKeyword: "Link", projectFile: "a.proj", taskFile: "a.proj", taskName: "Link"));
149 | Assert.AreEqual(0, eventRedirector.Events.Count);
150 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: "Unused libraries:", helpKeyword: "Link", senderName: "Link", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
151 | Assert.AreEqual(0, eventRedirector.Events.Count);
152 | eventSource.SendTaskFinished(new TaskFinishedEventArgs(message: "Link finished", helpKeyword: "Link", projectFile: "a.proj", taskFile: "a.proj", taskName: "Link", succeeded: true));
153 | Assert.AreEqual(0, eventRedirector.Events.Count);
154 | }
155 | finally
156 | {
157 | logger.Shutdown();
158 | }
159 | }
160 |
161 | [TestMethod]
162 | public void ForwardingLogger_ForwardsUnusedLibs()
163 | {
164 | var eventSource = new MockEventSource();
165 | var eventRedirector = new MockEventRedirector();
166 | var logger = new ForwardingLogger { BuildEventRedirector = eventRedirector };
167 | logger.Initialize(eventSource);
168 | try
169 | {
170 | eventSource.AssertExpectedForwardingEventSubscriptions();
171 | eventSource.SendTaskStarted(new TaskStartedEventArgs(message: "Link starting", helpKeyword: "Link", projectFile: "a.proj", taskFile: "a.proj", taskName: "Link"));
172 | Assert.AreEqual(0, eventRedirector.Events.Count);
173 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: "Unused libraries:", helpKeyword: "Link", senderName: "Link", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
174 | Assert.AreEqual(0, eventRedirector.Events.Count);
175 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: " user32.lib", helpKeyword: "Link", senderName: "Link", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
176 | Assert.AreEqual(0, eventRedirector.Events.Count);
177 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: " bar.lib", helpKeyword: "Link", senderName: "Link", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
178 | Assert.AreEqual(0, eventRedirector.Events.Count);
179 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: string.Empty, helpKeyword: "Link", senderName: "Link", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
180 | Assert.AreEqual(0, eventRedirector.Events.Count);
181 | eventSource.SendTaskFinished(new TaskFinishedEventArgs(message: "Link finished", helpKeyword: "Link", projectFile: "a.proj", taskFile: "a.proj", taskName: "Link", succeeded: true));
182 | Assert.AreEqual(1, eventRedirector.Events.Count);
183 | var unusedLibArgs = eventRedirector.Events[0] as UnusedLibsCustomBuildEventArgs;
184 | Assert.IsNotNull(unusedLibArgs);
185 | Assert.AreEqual("a.proj", unusedLibArgs.ProjectPath);
186 | Assert.IsTrue(unusedLibArgs.Message!.Contains("user32.lib", StringComparison.Ordinal), unusedLibArgs.Message);
187 | Assert.IsTrue(unusedLibArgs.Message.Contains("bar.lib", StringComparison.Ordinal), unusedLibArgs.Message);
188 | Assert.IsTrue(unusedLibArgs.UnusedLibraryPathsJson.Length > 0);
189 | }
190 | finally
191 | {
192 | logger.Shutdown();
193 | }
194 | }
195 |
196 | [TestMethod]
197 | public void ForwardingLogger_ForwardsNothingIfLinkTaskFails()
198 | {
199 | var eventSource = new MockEventSource();
200 | var eventRedirector = new MockEventRedirector();
201 | var logger = new ForwardingLogger { BuildEventRedirector = eventRedirector };
202 | logger.Initialize(eventSource);
203 | try
204 | {
205 | eventSource.AssertExpectedForwardingEventSubscriptions();
206 | eventSource.SendTaskStarted(new TaskStartedEventArgs(message: "Link starting", helpKeyword: "Link", projectFile: "a.proj", taskFile: "a.proj", taskName: "Link"));
207 | Assert.AreEqual(0, eventRedirector.Events.Count);
208 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: "Unused libraries:", helpKeyword: "Link", senderName: "Link", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
209 | Assert.AreEqual(0, eventRedirector.Events.Count);
210 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: " kernel32.lib", helpKeyword: "Link", senderName: "Link", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
211 | Assert.AreEqual(0, eventRedirector.Events.Count);
212 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: " foo.lib", helpKeyword: "Link", senderName: "Link", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
213 | Assert.AreEqual(0, eventRedirector.Events.Count);
214 | eventSource.SendMessageRaised(new BuildMessageEventArgs(message: string.Empty, helpKeyword: "Link", senderName: "Link", MessageImportance.High, DateTime.Now) { ProjectFile = "a.proj" });
215 | Assert.AreEqual(0, eventRedirector.Events.Count);
216 | eventSource.SendTaskFinished(new TaskFinishedEventArgs(message: "Link finished", helpKeyword: "Link", projectFile: "a.proj", taskFile: "a.proj", taskName: "Link", succeeded: false));
217 | Assert.AreEqual(0, eventRedirector.Events.Count);
218 | }
219 | finally
220 | {
221 | logger.Shutdown();
222 | }
223 | }
224 |
225 | [TestMethod]
226 | [DoNotParallelize]
227 | public void CentralLogger_WritesNoJsonIfNoUnusedLibEvents()
228 | {
229 | string jsonPath = Path.Combine(Environment.CurrentDirectory, CentralLogger.JsonLogFileName);
230 | DeleteIfExists(jsonPath);
231 |
232 | var eventSource = new MockEventSource();
233 | var centralLogger = new CentralLogger();
234 | centralLogger.Initialize(eventSource);
235 | eventSource.AssertExpectedCentralLoggerEventSubscriptions();
236 | eventSource.SendCustomEvent(new NonUnusedLibCustomEventArgs());
237 | eventSource.SendCustomEvent(new UnusedLibsCustomBuildEventArgs());
238 | centralLogger.Shutdown();
239 | Assert.IsFalse(File.Exists(jsonPath));
240 | }
241 |
242 | [TestMethod]
243 | [DoNotParallelize]
244 | public async Task CentralLogger_JsonOnUnusedLibEvents()
245 | {
246 | string jsonPath = Path.Combine(Environment.CurrentDirectory, CentralLogger.JsonLogFileName);
247 | DeleteIfExists(jsonPath);
248 |
249 | var eventSource = new MockEventSource();
250 | var centralLogger = new CentralLogger();
251 | centralLogger.Initialize(eventSource);
252 | eventSource.AssertExpectedCentralLoggerEventSubscriptions();
253 | eventSource.SendCustomEvent(new UnusedLibsCustomBuildEventArgs(message: "Unused libraries!",
254 | projectPath: "a.proj", unusedLibraryPathsJson: "{ \"aProp\": \"aValue\" }"));
255 | eventSource.SendCustomEvent(new UnusedLibsCustomBuildEventArgs(message: "Unused libraries 2!",
256 | projectPath: "a2.proj", unusedLibraryPathsJson: "{ \"aProp2\": \"aValue2\" }"));
257 | centralLogger.Shutdown();
258 | Assert.IsTrue(File.Exists(jsonPath));
259 | Assert.AreEqual($"[{Environment.NewLine}{{ \"aProp\": \"aValue\" }},{Environment.NewLine}{{ \"aProp2\": \"aValue2\" }}{Environment.NewLine}]{Environment.NewLine}",
260 | await File.ReadAllTextAsync(jsonPath));
261 | }
262 |
263 | private static void DeleteIfExists(string path)
264 | {
265 | if (File.Exists(path))
266 | {
267 | File.Delete(path);
268 | }
269 | }
270 | }
271 |
--------------------------------------------------------------------------------
/src/Tests/ReferenceTrimmer.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 | x64
5 | AnyCPU;x64
6 | $(NoWarn);0067;1591;CA1861
7 |
8 |
9 | $(DefaultItemExcludes);TestData/**;TestResults/**
10 |
11 |
12 |
13 | false
14 | Build;Pack
15 |
16 |
17 |
18 |
19 |
20 | PreserveNewest
21 |
22 |
23 |
24 |
25 |
26 | PreserveNewest
27 |
28 |
29 |
30 |
31 |
35 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/Tests/TestData/AbsoluteIntermediateOutputPath/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Newtonsoft.Json.JsonConvert.SerializeObject(null);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/AbsoluteIntermediateOutputPath/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 | $(MSBuildProjectDirectory)\obj
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Tests/TestData/BuildExtensions/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/BuildExtensions/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | netstandard2.0
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/BuildExtensions/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Dependency.Foo.Bar();
6 |
7 | public static string Baz() => Newtonsoft.Json.JsonConvert.SerializeObject(null);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Tests/TestData/BuildExtensions/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net462
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/Tests/TestData/BuildPackageReference/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 | $(NoWarn);1591
7 |
8 |
10 | <_NuGetTargetFallbackMoniker>$(_NuGetTargetFallbackMoniker);native,Version=v0.0
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Tests/TestData/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/Tests/TestData/LegacyStyleProject/Library/Class1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ClassLibrary1
8 | {
9 | public class Class1
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/LegacyStyleProject/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | 80472081-bc7f-43a9-af72-dc02c677c2c1
8 | Library
9 | Properties
10 | Library
11 | Library
12 | v4.7.2
13 | 512
14 | true
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | bin\Debug\Library.xml
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 | bin\Release\Library.xml
34 |
35 |
36 | true
37 | full
38 | false
39 | bin\Debug\
40 | DEBUG;TRACE
41 | prompt
42 | 4
43 | bin\Debug\Library.xml
44 |
45 |
46 | pdbonly
47 | true
48 | bin\Release\
49 | TRACE
50 | prompt
51 | 4
52 | bin\Release\Library.xml
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/Tests/TestData/LegacyStyleProject/Library/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ClassLibrary1")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ClassLibrary1")]
13 | [assembly: AssemblyCopyright("Copyright © 2023")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("80472081-bc7f-43a9-af72-dc02c677c2c1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/src/Tests/TestData/MissingReferenceSourceTarget/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/MissingReferenceSourceTarget/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 |
6 | netstandard2.0
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/Tests/TestData/MissingReferenceSourceTarget/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Dependency.Foo.Bar();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/MissingReferenceSourceTarget/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/NoTargets/Project.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Tests/TestData/PackageReferenceWithFakeBuildFile/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Newtonsoft.Json.JsonConvert.SerializeObject(null);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/PackageReferenceWithFakeBuildFile/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Tests/TestData/PlatformPackageConflictResolution/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/PlatformPackageConflictResolution/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Tests/TestData/ReferenceInPackage/Tests/FooTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 |
3 | namespace Tests
4 | {
5 | [TestClass]
6 | public class FooTests
7 | {
8 | [TestMethod]
9 | public static void Foo() => Assert.IsTrue(true);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/Tests/TestData/ReferenceInPackage/Tests/Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/Tests/TestData/ReferenceTrimmerDisabled/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/ReferenceTrimmerDisabled/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 | false
7 |
8 | false
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Tests/TestData/TargetFrameworkWithOs/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library;
2 |
3 | public static class Foo
4 | {
5 | public static string Bar() => Newtonsoft.Json.JsonConvert.SerializeObject(null);
6 | }
7 |
--------------------------------------------------------------------------------
/src/Tests/TestData/TargetFrameworkWithOs/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net6.0-windows
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppDelayLoadLibrary/App/App.cpp:
--------------------------------------------------------------------------------
1 | // App.cpp : This file contains the 'main' function. Program execution begins and ends there.
2 | //
3 |
4 | #include
5 |
6 | int main()
7 | {
8 | std::cout << "Hello World!\n";
9 | }
10 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppDelayLoadLibrary/App/App.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | Win32
6 |
7 |
8 | Release
9 | Win32
10 |
11 |
12 | Debug
13 | x64
14 |
15 |
16 | Release
17 | x64
18 |
19 |
20 |
21 | 16.0
22 | {500F3F51-4D42-48DB-BA30-B8DA2864F168}
23 | Win32Proj
24 | App
25 | 10.0
26 |
27 |
28 |
29 | Application
30 | true
31 | v143
32 | Unicode
33 |
34 |
35 | Application
36 | false
37 | v143
38 | true
39 | Unicode
40 |
41 |
42 | Application
43 | true
44 | v143
45 | Unicode
46 |
47 |
48 | Application
49 | false
50 | v143
51 | true
52 | Unicode
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | true
74 |
75 |
76 | true
77 |
78 |
79 | false
80 |
81 |
82 | false
83 |
84 |
85 |
86 |
87 |
88 | Level3
89 | Disabled
90 | true
91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 | Console
96 | true
97 |
98 |
99 |
100 |
101 |
102 |
103 | Level3
104 | Disabled
105 | true
106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
107 | true
108 |
109 |
110 | Console
111 | true
112 |
113 |
114 |
115 |
116 |
117 |
118 | Level3
119 | MaxSpeed
120 | true
121 | true
122 | true
123 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
124 | true
125 |
126 |
127 | Console
128 | true
129 | true
130 | true
131 |
132 |
133 |
134 |
135 |
136 |
137 | Level3
138 | MaxSpeed
139 | true
140 | true
141 | true
142 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
143 | true
144 |
145 |
146 | Console
147 | true
148 | true
149 | true
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | {10e385bf-5b1f-49be-b708-afc869118cf2}
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppDelayLoadLibrary/Dll/DLL.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 17.0
23 | Win32Proj
24 | {10e385bf-5b1f-49be-b708-afc869118cf2}
25 | DLL
26 | 10.0
27 |
28 |
29 |
30 | DynamicLibrary
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | DynamicLibrary
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | DynamicLibrary
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | DynamicLibrary
50 | false
51 | v143
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Level3
76 | true
77 | WIN32;_DEBUG;DLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
78 | true
79 | Use
80 | pch.h
81 |
82 |
83 | Windows
84 | true
85 | false
86 |
87 |
88 |
89 |
90 | Level3
91 | true
92 | true
93 | true
94 | WIN32;NDEBUG;DLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
95 | true
96 | Use
97 | pch.h
98 |
99 |
100 | Windows
101 | true
102 | true
103 | true
104 | false
105 |
106 |
107 |
108 |
109 | Level3
110 | true
111 | _DEBUG;DLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
112 | true
113 | Use
114 | pch.h
115 |
116 |
117 | Windows
118 | true
119 | false
120 |
121 |
122 |
123 |
124 | Level3
125 | true
126 | true
127 | true
128 | NDEBUG;DLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
129 | true
130 | Use
131 | pch.h
132 |
133 |
134 | Windows
135 | true
136 | true
137 | true
138 | false
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | Create
149 | Create
150 | Create
151 | Create
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppDelayLoadLibrary/Dll/dllmain.cpp:
--------------------------------------------------------------------------------
1 | // dllmain.cpp : Defines the entry point for the DLL application.
2 | #include "pch.h"
3 |
4 | BOOL APIENTRY DllMain( HMODULE hModule,
5 | DWORD ul_reason_for_call,
6 | LPVOID lpReserved
7 | )
8 | {
9 | switch (ul_reason_for_call)
10 | {
11 | case DLL_PROCESS_ATTACH:
12 | case DLL_THREAD_ATTACH:
13 | case DLL_THREAD_DETACH:
14 | case DLL_PROCESS_DETACH:
15 | break;
16 | }
17 | return TRUE;
18 | }
19 |
20 | __declspec(dllexport) void __cdecl DoNothingInDll()
21 | {
22 | // Do nothing
23 | }
24 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppDelayLoadLibrary/Dll/framework.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
4 | // Windows Header Files
5 | #include
6 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppDelayLoadLibrary/Dll/pch.cpp:
--------------------------------------------------------------------------------
1 | // pch.cpp: source file corresponding to the pre-compiled header
2 |
3 | #include "pch.h"
4 |
5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
6 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppDelayLoadLibrary/Dll/pch.h:
--------------------------------------------------------------------------------
1 | // pch.h: This is a precompiled header file.
2 | // Files listed below are compiled only once, improving build performance for future builds.
3 | // This also affects IntelliSense performance, including code completion and many code browsing features.
4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds.
5 | // Do not add files here that you will be updating frequently as this negates the performance advantage.
6 |
7 | #ifndef PCH_H
8 | #define PCH_H
9 |
10 | // add headers that you want to pre-compile here
11 | #include "framework.h"
12 |
13 | #endif //PCH_H
14 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppLibrary/App/App.cpp:
--------------------------------------------------------------------------------
1 | // App.cpp : This file contains the 'main' function. Program execution begins and ends there.
2 | //
3 |
4 | #include
5 |
6 | int main()
7 | {
8 | std::cout << "Hello World!\n";
9 | }
10 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppLibrary/App/App.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | Win32
6 |
7 |
8 | Release
9 | Win32
10 |
11 |
12 | Debug
13 | x64
14 |
15 |
16 | Release
17 | x64
18 |
19 |
20 |
21 | 16.0
22 | {500F3F51-4D42-48DB-BA30-B8DA2864F168}
23 | Win32Proj
24 | App
25 | 10.0
26 |
27 |
28 |
29 | Application
30 | true
31 | v143
32 | Unicode
33 |
34 |
35 | Application
36 | false
37 | v143
38 | true
39 | Unicode
40 |
41 |
42 | Application
43 | true
44 | v143
45 | Unicode
46 |
47 |
48 | Application
49 | false
50 | v143
51 | true
52 | Unicode
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | true
74 |
75 |
76 | true
77 |
78 |
79 | false
80 |
81 |
82 | false
83 |
84 |
85 |
86 |
87 |
88 | Level3
89 | Disabled
90 | true
91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 | Console
96 | true
97 |
98 |
99 |
100 |
101 |
102 |
103 | Level3
104 | Disabled
105 | true
106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
107 | true
108 |
109 |
110 | Console
111 | true
112 |
113 |
114 |
115 |
116 |
117 |
118 | Level3
119 | MaxSpeed
120 | true
121 | true
122 | true
123 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
124 | true
125 |
126 |
127 | Console
128 | true
129 | true
130 | true
131 |
132 |
133 |
134 |
135 |
136 |
137 | Level3
138 | MaxSpeed
139 | true
140 | true
141 | true
142 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
143 | true
144 |
145 |
146 | Console
147 | true
148 | true
149 | true
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | {f3844c7d-e56d-42bc-8169-cb466a06bdfc}
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppLibrary/Library/Library.cpp:
--------------------------------------------------------------------------------
1 | void DoNothing()
2 | {
3 | }
4 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedCppLibrary/Library/Library.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | Win32
6 |
7 |
8 | Release
9 | Win32
10 |
11 |
12 | Debug
13 | x64
14 |
15 |
16 | Release
17 | x64
18 |
19 |
20 |
21 | 17.0
22 | Win32Proj
23 | {f3844c7d-e56d-42bc-8169-cb466a06bdfc}
24 | StaticLib
25 | 10.0
26 |
27 |
28 |
29 | StaticLibrary
30 | true
31 | v143
32 | Unicode
33 |
34 |
35 | StaticLibrary
36 | false
37 | v143
38 | true
39 | Unicode
40 |
41 |
42 | StaticLibrary
43 | true
44 | v143
45 | Unicode
46 |
47 |
48 | StaticLibrary
49 | false
50 | v143
51 | true
52 | Unicode
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Level3
75 | true
76 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
77 | true
78 |
79 |
80 |
81 |
82 | true
83 |
84 |
85 |
86 |
87 | Level3
88 | true
89 | true
90 | true
91 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 |
96 |
97 | true
98 | true
99 | true
100 |
101 |
102 |
103 |
104 | Level3
105 | true
106 | _DEBUG;_LIB;%(PreprocessorDefinitions)
107 | true
108 |
109 |
110 |
111 |
112 | true
113 |
114 |
115 |
116 |
117 | Level3
118 | true
119 | true
120 | true
121 | NDEBUG;_LIB;%(PreprocessorDefinitions)
122 | true
123 |
124 |
125 |
126 |
127 | true
128 | true
129 | true
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedDirectAndTransitiveProjectReference/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Bar";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedDirectAndTransitiveProjectReference/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedDirectAndTransitiveProjectReference/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Dependency.Foo.Bar();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedDirectAndTransitiveProjectReference/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedDirectAndTransitiveProjectReference/TransitiveDependency/TransitiveDependency.cs:
--------------------------------------------------------------------------------
1 | namespace TransitiveDependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Baz() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedDirectAndTransitiveProjectReference/TransitiveDependency/TransitiveDependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedPackageReference/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedPackageReference/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedPackageReferenceDocDisabled/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedPackageReferenceDocDisabled/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedPackageReferenceNoWarn/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedPackageReferenceNoWarn/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedPackageReferenceTreatAsUsed/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedPackageReferenceTreatAsUsed/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReference/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReference/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReference/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReference/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceNoReferenceAssembly/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceNoReferenceAssembly/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 | true
7 | false
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceNoReferenceAssembly/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceNoReferenceAssembly/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 | true
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceNoWarn/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceNoWarn/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceNoWarn/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceNoWarn/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceProduceReferenceAssembly/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceProduceReferenceAssembly/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 | true
7 | true
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceProduceReferenceAssembly/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceProduceReferenceAssembly/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 | true
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceSuppressed/.globalconfig:
--------------------------------------------------------------------------------
1 | is_global=true
2 |
3 | dotnet_diagnostic.RT0002.severity = suggestion
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceSuppressed/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceSuppressed/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceSuppressed/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceSuppressed/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceTreatAsUsed/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceTreatAsUsed/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceTreatAsUsed/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedProjectReferenceTreatAsUsed/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceFromGac/Class1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ClassLibrary1
8 | {
9 | public class Class1
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceFromGac/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | 80472081-bc7f-43a9-af72-dc02c677c2c1
8 | Library
9 | Properties
10 | Library
11 | Library
12 | v4.7.2
13 | 512
14 | true
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | bin\Debug\Library.xml
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 | bin\Release\Library.xml
34 |
35 |
36 | true
37 | full
38 | false
39 | bin\Debug\
40 | DEBUG;TRACE
41 | prompt
42 | 4
43 | bin\Debug\Library.xml
44 |
45 |
46 | pdbonly
47 | true
48 | bin\Release\
49 | TRACE
50 | prompt
51 | 4
52 | bin\Release\Library.xml
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceFromGac/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ClassLibrary1")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ClassLibrary1")]
13 | [assembly: AssemblyCopyright("Copyright © 2023")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("80472081-bc7f-43a9-af72-dc02c677c2c1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPath/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPath/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPath/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPath/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 | ..\Dependency\$(OutputPath)\Dependency.dll
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPathNoWarn/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPathNoWarn/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPathNoWarn/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPathNoWarn/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 | ..\Dependency\$(OutputPath)\Dependency.dll
11 | Foo; rt0001 ; Bar
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPathTreatAsUsed/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPathTreatAsUsed/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPathTreatAsUsed/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceHintPathTreatAsUsed/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 | ..\Dependency\$(OutputPath)\Dependency.dll
11 | true
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpec/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpec/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpec/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpec/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpecNoWarn/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpecNoWarn/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpecNoWarn/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpecNoWarn/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpecTreatAsUsed/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpecTreatAsUsed/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpecTreatAsUsed/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedReferenceItemSpecTreatAsUsed/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedTransitiveProjectReference/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Bar";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedTransitiveProjectReference/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedTransitiveProjectReference/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Dependency.Foo.Bar();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedTransitiveProjectReference/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedTransitiveProjectReference/TransitiveDependency/TransitiveDependency.cs:
--------------------------------------------------------------------------------
1 | namespace TransitiveDependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Baz() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedTransitiveProjectReference/TransitiveDependency/TransitiveDependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedWinSdkImportLibrary/App/App.cpp:
--------------------------------------------------------------------------------
1 | // App.cpp : This file contains the 'main' function. Program execution begins and ends there.
2 | //
3 |
4 | #include
5 |
6 | int main()
7 | {
8 | std::cout << "Hello World!\n";
9 | }
10 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedWinSdkImportLibrary/App/App.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | Win32
6 |
7 |
8 | Release
9 | Win32
10 |
11 |
12 | Debug
13 | x64
14 |
15 |
16 | Release
17 | x64
18 |
19 |
20 |
21 | 16.0
22 | {500F3F51-4D42-48DB-BA30-B8DA2864F168}
23 | Win32Proj
24 | App
25 | 10.0
26 |
27 |
28 |
29 | Application
30 | true
31 | v143
32 | Unicode
33 |
34 |
35 | Application
36 | false
37 | v143
38 | true
39 | Unicode
40 |
41 |
42 | Application
43 | true
44 | v143
45 | Unicode
46 |
47 |
48 | Application
49 | false
50 | v143
51 | true
52 | Unicode
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | true
74 |
75 |
76 | true
77 |
78 |
79 | false
80 |
81 |
82 | false
83 |
84 |
85 |
86 |
87 |
88 | Level3
89 | Disabled
90 | true
91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 | Console
96 | true
97 |
98 |
99 |
100 |
101 |
102 |
103 | Level3
104 | Disabled
105 | true
106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
107 | true
108 |
109 |
110 | Console
111 | true
112 |
113 |
114 |
115 |
116 |
117 |
118 | Level3
119 | MaxSpeed
120 | true
121 | true
122 | true
123 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
124 | true
125 |
126 |
127 | Console
128 | true
129 | true
130 | true
131 |
132 |
133 |
134 |
135 |
136 |
137 | Level3
138 | MaxSpeed
139 | true
140 | true
141 | true
142 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
143 | true
144 |
145 |
146 | Console
147 | true
148 | true
149 | true
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UnusedWinSdkImportLibrary/App/util.cpp:
--------------------------------------------------------------------------------
1 | int doSomething()
2 | {
3 | return 0;
4 | }
5 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedIndirectPackageReference/WebHost/Program.cs:
--------------------------------------------------------------------------------
1 | namespace WebHost
2 | {
3 | using System.IO;
4 | using System.Net;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore.Builder;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.AspNetCore.Http;
9 |
10 | public class Program
11 | {
12 | public static Task Main()
13 | {
14 | return new WebHostBuilder()
15 | .UseKestrel(options => options.Listen(IPAddress.Loopback, 5001))
16 | .UseContentRoot(Directory.GetCurrentDirectory())
17 | .Configure(app =>
18 | app.Run(async context =>
19 | {
20 | await context.Response.WriteAsync("Hello World!");
21 | }))
22 | .Build()
23 | .RunAsync();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedIndirectPackageReference/WebHost/WebHost.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | Latest
6 | true
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedPackageReference/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Newtonsoft.Json.JsonConvert.SerializeObject(null);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedPackageReference/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReference/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReference/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReference/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Dependency.Foo.Bar();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReference/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReferenceNoReferenceAssembly/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReferenceNoReferenceAssembly/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 | true
7 | false
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReferenceNoReferenceAssembly/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Dependency.Foo.Bar();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReferenceNoReferenceAssembly/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 | true
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReferenceProduceReferenceAssembly/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReferenceProduceReferenceAssembly/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 | true
7 | true
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReferenceProduceReferenceAssembly/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Dependency.Foo.Bar();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedProjectReferenceProduceReferenceAssembly/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 | true
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceFromGac/Class1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Microsoft.Office.Interop.Outlook;
7 |
8 | namespace ClassLibrary1
9 | {
10 | public class Class1
11 | {
12 | public Application CreateApplication() => new Application();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceFromGac/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | 80472081-bc7f-43a9-af72-dc02c677c2c1
8 | Library
9 | Properties
10 | Library
11 | Library
12 | v4.7.2
13 | 512
14 | true
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | bin\Debug\Library.xml
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 | bin\Release\Library.xml
34 |
35 |
36 | true
37 | full
38 | false
39 | bin\Debug\
40 | DEBUG;TRACE
41 | prompt
42 | 4
43 | bin\Debug\Library.xml
44 |
45 |
46 | pdbonly
47 | true
48 | bin\Release\
49 | TRACE
50 | prompt
51 | 4
52 | bin\Release\Library.xml
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceFromGac/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ClassLibrary1")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ClassLibrary1")]
13 | [assembly: AssemblyCopyright("Copyright © 2023")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("80472081-bc7f-43a9-af72-dc02c677c2c1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceHintPath/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceHintPath/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceHintPath/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Dependency.Foo.Bar();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceHintPath/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 | ..\Dependency\$(OutputPath)\Dependency.dll
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceItemSpec/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceItemSpec/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceItemSpec/Library/Library.cs:
--------------------------------------------------------------------------------
1 | namespace Library
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => Dependency.Foo.Bar();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/UsedReferenceItemSpec/Library/Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/WpfApp/Dependency/Dependency.cs:
--------------------------------------------------------------------------------
1 | namespace Dependency
2 | {
3 | public static class Foo
4 | {
5 | public static string Bar() => "Baz";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Tests/TestData/WpfApp/Dependency/Dependency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | netstandard2.0
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/Tests/TestData/WpfApp/WpfApp/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/Tests/TestData/WpfApp/WpfApp/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Configuration;
2 | using System.Data;
3 | using System.Windows;
4 |
5 | namespace WpfApp
6 | {
7 | ///
8 | /// Interaction logic for App.xaml
9 | ///
10 | public partial class App : Application
11 | {
12 | // Use the dependency
13 | public string X = Dependency.Foo.Bar();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Tests/TestData/WpfApp/WpfApp/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(
4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
5 | //(used if a resource is not found in the page,
6 | // or application resource dictionaries)
7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
8 | //(used if a resource is not found in the page,
9 | // app, or any theme specific resource dictionaries)
10 | )]
11 |
--------------------------------------------------------------------------------
/src/Tests/TestData/WpfApp/WpfApp/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Tests/TestData/WpfApp/WpfApp/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 | using System.Windows.Data;
5 | using System.Windows.Documents;
6 | using System.Windows.Input;
7 | using System.Windows.Media;
8 | using System.Windows.Media.Imaging;
9 | using System.Windows.Navigation;
10 | using System.Windows.Shapes;
11 |
12 | namespace WpfApp
13 | {
14 | ///
15 | /// Interaction logic for MainWindow.xaml
16 | ///
17 | public partial class MainWindow : Window
18 | {
19 | public MainWindow()
20 | {
21 | InitializeComponent();
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Tests/TestData/WpfApp/WpfApp/WpfApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net8.0-windows
6 | enable
7 | enable
8 | true
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3 | "version": "3.3",
4 | "assemblyVersion": "3.3",
5 | "buildNumberOffset": -1,
6 | "publicReleaseRefSpec": [
7 | "^refs/tags/v\\d+\\.\\d+\\.\\d+"
8 | ],
9 | "cloudBuild": {
10 | "setVersionVariables": true,
11 | "buildNumber": {
12 | "enabled": true,
13 | "includeCommitId": {
14 | "when": "nonPublicReleaseOnly",
15 | "where": "buildMetadata"
16 | }
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------