CSharpParseOptions.cs 8.7 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>
G
gafter 已提交
24
        /// Gets the effective language version.
P
Pilchie 已提交
25
        /// </summary>
26
        public LanguageVersion LanguageVersion { get; private set; }
P
Pilchie 已提交
27

G
gafter 已提交
28 29 30 31 32
        /// <summary>
        /// Gets the specified language version.
        /// </summary>
        public LanguageVersion SpecifiedLanguageVersion { get; private set; }

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

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

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

            if (!kind.IsValid())
            {
59
                throw new ArgumentOutOfRangeException(nameof(kind));
P
Pilchie 已提交
60 61
            }

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

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

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

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

C
Charles Stoner 已提交
114
        public new CSharpParseOptions WithKind(SourceCodeKind kind)
P
Pilchie 已提交
115 116 117 118 119 120 121 122
        {
            if (kind == this.Kind)
            {
                return this;
            }

            if (!kind.IsValid())
            {
123
                throw new ArgumentOutOfRangeException(nameof(kind));
P
Pilchie 已提交
124 125
            }

126
            return new CSharpParseOptions(this) { Kind = kind };
P
Pilchie 已提交
127 128 129 130
        }

        public CSharpParseOptions WithLanguageVersion(LanguageVersion version)
        {
G
gafter 已提交
131
            if (version == this.SpecifiedLanguageVersion)
P
Pilchie 已提交
132 133 134 135
            {
                return this;
            }

G
gafter 已提交
136 137
            var effectiveLanguageVersion = version.MapSpecifiedToEffectiveVersion();
            if (!effectiveLanguageVersion.IsValid())
P
Pilchie 已提交
138
            {
139
                throw new ArgumentOutOfRangeException(nameof(version));
P
Pilchie 已提交
140 141
            }

G
gafter 已提交
142
            return new CSharpParseOptions(this) { SpecifiedLanguageVersion = version, LanguageVersion = effectiveLanguageVersion };
P
Pilchie 已提交
143 144 145 146 147 148 149 150 151
        }

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

        public CSharpParseOptions WithPreprocessorSymbols(params string[] preprocessorSymbols)
        {
152
            return WithPreprocessorSymbols(ImmutableArray.Create(preprocessorSymbols));
P
Pilchie 已提交
153 154 155 156 157 158 159 160 161 162 163 164 165 166
        }

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

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

167
            return new CSharpParseOptions(this) { PreprocessorSymbols = symbols };
P
Pilchie 已提交
168 169 170 171 172 173 174 175 176 177 178
        }

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

            if (!documentationMode.IsValid())
            {
179
                throw new ArgumentOutOfRangeException(nameof(documentationMode));
P
Pilchie 已提交
180 181
            }

182 183 184
            return new CSharpParseOptions(this) { DocumentationMode = documentationMode };
        }

C
Charles Stoner 已提交
185
        public override ParseOptions CommonWithKind(SourceCodeKind kind)
186 187 188 189 190 191 192
        {
            return WithKind(kind);
        }

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

N
nmgafter 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
        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));
            }

210
            return new CSharpParseOptions(this) { _features = features.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase) };
N
nmgafter 已提交
211 212 213 214 215 216
        }

        public override IReadOnlyDictionary<string, string> Features
        {
            get
            {
217
                return _features;
N
nmgafter 已提交
218 219 220
            }
        }

221 222
        internal bool IsFeatureEnabled(MessageID feature)
        {
223 224 225 226 227
            string featureFlag = feature.RequiredFeature();
            if (featureFlag != null)
            {
                return Features.ContainsKey(featureFlag);
            }
228 229 230 231 232
            LanguageVersion availableVersion = LanguageVersion;
            LanguageVersion requiredVersion = feature.RequiredVersion();
            return availableVersion >= requiredVersion;
        }

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

        public override int GetHashCode()
        {
            return
                Hash.Combine(base.GetHashCodeHelper(),
G
gafter 已提交
257
                Hash.Combine((int)this.SpecifiedLanguageVersion, 0));
P
Pilchie 已提交
258 259
        }
    }
260
}