1 // Copyright (c) Microsoft. All rights reserved.
2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 //-----------------------------------------------------------------------
4 // </copyright>
5 // <summary> Tool switch description class for DataDriven tasks. </summary>
6 //-----------------------------------------------------------------------
7 
8 using System;
9 using System.Collections;
10 using System.Collections.Generic;
11 using System.Text;
12 using Microsoft.Build.Framework;
13 using Microsoft.Build.Shared;
14 
15 namespace Microsoft.Build.Tasks.Xaml
16 {
17     /// <summary>
18     /// This enumeration specifies the different types for each switch in a tool
19     /// The types are used in the documentation
20     /// </summary>
21     public enum CommandLineToolSwitchType
22     {
23         /// <summary>
24         /// The boolean type has a boolean value, and there are types: one that can have a flag appended on the end
25         /// and one that can't
26         /// e.g. GlobalOptimizations = "true" would be /Og, and GlobalOptimizations="false" would be /Og-, but
27         /// WarnAsError = "true" would be /WX, while WarnAsError = "false" would be nothing.
28         /// </summary>
29         Boolean = 0,
30 
31         /// <summary>
32         /// The integer switch is used for properties that have several different integer values,
33         /// and depending on the value the property is set to, appends an integer to the end
34         /// of a certain switch
35         /// e.g. WarningLevel = "0" is /W0, WarningLevel = "2" is /W2
36         /// </summary>
37         Integer = 1,
38 
39         /// <summary>
40         /// The string switch is used for two kinds of properties.
41         /// The first is the kind that has multiple values, and has a different switch for each value
42         /// e.g. Optimization="disabled" is /Od, "Full" is /Ox
43         /// The second is the kind that has a literal string appended to the end of a switch.
44         /// This type is similar to the File type, but in this case, will never get quoted.
45         /// </summary>
46         String = 2,
47 
48         /// <summary>
49         /// The stringarray switch is used for properties that may have more
50         /// than one string appended to the end of the switch
51         /// e.g. InjectPrecompiledHeaderReference = myfile is /Ylmyfile
52         /// </summary>
53         StringArray = 3,
54 
55         /// <summary>
56         /// The ITaskItemArray type is used for properties that pass multiple files, but
57         /// want to keep the metadata. Otherwise, it is used in the same way as a StringArray type.
58         /// </summary>
59         ITaskItemArray = 4,
60     }
61 
62     /// <summary>
63     /// The class CommandLineToolSwitch holds information about the properties
64     /// for each task
65     /// </summary>
66     public class CommandLineToolSwitch
67     {
68         #region Constant strings
69 
70         /// <summary>
71         /// Boolean switch type
72         /// </summary>
73         private const string TypeBoolean = "CommandLineToolSwitchType.Boolean";
74 
75         /// <summary>
76         /// Integer switch type
77         /// </summary>
78         private const string TypeInteger = "CommandLineToolSwitchType.Integer";
79 
80         /// <summary>
81         /// ITaskItem switch type
82         /// </summary>
83         private const string TypeITaskItem = "CommandLineToolSwitchType.ITaskItem";
84 
85         /// <summary>
86         /// ITaskItemArray switch type.
87         /// </summary>
88         private const string TypeITaskItemArray = "CommandLineToolSwitchType.ITaskItemArray";
89 
90         /// <summary>
91         /// String array switch type.
92         /// </summary>
93         private const string TypeStringArray = "CommandLineToolSwitchType.StringArray";
94 
95         #endregion
96 
97         /// <summary>
98         /// The name of the switch.
99         /// </summary>
100         private string _name = String.Empty;
101 
102         /// <summary>
103         /// The switch type
104         /// </summary>
105         private CommandLineToolSwitchType _type;
106 
107         /// <summary>
108         /// "true" if this should be emitted on the command line.
109         /// </summary>
110         private bool _includeInCommandLine;
111 
112         /// <summary>
113         /// The suffix to use when the switch is false/negated.
114         /// </summary>
115         private string _falseSuffix = String.Empty;
116 
117         /// <summary>
118         /// The suffix to use when the switch is true.
119         /// </summary>
120         private string _trueSuffix = String.Empty;
121 
122         /// <summary>
123         /// The separator to use between the switch name and its parameters.
124         /// </summary>
125         private string _separator = String.Empty;
126 
127         /// <summary>
128         /// The fallback parameter.
129         /// </summary>
130         private string _fallback = String.Empty;
131 
132         /// <summary>
133         /// Flag indicating if the switch is required.
134         /// </summary>
135         private bool _required;
136 
137         /// <summary>
138         /// Parents for the switch.
139         /// </summary>
140         private LinkedList<string> _parents = new LinkedList<string>();
141 
142         /// <summary>
143         /// Overrides for the switch.
144         /// </summary>
145         private LinkedList<KeyValuePair<string, string>> _overrides = new LinkedList<KeyValuePair<string, string>>();
146 
147         /// <summary>
148         /// Flag indicating if the switch is valid.
149         /// </summary>
150         private bool _isValid;
151 
152         /// <summary>
153         /// Flag for boolean switches, indicating the switch is reversible.
154         /// </summary>
155         private bool _reversible;
156 
157         /// <summary>
158         /// Flag indicating if the switch has multiple values.
159         /// </summary>
160         private bool _allowMultipleValues;
161 
162         /// <summary>
163         /// The value for a boolean switch.
164         /// </summary>
165         private bool _booleanValue = true;
166 
167         /// <summary>
168         /// The value for the integer type.
169         /// </summary>
170         private int _number;
171 
172         /// <summary>
173         /// The list of strings for a string array.
174         /// </summary>
175         private string[] _stringList;
176 
177         /// <summary>
178         /// The list of task items for ITaskItemArray types.
179         /// </summary>
180         private ITaskItem[] _taskItemArray;
181 
182         /// <summary>
183         /// The value for a string type.
184         /// </summary>
185         private string _value = String.Empty;
186 
187         /// <summary>
188         /// The switch text.
189         /// </summary>
190         private string _switchValue = String.Empty;
191 
192         /// <summary>
193         /// The reverse switch text, for reversible switches.
194         /// </summary>
195         private string _reverseSwitchValue = String.Empty;
196 
197         /// <summary>
198         /// The arguments from which the value should be derived.
199         /// </summary>
200         private ICollection<Tuple<string, bool>> _arguments;
201 
202         /// <summary>
203         /// Thw switch description.
204         /// </summary>
205         private string _description = String.Empty;
206 
207         /// <summary>
208         /// The display name for the switch.
209         /// </summary>
210         private string _displayName = String.Empty;
211 
212         /// <summary>
213         /// The default constructor creates a new CommandLineToolSwitch to hold the name of
214         /// the tool, the attributes, the dependent switches, and the values (if they exist)
215         /// </summary>
CommandLineToolSwitch()216         public CommandLineToolSwitch()
217         {
218             // does nothing
219         }
220 
221         /// <summary>
222         /// Overloaded constructor. Takes a CommandLineToolSwitchType and sets the type.
223         /// </summary>
CommandLineToolSwitch(CommandLineToolSwitchType toolType)224         public CommandLineToolSwitch(CommandLineToolSwitchType toolType)
225         {
226             _type = toolType;
227         }
228 
229         #region Properties
230 
231         /// <summary>
232         /// The name of the parameter
233         /// </summary>
234         public string Name
235         {
236             get
237             {
238                 return _name;
239             }
240 
241             set
242             {
243                 _name = value;
244             }
245         }
246 
247         /// <summary>
248         /// Specifies if this switch should be included on the command-line.
249         /// </summary>
250         public bool IncludeInCommandLine
251         {
252             get
253             {
254                 return _includeInCommandLine;
255             }
256 
257             set
258             {
259                 _includeInCommandLine = value;
260             }
261         }
262 
263         /// <summary>
264         /// The Value of the parameter
265         /// </summary>
266         public string Value
267         {
268             get
269             {
270                 return _value;
271             }
272 
273             set
274             {
275                 _value = value;
276             }
277         }
278 
279         /// <summary>
280         /// Flag indicating if the switch is valid.
281         /// </summary>
282         public bool IsValid
283         {
284             get
285             {
286                 return _isValid;
287             }
288 
289             set
290             {
291                 _isValid = value;
292             }
293         }
294 
295         /// <summary>
296         /// The SwitchValue of the parameter
297         /// </summary>
298         public string SwitchValue
299         {
300             get
301             {
302                 return _switchValue;
303             }
304 
305             set
306             {
307                 _switchValue = value;
308             }
309         }
310 
311         /// <summary>
312         /// The SwitchValue of the parameter
313         /// </summary>
314         public string ReverseSwitchValue
315         {
316             get
317             {
318                 return _reverseSwitchValue;
319             }
320 
321             set
322             {
323                 _reverseSwitchValue = value;
324             }
325         }
326 
327         /// <summary>
328         /// The arguments.
329         /// </summary>
330         public ICollection<Tuple<string, bool>> Arguments
331         {
332             get
333             {
334                 return _arguments;
335             }
336 
337             set
338             {
339                 _arguments = value;
340             }
341         }
342 
343         /// <summary>
344         /// The DisplayName of the parameter
345         /// </summary>
346         public string DisplayName
347         {
348             get
349             {
350                 return _displayName;
351             }
352 
353             set
354             {
355                 _displayName = value;
356             }
357         }
358 
359         /// <summary>
360         /// The Description of the parameter
361         /// </summary>
362         public string Description
363         {
364             get
365             {
366                 return _description;
367             }
368 
369             set
370             {
371                 _description = value;
372             }
373         }
374 
375         /// <summary>
376         /// The type of the switch, i.e., boolean, string, stringarray, etc.
377         /// </summary>
378         public CommandLineToolSwitchType Type
379         {
380             get
381             {
382                 return _type;
383             }
384 
385             set
386             {
387                 _type = value;
388             }
389         }
390 
391         /// <summary>
392         /// Indicates whether or not the switch is emitted with a flag when false
393         /// </summary>
394         public bool Reversible
395         {
396             get
397             {
398                 return _reversible;
399             }
400 
401             set
402             {
403                 _reversible = value;
404             }
405         }
406 
407         /// <summary>
408         /// True if multiple values are allowed.
409         /// </summary>
410         public bool AllowMultipleValues
411         {
412             get
413             {
414                 return _allowMultipleValues;
415             }
416 
417             set
418             {
419                 _allowMultipleValues = value;
420             }
421         }
422 
423         /// <summary>
424         /// The flag to append at the end of a switch when the switch is set to false
425         /// i.e., for all CL switches that are reversible, the FalseSuffix is "-"
426         /// </summary>
427         public string FalseSuffix
428         {
429             get
430             {
431                 return _falseSuffix;
432             }
433 
434             set
435             {
436                 _falseSuffix = value;
437             }
438         }
439 
440         /// <summary>
441         /// The flag to append to the end of the switch when that switch is true
442         /// i.e., In the OptimizeForWindows98, the switch is OPT, the FalseSuffix is
443         /// :NOWIN98, and the TrueSuffix is :WIN98
444         /// </summary>
445         public string TrueSuffix
446         {
447             get
448             {
449                 return _trueSuffix;
450             }
451 
452             set
453             {
454                 _trueSuffix = value;
455             }
456         }
457 
458         /// <summary>
459         /// The separator indicates the characters that go between the switch and the string
460         /// in the string typed case, the characters that go between each name for the
461         /// string array case, or the characters that go between the switch and the
462         /// appendage for the boolean case.
463         /// </summary>
464         public string Separator
465         {
466             get
467             {
468                 return _separator;
469             }
470 
471             set
472             {
473                 _separator = value;
474             }
475         }
476 
477         /// <summary>
478         /// The Fallback attribute is used to specify which property to look at in the
479         /// case that the argument property is not set, or if the file that the
480         /// argument property indicates is nonexistent.
481         /// </summary>
482         public string FallbackArgumentParameter
483         {
484             get
485             {
486                 return _fallback;
487             }
488 
489             set
490             {
491                 _fallback = value;
492             }
493         }
494 
495         /// <summary>
496         /// This attribute specifies whether or not an argument attribute is required.
497         /// </summary>
498         public bool ArgumentRequired
499         {
500             get;
501             set;
502         }
503 
504         /// <summary>
505         /// This property indicates whether or not the property is required in the project file
506         /// </summary>
507         public bool Required
508         {
509             get
510             {
511                 return _required;
512             }
513 
514             set
515             {
516                 _required = value;
517             }
518         }
519 
520         /// <summary>
521         /// This property indicates the parent of the dependency
522         /// </summary>
523         public LinkedList<string> Parents
524         {
525             get
526             {
527                 return _parents;
528             }
529         }
530 
531         /// <summary>
532         /// This property indicates the parent of the dependency
533         /// </summary>
534         public LinkedList<KeyValuePair<string, string>> Overrides
535         {
536             get
537             {
538                 return _overrides;
539             }
540         }
541 
542         /// <summary>
543         /// The BooleanValue is used for the boolean switches, and are set to true
544         /// or false, depending on what you set it to.
545         /// </summary>
546         public bool BooleanValue
547         {
548             get
549             {
550                 ErrorUtilities.VerifyThrow(_type == CommandLineToolSwitchType.Boolean, "InvalidType", TypeBoolean);
551                 return _booleanValue;
552             }
553 
554             set
555             {
556                 ErrorUtilities.VerifyThrow(_type == CommandLineToolSwitchType.Boolean, "InvalidType", TypeBoolean);
557                 _booleanValue = value;
558             }
559         }
560 
561         /// <summary>
562         /// The number is the number you wish to append to the end of integer switches
563         /// </summary>
564         public int Number
565         {
566             get
567             {
568                 ErrorUtilities.VerifyThrow(_type == CommandLineToolSwitchType.Integer, "InvalidType", TypeInteger);
569                 return _number;
570             }
571 
572             set
573             {
574                 ErrorUtilities.VerifyThrow(_type == CommandLineToolSwitchType.Integer, "InvalidType", TypeInteger);
575                 _number = value;
576             }
577         }
578 
579         /// <summary>
580         /// Returns the set of inputs to a switch
581         /// </summary>
582         /// <returns></returns>
583         public string[] StringList
584         {
585             get
586             {
587                 ErrorUtilities.VerifyThrow(_type == CommandLineToolSwitchType.StringArray, "InvalidType", TypeStringArray);
588                 return _stringList;
589             }
590 
591             set
592             {
593                 ErrorUtilities.VerifyThrow(_type == CommandLineToolSwitchType.StringArray, "InvalidType", TypeStringArray);
594                 _stringList = value;
595             }
596         }
597 
598         /// <summary>
599         /// Returns the set of inputs to a switch that is a set of ITaskItems
600         /// </summary>
601         /// <returns></returns>
602         public ITaskItem[] TaskItemArray
603         {
604             get
605             {
606                 ErrorUtilities.VerifyThrow(_type == CommandLineToolSwitchType.ITaskItemArray, "InvalidType", TypeITaskItemArray);
607                 return _taskItemArray;
608             }
609 
610             set
611             {
612                 ErrorUtilities.VerifyThrow(_type == CommandLineToolSwitchType.ITaskItemArray, "InvalidType", TypeITaskItemArray);
613                 _taskItemArray = value;
614             }
615         }
616         #endregion
617     }
618 
619     /// <summary>
620     /// Expresses a relationship between an argument and a property.
621     /// </summary>
622     public class PropertyRelation
623     {
624         /// <summary>
625         /// Constructor
626         /// </summary>
PropertyRelation()627         public PropertyRelation()
628         {
629         }
630 
631         /// <summary>
632         /// Constructor.
633         /// </summary>
PropertyRelation(string argument, string value, bool required)634         public PropertyRelation(string argument, string value, bool required)
635         {
636             this.Argument = argument;
637             this.Value = value;
638             this.Required = required;
639         }
640 
641         /// <summary>
642         /// The name of the argument
643         /// </summary>
644         public string Argument
645         {
646             get;
647             set;
648         }
649 
650         /// <summary>
651         /// The value.
652         /// </summary>
653         public string Value
654         {
655             get;
656             set;
657         }
658 
659         /// <summary>
660         /// Flag indicating if the argument is required or not.
661         /// </summary>
662         public bool Required
663         {
664             get;
665             set;
666         }
667     }
668 
669     /// <summary>
670     /// Derived class indicating how to separate values from the specified argument.
671     /// </summary>
672     public class CommandLineArgumentRelation : PropertyRelation
673     {
674         /// <summary>
675         /// Constructor.
676         /// </summary>
CommandLineArgumentRelation(string argument, string value, bool required, string separator)677         public CommandLineArgumentRelation(string argument, string value, bool required, string separator)
678             : base(argument, value, required)
679         {
680             this.Separator = separator;
681         }
682 
683         /// <summary>
684         /// The separator.
685         /// </summary>
686         public string Separator
687         {
688             get;
689             set;
690         }
691     }
692 }
693