diff --git a/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs b/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs index 04dec11e75..2897d7fab2 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs @@ -73,7 +73,7 @@ namespace ICSharpCode.NRefactory.CSharp /// This is the only way to get an expression that isn't part of a statment. /// (eg. when an error follows an expression). /// - /// This is used for code completion to 'get the expression before a token - like ., <, ('. + /// This is used for code completion to 'get the expression before a token - like ., <, ('. /// public AstNode TopExpression { get; @@ -136,33 +136,25 @@ namespace ICSharpCode.NRefactory.CSharp public static CompilationUnit Parse (string text, string fileName = "", CompilerSettings settings = null, CancellationToken cancellationToken = default (CancellationToken)) { - var parser = new CSharpParser (); - if (settings != null) - parser.CompilerSettings = settings; + var parser = new CSharpParser (settings); return parser.Parse (text, fileName); } public static CompilationUnit Parse (TextReader reader, string fileName = "", CompilerSettings settings = null, CancellationToken cancellationToken = default (CancellationToken)) { - var parser = new CSharpParser (); - if (settings != null) - parser.CompilerSettings = settings; + var parser = new CSharpParser (settings); return parser.Parse (reader, fileName, 0); } public static CompilationUnit Parse (Stream stream, string fileName = "", CompilerSettings settings = null, CancellationToken cancellationToken = default (CancellationToken)) { - var parser = new CSharpParser (); - if (settings != null) - parser.CompilerSettings = settings; + var parser = new CSharpParser (settings); return parser.Parse (stream, fileName, 0); } public static CompilationUnit Parse (ITextSource textSource, string fileName = "", CompilerSettings settings = null, CancellationToken cancellationToken = default (CancellationToken)) { - var parser = new CSharpParser (); - if (settings != null) - parser.CompilerSettings = settings; + var parser = new CSharpParser (settings); return parser.Parse (textSource, fileName, 0); } } diff --git a/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs b/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs index b7475d4cec..44c6e22969 100644 --- a/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs +++ b/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs @@ -33,12 +33,15 @@ namespace ICSharpCode.NRefactory.CSharp string assemblyName; Dictionary parsedFiles; List assemblyReferences; + CompilerSettings compilerSettings; public CSharpProjectContent() { this.assemblyName = string.Empty; this.parsedFiles = new Dictionary(Platform.FileNameComparer); this.assemblyReferences = new List(); + this.compilerSettings = new CompilerSettings(); + compilerSettings.Freeze(); } protected CSharpProjectContent(CSharpProjectContent pc) @@ -46,6 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp this.assemblyName = pc.assemblyName; this.parsedFiles = new Dictionary(pc.parsedFiles, Platform.FileNameComparer); this.assemblyReferences = new List(pc.assemblyReferences); + this.compilerSettings = pc.compilerSettings; } public IEnumerable Files { @@ -60,6 +64,14 @@ namespace ICSharpCode.NRefactory.CSharp get { return assemblyName; } } + public CompilerSettings CompilerSettings { + get { return compilerSettings; } + } + + object IProjectContent.CompilerSettings { + get { return compilerSettings; } + } + public IEnumerable AssemblyAttributes { get { return this.Files.SelectMany(f => f.AssemblyAttributes); @@ -112,6 +124,16 @@ namespace ICSharpCode.NRefactory.CSharp return pc; } + public IProjectContent SetCompilerSettings(object compilerSettings) + { + if (!(compilerSettings is CompilerSettings)) + throw new ArgumentException("Settings must be an instance of " + typeof(CompilerSettings).FullName, "compilerSettings"); + CSharpProjectContent pc = Clone(); + pc.compilerSettings = (CompilerSettings)compilerSettings; + pc.compilerSettings.Freeze(); + return pc; + } + public IProjectContent AddAssemblyReferences(IEnumerable references) { CSharpProjectContent pc = Clone(); diff --git a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj index 82838a7b96..f82e527cf5 100644 --- a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj +++ b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj @@ -183,6 +183,7 @@ + diff --git a/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs index 3f2c274438..de60fd29e6 100644 --- a/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs @@ -36,6 +36,8 @@ namespace ICSharpCode.NRefactory.CSharp { public class CSharpParser { + CompilerSettings compilerSettings; + class ConversionVisitor : StructuralVisitor { CompilationUnit unit = new CompilationUnit (); @@ -244,12 +246,12 @@ namespace ICSharpCode.NRefactory.CSharp if (typeName is SpecialContraintExpr) { var sce = (SpecialContraintExpr)typeName; switch (sce.Constraint) { - case SpecialConstraint.Class: - return new PrimitiveType ("class", Convert (sce.Location)); - case SpecialConstraint.Struct: - return new PrimitiveType ("struct", Convert (sce.Location)); - case SpecialConstraint.Constructor: - return new PrimitiveType ("new", Convert (sce.Location)); + case SpecialConstraint.Class: + return new PrimitiveType ("class", Convert (sce.Location)); + case SpecialConstraint.Struct: + return new PrimitiveType ("struct", Convert (sce.Location)); + case SpecialConstraint.Constructor: + return new PrimitiveType ("new", Convert (sce.Location)); } } return new SimpleType ("unknown"); @@ -2182,21 +2184,21 @@ namespace ICSharpCode.NRefactory.CSharp { var result = new UnaryOperatorExpression (); switch (unaryExpression.Oper) { - case Unary.Operator.UnaryPlus: - result.Operator = UnaryOperatorType.Plus; - break; - case Unary.Operator.UnaryNegation: - result.Operator = UnaryOperatorType.Minus; - break; - case Unary.Operator.LogicalNot: - result.Operator = UnaryOperatorType.Not; - break; - case Unary.Operator.OnesComplement: - result.Operator = UnaryOperatorType.BitNot; - break; - case Unary.Operator.AddressOf: - result.Operator = UnaryOperatorType.AddressOf; - break; + case Unary.Operator.UnaryPlus: + result.Operator = UnaryOperatorType.Plus; + break; + case Unary.Operator.UnaryNegation: + result.Operator = UnaryOperatorType.Minus; + break; + case Unary.Operator.LogicalNot: + result.Operator = UnaryOperatorType.Not; + break; + case Unary.Operator.OnesComplement: + result.Operator = UnaryOperatorType.BitNot; + break; + case Unary.Operator.AddressOf: + result.Operator = UnaryOperatorType.AddressOf; + break; } result.AddChild (new CSharpTokenNode (Convert (unaryExpression.Location)), UnaryOperatorExpression.GetOperatorRole (result.Operator)); if (unaryExpression.Expr != null) @@ -2211,27 +2213,27 @@ namespace ICSharpCode.NRefactory.CSharp return result; var expression = (Expression)unaryMutatorExpression.Expr.Accept (this); switch (unaryMutatorExpression.UnaryMutatorMode) { - case UnaryMutator.Mode.PostDecrement: - result.Operator = UnaryOperatorType.PostDecrement; - result.AddChild (expression, Roles.Expression); - result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location)), UnaryOperatorExpression.DecrementRole); - break; - case UnaryMutator.Mode.PostIncrement: - result.Operator = UnaryOperatorType.PostIncrement; - result.AddChild (expression, Roles.Expression); - result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location)), UnaryOperatorExpression.IncrementRole); - break; + case UnaryMutator.Mode.PostDecrement: + result.Operator = UnaryOperatorType.PostDecrement; + result.AddChild (expression, Roles.Expression); + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location)), UnaryOperatorExpression.DecrementRole); + break; + case UnaryMutator.Mode.PostIncrement: + result.Operator = UnaryOperatorType.PostIncrement; + result.AddChild (expression, Roles.Expression); + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location)), UnaryOperatorExpression.IncrementRole); + break; - case UnaryMutator.Mode.PreIncrement: - result.Operator = UnaryOperatorType.Increment; - result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location)), UnaryOperatorExpression.IncrementRole); - result.AddChild (expression, Roles.Expression); - break; - case UnaryMutator.Mode.PreDecrement: - result.Operator = UnaryOperatorType.Decrement; - result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location)), UnaryOperatorExpression.DecrementRole); - result.AddChild (expression, Roles.Expression); - break; + case UnaryMutator.Mode.PreIncrement: + result.Operator = UnaryOperatorType.Increment; + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location)), UnaryOperatorExpression.IncrementRole); + result.AddChild (expression, Roles.Expression); + break; + case UnaryMutator.Mode.PreDecrement: + result.Operator = UnaryOperatorType.Decrement; + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location)), UnaryOperatorExpression.DecrementRole); + result.AddChild (expression, Roles.Expression); + break; } return result; @@ -2327,60 +2329,60 @@ namespace ICSharpCode.NRefactory.CSharp { var result = new BinaryOperatorExpression (); switch (binaryExpression.Oper) { - case Binary.Operator.Multiply: - result.Operator = BinaryOperatorType.Multiply; - break; - case Binary.Operator.Division: - result.Operator = BinaryOperatorType.Divide; - break; - case Binary.Operator.Modulus: - result.Operator = BinaryOperatorType.Modulus; - break; - case Binary.Operator.Addition: - result.Operator = BinaryOperatorType.Add; - break; - case Binary.Operator.Subtraction: - result.Operator = BinaryOperatorType.Subtract; - break; - case Binary.Operator.LeftShift: - result.Operator = BinaryOperatorType.ShiftLeft; - break; - case Binary.Operator.RightShift: - result.Operator = BinaryOperatorType.ShiftRight; - break; - case Binary.Operator.LessThan: - result.Operator = BinaryOperatorType.LessThan; - break; - case Binary.Operator.GreaterThan: - result.Operator = BinaryOperatorType.GreaterThan; - break; - case Binary.Operator.LessThanOrEqual: - result.Operator = BinaryOperatorType.LessThanOrEqual; - break; - case Binary.Operator.GreaterThanOrEqual: - result.Operator = BinaryOperatorType.GreaterThanOrEqual; - break; - case Binary.Operator.Equality: - result.Operator = BinaryOperatorType.Equality; - break; - case Binary.Operator.Inequality: - result.Operator = BinaryOperatorType.InEquality; - break; - case Binary.Operator.BitwiseAnd: - result.Operator = BinaryOperatorType.BitwiseAnd; - break; - case Binary.Operator.ExclusiveOr: - result.Operator = BinaryOperatorType.ExclusiveOr; - break; - case Binary.Operator.BitwiseOr: - result.Operator = BinaryOperatorType.BitwiseOr; - break; - case Binary.Operator.LogicalAnd: - result.Operator = BinaryOperatorType.ConditionalAnd; - break; - case Binary.Operator.LogicalOr: - result.Operator = BinaryOperatorType.ConditionalOr; - break; + case Binary.Operator.Multiply: + result.Operator = BinaryOperatorType.Multiply; + break; + case Binary.Operator.Division: + result.Operator = BinaryOperatorType.Divide; + break; + case Binary.Operator.Modulus: + result.Operator = BinaryOperatorType.Modulus; + break; + case Binary.Operator.Addition: + result.Operator = BinaryOperatorType.Add; + break; + case Binary.Operator.Subtraction: + result.Operator = BinaryOperatorType.Subtract; + break; + case Binary.Operator.LeftShift: + result.Operator = BinaryOperatorType.ShiftLeft; + break; + case Binary.Operator.RightShift: + result.Operator = BinaryOperatorType.ShiftRight; + break; + case Binary.Operator.LessThan: + result.Operator = BinaryOperatorType.LessThan; + break; + case Binary.Operator.GreaterThan: + result.Operator = BinaryOperatorType.GreaterThan; + break; + case Binary.Operator.LessThanOrEqual: + result.Operator = BinaryOperatorType.LessThanOrEqual; + break; + case Binary.Operator.GreaterThanOrEqual: + result.Operator = BinaryOperatorType.GreaterThanOrEqual; + break; + case Binary.Operator.Equality: + result.Operator = BinaryOperatorType.Equality; + break; + case Binary.Operator.Inequality: + result.Operator = BinaryOperatorType.InEquality; + break; + case Binary.Operator.BitwiseAnd: + result.Operator = BinaryOperatorType.BitwiseAnd; + break; + case Binary.Operator.ExclusiveOr: + result.Operator = BinaryOperatorType.ExclusiveOr; + break; + case Binary.Operator.BitwiseOr: + result.Operator = BinaryOperatorType.BitwiseOr; + break; + case Binary.Operator.LogicalAnd: + result.Operator = BinaryOperatorType.ConditionalAnd; + break; + case Binary.Operator.LogicalOr: + result.Operator = BinaryOperatorType.ConditionalOr; + break; } if (binaryExpression.Left != null) @@ -2435,29 +2437,29 @@ namespace ICSharpCode.NRefactory.CSharp ParameterDeclaration parameterDeclarationExpression = new ParameterDeclaration (); AddAttributeSection (parameterDeclarationExpression, p); switch (p.ModFlags) { - case Parameter.Modifier.OUT: - parameterDeclarationExpression.ParameterModifier = ParameterModifier.Out; - if (location != null) - parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0])), ParameterDeclaration.OutModifierRole); - break; - case Parameter.Modifier.REF: - parameterDeclarationExpression.ParameterModifier = ParameterModifier.Ref; - if (location != null) - parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0])), ParameterDeclaration.RefModifierRole); - break; - case Parameter.Modifier.PARAMS: - parameterDeclarationExpression.ParameterModifier = ParameterModifier.Params; - if (location != null) - parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0])), ParameterDeclaration.ParamsModifierRole); - break; - default: - if (p.HasExtensionMethodModifier) { - parameterDeclarationExpression.ParameterModifier = ParameterModifier.This; - if (location != null) { - parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0])), ParameterDeclaration.ThisModifierRole); + case Parameter.Modifier.OUT: + parameterDeclarationExpression.ParameterModifier = ParameterModifier.Out; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0])), ParameterDeclaration.OutModifierRole); + break; + case Parameter.Modifier.REF: + parameterDeclarationExpression.ParameterModifier = ParameterModifier.Ref; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0])), ParameterDeclaration.RefModifierRole); + break; + case Parameter.Modifier.PARAMS: + parameterDeclarationExpression.ParameterModifier = ParameterModifier.Params; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0])), ParameterDeclaration.ParamsModifierRole); + break; + default: + if (p.HasExtensionMethodModifier) { + parameterDeclarationExpression.ParameterModifier = ParameterModifier.This; + if (location != null) { + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0])), ParameterDeclaration.ThisModifierRole); + } } - } - break; + break; } if (p.TypeExpression != null) // lambdas may have no types (a, b) => ... parameterDeclarationExpression.AddChild (ConvertToType (p.TypeExpression), Roles.Type); @@ -2492,33 +2494,33 @@ namespace ICSharpCode.NRefactory.CSharp List varianceLocation; switch (arg.Variance) { - case Variance.Contravariant: - tp.Variance = VarianceModifier.Contravariant; - varianceLocation = LocationsBag.GetLocations (arg); - if (varianceLocation != null) - tp.AddChild (new CSharpTokenNode (Convert (varianceLocation [0])), TypeParameterDeclaration.InVarianceKeywordRole); - break; - case Variance.Covariant: - tp.Variance = VarianceModifier.Covariant; - varianceLocation = LocationsBag.GetLocations (arg); - if (varianceLocation != null) - tp.AddChild (new CSharpTokenNode (Convert (varianceLocation [0])), TypeParameterDeclaration.OutVarianceKeywordRole); - break; - default: - tp.Variance = VarianceModifier.Invariant; - break; - + case Variance.Contravariant: + tp.Variance = VarianceModifier.Contravariant; + varianceLocation = LocationsBag.GetLocations (arg); + if (varianceLocation != null) + tp.AddChild (new CSharpTokenNode (Convert (varianceLocation [0])), TypeParameterDeclaration.InVarianceKeywordRole); + break; + case Variance.Covariant: + tp.Variance = VarianceModifier.Covariant; + varianceLocation = LocationsBag.GetLocations (arg); + if (varianceLocation != null) + tp.AddChild (new CSharpTokenNode (Convert (varianceLocation [0])), TypeParameterDeclaration.OutVarianceKeywordRole); + break; + default: + tp.Variance = VarianceModifier.Invariant; + break; + } AddAttributeSection (tp, arg.OptAttributes); switch (arg.Variance) { - case Variance.Covariant: - tp.Variance = VarianceModifier.Covariant; - break; - case Variance.Contravariant: - tp.Variance = VarianceModifier.Contravariant; - break; + case Variance.Covariant: + tp.Variance = VarianceModifier.Covariant; + break; + case Variance.Contravariant: + tp.Variance = VarianceModifier.Contravariant; + break; } tp.AddChild (Identifier.Create (arg.Name, Convert (arg.Location)), Roles.Identifier); parent.AddChild (tp, Roles.TypeParameter); @@ -3082,36 +3084,36 @@ namespace ICSharpCode.NRefactory.CSharp { var result = new AssignmentExpression (); switch (compoundAssign.Op) { - case Binary.Operator.Multiply: - result.Operator = AssignmentOperatorType.Multiply; - break; - case Binary.Operator.Division: - result.Operator = AssignmentOperatorType.Divide; - break; - case Binary.Operator.Modulus: - result.Operator = AssignmentOperatorType.Modulus; - break; - case Binary.Operator.Addition: - result.Operator = AssignmentOperatorType.Add; - break; - case Binary.Operator.Subtraction: - result.Operator = AssignmentOperatorType.Subtract; - break; - case Binary.Operator.LeftShift: - result.Operator = AssignmentOperatorType.ShiftLeft; - break; - case Binary.Operator.RightShift: - result.Operator = AssignmentOperatorType.ShiftRight; - break; - case Binary.Operator.BitwiseAnd: - result.Operator = AssignmentOperatorType.BitwiseAnd; - break; - case Binary.Operator.BitwiseOr: - result.Operator = AssignmentOperatorType.BitwiseOr; - break; - case Binary.Operator.ExclusiveOr: - result.Operator = AssignmentOperatorType.ExclusiveOr; - break; + case Binary.Operator.Multiply: + result.Operator = AssignmentOperatorType.Multiply; + break; + case Binary.Operator.Division: + result.Operator = AssignmentOperatorType.Divide; + break; + case Binary.Operator.Modulus: + result.Operator = AssignmentOperatorType.Modulus; + break; + case Binary.Operator.Addition: + result.Operator = AssignmentOperatorType.Add; + break; + case Binary.Operator.Subtraction: + result.Operator = AssignmentOperatorType.Subtract; + break; + case Binary.Operator.LeftShift: + result.Operator = AssignmentOperatorType.ShiftLeft; + break; + case Binary.Operator.RightShift: + result.Operator = AssignmentOperatorType.ShiftRight; + break; + case Binary.Operator.BitwiseAnd: + result.Operator = AssignmentOperatorType.BitwiseAnd; + break; + case Binary.Operator.BitwiseOr: + result.Operator = AssignmentOperatorType.BitwiseOr; + break; + case Binary.Operator.ExclusiveOr: + result.Operator = AssignmentOperatorType.ExclusiveOr; + break; } if (compoundAssign.Target != null) @@ -3471,13 +3473,12 @@ namespace ICSharpCode.NRefactory.CSharp public CSharpParser () { - CompilerSettings = new CompilerSettings (); - CompilerSettings.Unsafe = true; + compilerSettings = new CompilerSettings(); } public CSharpParser (CompilerSettings args) { - CompilerSettings = args; + compilerSettings = args ?? new CompilerSettings(); } static AstNode GetOuterLeft (AstNode node) @@ -3673,8 +3674,12 @@ namespace ICSharpCode.NRefactory.CSharp } public CompilerSettings CompilerSettings { - get; - internal set; + get { return compilerSettings; } + set { + if (value == null) + throw new ArgumentNullException(); + compilerSettings = value; + } } public Action CompilationUnitCallback { @@ -3698,7 +3703,7 @@ namespace ICSharpCode.NRefactory.CSharp { lock (parseLock) { errorReportPrinter = new ErrorReportPrinter (""); - var ctx = new CompilerContext (CompilerSettings, errorReportPrinter); + var ctx = new CompilerContext (compilerSettings.ToMono(), errorReportPrinter); ctx.Settings.TabSize = 1; var reader = new SeekableStreamReader (stream, Encoding.UTF8); var file = new SourceFile (fileName, fileName, 0); diff --git a/ICSharpCode.NRefactory.CSharp/Parser/CompilerSettings.cs b/ICSharpCode.NRefactory.CSharp/Parser/CompilerSettings.cs new file mode 100644 index 0000000000..e71331e923 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Parser/CompilerSettings.cs @@ -0,0 +1,151 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// C# compiler settings. + /// + [Serializable] + public class CompilerSettings : AbstractFreezable + { + protected override void FreezeInternal() + { + conditionalSymbols = FreezableHelper.FreezeList(conditionalSymbols); + specificWarningsAsErrors = FreezableHelper.FreezeList(specificWarningsAsErrors); + disabledWarnings = FreezableHelper.FreezeList(disabledWarnings); + base.FreezeInternal(); + } + + /// + /// Creates a new CompilerSettings instance. + /// + public CompilerSettings() + { + } + + bool allowUnsafeBlocks = true; + + /// + /// Gets/Sets whether unsafe code is allowed. + /// The default is true. If set to false, parsing unsafe code will result in parser errors. + /// + public bool AllowUnsafeBlocks { + get { return allowUnsafeBlocks; } + set { + FreezableHelper.ThrowIfFrozen(this); + allowUnsafeBlocks = value; + } + } + + bool checkForOverflow; + + /// + /// Gets/Sets whether overflow checking is enabled. + /// The default is false. This setting effects semantic analysis. + /// + public bool CheckForOverflow { + get { return checkForOverflow; } + set { checkForOverflow = value; } + } + + Version languageVersion = new Version((int)Mono.CSharp.LanguageVersion.Default, 0); + + /// + /// Gets/Sets the language version used by the parser. + /// Using language constructs newer than the supplied version will result in parser errors. + /// + public Version LanguageVersion { + get { return languageVersion; } + set { + FreezableHelper.ThrowIfFrozen(this); + if (value == null) + throw new ArgumentNullException(); + languageVersion = value; + } + } + + IList conditionalSymbols = new List(); + + /// + /// Gets/Sets the list of conditional symbols that are defined project-wide. + /// + public IList ConditionalSymbols { + get { return conditionalSymbols; } + } + + bool treatWarningsAsErrors; + + public bool TreatWarningsAsErrors { + get { return treatWarningsAsErrors; } + set { + FreezableHelper.ThrowIfFrozen(this); + treatWarningsAsErrors = value; + } + } + + IList specificWarningsAsErrors = new List(); + + /// + /// Allows treating specific warnings as errors without setting to true. + /// + public IList SpecificWarningsAsErrors { + get { return specificWarningsAsErrors; } + } + + int warningLevel = 4; + + public int WarningLevel { + get { return warningLevel; } + set { + FreezableHelper.ThrowIfFrozen(this); + warningLevel = value; + } + } + + IList disabledWarnings = new List(); + + /// + /// Allows treating specific warnings as errors without setting to true. + /// + public IList DisabledWarnings { + get { return disabledWarnings; } + } + + internal Mono.CSharp.CompilerSettings ToMono() + { + var s = new Mono.CSharp.CompilerSettings(); + s.Unsafe = allowUnsafeBlocks; + s.Checked = checkForOverflow; + s.Version = (Mono.CSharp.LanguageVersion)languageVersion.Major; + s.WarningsAreErrors = treatWarningsAsErrors; + s.WarningLevel = warningLevel; + foreach (int code in disabledWarnings) + s.SetIgnoreWarning(code); + foreach (int code in specificWarningsAsErrors) + s.AddWarningAsError(code); + foreach (string sym in conditionalSymbols) + s.AddConditionalSymbol(sym); + return s; + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Parser/mcs/settings.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/settings.cs index 5c5a34b9ed..214c925591 100644 --- a/ICSharpCode.NRefactory.CSharp/Parser/mcs/settings.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/settings.cs @@ -224,7 +224,11 @@ namespace Mono.CSharp { return source_files; } } - + + public IList ConditionalSymbols { + get { return conditional_symbols; } + } + #endregion public void AddConditionalSymbol (string symbol) diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs index ec47908926..f634f266c8 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs @@ -56,6 +56,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.compilation = compilation; this.conversions = CSharpConversions.Get(compilation); this.context = new CSharpTypeResolveContext(compilation.MainAssembly); + + var pc = compilation.MainAssembly.UnresolvedAssembly as CSharpProjectContent; + if (pc != null) { + this.checkForOverflow = pc.CompilerSettings.CheckForOverflow; + } } public CSharpResolver(CSharpTypeResolveContext context) diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/CSharpProject.cs b/ICSharpCode.NRefactory.ConsistencyCheck/CSharpProject.cs index cb689e527f..0507ca395b 100644 --- a/ICSharpCode.NRefactory.ConsistencyCheck/CSharpProject.cs +++ b/ICSharpCode.NRefactory.ConsistencyCheck/CSharpProject.cs @@ -36,9 +36,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck public readonly List Files = new List(); - public readonly bool AllowUnsafeBlocks; - public readonly bool CheckForOverflowUnderflow; - public readonly string[] PreprocessorDefines; + public readonly CompilerSettings CompilerSettings = new CompilerSettings(); public IProjectContent ProjectContent; @@ -56,9 +54,11 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck var p = new Microsoft.Build.Evaluation.Project(fileName); this.AssemblyName = p.GetPropertyValue("AssemblyName"); - this.AllowUnsafeBlocks = GetBoolProperty(p, "AllowUnsafeBlocks") ?? false; - this.CheckForOverflowUnderflow = GetBoolProperty(p, "CheckForOverflowUnderflow") ?? false; - this.PreprocessorDefines = p.GetPropertyValue("DefineConstants").Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + this.CompilerSettings.AllowUnsafeBlocks = GetBoolProperty(p, "AllowUnsafeBlocks") ?? false; + this.CompilerSettings.CheckForOverflow = GetBoolProperty(p, "CheckForOverflowUnderflow") ?? false; + foreach (string symbol in p.GetPropertyValue("DefineConstants").Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { + this.CompilerSettings.ConditionalSymbols.Add(symbol.Trim()); + } foreach (var item in p.GetItems("Compile")) { Files.Add(new CSharpFile(this, Path.Combine(p.DirectoryPath, item.EvaluatedInclude))); } @@ -95,6 +95,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck } this.ProjectContent = new CSharpProjectContent() .SetAssemblyName(this.AssemblyName) + .SetCompilerSettings(this.CompilerSettings) .AddAssemblyReferences(references) .UpdateProjectContent(null, Files.Select(f => f.ParsedFile)); } @@ -121,15 +122,6 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck return null; } - public CSharpParser CreateParser() - { - var settings = new Mono.CSharp.CompilerSettings(); - settings.Unsafe = AllowUnsafeBlocks; - foreach (string define in PreprocessorDefines) - settings.AddConditionalSymbol(define); - return new CSharpParser(settings); - } - public override string ToString() { return string.Format("[CSharpProject AssemblyName={0}]", AssemblyName); @@ -176,7 +168,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck this.Content = new StringTextSource(File.ReadAllText(FileName)); this.LinesOfCode = 1 + this.Content.Text.Count(c => c == '\n'); - CSharpParser p = project.CreateParser(); + CSharpParser p = new CSharpParser(project.CompilerSettings); this.CompilationUnit = p.Parse(Content.CreateReader(), fileName); if (p.HasErrors) { Console.WriteLine("Error parsing " + fileName + ":"); diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/RoundtripTest.cs b/ICSharpCode.NRefactory.ConsistencyCheck/RoundtripTest.cs index 5fb237f6e0..cb3cd6b06f 100644 --- a/ICSharpCode.NRefactory.ConsistencyCheck/RoundtripTest.cs +++ b/ICSharpCode.NRefactory.ConsistencyCheck/RoundtripTest.cs @@ -55,9 +55,9 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck if (file.FileName.EndsWith("DefaultResolvedTypeDefinition.cs")) return; // skip due to MethodDeclarationTests.GenericMethodWithMultipleConstraints - Roundtrip(file.Project.CreateParser(), file.FileName, code); + Roundtrip(new CSharpParser(file.Project.CompilerSettings), file.FileName, code); // After trying unix-style newlines, also try windows-style newlines: - Roundtrip(file.Project.CreateParser(), file.FileName, code.Replace("\n", "\r\n")); + Roundtrip(new CSharpParser(file.Project.CompilerSettings), file.FileName, code.Replace("\n", "\r\n")); } public static void Roundtrip(CSharpParser parser, string fileName, string code) diff --git a/ICSharpCode.NRefactory.Demo/CSDemo.Designer.cs b/ICSharpCode.NRefactory.Demo/CSDemo.Designer.cs index 64aa9c597e..330a92e4a8 100644 --- a/ICSharpCode.NRefactory.Demo/CSDemo.Designer.cs +++ b/ICSharpCode.NRefactory.Demo/CSDemo.Designer.cs @@ -153,7 +153,7 @@ namespace ICSharpCode.NRefactory.Demo this.csharpParseButton.Name = "csharpParseButton"; this.csharpParseButton.Size = new System.Drawing.Size(100, 23); this.csharpParseButton.TabIndex = 0; - this.csharpParseButton.Text = "Parse"; + this.csharpParseButton.Text = "\u2193 Parse \u2193"; this.csharpParseButton.UseVisualStyleBackColor = true; this.csharpParseButton.Click += new System.EventHandler(this.CSharpParseButtonClick); // diff --git a/ICSharpCode.NRefactory.Demo/CSDemo.cs b/ICSharpCode.NRefactory.Demo/CSDemo.cs index a7bc38b461..812ce71269 100644 --- a/ICSharpCode.NRefactory.Demo/CSDemo.cs +++ b/ICSharpCode.NRefactory.Demo/CSDemo.cs @@ -203,9 +203,11 @@ namespace ICSharpCode.NRefactory.Demo ICompilation compilation = project.CreateCompilation(); + AstNode selectedNode = null; StoreInDictionaryNavigator navigator; if (csharpTreeView.SelectedNode != null) { - navigator = new StoreInDictionaryNavigator((AstNode)csharpTreeView.SelectedNode.Tag); + selectedNode = (AstNode)csharpTreeView.SelectedNode.Tag; + navigator = new StoreInDictionaryNavigator(selectedNode); } else { navigator = new StoreInDictionaryNavigator(); } @@ -214,6 +216,10 @@ namespace ICSharpCode.NRefactory.Demo csharpTreeView.BeginUpdate(); ShowResolveResultsInTree(csharpTreeView.Nodes, navigator); csharpTreeView.EndUpdate(); + if (csharpTreeView.SelectedNode != null) { + using (var dlg = new SemanticTreeDialog(resolver.Resolve(selectedNode))) + dlg.ShowDialog(); + } } sealed class StoreInDictionaryNavigator : NodeListResolveVisitorNavigator diff --git a/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj b/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj index 099b882669..c302a56ae0 100644 --- a/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj +++ b/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj @@ -72,6 +72,10 @@ + + + SemanticTreeDialog.cs + @@ -90,6 +94,9 @@ MainForm.cs + + SemanticTreeDialog.cs + \ No newline at end of file diff --git a/ICSharpCode.NRefactory.Demo/SemanticTreeDialog.Designer.cs b/ICSharpCode.NRefactory.Demo/SemanticTreeDialog.Designer.cs new file mode 100644 index 0000000000..8942d4a9ff --- /dev/null +++ b/ICSharpCode.NRefactory.Demo/SemanticTreeDialog.Designer.cs @@ -0,0 +1,80 @@ +/* + * Created by SharpDevelop. + * User: Daniel + * Date: 6/22/2012 + * Time: 17:08 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +namespace ICSharpCode.NRefactory.Demo +{ + partial class SemanticTreeDialog + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { + this.cancelButton = new System.Windows.Forms.Button(); + this.treeView = new System.Windows.Forms.TreeView(); + this.SuspendLayout(); + // + // cancelButton + // + this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.Location = new System.Drawing.Point(197, 236); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(75, 23); + this.cancelButton.TabIndex = 0; + this.cancelButton.Text = "Close"; + this.cancelButton.UseVisualStyleBackColor = true; + // + // treeView + // + this.treeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.treeView.Location = new System.Drawing.Point(12, 12); + this.treeView.Name = "treeView"; + this.treeView.ShowRootLines = false; + this.treeView.Size = new System.Drawing.Size(260, 218); + this.treeView.TabIndex = 1; + // + // SemanticTreeDialog + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.cancelButton; + this.ClientSize = new System.Drawing.Size(284, 262); + this.Controls.Add(this.treeView); + this.Controls.Add(this.cancelButton); + this.Name = "SemanticTreeDialog"; + this.Text = "Semantic Tree"; + this.ResumeLayout(false); + } + private System.Windows.Forms.TreeView treeView; + private System.Windows.Forms.Button cancelButton; + } +} diff --git a/ICSharpCode.NRefactory.Demo/SemanticTreeDialog.cs b/ICSharpCode.NRefactory.Demo/SemanticTreeDialog.cs new file mode 100644 index 0000000000..0cd82235a8 --- /dev/null +++ b/ICSharpCode.NRefactory.Demo/SemanticTreeDialog.cs @@ -0,0 +1,92 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections; +using System.Drawing; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Windows.Forms; +using ICSharpCode.NRefactory.Semantics; + +namespace ICSharpCode.NRefactory.Demo +{ + /// + /// Description of SemanticTreeDialog. + /// + public partial class SemanticTreeDialog : Form + { + public SemanticTreeDialog(ResolveResult rr) + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + + var rootNode = MakeObjectNode("Resolve() = ", rr); + rootNode.Expand(); + treeView.Nodes.Add(rootNode); + } + + TreeNode MakeObjectNode(string prefix, object obj) + { + if (obj == null) + return new TreeNode(prefix + "null"); + if (obj is ResolveResult) { + TreeNode t = new TreeNode(prefix + obj.GetType().Name); + t.Tag = obj; + foreach (PropertyInfo p in obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { + if (p.Name == "ConstantValue" && !((ResolveResult)obj).IsCompileTimeConstant) + continue; + TreeNode child = MakePropertyNode(p.Name, p.PropertyType, p.GetValue(obj, null)); + if (child != null) + t.Nodes.Add(child); + } + foreach (FieldInfo p in obj.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)) { + TreeNode child = MakePropertyNode(p.Name, p.FieldType, p.GetValue(obj)); + if (child != null) + t.Nodes.Add(child); + } + return t; + } else { + return new TreeNode(prefix + obj.ToString()); + } + } + + TreeNode MakePropertyNode(string propertyName, Type propertyType, object propertyValue) + { + if (propertyName == "IsError" && (propertyValue as bool?) == false) + return null; + if (propertyName == "IsCompileTimeConstant" && (propertyValue as bool?) == false) + return null; + if (propertyValue == null) { + return new TreeNode(propertyName + " = null"); + } + if (propertyType.GetInterface("System.Collections.IEnumerable") != null && propertyType != typeof(string)) { + var collection = ((IEnumerable)propertyValue).Cast().ToList(); + var node = new TreeNode(propertyName + " = Collection with " + collection.Count + " elements"); + foreach (object element in collection) { + node.Nodes.Add(MakeObjectNode("", element)); + } + return node; + } + return MakeObjectNode(propertyName + " = ", propertyValue); + } + } +} diff --git a/ICSharpCode.NRefactory.Demo/SemanticTreeDialog.resx b/ICSharpCode.NRefactory.Demo/SemanticTreeDialog.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/ICSharpCode.NRefactory.Demo/SemanticTreeDialog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs b/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs index 8bfe45c55b..7acfb81de2 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs @@ -42,6 +42,12 @@ namespace ICSharpCode.NRefactory.TypeSystem /// IEnumerable AssemblyReferences { get; } + /// + /// Gets the compiler settings object. + /// The concrete type of the settings object depends on the programming language used to implement this project. + /// + object CompilerSettings { get; } + /// /// Creates a new that allows resolving within this project. /// @@ -83,5 +89,12 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Removes types and attributes from oldFiles from the project, and adds those from newFiles. /// IProjectContent UpdateProjectContent(IEnumerable oldFiles, IEnumerable newFiles); + + /// + /// Sets the compiler settings object. + /// The concrete type of the settings object depends on the programming language used to implement this project. + /// Using the incorrect type of settings object results in an . + /// + IProjectContent SetCompilerSettings(object compilerSettings); } }