CSharpParseOptions.cs 9.0 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)
G
gafter 已提交
51
            : this(languageVersion, documentationMode, kind, preprocessorSymbols.ToImmutableArrayOrEmpty())
P
Pilchie 已提交
52
        {
N
Neal Gafter 已提交
53
            // We test the mapped value, LanguageVersion, rather than the parameter, languageVersion,
54
            // which has not had "Latest" mapped to the latest version yet.
55
            if (!LanguageVersion.IsValid())
P
Pilchie 已提交
56
            {
57
                throw new ArgumentOutOfRangeException(nameof(languageVersion));
P
Pilchie 已提交
58 59 60 61
            }

            if (!kind.IsValid())
            {
62
                throw new ArgumentOutOfRangeException(nameof(kind));
P
Pilchie 已提交
63 64
            }

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

77 78 79 80 81 82 83 84 85 86 87 88 89
        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 已提交
90
            _features = features;
91 92
        }

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

P
Pilchie 已提交
102 103 104 105 106
        // No validation
        internal CSharpParseOptions(
            LanguageVersion languageVersion,
            DocumentationMode documentationMode,
            SourceCodeKind kind,
107
            ImmutableArray<string> preprocessorSymbols)
P
Pilchie 已提交
108 109 110
            : base(kind, documentationMode)
        {
            Debug.Assert(!preprocessorSymbols.IsDefault);
G
gafter 已提交
111 112
            this.SpecifiedLanguageVersion = languageVersion;
            this.LanguageVersion = languageVersion.MapSpecifiedToEffectiveVersion();
P
Pilchie 已提交
113
            this.PreprocessorSymbols = preprocessorSymbols;
J
Jared Parsons 已提交
114
            _features = ImmutableDictionary<string, string>.Empty;
P
Pilchie 已提交
115 116
        }

117 118
        public override string Language => LanguageNames.CSharp;

C
Charles Stoner 已提交
119
        public new CSharpParseOptions WithKind(SourceCodeKind kind)
P
Pilchie 已提交
120 121 122 123 124 125 126 127
        {
            if (kind == this.Kind)
            {
                return this;
            }

            if (!kind.IsValid())
            {
128
                throw new ArgumentOutOfRangeException(nameof(kind));
P
Pilchie 已提交
129 130
            }

131
            return new CSharpParseOptions(this) { Kind = kind };
P
Pilchie 已提交
132 133 134 135
        }

        public CSharpParseOptions WithLanguageVersion(LanguageVersion version)
        {
G
gafter 已提交
136
            if (version == this.SpecifiedLanguageVersion)
P
Pilchie 已提交
137 138 139 140
            {
                return this;
            }

G
gafter 已提交
141 142
            var effectiveLanguageVersion = version.MapSpecifiedToEffectiveVersion();
            if (!effectiveLanguageVersion.IsValid())
P
Pilchie 已提交
143
            {
144
                throw new ArgumentOutOfRangeException(nameof(version));
P
Pilchie 已提交
145 146
            }

G
gafter 已提交
147
            return new CSharpParseOptions(this) { SpecifiedLanguageVersion = version, LanguageVersion = effectiveLanguageVersion };
P
Pilchie 已提交
148 149 150 151 152 153 154 155 156
        }

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

        public CSharpParseOptions WithPreprocessorSymbols(params string[] preprocessorSymbols)
        {
157
            return WithPreprocessorSymbols(ImmutableArray.Create(preprocessorSymbols));
P
Pilchie 已提交
158 159 160 161 162 163 164 165 166 167 168 169 170 171
        }

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

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

172
            return new CSharpParseOptions(this) { PreprocessorSymbols = symbols };
P
Pilchie 已提交
173 174 175 176 177 178 179 180 181 182 183
        }

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

            if (!documentationMode.IsValid())
            {
184
                throw new ArgumentOutOfRangeException(nameof(documentationMode));
P
Pilchie 已提交
185 186
            }

187 188 189
            return new CSharpParseOptions(this) { DocumentationMode = documentationMode };
        }

C
Charles Stoner 已提交
190
        public override ParseOptions CommonWithKind(SourceCodeKind kind)
191 192 193 194 195 196 197
        {
            return WithKind(kind);
        }

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

N
nmgafter 已提交
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
        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));
            }

215
            return new CSharpParseOptions(this) { _features = features.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase) };
N
nmgafter 已提交
216 217 218 219 220 221
        }

        public override IReadOnlyDictionary<string, string> Features
        {
            get
            {
222
                return _features;
N
nmgafter 已提交
223 224 225
            }
        }

226 227
        internal bool IsFeatureEnabled(MessageID feature)
        {
228 229 230 231 232
            string featureFlag = feature.RequiredFeature();
            if (featureFlag != null)
            {
                return Features.ContainsKey(featureFlag);
            }
233 234 235 236 237
            LanguageVersion availableVersion = LanguageVersion;
            LanguageVersion requiredVersion = feature.RequiredVersion();
            return availableVersion >= requiredVersion;
        }

P
Pilchie 已提交
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
        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 已提交
255
            return this.SpecifiedLanguageVersion == other.SpecifiedLanguageVersion;
P
Pilchie 已提交
256 257 258 259 260 261
        }

        public override int GetHashCode()
        {
            return
                Hash.Combine(base.GetHashCodeHelper(),
G
gafter 已提交
262
                Hash.Combine((int)this.SpecifiedLanguageVersion, 0));
P
Pilchie 已提交
263 264
        }
    }
265
}