CSharpParseOptions.cs 9.2 KB
Newer Older
1
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.
P
Pilchie 已提交
2 3 4 5 6 7 8 9 10 11 12 13

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp
{
    /// <summary>
    /// This class stores several source parsing related options and offers access to their values.
    /// </summary>
14
    public sealed class CSharpParseOptions : ParseOptions, IEquatable<CSharpParseOptions>
P
Pilchie 已提交
15 16 17 18
    {
        /// <summary>
        /// The default parse options.
        /// </summary>
19
        public static CSharpParseOptions Default { get; } = new CSharpParseOptions();
P
Pilchie 已提交
20

21 22
        private ImmutableDictionary<string, string> _features;

P
Pilchie 已提交
23
        /// <summary>
24 25
        /// Gets the effective language version, which the compiler uses to select the
        /// language rules to apply to the program.
P
Pilchie 已提交
26
        /// </summary>
27
        public LanguageVersion LanguageVersion { get; private set; }
P
Pilchie 已提交
28

G
gafter 已提交
29
        /// <summary>
30 31 32
        /// Gets the specified language version, which is the value that was specified in
        /// the call to the constructor, or modified using the <see cref="WithLanguageVersion"/> method,
        /// or provided on the command line.
G
gafter 已提交
33 34 35
        /// </summary>
        public LanguageVersion SpecifiedLanguageVersion { get; private set; }

36
        internal ImmutableArray<string> PreprocessorSymbols { get; private set; }
P
Pilchie 已提交
37 38 39 40 41 42 43 44 45 46

        /// <summary>
        /// Gets the names of defined preprocessor symbols.
        /// </summary>
        public override IEnumerable<string> PreprocessorSymbolNames
        {
            get { return PreprocessorSymbols; }
        }

        public CSharpParseOptions(
G
gafter 已提交
47
            LanguageVersion languageVersion = LanguageVersion.Default,
P
Pilchie 已提交
48 49
            DocumentationMode documentationMode = DocumentationMode.Parse,
            SourceCodeKind kind = SourceCodeKind.Regular,
50
            IEnumerable<string> preprocessorSymbols = null)
51 52 53 54 55
            : this(languageVersion, 
                  documentationMode, 
                  kind, 
                  preprocessorSymbols.ToImmutableArrayOrEmpty(), 
                  ImmutableDictionary<string, string>.Empty)
P
Pilchie 已提交
56
        {
N
Neal Gafter 已提交
57
            // We test the mapped value, LanguageVersion, rather than the parameter, languageVersion,
58
            // which has not had "Latest" mapped to the latest version yet.
59
            if (!LanguageVersion.IsValid())
P
Pilchie 已提交
60
            {
61
                throw new ArgumentOutOfRangeException(nameof(languageVersion));
P
Pilchie 已提交
62 63 64 65
            }

            if (!kind.IsValid())
            {
66
                throw new ArgumentOutOfRangeException(nameof(kind));
P
Pilchie 已提交
67 68
            }

69
            if (preprocessorSymbols != null)
P
Pilchie 已提交
70 71 72 73 74
            {
                foreach (var preprocessorSymbol in preprocessorSymbols)
                {
                    if (!SyntaxFacts.IsValidIdentifier(preprocessorSymbol))
                    {
75
                        throw new ArgumentException(nameof(preprocessorSymbol));
P
Pilchie 已提交
76 77 78 79 80
                    }
                }
            }
        }

81 82 83 84 85 86 87 88 89 90 91 92 93
        internal CSharpParseOptions(
            LanguageVersion languageVersion,
            DocumentationMode documentationMode,
            SourceCodeKind kind,
            IEnumerable<string> preprocessorSymbols,
            ImmutableDictionary<string, string> features)
            : this(languageVersion, documentationMode, kind, preprocessorSymbols)
        {
            if (features == null)
            {
                throw new ArgumentNullException(nameof(features));
            }

J
Jared Parsons 已提交
94
            _features = features;
95 96
        }

97
        private CSharpParseOptions(CSharpParseOptions other) : this(
G
gafter 已提交
98
            languageVersion: other.SpecifiedLanguageVersion,
99 100
            documentationMode: other.DocumentationMode,
            kind: other.Kind,
A
Andy Gocke 已提交
101 102
            preprocessorSymbols: other.PreprocessorSymbols,
            features: other.Features.ToImmutableDictionary())
103 104 105
        {
        }

P
Pilchie 已提交
106
        // No validation
107
        private CSharpParseOptions(
P
Pilchie 已提交
108 109 110
            LanguageVersion languageVersion,
            DocumentationMode documentationMode,
            SourceCodeKind kind,
111 112
            ImmutableArray<string> preprocessorSymbols,
            ImmutableDictionary<string, string> features)
P
Pilchie 已提交
113 114 115
            : base(kind, documentationMode)
        {
            Debug.Assert(!preprocessorSymbols.IsDefault);
G
gafter 已提交
116 117
            this.SpecifiedLanguageVersion = languageVersion;
            this.LanguageVersion = languageVersion.MapSpecifiedToEffectiveVersion();
P
Pilchie 已提交
118
            this.PreprocessorSymbols = preprocessorSymbols;
119
            _features = features;
P
Pilchie 已提交
120 121
        }

122 123
        public override string Language => LanguageNames.CSharp;

C
Charles Stoner 已提交
124
        public new CSharpParseOptions WithKind(SourceCodeKind kind)
P
Pilchie 已提交
125 126 127 128 129 130 131 132
        {
            if (kind == this.Kind)
            {
                return this;
            }

            if (!kind.IsValid())
            {
133
                throw new ArgumentOutOfRangeException(nameof(kind));
P
Pilchie 已提交
134 135
            }

136
            return new CSharpParseOptions(this) { Kind = kind };
P
Pilchie 已提交
137 138 139 140
        }

        public CSharpParseOptions WithLanguageVersion(LanguageVersion version)
        {
G
gafter 已提交
141
            if (version == this.SpecifiedLanguageVersion)
P
Pilchie 已提交
142 143 144 145
            {
                return this;
            }

G
gafter 已提交
146 147
            var effectiveLanguageVersion = version.MapSpecifiedToEffectiveVersion();
            if (!effectiveLanguageVersion.IsValid())
P
Pilchie 已提交
148
            {
149
                throw new ArgumentOutOfRangeException(nameof(version));
P
Pilchie 已提交
150 151
            }

G
gafter 已提交
152
            return new CSharpParseOptions(this) { SpecifiedLanguageVersion = version, LanguageVersion = effectiveLanguageVersion };
P
Pilchie 已提交
153 154 155 156 157 158 159 160 161
        }

        public CSharpParseOptions WithPreprocessorSymbols(IEnumerable<string> preprocessorSymbols)
        {
            return WithPreprocessorSymbols(preprocessorSymbols.AsImmutableOrNull());
        }

        public CSharpParseOptions WithPreprocessorSymbols(params string[] preprocessorSymbols)
        {
162
            return WithPreprocessorSymbols(ImmutableArray.Create(preprocessorSymbols));
P
Pilchie 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175 176
        }

        public CSharpParseOptions WithPreprocessorSymbols(ImmutableArray<string> symbols)
        {
            if (symbols.IsDefault)
            {
                symbols = ImmutableArray<string>.Empty;
            }

            if (symbols.Equals(this.PreprocessorSymbols))
            {
                return this;
            }

177
            return new CSharpParseOptions(this) { PreprocessorSymbols = symbols };
P
Pilchie 已提交
178 179 180 181 182 183 184 185 186 187 188
        }

        public new CSharpParseOptions WithDocumentationMode(DocumentationMode documentationMode)
        {
            if (documentationMode == this.DocumentationMode)
            {
                return this;
            }

            if (!documentationMode.IsValid())
            {
189
                throw new ArgumentOutOfRangeException(nameof(documentationMode));
P
Pilchie 已提交
190 191
            }

192 193 194
            return new CSharpParseOptions(this) { DocumentationMode = documentationMode };
        }

C
Charles Stoner 已提交
195
        public override ParseOptions CommonWithKind(SourceCodeKind kind)
196 197 198 199 200 201 202
        {
            return WithKind(kind);
        }

        protected override ParseOptions CommonWithDocumentationMode(DocumentationMode documentationMode)
        {
            return WithDocumentationMode(documentationMode);
P
Pilchie 已提交
203 204
        }

N
nmgafter 已提交
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
        protected override ParseOptions CommonWithFeatures(IEnumerable<KeyValuePair<string, string>> features)
        {
            return WithFeatures(features);
        }

        /// <summary>
        /// Enable some experimental language features for testing.
        /// </summary>
        public new CSharpParseOptions WithFeatures(IEnumerable<KeyValuePair<string, string>> features)
        {
            if (features == null)
            {
                throw new ArgumentNullException(nameof(features));
            }

220
            return new CSharpParseOptions(this) { _features = features.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase) };
N
nmgafter 已提交
221 222 223 224 225 226
        }

        public override IReadOnlyDictionary<string, string> Features
        {
            get
            {
227
                return _features;
N
nmgafter 已提交
228 229 230
            }
        }

231 232
        internal bool IsFeatureEnabled(MessageID feature)
        {
233 234 235 236 237
            string featureFlag = feature.RequiredFeature();
            if (featureFlag != null)
            {
                return Features.ContainsKey(featureFlag);
            }
238 239 240 241 242
            LanguageVersion availableVersion = LanguageVersion;
            LanguageVersion requiredVersion = feature.RequiredVersion();
            return availableVersion >= requiredVersion;
        }

P
Pilchie 已提交
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
        public override bool Equals(object obj)
        {
            return this.Equals(obj as CSharpParseOptions);
        }

        public bool Equals(CSharpParseOptions other)
        {
            if (object.ReferenceEquals(this, other))
            {
                return true;
            }

            if (!base.EqualsHelper(other))
            {
                return false;
            }

G
gafter 已提交
260
            return this.SpecifiedLanguageVersion == other.SpecifiedLanguageVersion;
P
Pilchie 已提交
261 262 263 264 265 266
        }

        public override int GetHashCode()
        {
            return
                Hash.Combine(base.GetHashCodeHelper(),
G
gafter 已提交
267
                Hash.Combine((int)this.SpecifiedLanguageVersion, 0));
P
Pilchie 已提交
268 269
        }
    }
270
}