Skip to content

Commit 47162a0

Browse files
committed
Update README.md, build output, and usage
1 parent 226962c commit 47162a0

File tree

3 files changed

+156
-5
lines changed

3 files changed

+156
-5
lines changed

README.md

Lines changed: 154 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,154 @@
1-
# DeadRegionAnalysis
2-
Roslyn tool for analyzing dead conditional regions of C# code across multiple project configurations
1+
# deadregions
2+
Tool for analyzing and cleaning up unecessary ("dead") conditional regions in C# code
3+
```
4+
SYNTAX
5+
DeadRegions [<project> ...] [options]
6+
DeadRegions [<source file> ...] [options]
7+
8+
OPTIONS
9+
config <symbol list>
10+
Specify a complete symbol configuration
11+
[multiple specifications allowed]
12+
13+
ignore <symbol list>
14+
Ignore a list of symbols (treat as varying)
15+
[multiple specifications allowed]
16+
17+
define <symbol list>
18+
Define a list of symbols (treat as always true)
19+
[multiple specifications allowed]
20+
21+
disable <symbol list>
22+
Disable a list of symbols (treat as always disabled)
23+
[multiple specifications allowed]
24+
25+
default <false|true|varying>
26+
Set the default value for symbols which do not have a specified value (defaults
27+
to varying)
28+
29+
printdisabled
30+
Print the list of always disabled conditional regions
31+
32+
printenabled
33+
Print the list of always enabled conditional regions
34+
35+
printvarying
36+
Print the list of varying conditional regions
37+
38+
printsymbols
39+
Print the lists of uniquely specified preprocessor symbols, symbols visited
40+
during analysis, and symbols not encountered during analysis
41+
42+
print
43+
Print the entire list of conditional regions and the lists of preprocessor
44+
symbols (combination of printenabled, printdisabled, printvarying, and
45+
printsymbols)
46+
47+
edit
48+
Perform edits to remove always enabled and always disabled conditional regions
49+
from source files, and simplify preprocessor expressions which evaluate to
50+
'varying'
51+
52+
53+
NOTES
54+
<symbol list> is a comma or semi-colon separated list of preprocessor symbols
55+
```
56+
57+
An unnecessary conditional region is one conditioned on a preprocessor expression that, across all possible build configurations for a given project, always evaluates to `true` or always evaluates to `false`. Such regions are either dead code (if conditioned on `false`) or have unnecessary preprocessor directives (if conditioned on `true`). Conversely, regions conditioned on preprocessor expressions which evaluate differently across different build configurations have meaningful preprocessor directives.
58+
59+
This tool can analyze a given project to determine which branching preprocessor directives and regions are unnecessary, and optionally remove them.
60+
61+
# Examples
62+
63+
## Analyze all conditional regions in a project
64+
65+
`> deadregions example.csproj /print`
66+
67+
This will print out something like
68+
```
69+
D:\example\Program.cs(2): "#if true" : Always Enabled
70+
D:\example\Program.cs(4): "#else" : Always Disabled
71+
D:\example\Program.cs(8): "#if ZERO // TODO(somebody): Re-enable this when x is fixed" : Varying
72+
D:\example\Program.cs(14): "#if DEBUG" : Varying
73+
Conditional Regions
74+
4 found in total
75+
1 always disabled
76+
1 always enabled
77+
2 varying
78+
79+
Symbols
80+
0 unique symbol(s) specified:
81+
3 unique symbol(s) visited: true;ZERO;DEBUG
82+
0 specified symbol(s) unvisited:
83+
```
84+
85+
There are a few things going on here. As you would expect, the `#if true` region is determined to be always enabled, and the corresponding `#else` is always disabled. You'll also notice that you get a summary of information about the conditional regions found in the project, as well as the preprocessor symbols that were specified on the command line, found in the project.
86+
87+
One interesting thing to note is that the `#if ZERO` and `#if DEBUG` regions are determined to be varying. That is because unlike the C# preprocessor, this tool evaluates symbols which do not have a specified value as "varying" by default. The rational behind this is that most of the time, you'll be using this tool to remove dead conditional regions, but you won't necessarily specify or even have all the data about all possible build configurations. So in order to avoid removing regions which are determined to be always disabled simply because you didn't specify a value for a symbol, the tool defaults the value to varying, which causes the region to be ignored in the clean-up pass.
88+
89+
If you would like to get the same behavior as the C# preprocessor (default undefined symbols to `false`), just pass `/default false`
90+
91+
```
92+
> deadregions .\example.csproj /print /default false
93+
D:\example\Program.cs(2): "#if true" : Always Enabled
94+
D:\example\Program.cs(4): "#else" : Always Disabled
95+
D:\example\Program.cs(8): "#if ZERO // TODO(somebody): Re-enable this when x is fixed" : Always Disabled
96+
D:\example\Program.cs(14): "#if DEBUG" : Always Disabled
97+
```
98+
99+
Voilà.
100+
101+
You can also provide specific values for preprocessor expressions using `/define`, `/disable` and `/ignore`. For example,
102+
```
103+
> deadregions .\example.csproj /print /disable ZERO
104+
...
105+
D:\example\Program.cs(8): "#if ZERO // TODO(somebody): Re-enable this when x is fixed" : Always Disabled
106+
...
107+
```
108+
109+
## Remove all unnecessary regions in a project
110+
111+
When you're ready to make edits to your source files based on the output of analysis (or you're using version control and you'd like to hurry up and produce a diff already), pass `/edit`
112+
113+
`> deadregions.exe example.csproj /disable ZERO /edit`
114+
115+
In my example, if I analyze the project again, I'm only left with varying regions as expected.
116+
117+
```
118+
> deadregions .\example.csproj /print
119+
D:\example\Program.cs(5): "#if DEBUG" : Varying
120+
Conditional Regions
121+
1 found in total
122+
1 varying
123+
124+
Symbols
125+
0 unique symbol(s) specified:
126+
1 unique symbol(s) visited: DEBUG
127+
0 specified symbol(s) unvisited:
128+
```
129+
130+
## Remove all unnecessary regions conditioned with "#if false"
131+
132+
Since you can override how literal preprocessor expressions evaluate, you can also use a similar command to remove all unnecessary regions conditioned with "#if false"
133+
134+
`> deadregions example.csproj /disable false /edit`
135+
136+
## Analyze a project with many different build configurations
137+
138+
If you're working with a large codebase with many different build configurations (and sets of preprocessor symbols), chances are you won't have an easy time figuring out or specifying the values for all those symbols by hand. Enter the `/config` switch: you can use this switch to specify each of your build configurations in their entirety, and the tool will evaluate each preprocessor expression in the context of each build configuration to determine the state of each conditional region.
139+
140+
`> deadregions hugecodebase.csproj /config A;B;C /config A;D;E;F;DEBUG /config EXPENSIVE_LOGGING;D;E`
141+
142+
By combining this with explicit specification of symbol values (maybe you have some build configurations which are only run by certain parts of a larger team so you don't know the whole of those configurations but you know the symbols involved), you should be able to pinpoint the set of symbols and conditional regions you care about.
143+
144+
## Use a response file to avoid a long command line
145+
146+
Since such command lines can get relatively long, it may be useful to specify options using a *response file*.
147+
148+
`> deadregions hugecodebase.csproj @hugecodebase.rsp`
149+
150+
where the file `hugecodebase.rsp` contains
151+
152+
`/config A;B;C /config A;D;E;F;DEBUG /config EXPENSIVE_LOGGING;D;E`
153+
154+
etc.

src/DeadRegions/DeadRegions.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<OutputType>Exe</OutputType>
77
<AppDesignerFolder>Properties</AppDesignerFolder>
88
<RootNamespace>DeadRegions</RootNamespace>
9-
<AssemblyName>DeadRegions</AssemblyName>
9+
<AssemblyName>deadregions</AssemblyName>
1010
</PropertyGroup>
1111
<!-- Default configurations to help VS understand -->
1212
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

src/DeadRegions/Program.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ public static int Main(string[] args)
144144
private static void PrintUsage()
145145
{
146146
Console.WriteLine(
147-
@"
148-
SYNTAX
147+
@"SYNTAX
149148
DeadRegions [<project> ...] [options]
150149
DeadRegions [<source file> ...] [options]
151150
");

0 commit comments

Comments
 (0)