Browse Source

Update ICSharpCode.Decompiler to ILSpy 09c2b45f.

pull/22/head
Daniel Grunwald 14 years ago
parent
commit
737fba5dc7
  1. 6
      src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 11
      src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  3. 189
      src/Libraries/ICSharpCode.Decompiler/Ast/CecilTypeResolveContext.cs
  4. 21
      src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs
  5. 12
      src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs
  6. 5
      src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs
  7. 7
      src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  8. 46
      src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
  9. 8
      src/Libraries/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  10. 365
      src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  11. 2
      src/Libraries/ICSharpCode.Decompiler/ILAst/LiftedOperators.cs
  12. 2
      src/Libraries/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  13. 4
      src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs
  14. 1
      src/Libraries/ICSharpCode.Decompiler/Tests/ValueTypes.cs
  15. 94
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs
  16. 110
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs
  17. 5
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs
  18. 1
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs
  19. 5
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs
  20. 25
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs
  21. 5
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs
  22. 31
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AssignmentExpression.cs
  23. 47
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/BinaryOperatorExpression.cs
  24. 74
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ErrorExpression.cs
  25. 3
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedExpression.cs
  26. 29
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/UnaryOperatorExpression.cs
  27. 18
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Comment.cs
  28. 9
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Constraint.cs
  29. 117
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/PreProcessorDirective.cs
  30. 2
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs
  31. 2
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs
  32. 2
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/NodeType.cs
  33. 10
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs
  34. 28
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs
  35. 20
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs
  36. 5
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/Accessor.cs
  37. 170
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs
  38. 2165
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  39. 448
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs
  40. 326
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs
  41. 237
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/CompletionDataWrapper.cs
  42. 71
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/ICompletionDataFactory.cs
  43. 46
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs
  44. 2
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs
  45. 54
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  46. 239
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs
  47. 125
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs
  48. 62
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
  49. 1
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/IOutputFormatter.cs
  50. 127
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs
  51. 224
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  52. 40
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs
  53. 3
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/argument.cs
  54. 21
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/assembly.cs
  55. 13
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/assign.cs
  56. 261
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs
  57. 3
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/attribute.cs
  58. 2
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cfold.cs
  59. 77
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/class.cs
  60. 6
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/codegen.cs
  61. 3
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/complete.cs
  62. 3
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/constant.cs
  63. 17
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/context.cs
  64. 18
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/convert.cs
  65. 8760
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs
  66. 327
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.jay
  67. 69
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs
  68. 4
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/decl.cs
  69. 10
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/delegate.cs
  70. 1
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/doc.cs
  71. 9
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/driver.cs
  72. 288
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs
  73. 1
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/enum.cs
  74. 21
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/eval.cs
  75. 318
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/expression.cs
  76. 12
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/field.cs
  77. 306
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/flowanalysis.cs
  78. 191
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/generic.cs
  79. 11
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/import.cs
  80. 12
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/iterators.cs
  81. 1
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/lambda.cs
  82. 7
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/linq.cs
  83. 3
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/literal.cs
  84. 10
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/location.cs
  85. 116
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/membercache.cs
  86. 114
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/method.cs
  87. 10
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/namespace.cs
  88. 1
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/nullable.cs
  89. 1
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/parameter.cs
  90. 11
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/pending.cs
  91. 17
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/property.cs
  92. 5
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/report.cs
  93. 15
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/rootcontext.cs
  94. 10
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/roottypes.cs
  95. 403
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs
  96. 1
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/support.cs
  97. 109
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/typemanager.cs
  98. 75
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs
  99. 38
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/visit.cs
  100. 8
      src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Properties/AssemblyInfo.cs
  101. Some files were not shown because too many files have changed in this diff Show More

6
src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -641,6 +641,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -641,6 +641,10 @@ namespace ICSharpCode.Decompiler.Ast
modifiers |= Modifiers.Readonly;
}
RequiredModifierType modreq = fieldDef.FieldType as RequiredModifierType;
if (modreq != null && modreq.ModifierType.FullName == typeof(IsVolatile).FullName)
modifiers |= Modifiers.Volatile;
return modifiers;
}
@ -793,7 +797,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -793,7 +797,7 @@ namespace ICSharpCode.Decompiler.Ast
{
foreach (var gp in genericParameters) {
Constraint c = new Constraint();
c.TypeParameter = CleanName(gp.Name);
c.TypeParameter = new SimpleType(CleanName(gp.Name));
// class/struct must be first
if (gp.HasReferenceTypeConstraint)
c.BaseTypes.Add(new PrimitiveType("class"));

11
src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -135,7 +135,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -135,7 +135,7 @@ namespace ICSharpCode.Decompiler.Ast
Ast.BlockStatement astBlock = new BlockStatement();
if (block != null) {
foreach(ILNode node in block.GetChildren()) {
astBlock.AddRange(TransformNode(node));
astBlock.Statements.AddRange(TransformNode(node));
}
}
return astBlock;
@ -175,11 +175,15 @@ namespace ICSharpCode.Decompiler.Ast @@ -175,11 +175,15 @@ namespace ICSharpCode.Decompiler.Ast
};
} else if (node is ILSwitch) {
ILSwitch ilSwitch = (ILSwitch)node;
if (TypeAnalysis.IsBoolean(ilSwitch.Condition.InferredType) && ilSwitch.CaseBlocks.SelectMany(cb => cb.Values).Any(val => val != 0 && val != 1)) {
// If switch cases contain values other then 0 and 1, force the condition to be non-boolean
ilSwitch.Condition.ExpectedType = typeSystem.Int32;
}
SwitchStatement switchStmt = new SwitchStatement() { Expression = (Expression)TransformExpression(ilSwitch.Condition) };
foreach (var caseBlock in ilSwitch.CaseBlocks) {
SwitchSection section = new SwitchSection();
if (caseBlock.Values != null) {
section.CaseLabels.AddRange(caseBlock.Values.Select(i => new CaseLabel() { Expression = AstBuilder.MakePrimitive(i, ilSwitch.Condition.InferredType) }));
section.CaseLabels.AddRange(caseBlock.Values.Select(i => new CaseLabel() { Expression = AstBuilder.MakePrimitive(i, ilSwitch.Condition.ExpectedType ?? ilSwitch.Condition.InferredType) }));
} else {
section.CaseLabels.Add(new CaseLabel());
}
@ -860,7 +864,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -860,7 +864,8 @@ namespace ICSharpCode.Decompiler.Ast
static readonly AstNode objectInitializerPattern = new AssignmentExpression(
new MemberReferenceExpression {
Target = new InitializedObjectExpression()
Target = new InitializedObjectExpression(),
MemberName = Pattern.AnyString
}.WithName("left"),
new AnyNode("right")
);

189
src/Libraries/ICSharpCode.Decompiler/Ast/CecilTypeResolveContext.cs

@ -1,189 +0,0 @@ @@ -1,189 +0,0 @@
// Copyright (c) 2011 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 System.Linq;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.Ast
{
/// <summary>
/// ITypeResolveContext implementation that lazily loads types from Cecil.
/// </summary>
public class CecilTypeResolveContext : AbstractAnnotatable, ISynchronizedTypeResolveContext, IProjectContent
{
readonly ModuleDefinition module;
readonly string[] namespaces;
readonly CecilLoader loader;
Dictionary<TypeDefinition, WeakReference> dict = new Dictionary<TypeDefinition, WeakReference>();
int countUntilNextCleanup = 4;
public CecilTypeResolveContext(ModuleDefinition module)
{
this.loader = new CecilLoader();
this.loader.IncludeInternalMembers = true;
this.module = module;
this.namespaces = module.Types.Select(t => t.Namespace).Distinct().ToArray();
List<IAttribute> assemblyAttributes = new List<IAttribute>();
foreach (var attr in module.Assembly.CustomAttributes) {
assemblyAttributes.Add(loader.ReadAttribute(attr));
}
this.AssemblyAttributes = assemblyAttributes.AsReadOnly();
}
ITypeDefinition GetClass(TypeDefinition cecilType)
{
lock (dict) {
WeakReference wr;
ITypeDefinition type;
if (dict.TryGetValue(cecilType, out wr)) {
type = (ITypeDefinition)wr.Target;
} else {
wr = null;
type = null;
}
if (type == null) {
type = loader.LoadType(cecilType, this);
}
if (wr == null) {
if (--countUntilNextCleanup <= 0)
CleanupDict();
wr = new WeakReference(type);
dict.Add(cecilType, wr);
} else {
wr.Target = type;
}
return type;
}
}
void CleanupDict()
{
List<TypeDefinition> deletedKeys = new List<TypeDefinition>();
foreach (var pair in dict) {
if (!pair.Value.IsAlive) {
deletedKeys.Add(pair.Key);
}
}
foreach (var key in deletedKeys) {
dict.Remove(key);
}
countUntilNextCleanup = dict.Count + 4;
}
public string AssemblyName {
get { return module.Assembly.Name.Name; }
}
public IList<IAttribute> ModuleAttributes { get; private set; }
public IList<IAttribute> AssemblyAttributes { get; private set; }
public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer)
{
if (typeParameterCount > 0)
name = name + "`" + typeParameterCount.ToString();
if (nameComparer == StringComparer.Ordinal) {
TypeDefinition cecilType = module.GetType(nameSpace, name);
if (cecilType != null)
return GetClass(cecilType);
else
return null;
}
foreach (TypeDefinition cecilType in module.Types) {
if (nameComparer.Equals(name, cecilType.Name)
&& nameComparer.Equals(nameSpace, cecilType.Namespace)
&& cecilType.GenericParameters.Count == typeParameterCount)
{
return GetClass(cecilType);
}
}
return null;
}
public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode)
{
return GetTypeDefinition("System", ReflectionHelper.GetShortNameByTypeCode(typeCode), 0, StringComparer.Ordinal);
}
public IEnumerable<ITypeDefinition> GetTypes()
{
foreach (TypeDefinition cecilType in module.Types) {
yield return GetClass(cecilType);
}
}
public IEnumerable<ITypeDefinition> GetTypes(string nameSpace, StringComparer nameComparer)
{
foreach (TypeDefinition cecilType in module.Types) {
if (nameComparer.Equals(nameSpace, cecilType.Namespace))
yield return GetClass(cecilType);
}
}
public IEnumerable<string> GetNamespaces()
{
return namespaces;
}
public string GetNamespace(string nameSpace, StringComparer nameComparer)
{
foreach (string ns in namespaces) {
if (nameComparer.Equals(ns, nameSpace))
return ns;
}
return null;
}
ICSharpCode.NRefactory.Utils.CacheManager ITypeResolveContext.CacheManager {
get {
// We don't support caching
return null;
}
}
ISynchronizedTypeResolveContext ITypeResolveContext.Synchronize()
{
// This class is logically immutable
return this;
}
void IDisposable.Dispose()
{
// exit from Synchronize() block
}
IEnumerable<IParsedFile> IProjectContent.Files {
get { return new IParsedFile[0]; }
}
void IProjectContent.UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile)
{
throw new NotSupportedException();
}
IParsedFile IProjectContent.GetFile(string fileName)
{
return null;
}
}
}

21
src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs

@ -147,7 +147,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -147,7 +147,7 @@ namespace ICSharpCode.Decompiler.Ast
if (nodeStack == null || nodeStack.Count == 0)
return null;
var node = nodeStack.Peek();
var node = nodeStack.Peek();
if (IsDefinition(node))
return node.Annotation<MemberReference>();
@ -246,7 +246,22 @@ namespace ICSharpCode.Decompiler.Ast @@ -246,7 +246,22 @@ namespace ICSharpCode.Decompiler.Ast
}
output.WriteLine();
break;
default:
output.Write(content);
break;
}
}
public void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument)
{
// pre-processor directive must start on its own line
output.Write('#');
output.Write(type.ToString().ToLowerInvariant());
if (!string.IsNullOrEmpty(argument)) {
output.Write(' ');
output.Write(argument);
}
output.WriteLine();
}
Stack<TextLocation> startLocations = new Stack<TextLocation>();
@ -312,10 +327,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -312,10 +327,10 @@ namespace ICSharpCode.Decompiler.Ast
private static bool IsDefinition(AstNode node)
{
return
return
node is FieldDeclaration ||
node is ConstructorDeclaration ||
node is DestructorDeclaration ||
node is DestructorDeclaration ||
node is EventDeclaration ||
node is DelegateDeclaration ||
node is OperatorDeclaration||

12
src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs

@ -81,13 +81,19 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -81,13 +81,19 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
Expression = new Choice {
new AnonymousTypeCreateExpression {
Initializers = {
new NamedNode("nae1", new NamedExpression { Expression = new IdentifierExpression() }),
new NamedNode("nae2", new NamedExpression { Expression = new AnyNode("nae2Expr") })
new NamedExpression {
Identifier = Pattern.AnyString,
Expression = new IdentifierExpression(Pattern.AnyString)
}.WithName("nae1"),
new NamedExpression {
Identifier = Pattern.AnyString,
Expression = new AnyNode("nae2Expr")
}.WithName("nae2")
}
},
new AnonymousTypeCreateExpression {
Initializers = {
new NamedNode("identifier", new IdentifierExpression()),
new NamedNode("identifier", new IdentifierExpression(Pattern.AnyString)),
new AnyNode("nae2Expr")
}
}

5
src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs

@ -60,7 +60,10 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -60,7 +60,10 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
static readonly ExpressionStatement fieldInitializerPattern = new ExpressionStatement {
Expression = new AssignmentExpression {
Left = new NamedNode("fieldAccess", new MemberReferenceExpression { Target = new ThisReferenceExpression() }),
Left = new NamedNode("fieldAccess", new MemberReferenceExpression {
Target = new ThisReferenceExpression(),
MemberName = Pattern.AnyString
}),
Operator = AssignmentOperatorType.Assign,
Right = new AnyNode("initializer")
}

7
src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

@ -293,7 +293,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -293,7 +293,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
static readonly ExpressionStatement displayClassAssignmentPattern =
new ExpressionStatement(new AssignmentExpression(
new NamedNode("variable", new IdentifierExpression()),
new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
new ObjectCreateExpression { Type = new AnyNode("type") }
));
@ -348,7 +348,10 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -348,7 +348,10 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
// "variableName.MemberName = right;"
ExpressionStatement closureFieldAssignmentPattern = new ExpressionStatement(
new AssignmentExpression(
new NamedNode("left", new MemberReferenceExpression { Target = new IdentifierExpression(variable.Name) }),
new NamedNode("left", new MemberReferenceExpression {
Target = new IdentifierExpression(variable.Name),
MemberName = Pattern.AnyString
}),
new AnyNode("right")
)
);

46
src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs

@ -140,7 +140,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -140,7 +140,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
/// </summary>
static readonly AstNode variableAssignPattern = new ExpressionStatement(
new AssignmentExpression(
new NamedNode("variable", new IdentifierExpression()),
new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
new AnyNode("initializer")
));
@ -158,12 +158,12 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -158,12 +158,12 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
FinallyBlock = new BlockStatement {
new Choice {
{ "valueType",
new ExpressionStatement(InvokeDispose(new NamedNode("ident", new IdentifierExpression())))
new ExpressionStatement(InvokeDispose(new NamedNode("ident", new IdentifierExpression(Pattern.AnyString))))
},
{ "referenceType",
new IfElseStatement {
Condition = new BinaryOperatorExpression(
new NamedNode("ident", new IdentifierExpression()),
new NamedNode("ident", new IdentifierExpression(Pattern.AnyString)),
BinaryOperatorType.InEquality,
new NullReferenceExpression()
),
@ -319,6 +319,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -319,6 +319,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
new NamedNode(
"enumeratorVariable",
new VariableInitializer {
Name = Pattern.AnyString,
Initializer = new AnyNode("collection").ToExpression().Invoke("GetEnumerator")
}
)
@ -326,16 +327,19 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -326,16 +327,19 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
},
EmbeddedStatement = new BlockStatement {
new Repeat(
new VariableDeclarationStatement { Type = new AnyNode(), Variables = { new VariableInitializer() } }.WithName("variablesOutsideLoop")
new VariableDeclarationStatement { Type = new AnyNode(), Variables = { new VariableInitializer(Pattern.AnyString) } }.WithName("variablesOutsideLoop")
).ToStatement(),
new WhileStatement {
Condition = new IdentifierExpressionBackreference("enumeratorVariable").ToExpression().Invoke("MoveNext"),
EmbeddedStatement = new BlockStatement {
new Repeat(
new VariableDeclarationStatement { Type = new AnyNode(), Variables = { new VariableInitializer() } }.WithName("variablesInsideLoop")
new VariableDeclarationStatement {
Type = new AnyNode(),
Variables = { new VariableInitializer(Pattern.AnyString) }
}.WithName("variablesInsideLoop")
).ToStatement(),
new AssignmentExpression {
Left = new IdentifierExpression().WithName("itemVariable"),
Left = new IdentifierExpression(Pattern.AnyString).WithName("itemVariable"),
Operator = AssignmentOperatorType.Assign,
Right = new IdentifierExpressionBackreference("enumeratorVariable").ToExpression().Member("Current")
},
@ -398,17 +402,17 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -398,17 +402,17 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
#region foreach (non-generic)
ExpressionStatement getEnumeratorPattern = new ExpressionStatement(
new AssignmentExpression(
new NamedNode("left", new IdentifierExpression()),
new NamedNode("left", new IdentifierExpression(Pattern.AnyString)),
new AnyNode("collection").ToExpression().Invoke("GetEnumerator")
));
TryCatchStatement nonGenericForeachPattern = new TryCatchStatement {
TryBlock = new BlockStatement {
new WhileStatement {
Condition = new IdentifierExpression().WithName("enumerator").Invoke("MoveNext"),
Condition = new IdentifierExpression(Pattern.AnyString).WithName("enumerator").Invoke("MoveNext"),
EmbeddedStatement = new BlockStatement {
new AssignmentExpression(
new IdentifierExpression().WithName("itemVar"),
new IdentifierExpression(Pattern.AnyString).WithName("itemVar"),
new Choice {
new Backreference("enumerator").ToExpression().Member("Current"),
new CastExpression {
@ -423,7 +427,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -423,7 +427,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
},
FinallyBlock = new BlockStatement {
new AssignmentExpression(
new IdentifierExpression().WithName("disposable"),
new IdentifierExpression(Pattern.AnyString).WithName("disposable"),
new Backreference("enumerator").ToExpression().CastAs(new TypePattern(typeof(IDisposable)))
),
new IfElseStatement {
@ -511,7 +515,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -511,7 +515,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
#region for
static readonly WhileStatement forPattern = new WhileStatement {
Condition = new BinaryOperatorExpression {
Left = new NamedNode("ident", new IdentifierExpression()),
Left = new NamedNode("ident", new IdentifierExpression(Pattern.AnyString)),
Operator = BinaryOperatorType.Any,
Right = new AnyNode("endExpr")
},
@ -604,7 +608,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -604,7 +608,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
#region lock
static readonly AstNode lockFlagInitPattern = new ExpressionStatement(
new AssignmentExpression(
new NamedNode("variable", new IdentifierExpression()),
new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
new PrimitiveExpression(false)
));
@ -614,7 +618,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -614,7 +618,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
"Enter", new AnyNode("enter"),
new DirectionExpression {
FieldDirection = FieldDirection.Ref,
Expression = new NamedNode("flag", new IdentifierExpression())
Expression = new NamedNode("flag", new IdentifierExpression(Pattern.AnyString))
}),
new Repeat(new AnyNode()).ToStatement()
},
@ -622,7 +626,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -622,7 +626,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
new IfElseStatement {
Condition = new Backreference("flag"),
TrueStatement = new BlockStatement {
new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Exit", new NamedNode("exit", new IdentifierExpression()))
new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Exit", new NamedNode("exit", new IdentifierExpression(Pattern.AnyString)))
}
}
}};
@ -680,10 +684,10 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -680,10 +684,10 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
new IfElseStatement {
Condition = new Backreference("cachedDict").ToExpression().Invoke(
"TryGetValue",
new NamedNode("switchVar", new IdentifierExpression()),
new NamedNode("switchVar", new IdentifierExpression(Pattern.AnyString)),
new DirectionExpression {
FieldDirection = FieldDirection.Out,
Expression = new IdentifierExpression().WithName("intVar")
Expression = new IdentifierExpression(Pattern.AnyString).WithName("intVar")
}),
TrueStatement = new BlockStatement {
Statements = {
@ -784,6 +788,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -784,6 +788,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
Modifiers = Modifiers.Any,
ReturnType = new AnyNode(),
PrivateImplementationType = new OptionalNode(new AnyNode()),
Name = Pattern.AnyString,
Getter = new Accessor {
Attributes = { new Repeat(new AnyNode()) },
Modifiers = Modifiers.Any,
@ -846,19 +851,20 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -846,19 +851,20 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
new VariableDeclarationStatement { Type = new Backreference("type"), Variables = { new AnyNode() } },
new VariableDeclarationStatement { Type = new Backreference("type"), Variables = { new AnyNode() } },
new AssignmentExpression {
Left = new NamedNode("var1", new IdentifierExpression()),
Left = new NamedNode("var1", new IdentifierExpression(Pattern.AnyString)),
Operator = AssignmentOperatorType.Assign,
Right = new NamedNode(
"field",
new MemberReferenceExpression {
Target = new Choice { new ThisReferenceExpression(), new TypeReferenceExpression { Type = new AnyNode() } }
Target = new Choice { new ThisReferenceExpression(), new TypeReferenceExpression { Type = new AnyNode() } },
MemberName = Pattern.AnyString
})
},
new DoWhileStatement {
EmbeddedStatement = new BlockStatement {
new AssignmentExpression(new NamedNode("var2", new IdentifierExpression()), new IdentifierExpressionBackreference("var1")),
new AssignmentExpression(new NamedNode("var2", new IdentifierExpression(Pattern.AnyString)), new IdentifierExpressionBackreference("var1")),
new AssignmentExpression {
Left = new NamedNode("var3", new IdentifierExpression()),
Left = new NamedNode("var3", new IdentifierExpression(Pattern.AnyString)),
Operator = AssignmentOperatorType.Assign,
Right = new AnyNode("delegateCombine").ToExpression().Invoke(
new IdentifierExpressionBackreference("var2"),

8
src/Libraries/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -14,6 +14,10 @@ @@ -14,6 +14,10 @@
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\NewNRefactory\ICSharpCode.NRefactory.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -51,7 +55,6 @@ @@ -51,7 +55,6 @@
<Compile Include="Ast\Annotations.cs" />
<Compile Include="Ast\AstBuilder.cs" />
<Compile Include="Ast\AstMethodBodyBuilder.cs" />
<Compile Include="Ast\CecilTypeResolveContext.cs" />
<Compile Include="Ast\CommentStatement.cs" />
<Compile Include="Ast\DecompilerContext.cs" />
<Compile Include="Ast\NameVariables.cs" />
@ -115,9 +118,10 @@ @@ -115,9 +118,10 @@
<Compile Include="ILAst\YieldReturnDecompiler.cs" />
<Compile Include="ITextOutput.cs" />
<Compile Include="PlainTextOutput.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReferenceResolvingException.cs" />
<Compile Include="TextOutputWriter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<None Include="Properties\AssemblyInfo.template.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Mono.Cecil\Mono.Cecil.csproj">

365
src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -28,85 +28,66 @@ using Cecil = Mono.Cecil; @@ -28,85 +28,66 @@ using Cecil = Mono.Cecil;
namespace ICSharpCode.Decompiler.ILAst
{
/// <summary>
/// Converts stack-based bytecode to variable-based bytecode by calculating use-define chains
/// </summary>
public class ILAstBuilder
{
static ByteCode[] EmptyByteCodeArray = new ByteCode[] {};
/// <summary> Immutable </summary>
class StackSlot
struct StackSlot
{
public readonly ByteCode[] PushedBy; // One of those
public readonly ILVariable LoadFrom; // Where can we get the value from in AST
public readonly ByteCode[] Definitions; // Reaching definitions of this stack slot
public readonly ILVariable LoadFrom; // Variable used for storage of the value
public StackSlot(ByteCode[] pushedBy, ILVariable loadFrom)
public StackSlot(ByteCode[] definitions, ILVariable loadFrom)
{
this.PushedBy = pushedBy;
this.Definitions = definitions;
this.LoadFrom = loadFrom;
}
public StackSlot(ByteCode pushedBy)
{
this.PushedBy = new[] { pushedBy };
this.LoadFrom = null;
}
public static List<StackSlot> CloneStack(List<StackSlot> stack, int? popCount)
public static StackSlot[] ModifyStack(StackSlot[] stack, int popCount, int pushCount, ByteCode pushDefinition)
{
if (popCount.HasValue) {
return stack.GetRange(0, stack.Count - popCount.Value);
} else {
return new List<StackSlot>(0);
StackSlot[] newStack = new StackSlot[stack.Length - popCount + pushCount];
Array.Copy(stack, newStack, stack.Length - popCount);
for (int i = stack.Length - popCount; i < newStack.Length; i++) {
newStack[i] = new StackSlot(new [] { pushDefinition }, null);
}
return newStack;
}
}
/// <summary> Immutable </summary>
class VariableSlot
struct VariableSlot
{
public readonly ByteCode[] StoredBy; // One of those
public readonly bool StoredByAll; // Overestimate which is useful for exceptional control flow.
public readonly ByteCode[] Definitions; // Reaching deinitions of this variable
public readonly bool UnknownDefinition; // Used for initial state and exceptional control flow
public VariableSlot(ByteCode[] storedBy, bool storedByAll)
{
this.StoredBy = storedBy;
this.StoredByAll = storedByAll;
}
public VariableSlot(ByteCode storedBy)
static readonly VariableSlot UnknownInstance = new VariableSlot(new ByteCode[0], true);
public VariableSlot(ByteCode[] definitions, bool unknownDefinition)
{
this.StoredBy = new[] { storedBy };
this.StoredByAll = false;
this.Definitions = definitions;
this.UnknownDefinition = unknownDefinition;
}
public static VariableSlot[] CloneVariableState(VariableSlot[] state)
{
VariableSlot[] clone = new VariableSlot[state.Length];
for (int i = 0; i < clone.Length; i++) {
clone[i] = state[i];
}
Array.Copy(state, clone, state.Length);
return clone;
}
public static VariableSlot[] MakeEmptyState(int varCount)
{
VariableSlot[] emptyVariableState = new VariableSlot[varCount];
for (int i = 0; i < emptyVariableState.Length; i++) {
emptyVariableState[i] = new VariableSlot(EmptyByteCodeArray, false);
}
return emptyVariableState;
}
public static VariableSlot[] MakeFullState(int varCount)
public static VariableSlot[] MakeUknownState(int varCount)
{
VariableSlot[] unknownVariableState = new VariableSlot[varCount];
for (int i = 0; i < unknownVariableState.Length; i++) {
unknownVariableState[i] = new VariableSlot(EmptyByteCodeArray, true);
unknownVariableState[i] = UnknownInstance;
}
return unknownVariableState;
}
}
class ByteCode
sealed class ByteCode
{
public ILLabel Label; // Non-null only if needed
public int Offset;
@ -118,11 +99,15 @@ namespace ICSharpCode.Decompiler.ILAst @@ -118,11 +99,15 @@ namespace ICSharpCode.Decompiler.ILAst
public string Name { get { return "IL_" + this.Offset.ToString("X2"); } }
public ByteCode Next;
public Instruction[] Prefixes; // Non-null only if needed
public List<StackSlot> StackBefore; // Unique per bytecode; not shared
public List<ILVariable> StoreTo; // Store result of instruction to those AST variables
public StackSlot[] StackBefore; // Unique per bytecode; not shared
public VariableSlot[] VariablesBefore; // Unique per bytecode; not shared
public List<ILVariable> StoreTo; // Store result of instruction to those AST variables
public VariableDefinition OperandAsVariable { get { return (VariableDefinition)this.Operand; } }
public bool IsVariableDefinition {
get {
return (this.Code == ILCode.Stloc) || (this.Code == ILCode.Ldloca && this.Next != null && this.Next.Code == ILCode.Initobj);
}
}
public override string ToString()
{
@ -171,9 +156,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -171,9 +156,9 @@ namespace ICSharpCode.Decompiler.ILAst
foreach (StackSlot slot in this.StackBefore) {
if (!first) sb.Append(",");
bool first2 = true;
foreach(ByteCode pushedBy in slot.PushedBy) {
foreach(ByteCode defs in slot.Definitions) {
if (!first2) sb.Append("|");
sb.AppendFormat("IL_{0:X2}", pushedBy.Offset);
sb.AppendFormat("IL_{0:X2}", defs.Offset);
first2 = false;
}
first = false;
@ -197,13 +182,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -197,13 +182,11 @@ namespace ICSharpCode.Decompiler.ILAst
bool first = true;
foreach (VariableSlot varSlot in this.VariablesBefore) {
if (!first) sb.Append(",");
if (varSlot.StoredByAll) {
sb.Append("*");
} else if (varSlot.StoredBy.Length == 0) {
sb.Append("_");
if (varSlot.UnknownDefinition) {
sb.Append("?");
} else {
bool first2 = true;
foreach (ByteCode storedBy in varSlot.StoredBy) {
foreach (ByteCode storedBy in varSlot.Definitions) {
if (!first2) sb.Append("|");
sb.AppendFormat("IL_{0:X2}", storedBy.Offset);
first2 = false;
@ -290,8 +273,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -290,8 +273,8 @@ namespace ICSharpCode.Decompiler.ILAst
if(methodDef.Body.HasExceptionHandlers) {
foreach(ExceptionHandler ex in methodDef.Body.ExceptionHandlers) {
ByteCode handlerStart = instrToByteCode[ex.HandlerStart];
handlerStart.StackBefore = new List<StackSlot>();
handlerStart.VariablesBefore = VariableSlot.MakeFullState(varCount);
handlerStart.StackBefore = new StackSlot[0];
handlerStart.VariablesBefore = VariableSlot.MakeUknownState(varCount);
if (ex.HandlerType == ExceptionHandlerType.Catch || ex.HandlerType == ExceptionHandlerType.Filter) {
// Catch and Filter handlers start with the exeption on the stack
ByteCode ldexception = new ByteCode() {
@ -301,15 +284,13 @@ namespace ICSharpCode.Decompiler.ILAst @@ -301,15 +284,13 @@ namespace ICSharpCode.Decompiler.ILAst
PushCount = 1
};
ldexceptions[ex] = ldexception;
handlerStart.StackBefore.Add(new StackSlot(ldexception));
handlerStart.StackBefore = new StackSlot[] { new StackSlot(new [] { ldexception }, null) };
}
agenda.Push(handlerStart);
if (ex.HandlerType == ExceptionHandlerType.Filter)
{
ByteCode filterStart = instrToByteCode[ex.FilterStart];
filterStart.StackBefore = new List<StackSlot>();
filterStart.VariablesBefore = VariableSlot.MakeFullState(varCount);
ByteCode ldexception = new ByteCode() {
Code = ILCode.Ldexception,
Operand = ex.CatchType,
@ -317,14 +298,15 @@ namespace ICSharpCode.Decompiler.ILAst @@ -317,14 +298,15 @@ namespace ICSharpCode.Decompiler.ILAst
PushCount = 1
};
// TODO: ldexceptions[ex] = ldexception;
filterStart.StackBefore.Add(new StackSlot(ldexception));
filterStart.StackBefore = new StackSlot[] { new StackSlot(new [] { ldexception }, null) };
filterStart.VariablesBefore = VariableSlot.MakeUknownState(varCount);
agenda.Push(filterStart);
}
}
}
body[0].StackBefore = new List<StackSlot>();
body[0].VariablesBefore = VariableSlot.MakeEmptyState(varCount);
body[0].StackBefore = new StackSlot[0];
body[0].VariablesBefore = VariableSlot.MakeUknownState(varCount);
agenda.Push(body[0]);
// Process agenda
@ -332,22 +314,17 @@ namespace ICSharpCode.Decompiler.ILAst @@ -332,22 +314,17 @@ namespace ICSharpCode.Decompiler.ILAst
ByteCode byteCode = agenda.Pop();
// Calculate new stack
List<StackSlot> newStack = StackSlot.CloneStack(byteCode.StackBefore, byteCode.PopCount);
for (int i = 0; i < byteCode.PushCount; i++) {
newStack.Add(new StackSlot(byteCode));
}
StackSlot[] newStack = StackSlot.ModifyStack(byteCode.StackBefore, byteCode.PopCount ?? byteCode.StackBefore.Length, byteCode.PushCount, byteCode);
// Calculate new variable state
VariableSlot[] newVariableState = VariableSlot.CloneVariableState(byteCode.VariablesBefore);
if (byteCode.Code == ILCode.Stloc || byteCode.Code == ILCode.Ldloca) {
int varIndex = ((VariableReference)byteCode.Operand).Index;
newVariableState[varIndex] = byteCode.Code == ILCode.Stloc || byteCode.Next.Code == ILCode.Initobj ?
new VariableSlot(byteCode) : new VariableSlot(newVariableState[varIndex].StoredBy.Union(byteCode), false);
if (byteCode.IsVariableDefinition) {
newVariableState[((VariableReference)byteCode.Operand).Index] = new VariableSlot(new [] { byteCode }, false);
}
// After the leave, finally block might have touched the variables
if (byteCode.Code == ILCode.Leave) {
newVariableState = VariableSlot.MakeFullState(varCount);
newVariableState = VariableSlot.MakeUknownState(varCount);
}
// Find all successors
@ -386,12 +363,12 @@ namespace ICSharpCode.Decompiler.ILAst @@ -386,12 +363,12 @@ namespace ICSharpCode.Decompiler.ILAst
branchTarget.VariablesBefore = newVariableState;
} else {
// Do not share data for several bytecodes
branchTarget.StackBefore = StackSlot.CloneStack(newStack, 0);
branchTarget.StackBefore = StackSlot.ModifyStack(newStack, 0, 0, null);
branchTarget.VariablesBefore = VariableSlot.CloneVariableState(newVariableState);
}
agenda.Push(branchTarget);
} else {
if (branchTarget.StackBefore.Count != newStack.Count) {
if (branchTarget.StackBefore.Length != newStack.Length) {
throw new Exception("Inconsistent stack size at " + byteCode.Name);
}
@ -401,11 +378,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -401,11 +378,11 @@ namespace ICSharpCode.Decompiler.ILAst
bool modified = false;
// Merge stacks - modify the target
for (int i = 0; i < newStack.Count; i++) {
ByteCode[] oldPushedBy = branchTarget.StackBefore[i].PushedBy;
ByteCode[] newPushedBy = oldPushedBy.Union(newStack[i].PushedBy);
if (newPushedBy.Length > oldPushedBy.Length) {
branchTarget.StackBefore[i] = new StackSlot(newPushedBy, null);
for (int i = 0; i < newStack.Length; i++) {
ByteCode[] oldDefs = branchTarget.StackBefore[i].Definitions;
ByteCode[] newDefs = oldDefs.Union(newStack[i].Definitions);
if (newDefs.Length > oldDefs.Length) {
branchTarget.StackBefore[i] = new StackSlot(newDefs, null);
modified = true;
}
}
@ -414,16 +391,15 @@ namespace ICSharpCode.Decompiler.ILAst @@ -414,16 +391,15 @@ namespace ICSharpCode.Decompiler.ILAst
for (int i = 0; i < newVariableState.Length; i++) {
VariableSlot oldSlot = branchTarget.VariablesBefore[i];
VariableSlot newSlot = newVariableState[i];
// All can not be unioned further
if (!oldSlot.StoredByAll) {
if (newSlot.StoredByAll) {
if (!oldSlot.UnknownDefinition) {
if (newSlot.UnknownDefinition) {
branchTarget.VariablesBefore[i] = newSlot;
modified = true;
} else {
ByteCode[] oldStoredBy = oldSlot.StoredBy;
ByteCode[] newStoredBy = oldStoredBy.Union(newSlot.StoredBy);
if (newStoredBy.Length > oldStoredBy.Length) {
branchTarget.VariablesBefore[i] = new VariableSlot(newStoredBy, false);
ByteCode[] oldDefs = oldSlot.Definitions;
ByteCode[] newDefs = oldDefs.Union(newSlot.Definitions);
if (newDefs.Length > oldDefs.Length) {
branchTarget.VariablesBefore[i] = new VariableSlot(newDefs, false);
modified = true;
}
}
@ -437,18 +413,18 @@ namespace ICSharpCode.Decompiler.ILAst @@ -437,18 +413,18 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
// Occasionally the compilers or obfuscators generate unreachable code (which migt be intentonally invalid)
// Occasionally the compilers or obfuscators generate unreachable code (which might be intentonally invalid)
// I belive it is safe to just remove it
body.RemoveAll(b => b.StackBefore == null);
// Genertate temporary variables to replace stack
foreach(ByteCode byteCode in body) {
int argIdx = 0;
int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count;
for (int i = byteCode.StackBefore.Count - popCount; i < byteCode.StackBefore.Count; i++) {
int popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
for (int i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++) {
ILVariable tmpVar = new ILVariable() { Name = string.Format("arg_{0:X2}_{1}", byteCode.Offset, argIdx), IsGenerated = true };
byteCode.StackBefore[i] = new StackSlot(byteCode.StackBefore[i].PushedBy, tmpVar);
foreach(ByteCode pushedBy in byteCode.StackBefore[i].PushedBy) {
byteCode.StackBefore[i] = new StackSlot(byteCode.StackBefore[i].Definitions, tmpVar);
foreach(ByteCode pushedBy in byteCode.StackBefore[i].Definitions) {
if (pushedBy.StoreTo == null) {
pushedBy.StoreTo = new List<ILVariable>(1);
}
@ -467,16 +443,16 @@ namespace ICSharpCode.Decompiler.ILAst @@ -467,16 +443,16 @@ namespace ICSharpCode.Decompiler.ILAst
var loadedBy = locVars.Select(locVar => body.SelectMany(bc => bc.StackBefore).Single(s => s.LoadFrom == locVar)).ToList();
// We now know that all the variables have a single load,
// Let's make sure that they have also a single store - us
if (loadedBy.All(slot => slot.PushedBy.Length == 1 && slot.PushedBy[0] == byteCode)) {
if (loadedBy.All(slot => slot.Definitions.Length == 1 && slot.Definitions[0] == byteCode)) {
// Great - we can reduce everything into single variable
ILVariable tmpVar = new ILVariable() { Name = string.Format("expr_{0:X2}", byteCode.Offset), IsGenerated = true };
byteCode.StoreTo = new List<ILVariable>() { tmpVar };
foreach(ByteCode bc in body) {
for (int i = 0; i < bc.StackBefore.Count; i++) {
for (int i = 0; i < bc.StackBefore.Length; i++) {
// Is it one of the variable to be merged?
if (locVars.Contains(bc.StackBefore[i].LoadFrom)) {
// Replace with the new temp variable
bc.StackBefore[i] = new StackSlot(bc.StackBefore[i].PushedBy, tmpVar);
bc.StackBefore[i] = new StackSlot(bc.StackBefore[i].Definitions, tmpVar);
}
}
}
@ -505,12 +481,42 @@ namespace ICSharpCode.Decompiler.ILAst @@ -505,12 +481,42 @@ namespace ICSharpCode.Decompiler.ILAst
return body;
}
static bool IsDeterministicLdloca(ByteCode b)
{
var v = b.Operand;
b = b.Next;
if (b.Code == ILCode.Initobj) return true;
// instance method calls on value types use the variable ref deterministically
int stack = 1;
while (true) {
if (b.PopCount == null) return false;
stack -= b.PopCount.GetValueOrDefault();
if (stack == 0) break;
if (stack < 0) return false;
if (b.Code.IsConditionalControlFlow() || b.Code.IsUnconditionalControlFlow()) return false;
switch (b.Code) {
case ILCode.Ldloc:
case ILCode.Ldloca:
case ILCode.Stloc:
if (b.Operand == v) return false;
break;
}
stack += b.PushCount;
b = b.Next;
if (b == null) return false;
}
if (b.Code == ILCode.Ldfld || b.Code == ILCode.Stfld)
return true;
return (b.Code == ILCode.Call || b.Code == ILCode.Callvirt) && ((MethodReference)b.Operand).HasThis;
}
class VariableInfo
sealed class VariableInfo
{
public ILVariable Variable;
public List<ByteCode> Stores;
public List<ByteCode> Loads;
public List<ByteCode> Defs;
public List<ByteCode> Uses;
}
/// <summary>
@ -519,110 +525,75 @@ namespace ICSharpCode.Decompiler.ILAst @@ -519,110 +525,75 @@ namespace ICSharpCode.Decompiler.ILAst
/// </summary>
void ConvertLocalVariables(List<ByteCode> body)
{
if (optimize) {
int varCount = methodDef.Body.Variables.Count;
foreach(VariableDefinition varDef in methodDef.Body.Variables) {
for(int variableIndex = 0; variableIndex < varCount; variableIndex++) {
// Find all stores and loads for this variable
var stores = body.Where(b => (b.Code == ILCode.Stloc || b.Code == ILCode.Ldloca) && b.Operand is VariableDefinition && b.OperandAsVariable.Index == variableIndex).ToList();
// ldloca on an uninitialized variable or followed by initobj isn't considered a load
var loads = body.Where(b =>
(b.Code == ILCode.Ldloc || (b.Code == ILCode.Ldloca && b.Next.Code != ILCode.Initobj &&
(b.VariablesBefore[variableIndex].StoredBy.Length != 0 || b.VariablesBefore[variableIndex].StoredByAll)))
&& b.Operand is VariableDefinition && b.OperandAsVariable.Index == variableIndex).ToList();
TypeReference varType = methodDef.Body.Variables[variableIndex].VariableType;
// Find all definitions and uses of this variable
var defs = body.Where(b => b.Operand == varDef && b.IsVariableDefinition).ToList();
var uses = body.Where(b => b.Operand == varDef && !b.IsVariableDefinition).ToList();
List<VariableInfo> newVars;
// If the variable is pinned, use single variable.
// If any of the uses is from unknown definition, use single variable
// If any of the uses is ldloca with a nondeterministic usage pattern, use single variable
if (!optimize || varDef.IsPinned || uses.Any(b => b.VariablesBefore[varDef.Index].UnknownDefinition || (b.Code == ILCode.Ldloca && !IsDeterministicLdloca(b)))) {
newVars = new List<VariableInfo>(1) { new VariableInfo() {
Variable = new ILVariable() {
Name = string.IsNullOrEmpty(varDef.Name) ? "var_" + varDef.Index : varDef.Name,
Type = varDef.IsPinned ? ((PinnedType)varDef.VariableType).ElementType : varDef.VariableType,
OriginalVariable = varDef
},
Defs = defs,
Uses = uses
}};
} else {
// Create a new variable for each definition
newVars = defs.Select(def => new VariableInfo() {
Variable = new ILVariable() {
Name = (string.IsNullOrEmpty(varDef.Name) ? "var_" + varDef.Index : varDef.Name) + "_" + def.Offset.ToString("X2"),
Type = varDef.VariableType,
OriginalVariable = varDef
},
Defs = new List<ByteCode>() { def },
Uses = new List<ByteCode>()
}).ToList();
List<VariableInfo> newVars;
// VB.NET uses the 'init' to allow use of uninitialized variables.
// We do not really care about them too much - if the original variable
// was uninitialized at that point it means that no store was called and
// thus all our new variables must be uninitialized as well.
// So it does not matter which one we load.
bool isPinned = methodDef.Body.Variables[variableIndex].IsPinned;
// If the variable is pinned, use single variable.
// If any of the loads is from "all", use single variable
if (isPinned || loads.Any(b => b.VariablesBefore[variableIndex].StoredByAll)) {
newVars = new List<VariableInfo>(1) { new VariableInfo() {
Variable = new ILVariable() {
Name = "var_" + variableIndex,
Type = isPinned ? ((PinnedType)varType).ElementType : varType,
OriginalVariable = methodDef.Body.Variables[variableIndex]
},
Stores = stores,
Loads = loads
}};
} else {
// Create a new variable for each store
newVars = stores.Where(st =>
{
if (st.Code == ILCode.Stloc || st.Next.Code == ILCode.Initobj) return true;
var storedBy = st.VariablesBefore[variableIndex].StoredBy;
return storedBy.Length == 0 || storedBy[0] == st;
}).Select(st => new VariableInfo() {
Variable = new ILVariable() {
Name = "var_" + variableIndex + "_" + st.Offset.ToString("X2"),
Type = varType,
OriginalVariable = methodDef.Body.Variables[variableIndex]
},
Stores = new List<ByteCode>() {st},
Loads = new List<ByteCode>()
}).ToList();
// VB.NET uses the 'init' to allow use of uninitialized variables.
// We do not really care about them too much - if the original variable
// was uninitialized at that point it means that no store was called and
// thus all our new variables must be uninitialized as well.
// So it does not matter which one we load.
// TODO: We should add explicit initialization so that C# code compiles.
// Remember to handle cases where one path inits the variable, but other does not.
// Add loads to the data structure; merge variables if necessary
foreach(ByteCode load in loads) {
ByteCode[] storedBy = load.VariablesBefore[variableIndex].StoredBy;
if (storedBy.Length == 0) {
// Load which always loads the default ('uninitialized') value
// Create a dummy variable just for this load
newVars.Add(new VariableInfo() {
Variable = new ILVariable() {
Name = "var_" + variableIndex + "_" + load.Offset.ToString("X2") + "_default",
Type = varType,
OriginalVariable = methodDef.Body.Variables[variableIndex]
},
Stores = new List<ByteCode>(),
Loads = new List<ByteCode>() { load }
});
} else if (storedBy.Length == 1) {
VariableInfo newVar = newVars.Single(v => v.Stores.Contains(storedBy[0]));
newVar.Loads.Add(load);
if (load.Code == ILCode.Ldloca) newVar.Stores.Add(load);
} else {
List<VariableInfo> mergeVars = newVars.Where(v => v.Stores.Intersect(storedBy).Any()).ToList();
VariableInfo mergedVar = new VariableInfo() {
Variable = mergeVars[0].Variable,
Stores = mergeVars.SelectMany(v => v.Stores).ToList(),
Loads = mergeVars.SelectMany(v => v.Loads).ToList()
};
mergedVar.Loads.Add(load);
if (load.Code == ILCode.Ldloca) mergedVar.Stores.Add(load);
newVars = newVars.Except(mergeVars).ToList();
newVars.Add(mergedVar);
}
}
}
// TODO: We should add explicit initialization so that C# code compiles.
// Remember to handle cases where one path inits the variable, but other does not.
// Set bytecode operands
foreach(VariableInfo newVar in newVars) {
foreach(ByteCode store in newVar.Stores) {
store.Operand = newVar.Variable;
}
foreach(ByteCode load in newVar.Loads) {
load.Operand = newVar.Variable;
// Add loads to the data structure; merge variables if necessary
foreach(ByteCode use in uses) {
ByteCode[] useDefs = use.VariablesBefore[varDef.Index].Definitions;
if (useDefs.Length == 1) {
VariableInfo newVar = newVars.Single(v => v.Defs.Contains(useDefs[0]));
newVar.Uses.Add(use);
} else {
List<VariableInfo> mergeVars = newVars.Where(v => v.Defs.Intersect(useDefs).Any()).ToList();
VariableInfo mergedVar = new VariableInfo() {
Variable = mergeVars[0].Variable,
Defs = mergeVars.SelectMany(v => v.Defs).ToList(),
Uses = mergeVars.SelectMany(v => v.Uses).ToList()
};
mergedVar.Uses.Add(use);
newVars = newVars.Except(mergeVars).ToList();
newVars.Add(mergedVar);
}
}
}
} else {
var variables = methodDef.Body.Variables.Select(v => new ILVariable() { Name = string.IsNullOrEmpty(v.Name) ? "var_" + v.Index : v.Name, Type = v.VariableType, OriginalVariable = v }).ToList();
foreach(ByteCode byteCode in body) {
if (byteCode.Code == ILCode.Ldloc || byteCode.Code == ILCode.Stloc || byteCode.Code == ILCode.Ldloca) {
int index = ((VariableDefinition)byteCode.Operand).Index;
byteCode.Operand = variables[index];
// Set bytecode operands
foreach(VariableInfo newVar in newVars) {
foreach(ByteCode def in newVar.Defs) {
def.Operand = newVar.Variable;
}
foreach(ByteCode use in newVar.Uses) {
use.Operand = newVar.Variable;
}
}
}
@ -795,8 +766,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -795,8 +766,8 @@ namespace ICSharpCode.Decompiler.ILAst
}
// Reference arguments using temporary variables
int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count;
for (int i = byteCode.StackBefore.Count - popCount; i < byteCode.StackBefore.Count; i++) {
int popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
for (int i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++) {
StackSlot slot = byteCode.StackBefore[i];
expr.Arguments.Add(new ILExpression(ILCode.Ldloc, slot.LoadFrom));
}
@ -838,7 +809,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -838,7 +809,7 @@ namespace ICSharpCode.Decompiler.ILAst
if (Array.IndexOf(a, b) >= 0)
return a;
var res = new T[a.Length + 1];
Array.Copy(a, res, a.Length);
Array.Copy(a, 0, res, 0, a.Length);
res[res.Length - 1] = b;
return res;
}

2
src/Libraries/ICSharpCode.Decompiler/ILAst/LiftedOperators.cs

@ -515,7 +515,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -515,7 +515,7 @@ namespace ICSharpCode.Decompiler.ILAst
{
// IL ranges from removed nodes are assigned to the new operator expression
var removednodes = expr.GetSelfAndChildrenRecursive<ILExpression>().Except(n.GetSelfAndChildrenRecursive<ILExpression>());
n.ILRanges = ILRange.OrderAndJoint(n.ILRanges.Concat(removednodes.SelectMany(el => el.ILRanges)));
n.ILRanges.AddRange(removednodes.SelectMany(el => el.ILRanges));
// the new expression is wrapped in a container so that negations aren't pushed through lifted comparison operations
expr.Code = ILCode.Wrap;
expr.Arguments.Clear();

2
src/Libraries/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -799,7 +799,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -799,7 +799,7 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Dup:
{
var arg = expr.Arguments.Single();
return arg.ExpectedType = InferTypeForExpression(expr.Arguments.Single(), expectedType);
return arg.ExpectedType = InferTypeForExpression(arg, expectedType);
}
default:
Debug.WriteLine("Type Inference: Can't handle " + expr.Code.GetName());

4
src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs

@ -19,8 +19,8 @@ using System.Runtime.InteropServices; @@ -19,8 +19,8 @@ using System.Runtime.InteropServices;
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("2.0.0.1486")]
[assembly: AssemblyInformationalVersion("2.0.0.1486-becc8f14")]
[assembly: AssemblyVersion("2.0.0.1509")]
[assembly: AssemblyInformationalVersion("2.0.0.1509-09c2b45f")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",

1
src/Libraries/ICSharpCode.Decompiler/Tests/ValueTypes.cs

@ -52,6 +52,7 @@ public static class ValueTypes @@ -52,6 +52,7 @@ public static class ValueTypes
private static readonly ValueTypes.S ReadOnlyS = default(ValueTypes.S);
private static ValueTypes.S MutableS = default(ValueTypes.S);
private static volatile int VolatileInt;
public static void CallMethodViaField()
{

94
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs

@ -24,7 +24,7 @@ using System.Threading; @@ -24,7 +24,7 @@ using System.Threading;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.CSharp.Analysis
{
@ -145,38 +145,35 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -145,38 +145,35 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
protected virtual ControlFlowNode CreateNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type)
{
cancellationToken.ThrowIfCancellationRequested();
return new ControlFlowNode(previousStatement, nextStatement, type);
}
protected virtual ControlFlowEdge CreateEdge(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type)
{
cancellationToken.ThrowIfCancellationRequested();
return new ControlFlowEdge(from, to, type);
}
Statement rootStatement;
ResolveVisitor resolveVisitor;
CSharpAstResolver resolver;
List<ControlFlowNode> nodes;
Dictionary<string, ControlFlowNode> labels;
List<ControlFlowNode> gotoStatements;
CancellationToken cancellationToken;
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, ITypeResolveContext context)
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, CancellationToken cancellationToken = default(CancellationToken))
{
return BuildControlFlowGraph(statement, context, CancellationToken.None);
CSharpResolver r = new CSharpResolver(MinimalCorlib.Instance.CreateCompilation());
return BuildControlFlowGraph(statement, new CSharpAstResolver(r, statement), cancellationToken);
}
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, ITypeResolveContext context, CancellationToken cancellationToken)
{
return BuildControlFlowGraph(statement, new ResolveVisitor(
new CSharpResolver(context, cancellationToken),
null));
}
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, ResolveVisitor resolveVisitor)
public IList<ControlFlowNode> BuildControlFlowGraph(Statement statement, CSharpAstResolver resolver, CancellationToken cancellationToken = default(CancellationToken))
{
if (statement == null)
throw new ArgumentNullException("statement");
if (resolveVisitor == null)
throw new ArgumentNullException("resolveVisitor");
if (resolver == null)
throw new ArgumentNullException("resolver");
NodeCreationVisitor nodeCreationVisitor = new NodeCreationVisitor();
nodeCreationVisitor.builder = this;
@ -185,7 +182,9 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -185,7 +182,9 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
this.labels = new Dictionary<string, ControlFlowNode>();
this.gotoStatements = new List<ControlFlowNode>();
this.rootStatement = statement;
this.resolveVisitor = resolveVisitor;
this.resolver = resolver;
this.cancellationToken = cancellationToken;
ControlFlowNode entryPoint = CreateStartNode(statement);
statement.AcceptVisitor(nodeCreationVisitor, entryPoint);
@ -205,7 +204,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -205,7 +204,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
this.labels = null;
this.gotoStatements = null;
this.rootStatement = null;
this.resolveVisitor = null;
this.resolver = null;
this.cancellationToken = CancellationToken.None;
}
}
@ -282,13 +282,13 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -282,13 +282,13 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// Evaluates an expression.
/// </summary>
/// <returns>The constant value of the expression; or null if the expression is not a constant.</returns>
ConstantResolveResult EvaluateConstant(Expression expr)
ResolveResult EvaluateConstant(Expression expr)
{
if (EvaluateOnlyPrimitiveConstants) {
if (!(expr is PrimitiveExpression || expr is NullReferenceExpression))
return null;
}
return resolveVisitor.Resolve(expr) as ConstantResolveResult;
return resolver.Resolve(expr, cancellationToken);
}
/// <summary>
@ -297,18 +297,18 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -297,18 +297,18 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// <returns>The value of the constant boolean expression; or null if the value is not a constant boolean expression.</returns>
bool? EvaluateCondition(Expression expr)
{
ConstantResolveResult rr = EvaluateConstant(expr);
if (rr != null)
ResolveResult rr = EvaluateConstant(expr);
if (rr != null && rr.IsCompileTimeConstant)
return rr.ConstantValue as bool?;
else
return null;
}
bool AreEqualConstants(ConstantResolveResult c1, ConstantResolveResult c2)
bool AreEqualConstants(ResolveResult c1, ResolveResult c2)
{
if (c1 == null || c2 == null)
if (c1 == null || c2 == null || !c1.IsCompileTimeConstant || !c2.IsCompileTimeConstant)
return false;
CSharpResolver r = new CSharpResolver(resolveVisitor.TypeResolveContext, resolveVisitor.CancellationToken);
CSharpResolver r = new CSharpResolver(resolver.TypeResolveContext);
ResolveResult c = r.ResolveBinaryOperator(BinaryOperatorType.Equality, c1, c2);
return c.IsCompileTimeConstant && (c.ConstantValue as bool?) == true;
}
@ -422,35 +422,40 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -422,35 +422,40 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
public override ControlFlowNode VisitSwitchStatement(SwitchStatement switchStatement, ControlFlowNode data)
{
// First, figure out which switch section will get called (if the expression is constant):
ConstantResolveResult constant = builder.EvaluateConstant(switchStatement.Expression);
ResolveResult constant = builder.EvaluateConstant(switchStatement.Expression);
SwitchSection defaultSection = null;
SwitchSection sectionMatchedByConstant = null;
foreach (SwitchSection section in switchStatement.SwitchSections) {
foreach (CaseLabel label in section.CaseLabels) {
if (label.Expression.IsNull) {
defaultSection = section;
} else if (constant != null) {
ConstantResolveResult labelConstant = builder.EvaluateConstant(label.Expression);
} else if (constant != null && constant.IsCompileTimeConstant) {
ResolveResult labelConstant = builder.EvaluateConstant(label.Expression);
if (builder.AreEqualConstants(constant, labelConstant))
sectionMatchedByConstant = section;
}
}
}
if (constant != null && sectionMatchedByConstant == null)
if (constant != null && constant.IsCompileTimeConstant && sectionMatchedByConstant == null)
sectionMatchedByConstant = defaultSection;
int gotoCaseOrDefaultInOuterScope = gotoCaseOrDefault.Count;
List<ControlFlowNode> sectionStartNodes = new List<ControlFlowNode>();
ControlFlowNode end = builder.CreateEndNode(switchStatement, addToNodeList: false);
breakTargets.Push(end);
foreach (SwitchSection section in switchStatement.SwitchSections) {
if (constant == null || section == sectionMatchedByConstant) {
int sectionStartNodeID = builder.nodes.Count;
if (constant == null || !constant.IsCompileTimeConstant || section == sectionMatchedByConstant) {
HandleStatementList(section.Statements, data);
} else {
// This section is unreachable: pass null to HandleStatementList.
HandleStatementList(section.Statements, null);
}
// Don't bother connecting the ends of the sections: the 'break' statement takes care of that.
// Store the section start node for 'goto case' statements.
sectionStartNodes.Add(sectionStartNodeID < builder.nodes.Count ? builder.nodes[sectionStartNodeID] : null);
}
breakTargets.Pop();
if (defaultSection == null && sectionMatchedByConstant == null) {
@ -459,7 +464,38 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -459,7 +464,38 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
if (gotoCaseOrDefault.Count > gotoCaseOrDefaultInOuterScope) {
// Resolve 'goto case' statements:
throw new NotImplementedException();
for (int i = gotoCaseOrDefaultInOuterScope; i < gotoCaseOrDefault.Count; i++) {
ControlFlowNode gotoCaseNode = gotoCaseOrDefault[i];
GotoCaseStatement gotoCaseStatement = gotoCaseNode.NextStatement as GotoCaseStatement;
ResolveResult gotoCaseConstant = null;
if (gotoCaseStatement != null) {
gotoCaseConstant = builder.EvaluateConstant(gotoCaseStatement.LabelExpression);
}
int targetSectionIndex = -1;
int currentSectionIndex = 0;
foreach (SwitchSection section in switchStatement.SwitchSections) {
foreach (CaseLabel label in section.CaseLabels) {
if (gotoCaseStatement != null) {
// goto case
if (!label.Expression.IsNull) {
ResolveResult labelConstant = builder.EvaluateConstant(label.Expression);
if (builder.AreEqualConstants(gotoCaseConstant, labelConstant))
targetSectionIndex = currentSectionIndex;
}
} else {
// goto default
if (label.Expression.IsNull)
targetSectionIndex = currentSectionIndex;
}
}
currentSectionIndex++;
}
if (targetSectionIndex >= 0 && sectionStartNodes[targetSectionIndex] != null)
Connect(gotoCaseNode, sectionStartNodes[targetSectionIndex], ControlFlowEdgeType.Jump);
else
Connect(gotoCaseNode, end, ControlFlowEdgeType.Jump);
}
gotoCaseOrDefault.RemoveRange(gotoCaseOrDefaultInOuterScope, gotoCaseOrDefault.Count - gotoCaseOrDefaultInOuterScope);
}
builder.nodes.Add(end);

110
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs

@ -81,56 +81,42 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -81,56 +81,42 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
}
}
readonly DerivedControlFlowGraphBuilder cfgBuilder = new DerivedControlFlowGraphBuilder();
readonly DefiniteAssignmentVisitor visitor = new DefiniteAssignmentVisitor();
readonly List<DefiniteAssignmentNode> allNodes = new List<DefiniteAssignmentNode>();
readonly Dictionary<Statement, DefiniteAssignmentNode> beginNodeDict = new Dictionary<Statement, DefiniteAssignmentNode>();
readonly Dictionary<Statement, DefiniteAssignmentNode> endNodeDict = new Dictionary<Statement, DefiniteAssignmentNode>();
readonly Dictionary<Statement, DefiniteAssignmentNode> conditionNodeDict = new Dictionary<Statement, DefiniteAssignmentNode>();
readonly ResolveVisitor resolveVisitor;
readonly CancellationToken cancellationToken;
readonly CSharpAstResolver resolver;
Dictionary<ControlFlowEdge, DefiniteAssignmentStatus> edgeStatus = new Dictionary<ControlFlowEdge, DefiniteAssignmentStatus>();
string variableName;
List<IdentifierExpression> unassignedVariableUses = new List<IdentifierExpression>();
int analyzedRangeStart, analyzedRangeEnd;
CancellationToken analysisCancellationToken;
Queue<DefiniteAssignmentNode> nodesWithModifiedInput = new Queue<DefiniteAssignmentNode>();
public DefiniteAssignmentAnalysis(Statement rootStatement)
: this(rootStatement, null, CancellationToken.None)
{
}
public DefiniteAssignmentAnalysis(Statement rootStatement, CancellationToken cancellationToken)
: this(rootStatement, null, cancellationToken)
{
}
public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context)
: this(rootStatement, context, CancellationToken.None)
: this(rootStatement,
new CSharpAstResolver(new CSharpResolver(MinimalCorlib.Instance.CreateCompilation()), rootStatement),
cancellationToken)
{
}
public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context, CancellationToken cancellationToken)
: this(rootStatement, new ResolveVisitor(new CSharpResolver(context ?? MinimalResolveContext.Instance, cancellationToken),
null))
{
}
public DefiniteAssignmentAnalysis(Statement rootStatement, ResolveVisitor resolveVisitor)
public DefiniteAssignmentAnalysis(Statement rootStatement, CSharpAstResolver resolver, CancellationToken cancellationToken)
{
if (rootStatement == null)
throw new ArgumentNullException("rootStatement");
if (resolveVisitor == null)
throw new ArgumentNullException("resolveVisitor");
this.resolveVisitor = resolveVisitor;
this.cancellationToken = resolveVisitor.CancellationToken;
if (resolver == null)
throw new ArgumentNullException("resolver");
this.resolver = resolver;
visitor.analysis = this;
if (resolveVisitor.TypeResolveContext is MinimalResolveContext) {
DerivedControlFlowGraphBuilder cfgBuilder = new DerivedControlFlowGraphBuilder();
if (resolver.TypeResolveContext.Compilation.MainAssembly.UnresolvedAssembly is MinimalCorlib) {
cfgBuilder.EvaluateOnlyPrimitiveConstants = true;
}
allNodes.AddRange(cfgBuilder.BuildControlFlowGraph(rootStatement, resolveVisitor).Cast<DefiniteAssignmentNode>());
allNodes.AddRange(cfgBuilder.BuildControlFlowGraph(rootStatement, resolver, cancellationToken).Cast<DefiniteAssignmentNode>());
for (int i = 0; i < allNodes.Count; i++) {
DefiniteAssignmentNode node = allNodes[i];
node.Index = i; // assign numbers to the nodes
@ -138,7 +124,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -138,7 +124,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
// Anonymous methods have separate control flow graphs, but we also need to analyze those.
// Iterate backwards so that anonymous methods are inserted in the correct order
for (AstNode child = node.NextStatement.LastChild; child != null; child = child.PrevSibling) {
InsertAnonymousMethods(i + 1, child);
InsertAnonymousMethods(i + 1, child, cfgBuilder, cancellationToken);
}
}
// Now register the node in the dictionaries:
@ -159,25 +145,25 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -159,25 +145,25 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
this.analyzedRangeEnd = allNodes.Count - 1;
}
void InsertAnonymousMethods(int insertPos, AstNode node)
void InsertAnonymousMethods(int insertPos, AstNode node, ControlFlowGraphBuilder cfgBuilder, CancellationToken cancellationToken)
{
// Ignore any statements, as those have their own ControlFlowNode and get handled separately
if (node is Statement)
return;
AnonymousMethodExpression ame = node as AnonymousMethodExpression;
if (ame != null) {
allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph(ame.Body, resolveVisitor).Cast<DefiniteAssignmentNode>());
allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph(ame.Body, resolver, cancellationToken).Cast<DefiniteAssignmentNode>());
return;
}
LambdaExpression lambda = node as LambdaExpression;
if (lambda != null && lambda.Body is Statement) {
allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph((Statement)lambda.Body, resolveVisitor).Cast<DefiniteAssignmentNode>());
allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph((Statement)lambda.Body, resolver, cancellationToken).Cast<DefiniteAssignmentNode>());
return;
}
// Descend into child expressions
// Iterate backwards so that anonymous methods are inserted in the correct order
for (AstNode child = node.LastChild; child != null; child = child.PrevSibling) {
InsertAnonymousMethods(insertPos, child);
InsertAnonymousMethods(insertPos, child, cfgBuilder, cancellationToken);
}
}
@ -209,26 +195,32 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -209,26 +195,32 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
this.analyzedRangeEnd = endIndex;
}
public void Analyze(string variable, DefiniteAssignmentStatus initialStatus = DefiniteAssignmentStatus.PotentiallyAssigned)
public void Analyze(string variable, DefiniteAssignmentStatus initialStatus = DefiniteAssignmentStatus.PotentiallyAssigned, CancellationToken cancellationToken = default(CancellationToken))
{
this.analysisCancellationToken = cancellationToken;
this.variableName = variable;
// Reset the status:
unassignedVariableUses.Clear();
foreach (DefiniteAssignmentNode node in allNodes) {
node.NodeStatus = DefiniteAssignmentStatus.CodeUnreachable;
foreach (ControlFlowEdge edge in node.Outgoing)
edgeStatus[edge] = DefiniteAssignmentStatus.CodeUnreachable;
}
ChangeNodeStatus(allNodes[analyzedRangeStart], initialStatus);
// Iterate as long as the input status of some nodes is changing:
while (nodesWithModifiedInput.Count > 0) {
DefiniteAssignmentNode node = nodesWithModifiedInput.Dequeue();
DefiniteAssignmentStatus inputStatus = DefiniteAssignmentStatus.CodeUnreachable;
foreach (ControlFlowEdge edge in node.Incoming) {
inputStatus = MergeStatus(inputStatus, edgeStatus[edge]);
try {
// Reset the status:
unassignedVariableUses.Clear();
foreach (DefiniteAssignmentNode node in allNodes) {
node.NodeStatus = DefiniteAssignmentStatus.CodeUnreachable;
foreach (ControlFlowEdge edge in node.Outgoing)
edgeStatus[edge] = DefiniteAssignmentStatus.CodeUnreachable;
}
ChangeNodeStatus(allNodes[analyzedRangeStart], initialStatus);
// Iterate as long as the input status of some nodes is changing:
while (nodesWithModifiedInput.Count > 0) {
DefiniteAssignmentNode node = nodesWithModifiedInput.Dequeue();
DefiniteAssignmentStatus inputStatus = DefiniteAssignmentStatus.CodeUnreachable;
foreach (ControlFlowEdge edge in node.Incoming) {
inputStatus = MergeStatus(inputStatus, edgeStatus[edge]);
}
ChangeNodeStatus(node, inputStatus);
}
ChangeNodeStatus(node, inputStatus);
} finally {
this.analysisCancellationToken = CancellationToken.None;
this.variableName = null;
}
}
@ -414,13 +406,9 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -414,13 +406,9 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// Evaluates an expression.
/// </summary>
/// <returns>The constant value of the expression; or null if the expression is not a constant.</returns>
ConstantResolveResult EvaluateConstant(Expression expr)
ResolveResult EvaluateConstant(Expression expr)
{
if (resolveVisitor.TypeResolveContext is MinimalResolveContext) {
if (!(expr is PrimitiveExpression || expr is NullReferenceExpression))
return null;
}
return resolveVisitor.Resolve(expr) as ConstantResolveResult;
return resolver.Resolve(expr, analysisCancellationToken);
}
/// <summary>
@ -429,8 +417,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -429,8 +417,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// <returns>The value of the constant boolean expression; or null if the value is not a constant boolean expression.</returns>
bool? EvaluateCondition(Expression expr)
{
ConstantResolveResult rr = EvaluateConstant(expr);
if (rr != null)
ResolveResult rr = EvaluateConstant(expr);
if (rr != null && rr.IsCompileTimeConstant)
return rr.ConstantValue as bool?;
else
return null;
@ -457,6 +445,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -457,6 +445,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
Debug.Assert(data == CleanSpecialValues(data));
DefiniteAssignmentStatus status = data;
foreach (AstNode child in node.Children) {
analysis.analysisCancellationToken.ThrowIfCancellationRequested();
Debug.Assert(!(child is Statement)); // statements are visited with the CFG, not with the visitor pattern
status = child.AcceptVisitor(this, status);
status = CleanSpecialValues(status);
@ -569,6 +559,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -569,6 +559,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
}
#endregion
#region Expressions
public override DefiniteAssignmentStatus VisitDirectionExpression(DirectionExpression directionExpression, DefiniteAssignmentStatus data)
{
if (directionExpression.FieldDirection == FieldDirection.Out) {
@ -678,8 +669,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -678,8 +669,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
return DefiniteAssignmentStatus.PotentiallyAssigned;
} else if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing) {
// C# 4.0 spec: §5.3.3.27 Definite assignment for ?? expressions
ConstantResolveResult crr = analysis.EvaluateConstant(binaryOperatorExpression.Left);
if (crr != null && crr.ConstantValue == null)
ResolveResult crr = analysis.EvaluateConstant(binaryOperatorExpression.Left);
if (crr != null && crr.IsCompileTimeConstant && crr.ConstantValue == null)
return binaryOperatorExpression.Right.AcceptVisitor(this, data);
DefiniteAssignmentStatus status = CleanSpecialValues(binaryOperatorExpression.Left.AcceptVisitor(this, data));
binaryOperatorExpression.Right.AcceptVisitor(this, status);
@ -763,6 +754,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -763,6 +754,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
}
return data;
}
#endregion
}
}
}

5
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs

@ -444,9 +444,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -444,9 +444,9 @@ namespace ICSharpCode.NRefactory.CSharp
public abstract S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data = default(T));
#region Pattern Matching
protected static bool MatchString (string name1, string name2)
protected static bool MatchString (string pattern, string text)
{
return string.IsNullOrEmpty (name1) || name1 == name2;
return PatternMatching.Pattern.MatchString(pattern, text);
}
protected internal abstract bool DoMatch (AstNode other, PatternMatching.Match match);
@ -663,6 +663,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -663,6 +663,7 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly Role<CSharpTokenNode> Assign = new Role<CSharpTokenNode> ("Assign", CSharpTokenNode.Null);
public static readonly Role<CSharpTokenNode> Colon = new Role<CSharpTokenNode> ("Colon", CSharpTokenNode.Null);
public static readonly Role<Comment> Comment = new Role<Comment> ("Comment");
public static readonly Role<PreProcessorDirective> PreProcessorDirective = new Role<PreProcessorDirective> ("PreProcessorDirective");
public static readonly Role<ErrorNode> Error = new Role<ErrorNode> ("Error");
}

1
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp
{

5
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs

@ -57,6 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -57,6 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp
Modifiers.Abstract, Modifiers.Virtual, Modifiers.Sealed, Modifiers.Static, Modifiers.Override,
Modifiers.Readonly, Modifiers.Volatile,
Modifiers.Extern, Modifiers.Partial, Modifiers.Const,
Modifiers.Async,
Modifiers.Any
};
@ -104,8 +105,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -104,8 +105,10 @@ namespace ICSharpCode.NRefactory.CSharp
return "volatile";
case Modifiers.Unsafe:
return "unsafe";
case Modifiers.Async:
return "async";
case Modifiers.Any:
// even though it's used for patterns only, it needs to be in this list to be usable in the AST
// even though it's used for pattern matching only, 'any' needs to be in this list to be usable in the AST
return "any";
default:
throw new NotSupportedException("Invalid value for Modifiers");

25
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
//
// CompilationUnit.cs
//
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
@ -25,11 +25,13 @@ @@ -25,11 +25,13 @@
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp
{
public class CompilationUnit : AstNode
public class CompilationUnit : AstNode
{
public static readonly Role<AstNode> MemberRole = new Role<AstNode>("Member", AstNode.Null);
@ -39,6 +41,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -39,6 +41,11 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
/// <summary>
/// Gets/Sets the file name of this compilation unit.
/// </summary>
public string FileName { get; set; }
List<Error> errors = new List<Error> ();
public List<Error> Errors {
@ -71,7 +78,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -71,7 +78,7 @@ namespace ICSharpCode.NRefactory.CSharp
yield return (TypeDeclaration)curNode;
foreach (var child in curNode.Children) {
if (!(child is Statement || child is Expression) &&
(child.Role != TypeDeclaration.MemberRole || (child is TypeDeclaration && includeInnerTypes)))
(child.Role != TypeDeclaration.MemberRole || (child is TypeDeclaration && includeInnerTypes)))
nodeStack.Push (child);
}
}
@ -87,6 +94,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -87,6 +94,18 @@ namespace ICSharpCode.NRefactory.CSharp
{
return visitor.VisitCompilationUnit (this, data);
}
/// <summary>
/// Converts this compilation unit into a parsed file that can be stored in the type system.
/// </summary>
public CSharpParsedFile ToTypeSystem()
{
if (string.IsNullOrEmpty(this.FileName))
throw new InvalidOperationException("Cannot use ToTypeSystem() on a compilation unit without file name.");
var v = new TypeSystemConvertVisitor(this.FileName);
v.VisitCompilationUnit(this, null);
return v.ParsedFile;
}
}
}

5
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs

@ -55,6 +55,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -55,6 +55,11 @@ namespace ICSharpCode.NRefactory.CSharp
return VisitChildren (comment, data);
}
public virtual S VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective, T data)
{
return VisitChildren (preProcessorDirective, data);
}
public virtual S VisitIdentifier (Identifier identifier, T data)
{
return VisitChildren (identifier, data);

31
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AssignmentExpression.cs

@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
// THE SOFTWARE.
using System;
using System.Linq.Expressions;
namespace ICSharpCode.NRefactory.CSharp
{
@ -115,6 +116,36 @@ namespace ICSharpCode.NRefactory.CSharp @@ -115,6 +116,36 @@ namespace ICSharpCode.NRefactory.CSharp
throw new NotSupportedException("Invalid value for AssignmentOperatorType");
}
}
public static ExpressionType GetLinqNodeType(AssignmentOperatorType op, bool checkForOverflow)
{
switch (op) {
case AssignmentOperatorType.Assign:
return ExpressionType.Assign;
case AssignmentOperatorType.Add:
return checkForOverflow ? ExpressionType.AddAssignChecked : ExpressionType.AddAssign;
case AssignmentOperatorType.Subtract:
return checkForOverflow ? ExpressionType.SubtractAssignChecked : ExpressionType.SubtractAssign;
case AssignmentOperatorType.Multiply:
return checkForOverflow ? ExpressionType.MultiplyAssignChecked : ExpressionType.MultiplyAssign;
case AssignmentOperatorType.Divide:
return ExpressionType.DivideAssign;
case AssignmentOperatorType.Modulus:
return ExpressionType.ModuloAssign;
case AssignmentOperatorType.ShiftLeft:
return ExpressionType.LeftShiftAssign;
case AssignmentOperatorType.ShiftRight:
return ExpressionType.RightShiftAssign;
case AssignmentOperatorType.BitwiseAnd:
return ExpressionType.AndAssign;
case AssignmentOperatorType.BitwiseOr:
return ExpressionType.OrAssign;
case AssignmentOperatorType.ExclusiveOr:
return ExpressionType.ExclusiveOrAssign;
default:
throw new NotSupportedException("Invalid value for AssignmentOperatorType");
}
}
}
public enum AssignmentOperatorType

47
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/BinaryOperatorExpression.cs

@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
// THE SOFTWARE.
using System;
using System.Linq.Expressions;
namespace ICSharpCode.NRefactory.CSharp
{
@ -124,6 +125,52 @@ namespace ICSharpCode.NRefactory.CSharp @@ -124,6 +125,52 @@ namespace ICSharpCode.NRefactory.CSharp
throw new NotSupportedException("Invalid value for BinaryOperatorType");
}
}
public static ExpressionType GetLinqNodeType(BinaryOperatorType op, bool checkForOverflow)
{
switch (op) {
case BinaryOperatorType.BitwiseAnd:
return ExpressionType.And;
case BinaryOperatorType.BitwiseOr:
return ExpressionType.Or;
case BinaryOperatorType.ConditionalAnd:
return ExpressionType.AndAlso;
case BinaryOperatorType.ConditionalOr:
return ExpressionType.OrElse;
case BinaryOperatorType.ExclusiveOr:
return ExpressionType.ExclusiveOr;
case BinaryOperatorType.GreaterThan:
return ExpressionType.GreaterThan;
case BinaryOperatorType.GreaterThanOrEqual:
return ExpressionType.GreaterThanOrEqual;
case BinaryOperatorType.Equality:
return ExpressionType.Equal;
case BinaryOperatorType.InEquality:
return ExpressionType.NotEqual;
case BinaryOperatorType.LessThan:
return ExpressionType.LessThan;
case BinaryOperatorType.LessThanOrEqual:
return ExpressionType.LessThanOrEqual;
case BinaryOperatorType.Add:
return checkForOverflow ? ExpressionType.AddChecked : ExpressionType.Add;
case BinaryOperatorType.Subtract:
return checkForOverflow ? ExpressionType.SubtractChecked : ExpressionType.Subtract;
case BinaryOperatorType.Multiply:
return checkForOverflow ? ExpressionType.MultiplyChecked : ExpressionType.Multiply;
case BinaryOperatorType.Divide:
return ExpressionType.Divide;
case BinaryOperatorType.Modulus:
return ExpressionType.Modulo;
case BinaryOperatorType.ShiftLeft:
return ExpressionType.LeftShift;
case BinaryOperatorType.ShiftRight:
return ExpressionType.RightShift;
case BinaryOperatorType.NullCoalescing:
return ExpressionType.Coalesce;
default:
throw new NotSupportedException("Invalid value for BinaryOperatorType");
}
}
}
public enum BinaryOperatorType

74
src/Libraries/NewNRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Indent.cs → src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ErrorExpression.cs

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
//
// Indent.cs
// ErrorExpression.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
// Copyright (c) 2011 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -27,63 +27,43 @@ using System; @@ -27,63 +27,43 @@ using System;
namespace ICSharpCode.NRefactory.CSharp
{
public class Indent
public class ErrorExpression : Expression
{
public int Level {
get;
set;
}
public int ExtraSpaces {
get;
set;
}
TextLocation location;
public bool TabsToSpaces {
get;
set;
}
public int TabSize {
get;
set;
public override TextLocation StartLocation {
get {
return location;
}
}
public Indent ()
{
public override TextLocation EndLocation {
get {
return location;
}
}
public Indent (int level, int extraSpaces)
public ErrorExpression ()
{
this.Level = level;
this.ExtraSpaces = extraSpaces;
}
public static Indent operator+ (Indent left, Indent right)
public ErrorExpression (TextLocation location)
{
return new Indent (left.Level + right.Level, left.ExtraSpaces + right.ExtraSpaces);
this.location = location;
}
public static Indent operator- (Indent left, Indent right)
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data = default(T))
{
return new Indent (left.Level - right.Level, left.ExtraSpaces - right.ExtraSpaces);
}
public string IndentString {
get {
return (TabsToSpaces ? new string (' ', Level * TabSize) : new string ('\t', Level)) + new string (' ', ExtraSpaces);
}
// nothing
return default(S);
}
public string SingleIndent {
get {
return TabsToSpaces ? new string (' ', TabSize) : "\t";
}
}
public override string ToString ()
protected internal override bool DoMatch (AstNode other, PatternMatching.Match match)
{
return string.Format ("[Indent: Level={0}, ExtraSpaces={1}]", Level, ExtraSpaces);
var o = other as ErrorExpression;
return o != null;
}
}
}

3
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedExpression.cs

@ -31,7 +31,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -31,7 +31,8 @@ namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// name = expression
/// This isn't the same as 'assign' even if it has the same syntax. This expression is used in object initializers.
/// This isn't the same as 'assign' even though it has the same syntax.
/// This expression is used in object initializers and for named attribute arguments [Attr(FieldName = value)].
/// </summary>
public class NamedExpression : Expression
{

29
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/UnaryOperatorExpression.cs

@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
// THE SOFTWARE.
using System;
using System.Linq.Expressions;
namespace ICSharpCode.NRefactory.CSharp
{
@ -98,6 +99,34 @@ namespace ICSharpCode.NRefactory.CSharp @@ -98,6 +99,34 @@ namespace ICSharpCode.NRefactory.CSharp
throw new NotSupportedException("Invalid value for UnaryOperatorType");
}
}
public static ExpressionType GetLinqNodeType(UnaryOperatorType op, bool checkForOverflow)
{
switch (op) {
case UnaryOperatorType.Not:
return ExpressionType.Not;
case UnaryOperatorType.BitNot:
return ExpressionType.OnesComplement;
case UnaryOperatorType.Minus:
return checkForOverflow ? ExpressionType.NegateChecked : ExpressionType.Negate;
case UnaryOperatorType.Plus:
return ExpressionType.UnaryPlus;
case UnaryOperatorType.Increment:
return ExpressionType.PreIncrementAssign;
case UnaryOperatorType.Decrement:
return ExpressionType.PreDecrementAssign;
case UnaryOperatorType.PostIncrement:
return ExpressionType.PostIncrementAssign;
case UnaryOperatorType.PostDecrement:
return ExpressionType.PostDecrementAssign;
case UnaryOperatorType.Dereference:
case UnaryOperatorType.AddressOf:
case UnaryOperatorType.Await:
return ExpressionType.Extension;
default:
throw new NotSupportedException("Invalid value for UnaryOperatorType");
}
}
}
public enum UnaryOperatorType

18
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Comment.cs

@ -26,10 +26,24 @@ @@ -26,10 +26,24 @@
namespace ICSharpCode.NRefactory.CSharp
{
public enum CommentType {
public enum CommentType
{
/// <summary>
/// "//" comment
/// </summary>
SingleLine,
/// <summary>
/// "/* */" comment
/// </summary>
MultiLine,
Documentation
/// <summary>
/// "///" comment
/// </summary>
Documentation,
/// <summary>
/// Inactive code (code in non-taken "#if")
/// </summary>
InactiveCode
}
public class Comment : AstNode, IRelocatable

9
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Constraint.cs

@ -38,6 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -38,6 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
public readonly static Role<CSharpTokenNode> ColonRole = TypeDeclaration.ColonRole;
public readonly static Role<AstType> BaseTypeRole = TypeDeclaration.BaseTypeRole;
public readonly static Role<SimpleType> TypeParameterRole = new Role<SimpleType> ("TypeParameter", SimpleType.Null);
public override NodeType NodeType {
get {
@ -45,12 +46,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -45,12 +46,12 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public string TypeParameter {
public SimpleType TypeParameter {
get {
return GetChildByRole (Roles.Identifier).Name;
return GetChildByRole (TypeParameterRole);
}
set {
SetChildByRole(Roles.Identifier, Identifier.Create (value, TextLocation.Empty));
SetChildByRole(TypeParameterRole, value);
}
}
@ -66,7 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -66,7 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
Constraint o = other as Constraint;
return o != null && MatchString(this.TypeParameter, o.TypeParameter) && this.BaseTypes.DoMatch(o.BaseTypes, match);
return o != null && this.TypeParameter.DoMatch (o.TypeParameter, match) && this.BaseTypes.DoMatch(o.BaseTypes, match);
}
}
}

117
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/PreProcessorDirective.cs

@ -0,0 +1,117 @@ @@ -0,0 +1,117 @@
//
// PreProcessorDirective.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2011 Xamarin Inc.
//
// 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;
namespace ICSharpCode.NRefactory.CSharp
{
public enum PreProcessorDirectiveType : byte
{
Invalid = 0,
Region = 1,
Endregion = 2,
If = 3,
Endif = 4,
Elif = 5,
Else = 6,
Define = 7,
Undef = 8,
Error = 9,
Warning = 10,
Pragma = 11,
Line = 12
}
public class PreProcessorDirective : AstNode, IRelocatable
{
public override NodeType NodeType {
get {
return NodeType.Whitespace;
}
}
public PreProcessorDirectiveType Type {
get;
set;
}
public string Argument {
get;
set;
}
/// <summary>
/// For an '#if' directive, specifies whether the condition evaluated to true.
/// </summary>
public bool Take {
get;
set;
}
TextLocation startLocation;
public override TextLocation StartLocation {
get {
return startLocation;
}
}
TextLocation endLocation;
public override TextLocation EndLocation {
get {
return endLocation;
}
}
public PreProcessorDirective (PreProcessorDirectiveType type, TextLocation startLocation, TextLocation endLocation)
{
this.Type = type;
this.startLocation = startLocation;
this.endLocation = endLocation;
}
#region IRelocationable implementation
void IRelocatable.SetStartLocation (TextLocation startLocation)
{
int lineDelta = startLocation.Line - this.startLocation.Line;
endLocation = new TextLocation (endLocation.Line + lineDelta, lineDelta != 0 ? endLocation.Column : endLocation.Column + startLocation.Column - this.startLocation.Column);
this.startLocation = startLocation;
}
#endregion
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data = default(T))
{
return visitor.VisitPreProcessorDirective (this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
PreProcessorDirective o = other as PreProcessorDirective;
return o != null && Type == o.Type && MatchString(Argument, o.Argument);
}
}
}

2
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp
public class TypeParameterDeclaration : AstNode
{
public static readonly Role<AttributeSection> AttributeRole = AttributedNode.AttributeRole;
public static readonly Role<CSharpTokenNode> VarianceRole = new Role<CSharpTokenNode>("Variance");
public static readonly Role<CSharpTokenNode> VarianceRole = new Role<CSharpTokenNode>("Variance", CSharpTokenNode.Null);
public override NodeType NodeType {
get { return NodeType.Unknown; }

2
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs

@ -137,6 +137,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -137,6 +137,8 @@ namespace ICSharpCode.NRefactory.CSharp
S VisitPrimitiveType(PrimitiveType primitiveType, T data);
S VisitComment(Comment comment, T data);
S VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective, T data);
S VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, T data);
S VisitConstraint(Constraint constraint, T data);
S VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, T data);

2
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/NodeType.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
Unknown,
/// <summary>
/// DomType
/// AstType
/// </summary>
TypeReference,
/// <summary>

10
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs

@ -61,6 +61,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -61,6 +61,16 @@ namespace ICSharpCode.NRefactory.CSharp
return VisitChildren (comment, data);
}
public event Action<PreProcessorDirective, T> PreProcessorDirectiveVisited;
S IAstVisitor<T, S>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective, T data)
{
var handler = PreProcessorDirectiveVisited;
if (handler != null)
handler (preProcessorDirective, data);
return VisitChildren (preProcessorDirective, data);
}
public event Action<Identifier, T> IdentifierVisited;
S IAstVisitor<T, S>.VisitIdentifier (Identifier identifier, T data)

28
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs

@ -33,6 +33,29 @@ namespace ICSharpCode.NRefactory.CSharp @@ -33,6 +33,29 @@ namespace ICSharpCode.NRefactory.CSharp
{
public class SimpleType : AstType
{
#region Null
public new static readonly SimpleType Null = new NullSimpleType ();
sealed class NullSimpleType : SimpleType
{
public override bool IsNull {
get {
return true;
}
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data = default(T))
{
return default (S);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
return other == null || other.IsNull;
}
}
#endregion
public SimpleType()
{
}
@ -42,6 +65,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -42,6 +65,11 @@ namespace ICSharpCode.NRefactory.CSharp
this.Identifier = identifier;
}
public SimpleType (Identifier identifier)
{
this.IdentifierToken = identifier;
}
public SimpleType(string identifier, TextLocation location)
{
SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (identifier, location));

20
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs

@ -116,7 +116,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -116,7 +116,6 @@ namespace ICSharpCode.NRefactory.CSharp
return o != null && !o.IsNull && this.Statements.DoMatch(o.Statements, match);
}
#region Builder methods
public void Add(Statement statement)
{
AddChild(statement, StatementRole);
@ -124,26 +123,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -124,26 +123,9 @@ namespace ICSharpCode.NRefactory.CSharp
public void Add(Expression expression)
{
AddChild(new ExpressionStatement { Expression = expression }, StatementRole);
AddChild(new ExpressionStatement(expression), StatementRole);
}
public void AddRange(IEnumerable<Statement> statements)
{
foreach (Statement st in statements)
AddChild(st, StatementRole);
}
public void AddAssignment(Expression left, Expression right)
{
Add(new AssignmentExpression { Left = left, Operator = AssignmentOperatorType.Assign, Right = right });
}
public void AddReturnStatement(Expression expression)
{
Add(new ReturnStatement { Expression = expression });
}
#endregion
IEnumerator<Statement> IEnumerable<Statement>.GetEnumerator()
{
return this.Statements.GetEnumerator();

5
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/Accessor.cs

@ -46,6 +46,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -46,6 +46,11 @@ namespace ICSharpCode.NRefactory.CSharp
{
return default (S);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
return other == null || other.IsNull;
}
}
public override NodeType NodeType {

170
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs

@ -0,0 +1,170 @@ @@ -0,0 +1,170 @@
// 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 System.Linq;
using System.Runtime.Serialization;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp
{
[Serializable]
public class CSharpProjectContent : IProjectContent
{
string assemblyName;
Dictionary<string, IParsedFile> parsedFiles;
List<IAssemblyReference> assemblyReferences;
public CSharpProjectContent()
{
this.assemblyName = string.Empty;
this.parsedFiles = new Dictionary<string, IParsedFile>(Platform.FileNameComparer);
this.assemblyReferences = new List<IAssemblyReference>();
}
protected CSharpProjectContent(CSharpProjectContent pc)
{
this.assemblyName = pc.assemblyName;
this.parsedFiles = new Dictionary<string, IParsedFile>(pc.parsedFiles);
this.assemblyReferences = new List<IAssemblyReference>(pc.assemblyReferences);
}
public IEnumerable<IParsedFile> Files {
get { return parsedFiles.Values; }
}
public IEnumerable<IAssemblyReference> AssemblyReferences {
get { return assemblyReferences; }
}
public string AssemblyName {
get { return assemblyName; }
}
public IEnumerable<IUnresolvedAttribute> AssemblyAttributes {
get {
return this.Files.SelectMany(f => f.AssemblyAttributes);
}
}
public IEnumerable<IUnresolvedAttribute> ModuleAttributes {
get {
return this.Files.SelectMany(f => f.ModuleAttributes);
}
}
public IEnumerable<IUnresolvedTypeDefinition> TopLevelTypeDefinitions {
get {
return this.Files.SelectMany(f => f.TopLevelTypeDefinitions);
}
}
public IParsedFile GetFile(string fileName)
{
IParsedFile file;
if (parsedFiles.TryGetValue(fileName, out file))
return file;
else
return null;
}
public ICompilation CreateCompilation()
{
var solutionSnapshot = new DefaultSolutionSnapshot();
ICompilation compilation = new SimpleCompilation(solutionSnapshot, this, assemblyReferences);
solutionSnapshot.AddCompilation(this, compilation);
return compilation;
}
public ICompilation CreateCompilation(ISolutionSnapshot solutionSnapshot)
{
return new SimpleCompilation(solutionSnapshot, this, assemblyReferences);
}
public IProjectContent SetAssemblyName(string newAssemblyName)
{
CSharpProjectContent pc = new CSharpProjectContent(this);
pc.assemblyName = newAssemblyName;
return pc;
}
public IProjectContent AddAssemblyReferences(IEnumerable<IAssemblyReference> references)
{
CSharpProjectContent pc = new CSharpProjectContent(this);
pc.assemblyReferences.AddRange(references);
return pc;
}
public IProjectContent RemoveAssemblyReferences(IEnumerable<IAssemblyReference> references)
{
CSharpProjectContent pc = new CSharpProjectContent(this);
pc.assemblyReferences.RemoveAll(r => references.Contains(r));
return pc;
}
public IProjectContent UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile)
{
if (oldFile == null && newFile == null)
return this;
if (oldFile != null && newFile != null) {
if (!Platform.FileNameComparer.Equals(oldFile.FileName, newFile.FileName))
throw new ArgumentException("When both oldFile and newFile are specified, they must use the same file name.");
}
CSharpProjectContent pc = new CSharpProjectContent(this);
if (newFile == null)
pc.parsedFiles.Remove(oldFile.FileName);
else
pc.parsedFiles[newFile.FileName] = newFile;
return pc;
}
public IProjectContent UpdateProjectContent(IEnumerable<IParsedFile> oldFiles, IEnumerable<IParsedFile> newFiles)
{
CSharpProjectContent pc = new CSharpProjectContent(this);
if (oldFiles != null) {
foreach (var oldFile in oldFiles) {
pc.parsedFiles.Remove(oldFile.FileName);
}
}
if (newFiles != null) {
foreach (var newFile in newFiles) {
pc.parsedFiles.Add(newFile.FileName, newFile);
}
}
return pc;
}
IAssembly IAssemblyReference.Resolve(ITypeResolveContext context)
{
if (context == null)
throw new ArgumentNullException("context");
var cache = context.Compilation.CacheManager;
IAssembly asm = (IAssembly)cache.GetShared(this);
if (asm != null) {
return asm;
} else {
asm = new CSharpAssembly(context.Compilation, this);
return (IAssembly)cache.GetOrAddShared(this, asm);
}
}
}
}

2165
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

File diff suppressed because it is too large Load Diff

448
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs

@ -0,0 +1,448 @@ @@ -0,0 +1,448 @@
//
// CSharpCompletionEngineBase.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
//
// 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 System.Linq;
using System.Text;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Completion
{
/// <summary>
/// Acts as a common base between code completion and parameter completion.
/// </summary>
public class CSharpCompletionEngineBase
{
protected IDocument document;
protected int offset;
protected TextLocation location;
protected IUnresolvedTypeDefinition currentType;
protected IUnresolvedMember currentMember;
#region Input properties
public CSharpTypeResolveContext ctx { get; set; }
public CompilationUnit Unit { get; set; }
public CSharpParsedFile CSharpParsedFile { get; set; }
public IProjectContent ProjectContent { get; set; }
ICompilation compilation;
protected ICompilation Compilation {
get {
if (compilation == null)
compilation = ProjectContent.Resolve (ctx).Compilation;
return compilation;
}
}
#endregion
protected void SetOffset (int offset)
{
Reset ();
this.offset = offset;
this.location = document.GetLocation (offset);
this.currentType = CSharpParsedFile.GetInnermostTypeDefinition (location);
this.currentMember = null;
if (this.currentType != null) {
foreach (var member in currentType.Members) {
if (member.Region.Begin < location && (currentMember == null || currentMember.Region.Begin < member.Region.Begin))
currentMember = member;
}
}
var stack = GetBracketStack (GetMemberTextToCaret ().Item1);
if (stack.Count == 0)
currentMember = null;
}
#region Context helper methods
protected bool IsInsideCommentOrString ()
{
var text = GetMemberTextToCaret ();
bool inSingleComment = false, inString = false, inVerbatimString = false, inChar = false, inMultiLineComment = false;
for (int i = 0; i < text.Item1.Length - 1; i++) {
char ch = text.Item1 [i];
char nextCh = text.Item1 [i + 1];
switch (ch) {
case '/':
if (inString || inChar || inVerbatimString)
break;
if (nextCh == '/') {
i++;
inSingleComment = true;
}
if (nextCh == '*')
inMultiLineComment = true;
break;
case '*':
if (inString || inChar || inVerbatimString || inSingleComment)
break;
if (nextCh == '/') {
i++;
inMultiLineComment = false;
}
break;
case '@':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment)
break;
if (nextCh == '"') {
i++;
inVerbatimString = true;
}
break;
case '\n':
case '\r':
inSingleComment = false;
inString = false;
inChar = false;
break;
case '\\':
if (inString || inChar)
i++;
break;
case '"':
if (inSingleComment || inMultiLineComment || inChar)
break;
if (inVerbatimString) {
if (nextCh == '"') {
i++;
break;
}
inVerbatimString = false;
break;
}
inString = !inString;
break;
case '\'':
if (inSingleComment || inMultiLineComment || inString || inVerbatimString)
break;
inChar = !inChar;
break;
}
}
return inSingleComment || inString || inVerbatimString || inChar || inMultiLineComment;
}
protected bool IsInsideComment (int offset)
{
var loc = document.GetLocation (offset);
return Unit.GetNodeAt<ICSharpCode.NRefactory.CSharp.Comment> (loc.Line, loc.Column) != null;
}
protected bool IsInsideDocComment ()
{
var loc = document.GetLocation (offset);
var cmt = Unit.GetNodeAt<ICSharpCode.NRefactory.CSharp.Comment> (loc.Line, loc.Column - 1);
return cmt != null && cmt.CommentType == CommentType.Documentation;
}
protected bool IsInsideString (int offset)
{
var loc = document.GetLocation (offset);
var expr = Unit.GetNodeAt<PrimitiveExpression> (loc.Line, loc.Column);
return expr != null && expr.Value is string;
}
#endregion
#region Basic parsing/resolving functions
Stack<Tuple<char, int>> GetBracketStack (string memberText)
{
var bracketStack = new Stack<Tuple<char, int>> ();
bool isInString = false, isInChar = false;
bool isInLineComment = false, isInBlockComment = false;
for (int pos = 0; pos < memberText.Length; pos++) {
char ch = memberText [pos];
switch (ch) {
case '(':
case '[':
case '{':
if (!isInString && !isInChar && !isInLineComment && !isInBlockComment)
bracketStack.Push (Tuple.Create (ch, pos));
break;
case ')':
case ']':
case '}':
if (!isInString && !isInChar && !isInLineComment && !isInBlockComment)
if (bracketStack.Count > 0)
bracketStack.Pop ();
break;
case '\r':
case '\n':
isInLineComment = false;
break;
case '/':
if (isInBlockComment) {
if (pos > 0 && memberText [pos - 1] == '*')
isInBlockComment = false;
} else if (!isInString && !isInChar && pos + 1 < memberText.Length) {
char nextChar = memberText [pos + 1];
if (nextChar == '/')
isInLineComment = true;
if (!isInLineComment && nextChar == '*')
isInBlockComment = true;
}
break;
case '"':
if (!(isInChar || isInLineComment || isInBlockComment))
isInString = !isInString;
break;
case '\'':
if (!(isInString || isInLineComment || isInBlockComment))
isInChar = !isInChar;
break;
default :
break;
}
}
return bracketStack;
}
protected void AppendMissingClosingBrackets (StringBuilder wrapper, string memberText, bool appendSemicolon)
{
var bracketStack = GetBracketStack (memberText);
bool didAppendSemicolon = !appendSemicolon;
char lastBracket = '\0';
while (bracketStack.Count > 0) {
var t = bracketStack.Pop ();
switch (t.Item1) {
case '(':
wrapper.Append (')');
didAppendSemicolon = false;
lastBracket = ')';
break;
case '[':
wrapper.Append (']');
didAppendSemicolon = false;
lastBracket = ']';
break;
case '<':
wrapper.Append ('>');
didAppendSemicolon = false;
lastBracket = '>';
break;
case '{':
int o = t.Item2 - 1;
if (!didAppendSemicolon) {
didAppendSemicolon = true;
wrapper.Append (';');
}
bool didAppendCatch = false;
while (o >= "try".Length) {
char ch = memberText [o];
if (!char.IsWhiteSpace (ch)) {
if (ch == 'y' && memberText [o - 1] == 'r' && memberText [o - 2] == 't') {
wrapper.Append ("} catch {}");
didAppendCatch = true;
}
break;
}
o--;
}
if (!didAppendCatch)
wrapper.Append ('}');
break;
}
}
if (currentMember == null && lastBracket == ']') {
// attribute context
wrapper.Append ("class GenAttr {}");
} else {
if (!didAppendSemicolon)
wrapper.Append (';');
}
}
protected CompilationUnit ParseStub (string continuation, bool appendSemicolon = true)
{
var mt = GetMemberTextToCaret ();
if (mt == null)
return null;
string memberText = mt.Item1;
bool wrapInClass = mt.Item2;
var wrapper = new StringBuilder ();
if (wrapInClass) {
/* foreach (var child in Unit.Children) {
if (child is UsingDeclaration) {
var offset = document.GetOffset (child.StartLocation);
wrapper.Append (document.GetText (offset, document.GetOffset (child.EndLocation) - offset));
}
}*/
wrapper.Append ("class Stub {");
wrapper.AppendLine ();
}
wrapper.Append (memberText);
wrapper.Append (continuation);
AppendMissingClosingBrackets (wrapper, memberText, appendSemicolon);
if (wrapInClass)
wrapper.Append ('}');
TextLocation memberLocation;
if (currentMember != null && currentType.Kind != TypeKind.Enum) {
memberLocation = currentMember.Region.Begin;
} else if (currentType != null) {
memberLocation = currentType.Region.Begin;
} else {
memberLocation = new TextLocation (1, 1);
}
using (var stream = new System.IO.StringReader (wrapper.ToString ())) {
try {
var parser = new CSharpParser ();
return parser.Parse (stream, "stub.cs" , wrapInClass ? memberLocation.Line - 2 : 0);
} catch (Exception){
Console.WriteLine ("------");
Console.WriteLine (wrapper);
throw;
}
}
}
string cachedText = null;
protected virtual void Reset ()
{
cachedText = null;
}
protected Tuple<string, bool> GetMemberTextToCaret ()
{
int startOffset;
if (currentMember != null && currentType.Kind != TypeKind.Enum) {
startOffset = document.GetOffset (currentMember.Region.BeginLine, currentMember.Region.BeginColumn);
} else if (currentType != null) {
startOffset = document.GetOffset (currentType.Region.BeginLine, currentType.Region.BeginColumn);
} else {
startOffset = 0;
}
while (startOffset > 0) {
char ch = document.GetCharAt (startOffset - 1);
if (ch != ' ' && ch != '\t')
break;
--startOffset;
}
if (cachedText == null)
cachedText = document.GetText (startOffset, offset - startOffset);
return Tuple.Create (cachedText, startOffset != 0);
}
protected Tuple<CSharpParsedFile, AstNode, CompilationUnit> GetInvocationBeforeCursor (bool afterBracket)
{
CompilationUnit baseUnit;
if (currentMember == null) {
baseUnit = ParseStub ("", false);
var section = baseUnit.GetNodeAt<AttributeSection> (location.Line, location.Column - 2);
var attr = section != null ? section.Attributes.LastOrDefault () : null;
if (attr != null) {
// insert target type into compilation unit, to respect the
attr.Remove ();
var node = Unit.GetNodeAt (location) ?? Unit;
node.AddChild (attr, AttributeSection.AttributeRole);
return Tuple.Create (CSharpParsedFile, (AstNode)attr, Unit);
}
}
if (currentMember == null && currentType == null) {
return null;
}
baseUnit = ParseStub (afterBracket ? "" : "x");
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
var mref = baseUnit.GetNodeAt (location.Line, location.Column - 1, n => n is InvocationExpression || n is ObjectCreateExpression);
AstNode expr;
if (mref is InvocationExpression) {
expr = ((InvocationExpression)mref).Target;
} else if (mref is ObjectCreateExpression) {
expr = mref;
} else {
return null;
}
var member = Unit.GetNodeAt<AttributedNode> (memberLocation);
var member2 = baseUnit.GetNodeAt<AttributedNode> (memberLocation);
member2.Remove ();
member.ReplaceWith (member2);
var tsvisitor = new TypeSystemConvertVisitor (CSharpParsedFile.FileName);
Unit.AcceptVisitor (tsvisitor, null);
return Tuple.Create (tsvisitor.ParsedFile, (AstNode)expr, Unit);
}
protected Tuple<ResolveResult, CSharpResolver> ResolveExpression (CSharpParsedFile file, AstNode expr, CompilationUnit unit)
{
if (expr == null)
return null;
AstNode resolveNode;
if (expr is Expression || expr is AstType) {
resolveNode = expr;
} else if (expr is VariableDeclarationStatement) {
resolveNode = ((VariableDeclarationStatement)expr).Type;
} else {
resolveNode = expr;
}
// var newContent = ProjectContent.UpdateProjectContent (CSharpParsedFile, file);
var csResolver = new CSharpResolver (ctx);
var navigator = new NodeListResolveVisitorNavigator (new[] { resolveNode });
var visitor = new ResolveVisitor (csResolver, CSharpParsedFile, navigator);
visitor.Scan (unit);
var state = visitor.GetResolverStateBefore (resolveNode);
var result = visitor.GetResolveResult (resolveNode);
return Tuple.Create (result, state);
}
protected static void Print (AstNode node)
{
var v = new CSharpOutputVisitor (Console.Out, new CSharpFormattingOptions ());
node.AcceptVisitor (v, null);
}
#endregion
}
}

326
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs

@ -0,0 +1,326 @@ @@ -0,0 +1,326 @@
//
// CSharpParameterCompletionEngine.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
//
// 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 ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Completion;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Completion
{
public class CSharpParameterCompletionEngine : CSharpCompletionEngineBase
{
internal IParameterCompletionDataFactory factory;
public CSharpParameterCompletionEngine (IDocument document, IParameterCompletionDataFactory factory)
{
this.document = document;
this.factory = factory;
}
public Tuple<CSharpParsedFile, AstNode, CompilationUnit> GetIndexerBeforeCursor ()
{
CompilationUnit baseUnit;
if (currentMember == null && currentType == null)
return null;
baseUnit = ParseStub ("x] = a[1");
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
var mref = baseUnit.GetNodeAt (location, n => n is IndexerExpression);
Print (baseUnit);
AstNode expr;
if (mref is IndexerExpression) {
expr = ((IndexerExpression)mref).Target;
} else {
return null;
}
var member = Unit.GetNodeAt<AttributedNode> (memberLocation);
var member2 = baseUnit.GetNodeAt<AttributedNode> (memberLocation);
member2.Remove ();
member.ReplaceWith (member2);
var tsvisitor = new TypeSystemConvertVisitor (CSharpParsedFile.FileName);
Unit.AcceptVisitor (tsvisitor, null);
return Tuple.Create (tsvisitor.ParsedFile, (AstNode)expr, Unit);
}
public IParameterDataProvider GetParameterDataProvider (int offset, char completionChar)
{
if (offset <= 0)
return null;
if (completionChar != '(' && completionChar != '<' && completionChar != '[' && completionChar != ',')
return null;
SetOffset (offset);
if (IsInsideCommentOrString ())
return null;
var invoke = GetInvocationBeforeCursor (true) ?? GetIndexerBeforeCursor ();
if (invoke == null)
return null;
ResolveResult resolveResult;
switch (completionChar) {
case '(':
if (invoke.Item2 is ObjectCreateExpression) {
var createType = ResolveExpression (invoke.Item1, ((ObjectCreateExpression)invoke.Item2).Type, invoke.Item3);
return factory.CreateConstructorProvider (createType.Item1.Type);
}
if (invoke.Item2 is ICSharpCode.NRefactory.CSharp.Attribute) {
var attribute = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3);
if (attribute == null || attribute.Item1 == null)
return null;
return factory.CreateConstructorProvider (attribute.Item1.Type);
}
var invocationExpression = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3);
if (invocationExpression == null || invocationExpression.Item1 == null || invocationExpression.Item1.IsError)
return null;
resolveResult = invocationExpression.Item1;
if (resolveResult is MethodGroupResolveResult)
return factory.CreateMethodDataProvider (resolveResult as MethodGroupResolveResult);
if (resolveResult is MemberResolveResult) {
var mr = resolveResult as MemberResolveResult;
if (mr.Member is IMethod)
return factory.CreateMethodDataProvider ((IMethod)mr.Member);
}
if (resolveResult.Type.Kind == TypeKind.Delegate)
return factory.CreateDelegateDataProvider (resolveResult.Type);
//
// if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) {
// if (resolveResult is ThisResolveResult)
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult);
// if (resolveResult is BaseResolveResult)
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult);
// }
// IType resolvedType = resolver.SearchType (resolveResult.ResolvedType);
// if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) {
// return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType);
// }
break;
case ',':
if (invoke.Item2 is ObjectCreateExpression) {
var createType = ResolveExpression (invoke.Item1, ((ObjectCreateExpression)invoke.Item2).Type, invoke.Item3);
return factory.CreateConstructorProvider (createType.Item1.Type);
}
if (invoke.Item2 is ICSharpCode.NRefactory.CSharp.Attribute) {
var attribute = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3);
if (attribute == null || attribute.Item1 == null)
return null;
return factory.CreateConstructorProvider (attribute.Item1.Type);
}
invocationExpression = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3);
if (invocationExpression == null || invocationExpression.Item1 == null || invocationExpression.Item1.IsError)
return null;
resolveResult = invocationExpression.Item1;
if (resolveResult is MethodGroupResolveResult)
return factory.CreateMethodDataProvider (resolveResult as MethodGroupResolveResult);
if (resolveResult is MemberResolveResult) {
if (resolveResult.Type.Kind == TypeKind.Delegate)
return factory.CreateDelegateDataProvider (resolveResult.Type);
var mr = resolveResult as MemberResolveResult;
if (mr.Member is IMethod)
return factory.CreateMethodDataProvider ((IMethod)mr.Member);
}
if (resolveResult != null)
return factory.CreateIndexerParameterDataProvider (resolveResult.Type, invoke.Item2);
break;
// case '<':
// if (string.IsNullOrEmpty (result.Expression))
// return null;
// return new NRefactoryTemplateParameterDataProvider (textEditorData, resolver, GetUsedNamespaces (), result, new TextLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
case '[':
var indexerExpression = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3);
if (indexerExpression == null || indexerExpression.Item1 == null || indexerExpression.Item1.IsError)
return null;
return factory.CreateIndexerParameterDataProvider (indexerExpression.Item1.Type, invoke.Item2);
}
return null;
}
List<string> GetUsedNamespaces ()
{
var scope = CSharpParsedFile.GetUsingScope (location);
var result = new List<string> ();
var resolver = new CSharpResolver (ctx);
while (scope != null) {
result.Add (scope.NamespaceName);
foreach (var u in scope.Usings) {
var ns = u.ResolveNamespace (resolver);
if (ns == null)
continue;
result.Add (ns.FullName);
}
scope = scope.Parent;
}
return result;
}
public int GetCurrentParameterIndex (int triggerOffset)
{
SetOffset (triggerOffset);
var text = GetMemberTextToCaret ();
if (text.Item1.EndsWith ("("))
return 0;
var parameter = new Stack<int> ();
bool inSingleComment = false, inString = false, inVerbatimString = false, inChar = false, inMultiLineComment = false;
for (int i = 0; i < text.Item1.Length; i++) {
char ch = text.Item1 [i];
char nextCh = i + 1 < text.Item1.Length ? text.Item1 [i + 1] : '\0';
switch (ch) {
case '(':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment)
break;
parameter.Push (0);
break;
case ')':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment)
break;
if (parameter.Count > 0)
parameter.Pop ();
break;
case ',':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment)
break;
if (parameter.Count > 0)
parameter.Push (parameter.Pop () + 1);
break;
case '/':
if (inString || inChar || inVerbatimString)
break;
if (nextCh == '/') {
i++;
inSingleComment = true;
}
if (nextCh == '*')
inMultiLineComment = true;
break;
case '*':
if (inString || inChar || inVerbatimString || inSingleComment)
break;
if (nextCh == '/') {
i++;
inMultiLineComment = false;
}
break;
case '@':
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment)
break;
if (nextCh == '"') {
i++;
inVerbatimString = true;
}
break;
case '\n':
case '\r':
inSingleComment = false;
inString = false;
inChar = false;
break;
case '\\':
if (inString || inChar)
i++;
break;
case '"':
if (inSingleComment || inMultiLineComment || inChar)
break;
if (inVerbatimString) {
if (nextCh == '"') {
i++;
break;
}
inVerbatimString = false;
break;
}
inString = !inString;
break;
case '\'':
if (inSingleComment || inMultiLineComment || inString || inVerbatimString)
break;
inChar = !inChar;
break;
}
}
if (parameter.Count == 0)
return -1;
return parameter.Pop () + 1;
}
/*
public override bool GetParameterCompletionCommandOffset (out int cpos)
{
// Start calculating the parameter offset from the beginning of the
// current member, instead of the beginning of the file.
cpos = textEditorData.Caret.Offset - 1;
var parsedDocument = Document.ParsedDocument;
if (parsedDocument == null)
return false;
IMember mem = currentMember;
if (mem == null || (mem is IType))
return false;
int startPos = textEditorData.LocationToOffset (mem.Region.BeginLine, mem.Region.BeginColumn);
int parenDepth = 0;
int chevronDepth = 0;
while (cpos > startPos) {
char c = textEditorData.GetCharAt (cpos);
if (c == ')')
parenDepth++;
if (c == '>')
chevronDepth++;
if (parenDepth == 0 && c == '(' || chevronDepth == 0 && c == '<') {
int p = MethodParameterDataProvider.GetCurrentParameterIndex (CompletionWidget, cpos + 1, startPos);
if (p != -1) {
cpos++;
return true;
} else {
return false;
}
}
if (c == '(')
parenDepth--;
if (c == '<')
chevronDepth--;
cpos--;
}
return false;
}*/
}
}

237
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/CompletionDataWrapper.cs

@ -0,0 +1,237 @@ @@ -0,0 +1,237 @@
//
// CompletionDataWrapper.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
//
// 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.Completion;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Completion
{
class CompletionDataWrapper
{
CSharpCompletionEngine completion;
List<ICompletionData> result = new List<ICompletionData> ();
public List<ICompletionData> Result {
get {
return result;
}
}
ICompletionDataFactory Factory {
get {
return completion.factory;
}
}
public CompletionDataWrapper (CSharpCompletionEngine completion)
{
this.completion = completion;
}
public void Add (ICompletionData data)
{
result.Add (data);
}
public void AddCustom (string displayText, string description = null, string completionText = null)
{
result.Add (Factory.CreateLiteralCompletionData (displayText, description, completionText));
}
HashSet<string> usedNamespaces = new HashSet<string> ();
public void AddNamespace (string name)
{
if (string.IsNullOrEmpty (name) || usedNamespaces.Contains (name))
return;
usedNamespaces.Add (name);
result.Add (Factory.CreateNamespaceCompletionData (name));
}
HashSet<string> usedTypes = new HashSet<string> ();
public void AddType (IType type, string shortType)
{
if (type == null || string.IsNullOrEmpty (shortType) || usedTypes.Contains (shortType))
return;
usedTypes.Add (shortType);
result.Add (Factory.CreateTypeCompletionData (type, shortType));
}
public void AddType (IUnresolvedTypeDefinition type, string shortType)
{
if (type == null || string.IsNullOrEmpty (shortType) || usedTypes.Contains (shortType))
return;
usedTypes.Add (shortType);
result.Add (Factory.CreateTypeCompletionData (type, shortType));
}
Dictionary<string, List<ICompletionData>> data = new Dictionary<string, List<ICompletionData>> ();
public void AddVariable (IVariable variable)
{
if (data.ContainsKey (variable.Name))
return;
data [variable.Name] = new List<ICompletionData> ();
result.Add (Factory.CreateVariableCompletionData (variable));
}
public void AddTypeParameter (IUnresolvedTypeParameter variable)
{
if (data.ContainsKey (variable.Name))
return;
data [variable.Name] = new List<ICompletionData> ();
result.Add (Factory.CreateVariableCompletionData (variable));
}
public ICompletionData AddMember (IUnresolvedMember member)
{
var newData = Factory.CreateEntityCompletionData (member);
// newData.HideExtensionParameter = HideExtensionParameter;
string memberKey = newData.DisplayText;
if (memberKey == null)
return null;
if (member is IMember) {
newData.CompletionCategory = GetCompletionCategory (member.DeclaringTypeDefinition.Resolve (completion.ctx));
}
List<ICompletionData> existingData;
data.TryGetValue (memberKey, out existingData);
if (existingData != null) {
var a = member as IEntity;
foreach (var d in existingData) {
if (!(d is IEntityCompletionData))
continue;
var b = ((IEntityCompletionData)d).Entity;
if (a == null || b == null || a.EntityType == b.EntityType) {
d.AddOverload (newData);
return d;
}
}
if (newData != null) {
result.Add (newData);
data [memberKey].Add (newData);
}
} else {
result.Add (newData);
data [memberKey] = new List<ICompletionData> ();
data [memberKey].Add (newData);
}
return newData;
}
public ICompletionData AddMember (IMember member)
{
var newData = Factory.CreateEntityCompletionData (member);
// newData.HideExtensionParameter = HideExtensionParameter;
string memberKey = newData.DisplayText;
if (memberKey == null)
return null;
if (member is IMember) {
newData.CompletionCategory = GetCompletionCategory (member.DeclaringTypeDefinition);
}
List<ICompletionData> existingData;
data.TryGetValue (memberKey, out existingData);
if (existingData != null) {
var a = member as IEntity;
foreach (var d in existingData) {
if (!(d is IEntityCompletionData))
continue;
var b = ((IEntityCompletionData)d).Entity;
if (a == null || b == null || a.EntityType == b.EntityType) {
d.AddOverload (newData);
return d;
}
}
if (newData != null) {
result.Add (newData);
data [memberKey].Add (newData);
}
} else {
result.Add (newData);
data [memberKey] = new List<ICompletionData> ();
data [memberKey].Add (newData);
}
return newData;
}
internal CompletionCategory GetCompletionCategory (IType type)
{
if (type == null)
return null;
if (!completionCategories.ContainsKey (type))
completionCategories [type] = new TypeCompletionCategory (type);
return completionCategories [type];
}
Dictionary<IType, CompletionCategory> completionCategories = new Dictionary<IType, CompletionCategory> ();
class TypeCompletionCategory : CompletionCategory
{
public IType Type {
get;
private set;
}
public TypeCompletionCategory (IType type) : base (type.FullName, null)
{
this.Type = type;
}
public override int CompareTo (CompletionCategory other)
{
var compareCategory = other as TypeCompletionCategory;
if (compareCategory == null)
return 1;
if (Type.ReflectionName == compareCategory.Type.ReflectionName)
return 0;
// System.Object is always the smallest
if (Type.ReflectionName == "System.Object")
return -1;
if (compareCategory.Type.ReflectionName == "System.Object")
return 1;
/* if (Type.GetProjectContent () != null) {
if (Type.GetProjectContent ().GetInheritanceTree (Type).Any (t => t != null && t.DecoratedFullName == compareCategory.Type.DecoratedFullName))
return 1;
return -1;
}
// source project dom == null - try to make the opposite comparison
if (compareCategory.Type.GetProjectContent () != null && compareCategory.Type.GetProjectContent ().GetInheritanceTree (Type).Any (t => t != null && t.DecoratedFullName == Type.DecoratedFullName))
return -1;*/
return 1;
}
}
}
}

71
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/ICompletionDataFactory.cs

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
//
// ICompletionDataFactory.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
//
// 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;
using ICSharpCode.NRefactory.Completion;
namespace ICSharpCode.NRefactory.CSharp.Completion
{
public interface ICompletionDataFactory
{
ICompletionData CreateEntityCompletionData (IUnresolvedEntity entity);
ICompletionData CreateEntityCompletionData (IUnresolvedEntity entity, string text);
ICompletionData CreateEntityCompletionData (IEntity entity);
ICompletionData CreateEntityCompletionData (IEntity entity, string text);
ICompletionData CreateTypeCompletionData (IType type, string shortType);
ICompletionData CreateTypeCompletionData (IUnresolvedTypeDefinition type, string shortType);
/// <summary>
/// Creates a generic completion data.
/// </summary>
/// <returns>
/// The title of the completion data
/// </param>
/// <param name='description'>
/// The description of the literal.
/// </param>
/// <param name='insertText'>
/// The insert text. If null, title is taken.
/// </param>
ICompletionData CreateLiteralCompletionData (string title, string description = null, string insertText = null);
ICompletionData CreateNamespaceCompletionData (string name);
ICompletionData CreateVariableCompletionData (IVariable variable);
ICompletionData CreateVariableCompletionData (IUnresolvedTypeParameter parameter);
ICompletionData CreateEventCreationCompletionData (string varName, IType delegateType, IEvent evt, string parameterDefinition, IUnresolvedMember currentMember, IUnresolvedTypeDefinition currentType);
ICompletionData CreateNewOverrideCompletionData (int declarationBegin, IUnresolvedTypeDefinition type, IMember m);
IEnumerable<ICompletionData> CreateCodeTemplateCompletionData ();
IEnumerable<ICompletionData> CreatePreProcessorDefinesCompletionData ();
}
}

46
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
//
// IParameterCopmletionFactory.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
//
// 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 ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Completion
{
public interface IParameterCompletionDataFactory
{
IParameterDataProvider CreateConstructorProvider (IType type);
IParameterDataProvider CreateMethodDataProvider (MethodGroupResolveResult par1);
IParameterDataProvider CreateMethodDataProvider (IMethod method);
IParameterDataProvider CreateDelegateDataProvider (IType type);
IParameterDataProvider CreateIndexerParameterDataProvider (IType type, AstNode resolvedNode);
}
}

2
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs

@ -995,7 +995,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -995,7 +995,7 @@ namespace ICSharpCode.NRefactory.CSharp
return;
}
}
//Console.WriteLine ("offset={0}, removedChars={1}, insertedText={2}", offset, removedChars, insertedText == null ? "<null>" : insertedText.Replace ("\n", "\\n").Replace ("\t", "\\t").Replace (" ", "."));
//Console.WriteLine ("offset={0}, removedChars={1}, insertedText={2}", offset, removedChars, insertedText == null ? "<null>" : insertedText.Replace ("\n", "\\n").Replace ("\r", "\\r").Replace ("\t", "\\t").Replace (" ", "."));
//Console.WriteLine (Environment.StackTrace);
changes.Add (factory.CreateTextReplaceAction (offset, removedChars, insertedText));

54
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<ProjectGuid>{53DCA265-3C3C-42F9-B647-F72BA678122B}</ProjectGuid>
@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<SignAssembly>True</SignAssembly>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\ICSharpCode.NRefactory.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
@ -165,10 +165,12 @@ @@ -165,10 +165,12 @@
<Compile Include="Ast\TypeMembers\ParameterDeclaration.cs" />
<Compile Include="Ast\TypeMembers\PropertyDeclaration.cs" />
<Compile Include="Ast\TypeMembers\VariableInitializer.cs" />
<Compile Include="CSharpProjectContent.cs" />
<Compile Include="Formatter\AstFormattingVisitor.cs" />
<Compile Include="Formatter\CSharpFormattingOptions.cs" />
<Compile Include="Formatter\Indent.cs" />
<Compile Include="OutputVisitor\CodeDomConvertVisitor.cs" />
<Compile Include="OutputVisitor\CSharpAmbience.cs" />
<Compile Include="OutputVisitor\InsertParenthesesVisitor.cs" />
<Compile Include="OutputVisitor\IOutputFormatter.cs" />
<Compile Include="OutputVisitor\CSharpOutputVisitor.cs" />
@ -233,8 +235,6 @@ @@ -233,8 +235,6 @@
<Compile Include="Parser\mcs\typemanager.cs" />
<Compile Include="Parser\mcs\typespec.cs" />
<Compile Include="Parser\mcs\visit.cs" />
<Compile Include="Parser\ParsedFile.cs" />
<Compile Include="Parser\TypeSystemConvertVisitor.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Refactoring\Action.cs" />
<Compile Include="Refactoring\ContextAction\AddAnotherAccessor.cs" />
@ -270,38 +270,52 @@ @@ -270,38 +270,52 @@
<Compile Include="Refactoring\Script.cs" />
<Compile Include="Refactoring\TextReplaceAction.cs" />
<Compile Include="Refactoring\TypeSystemAstBuilder.cs" />
<Compile Include="Resolver\AliasNamespaceReference.cs" />
<Compile Include="Resolver\CompositeResolveVisitorNavigator.cs" />
<Compile Include="Resolver\ConstantValues.cs" />
<Compile Include="Resolver\ConversionResolveResult.cs" />
<Compile Include="Resolver\Conversions.cs" />
<Compile Include="Resolver\CSharpAttribute.cs" />
<Compile Include="Resolver\CSharpAstResolver.cs" />
<Compile Include="Resolver\CSharpInvocationResolveResult.cs" />
<Compile Include="Resolver\CSharpOperators.cs" />
<Compile Include="Resolver\CSharpResolver.cs" />
<Compile Include="Resolver\DetectSkippableNodesNavigator.cs" />
<Compile Include="Resolver\ErrorResolveResult.cs" />
<Compile Include="Resolver\FindReferencedEntities.cs" />
<Compile Include="Resolver\FindReferences.cs" />
<Compile Include="Resolver\FindReferenceSearchScope.cs" />
<Compile Include="Resolver\IResolveVisitorNavigator.cs" />
<Compile Include="Resolver\ITypeOrNamespaceReference.cs" />
<Compile Include="Resolver\LambdaResolveResult.cs" />
<Compile Include="Resolver\Log.cs" />
<Compile Include="Resolver\MapTypeIntoNewContext.cs" />
<Compile Include="Resolver\MemberLookup.cs" />
<Compile Include="Resolver\MemberTypeOrNamespaceReference.cs" />
<Compile Include="Resolver\MethodGroupResolveResult.cs" />
<Compile Include="Resolver\NodeListResolveVisitorNavigator.cs" />
<Compile Include="Resolver\OperatorResolveResult.cs" />
<Compile Include="Resolver\OverloadResolution.cs" />
<Compile Include="Resolver\OverloadResolutionErrors.cs" />
<Compile Include="Resolver\ResolveAtLocation.cs" />
<Compile Include="Resolver\ResolveVisitor.cs" />
<Compile Include="Resolver\SimpleNameLookupMode.cs" />
<Compile Include="Resolver\SimpleTypeOrNamespaceReference.cs" />
<Compile Include="Resolver\TypeInference.cs" />
<Compile Include="Resolver\UsingScope.cs" />
<Compile Include="Completion\ICompletionDataFactory.cs" />
<Compile Include="Completion\IParameterCompletionDataFactory.cs" />
<Compile Include="TypeSystem\AliasNamespaceReference.cs" />
<Compile Include="TypeSystem\AttributeTypeReference.cs" />
<Compile Include="TypeSystem\ConstantValues.cs" />
<Compile Include="TypeSystem\CSharpAssembly.cs" />
<Compile Include="TypeSystem\CSharpAttribute.cs" />
<Compile Include="TypeSystem\CSharpParsedFile.cs" />
<Compile Include="TypeSystem\CSharpUnresolvedTypeDefinition.cs" />
<Compile Include="TypeSystem\CSharpTypeResolveContext.cs" />
<Compile Include="TypeSystem\ResolvedUsingScope.cs" />
<Compile Include="TypeSystem\TypeOrNamespaceReference.cs" />
<Compile Include="TypeSystem\MemberTypeOrNamespaceReference.cs" />
<Compile Include="TypeSystem\SimpleTypeOrNamespaceReference.cs" />
<Compile Include="TypeSystem\MethodTypeParameterWithInheritedConstraints.cs" />
<Compile Include="TypeSystem\TypeSystemConvertVisitor.cs" />
<Compile Include="TypeSystem\UsingScope.cs" />
<Compile Include="Ast\GeneralScope\PreProcessorDirective.cs" />
<Compile Include="Ast\Expressions\ErrorExpression.cs" />
<Compile Include="Completion\CompletionDataWrapper.cs" />
<Compile Include="Completion\CSharpCompletionEngine.cs" />
<Compile Include="Completion\CSharpCompletionEngineBase.cs" />
<Compile Include="Completion\CSharpParameterCompletionEngine.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
@ -310,4 +324,16 @@ @@ -310,4 +324,16 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<ItemGroup>
<Folder Include="Completion\" />
</ItemGroup>
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy TabWidth="4" EolMarker="Unix" inheritsSet="Mono" inheritsScope="text/plain" scope="text/plain" />
</Policies>
</Properties>
</MonoDevelop>
</ProjectExtensions>
</Project>

239
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs

@ -0,0 +1,239 @@ @@ -0,0 +1,239 @@
// 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.IO;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// C# ambience.
/// </summary>
public class CSharpAmbience : IAmbience
{
public ConversionFlags ConversionFlags { get; set; }
#region ConvertEntity
public string ConvertEntity(IEntity e)
{
StringWriter writer = new StringWriter();
if (e.EntityType == EntityType.TypeDefinition) {
ConvertTypeDeclaration((ITypeDefinition)e, writer);
} else {
ConvertMember((IMember)e, writer);
}
return writer.ToString().TrimEnd();
}
void ConvertMember(IMember member, StringWriter writer)
{
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
astBuilder.ShowParameterNames = (ConversionFlags & ConversionFlags.ShowParameterNames) == ConversionFlags.ShowParameterNames;
AttributedNode node = (AttributedNode)astBuilder.ConvertEntity(member);
PrintModifiers(node.Modifiers, writer);
if ((ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) {
var rt = node.GetChildByRole(AstNode.Roles.Type);
if (rt != AstNode.Roles.Type.NullObject) {
writer.Write(rt.AcceptVisitor(CreatePrinter(writer), null));
writer.Write(' ');
}
}
WriteMemberDeclarationName(member, writer);
if ((ConversionFlags & ConversionFlags.ShowParameterList) == ConversionFlags.ShowParameterList
&& member is IParameterizedMember && member.EntityType != EntityType.Property) {
writer.Write((node is IndexerDeclaration) ? '[' : '(');
bool first = true;
foreach (var param in node.GetChildrenByRole(AstNode.Roles.Parameter)) {
if (first)
first = false;
else
writer.Write(", ");
param.AcceptVisitor(CreatePrinter(writer), null);
}
writer.Write((node is IndexerDeclaration) ? ']' : ')');
}
if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody) {
IProperty property = member as IProperty;
if (property != null) {
writer.Write(" { ");
if (property.CanGet)
writer.Write("get; ");
if (property.CanSet)
writer.Write("set; ");
writer.Write('}');
} else {
writer.Write(';');
}
}
}
TypeSystemAstBuilder CreateAstBuilder()
{
TypeSystemAstBuilder astBuilder = new TypeSystemAstBuilder();
astBuilder.ShowModifiers = (ConversionFlags & ConversionFlags.ShowModifiers) == ConversionFlags.ShowModifiers;
astBuilder.ShowAccessibility = (ConversionFlags & ConversionFlags.ShowAccessibility) == ConversionFlags.ShowAccessibility;
astBuilder.AlwaysUseShortTypeNames = (ConversionFlags & ConversionFlags.UseFullyQualifiedTypeNames) != ConversionFlags.UseFullyQualifiedTypeNames;
return astBuilder;
}
void ConvertTypeDeclaration(ITypeDefinition typeDef, StringWriter writer)
{
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
TypeDeclaration typeDeclaration = (TypeDeclaration)astBuilder.ConvertEntity(typeDef);
PrintModifiers(typeDeclaration.Modifiers, writer);
if ((ConversionFlags & ConversionFlags.ShowDefinitionKeyWord) == ConversionFlags.ShowDefinitionKeyWord) {
switch (typeDeclaration.ClassType) {
case ClassType.Class:
writer.Write("class");
break;
case ClassType.Struct:
writer.Write("struct");
break;
case ClassType.Interface:
writer.Write("interface");
break;
case ClassType.Enum:
writer.Write("enum");
break;
default:
throw new Exception("Invalid value for ClassType");
}
writer.Write(' ');
}
WriteTypeDeclarationName(typeDef, writer);
}
void WriteTypeDeclarationName(ITypeDefinition typeDef, StringWriter writer)
{
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
if (typeDef.DeclaringTypeDefinition != null) {
WriteTypeDeclarationName(typeDef.DeclaringTypeDefinition, writer);
writer.Write('.');
} else if ((ConversionFlags & ConversionFlags.UseFullyQualifiedMemberNames) == ConversionFlags.UseFullyQualifiedMemberNames) {
writer.Write(typeDef.Namespace);
writer.Write('.');
}
writer.Write(typeDef.Name);
if ((ConversionFlags & ConversionFlags.ShowTypeParameterList) == ConversionFlags.ShowTypeParameterList) {
CreatePrinter(writer).WriteTypeParameters(((TypeDeclaration)astBuilder.ConvertEntity(typeDef)).TypeParameters);
}
}
void WriteMemberDeclarationName(IMember member, StringWriter writer)
{
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
if ((ConversionFlags & ConversionFlags.UseFullyQualifiedMemberNames) == ConversionFlags.UseFullyQualifiedMemberNames) {
writer.Write(ConvertType(member.DeclaringType));
writer.Write('.');
}
switch (member.EntityType) {
case EntityType.Indexer:
writer.Write("this");
break;
case EntityType.Constructor:
writer.Write(member.DeclaringType.Name);
break;
case EntityType.Destructor:
writer.Write('~');
writer.Write(member.DeclaringType.Name);
break;
case EntityType.Operator:
switch (member.Name) {
case "op_Implicit":
writer.Write("implicit operator ");
writer.Write(ConvertType(member.ReturnType));
break;
case "op_Explicit":
writer.Write("explicit operator ");
writer.Write(ConvertType(member.ReturnType));
break;
default:
writer.Write("operator ");
var operatorType = OperatorDeclaration.GetOperatorType(member.Name);
if (operatorType.HasValue)
writer.Write(OperatorDeclaration.GetToken(operatorType.Value));
else
writer.Write(member.Name);
break;
}
break;
default:
writer.Write(member.Name);
break;
}
if ((ConversionFlags & ConversionFlags.ShowTypeParameterList) == ConversionFlags.ShowTypeParameterList && member.EntityType == EntityType.Method) {
CreatePrinter(writer).WriteTypeParameters(astBuilder.ConvertEntity(member).GetChildrenByRole(AstNode.Roles.TypeParameter));
}
}
CSharpOutputVisitor CreatePrinter(StringWriter writer)
{
return new CSharpOutputVisitor(writer, new CSharpFormattingOptions());
}
void PrintModifiers(Modifiers modifiers, StringWriter writer)
{
foreach (var m in CSharpModifierToken.AllModifiers) {
if ((modifiers & m) == m) {
writer.Write(CSharpModifierToken.GetModifierName(m));
writer.Write(' ');
}
}
}
#endregion
public string ConvertVariable(IVariable v)
{
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
AstNode astNode = astBuilder.ConvertVariable(v);
CSharpFormattingOptions formatting = new CSharpFormattingOptions();
StringWriter writer = new StringWriter();
astNode.AcceptVisitor(new CSharpOutputVisitor(writer, formatting), null);
return writer.ToString().TrimEnd(';', '\r', '\n');
}
public string ConvertType(IType type)
{
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
AstType astType = astBuilder.ConvertType(type);
CSharpFormattingOptions formatting = new CSharpFormattingOptions();
StringWriter writer = new StringWriter();
astType.AcceptVisitor(new CSharpOutputVisitor(writer, formatting), null);
return writer.ToString();
}
public string WrapAttribute(string attribute)
{
return "[" + attribute + "]";
}
public string WrapComment(string comment)
{
return "// " + comment;
}
}
}

125
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -142,7 +142,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -142,7 +142,7 @@ namespace ICSharpCode.NRefactory.CSharp
void WriteSpecials (AstNode start, AstNode end)
{
for (AstNode pos = start; pos != end; pos = pos.NextSibling) {
if (pos.Role == AstNode.Roles.Comment) {
if (pos.Role == AstNode.Roles.Comment || pos.Role == AstNode.Roles.PreProcessorDirective) {
pos.AcceptVisitor (this, null);
}
}
@ -154,10 +154,21 @@ namespace ICSharpCode.NRefactory.CSharp @@ -154,10 +154,21 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
void WriteSpecialsUpToRole (Role role)
{
for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) {
WriteSpecialsUpToRole (role, null);
}
void WriteSpecialsUpToRole (Role role, AstNode nextNode)
{
if (positionStack.Count == 0)
return;
// Look for the role between the current position and the nextNode.
for (AstNode pos = positionStack.Peek(); pos != null && pos != nextNode; pos = pos.NextSibling) {
if (pos.Role == role) {
WriteSpecials (positionStack.Pop (), pos);
positionStack.Push (pos);
// Push the next sibling because the node matching the role is not a special,
// and should be considered to be already handled.
positionStack.Push (pos.NextSibling);
// This is necessary for OptionalComma() to work correctly.
break;
}
}
@ -169,22 +180,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -169,22 +180,15 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
void WriteSpecialsUpToNode (AstNode node)
{
if (positionStack.Count == 0)
return;
for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) {
if (pos == node) {
WriteSpecials (positionStack.Pop (), pos);
positionStack.Push (pos);
break;
}
}
}
void WriteSpecialsUpToRole (Role role, AstNode nextNode)
{
// Look for the role between the current position and the nextNode.
for (AstNode pos = positionStack.Peek(); pos != null && pos != nextNode; pos = pos.NextSibling) {
if (pos.Role == AstNode.Roles.Comma) {
WriteSpecials (positionStack.Pop (), pos);
positionStack.Push (pos);
// Push the next sibling because the node itself is not a special,
// and should be considered to be already handled.
positionStack.Push (pos.NextSibling);
// This is necessary for OptionalComma() to work correctly.
break;
}
}
@ -206,6 +210,32 @@ namespace ICSharpCode.NRefactory.CSharp @@ -206,6 +210,32 @@ namespace ICSharpCode.NRefactory.CSharp
Space (!noSpaceAfterComma && policy.SpaceAfterBracketComma); // TODO: Comma policy has changed.
}
/// <summary>
/// Writes an optional comma, e.g. at the end of an enum declaration or in an array initializer
/// </summary>
void OptionalComma()
{
// Look if there's a comma after the current node, and insert it if it exists.
AstNode pos = positionStack.Peek();
while (pos != null && pos.NodeType == NodeType.Whitespace)
pos = pos.NextSibling;
if (pos != null && pos.Role == AstNode.Roles.Comma)
Comma(null, noSpaceAfterComma: true);
}
/// <summary>
/// Writes an optional semicolon, e.g. at the end of a type or namespace declaration.
/// </summary>
void OptionalSemicolon()
{
// Look if there's a semicolon after the current node, and insert it if it exists.
AstNode pos = positionStack.Peek();
while (pos != null && pos.NodeType == NodeType.Whitespace)
pos = pos.NextSibling;
if (pos != null && pos.Role == AstNode.Roles.Semicolon)
Semicolon();
}
void WriteCommaSeparatedList (IEnumerable<AstNode> list)
{
bool isFirst = true;
@ -341,7 +371,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -341,7 +371,7 @@ namespace ICSharpCode.NRefactory.CSharp
void RPar ()
{
WriteToken (")", AstNode.Roles.LPar);
WriteToken (")", AstNode.Roles.RPar);
}
/// <summary>
@ -441,7 +471,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -441,7 +471,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
void WriteTypeParameters (IEnumerable<TypeParameterDeclaration> typeParameters)
public void WriteTypeParameters (IEnumerable<TypeParameterDeclaration> typeParameters)
{
if (typeParameters.Any ()) {
WriteToken ("<", AstNode.Roles.LChevron);
@ -574,10 +604,41 @@ namespace ICSharpCode.NRefactory.CSharp @@ -574,10 +604,41 @@ namespace ICSharpCode.NRefactory.CSharp
public object VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, object data)
{
StartNode (arrayInitializerExpression);
PrintInitializerElements(arrayInitializerExpression.Elements);
// "new List<int> { { 1 } }" and "new List<int> { 1 }" are the same semantically.
// We also use the same AST for both: we always use two nested ArrayInitializerExpressions
// for collection initializers, even if the user did not write nested brackets.
// The output visitor will output nested braces only if they are necessary,
// or if the braces tokens exist in the AST.
bool bracesAreOptional = arrayInitializerExpression.Elements.Count == 1
&& IsObjectOrCollectionInitializer(arrayInitializerExpression.Parent)
&& !CanBeConfusedWithObjectInitializer(arrayInitializerExpression.Elements.Single());
if (bracesAreOptional && arrayInitializerExpression.LBraceToken.IsNull) {
arrayInitializerExpression.Elements.Single().AcceptVisitor(this, data);
} else {
PrintInitializerElements(arrayInitializerExpression.Elements);
}
return EndNode (arrayInitializerExpression);
}
bool CanBeConfusedWithObjectInitializer(Expression expr)
{
// "int a; new List<int> { a = 1 };" is an object initalizers and invalid, but
// "int a; new List<int> { { a = 1 } };" is a valid collection initializer.
AssignmentExpression ae = expr as AssignmentExpression;
return ae != null && ae.Operator == AssignmentOperatorType.Assign;
}
bool IsObjectOrCollectionInitializer(AstNode node)
{
if (!(node is ArrayInitializerExpression))
return false;
if (node.Parent is ObjectCreateExpression)
return node.Role == ObjectCreateExpression.InitializerRole;
if (node.Parent is NamedExpression)
return node.Role == NamedExpression.Roles.Expression;
return false;
}
void PrintInitializerElements(AstNodeCollection<Expression> elements)
{
BraceStyle style;
@ -596,6 +657,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -596,6 +657,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
node.AcceptVisitor(this, null);
}
OptionalComma();
NewLine();
CloseBrace(style);
}
@ -881,7 +943,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -881,7 +943,6 @@ namespace ICSharpCode.NRefactory.CSharp
{
StartNode (anonymousTypeCreateExpression);
WriteKeyword ("new");
Space ();
PrintInitializerElements(anonymousTypeCreateExpression.Initializers);
return EndNode (anonymousTypeCreateExpression);
}
@ -1306,9 +1367,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1306,9 +1367,10 @@ namespace ICSharpCode.NRefactory.CSharp
{
StartNode (attribute);
attribute.Type.AcceptVisitor (this, data);
Space (policy.SpaceBeforeMethodCallParentheses);
if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole (AstNode.Roles.LPar).IsNull)
if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole (AstNode.Roles.LPar).IsNull) {
Space (policy.SpaceBeforeMethodCallParentheses);
WriteCommaSeparatedListInParenthesis (attribute.Arguments, policy.SpaceWithinMethodCallParentheses);
}
return EndNode (attribute);
}
@ -1358,6 +1420,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1358,6 +1420,7 @@ namespace ICSharpCode.NRefactory.CSharp
foreach (var member in namespaceDeclaration.Members)
member.AcceptVisitor (this, data);
CloseBrace (policy.NamespaceBraceStyle);
OptionalSemicolon ();
NewLine ();
return EndNode (namespaceDeclaration);
}
@ -1409,6 +1472,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1409,6 +1472,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
member.AcceptVisitor (this, data);
}
OptionalComma();
NewLine ();
} else {
foreach (var member in typeDeclaration.Members) {
@ -1416,6 +1480,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1416,6 +1480,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
CloseBrace (braceStyle);
OptionalSemicolon ();
NewLine ();
return EndNode (typeDeclaration);
}
@ -1848,6 +1913,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1848,6 +1913,7 @@ namespace ICSharpCode.NRefactory.CSharp
public object VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, object data)
{
StartNode (variableDeclarationStatement);
WriteModifiers (variableDeclarationStatement.GetChildrenByRole (VariableDeclarationStatement.ModifierRole));
variableDeclarationStatement.Type.AcceptVisitor (this, data);
Space ();
WriteCommaSeparatedList (variableDeclarationStatement.Variables);
@ -2264,6 +2330,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2264,6 +2330,15 @@ namespace ICSharpCode.NRefactory.CSharp
return null;
}
public object VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective, object data)
{
formatter.StartNode (preProcessorDirective);
formatter.WritePreProcessorDirective(preProcessorDirective.Type, preProcessorDirective.Argument);
formatter.EndNode (preProcessorDirective);
lastWritten = LastWritten.Whitespace;
return null;
}
public object VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration, object data)
{
StartNode (typeParameterDeclaration);
@ -2289,7 +2364,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2289,7 +2364,7 @@ namespace ICSharpCode.NRefactory.CSharp
StartNode (constraint);
Space ();
WriteKeyword ("where");
WriteIdentifier (constraint.TypeParameter);
WriteIdentifier (constraint.TypeParameter.Identifier);
Space ();
WriteToken (":", Constraint.ColonRole);
Space ();
@ -2415,7 +2490,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2415,7 +2490,7 @@ namespace ICSharpCode.NRefactory.CSharp
} else if (childNode is OptionalNode) {
VisitOptionalNode((OptionalNode)childNode, data);
} else {
throw new InvalidOperationException ("Unknown node type in pattern");
WritePrimitiveValue(childNode);
}
}
#endregion

62
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs

@ -21,8 +21,8 @@ using System.CodeDom; @@ -21,8 +21,8 @@ using System.CodeDom;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
@ -38,8 +38,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -38,8 +38,8 @@ namespace ICSharpCode.NRefactory.CSharp
/// </remarks>
public class CodeDomConvertVisitor : IAstVisitor<object, CodeObject>
{
ITypeResolveContext context = MinimalResolveContext.Instance;
ResolveVisitor resolveVisitor;
//ICompilation compilation = MinimalResolveContext.Instance;
CSharpAstResolver resolver;
bool useFullyQualifiedTypeNames;
/// <summary>
@ -60,19 +60,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -60,19 +60,15 @@ namespace ICSharpCode.NRefactory.CSharp
/// <remarks>
/// This conversion process requires a resolver because it needs to distinguish field/property/event references etc.
/// </remarks>
public CodeCompileUnit Convert(CompilationUnit compilationUnit, ITypeResolveContext context, CSharpParsedFile parsedFile)
public CodeCompileUnit Convert(ICompilation compilation, CompilationUnit compilationUnit, CSharpParsedFile parsedFile)
{
if (compilationUnit == null)
throw new ArgumentNullException("compilationUnit");
if (context == null)
throw new ArgumentNullException("context");
if (parsedFile == null)
throw new ArgumentNullException("parsedFile");
using (var ctx = context.Synchronize()) {
ResolveVisitor resolveVisitor = new ResolveVisitor(new CSharpResolver(ctx), parsedFile);
resolveVisitor.Scan(compilationUnit);
return (CodeCompileUnit)Convert(compilationUnit, resolveVisitor);
}
if (compilation == null)
throw new ArgumentNullException("compilation");
CSharpAstResolver resolver = new CSharpAstResolver(compilation, compilationUnit, parsedFile);
return (CodeCompileUnit)Convert(compilationUnit, resolver);
}
/// <summary>
@ -85,28 +81,26 @@ namespace ICSharpCode.NRefactory.CSharp @@ -85,28 +81,26 @@ namespace ICSharpCode.NRefactory.CSharp
/// <remarks>
/// This conversion process requires a resolver because it needs to distinguish field/property/event references etc.
/// </remarks>
public CodeObject Convert(AstNode node, ResolveVisitor resolveVisitor)
public CodeObject Convert(AstNode node, CSharpAstResolver resolver)
{
if (node == null)
throw new ArgumentNullException("node");
if (resolveVisitor == null)
throw new ArgumentNullException("resolveVisitor");
if (resolver == null)
throw new ArgumentNullException("resolver");
try {
this.resolveVisitor = resolveVisitor;
this.context = resolveVisitor.TypeResolveContext;
this.resolver = resolver;
return node.AcceptVisitor(this);
} finally {
this.resolveVisitor = null;
this.context = MinimalResolveContext.Instance;
this.resolver = null;
}
}
ResolveResult Resolve(AstNode node)
{
if (resolveVisitor == null)
if (resolver == null)
return ErrorResolveResult.UnknownError;
else
return resolveVisitor.GetResolveResult(node);
return resolver.Resolve(node);
}
CodeExpression Convert(Expression expr)
@ -297,8 +291,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -297,8 +291,8 @@ namespace ICSharpCode.NRefactory.CSharp
break;
case BinaryOperatorType.Equality:
case BinaryOperatorType.InEquality:
BinaryOperatorResolveResult rr = Resolve(binaryOperatorExpression) as BinaryOperatorResolveResult;
if (rr != null && rr.Left.Type.IsReferenceType(context) == true) {
OperatorResolveResult rr = Resolve(binaryOperatorExpression) as OperatorResolveResult;
if (rr != null && rr.GetChildResults().Any(cr => cr.Type.IsReferenceType == true)) {
if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality)
op = CodeBinaryOperatorType.IdentityEquality;
else
@ -1240,16 +1234,22 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1240,16 +1234,22 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<object, CodeObject>.VisitPrimitiveType(PrimitiveType primitiveType, object data)
{
string keyword = primitiveType.Keyword;
for (TypeCode c = TypeCode.Empty; c <= TypeCode.String; c++) {
if (ReflectionHelper.GetCSharpNameByTypeCode(c) == keyword)
return new CodeTypeReference("System." + ReflectionHelper.GetShortNameByTypeCode(c));
KnownTypeCode typeCode = TypeSystemConvertVisitor.GetTypeCodeForPrimitiveType(keyword);
if (typeCode != KnownTypeCode.None) {
KnownTypeReference ktr = KnownTypeReference.Get(typeCode);
return new CodeTypeReference(ktr.Namespace + "." + ktr.Name);
}
return new CodeTypeReference(primitiveType.Keyword);
return new CodeTypeReference(keyword);
}
CodeObject IAstVisitor<object, CodeObject>.VisitComment (Comment comment, object data)
{
return new CodeComment (comment.Content, comment.CommentType == CommentType.Documentation);
}
CodeObject IAstVisitor<object, CodeObject>.VisitComment(Comment comment, object data)
CodeObject IAstVisitor<object, CodeObject>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective, object data)
{
return new CodeComment(comment.Content, comment.CommentType == CommentType.Documentation);
return new CodeComment ("#" + preProcessorDirective.Type.ToString ().ToLower ());
}
CodeObject IAstVisitor<object, CodeObject>.VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data)
@ -1269,7 +1269,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1269,7 +1269,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeTypeParameter tp = new CodeTypeParameter(tpDecl.Name);
tp.CustomAttributes.AddRange(Convert(tpDecl.Attributes));
foreach (Constraint constraint in constraints) {
if (constraint.TypeParameter == tp.Name) {
if (constraint.TypeParameter.Identifier == tp.Name) {
foreach (AstType baseType in constraint.BaseTypes) {
if (baseType is PrimitiveType && ((PrimitiveType)baseType).Keyword == "new") {
tp.HasConstructorConstraint = true;

1
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/IOutputFormatter.cs

@ -55,5 +55,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -55,5 +55,6 @@ namespace ICSharpCode.NRefactory.CSharp
void NewLine();
void WriteComment(CommentType commentType, string content);
void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument);
}
}

127
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs

@ -75,38 +75,41 @@ namespace ICSharpCode.NRefactory.CSharp @@ -75,38 +75,41 @@ namespace ICSharpCode.NRefactory.CSharp
public void OpenBrace(BraceStyle style)
{
bool isAtStartOfLine = needsIndent;
switch (style) {
case BraceStyle.DoNotChange:
case BraceStyle.EndOfLine:
WriteIndentation();
textWriter.Write(' ');
textWriter.Write('{');
break;
case BraceStyle.EndOfLineWithoutSpace:
WriteIndentation();
textWriter.Write('{');
break;
case BraceStyle.NextLine:
NewLine ();
WriteIndentation();
textWriter.Write('{');
break;
case BraceStyle.NextLineShifted:
NewLine ();
Indent();
WriteIndentation();
textWriter.Write('{');
NewLine();
return;
case BraceStyle.NextLineShifted2:
NewLine ();
Indent();
WriteIndentation();
textWriter.Write('{');
break;
default:
throw new ArgumentOutOfRangeException ();
case BraceStyle.DoNotChange:
case BraceStyle.EndOfLine:
WriteIndentation();
if (!isAtStartOfLine)
textWriter.Write(' ');
textWriter.Write('{');
break;
case BraceStyle.EndOfLineWithoutSpace:
WriteIndentation();
textWriter.Write('{');
break;
case BraceStyle.NextLine:
if (!isAtStartOfLine)
NewLine();
WriteIndentation();
textWriter.Write('{');
break;
case BraceStyle.NextLineShifted:
NewLine ();
Indent();
WriteIndentation();
textWriter.Write('{');
NewLine();
return;
case BraceStyle.NextLineShifted2:
NewLine ();
Indent();
WriteIndentation();
textWriter.Write('{');
break;
default:
throw new ArgumentOutOfRangeException ();
}
Indent();
NewLine();
@ -115,27 +118,27 @@ namespace ICSharpCode.NRefactory.CSharp @@ -115,27 +118,27 @@ namespace ICSharpCode.NRefactory.CSharp
public void CloseBrace(BraceStyle style)
{
switch (style) {
case BraceStyle.DoNotChange:
case BraceStyle.EndOfLine:
case BraceStyle.EndOfLineWithoutSpace:
case BraceStyle.NextLine:
Unindent();
WriteIndentation();
textWriter.Write('}');
break;
case BraceStyle.NextLineShifted:
WriteIndentation();
textWriter.Write('}');
Unindent();
break;
case BraceStyle.NextLineShifted2:
Unindent();
WriteIndentation();
textWriter.Write('}');
Unindent();
break;
default:
throw new ArgumentOutOfRangeException ();
case BraceStyle.DoNotChange:
case BraceStyle.EndOfLine:
case BraceStyle.EndOfLineWithoutSpace:
case BraceStyle.NextLine:
Unindent();
WriteIndentation();
textWriter.Write('}');
break;
case BraceStyle.NextLineShifted:
WriteIndentation();
textWriter.Write('}');
Unindent();
break;
case BraceStyle.NextLineShifted2:
Unindent();
WriteIndentation();
textWriter.Write('}');
Unindent();
break;
default:
throw new ArgumentOutOfRangeException ();
}
}
@ -172,6 +175,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -172,6 +175,7 @@ namespace ICSharpCode.NRefactory.CSharp
case CommentType.SingleLine:
textWriter.Write("//");
textWriter.WriteLine(content);
needsIndent = true;
break;
case CommentType.MultiLine:
textWriter.Write("/*");
@ -181,10 +185,29 @@ namespace ICSharpCode.NRefactory.CSharp @@ -181,10 +185,29 @@ namespace ICSharpCode.NRefactory.CSharp
case CommentType.Documentation:
textWriter.Write("///");
textWriter.WriteLine(content);
needsIndent = true;
break;
default:
textWriter.Write(content);
break;
}
}
public void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument)
{
// pre-processor directive must start on its own line
if (!needsIndent)
NewLine();
WriteIndentation();
textWriter.Write('#');
textWriter.Write(type.ToString().ToLowerInvariant());
if (!string.IsNullOrEmpty(argument)) {
textWriter.Write(' ');
textWriter.Write(argument);
}
NewLine();
}
public virtual void StartNode(AstNode node)
{
}

224
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs

@ -621,11 +621,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -621,11 +621,11 @@ namespace ICSharpCode.NRefactory.CSharp
EnumMemberDeclaration newField = new EnumMemberDeclaration ();
AddAttributeSection (newField, em);
newField.AddChild (Identifier.Create (em.Name, Convert (em.Location)), AstNode.Roles.Identifier);
if (em.Initializer != null) {
newField.AddChild (new CSharpTokenNode (Convert (em.Initializer.Location), 1), EnumMemberDeclaration.Roles.Assign);
newField.AddChild ((Expression)em.Initializer.Accept (this), EnumMemberDeclaration.InitializerRole);
}
//Console.WriteLine (newField.StartLocation +"-" + newField.EndLocation);
typeStack.Peek ().AddChild (newField, TypeDeclaration.MemberRole);
}
@ -814,7 +814,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -814,7 +814,7 @@ namespace ICSharpCode.NRefactory.CSharp
public void AddAttributeSection (AstNode parent, Attributable a)
{
if (a.OptAttributes == null)
if (a == null || a.OptAttributes == null)
return;
AddAttributeSection (parent, a.OptAttributes);
}
@ -900,7 +900,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -900,7 +900,6 @@ namespace ICSharpCode.NRefactory.CSharp
AddAttributeSection (newMethod, m);
var location = LocationsBag.GetMemberLocation (m);
AddModifiers (newMethod, location);
newMethod.AddChild (ConvertToType (m.TypeName), AstNode.Roles.Type);
if (m.MethodName.Left != null) {
newMethod.AddChild (ConvertToType (m.MethodName.Left), MethodDeclaration.PrivateImplementationTypeRole);
@ -961,6 +960,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -961,6 +960,7 @@ namespace ICSharpCode.NRefactory.CSharp
modifierTable [Mono.CSharp.Modifiers.EXTERN] = ICSharpCode.NRefactory.CSharp.Modifiers.Extern;
modifierTable [Mono.CSharp.Modifiers.VOLATILE] = ICSharpCode.NRefactory.CSharp.Modifiers.Volatile;
modifierTable [Mono.CSharp.Modifiers.UNSAFE] = ICSharpCode.NRefactory.CSharp.Modifiers.Unsafe;
modifierTable [Mono.CSharp.Modifiers.ASYNC] = ICSharpCode.NRefactory.CSharp.Modifiers.Async;
keywordTable = new string[255];
for (int i = 0; i< keywordTable.Length; i++)
@ -988,7 +988,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -988,7 +988,12 @@ namespace ICSharpCode.NRefactory.CSharp
if (location == null || location.Modifiers == null)
return;
foreach (var modifier in location.Modifiers) {
parent.AddChild (new CSharpModifierToken (Convert (modifier.Item2), modifierTable[modifier.Item1]), AttributedNode.ModifierRole);
ICSharpCode.NRefactory.CSharp.Modifiers mod;
if (!modifierTable.TryGetValue (modifier.Item1, out mod)) {
Console.WriteLine ("modifier "+ modifier.Item1 + " can't be converted,");
}
parent.AddChild (new CSharpModifierToken (Convert (modifier.Item2), mod), AttributedNode.ModifierRole);
}
}
@ -1328,6 +1333,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1328,6 +1333,11 @@ namespace ICSharpCode.NRefactory.CSharp
return new ICSharpCode.NRefactory.CSharp.EmptyExpression (Convert (emptyExpression.Location));
}
public override object Visit (Mono.CSharp.ErrorExpression emptyExpression)
{
return new ICSharpCode.NRefactory.CSharp.ErrorExpression (Convert (emptyExpression.Location));
}
public override object Visit (EmptyExpressionStatement emptyExpressionStatement)
{
return new EmptyExpression (Convert (emptyExpressionStatement.Location));
@ -1343,7 +1353,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1343,7 +1353,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), IfElseStatement.Roles.LPar);
result.AddChild ((Expression)ifStatement.Expr.Accept (this), IfElseStatement.Roles.Condition);
if (location != null)
if (location != null && location.Count > 1)
result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), IfElseStatement.Roles.RPar);
if (ifStatement.TrueStatement != null)
@ -1366,10 +1376,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1366,10 +1376,11 @@ namespace ICSharpCode.NRefactory.CSharp
result.AddChild ((Statement)doStatement.EmbeddedStatement.Accept (this), WhileStatement.Roles.EmbeddedStatement);
if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location[0]), "while".Length), DoWhileStatement.WhileKeywordRole);
if (location != null)
if (location != null && location.Count > 1)
result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), DoWhileStatement.Roles.LPar);
result.AddChild ((Expression)doStatement.expr.Accept (this), DoWhileStatement.Roles.Condition);
if (location != null) {
if (doStatement.expr != null)
result.AddChild ((Expression)doStatement.expr.Accept (this), DoWhileStatement.Roles.Condition);
if (location != null && location.Count > 2) {
result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), DoWhileStatement.Roles.RPar);
result.AddChild (new CSharpTokenNode (Convert (location[3]), 1), DoWhileStatement.Roles.Semicolon);
}
@ -1419,18 +1430,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1419,18 +1430,18 @@ namespace ICSharpCode.NRefactory.CSharp
if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), ForStatement.Roles.LPar);
AddStatementOrList (result, forStatement.InitStatement, ForStatement.InitializerRole);
AddStatementOrList (result, forStatement.Initializer, ForStatement.InitializerRole);
if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location [1]), 1), ForStatement.Roles.Semicolon);
if (forStatement.Test != null)
result.AddChild ((Expression)forStatement.Test.Accept (this), ForStatement.Roles.Condition);
if (location != null)
if (forStatement.Condition != null)
result.AddChild ((Expression)forStatement.Condition.Accept (this), ForStatement.Roles.Condition);
if (location != null && location.Count >= 3)
result.AddChild (new CSharpTokenNode (Convert (location [2]), 1), ForStatement.Roles.Semicolon);
AddStatementOrList (result, forStatement.Increment, ForStatement.IteratorRole);
AddStatementOrList (result, forStatement.Iterator, ForStatement.IteratorRole);
if (location != null)
if (location != null && location.Count >= 4)
result.AddChild (new CSharpTokenNode (Convert (location [3]), 1), ForStatement.Roles.RPar);
if (forStatement.Statement != null)
@ -1442,9 +1453,32 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1442,9 +1453,32 @@ namespace ICSharpCode.NRefactory.CSharp
public override object Visit (StatementExpression statementExpression)
{
var result = new ExpressionStatement ();
object expr = statementExpression.Expr.Accept (this);
var expr = statementExpression.Expr.Accept (this) as Expression;
if (expr != null)
result.AddChild ((Expression)expr, ExpressionStatement.Roles.Expression);
var location = LocationsBag.GetLocations (statementExpression);
if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ExpressionStatement.Roles.Semicolon);
return result;
}
public override object Visit (StatementErrorExpression statementErrorExpression)
{
var result = new ExpressionStatement ();
var expr = statementErrorExpression.Expression.Accept (this) as Expression;
if (expr != null)
result.AddChild ((Expression)expr, ExpressionStatement.Roles.Expression);
return result;
}
public override object Visit (InvalidStatementExpression statementExpression)
{
var result = new ExpressionStatement ();
if (statementExpression.Expression == null)
return result;
var expr = statementExpression.Expression.Accept (this) as Expression;
if (expr != null)
result.AddChild (expr, ExpressionStatement.Roles.Expression);
var location = LocationsBag.GetLocations (statementExpression);
if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ExpressionStatement.Roles.Semicolon);
@ -1582,7 +1616,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1582,7 +1616,8 @@ namespace ICSharpCode.NRefactory.CSharp
}
cur = u.Statement;
usingResult.AddChild (new CSharpTokenNode (Convert (blockStatement.EndLocation), 1), UsingStatement.Roles.RPar);
usingResult.AddChild ((Statement)cur.Accept (this), UsingStatement.Roles.EmbeddedStatement);
if (cur != null)
usingResult.AddChild ((Statement)cur.Accept (this), UsingStatement.Roles.EmbeddedStatement);
}
return usingResult;
}
@ -1814,8 +1849,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1814,8 +1849,10 @@ namespace ICSharpCode.NRefactory.CSharp
result.AddChild (new CSharpTokenNode (Convert (tryCatchStatement.loc), "try".Length), TryCatchStatement.TryKeywordRole);
if (tryCatchStatement.Block != null)
result.AddChild ((BlockStatement)tryCatchStatement.Block.Accept (this), TryCatchStatement.TryBlockRole);
foreach (Catch ctch in tryCatchStatement.Specific) {
result.AddChild (ConvertCatch (ctch), TryCatchStatement.CatchClauseRole);
if (tryCatchStatement.Specific != null) {
foreach (Catch ctch in tryCatchStatement.Specific) {
result.AddChild (ConvertCatch (ctch), TryCatchStatement.CatchClauseRole);
}
}
if (tryCatchStatement.General != null)
result.AddChild (ConvertCatch (tryCatchStatement.General), TryCatchStatement.CatchClauseRole);
@ -1857,13 +1894,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1857,13 +1894,13 @@ namespace ICSharpCode.NRefactory.CSharp
if (foreachStatement.Variable != null)
result.AddChild (Identifier.Create (foreachStatement.Variable.Name, Convert (foreachStatement.Variable.Location)), ForeachStatement.Roles.Identifier);
if (location != null)
if (location != null && location.Count > 1)
result.AddChild (new CSharpTokenNode (Convert (location [1]), "in".Length), ForeachStatement.Roles.InKeyword);
if (foreachStatement.Expr != null)
result.AddChild ((Expression)foreachStatement.Expr.Accept (this), ForeachStatement.Roles.Expression);
if (location != null)
if (location != null && location.Count > 2)
result.AddChild (new CSharpTokenNode (Convert (location [2]), 1), ForeachStatement.Roles.RPar);
if (foreachStatement.Statement != null)
result.AddChild ((Statement)foreachStatement.Statement.Accept (this), ForeachStatement.Roles.EmbeddedStatement);
@ -2252,6 +2289,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2252,6 +2289,8 @@ namespace ICSharpCode.NRefactory.CSharp
for (int i = 0; i < parameters.Count; i++) {
var p = (Parameter)parameters.FixedParameters [i];
if (p == null)
continue;
var location = LocationsBag.GetLocations (p);
ParameterDeclaration parameterDeclarationExpression = new ParameterDeclaration ();
AddAttributeSection (parameterDeclarationExpression, p);
@ -2378,7 +2417,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2378,7 +2417,7 @@ namespace ICSharpCode.NRefactory.CSharp
var location = LocationsBag.GetLocations (c);
var constraint = new Constraint ();
constraint.AddChild (new CSharpTokenNode (Convert (c.Location), "where".Length), InvocationExpression.Roles.Keyword);
constraint.AddChild (Identifier.Create (c.TypeParameter.Value, Convert (c.TypeParameter.Location)), InvocationExpression.Roles.Identifier);
constraint.AddChild (new SimpleType (Identifier.Create (c.TypeParameter.Value, Convert (c.TypeParameter.Location))), Constraint.TypeParameterRole);
if (location != null)
constraint.AddChild (new CSharpTokenNode (Convert (location [0]), 1), Constraint.ColonRole);
var commaLocs = LocationsBag.GetLocations (c.ConstraintExpressions);
@ -2639,7 +2678,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2639,7 +2678,10 @@ namespace ICSharpCode.NRefactory.CSharp
initializer.AddChild (new CSharpTokenNode (Convert (arrayCreationExpression.Initializers.Location), 1), ArrayCreateExpression.Roles.LBrace);
var commaLocations = LocationsBag.GetLocations (arrayCreationExpression.Initializers.Elements);
for (int i = 0; i < arrayCreationExpression.Initializers.Count; i++) {
initializer.AddChild ((Expression)arrayCreationExpression.Initializers[i].Accept (this), ArrayInitializerExpression.Roles.Expression);
var init = arrayCreationExpression.Initializers[i];
if (init == null)
continue;
initializer.AddChild ((Expression)init.Accept (this), ArrayInitializerExpression.Roles.Expression);
if (commaLocations != null && i < commaLocations.Count) {
initializer.AddChild (new CSharpTokenNode (Convert (commaLocations [i]), 1), IndexerExpression.Roles.Comma);
}
@ -2885,14 +2927,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2885,14 +2927,19 @@ namespace ICSharpCode.NRefactory.CSharp
{
var result = new AnonymousMethodExpression ();
var location = LocationsBag.GetLocations (anonymousMethodExpression);
int l = 0;
if (anonymousMethodExpression.IsAsync) {
result.IsAsync = true;
result.AddChild (new CSharpTokenNode (Convert (location[l++]), "async".Length), AnonymousMethodExpression.AsyncModifierRole);
}
if (location != null) {
result.AddChild (new CSharpTokenNode (Convert (location[0]), "delegate".Length), AnonymousMethodExpression.Roles.Keyword);
result.AddChild (new CSharpTokenNode (Convert (location[l++]), "delegate".Length), AnonymousMethodExpression.Roles.Keyword);
if (location.Count > 1) {
if (location.Count > l) {
result.HasParameterList = true;
result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AnonymousMethodExpression.Roles.LPar);
result.AddChild (new CSharpTokenNode (Convert (location[l++]), 1), AnonymousMethodExpression.Roles.LPar);
AddParameter (result, anonymousMethodExpression.Parameters);
result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AnonymousMethodExpression.Roles.RPar);
result.AddChild (new CSharpTokenNode (Convert (location[l++]), 1), AnonymousMethodExpression.Roles.RPar);
}
}
result.AddChild ((BlockStatement)anonymousMethodExpression.Block.Accept (this), AnonymousMethodExpression.Roles.Body);
@ -2903,24 +2950,31 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2903,24 +2950,31 @@ namespace ICSharpCode.NRefactory.CSharp
{
var result = new LambdaExpression ();
var location = LocationsBag.GetLocations (lambdaExpression);
int l = 0;
if (lambdaExpression.IsAsync) {
result.IsAsync = true;
result.AddChild (new CSharpTokenNode (Convert (location [l++]), "async".Length), LambdaExpression.AsyncModifierRole);
}
if (location == null || location.Count == 1) {
if (location == null || location.Count == l + 1) {
AddParameter (result, lambdaExpression.Parameters);
if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location [0]), "=>".Length), LambdaExpression.ArrowRole);
result.AddChild (new CSharpTokenNode (Convert (location [l++]), "=>".Length), LambdaExpression.ArrowRole);
} else {
result.AddChild (new CSharpTokenNode (Convert (lambdaExpression.Location), 1), LambdaExpression.Roles.LPar);
result.AddChild (new CSharpTokenNode (Convert (location [l++]), 1), LambdaExpression.Roles.LPar);
AddParameter (result, lambdaExpression.Parameters);
if (location != null) {
result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), LambdaExpression.Roles.RPar);
result.AddChild (new CSharpTokenNode (Convert (location [1]), "=>".Length), LambdaExpression.ArrowRole);
result.AddChild (new CSharpTokenNode (Convert (location [l++]), 1), LambdaExpression.Roles.RPar);
result.AddChild (new CSharpTokenNode (Convert (location [l++]), "=>".Length), LambdaExpression.ArrowRole);
}
}
if (lambdaExpression.Block.IsCompilerGenerated) {
ContextualReturn generatedReturn = (ContextualReturn)lambdaExpression.Block.Statements [0];
result.AddChild ((AstNode)generatedReturn.Expr.Accept (this), LambdaExpression.BodyRole);
} else {
result.AddChild ((AstNode)lambdaExpression.Block.Accept (this), LambdaExpression.BodyRole);
if (lambdaExpression.Block != null) {
if (lambdaExpression.Block.IsCompilerGenerated) {
ContextualReturn generatedReturn = (ContextualReturn)lambdaExpression.Block.Statements [0];
result.AddChild ((AstNode)generatedReturn.Expr.Accept (this), LambdaExpression.BodyRole);
} else {
result.AddChild ((AstNode)lambdaExpression.Block.Accept (this), LambdaExpression.BodyRole);
}
}
return result;
@ -2938,7 +2992,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2938,7 +2992,10 @@ namespace ICSharpCode.NRefactory.CSharp
result.AddChild (new CSharpTokenNode (Convert (arrayInitializer.Location), "{".Length), ArrayInitializerExpression.Roles.LBrace);
var commaLocations = LocationsBag.GetLocations (arrayInitializer.Elements);
for (int i = 0; i < arrayInitializer.Count; i++) {
result.AddChild ((Expression)arrayInitializer[i].Accept (this), ArrayInitializerExpression.Roles.Expression);
var init = arrayInitializer[i];
if (init == null)
continue;
result.AddChild ((Expression)init.Accept (this), ArrayInitializerExpression.Roles.Expression);
if (commaLocations != null && i < commaLocations.Count)
result.AddChild (new CSharpTokenNode (Convert (commaLocations[i]), ",".Length), ArrayInitializerExpression.Roles.Comma);
}
@ -3186,6 +3243,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3186,6 +3243,16 @@ namespace ICSharpCode.NRefactory.CSharp
result.AddChild (ordering, QueryOrderClause.OrderingRole);
return result;
}
public override object Visit (Await awaitExpr)
{
var result = new UnaryOperatorExpression ();
result.Operator = UnaryOperatorType.Await;
result.AddChild (new CSharpTokenNode (Convert (awaitExpr.Location), 1), UnaryOperatorExpression.OperatorRole);
if (awaitExpr.Expression != null)
result.AddChild ((Expression)awaitExpr.Expression.Accept (this), UnaryOperatorExpression.Roles.Expression);
return result;
}
#endregion
}
@ -3220,11 +3287,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3220,11 +3287,9 @@ namespace ICSharpCode.NRefactory.CSharp
static void InsertComments (CompilerCompilationUnit top, ConversionVisitor conversionVisitor)
{
var leaf = GetOuterLeft (conversionVisitor.Unit);
for (int i = 0; i < top.SpecialsBag.Specials.Count; i++) {
var special = top.SpecialsBag.Specials [i];
Comment newLeaf = null;
AstNode newLeaf = null;
var comment = special as SpecialsBag.Comment;
if (comment != null) {
if (conversionVisitor.convertTypeSystemMode && (comment.CommentType != SpecialsBag.CommentType.Documentation))
@ -3237,37 +3302,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3237,37 +3302,14 @@ namespace ICSharpCode.NRefactory.CSharp
Content = comment.Content
};
} else {
// TODO: Proper handling of pre processor directives (atm got treated as comments Ast wise)
var directive = special as SpecialsBag.PreProcessorDirective;
if (directive != null) {
newLeaf = new Comment (CommentType.SingleLine, new TextLocation (directive.Line, directive.Col), new TextLocation (directive.EndLine, directive.EndCol + 1));
if (!directive.Take) {
SpecialsBag.PreProcessorDirective endif = null;
int endifLevel = 0;
for (int j = i + 1; j < top.SpecialsBag.Specials.Count; j++) {
var s = top.SpecialsBag.Specials [j] as SpecialsBag.PreProcessorDirective;
if (s == null)
continue;
if (s.Cmd == Tokenizer.PreprocessorDirective.If) {
endifLevel++;
continue;
}
if (s.Cmd == Tokenizer.PreprocessorDirective.Endif || endifLevel == 0 && s.Cmd == Tokenizer.PreprocessorDirective.Else) {
if (endifLevel == 0) {
endif = s;
i = j;
break;
}
endifLevel--;
}
}
if (endif != null)
newLeaf = new Comment (CommentType.SingleLine, new TextLocation (directive.Line, directive.Col), new TextLocation (endif.EndLine, endif.EndCol));
}
newLeaf = new PreProcessorDirective ((ICSharpCode.NRefactory.CSharp.PreProcessorDirectiveType)((int)directive.Cmd & 0xF), new TextLocation (directive.Line, directive.Col), new TextLocation (directive.EndLine, directive.EndCol)) {
Argument = directive.Arg,
Take = directive.Take
};
}
}
if (newLeaf == null)
continue;
@ -3280,7 +3322,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3280,7 +3322,11 @@ namespace ICSharpCode.NRefactory.CSharp
leaf = node;
node = node.Parent;
}
node.InsertChildBefore (leaf, newLeaf, AstNode.Roles.Comment);
if (newLeaf is Comment) {
node.InsertChildBefore (leaf, (Comment)newLeaf, AstNode.Roles.Comment);
} else {
node.InsertChildBefore (leaf, (PreProcessorDirective)newLeaf, AstNode.Roles.PreProcessorDirective);
}
leaf = newLeaf;
break;
}
@ -3288,7 +3334,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3288,7 +3334,11 @@ namespace ICSharpCode.NRefactory.CSharp
// insert comment at the end
if (nextLeaf == null) {
var node = leaf.Parent ?? conversionVisitor.Unit;
node.AddChild (newLeaf, AstNode.Roles.Comment);
if (newLeaf is Comment) {
node.AddChild ((Comment)newLeaf, AstNode.Roles.Comment);
} else {
node.AddChild ((PreProcessorDirective)newLeaf, AstNode.Roles.PreProcessorDirective);
}
leaf = newLeaf;
break;
}
@ -3296,7 +3346,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3296,7 +3346,11 @@ namespace ICSharpCode.NRefactory.CSharp
// comment is between 2 nodes
if (leaf.EndLocation <= newLeaf.StartLocation && newLeaf.StartLocation <= nextLeaf.StartLocation) {
var node = leaf.Parent ?? conversionVisitor.Unit;
node.InsertChildAfter (leaf, newLeaf, AstNode.Roles.Comment);
if (newLeaf is Comment) {
node.InsertChildAfter (leaf, (Comment)newLeaf, AstNode.Roles.Comment);
} else {
node.InsertChildAfter (leaf, (PreProcessorDirective)newLeaf, AstNode.Roles.PreProcessorDirective);
}
leaf = newLeaf;
break;
}
@ -3353,7 +3407,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3353,7 +3407,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public CompilationUnit Parse (TextReader reader, int line = 0)
public CompilationUnit Parse (TextReader reader, string fileName, int lineModifier = 0)
{
// TODO: can we optimize this to avoid the text->stream->text roundtrip?
using (MemoryStream stream = new MemoryStream ()) {
@ -3364,21 +3418,21 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3364,21 +3418,21 @@ namespace ICSharpCode.NRefactory.CSharp
w.Write (buffer, 0, read);
w.Flush (); // we can't close the StreamWriter because that would also close the MemoryStream
stream.Position = 0;
return Parse (stream, line);
return Parse (stream, fileName, lineModifier);
}
}
public static void AdjustLineLocations (AstNode node, int line)
public static void AdjustLineLocations (AstNode node, int lineModifier)
{
if (node is IRelocatable) {
((IRelocatable)node).SetStartLocation (new TextLocation (node.StartLocation.Line + line, node.StartLocation.Column));
((IRelocatable)node).SetStartLocation (new TextLocation (node.StartLocation.Line + lineModifier, node.StartLocation.Column));
}
foreach (var child in node.Children) {
AdjustLineLocations (child, line);
AdjustLineLocations (child, lineModifier);
}
}
public CompilationUnit Parse (CompilerCompilationUnit top, int line)
public CompilationUnit Parse (CompilerCompilationUnit top, string fileName, int lineModifier = 0)
{
if (top == null)
return null;
@ -3388,10 +3442,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3388,10 +3442,11 @@ namespace ICSharpCode.NRefactory.CSharp
InsertComments (top, conversionVisitor);
if (CompilationUnitCallback != null)
CompilationUnitCallback (top);
if (line != 0)
AdjustLineLocations (conversionVisitor.Unit, line);
if (lineModifier != 0)
AdjustLineLocations (conversionVisitor.Unit, lineModifier);
if (top.LastYYValue is Mono.CSharp.Expression)
conversionVisitor.Unit.TopExpression = ((Mono.CSharp.Expression)top.LastYYValue).Accept (conversionVisitor) as AstNode;
conversionVisitor.Unit.FileName = fileName;
return conversionVisitor.Unit;
}
@ -3410,12 +3465,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3410,12 +3465,17 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public CompilationUnit Parse (Stream stream, int line = 0)
public CompilationUnit Parse (string program, string fileName)
{
return Parse (new StringReader (program), fileName);
}
public CompilationUnit Parse (Stream stream, string fileName, int lineModifier = 0)
{
lock (CompilerCallableEntryPoint.parseLock) {
errorReportPrinter = new ErrorReportPrinter ("");
CompilerCompilationUnit top = CompilerCallableEntryPoint.ParseFile (CompilerArguments, stream, "parsed.cs", errorReportPrinter);
var unit = Parse (top, line);
CompilerCompilationUnit top = CompilerCallableEntryPoint.ParseFile (CompilerArguments, stream, fileName, errorReportPrinter);
var unit = Parse (top, fileName, lineModifier);
unit.Errors.AddRange (errorReportPrinter.Errors);
return unit;
}
@ -3424,7 +3484,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3424,7 +3484,7 @@ namespace ICSharpCode.NRefactory.CSharp
public IEnumerable<AttributedNode> ParseTypeMembers (TextReader reader, int lineModifier = 0)
{
string code = "unsafe partial class MyClass { " + Environment.NewLine + reader.ReadToEnd () + "}";
var cu = Parse (new StringReader (code), -1 + lineModifier);
var cu = Parse (new StringReader (code), "parsed.cs", lineModifier - 1);
if (cu == null)
return Enumerable.Empty<AttributedNode> ();
var td = cu.Children.FirstOrDefault () as TypeDeclaration;

40
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs

@ -6,7 +6,8 @@ @@ -6,7 +6,8 @@
// Marek Safar (marek.safar@gmail.com)
//
// Dual licensed under the terms of the MIT X11 or GNU GPL
// Copyright 2003-2008 Novell, Inc.
// Copyright 2003-2011 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
using System;
@ -881,13 +882,12 @@ namespace Mono.CSharp { @@ -881,13 +882,12 @@ namespace Mono.CSharp {
}
readonly Dictionary<TypeSpec, Expression> compatibles;
readonly bool is_async;
public ParametersBlock Block;
public AnonymousMethodExpression (bool isAsync, Location loc)
{
this.is_async = isAsync;
this.IsAsync = isAsync;
this.loc = loc;
this.compatibles = new Dictionary<TypeSpec, Expression> ();
}
@ -906,18 +906,16 @@ namespace Mono.CSharp { @@ -906,18 +906,16 @@ namespace Mono.CSharp {
}
}
public bool IsAsync {
get {
return is_async;
}
}
public ParametersCompiled Parameters {
get {
return Block.Parameters;
}
}
public bool IsAsync {
get;
private set;
}
#endregion
//
@ -1070,11 +1068,11 @@ namespace Mono.CSharp { @@ -1070,11 +1068,11 @@ namespace Mono.CSharp {
using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) {
var body = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type);
if (body != null) {
if (is_async) {
if (Block.IsAsync) {
AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, null, loc);
}
am = body.Compatible (ec, body, is_async);
am = body.Compatible (ec, body);
} else {
am = null;
}
@ -1135,7 +1133,7 @@ namespace Mono.CSharp { @@ -1135,7 +1133,7 @@ namespace Mono.CSharp {
// lambda, this also means no variable capturing between this
// and parent scope
//
am = body.Compatible (ec, ec.CurrentAnonymousMethod, is_async);
am = body.Compatible (ec, ec.CurrentAnonymousMethod);
//
// Quote nested expression tree
@ -1156,8 +1154,16 @@ namespace Mono.CSharp { @@ -1156,8 +1154,16 @@ namespace Mono.CSharp {
am = CreateExpressionTree (ec, delegate_type);
}
} else {
if (is_async) {
AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, body.ReturnType, loc);
if (Block.IsAsync) {
var rt = body.ReturnType;
if (rt.Kind != MemberKind.Void &&
rt != ec.Module.PredefinedTypes.Task.TypeSpec &&
!rt.IsGenericTask) {
ec.Report.Error (4010, loc, "Cannot convert async {0} to delegate type `{1}'",
GetSignatureForError (), type.GetSignatureForError ());
}
AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, rt, loc);
}
am = body.Compatible (ec);
@ -1394,10 +1400,10 @@ namespace Mono.CSharp { @@ -1394,10 +1400,10 @@ namespace Mono.CSharp {
public AnonymousExpression Compatible (ResolveContext ec)
{
return Compatible (ec, this, false);
return Compatible (ec, this);
}
public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae, bool isAsync)
public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae)
{
if (block.Resolved)
return this;
@ -1438,7 +1444,7 @@ namespace Mono.CSharp { @@ -1438,7 +1444,7 @@ namespace Mono.CSharp {
// If e is synchronous the inferred return type is T
// If e is asynchronous the inferred return type is Task<T>
//
if (isAsync && ReturnType != null) {
if (block.IsAsync && ReturnType != null) {
ReturnType = ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType });
}
}

3
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/argument.cs

@ -6,7 +6,8 @@ @@ -6,7 +6,8 @@
// Marek Safar (marek.safar@gmail.com)
//
// Dual licensed under the terms of the MIT X11 or GNU GPL
// Copyright 2003-2008 Novell, Inc.
// Copyright 2003-2011 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
using System;

21
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/assembly.cs

@ -6,7 +6,8 @@ @@ -6,7 +6,8 @@
// Marek Safar (marek.safar@gmail.com)
//
// Copyright 2001, 2002, 2003 Ximian, Inc.
// Copyright 2004 Novell, Inc.
// Copyright 2004-2011 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
@ -317,17 +318,16 @@ namespace Mono.CSharp @@ -317,17 +318,16 @@ namespace Mono.CSharp
string assembly_name = a.GetString ();
if (assembly_name.Length == 0)
return;
AssemblyName aname = null;
try {
aname = new AssemblyName (assembly_name);
} catch (Exception) {
#if STATIC
ParsedAssemblyName aname;
ParseAssemblyResult r = Fusion.ParseAssemblyName (assembly_name, out aname);
if (r != ParseAssemblyResult.OK) {
Report.Warning (1700, 3, a.Location, "Assembly reference `{0}' is invalid and cannot be resolved",
assembly_name);
return;
}
if (aname.Version != null || aname.CultureInfo != null || aname.ProcessorArchitecture != ProcessorArchitecture.None) {
if (aname.Version != null || aname.Culture != null || aname.ProcessorArchitecture != ProcessorArchitecture.None) {
Report.Error (1725, a.Location,
"Friend assembly reference `{0}' is invalid. InternalsVisibleTo declarations cannot have a version, culture or processor architecture specified",
assembly_name);
@ -335,13 +335,13 @@ namespace Mono.CSharp @@ -335,13 +335,13 @@ namespace Mono.CSharp
return;
}
// TODO: GetPublicKey () does not work on .NET when AssemblyName is constructed from a string
if (public_key != null && aname.GetPublicKey () == null) {
if (public_key != null && !aname.HasPublicKey) {
Report.Error (1726, a.Location,
"Friend assembly reference `{0}' is invalid. Strong named assemblies must specify a public key in their InternalsVisibleTo declarations",
assembly_name);
return;
}
#endif
} else if (a.Type == pa.RuntimeCompatibility) {
wrap_non_exception_throws_custom = true;
} else if (a.Type == pa.AssemblyFileVersion) {
@ -485,6 +485,7 @@ namespace Mono.CSharp @@ -485,6 +485,7 @@ namespace Mono.CSharp
}
#else
var args = new PermissionSet[3];
#pragma warning disable 618
declarative_security.TryGetValue (SecurityAction.RequestMinimum, out args[0]);
declarative_security.TryGetValue (SecurityAction.RequestOptional, out args[1]);
declarative_security.TryGetValue (SecurityAction.RequestRefuse, out args[2]);
@ -826,7 +827,7 @@ namespace Mono.CSharp @@ -826,7 +827,7 @@ namespace Mono.CSharp
Compiler.TimeReporter.Stop (TimeReporter.TimerType.OutputSave);
// Save debug symbols file
if (symbol_writer != null) {
if (symbol_writer != null && Compiler.Report.Errors == 0) {
// TODO: it should run in parallel
Compiler.TimeReporter.Start (TimeReporter.TimerType.DebugSave);
symbol_writer.WriteSymbolFile (SymbolWriter.GetGuid (module.Builder));

13
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/assign.cs

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
//
// Copyright 2001, 2002, 2003 Ximian, Inc.
// Copyright 2004-2008 Novell, Inc
// Copyright 2011 Xamarin Inc
//
using System;
@ -342,7 +343,7 @@ namespace Mono.CSharp { @@ -342,7 +343,7 @@ namespace Mono.CSharp {
type = target_type;
if (!(target is IAssignMethod)) {
Error_ValueAssignment (ec, loc);
Error_ValueAssignment (ec, source);
return null;
}
@ -484,6 +485,16 @@ namespace Mono.CSharp { @@ -484,6 +485,16 @@ namespace Mono.CSharp {
{
}
protected override Expression DoResolve (ResolveContext ec)
{
var expr = base.DoResolve (ec);
var vr = target as VariableReference;
if (vr != null && vr.VariableInfo != null)
vr.VariableInfo.IsEverAssigned = false;
return expr;
}
public void UpdateSource (Expression source)
{
base.source = source;

261
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs

@ -23,11 +23,17 @@ using System.Reflection.Emit; @@ -23,11 +23,17 @@ using System.Reflection.Emit;
namespace Mono.CSharp
{
class Await : ExpressionStatement
public class Await : ExpressionStatement
{
Expression expr;
AwaitStatement stmt;
public Expression Expression {
get {
return expr;
}
}
public Await (Expression expr, Location loc)
{
this.expr = expr;
@ -64,18 +70,12 @@ namespace Mono.CSharp @@ -64,18 +70,12 @@ namespace Mono.CSharp
}
if (rc.IsUnsafe) {
// TODO: New error code
rc.Report.Error (-1900, loc,
rc.Report.Error (4004, loc,
"The `await' operator cannot be used in an unsafe context");
}
var bc = (BlockContext) rc;
if (!bc.CurrentBlock.ParametersBlock.IsAsync) {
// TODO: Should check for existence of await type but
// what to do with it
}
stmt = new AwaitStatement (expr, loc);
if (!stmt.Resolve (bc))
return null;
@ -108,6 +108,11 @@ namespace Mono.CSharp @@ -108,6 +108,11 @@ namespace Mono.CSharp
{
stmt.EmitStatement (ec);
}
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
}
}
class AwaitStatement : YieldStatement<AsyncInitializer>
@ -121,12 +126,12 @@ namespace Mono.CSharp @@ -121,12 +126,12 @@ namespace Mono.CSharp
protected override void Error_TypeDoesNotContainDefinition (ResolveContext rc, TypeSpec type, string name)
{
Error_WrongGetAwaiter (rc, loc, type);
Error_OperatorCannotBeApplied (rc, type);
}
protected override void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type)
{
rc.Report.Error (1991, loc, "Cannot await `{0}' expression", type.GetSignatureForError ());
rc.Report.Error (4001, loc, "Cannot await `{0}' expression", type.GetSignatureForError ());
}
}
@ -243,12 +248,11 @@ namespace Mono.CSharp @@ -243,12 +248,11 @@ namespace Mono.CSharp
//
ec.AssertEmptyStack ();
var args = new Arguments (1);
var storey = (AsyncTaskStorey) machine_initializer.Storey;
var fe_cont = new FieldExpr (storey.Continuation, loc);
fe_cont.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
var cont_field = storey.EmitContinuationInitialization (ec);
args.Add (new Argument (fe_cont));
var args = new Arguments (1);
args.Add (new Argument (cont_field));
if (IsDynamic) {
var rc = new ResolveContext (ec.MemberContext);
@ -288,16 +292,9 @@ namespace Mono.CSharp @@ -288,16 +292,9 @@ namespace Mono.CSharp
}
}
static void Error_WrongGetAwaiter (ResolveContext rc, Location loc, TypeSpec type)
{
rc.Report.Error (1986, loc,
"The `await' operand type `{0}' must have suitable GetAwaiter method",
type.GetSignatureForError ());
}
void Error_WrongAwaiterPattern (ResolveContext rc, TypeSpec awaiter)
{
rc.Report.Error (1999, loc, "The awaiter type `{0}' must have suitable IsCompleted, OnCompleted, and GetResult members",
rc.Report.Error (4011, loc, "The awaiter type `{0}' must have suitable IsCompleted, OnCompleted, and GetResult members",
awaiter.GetSignatureForError ());
}
@ -335,7 +332,10 @@ namespace Mono.CSharp @@ -335,7 +332,10 @@ namespace Mono.CSharp
bc.Report.SetPrinter (old);
if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression (ama.Type)) {
Error_WrongGetAwaiter (bc, expr.Location, expr.Type);
bc.Report.Error (1986, expr.Location,
"The `await' operand type `{0}' must have suitable GetAwaiter method",
expr.Type.GetSignatureForError ());
return false;
}
@ -428,12 +428,6 @@ namespace Mono.CSharp @@ -428,12 +428,6 @@ namespace Mono.CSharp
public static void Create (IMemberContext context, ParametersBlock block, ParametersCompiled parameters, TypeContainer host, TypeSpec returnType, Location loc)
{
if (returnType != null && returnType.Kind != MemberKind.Void &&
returnType != host.Module.PredefinedTypes.Task.TypeSpec &&
!returnType.IsGenericTask) {
host.Compiler.Report.Error (1983, loc, "The return type of an async method must be void, Task, or Task<T>");
}
for (int i = 0; i < parameters.Count; i++) {
Parameter p = parameters[i];
Parameter.Modifier mod = p.ModFlags;
@ -443,22 +437,20 @@ namespace Mono.CSharp @@ -443,22 +437,20 @@ namespace Mono.CSharp
return;
}
// TODO:
if (p is ArglistParameter) {
host.Compiler.Report.Error (1636, p.Location,
"__arglist is not allowed in parameter list of iterators");
host.Compiler.Report.Error (4006, p.Location,
"__arglist is not allowed in parameter list of async methods");
return;
}
// TODO:
if (parameters.Types[i].IsPointer) {
host.Compiler.Report.Error (1637, p.Location,
"Iterators cannot have unsafe parameters or yield types");
host.Compiler.Report.Error (4005, p.Location,
"Async methods cannot have unsafe parameters");
return;
}
}
if (!block.IsAsync) {
if (!block.HasAwait) {
host.Compiler.Report.Warning (1998, 1, loc,
"Async block lacks `await' operator and will run synchronously");
}
@ -533,41 +525,6 @@ namespace Mono.CSharp @@ -533,41 +525,6 @@ namespace Mono.CSharp
class AsyncTaskStorey : StateMachine
{
sealed class ParametersLoadStatement : Statement
{
readonly FieldSpec[] fields;
readonly TypeSpec[] parametersTypes;
readonly int thisParameterIndex;
public ParametersLoadStatement (FieldSpec[] fields, TypeSpec[] parametersTypes, int thisParameterIndex)
{
this.fields = fields;
this.parametersTypes = parametersTypes;
this.thisParameterIndex = thisParameterIndex;
}
protected override void CloneTo (CloneContext clonectx, Statement target)
{
throw new NotImplementedException ();
}
protected override void DoEmit (EmitContext ec)
{
for (int i = 0; i < fields.Length; ++i) {
var field = fields[i];
if (field == null)
continue;
ec.EmitArgumentLoad (thisParameterIndex);
ec.EmitArgumentLoad (i);
if (parametersTypes[i] is ReferenceContainer)
ec.EmitLoadFromPtr (field.MemberType);
ec.Emit (OpCodes.Stfld, field);
}
}
}
int awaiters;
Field builder, continuation;
readonly TypeSpec return_type;
@ -576,6 +533,8 @@ namespace Mono.CSharp @@ -576,6 +533,8 @@ namespace Mono.CSharp
PropertySpec task;
LocalVariable hoisted_return;
int locals_captured;
Dictionary<TypeSpec, List<StackField>> stack_fields;
TypeSpec action;
public AsyncTaskStorey (IMemberContext context, AsyncInitializer initializer, TypeSpec type)
: base (initializer.OriginalBlock, initializer.Host,context.CurrentMemberDefinition as MemberBase, context.CurrentTypeParameters, "async")
@ -591,12 +550,6 @@ namespace Mono.CSharp @@ -591,12 +550,6 @@ namespace Mono.CSharp
}
}
public Field Continuation {
get {
return continuation;
}
}
public LocalVariable HoistedReturn {
get {
return hoisted_return;
@ -619,27 +572,45 @@ namespace Mono.CSharp @@ -619,27 +572,45 @@ namespace Mono.CSharp
public Field AddAwaiter (TypeSpec type, Location loc)
{
return AddCompilerGeneratedField ("$awaiter" + awaiters++.ToString ("X"), new TypeExpression (type, loc), true);
return AddCapturedVariable ("$awaiter" + awaiters++.ToString ("X"), type);
}
public Field AddCapturedLocalVariable (TypeSpec type)
public StackField AddCapturedLocalVariable (TypeSpec type)
{
if (mutator != null)
type = mutator.Mutate (type);
var field = AddCompilerGeneratedField ("<s>$" + locals_captured++.ToString ("X"), new TypeExpression (type, Location), true);
List<StackField> existing_fields = null;
if (stack_fields == null) {
stack_fields = new Dictionary<TypeSpec, List<StackField>> ();
} else if (stack_fields.TryGetValue (type, out existing_fields)) {
foreach (var f in existing_fields) {
if (f.CanBeReused) {
f.CanBeReused = false;
return f;
}
}
}
const Modifiers mod = Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE;
var field = new StackField (this, new TypeExpression (type, Location), mod, new MemberName ("<s>$" + locals_captured++.ToString ("X"), Location));
AddField (field);
field.Define ();
if (existing_fields == null) {
existing_fields = new List<StackField> ();
stack_fields.Add (type, existing_fields);
}
existing_fields.Add (field);
return field;
}
protected override bool DoDefineMembers ()
{
var action = Module.PredefinedTypes.Action.Resolve ();
if (action != null) {
continuation = AddCompilerGeneratedField ("$continuation", new TypeExpression (action, Location), true);
continuation.ModFlags |= Modifiers.READONLY;
}
action = Module.PredefinedTypes.Action.Resolve ();
PredefinedType builder_type;
PredefinedMember<MethodSpec> bf;
@ -658,22 +629,26 @@ namespace Mono.CSharp @@ -658,22 +629,26 @@ namespace Mono.CSharp
bf = pred_members.AsyncTaskMethodBuilderCreate;
sr = pred_members.AsyncTaskMethodBuilderSetResult;
se = pred_members.AsyncTaskMethodBuilderSetException;
task = pred_members.AsyncTaskMethodBuilderTask.Resolve (Location);
task = pred_members.AsyncTaskMethodBuilderTask.Get ();
} else {
builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric;
bf = pred_members.AsyncTaskMethodBuilderGenericCreate;
sr = pred_members.AsyncTaskMethodBuilderGenericSetResult;
se = pred_members.AsyncTaskMethodBuilderGenericSetException;
task = pred_members.AsyncTaskMethodBuilderGenericTask.Resolve (Location);
task = pred_members.AsyncTaskMethodBuilderGenericTask.Get ();
has_task_return_type = true;
}
set_result = sr.Resolve (Location);
set_exception = se.Resolve (Location);
var builder_factory = bf.Resolve (Location);
var bt = builder_type.Resolve ();
if (bt == null || set_result == null || builder_factory == null || set_exception == null)
return false;
set_result = sr.Get ();
set_exception = se.Get ();
var builder_factory = bf.Get ();
if (!builder_type.Define () || set_result == null || builder_factory == null || set_exception == null) {
Report.Error (1993, Location,
"Cannot find compiler required types for asynchronous functions support. Are you targeting the wrong framework version?");
return base.DoDefineMembers ();
}
var bt = builder_type.TypeSpec;
//
// Inflate generic Task types
@ -693,35 +668,17 @@ namespace Mono.CSharp @@ -693,35 +668,17 @@ namespace Mono.CSharp
}
builder = AddCompilerGeneratedField ("$builder", new TypeExpression (bt, Location));
builder.ModFlags |= Modifiers.READONLY;
if (!base.DoDefineMembers ())
return false;
MethodGroupExpr mg;
var block = instance_constructors[0].Block;
//
// Initialize continuation with state machine method
//
if (continuation != null) {
var args = new Arguments (1);
mg = MethodGroupExpr.CreatePredefined (StateMachineMethod.Spec, spec, Location);
args.Add (new Argument (mg));
block.AddStatement (
new StatementExpression (new SimpleAssign (
new FieldExpr (continuation, Location),
new NewDelegate (action, args, Location),
Location
)));
}
mg = MethodGroupExpr.CreatePredefined (builder_factory, bt, Location);
var mg = MethodGroupExpr.CreatePredefined (builder_factory, bt, Location);
block.AddStatement (
new StatementExpression (new SimpleAssign (
new FieldExpr (builder, Location),
new Invocation (mg, new Arguments (0)),
new FieldExpr (builder, Location),
new Invocation (mg, new Arguments (0)),
Location)));
if (has_task_return_type) {
@ -731,6 +688,54 @@ namespace Mono.CSharp @@ -731,6 +688,54 @@ namespace Mono.CSharp
return true;
}
public Expression EmitContinuationInitialization (EmitContext ec)
{
//
// When more than 1 awaiter has been used in the block we
// introduce class scope field to cache continuation delegate
//
if (awaiters > 1) {
if (continuation == null) {
continuation = AddCompilerGeneratedField ("$continuation", new TypeExpression (action, Location), true);
continuation.Define ();
}
var fexpr = new FieldExpr (continuation, Location);
fexpr.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location);
//
// if ($continuation == null)
// $continuation = new Action (MoveNext);
//
fexpr.Emit (ec);
var skip_cont_init = ec.DefineLabel ();
ec.Emit (OpCodes.Brtrue_S, skip_cont_init);
ec.EmitThis ();
EmitActionLoad (ec);
ec.Emit (OpCodes.Stfld, continuation.Spec);
ec.MarkLabel (skip_cont_init);
return fexpr;
}
//
// Otherwise simply use temporary local variable
//
var field = LocalVariable.CreateCompilerGenerated (action, OriginalSourceBlock, Location);
EmitActionLoad (ec);
field.EmitAssign (ec);
return new LocalVariableReference (field, Location);
}
void EmitActionLoad (EmitContext ec)
{
ec.EmitThis ();
ec.Emit (OpCodes.Ldftn, StateMachineMethod.Spec);
ec.Emit (OpCodes.Newobj, (MethodSpec) MemberCache.FindMember (action, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly));
}
public void EmitSetException (EmitContext ec, LocalVariableReference exceptionVariable)
{
//
@ -769,4 +774,30 @@ namespace Mono.CSharp @@ -769,4 +774,30 @@ namespace Mono.CSharp
mg.EmitCall (ec, args);
}
}
class StackField : Field
{
public StackField (DeclSpace parent, FullNamedExpression type, Modifiers mod, MemberName name)
: base (parent, type, mod, name, null)
{
}
public bool CanBeReused { get; set; }
}
class StackFieldExpr : FieldExpr
{
public StackFieldExpr (Field field)
: base (field, Location.Null)
{
}
public override void Emit (EmitContext ec)
{
base.Emit (ec);
var field = (StackField) spec.MemberDefinition;
field.CanBeReused = true;
}
}
}

3
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/attribute.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
//
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2008 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
using System;
@ -963,7 +964,7 @@ namespace Mono.CSharp { @@ -963,7 +964,7 @@ namespace Mono.CSharp {
if (j == 0) {
if ((Type == predefined.IndexerName || Type == predefined.Conditional) && arg_expr is Constant) {
string v = ((Constant) arg_expr).GetValue () as string;
if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
if (!Tokenizer.IsValidIdentifier (v) || (Type == predefined.IndexerName && Tokenizer.IsKeyword (v))) {
context.Module.Compiler.Report.Error (633, arg_expr.Location,
"The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
return;

2
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cfold.cs

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
// Marek Safar (marek.safar@seznam.cz)
//
// Copyright 2002, 2003 Ximian, Inc.
// Copyright 2003-2008, Novell, Inc.
// Copyright 2003-2011, Novell, Inc.
//
using System;

77
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/class.cs

@ -3,12 +3,13 @@ @@ -3,12 +3,13 @@
//
// Authors: Miguel de Icaza (miguel@gnu.org)
// Martin Baulig (martin@ximian.com)
// Marek Safar (marek.safar@seznam.cz)
// Marek Safar (marek.safar@gmail.com)
//
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2008 Novell, Inc
// Copyright 2004-2011 Novell, Inc
// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
//
using System;
@ -1241,7 +1242,7 @@ namespace Mono.CSharp @@ -1241,7 +1242,7 @@ namespace Mono.CSharp
if (iface_type == null)
continue;
if (!spec.AddInterface (iface_type))
if (!spec.AddInterfaceDefined (iface_type))
continue;
TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
@ -1257,7 +1258,7 @@ namespace Mono.CSharp @@ -1257,7 +1258,7 @@ namespace Mono.CSharp
var base_ifaces = new List<TypeSpec> (iface_type.Interfaces);
for (int i = 0; i < base_ifaces.Count; ++i) {
var ii_iface_type = base_ifaces[i];
if (spec.AddInterface (ii_iface_type)) {
if (spec.AddInterfaceDefined (ii_iface_type)) {
TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ());
if (ii_iface_type.Interfaces != null)
@ -1575,7 +1576,9 @@ namespace Mono.CSharp @@ -1575,7 +1576,9 @@ namespace Mono.CSharp
GetSignatureForError (), iface_type.GetSignatureForError ());
return false;
}
}
if (iface_type.IsGenericOrParentIsGeneric) {
if (spec.Interfaces != null) {
foreach (var prev_iface in iface_exprs) {
if (prev_iface == iface_type)
@ -2593,12 +2596,6 @@ namespace Mono.CSharp @@ -2593,12 +2596,6 @@ namespace Mono.CSharp
continue;
}
Method method = m as Method;
if (method != null && method.ParameterInfo.HasExtensionMethodType) {
Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ());
continue;
}
Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
}
@ -2848,44 +2845,41 @@ namespace Mono.CSharp @@ -2848,44 +2845,41 @@ namespace Mono.CSharp
public override bool IsUnmanagedType ()
{
if (fields == null)
return true;
if (has_unmanaged_check_done)
return is_unmanaged;
if (requires_delayed_unmanagedtype_check)
return true;
requires_delayed_unmanagedtype_check = true;
if (Parent != null && Parent.IsGeneric) {
has_unmanaged_check_done = true;
return false;
}
foreach (FieldBase f in fields) {
if (f.IsStatic)
continue;
if (fields != null) {
requires_delayed_unmanagedtype_check = true;
// It can happen when recursive unmanaged types are defined
// struct S { S* s; }
TypeSpec mt = f.MemberType;
if (mt == null) {
return true;
}
foreach (FieldBase f in fields) {
if (f.IsStatic)
continue;
// It can happen when recursive unmanaged types are defined
// struct S { S* s; }
TypeSpec mt = f.MemberType;
if (mt == null) {
return true;
}
while (mt.IsPointer)
mt = TypeManager.GetElementType (mt);
if (mt.IsUnmanaged)
continue;
if (mt.IsGenericOrParentIsGeneric || mt.IsGenericParameter) {
has_unmanaged_check_done = true;
return false;
}
if (TypeManager.IsUnmanagedType (mt))
continue;
has_unmanaged_check_done = true;
return false;
}
has_unmanaged_check_done = true;
is_unmanaged = true;
return true;
}
@ -3149,13 +3143,13 @@ namespace Mono.CSharp @@ -3149,13 +3143,13 @@ namespace Mono.CSharp
if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
Report.SymbolRelatedToPreviousError (base_member);
Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
GetSignatureForError (), TypeManager.GetFullNameSignature (base_member));
GetSignatureForError (), base_member.GetSignatureForError ());
}
} else {
if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
Report.SymbolRelatedToPreviousError (base_member);
Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
GetSignatureForError (), TypeManager.GetFullNameSignature (base_member));
GetSignatureForError (), base_member.GetSignatureForError ());
}
}
@ -3598,13 +3592,22 @@ namespace Mono.CSharp @@ -3598,13 +3592,22 @@ namespace Mono.CSharp
}
}
protected bool IsTypePermitted ()
protected void IsTypePermitted ()
{
if (MemberType.IsSpecialRuntimeType) {
Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
return false;
if (Parent is StateMachine) {
Report.Error (4012, Location,
"Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
MemberType.GetSignatureForError ());
} else if (Parent is HoistedStoreyClass) {
Report.Error (4013, Location,
"Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
MemberType.GetSignatureForError ());
} else {
Report.Error (610, Location,
"Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
}
}
return true;
}
protected virtual bool CheckBase ()

6
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/codegen.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
//
// Copyright 2001, 2002, 2003 Ximian, Inc.
// Copyright 2004 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
using System;
@ -280,7 +281,7 @@ namespace Mono.CSharp @@ -280,7 +281,7 @@ namespace Mono.CSharp
public FieldExpr GetTemporaryField (TypeSpec type)
{
var f = AsyncTaskStorey.AddCapturedLocalVariable (type);
var fexpr = new FieldExpr (f, Location.Null);
var fexpr = new StackFieldExpr (f);
fexpr.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location.Null);
return fexpr;
}
@ -958,7 +959,7 @@ namespace Mono.CSharp @@ -958,7 +959,7 @@ namespace Mono.CSharp
//
// Push the instance expression
//
if ((instance_type.IsStruct && (callOpcode == OpCodes.Callvirt || (callOpcode == OpCodes.Call && declaringType == instance_type))) ||
if ((instance_type.IsStruct && (callOpcode == OpCodes.Callvirt || (callOpcode == OpCodes.Call && declaringType.IsStruct))) ||
instance_type.IsGenericParameter || declaringType.IsNullableType) {
//
// If the expression implements IMemoryLocation, then
@ -975,7 +976,6 @@ namespace Mono.CSharp @@ -975,7 +976,6 @@ namespace Mono.CSharp
instance.Emit (ec);
temp.Store (ec);
temp.AddressOf (ec, AddressOp.Load);
temp.Release (ec);
}
return ReferenceContainer.MakeType (ec.Module, instance_type);

3
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/complete.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
//
// Copyright 2001, 2002, 2003 Ximian, Inc.
// Copyright 2003-2009 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
// Completion* classes derive from ExpressionStatement as this allows
// them to pass through the parser in many conditions that require
@ -120,7 +121,7 @@ namespace Mono.CSharp { @@ -120,7 +121,7 @@ namespace Mono.CSharp {
TypeSpec expr_type = expr_resolved.Type;
if (expr_type.IsPointer || expr_type.Kind == MemberKind.Void || expr_type == InternalType.NullLiteral || expr_type == InternalType.AnonymousMethod) {
Unary.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type);
expr_resolved.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type);
return null;
}

3
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/constant.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
//
// Copyright 2001-2003 Ximian, Inc.
// Copyright 2003-2008 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
using System;
@ -274,7 +275,7 @@ namespace Mono.CSharp { @@ -274,7 +275,7 @@ namespace Mono.CSharp {
return this;
Constant c;
if (TypeManager.IsEnumType (target_type)) {
if (target_type.IsEnum) {
c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type));
if (c == null)
return null;

17
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/context.cs

@ -469,10 +469,19 @@ namespace Mono.CSharp @@ -469,10 +469,19 @@ namespace Mono.CSharp
if (CurrentAnonymousMethod == null)
return false;
// FIXME: IsIterator is too aggressive, we should capture only if child
// block contains yield
if (CurrentAnonymousMethod.IsIterator || CurrentAnonymousMethod is AsyncInitializer)
return true;
//
// Capture only if this or any of child blocks contain yield
// or it's a parameter
//
if (CurrentAnonymousMethod.IsIterator)
return local.IsParameter || CurrentBlock.Explicit.HasYield;
//
// Capture only if this or any of child blocks contain await
// or it's a parameter
//
if (CurrentAnonymousMethod is AsyncInitializer)
return CurrentBlock.Explicit.HasAwait;
return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original;
}

18
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/convert.cs

@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
//
// Copyright 2001, 2002, 2003 Ximian, Inc.
// Copyright 2003-2008 Novell, Inc.
// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
// Copyright 2011 Xamarin Inc (http://www.xamarin.com)
//
using System;
@ -818,7 +818,7 @@ namespace Mono.CSharp { @@ -818,7 +818,7 @@ namespace Mono.CSharp {
/// Finds "most encompassed type" according to the spec (13.4.2)
/// amongst the methods in the MethodGroupExpr
/// </summary>
public static TypeSpec FindMostEncompassedType (IEnumerable<TypeSpec> types)
public static TypeSpec FindMostEncompassedType (IList<TypeSpec> types)
{
TypeSpec best = null;
EmptyExpression expr;
@ -1259,7 +1259,7 @@ namespace Mono.CSharp { @@ -1259,7 +1259,7 @@ namespace Mono.CSharp {
static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast)
{
if (expr.eclass == ExprClass.MethodGroup){
if (!TypeManager.IsDelegateType (target_type)){
if (!target_type.IsDelegate){
return null;
}
@ -1334,7 +1334,7 @@ namespace Mono.CSharp { @@ -1334,7 +1334,7 @@ namespace Mono.CSharp {
if (e != null)
return e;
if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)){
if (expr is IntegralConstant && target_type.IsEnum){
var i = (IntegralConstant) expr;
//
// LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
@ -1871,7 +1871,7 @@ namespace Mono.CSharp { @@ -1871,7 +1871,7 @@ namespace Mono.CSharp {
//
// From System delegate to any delegate-type
//
if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && TypeManager.IsDelegateType (target_type))
if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && target_type.IsDelegate)
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
//
@ -1931,8 +1931,8 @@ namespace Mono.CSharp { @@ -1931,8 +1931,8 @@ namespace Mono.CSharp {
if (ne != null)
return ne;
if (TypeManager.IsEnumType (expr_type)) {
TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type;
if (expr_type.IsEnum) {
TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type;
Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type));
if (underlying.Type == real_target)
ne = underlying;
@ -1952,14 +1952,14 @@ namespace Mono.CSharp { @@ -1952,14 +1952,14 @@ namespace Mono.CSharp {
return ne != null ? EmptyCast.Create (ne, target_type) : null;
}
if (TypeManager.IsEnumType (target_type)) {
if (target_type.IsEnum) {
//
// System.Enum can be unboxed to any enum-type
//
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Enum)
return new UnboxCast (expr, target_type);
TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type;
TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type;
if (expr_type == real_target)
return EmptyCast.Create (expr, target_type);

8760
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs

File diff suppressed because it is too large Load Diff

327
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.jay

@ -75,6 +75,8 @@ namespace Mono.CSharp @@ -75,6 +75,8 @@ namespace Mono.CSharp
ParametersCompiled current_local_parameters;
bool parsing_anonymous_method;
bool async_block;
///
/// An out-of-band stack.
@ -149,20 +151,6 @@ namespace Mono.CSharp @@ -149,20 +151,6 @@ namespace Mono.CSharp
List<Location> attributeCommas = new List<Location> ();
List<Location> attributeArgumentCommas = new List<Location> ();
List<Location> parameterListCommas = new List<Location> ();
List<Location> enumCommas = new List<Location> ();
object lastYYVal;
// Can be used for code completion to get the last valid expression before an error.
// needs a hack in yyparse to make it work add
// lastYYVal = yyVal;
// after the big switch/case (somewhere around line 3915)
public object LastYYVal {
get {
return lastYYVal;
}
}
%}
%token EOF
@ -885,7 +873,7 @@ named_attribute_argument @@ -885,7 +873,7 @@ named_attribute_argument
;
named_argument
: IDENTIFIER COLON opt_named_modifier expression
: identifier_inside_body COLON opt_named_modifier expression
{
if (lang_version <= LanguageVersion.V_3)
FeatureIsNotAvailable (GetLocation ($1), "named argument");
@ -1254,14 +1242,14 @@ method_declaration @@ -1254,14 +1242,14 @@ method_declaration
// Add it early in the case of body being eof for full ast
Method m = (Method) $1;
lexer.async_block = (m.ModFlags & Modifiers.ASYNC) != 0;
async_block = (m.ModFlags & Modifiers.ASYNC) != 0;
current_container.AddMethod (m);
}
method_body
{
Method method = (Method) $1;
method.Block = (ToplevelBlock) $3;
lexer.async_block = false;
async_block = false;
if (method.Block == null) {
lbag.AppendToMember (method, savedLocation); // semicolon
@ -1315,15 +1303,9 @@ method_header @@ -1315,15 +1303,9 @@ method_header
"Constraints are not allowed on non-generic declarations");
}
Method method = new Method (current_class, generic, (FullNamedExpression) $3, (Modifiers) $2,
name, current_local_parameters, (Attributes) $1);
var method = Method.Create (current_class, generic, (FullNamedExpression) $3, (Modifiers) $2,
name, current_local_parameters, (Attributes) $1, $10 != null);
if ($10 != null && ((method.ModFlags & Modifiers.OVERRIDE) != 0 || method.IsExplicitImpl)) {
report.Error (460, method.Location,
"`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
method.GetSignatureForError ());
}
if (doc_support)
method.DocComment = Lexer.consume_doc_comment ();
@ -1359,7 +1341,6 @@ method_header @@ -1359,7 +1341,6 @@ method_header
report.Error (80, lexer.Location,
"Constraints are not allowed on non-generic declarations");
Method method;
GenericMethod generic = null;
if (name.TypeArguments != null) {
generic = new GenericMethod (current_namespace, current_class, name,
@ -1370,25 +1351,10 @@ method_header @@ -1370,25 +1351,10 @@ method_header
}
var modifiers = (Modifiers) $2;
modifiers |= Modifiers.PARTIAL;
const Modifiers invalid_partial_mod = Modifiers.AccessibilityMask | Modifiers.ABSTRACT | Modifiers.EXTERN |
Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.SEALED | Modifiers.VIRTUAL;
if ((modifiers & invalid_partial_mod) != 0) {
report.Error (750, name.Location, "A partial method cannot define access modifier or " +
"any of abstract, extern, new, override, sealed, or virtual modifiers");
modifiers &= ~invalid_partial_mod;
}
if ((current_class.ModFlags & Modifiers.PARTIAL) == 0) {
report.Error (751, name.Location, "A partial method must be declared within a " +
"partial class or partial struct");
}
modifiers |= Modifiers.PARTIAL | Modifiers.PRIVATE;
method = new Method (current_class, generic, new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($4)),
modifiers, name, current_local_parameters, (Attributes) $1);
var method = Method.Create (current_class, generic, new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($4)),
modifiers, name, current_local_parameters, (Attributes) $1, $11 != null);
if (doc_support)
method.DocComment = Lexer.consume_doc_comment ();
@ -1406,8 +1372,8 @@ method_header @@ -1406,8 +1372,8 @@ method_header
report.Error (1585, name.Location,
"Member modifier `{0}' must precede the member type and name", ModifiersExtensions.Name ((Modifiers) $4));
Method method = new Method (current_class, null, (FullNamedExpression) $3,
0, name, (ParametersCompiled) $7, (Attributes) $1);
var method = Method.Create (current_class, null, (FullNamedExpression) $3,
0, name, (ParametersCompiled) $7, (Attributes) $1, false);
current_local_parameters = (ParametersCompiled) $7;
@ -2564,9 +2530,6 @@ enum_declaration @@ -2564,9 +2530,6 @@ enum_declaration
: opt_attributes
opt_modifiers
ENUM
{
enumCommas.Add (GetLocation ($3));
}
type_declaration_name
opt_enum_base
{
@ -2577,14 +2540,18 @@ enum_declaration @@ -2577,14 +2540,18 @@ enum_declaration
{
if (doc_support)
Lexer.doc_state = XmlCommentState.Allowed;
enumCommas.Add (GetLocation ($8));
MemberName name = (MemberName) $5;
MemberName name = (MemberName) $4;
if (name.IsGeneric) {
report.Error (1675, name.Location, "Enums cannot have type parameters");
}
push_current_class (new Enum (current_namespace, current_class, (TypeExpression) $6, (Modifiers) $2, MakeName (name), (Attributes) $1), null);
push_current_class (new Enum (current_namespace, current_class, (TypeExpression) $5, (Modifiers) $2, MakeName (name), (Attributes) $1), null);
if ($5 != null) {
lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($3), savedLocation, GetLocation ($7));
} else {
lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($3), GetLocation ($7));
}
}
opt_enum_member_declarations
{
@ -2594,16 +2561,16 @@ enum_declaration @@ -2594,16 +2561,16 @@ enum_declaration
}
CLOSE_BRACE opt_semicolon
{
enumCommas.Add (GetLocation ($12));
if ($13 != null)
current_class.OptionalSemicolon = GetLocation ($13);
lbag.AppendToMember (current_class, GetLocation ($11));
if ($12 != null) {
current_class.OptionalSemicolon = GetLocation ($12);
lbag.AppendToMember (current_class, GetLocation ($12));
}
if (doc_support)
current_class.DocComment = enumTypeComment;
--lexer.parsing_declaration;
lbag.AddMember (current_class, GetModifierLocations (), enumCommas);
enumCommas.Clear ();
$$ = pop_current_class ();
}
;
@ -2617,7 +2584,7 @@ opt_enum_base @@ -2617,7 +2584,7 @@ opt_enum_base
Enum.Error_1008 (GetLocation ($2), report);
$$ = null;
} else {
enumCommas.Add (GetLocation ($1));
savedLocation = GetLocation ($1);
$$ = $2;
}
}
@ -2633,7 +2600,7 @@ opt_enum_member_declarations @@ -2633,7 +2600,7 @@ opt_enum_member_declarations
| enum_member_declarations
| enum_member_declarations COMMA
{
enumCommas.Add (GetLocation ($2));
lbag.AppendToMember (current_class, GetLocation ($2));
}
;
@ -2641,7 +2608,7 @@ enum_member_declarations @@ -2641,7 +2608,7 @@ enum_member_declarations
: enum_member_declaration
| enum_member_declarations COMMA enum_member_declaration
{
enumCommas.Add (GetLocation ($2));
lbag.AppendToMember (current_class, GetLocation ($2));
$$ = $3;
}
;
@ -3401,6 +3368,14 @@ element_access @@ -3401,6 +3368,14 @@ element_access
$$ = new ElementAccess ((Expression) $1, (Arguments) $3, GetLocation ($2));
lbag.AddLocation ($$, GetLocation ($4));
}
| primary_expression OPEN_BRACKET_EXPR expression_list_arguments error
{
$$ = new ElementAccess ((Expression) $1, (Arguments) $3, GetLocation ($2));
}
| primary_expression OPEN_BRACKET_EXPR error
{
$$ = new ElementAccess ((Expression) $1, null, GetLocation ($2));
}
;
expression_list
@ -3731,13 +3706,13 @@ typeof_type_expression @@ -3731,13 +3706,13 @@ typeof_type_expression
;
unbound_type_name
: IDENTIFIER generic_dimension
: identifier_inside_body generic_dimension
{
var lt = (Tokenizer.LocatedToken) $1;
$$ = new SimpleName (lt.Value, (int) $2, lt.Location);
}
| qualified_alias_member IDENTIFIER generic_dimension
| qualified_alias_member identifier_inside_body generic_dimension
{
var lt1 = (Tokenizer.LocatedToken) $1;
var lt2 = (Tokenizer.LocatedToken) $2;
@ -3745,7 +3720,7 @@ unbound_type_name @@ -3745,7 +3720,7 @@ unbound_type_name
$$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (int) $3, lt1.Location);
lbag.AddLocation ($$, GetLocation ($2));
}
| unbound_type_name DOT IDENTIFIER
| unbound_type_name DOT identifier_inside_body
{
var lt = (Tokenizer.LocatedToken) $3;
@ -3753,7 +3728,7 @@ unbound_type_name @@ -3753,7 +3728,7 @@ unbound_type_name
DotLocation = GetLocation ($2)
};
}
| unbound_type_name DOT IDENTIFIER generic_dimension
| unbound_type_name DOT identifier_inside_body generic_dimension
{
var lt = (Tokenizer.LocatedToken) $3;
@ -3761,7 +3736,7 @@ unbound_type_name @@ -3761,7 +3736,7 @@ unbound_type_name
DotLocation = GetLocation ($2)
};
}
| namespace_or_type_name DOT IDENTIFIER generic_dimension
| namespace_or_type_name DOT identifier_inside_body generic_dimension
{
var te = ((MemberName) $1).GetTypeExpression ();
if (te.HasTypeArguments)
@ -3848,6 +3823,12 @@ anonymous_method_expression @@ -3848,6 +3823,12 @@ anonymous_method_expression
block
{
$$ = end_anonymous ((ParametersBlock) $5);
if ((ParametersCompiled) $3 != ParametersCompiled.Undefined) {
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), savedOpenLocation, savedCloseLocation);
} else {
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2));
}
}
;
@ -3894,22 +3875,20 @@ unary_expression @@ -3894,22 +3875,20 @@ unary_expression
{
$$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, GetLocation ($1));
}
| cast_expression
| await_expression
;
cast_expression
: OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression
| OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression
{
$$ = new Cast ((FullNamedExpression) $2, (Expression) $4, GetLocation ($1));
lbag.AddLocation ($$, GetLocation ($3));
}
;
await_expression
: AWAIT unary_expression
| AWAIT prefixed_unary_expression
{
current_block.ParametersBlock.IsAsync = true;
if (!async_block) {
report.Error (1992, GetLocation ($1),
"The `await' operator can only be used when its containing method or lambda expression is marked with the `async' modifier");
} else {
current_block.Explicit.RegisterAsyncAwait ();
}
$$ = new Await ((Expression) $2, GetLocation ($1));
}
;
@ -4189,13 +4168,13 @@ lambda_parameter_list @@ -4189,13 +4168,13 @@ lambda_parameter_list
;
lambda_parameter
: parameter_modifier parameter_type IDENTIFIER
: parameter_modifier parameter_type identifier_inside_body
{
var lt = (Tokenizer.LocatedToken) $3;
$$ = new Parameter ((FullNamedExpression) $2, lt.Value, (Parameter.Modifier) $1, null, lt.Location);
}
| parameter_type IDENTIFIER
| parameter_type identifier_inside_body
{
var lt = (Tokenizer.LocatedToken) $2;
@ -4256,7 +4235,7 @@ lambda_expression @@ -4256,7 +4235,7 @@ lambda_expression
$$ = end_anonymous ((ParametersBlock) $4);
lbag.AddLocation ($$, GetLocation ($2));
}
| ASYNC IDENTIFIER ARROW
| ASYNC identifier_inside_body ARROW
{
var lt = (Tokenizer.LocatedToken) $2;
Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location);
@ -4279,7 +4258,7 @@ lambda_expression @@ -4279,7 +4258,7 @@ lambda_expression
lambda_expression_body
{
$$ = end_anonymous ((ParametersBlock) $7);
lbag.AddLocation ($$, GetLocation ($4), GetLocation ($5));
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($4), GetLocation ($5));
}
| ASYNC OPEN_PARENS_LAMBDA
{
@ -4293,7 +4272,7 @@ lambda_expression @@ -4293,7 +4272,7 @@ lambda_expression
lambda_expression_body
{
$$ = end_anonymous ((ParametersBlock) $8);
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($5), GetLocation ($6));
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($5), GetLocation ($6));
}
;
@ -4726,6 +4705,16 @@ statement @@ -4726,6 +4705,16 @@ statement
current_block.AddStatement ((Statement) $1);
}
| labeled_statement
// WORKAROUND:Remove that rule, if it is >really< fixed.
| IDENTIFIER error
{
Error_SyntaxError (yyToken);
var lt =(Tokenizer.LocatedToken) $1;
var sn = new SimpleName (lt.Value, lt.Location);
current_block.AddStatement(new StatementErrorExpression (sn));
$$ = null;
}
////////
| error
{
Error_SyntaxError (yyToken);
@ -4816,7 +4805,7 @@ empty_statement @@ -4816,7 +4805,7 @@ empty_statement
;
labeled_statement
: IDENTIFIER COLON
: identifier_inside_body COLON
{
var lt = (Tokenizer.LocatedToken) $1;
LabeledStatement labeled = new LabeledStatement (lt.Value, current_block, lt.Location);
@ -4924,8 +4913,19 @@ pointer_star @@ -4924,8 +4913,19 @@ pointer_star
}
;
identifier_inside_body
: IDENTIFIER
| AWAIT
{
if (async_block) {
report.Error (4003, GetLocation ($1), "`await' cannot be used as an identifier within an async method or lambda expression");
$$ = Tokenizer.LocatedToken.Create ("await", GetLocation ($1));
}
}
;
block_variable_declaration
: variable_type IDENTIFIER
: variable_type identifier_inside_body
{
var lt = (Tokenizer.LocatedToken) $2;
var li = new LocalVariable (current_block, lt.Value, lt.Location);
@ -4938,7 +4938,7 @@ block_variable_declaration @@ -4938,7 +4938,7 @@ block_variable_declaration
current_variable = null;
lbag.AppendTo ($$, GetLocation ($6));
}
| CONST variable_type IDENTIFIER
| CONST variable_type identifier_inside_body
{
var lt = (Tokenizer.LocatedToken) $3;
var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location);
@ -4964,6 +4964,20 @@ opt_local_variable_initializer @@ -4964,6 +4964,20 @@ opt_local_variable_initializer
current_variable.Initializer = (Expression) $2;
lbag.AppendTo (current_variable, GetLocation ($1));
}
| ASSIGN error
{
if (yyToken == Token.OPEN_BRACKET_EXPR) {
report.Error (650, lexer.Location,
"Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type");
current_variable.Initializer = ErrorExpression.Create (650, lexer.Location,
"Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type");
} else {
Error_SyntaxError (yyToken);
current_variable.Initializer = ErrorExpression.Create (0, lexer.Location,
"Syntax error");
}
lbag.AppendTo (current_variable, GetLocation ($1));
}
| error
{
if (yyToken == Token.OPEN_BRACKET_EXPR) {
@ -4997,7 +5011,7 @@ variable_declarators @@ -4997,7 +5011,7 @@ variable_declarators
;
variable_declarator
: COMMA IDENTIFIER
: COMMA identifier_inside_body
{
var lt = (Tokenizer.LocatedToken) $2;
var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location);
@ -5006,7 +5020,7 @@ variable_declarator @@ -5006,7 +5020,7 @@ variable_declarator
current_block.AddLocalName (li);
lbag.AddLocation (d, GetLocation ($1));
}
| COMMA IDENTIFIER ASSIGN block_variable_initializer
| COMMA identifier_inside_body ASSIGN block_variable_initializer
{
var lt = (Tokenizer.LocatedToken) $2;
var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location);
@ -5040,7 +5054,7 @@ const_declarators @@ -5040,7 +5054,7 @@ const_declarators
;
const_declarator
: COMMA IDENTIFIER ASSIGN constant_initializer_expr
: COMMA identifier_inside_body ASSIGN constant_initializer_expr
{
var lt = (Tokenizer.LocatedToken) $2;
var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location);
@ -5089,7 +5103,7 @@ statement_expression @@ -5089,7 +5103,7 @@ statement_expression
ExpressionStatement s = $1 as ExpressionStatement;
if (s == null) {
Expression.Error_InvalidExpressionStatement (report, GetLocation ($1));
$$ = new StatementExpression (EmptyExpressionStatement.Instance);
$$ = new InvalidStatementExpression ($1 as Expression);
} else {
$$ = new StatementExpression (s);
}
@ -5138,6 +5152,12 @@ if_statement @@ -5138,6 +5152,12 @@ if_statement
if ($7 is EmptyStatement)
Warning_EmptyStatement (GetLocation ($7));
}
| IF open_parens_any boolean_expression error {
var eloc = GetLocation ($3);
report.Error (1026, eloc, "Expected a ')'");
$$ = new If ((BooleanExpression) $3, null, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($2));
}
;
switch_statement
@ -5249,6 +5269,18 @@ do_statement @@ -5249,6 +5269,18 @@ do_statement
$$ = new Do ((Statement) $2, (BooleanExpression) $5, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($3), GetLocation ($4), GetLocation ($6), GetLocation ($7));
}
| DO embedded_statement error
{
var loc = GetLocation ($1);
report.Error (-100, loc, "Expected `while'");
$$ = new Do ((Statement) $2, null, loc);
}
| DO embedded_statement
WHILE open_parens_any boolean_expression error
{
$$ = new Do ((Statement) $2, (BooleanExpression) $5, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($3), GetLocation ($4));
}
;
for_statement
@ -5256,6 +5288,9 @@ for_statement @@ -5256,6 +5288,9 @@ for_statement
{
start_block (GetLocation ($2));
current_block.IsCompilerGenerated = true;
For f = new For (GetLocation ($1));
current_block.AddStatement (f);
$$ = f;
}
for_statement_cont
{
@ -5266,17 +5301,25 @@ for_statement @@ -5266,17 +5301,25 @@ for_statement
// Has to use be extra rule to recover started block
for_statement_cont
: opt_for_initializer SEMICOLON
{
((For) $0).Initializer = (Statement) $1;
}
opt_for_condition SEMICOLON
{
((For) $0).Condition = (BooleanExpression) $4;
}
opt_for_iterator CLOSE_PARENS
{
((For) $0).Iterator = (Statement) $7;
}
embedded_statement
{
if ($7 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE)
Warning_EmptyStatement (GetLocation ($7));
if ($10 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE)
Warning_EmptyStatement (GetLocation ($10));
For f = new For ((Statement) $1, (BooleanExpression) $3, (Statement) $5, (Statement) $7, GetLocation ($-2));
current_block.AddStatement (f);
lbag.AddStatement (f, current_block.StartLocation, GetLocation ($2), GetLocation ($4), GetLocation ($6));
For f = ((For) $0);
f.Statement = (Statement) $10;
lbag.AddStatement (f, current_block.StartLocation, GetLocation ($2), GetLocation ($5), GetLocation ($8));
$$ = end_block (GetLocation ($2));
}
@ -5293,7 +5336,7 @@ opt_for_initializer @@ -5293,7 +5336,7 @@ opt_for_initializer
;
for_initializer
: variable_type IDENTIFIER
: variable_type identifier_inside_body
{
var lt = (Tokenizer.LocatedToken) $2;
var li = new LocalVariable (current_block, lt.Value, lt.Location);
@ -5345,7 +5388,7 @@ foreach_statement @@ -5345,7 +5388,7 @@ foreach_statement
report.Error (230, GetLocation ($1), "Type and identifier are both required in a foreach statement");
$$ = null;
}
| FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS
| FOREACH open_parens_any type identifier_inside_body IN expression CLOSE_PARENS
{
start_block (GetLocation ($2));
current_block.IsCompilerGenerated = true;
@ -5365,6 +5408,27 @@ foreach_statement @@ -5365,6 +5408,27 @@ foreach_statement
lbag.AddStatement (f, GetLocation ($2), GetLocation ($5), GetLocation ($7));
$$ = end_block (GetLocation ($7));
}
| FOREACH open_parens_any type identifier_inside_body error
{
start_block (GetLocation ($2));
current_block.IsCompilerGenerated = true;
var lt = $4 as Tokenizer.LocatedToken;
var li = lt != null ? new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location) : null;
Foreach f = new Foreach ((Expression) $3, li, null, null, GetLocation ($1));
current_block.AddStatement (f);
lbag.AddStatement (f, GetLocation ($2));
$$ = end_block (GetLocation ($5));
}
| FOREACH open_parens_any type error
{
Foreach f = new Foreach ((Expression) $3, null, null, null, GetLocation ($1));
current_block.AddStatement (f);
lbag.AddStatement (f, GetLocation ($2));
$$ = f;
}
;
jump_statement
@ -5393,7 +5457,7 @@ continue_statement @@ -5393,7 +5457,7 @@ continue_statement
;
goto_statement
: GOTO IDENTIFIER SEMICOLON
: GOTO identifier_inside_body SEMICOLON
{
var lt = (Tokenizer.LocatedToken) $2;
$$ = new Goto (lt.Value, GetLocation ($1));
@ -5428,7 +5492,7 @@ throw_statement @@ -5428,7 +5492,7 @@ throw_statement
;
yield_statement
: IDENTIFIER RETURN opt_expression SEMICOLON
: identifier_inside_body RETURN opt_expression SEMICOLON
{
var lt = (Tokenizer.LocatedToken) $1;
string s = lt.Value;
@ -5440,11 +5504,11 @@ yield_statement @@ -5440,11 +5504,11 @@ yield_statement
FeatureIsNotAvailable (lt.Location, "iterators");
}
current_block.ParametersBlock.TopBlock.IsIterator = true;
current_block.Explicit.RegisterIteratorYield ();
$$ = new Yield ((Expression) $3, lt.Location);
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4));
}
| IDENTIFIER BREAK SEMICOLON
| identifier_inside_body BREAK SEMICOLON
{
var lt = (Tokenizer.LocatedToken) $1;
string s = lt.Value;
@ -5454,7 +5518,7 @@ yield_statement @@ -5454,7 +5518,7 @@ yield_statement
FeatureIsNotAvailable (lt.Location, "iterators");
}
current_block.ParametersBlock.TopBlock.IsIterator = true;
current_block.Explicit.RegisterIteratorYield ();
$$ = new YieldBreak (lt.Location);
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3));
}
@ -5483,7 +5547,7 @@ try_statement @@ -5483,7 +5547,7 @@ try_statement
| TRY block error
{
report.Error (1524, GetLocation ($1), "Expected catch or finally");
$$ = null;
$$ = new TryCatch ((Block) $2, null, GetLocation ($1), false);
}
;
@ -5515,7 +5579,7 @@ catch_clauses @@ -5515,7 +5579,7 @@ catch_clauses
opt_identifier
: /* empty */
| IDENTIFIER
| identifier_inside_body
;
catch_clause
@ -5591,7 +5655,7 @@ lock_statement @@ -5591,7 +5655,7 @@ lock_statement
;
fixed_statement
: FIXED open_parens_any variable_type IDENTIFIER
: FIXED open_parens_any variable_type identifier_inside_body
{
start_block (GetLocation ($2));
@ -5619,7 +5683,7 @@ fixed_statement @@ -5619,7 +5683,7 @@ fixed_statement
;
using_statement
: USING open_parens_any variable_type IDENTIFIER
: USING open_parens_any variable_type identifier_inside_body
{
start_block (GetLocation ($2));
@ -5629,20 +5693,20 @@ using_statement @@ -5629,20 +5693,20 @@ using_statement
current_block.AddLocalName (li);
current_variable = new Using.VariableDeclaration ((FullNamedExpression) $3, li);
}
using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators CLOSE_PARENS
using_initialization CLOSE_PARENS
{
$$ = current_variable;
current_variable = null;
}
embedded_statement
{
if ($10 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE)
Warning_EmptyStatement (GetLocation ($10));
if ($9 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE)
Warning_EmptyStatement (GetLocation ($9));
Using u = new Using ((Using.VariableDeclaration) $9, (Statement) $10, GetLocation ($1));
lbag.AddStatement (u, GetLocation ($2), GetLocation ($8));
Using u = new Using ((Using.VariableDeclaration) $8, (Statement) $9, GetLocation ($1));
lbag.AddStatement (u, GetLocation ($2), GetLocation ($7));
current_block.AddStatement (u);
$$ = end_block (GetLocation ($8));
$$ = end_block (GetLocation ($7));
}
| USING open_parens_any expression CLOSE_PARENS embedded_statement
{
@ -5655,6 +5719,15 @@ using_statement @@ -5655,6 +5719,15 @@ using_statement
}
;
using_initialization
: using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators
| error
{
// It has to be here for the parent to safely restore artificial block
Error_SyntaxError (yyToken);
}
;
using_or_fixed_variable_initializer
: /* empty */
{
@ -5711,7 +5784,7 @@ query_expression @@ -5711,7 +5784,7 @@ query_expression
;
first_from_clause
: FROM_FIRST IDENTIFIER IN expression
: FROM_FIRST identifier_inside_body IN expression
{
current_block = new Linq.QueryBlock (current_block, lexer.Location);
@ -5719,7 +5792,7 @@ first_from_clause @@ -5719,7 +5792,7 @@ first_from_clause
var rv = new Linq.RangeVariable (lt.Value, lt.Location);
$$ = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, rv, GetLocation ($1)));
}
| FROM_FIRST type IDENTIFIER IN expression
| FROM_FIRST type identifier_inside_body IN expression
{
current_block = new Linq.QueryBlock (current_block, lexer.Location);
@ -5734,7 +5807,7 @@ first_from_clause @@ -5734,7 +5807,7 @@ first_from_clause
;
nested_from_clause
: FROM IDENTIFIER IN expression
: FROM identifier_inside_body IN expression
{
current_block = new Linq.QueryBlock (current_block, lexer.Location);
@ -5742,7 +5815,7 @@ nested_from_clause @@ -5742,7 +5815,7 @@ nested_from_clause
var rv = new Linq.RangeVariable (lt.Value, lt.Location);
$$ = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, rv, GetLocation ($1)));
}
| FROM type IDENTIFIER IN expression
| FROM type identifier_inside_body IN expression
{
current_block = new Linq.QueryBlock (current_block, lexer.Location);
@ -5757,7 +5830,7 @@ nested_from_clause @@ -5757,7 +5830,7 @@ nested_from_clause
;
from_clause
: FROM IDENTIFIER IN
: FROM identifier_inside_body IN
{
current_block = new Linq.QueryBlock (current_block, lexer.Location);
}
@ -5772,7 +5845,7 @@ from_clause @@ -5772,7 +5845,7 @@ from_clause
((Linq.QueryBlock)current_block).AddRangeVariable (sn);
}
| FROM type IDENTIFIER IN
| FROM type identifier_inside_body IN
{
current_block = new Linq.QueryBlock (current_block, lexer.Location);
}
@ -5876,7 +5949,7 @@ query_body_clause @@ -5876,7 +5949,7 @@ query_body_clause
;
let_clause
: LET IDENTIFIER ASSIGN
: LET identifier_inside_body ASSIGN
{
current_block = new Linq.QueryBlock (current_block, lexer.Location);
}
@ -5909,7 +5982,7 @@ where_clause @@ -5909,7 +5982,7 @@ where_clause
;
join_clause
: JOIN IDENTIFIER IN
: JOIN identifier_inside_body IN
{
if (linq_clause_blocks == null)
linq_clause_blocks = new Stack<Linq.QueryBlock> ();
@ -5971,7 +6044,7 @@ join_clause @@ -5971,7 +6044,7 @@ join_clause
current_block = block.Parent;
((Linq.QueryBlock)current_block).AddRangeVariable (into);
}
| JOIN type IDENTIFIER IN
| JOIN type identifier_inside_body IN
{
if (linq_clause_blocks == null)
linq_clause_blocks = new Stack<Linq.QueryBlock> ();
@ -6039,7 +6112,7 @@ join_clause @@ -6039,7 +6112,7 @@ join_clause
opt_join_into
: /* empty */
| INTO IDENTIFIER
| INTO identifier_inside_body
{
$$ = $2;
}
@ -6128,7 +6201,7 @@ then_by @@ -6128,7 +6201,7 @@ then_by
opt_query_continuation
: /* empty */
| INTO IDENTIFIER
| INTO identifier_inside_body
{
// query continuation block is not linked with query block but with block
// before. This means each query can use same range variable names for
@ -6667,7 +6740,7 @@ void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync @@ -6667,7 +6740,7 @@ void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync
oob_stack.Push (current_anonymous_method);
oob_stack.Push (current_local_parameters);
oob_stack.Push (current_variable);
oob_stack.Push (lexer.async_block);
oob_stack.Push (async_block);
current_local_parameters = parameters;
if (isLambda) {
@ -6682,7 +6755,7 @@ void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync @@ -6682,7 +6755,7 @@ void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync
current_anonymous_method = new AnonymousMethodExpression (isAsync, loc);
}
lexer.async_block = isAsync;
async_block = isAsync;
// Force the next block to be created as a ToplevelBlock
parsing_anonymous_method = true;
}
@ -6695,10 +6768,13 @@ AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) @@ -6695,10 +6768,13 @@ AnonymousMethodExpression end_anonymous (ParametersBlock anon_block)
{
AnonymousMethodExpression retval;
if (async_block)
anon_block.IsAsync = true;
current_anonymous_method.Block = anon_block;
retval = current_anonymous_method;
lexer.async_block = (bool) oob_stack.Pop ();
async_block = (bool) oob_stack.Pop ();
current_variable = (BlockVariableDeclaration) oob_stack.Pop ();
current_local_parameters = (ParametersCompiled) oob_stack.Pop ();
current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop ();
@ -7178,6 +7254,7 @@ static string GetTokenName (int token) @@ -7178,6 +7254,7 @@ static string GetTokenName (int token)
case Token.LITERAL:
return "value";
case Token.IDENTIFIER:
case Token.AWAIT:
return "identifier";
case Token.EOF:

69
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs

@ -85,6 +85,11 @@ namespace Mono.CSharp @@ -85,6 +85,11 @@ namespace Mono.CSharp
return Create (null, row, column);
}
public static LocatedToken Create (string value, Location loc)
{
return Create (value, loc.Row, loc.Column);
}
public static LocatedToken Create (string value, int row, int column)
{
//
@ -207,8 +212,6 @@ namespace Mono.CSharp @@ -207,8 +212,6 @@ namespace Mono.CSharp
public bool parsing_modifiers;
public bool async_block;
//
// The special characters to inject on streams to run the unit parser
// in the special expression mode. Using private characters from
@ -421,10 +424,6 @@ namespace Mono.CSharp @@ -421,10 +424,6 @@ namespace Mono.CSharp
else
tab_size = 8;
//
// FIXME: This could be `Location.Push' but we have to
// find out why the MS compiler allows this
//
Mono.CSharp.Location.Push (file, file);
}
@ -830,14 +829,13 @@ namespace Mono.CSharp @@ -830,14 +829,13 @@ namespace Mono.CSharp
break;
case Token.AWAIT:
if (!async_block)
if (parsing_block == 0)
res = -1;
break;
}
return res;
return res;
}
static PreprocessorDirective GetPreprocessorDirective (char[] id, int id_len)
@ -1826,11 +1824,11 @@ namespace Mono.CSharp @@ -1826,11 +1824,11 @@ namespace Mono.CSharp
{
// skip over white space
do {
endLine = line;
endCol = col;
c = get_char ();
} while (c == ' ' || c == '\t');
endLine = line;
endCol = col;
int pos = 0;
while (c != -1 && c >= 'a' && c <= 'z') {
id_builder[pos++] = (char) c;
@ -1871,15 +1869,13 @@ namespace Mono.CSharp @@ -1871,15 +1869,13 @@ namespace Mono.CSharp
return cmd;
}
// skip over white space
while (c == ' ' || c == '\t')
while (c == ' ' || c == '\t') {
c = get_char ();
}
int has_identifier_argument = (int)(cmd & PreprocessorDirective.RequiresArgument);
int pos = 0;
while (c != -1 && c != '\n' && c != '\r') {
if (c == '\\' && has_identifier_argument >= 0) {
if (has_identifier_argument != 0) {
@ -1913,9 +1909,9 @@ namespace Mono.CSharp @@ -1913,9 +1909,9 @@ namespace Mono.CSharp
break;
}
endLine = line;
endCol = col;
endCol = col + 1;
if (pos == value_builder.Length)
Array.Resize (ref value_builder, pos * 2);
@ -2240,7 +2236,7 @@ namespace Mono.CSharp @@ -2240,7 +2236,7 @@ namespace Mono.CSharp
if (position_stack.Count == 0)
sbag.PushCommentChar (c);
var pc = peek_char ();
if (pc == '\n' || pc == -1 && position_stack.Count == 0)
if ((pc == '\n' || pc == -1) && position_stack.Count == 0)
sbag.EndComment (line, col + 1);
} while (c != -1 && c != '\n');
}
@ -2878,7 +2874,7 @@ namespace Mono.CSharp @@ -2878,7 +2874,7 @@ namespace Mono.CSharp
if (id_builder [0] >= '_' && !quoted) {
int keyword = GetKeyword (id_builder, pos);
if (keyword != -1) {
val = LocatedToken.Create (null, ref_line, column);
val = LocatedToken.Create (keyword == Token.AWAIT ? "await" : null, ref_line, column);
return keyword;
}
}
@ -3215,14 +3211,16 @@ namespace Mono.CSharp @@ -3215,14 +3211,16 @@ namespace Mono.CSharp
}
d = peek_char ();
int endLine = line, endCol = col;
while ((d = get_char ()) != -1 && (d != '\n') && d != '\r') {
if (position_stack.Count == 0)
sbag.PushCommentChar (d);
endLine = line;
endCol = col;
}
if (position_stack.Count == 0)
sbag.EndComment (line, col + 1);
sbag.EndComment (endLine, endCol + 1);
any_token_seen |= tokens_seen;
tokens_seen = false;
comments_seen = false;
@ -3234,16 +3232,16 @@ namespace Mono.CSharp @@ -3234,16 +3232,16 @@ namespace Mono.CSharp
bool docAppend = false;
if (doc_processing && peek_char () == '*') {
int ch = get_char ();
if (position_stack.Count == 0)
sbag.PushCommentChar (ch);
// But when it is /**/, just do nothing.
if (peek_char () == '/') {
ch = get_char ();
if (position_stack.Count == 0) {
sbag.PushCommentChar (ch);
sbag.EndComment (line, col + 1);
}
continue;
} else {
if (position_stack.Count == 0)
sbag.PushCommentChar (ch);
}
if (doc_state == XmlCommentState.Allowed)
docAppend = true;
@ -3259,16 +3257,15 @@ namespace Mono.CSharp @@ -3259,16 +3257,15 @@ namespace Mono.CSharp
}
while ((d = get_char ()) != -1){
if (position_stack.Count == 0)
sbag.PushCommentChar (d);
if (d == '*' && peek_char () == '/'){
if (position_stack.Count == 0)
sbag.PushCommentChar ('/');
get_char ();
if (position_stack.Count == 0)
sbag.EndComment (line, col + 1);
comments_seen = true;
break;
} else {
if (position_stack.Count == 0)
sbag.PushCommentChar (d);
}
if (docAppend)
xml_comment_buffer.Append ((char) d);
@ -3346,7 +3343,7 @@ namespace Mono.CSharp @@ -3346,7 +3343,7 @@ namespace Mono.CSharp
if (ParsePreprocessingDirective (true))
continue;
sbag.StartComment (SpecialsBag.CommentType.InactiveCode, false, line, 1);
bool directive_expected = false;
while ((c = get_char ()) != -1) {
if (col == 1) {
@ -3357,26 +3354,30 @@ namespace Mono.CSharp @@ -3357,26 +3354,30 @@ namespace Mono.CSharp
// Eror_WrongPreprocessorLocation ();
// return Token.ERROR;
// }
sbag.PushCommentChar (c);
continue;
}
if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' )
if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' ) {
sbag.PushCommentChar (c);
continue;
}
if (c == '#') {
if (ParsePreprocessingDirective (false))
break;
}
sbag.PushCommentChar (c);
directive_expected = false;
}
sbag.EndComment (line, col);
if (c != -1) {
tokens_seen = false;
continue;
}
return Token.EOF;
case '"':
return consume_string (false);
@ -3444,7 +3445,7 @@ namespace Mono.CSharp @@ -3444,7 +3445,7 @@ namespace Mono.CSharp
return Token.LITERAL;
}
if (c == '\r') {
if (c == '\n') {
Report.Error (1010, start_location, "Newline in constant");
return Token.ERROR;
}

4
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/decl.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
//
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2008 Novell, Inc
// Copyright 2011 Xamarin Inc
//
//
@ -27,7 +28,6 @@ using IKVM.Reflection.Emit; @@ -27,7 +28,6 @@ using IKVM.Reflection.Emit;
#else
using System.Reflection;
using System.Reflection.Emit;
//using Mono.Collections.Generic;
#endif
namespace Mono.CSharp {
@ -1347,7 +1347,7 @@ namespace Mono.CSharp { @@ -1347,7 +1347,7 @@ namespace Mono.CSharp {
} else {
Report.Error (102, symbol.Location,
"The type `{0}' already contains a definition for `{1}'",
GetSignatureForError (), symbol.MemberName.Name);
GetSignatureForError (), name);
}
return false;

10
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/delegate.cs

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
//
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2009 Novell, Inc (http://www.novell.com)
// Copyright 2011 Xamarin Inc
//
using System;
@ -176,20 +177,21 @@ namespace Mono.CSharp { @@ -176,20 +177,21 @@ namespace Mono.CSharp {
TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this);
InvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName (InvokeMethodName), p, null);
var resolved_rt = new TypeExpression (ret_type, Location);
InvokeBuilder = new Method (this, null, resolved_rt, MethodModifiers, new MemberName (InvokeMethodName), p, null);
InvokeBuilder.Define ();
//
// Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
//
if (!IsCompilerGenerated) {
DefineAsyncMethods (Parameters.CallingConvention);
DefineAsyncMethods (Parameters.CallingConvention, resolved_rt);
}
return true;
}
void DefineAsyncMethods (CallingConventions cc)
void DefineAsyncMethods (CallingConventions cc, TypeExpression returnType)
{
var iasync_result = Module.PredefinedTypes.IAsyncResult;
var async_callback = Module.PredefinedTypes.AsyncCallback;
@ -280,7 +282,7 @@ namespace Mono.CSharp { @@ -280,7 +282,7 @@ namespace Mono.CSharp {
//
// Create method, define parameters, register parameters with type system
//
EndInvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null);
EndInvokeBuilder = new Method (this, null, returnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null);
EndInvokeBuilder.Define ();
}

1
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/doc.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright 2004 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
//

9
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/driver.cs

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
//
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc
// Copyright 2011 Xamarin Inc
//
using System;
@ -434,7 +435,8 @@ namespace Mono.CSharp @@ -434,7 +435,8 @@ namespace Mono.CSharp
var setting = cmd.ParseArguments (args);
if (setting == null || r.Errors > 0)
return null;
setting.Version = LanguageVersion.V_5;
CompilerContext ctx = new CompilerContext (setting, r);
var files = new List<CompilationSourceFile> ();
@ -445,7 +447,7 @@ namespace Mono.CSharp @@ -445,7 +447,7 @@ namespace Mono.CSharp
Location.Initialize (files);
// TODO: encoding from driver
SeekableStreamReader reader = new SeekableStreamReader (input, Encoding.Default);
SeekableStreamReader reader = new SeekableStreamReader (input, Encoding.UTF8);
RootContext.ToplevelTypes = module;
@ -460,8 +462,7 @@ namespace Mono.CSharp @@ -460,8 +462,7 @@ namespace Mono.CSharp
ModuleCompiled = RootContext.ToplevelTypes,
LocationsBag = parser.LocationsBag,
UsingsBag = parser.UsingsBag,
SpecialsBag = parser.Lexer.sbag,
LastYYValue = parser.LastYYVal
SpecialsBag = parser.Lexer.sbag
};
} finally {
Reset ();

288
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs

@ -316,9 +316,20 @@ namespace Mono.CSharp { @@ -316,9 +316,20 @@ namespace Mono.CSharp {
TypeManager.CSharpName (type), name);
}
protected static void Error_ValueAssignment (ResolveContext ec, Location loc)
public void Error_ValueAssignment (ResolveContext rc, Expression rhs)
{
ec.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
if (rhs == EmptyExpression.LValueMemberAccess || rhs == EmptyExpression.LValueMemberOutAccess) {
rc.Report.SymbolRelatedToPreviousError (type);
if (rc.CurrentInitializerVariable != null) {
rc.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer",
type.GetSignatureForError (), GetSignatureForError ());
} else {
rc.Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
GetSignatureForError ());
}
} else {
rc.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
}
}
protected void Error_VoidPointerOperation (ResolveContext rc)
@ -391,7 +402,7 @@ namespace Mono.CSharp { @@ -391,7 +402,7 @@ namespace Mono.CSharp {
throw;
ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message);
return EmptyExpression.Null; // TODO: Add location
return ErrorExpression.Instance; // TODO: Add location
}
}
@ -432,7 +443,7 @@ namespace Mono.CSharp { @@ -432,7 +443,7 @@ namespace Mono.CSharp {
if (out_access)
ec.Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
else
Error_ValueAssignment (ec, loc);
Error_ValueAssignment (ec, right_side);
}
return null;
}
@ -529,12 +540,12 @@ namespace Mono.CSharp { @@ -529,12 +540,12 @@ namespace Mono.CSharp {
//
// Store the result to temporary field when we
// cannot load this directly
// cannot load `this' directly
//
var field = ec.GetTemporaryField (type);
if (needs_temporary) {
//
// Create temporary local (we cannot load this before Emit)
// Create temporary local (we cannot load `this' before Emit)
//
var temp = ec.GetTemporaryLocal (type);
ec.Emit (OpCodes.Stloc, temp);
@ -629,15 +640,11 @@ namespace Mono.CSharp { @@ -629,15 +640,11 @@ namespace Mono.CSharp {
}
var r = new OverloadResolver (ctors, OverloadResolver.Restrictions.NoBaseMembers, loc);
var ctor = r.ResolveMember<MethodSpec> (rc, ref args);
if (ctor == null)
return null;
if ((ctor.Modifiers & Modifiers.PROTECTED) != 0 && !rc.HasSet (ResolveContext.Options.BaseInitializer)) {
MemberExpr.CheckProtectedMemberAccess (rc, ctor, ctor.DeclaringType, loc);
if (!rc.HasSet (ResolveContext.Options.BaseInitializer)) {
r.InstanceQualifier = new ConstructorInstanceQualifier (type);
}
return ctor;
return r.ResolveMember<MethodSpec> (rc, ref args);
}
[Flags]
@ -669,6 +676,9 @@ namespace Mono.CSharp { @@ -669,6 +676,9 @@ namespace Mono.CSharp {
if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event)
continue;
if ((member.Modifiers & Modifiers.BACKING_FIELD) != 0)
continue;
if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity)
continue;
@ -739,6 +749,12 @@ namespace Mono.CSharp { @@ -739,6 +749,12 @@ namespace Mono.CSharp {
throw new NotImplementedException ();
}
public virtual void Error_OperatorCannotBeApplied (ResolveContext rc, Location loc, string oper, TypeSpec t)
{
rc.Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
oper, t.GetSignatureForError ());
}
protected void Error_PointerInsideExpressionTree (ResolveContext ec)
{
ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
@ -832,7 +848,7 @@ namespace Mono.CSharp { @@ -832,7 +848,7 @@ namespace Mono.CSharp {
name, was, expected);
}
public void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
public virtual void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
{
string [] valid = new string [4];
int count = 0;
@ -875,18 +891,6 @@ namespace Mono.CSharp { @@ -875,18 +891,6 @@ namespace Mono.CSharp {
Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
}
protected void Error_CannotModifyIntermediateExpressionValue (ResolveContext ec)
{
ec.Report.SymbolRelatedToPreviousError (type);
if (ec.CurrentInitializerVariable != null) {
ec.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer",
TypeManager.CSharpName (type), GetSignatureForError ());
} else {
ec.Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
GetSignatureForError ());
}
}
//
// Converts `source' to an int, uint, long or ulong.
//
@ -2230,9 +2234,16 @@ namespace Mono.CSharp { @@ -2230,9 +2234,16 @@ namespace Mono.CSharp {
return new SimpleName (Name, targs, loc);
}
protected override Expression DoResolve (ResolveContext ec)
protected override Expression DoResolve (ResolveContext rc)
{
return SimpleNameResolve (ec, null, false);
var e = SimpleNameResolve (rc, null, false);
var fe = e as FieldExpr;
if (fe != null) {
fe.VerifyAssignedStructField (rc, null);
}
return e;
}
public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
@ -2660,7 +2671,7 @@ namespace Mono.CSharp { @@ -2660,7 +2671,7 @@ namespace Mono.CSharp {
/// This class denotes an expression which evaluates to a member
/// of a struct or a class.
/// </summary>
public abstract class MemberExpr : Expression
public abstract class MemberExpr : Expression, OverloadResolver.IInstanceQualifier
{
//
// An instance expression associated with this member, if it's a
@ -2700,6 +2711,12 @@ namespace Mono.CSharp { @@ -2700,6 +2711,12 @@ namespace Mono.CSharp {
get;
}
TypeSpec OverloadResolver.IInstanceQualifier.InstanceType {
get {
return InstanceExpression.Type;
}
}
//
// Converts best base candidate for virtual method starting from QueriedBaseType
//
@ -2764,32 +2781,41 @@ namespace Mono.CSharp { @@ -2764,32 +2781,41 @@ namespace Mono.CSharp {
return method;
}
protected void CheckProtectedMemberAccess<T> (ResolveContext rc, T member) where T : MemberSpec
protected void CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member)
{
if (InstanceExpression == null)
return;
if ((member.Modifiers & Modifiers.PROTECTED) != 0 && !(InstanceExpression is This)) {
CheckProtectedMemberAccess (rc, member, InstanceExpression.Type, loc);
if (!CheckProtectedMemberAccess (rc, member, InstanceExpression.Type)) {
Error_ProtectedMemberAccess (rc, member, InstanceExpression.Type, loc);
}
}
}
public static void CheckProtectedMemberAccess<T> (ResolveContext rc, T member, TypeSpec qualifier, Location loc) where T : MemberSpec
bool OverloadResolver.IInstanceQualifier.CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member)
{
if (InstanceExpression == null)
return true;
return InstanceExpression is This || CheckProtectedMemberAccess (rc, member, InstanceExpression.Type);
}
public static bool CheckProtectedMemberAccess<T> (ResolveContext rc, T member, TypeSpec qualifier) where T : MemberSpec
{
var ct = rc.CurrentType;
if (ct == qualifier)
return;
return true;
if ((member.Modifiers & Modifiers.INTERNAL) != 0 && member.DeclaringType.MemberDefinition.IsInternalAsPublic (ct.MemberDefinition.DeclaringAssembly))
return;
return true;
qualifier = qualifier.GetDefinition ();
if (ct != qualifier && !IsSameOrBaseQualifier (ct, qualifier)) {
rc.Report.SymbolRelatedToPreviousError (member);
rc.Report.Error (1540, loc,
"Cannot access protected member `{0}' via a qualifier of type `{1}'. The qualifier must be of type `{2}' or derived from it",
member.GetSignatureForError (), qualifier.GetSignatureForError (), ct.GetSignatureForError ());
return false;
}
return true;
}
public override bool ContainsEmitWithAwait ()
@ -2842,6 +2868,14 @@ namespace Mono.CSharp { @@ -2842,6 +2868,14 @@ namespace Mono.CSharp {
rc.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
}
public static void Error_ProtectedMemberAccess (ResolveContext rc, MemberSpec member, TypeSpec qualifier, Location loc)
{
rc.Report.SymbolRelatedToPreviousError (member);
rc.Report.Error (1540, loc,
"Cannot access protected member `{0}' via a qualifier of type `{1}'. The qualifier must be of type `{2}' or derived from it",
member.GetSignatureForError (), qualifier.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
}
//
// Implements identicial simple name and type-name
//
@ -2903,6 +2937,7 @@ namespace Mono.CSharp { @@ -2903,6 +2937,7 @@ namespace Mono.CSharp {
"An object reference is required to access non-static member `{0}'",
GetSignatureForError ());
InstanceExpression = new CompilerGeneratedThis (type, loc).Resolve (rc);
return false;
}
@ -2913,7 +2948,7 @@ namespace Mono.CSharp { @@ -2913,7 +2948,7 @@ namespace Mono.CSharp {
}
InstanceExpression = new This (loc);
if (this is FieldExpr && rc.CurrentType.IsStruct) {
if (this is FieldExpr && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
InstanceExpression = InstanceExpression.Resolve (rc);
}
@ -2944,7 +2979,7 @@ namespace Mono.CSharp { @@ -2944,7 +2979,7 @@ namespace Mono.CSharp {
// the expression is not field expression which is the only
// expression which can use uninitialized this
//
if (InstanceExpression is This && !(this is FieldExpr) && rc.CurrentType.IsStruct) {
if (InstanceExpression is This && !(this is FieldExpr) && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
((This)InstanceExpression).CheckStructThisDefiniteAssignment (rc);
}
@ -2952,9 +2987,6 @@ namespace Mono.CSharp { @@ -2952,9 +2987,6 @@ namespace Mono.CSharp {
// Additional checks for l-value member access
//
if (rhs != null) {
//
// TODO: It should be recursive but that would break csc compatibility
//
if (InstanceExpression is UnboxCast) {
rc.Report.Error (445, InstanceExpression.Location, "Cannot modify the result of an unboxing conversion");
}
@ -2981,11 +3013,12 @@ namespace Mono.CSharp { @@ -2981,11 +3013,12 @@ namespace Mono.CSharp {
if (InstanceExpression is IMemoryLocation) {
((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.Load);
} else {
// Cannot release the temporary variable when its address
// is required to be on stack for any parent
LocalTemporary t = new LocalTemporary (instance_type);
InstanceExpression.Emit (ec);
t.Store (ec);
t.AddressOf (ec, AddressOp.Store);
t.Release (ec);
}
} else {
InstanceExpression.Emit (ec);
@ -3361,6 +3394,7 @@ namespace Mono.CSharp { @@ -3361,6 +3394,7 @@ namespace Mono.CSharp {
var r = new OverloadResolver (Methods, type_arguments, restr, loc);
if ((restr & OverloadResolver.Restrictions.NoBaseMembers) == 0) {
r.BaseMembersProvider = this;
r.InstanceQualifier = this;
}
if (cerrors != null)
@ -3389,8 +3423,6 @@ namespace Mono.CSharp { @@ -3389,8 +3423,6 @@ namespace Mono.CSharp {
}
ResolveInstanceExpression (ec, null);
if (InstanceExpression != null)
CheckProtectedMemberAccess (ec, best_candidate);
}
var base_override = CandidateToBaseOverride (ec, best_candidate);
@ -3456,6 +3488,22 @@ namespace Mono.CSharp { @@ -3456,6 +3488,22 @@ namespace Mono.CSharp {
#endregion
}
struct ConstructorInstanceQualifier : OverloadResolver.IInstanceQualifier
{
public ConstructorInstanceQualifier (TypeSpec type)
: this ()
{
InstanceType = type;
}
public TypeSpec InstanceType { get; private set; }
public bool CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member)
{
return MemberExpr.CheckProtectedMemberAccess (rc, member, InstanceType);
}
}
public struct OverloadResolver
{
[Flags]
@ -3484,6 +3532,12 @@ namespace Mono.CSharp { @@ -3484,6 +3532,12 @@ namespace Mono.CSharp {
bool TypeInferenceFailed (ResolveContext rc, MemberSpec best);
}
public interface IInstanceQualifier
{
TypeSpec InstanceType { get; }
bool CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member);
}
sealed class NoBaseMembers : IBaseMembersProvider
{
public static readonly IBaseMembersProvider Instance = new NoBaseMembers ();
@ -3523,6 +3577,7 @@ namespace Mono.CSharp { @@ -3523,6 +3577,7 @@ namespace Mono.CSharp {
TypeArguments type_arguments;
IBaseMembersProvider base_provider;
IErrorHandler custom_errors;
IInstanceQualifier instance_qualifier;
Restrictions restrictions;
MethodGroupExpr best_candidate_extension_group;
TypeSpec best_candidate_return_type;
@ -3600,6 +3655,15 @@ namespace Mono.CSharp { @@ -3600,6 +3655,15 @@ namespace Mono.CSharp {
}
}
public IInstanceQualifier InstanceQualifier {
get {
return instance_qualifier;
}
set {
instance_qualifier = value;
}
}
bool IsProbingOnly {
get {
return (restrictions & Restrictions.ProbingOnly) != 0;
@ -3674,16 +3738,16 @@ namespace Mono.CSharp { @@ -3674,16 +3738,16 @@ namespace Mono.CSharp {
// better conversion is performed between underlying types Y1 and Y2
//
if (p.IsGenericTask || q.IsGenericTask) {
if (p.IsGenericTask != q.IsGenericTask) {
return 0;
}
var async_am = a.Expr as AnonymousMethodExpression;
if (async_am == null || !async_am.IsAsync)
return 0;
if (async_am != null && async_am.Block.IsAsync) {
q = q.TypeArguments[0];
p = p.TypeArguments[0];
if (p.IsGenericTask != q.IsGenericTask) {
return 0;
}
q = q.TypeArguments[0];
p = p.TypeArguments[0];
}
}
//
@ -4181,7 +4245,7 @@ namespace Mono.CSharp { @@ -4181,7 +4245,7 @@ namespace Mono.CSharp {
// if the type matches
//
Expression e = pd.FixedParameters[i].DefaultValue;
if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric) {
if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric || e.Type.IsGenericParameter) {
//
// LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
//
@ -4429,6 +4493,11 @@ namespace Mono.CSharp { @@ -4429,6 +4493,11 @@ namespace Mono.CSharp {
if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc))
continue;
if ((member.Modifiers & (Modifiers.PROTECTED | Modifiers.STATIC)) == Modifiers.PROTECTED &&
instance_qualifier != null && !instance_qualifier.CheckProtectedMemberAccess (rc, member)) {
continue;
}
}
IParametersMember pm = member as IParametersMember;
@ -4568,6 +4637,9 @@ namespace Mono.CSharp { @@ -4568,6 +4637,9 @@ namespace Mono.CSharp {
if (error_mode)
break;
if (lambda_conv_msgs != null && !lambda_conv_msgs.IsEmpty)
break;
lambda_conv_msgs = null;
error_mode = true;
}
@ -4730,6 +4802,12 @@ namespace Mono.CSharp { @@ -4730,6 +4802,12 @@ namespace Mono.CSharp {
return;
}
if ((best_candidate.Modifiers & (Modifiers.PROTECTED | Modifiers.STATIC)) == Modifiers.PROTECTED &&
InstanceQualifier != null && !InstanceQualifier.CheckProtectedMemberAccess (rc, best_candidate)) {
MemberExpr.Error_ProtectedMemberAccess (rc, best_candidate, InstanceQualifier.InstanceType, loc);
}
//
// For candidates which match on parameters count report more details about incorrect arguments
//
@ -5082,7 +5160,7 @@ namespace Mono.CSharp { @@ -5082,7 +5160,7 @@ namespace Mono.CSharp {
public override string GetSignatureForError ()
{
return TypeManager.GetFullNameSignature (spec);
return spec.GetSignatureForError ();
}
public bool IsMarshalByRefAccess (ResolveContext rc)
@ -5096,8 +5174,9 @@ namespace Mono.CSharp { @@ -5096,8 +5174,9 @@ namespace Mono.CSharp {
public void SetHasAddressTaken ()
{
IVariableReference vr = InstanceExpression as IVariableReference;
if (vr != null)
if (vr != null) {
vr.SetHasAddressTaken ();
}
}
public override Expression CreateExpressionTree (ResolveContext ec)
@ -5162,7 +5241,7 @@ namespace Mono.CSharp { @@ -5162,7 +5241,7 @@ namespace Mono.CSharp {
IVariableReference var = InstanceExpression as IVariableReference;
if (lvalue_instance && var != null && var.VariableInfo != null) {
var.VariableInfo.SetFieldAssigned (ec, Name);
var.VariableInfo.SetStructFieldAssigned (ec, Name);
}
if (fb != null) {
@ -5182,18 +5261,43 @@ namespace Mono.CSharp { @@ -5182,18 +5261,43 @@ namespace Mono.CSharp {
return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec);
}
//
// Set flow-analysis variable info for struct member access. It will be check later
// for precise error reporting
//
if (var != null && var.VariableInfo != null && InstanceExpression.Type.IsStruct) {
variable_info = var.VariableInfo.GetStructFieldInfo (Name);
if (rhs != null && variable_info != null)
variable_info.SetStructFieldAssigned (ec, Name);
}
eclass = ExprClass.Variable;
return this;
}
// If the instance expression is a local variable or parameter.
if (var == null || var.VariableInfo == null)
return this;
public void VerifyAssignedStructField (ResolveContext rc, Expression rhs)
{
var fe = this;
VariableInfo vi = var.VariableInfo;
if (!vi.IsFieldAssigned (ec, Name, loc))
return null;
do {
var var = fe.InstanceExpression as IVariableReference;
if (var != null) {
var vi = var.VariableInfo;
variable_info = vi.GetSubStruct (Name);
return this;
if (vi != null && !vi.IsStructFieldAssigned (rc, fe.Name) && (rhs == null || !fe.type.IsStruct)) {
if (rhs != null) {
rc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
} else {
rc.Report.Error (170, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
}
return;
}
}
fe = fe.InstanceExpression as FieldExpr;
} while (fe != null);
}
static readonly int [] codes = {
@ -5315,10 +5419,7 @@ namespace Mono.CSharp { @@ -5315,10 +5419,7 @@ namespace Mono.CSharp {
public void Emit (EmitContext ec, bool leave_copy)
{
bool is_volatile = false;
if ((spec.Modifiers & Modifiers.VOLATILE) != 0)
is_volatile = true;
bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0;
spec.MemberDefinition.SetIsUsed ();
@ -5577,8 +5678,9 @@ namespace Mono.CSharp { @@ -5577,8 +5678,9 @@ namespace Mono.CSharp {
return CreateExpressionFactoryCall (ec, "Property", args);
}
public Expression CreateSetterTypeOfExpression ()
public Expression CreateSetterTypeOfExpression (ResolveContext rc)
{
DoResolveLValue (rc, null);
return new TypeOfMethod (Setter, loc);
}
@ -5798,7 +5900,7 @@ namespace Mono.CSharp { @@ -5798,7 +5900,7 @@ namespace Mono.CSharp {
// if the property/indexer returns a value type, and we try to set a field in it
if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
Error_CannotModifyIntermediateExpressionValue (ec);
Error_ValueAssignment (ec, right_side);
}
if (eclass == ExprClass.Unresolved) {
@ -6205,6 +6307,10 @@ namespace Mono.CSharp { @@ -6205,6 +6307,10 @@ namespace Mono.CSharp {
public override VariableInfo VariableInfo {
get { return null; }
}
public override void VerifyAssigned (ResolveContext rc)
{
}
}
///
@ -6243,4 +6349,42 @@ namespace Mono.CSharp { @@ -6243,4 +6349,42 @@ namespace Mono.CSharp {
ec.Module.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
}
}
public class InvalidStatementExpression : Statement
{
public Expression Expression {
get;
private set;
}
public InvalidStatementExpression (Expression expr)
{
this.Expression = expr;
}
public override void Emit (EmitContext ec)
{
// nothing
}
protected override void DoEmit (EmitContext ec)
{
// nothing
}
protected override void CloneTo (CloneContext clonectx, Statement target)
{
// nothing
}
public override Mono.CSharp.Expression CreateExpressionTree (ResolveContext ec)
{
return null;
}
public override object Accept (Mono.CSharp.StructuralVisitor visitor)
{
return visitor.Visit (this);
}
}
}

1
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/enum.cs

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
//
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2003 Novell, Inc (http://www.novell.com)
// Copyright 2011 Xamarin Inc
//
using System;

21
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/eval.cs

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
//
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2011 Novell, Inc
// Copyright 2011 Xamarin Inc
//
using System;
@ -55,7 +56,9 @@ namespace Mono.CSharp @@ -55,7 +56,9 @@ namespace Mono.CSharp
static object evaluator_lock = new object ();
static volatile bool invoking;
#if !STATIC
static int count;
#endif
static Thread invoke_thread;
readonly Dictionary<string, Tuple<FieldSpec, FieldInfo>> fields;
@ -134,6 +137,11 @@ namespace Mono.CSharp @@ -134,6 +137,11 @@ namespace Mono.CSharp
/// </summary>
public bool DescribeTypeExpressions;
/// <summary>
/// Whether the evaluator will use terse syntax, and the semicolons at the end are optional
/// </summary>
public bool Terse = true;
/// <summary>
/// The base class for the classes that host the user generated code
/// </summary>
@ -200,7 +208,7 @@ namespace Mono.CSharp @@ -200,7 +208,7 @@ namespace Mono.CSharp
/// compiled parameter will be set to the delegate
/// that can be invoked to execute the code.
///
/// </remarks>
/// </remarks>
public string Compile (string input, out CompiledMethod compiled)
{
if (input == null || input.Length == 0){
@ -218,6 +226,10 @@ namespace Mono.CSharp @@ -218,6 +226,10 @@ namespace Mono.CSharp
bool partial_input;
CSharpParser parser = ParseString (ParseMode.Silent, input, out partial_input);
if (parser == null && Terse && partial_input){
bool ignore;
parser = ParseString (ParseMode.Silent, input + ";", out ignore);
}
if (parser == null){
compiled = null;
if (partial_input)
@ -604,11 +616,12 @@ namespace Mono.CSharp @@ -604,11 +616,12 @@ namespace Mono.CSharp
CompiledMethod CompileBlock (Class host, Undo undo, Report Report)
{
string current_debug_name = "eval-" + count + ".dll";
++count;
#if STATIC
throw new NotSupportedException ();
#else
string current_debug_name = "eval-" + count + ".dll";
++count;
AssemblyDefinitionDynamic assembly;
AssemblyBuilderAccess access;
@ -1074,7 +1087,7 @@ namespace Mono.CSharp @@ -1074,7 +1087,7 @@ namespace Mono.CSharp
ec.Report.SetPrinter (old_printer);
}
if (tclone != null) {
if (tclone is TypeExpr) {
Arguments args = new Arguments (1);
args.Add (new Argument (new TypeOf ((TypeExpr) clone, Location)));
return new Invocation (new SimpleName ("Describe", Location), args).Resolve (ec);

318
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/expression.cs

@ -324,7 +324,7 @@ namespace Mono.CSharp @@ -324,7 +324,7 @@ namespace Mono.CSharp
//
// E operator ~(E x);
//
if (Oper == Operator.OnesComplement && TypeManager.IsEnumType (expr_type))
if (Oper == Operator.OnesComplement && expr_type.IsEnum)
return ResolveEnumOperator (ec, expr, predefined);
return ResolveUserType (ec, expr, predefined);
@ -565,12 +565,6 @@ namespace Mono.CSharp @@ -565,12 +565,6 @@ namespace Mono.CSharp
Expr.EmitSideEffect (ec);
}
public static void Error_OperatorCannotBeApplied (ResolveContext ec, Location loc, string oper, TypeSpec t)
{
ec.Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
oper, TypeManager.CSharpName (t));
}
//
// Converts operator to System.Linq.Expressions.ExpressionType enum name
//
@ -653,17 +647,6 @@ namespace Mono.CSharp @@ -653,17 +647,6 @@ namespace Mono.CSharp
IVariableReference vr = Expr as IVariableReference;
bool is_fixed;
if (vr != null) {
VariableInfo vi = vr.VariableInfo;
if (vi != null) {
if (vi.LocalInfo != null)
vi.LocalInfo.SetIsUsed ();
//
// A variable is considered definitely assigned if you take its address.
//
vi.SetAssigned (ec);
}
is_fixed = vr.IsFixed;
vr.SetHasAddressTaken ();
@ -1212,7 +1195,7 @@ namespace Mono.CSharp @@ -1212,7 +1195,7 @@ namespace Mono.CSharp
source = operation;
if (source == null) {
Unary.Error_OperatorCannotBeApplied (ec, loc, Operator.GetName (user_op), type);
expr.Error_OperatorCannotBeApplied (ec, loc, Operator.GetName (user_op), type);
return null;
}
@ -2330,7 +2313,7 @@ namespace Mono.CSharp @@ -2330,7 +2313,7 @@ namespace Mono.CSharp
public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, string oper, Location loc)
{
if (left.Type == InternalType.FakeInternalType || right.Type == InternalType.FakeInternalType)
if (left.Type == InternalType.ErrorType || right.Type == InternalType.ErrorType)
return;
string l, r;
@ -2663,7 +2646,7 @@ namespace Mono.CSharp @@ -2663,7 +2646,7 @@ namespace Mono.CSharp
case Operator.LessThanOrEqual:
case Operator.GreaterThan:
case Operator.GreaterThanOrEqual:
if (TypeManager.IsEnumType (left.Type))
if (left.Type.IsEnum)
return left;
if (left.IsZeroInteger)
@ -2680,7 +2663,7 @@ namespace Mono.CSharp @@ -2680,7 +2663,7 @@ namespace Mono.CSharp
case Operator.Modulus:
case Operator.LeftShift:
case Operator.RightShift:
if (TypeManager.IsEnumType (right.Type) || TypeManager.IsEnumType (left.Type))
if (right.Type.IsEnum || left.Type.IsEnum)
break;
return left;
}
@ -2937,7 +2920,7 @@ namespace Mono.CSharp @@ -2937,7 +2920,7 @@ namespace Mono.CSharp
Constant rc = right as Constant;
// The conversion rules are ignored in enum context but why
if (!ec.HasSet (ResolveContext.Options.EnumScope) && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) {
if (!ec.HasSet (ResolveContext.Options.EnumScope) && lc != null && rc != null && (left.Type.IsEnum || right.Type.IsEnum)) {
lc = EnumLiftUp (ec, lc, rc, loc);
if (lc != null)
rc = EnumLiftUp (ec, rc, lc, loc);
@ -4682,13 +4665,14 @@ namespace Mono.CSharp @@ -4682,13 +4665,14 @@ namespace Mono.CSharp
#region Abstract
public abstract HoistedVariable GetHoistedVariable (AnonymousExpression ae);
public abstract void SetHasAddressTaken ();
public abstract void VerifyAssigned (ResolveContext rc);
public abstract bool IsLockedByStatement { get; set; }
public abstract bool IsFixed { get; }
public abstract bool IsRef { get; }
public abstract string Name { get; }
public abstract void SetHasAddressTaken ();
//
// Variable IL data, it has to be protected to encapsulate hoisted variables
@ -4915,21 +4899,26 @@ namespace Mono.CSharp @@ -4915,21 +4899,26 @@ namespace Mono.CSharp
#endregion
public bool VerifyAssigned (ResolveContext ec)
public override void VerifyAssigned (ResolveContext rc)
{
VariableInfo variable_info = local_info.VariableInfo;
return variable_info == null || variable_info.IsAssigned (ec, loc);
if (variable_info == null)
return;
if (variable_info.IsAssigned (rc))
return;
rc.Report.Error (165, loc, "Use of unassigned local variable `{0}'", Name);
variable_info.SetAssigned (rc);
}
public override void SetHasAddressTaken ()
{
local_info.AddressTaken = true;
local_info.SetHasAddressTaken ();
}
void DoResolveBase (ResolveContext ec)
{
VerifyAssigned (ec);
//
// If we are referencing a variable from the external block
// flag it for capturing
@ -4957,6 +4946,8 @@ namespace Mono.CSharp @@ -4957,6 +4946,8 @@ namespace Mono.CSharp
{
local_info.SetIsUsed ();
VerifyAssigned (ec);
DoResolveBase (ec);
return this;
}
@ -4986,7 +4977,8 @@ namespace Mono.CSharp @@ -4986,7 +4977,8 @@ namespace Mono.CSharp
VariableInfo.SetAssigned (ec);
}
DoResolveBase (ec);
if (eclass == ExprClass.Unresolved)
DoResolveBase (ec);
return base.DoResolveLValue (ec, right_side);
}
@ -5089,17 +5081,17 @@ namespace Mono.CSharp @@ -5089,17 +5081,17 @@ namespace Mono.CSharp
#endregion
public bool IsAssigned (ResolveContext ec, Location loc)
public override void AddressOf (EmitContext ec, AddressOp mode)
{
// HACK: Variables are not captured in probing mode
if (ec.IsInProbingMode)
return true;
if (!ec.DoFlowAnalysis || !HasOutModifier || ec.CurrentBranching.IsAssigned (VariableInfo))
return true;
//
// ParameterReferences might already be a reference
//
if (IsRef) {
EmitLoad (ec);
return;
}
ec.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
return false;
base.AddressOf (ec, mode);
}
public override void SetHasAddressTaken ()
@ -5157,20 +5149,7 @@ namespace Mono.CSharp @@ -5157,20 +5149,7 @@ namespace Mono.CSharp
return Name == pr.Name;
}
public override void AddressOf (EmitContext ec, AddressOp mode)
{
//
// ParameterReferences might already be a reference
//
if (IsRef) {
EmitLoad (ec);
return;
}
base.AddressOf (ec, mode);
}
protected override void CloneTo (CloneContext clonectx, Expression target)
{
// Nothing to clone
@ -5203,14 +5182,7 @@ namespace Mono.CSharp @@ -5203,14 +5182,7 @@ namespace Mono.CSharp
if (!DoResolveBase (ec))
return null;
// HACK: Variables are not captured in probing mode
if (ec.IsInProbingMode)
return this;
if (HasOutModifier && ec.DoFlowAnalysis &&
(!ec.OmitStructFlowAnalysis || !VariableInfo.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
return null;
VerifyAssigned (ec);
return this;
}
@ -5222,6 +5194,17 @@ namespace Mono.CSharp @@ -5222,6 +5194,17 @@ namespace Mono.CSharp
SetAssigned (ec);
return base.DoResolveLValue (ec, right_side);
}
public override void VerifyAssigned (ResolveContext rc)
{
// HACK: Variables are not captured in probing mode
if (rc.IsInProbingMode)
return;
if (HasOutModifier && !VariableInfo.IsAssigned (rc)) {
rc.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
}
}
}
/// <summary>
@ -5320,7 +5303,7 @@ namespace Mono.CSharp @@ -5320,7 +5303,7 @@ namespace Mono.CSharp
Expression invoke = null;
if (mg == null) {
if (expr_type != null && TypeManager.IsDelegateType (expr_type)) {
if (expr_type != null && expr_type.IsDelegate) {
invoke = new DelegateInvocation (member_expr, arguments, loc);
invoke = invoke.Resolve (ec);
if (invoke == null || !dynamic_arg)
@ -5439,6 +5422,11 @@ namespace Mono.CSharp @@ -5439,6 +5422,11 @@ namespace Mono.CSharp
return list.ArgumentTypes;
}
public override string GetSignatureForError ()
{
return mg.GetSignatureForError ();
}
//
// If a member is a method or event, or if it is a constant, field or property of either a delegate type
// or the type dynamic, then the member is invocable
@ -5660,7 +5648,7 @@ namespace Mono.CSharp @@ -5660,7 +5648,7 @@ namespace Mono.CSharp
return ReducedExpression.Create (c, this);
}
if (TypeManager.IsDelegateType (type)) {
if (type.IsDelegate) {
return (new NewDelegate (type, arguments, loc)).Resolve (ec);
}
@ -5670,7 +5658,7 @@ namespace Mono.CSharp @@ -5670,7 +5658,7 @@ namespace Mono.CSharp
// Check whether the type of type parameter can be constructed. BaseType can be a struct for method overrides
// where type parameter constraint is inflated to struct
//
if ((tparam.SpecialConstraint & (SpecialConstraint.Struct | SpecialConstraint.Constructor)) == 0 && !tparam.BaseType.IsStruct) {
if ((tparam.SpecialConstraint & (SpecialConstraint.Struct | SpecialConstraint.Constructor)) == 0 && !TypeSpec.IsValueType (tparam)) {
ec.Report.Error (304, loc,
"Cannot create an instance of the variable type `{0}' because it does not have the new() constraint",
TypeManager.CSharpName (type));
@ -6056,7 +6044,7 @@ namespace Mono.CSharp @@ -6056,7 +6044,7 @@ namespace Mono.CSharp
// The number of constants in array initializers
int const_initializers_count;
bool only_constant_initializers;
// bool only_constant_initializers;
public List<Expression> Arguments {
get { return this.arguments; }
@ -6191,7 +6179,7 @@ namespace Mono.CSharp @@ -6191,7 +6179,7 @@ namespace Mono.CSharp
++const_initializers_count;
}
} else {
only_constant_initializers = false;
// only_constant_initializers = false;
}
array_data.Add (element);
@ -6296,7 +6284,7 @@ namespace Mono.CSharp @@ -6296,7 +6284,7 @@ namespace Mono.CSharp
protected bool ResolveInitializers (ResolveContext ec)
{
only_constant_initializers = true;
// only_constant_initializers = true;
if (arguments != null) {
bool res = true;
@ -6376,7 +6364,7 @@ namespace Mono.CSharp @@ -6376,7 +6364,7 @@ namespace Mono.CSharp
int count = array_data.Count;
TypeSpec element_type = array_element_type;
if (TypeManager.IsEnumType (element_type))
if (element_type.IsEnum)
element_type = EnumSpec.GetUnderlyingType (element_type);
factor = BuiltinTypeSpec.GetSize (element_type);
@ -6800,7 +6788,8 @@ namespace Mono.CSharp @@ -6800,7 +6788,8 @@ namespace Mono.CSharp
array_element_type = best_type_inference.InferredTypeArguments[0];
best_type_inference = null;
if (array_element_type == null || array_element_type == InternalType.MethodGroup || array_element_type == InternalType.AnonymousMethod ||
if (array_element_type == null ||
array_element_type == InternalType.NullLiteral || array_element_type == InternalType.MethodGroup || array_element_type == InternalType.AnonymousMethod ||
arguments.Count != rank.Dimension) {
ec.Report.Error (826, loc,
"The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
@ -6934,7 +6923,17 @@ namespace Mono.CSharp @@ -6934,7 +6923,17 @@ namespace Mono.CSharp
public void CheckStructThisDefiniteAssignment (ResolveContext rc)
{
if (variable_info != null && !variable_info.IsAssigned (rc)) {
//
// It's null for all cases when we don't need to check `this'
// definitive assignment
//
if (variable_info == null)
return;
if (rc.HasSet (ResolveContext.Options.OmitStructFlowAnalysis))
return;
if (!variable_info.IsAssigned (rc)) {
rc.Report.Error (188, loc,
"The `this' object cannot be used before all of its fields are assigned to");
}
@ -6978,7 +6977,7 @@ namespace Mono.CSharp @@ -6978,7 +6977,7 @@ namespace Mono.CSharp
if (ignoreAnonymous || ec.CurrentAnonymousMethod == null)
return true;
if (ec.CurrentType.IsStruct && ec.CurrentIterator == null)
if (ec.CurrentType.IsStruct && !(ec.CurrentAnonymousMethod is StateMachineInitializer))
return false;
return true;
@ -7010,16 +7009,15 @@ namespace Mono.CSharp @@ -7010,16 +7009,15 @@ namespace Mono.CSharp
{
ResolveBase (ec);
if (variable_info != null && type.IsStruct) {
CheckStructThisDefiniteAssignment (ec);
}
CheckStructThisDefiniteAssignment (ec);
return this;
}
override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
{
ResolveBase (ec);
if (eclass == ExprClass.Unresolved)
ResolveBase (ec);
if (variable_info != null)
variable_info.SetAssigned (ec);
@ -7059,6 +7057,12 @@ namespace Mono.CSharp @@ -7059,6 +7057,12 @@ namespace Mono.CSharp
{
// Nothing
}
public override void VerifyAssigned (ResolveContext rc)
{
}
public override object Accept (StructuralVisitor visitor)
{
@ -7625,7 +7629,7 @@ namespace Mono.CSharp @@ -7625,7 +7629,7 @@ namespace Mono.CSharp
if (type_queried == null)
return null;
if (TypeManager.IsEnumType (type_queried))
if (type_queried.IsEnum)
type_queried = EnumSpec.GetUnderlyingType (type_queried);
int size_of = BuiltinTypeSpec.GetSize (type_queried);
@ -7800,14 +7804,33 @@ namespace Mono.CSharp @@ -7800,14 +7804,33 @@ namespace Mono.CSharp
}
}
protected override Expression DoResolve (ResolveContext ec)
protected override Expression DoResolve (ResolveContext rc)
{
return DoResolveName (ec, null);
var e = DoResolveName (rc, null);
if (!rc.OmitStructFlowAnalysis) {
var fe = e as FieldExpr;
if (fe != null) {
fe.VerifyAssignedStructField (rc, null);
}
}
return e;
}
public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
public override Expression DoResolveLValue (ResolveContext rc, Expression rhs)
{
return DoResolveName (ec, right_side);
var e = DoResolveName (rc, rhs);
if (!rc.OmitStructFlowAnalysis) {
var fe = e as FieldExpr;
if (fe != null && fe.InstanceExpression is FieldExpr) {
fe = (FieldExpr) fe.InstanceExpression;
fe.VerifyAssignedStructField (rc, rhs);
}
}
return e;
}
Expression DoResolveName (ResolveContext rc, Expression right_side)
@ -7835,7 +7858,7 @@ namespace Mono.CSharp @@ -7835,7 +7858,7 @@ namespace Mono.CSharp
if (type == InternalType.NullLiteral && rc.IsRuntimeBinder)
rc.Report.Error (Report.RuntimeErrorId, loc, "Cannot perform member binding on `null' value");
else
Unary.Error_OperatorCannotBeApplied (rc, loc, ".", type);
expr.Error_OperatorCannotBeApplied (rc, loc, ".", type);
}
public static bool IsValidDotExpression (TypeSpec type)
@ -7861,8 +7884,11 @@ namespace Mono.CSharp @@ -7861,8 +7884,11 @@ namespace Mono.CSharp
if (sn != null) {
expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
// Call resolve on expression which does have type set as we need expression type
// TODO: I should probably ensure that the type is always set and leave resolve for the final
//
// Resolve expression which does have type set as we need expression type
// with disable flow analysis as we don't know whether left side expression
// is used as variable or type
//
if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) {
expr = expr.Resolve (rc);
@ -7901,6 +7927,16 @@ namespace Mono.CSharp @@ -7901,6 +7927,16 @@ namespace Mono.CSharp
if (me != null)
me.ResolveInstanceExpression (rc, null);
//
// Run defined assigned checks on expressions resolved with
// disabled flow-analysis
//
if (sn != null) {
var vr = expr as VariableReference;
if (vr != null)
vr.VerifyAssigned (rc);
}
Arguments args = new Arguments (1);
args.Add (new Argument (expr));
return new DynamicMemberBinder (Name, args, loc);
@ -7931,6 +7967,16 @@ namespace Mono.CSharp @@ -7931,6 +7967,16 @@ namespace Mono.CSharp
emg.SetTypeArguments (rc, targs);
}
//
// Run defined assigned checks on expressions resolved with
// disabled flow-analysis
//
if (sn != null && !errorMode) {
var vr = expr as VariableReference;
if (vr != null)
vr.VerifyAssigned (rc);
}
// TODO: it should really skip the checks bellow
return emg.Resolve (rc);
}
@ -7994,8 +8040,9 @@ namespace Mono.CSharp @@ -7994,8 +8040,9 @@ namespace Mono.CSharp
me = member_lookup as MemberExpr;
if (sn != null && me.IsStatic)
expr = me.ProbeIdenticalTypeName (rc, expr, sn);
if (sn != null && me.IsStatic && (expr = me.ProbeIdenticalTypeName (rc, expr, sn)) != expr) {
sn = null;
}
me = me.ResolveMemberAccess (rc, expr, sn);
@ -8006,12 +8053,14 @@ namespace Mono.CSharp @@ -8006,12 +8053,14 @@ namespace Mono.CSharp
me.SetTypeArguments (rc, targs);
}
if (sn != null && (!TypeSpec.IsValueType (expr_type) || me is PropertyExpr)) {
if (me.IsInstance) {
LocalVariableReference var = expr as LocalVariableReference;
if (var != null && !var.VerifyAssigned (rc))
return null;
}
//
// Run defined assigned checks on expressions resolved with
// disabled flow-analysis
//
if (sn != null && !(me is FieldExpr && TypeSpec.IsValueType (expr_type))) {
var vr = expr as VariableReference;
if (vr != null)
vr.VerifyAssigned (rc);
}
return me;
@ -8377,7 +8426,7 @@ namespace Mono.CSharp @@ -8377,7 +8426,7 @@ namespace Mono.CSharp
return res.Resolve (ec);
}
public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
public override Expression DoResolveLValue (ResolveContext ec, Expression rhs)
{
Expr = Expr.Resolve (ec);
if (Expr == null)
@ -8389,7 +8438,12 @@ namespace Mono.CSharp @@ -8389,7 +8438,12 @@ namespace Mono.CSharp
if (res == null)
return null;
return res.ResolveLValue (ec, right_side);
bool lvalue_instance = rhs != null && type.IsStruct && (Expr is Invocation || Expr is PropertyExpr);
if (lvalue_instance) {
Expr.Error_ValueAssignment (ec, EmptyExpression.LValueMemberAccess);
}
return res.ResolveLValue (ec, rhs);
}
public override void Emit (EmitContext ec)
@ -8844,6 +8898,7 @@ namespace Mono.CSharp @@ -8844,6 +8898,7 @@ namespace Mono.CSharp
} else {
var res = new OverloadResolver (indexers, OverloadResolver.Restrictions.None, loc);
res.BaseMembersProvider = this;
res.InstanceQualifier = this;
// TODO: Do I need 2 argument sets?
best_candidate = res.ResolveMember<IndexerSpec> (rc, ref arguments);
@ -8870,8 +8925,12 @@ namespace Mono.CSharp @@ -8870,8 +8925,12 @@ namespace Mono.CSharp
return new DynamicIndexBinder (args, loc);
}
ResolveInstanceExpression (rc, right_side);
CheckProtectedMemberAccess (rc, best_candidate);
//
// Try to avoid resolving left expression again
//
if (right_side != null)
ResolveInstanceExpression (rc, right_side);
return this;
}
@ -9109,14 +9168,29 @@ namespace Mono.CSharp @@ -9109,14 +9168,29 @@ namespace Mono.CSharp
}
}
class ErrorExpression : EmptyExpression
public class ErrorExpression : EmptyExpression
{
public static readonly ErrorExpression Instance = new ErrorExpression ();
public readonly int ErrorCode;
public readonly string Error;
private ErrorExpression ()
: base (InternalType.FakeInternalType)
: base (InternalType.ErrorType)
{
}
ErrorExpression (int errorCode, Location location, string error)
: base (InternalType.ErrorType)
{
this.ErrorCode = errorCode;
base.loc = location;
this.Error = error;
}
public static ErrorExpression Create (int errorCode, Location location, string error)
{
return new ErrorExpression (errorCode, location, error);
}
public override Expression CreateExpressionTree (ResolveContext ec)
{
@ -9128,9 +9202,22 @@ namespace Mono.CSharp @@ -9128,9 +9202,22 @@ namespace Mono.CSharp
return this;
}
public override void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
{
}
public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
{
}
public override void Error_OperatorCannotBeApplied (ResolveContext rc, Location loc, string oper, TypeSpec t)
{
}
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
}
}
public class UserCast : Expression {
@ -9566,12 +9653,21 @@ namespace Mono.CSharp @@ -9566,12 +9653,21 @@ namespace Mono.CSharp
if (fe != null)
args.Add (new Argument (fe.CreateTypeOfExpression ()));
else
args.Add (new Argument (((PropertyExpr)target).CreateSetterTypeOfExpression ()));
args.Add (new Argument (((PropertyExpr) target).CreateSetterTypeOfExpression (ec)));
string mname;
Expression arg_expr;
var cinit = source as CollectionOrObjectInitializers;
if (cinit == null) {
mname = "Bind";
arg_expr = source.CreateExpressionTree (ec);
} else {
mname = cinit.IsEmpty || cinit.Initializers[0] is ElementInitializer ? "MemberBind" : "ListBind";
arg_expr = cinit.CreateExpressionTree (ec, !cinit.IsEmpty);
}
args.Add (new Argument (source.CreateExpressionTree (ec)));
return CreateExpressionFactoryCall (ec,
source is CollectionOrObjectInitializers ? "ListBind" : "Bind",
args);
args.Add (new Argument (arg_expr));
return CreateExpressionFactoryCall (ec, mname, args);
}
protected override Expression DoResolve (ResolveContext ec)
@ -9775,6 +9871,11 @@ namespace Mono.CSharp @@ -9775,6 +9871,11 @@ namespace Mono.CSharp
}
public override Expression CreateExpressionTree (ResolveContext ec)
{
return CreateExpressionTree (ec, false);
}
public Expression CreateExpressionTree (ResolveContext ec, bool inferType)
{
var expr_initializers = new ArrayInitializer (initializers.Count, loc);
foreach (Expression e in initializers) {
@ -9783,7 +9884,10 @@ namespace Mono.CSharp @@ -9783,7 +9884,10 @@ namespace Mono.CSharp
expr_initializers.Add (expr);
}
return new ImplicitlyTypedArrayCreation (expr_initializers, loc);
if (inferType)
return new ImplicitlyTypedArrayCreation (expr_initializers, loc);
return new ArrayCreation (new TypeExpression (ec.Module.PredefinedTypes.MemberBinding.Resolve (), loc), expr_initializers, loc);
}
protected override Expression DoResolve (ResolveContext ec)
@ -9959,7 +10063,7 @@ namespace Mono.CSharp @@ -9959,7 +10063,7 @@ namespace Mono.CSharp
Arguments args = new Arguments (2);
args.Add (new Argument (base.CreateExpressionTree (ec)));
if (!initializers.IsEmpty)
args.Add (new Argument (initializers.CreateExpressionTree (ec)));
args.Add (new Argument (initializers.CreateExpressionTree (ec, initializers.IsCollectionInitializer)));
return CreateExpressionFactoryCall (ec,
initializers.IsCollectionInitializer ? "ListInit" : "MemberInit",
@ -10202,7 +10306,7 @@ namespace Mono.CSharp @@ -10202,7 +10306,7 @@ namespace Mono.CSharp
type = e.Type;
if (type.Kind == MemberKind.Void || type == InternalType.NullLiteral || type == InternalType.AnonymousMethod || type.IsPointer) {
Error_InvalidInitializer (ec, e.GetSignatureForError ());
Error_InvalidInitializer (ec, type.GetSignatureForError ());
return null;
}

12
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/field.cs

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
//
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2008 Novell, Inc
// Copyright 2011 Xamarin Inc
//
using System;
@ -626,8 +627,11 @@ namespace Mono.CSharp @@ -626,8 +627,11 @@ namespace Mono.CSharp
spec = new FieldSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags);
// Don't cache inaccessible fields
if ((ModFlags & Modifiers.BACKING_FIELD) == 0) {
//
// Don't cache inaccessible fields except for struct where we
// need them for definitive assignment checks
//
if ((ModFlags & Modifiers.BACKING_FIELD) == 0 || Parent.Kind == MemberKind.Struct) {
Parent.MemberCache.AddMember (spec);
}
@ -648,10 +652,6 @@ namespace Mono.CSharp @@ -648,10 +652,6 @@ namespace Mono.CSharp
}
}
/*
if ((ModFlags & (Modifiers.STATIC | Modifiers.READONLY | Modifiers.COMPILER_GENERATED)) == Modifiers.STATIC)
Console.WriteLine ("{0}: {1}", Location.ToString (), GetSignatureForError ());
*/
return true;
}

306
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/flowanalysis.cs

@ -1,9 +1,10 @@ @@ -1,9 +1,10 @@
//
// flowanalyis.cs: The control flow analysis code
//
// Author:
// Authors:
// Martin Baulig (martin@ximian.com)
// Raja R Harinath (rharinath@novell.com)
// Marek Safar (marek.safar@gmail.com)
//
// Copyright 2001, 2002, 2003 Ximian, Inc.
// Copyright 2003-2008 Novell, Inc.
@ -236,18 +237,18 @@ namespace Mono.CSharp @@ -236,18 +237,18 @@ namespace Mono.CSharp
public bool IsFieldAssigned (VariableInfo var, string name)
{
if (!var.IsParameter && IsUnreachable)
if (/*!var.IsParameter &&*/ IsUnreachable)
return true;
return var.IsFieldAssigned (locals, name);
return var.IsStructFieldAssigned (locals, name);
}
public void SetFieldAssigned (VariableInfo var, string name)
{
if (!var.IsParameter && IsUnreachable)
if (/*!var.IsParameter &&*/ IsUnreachable)
return;
var.SetFieldAssigned (locals, name);
var.SetStructFieldAssigned (locals, name);
}
public bool IsUnreachable {
@ -455,7 +456,7 @@ namespace Mono.CSharp @@ -455,7 +456,7 @@ namespace Mono.CSharp
return CurrentUsageVector.IsAssigned (vi, false);
}
public bool IsFieldAssigned (VariableInfo vi, string field_name)
public bool IsStructFieldAssigned (VariableInfo vi, string field_name)
{
return CurrentUsageVector.IsAssigned (vi, false) || CurrentUsageVector.IsFieldAssigned (vi, field_name);
}
@ -720,10 +721,10 @@ namespace Mono.CSharp @@ -720,10 +721,10 @@ namespace Mono.CSharp
protected override UsageVector Merge ()
{
for (UsageVector origin = return_origins; origin != null; origin = origin.Next)
Block.ParametersBlock.CheckOutParameters (origin, origin.Location);
Block.ParametersBlock.CheckOutParameters (origin);
UsageVector vector = base.Merge ();
Block.ParametersBlock.CheckOutParameters (vector, Block.loc);
Block.ParametersBlock.CheckOutParameters (vector);
// Note: we _do_not_ merge in the return origins
return vector;
}
@ -1066,8 +1067,7 @@ namespace Mono.CSharp @@ -1066,8 +1067,7 @@ namespace Mono.CSharp
}
// <summary>
// This is used by the flow analysis code to keep track of the type of local variables
// and variables.
// This is used by the flow analysis code to keep track of the type of local variables.
//
// The flow code uses a BitVector to keep track of whether a variable has been assigned
// or not. This is easy for fundamental types (int, char etc.) or reference types since
@ -1081,8 +1081,6 @@ namespace Mono.CSharp @@ -1081,8 +1081,6 @@ namespace Mono.CSharp
// </summary>
public class TypeInfo
{
public readonly TypeSpec Type;
// <summary>
// Total number of bits a variable of this type consumes in the flow vector.
// </summary>
@ -1102,7 +1100,7 @@ namespace Mono.CSharp @@ -1102,7 +1100,7 @@ namespace Mono.CSharp
// <summary>
// If this is a struct.
// </summary>
public readonly bool IsStruct;
public readonly bool IsStruct;
// <summary>
// If this is a struct, all fields which are structs theirselves.
@ -1111,6 +1109,8 @@ namespace Mono.CSharp @@ -1111,6 +1109,8 @@ namespace Mono.CSharp
readonly StructInfo struct_info;
private static Dictionary<TypeSpec, TypeInfo> type_hash;
static readonly TypeInfo simple_type = new TypeInfo (1);
static TypeInfo ()
{
@ -1123,34 +1123,11 @@ namespace Mono.CSharp @@ -1123,34 +1123,11 @@ namespace Mono.CSharp
StructInfo.field_type_hash = new Dictionary<TypeSpec, StructInfo> ();
}
public static TypeInfo GetTypeInfo (TypeSpec type)
TypeInfo (int totalLength)
{
TypeInfo info;
if (type_hash.TryGetValue (type, out info))
return info;
info = new TypeInfo (type);
type_hash.Add (type, info);
return info;
}
private TypeInfo (TypeSpec type)
{
this.Type = type;
struct_info = StructInfo.GetStructInfo (type);
if (struct_info != null) {
Length = struct_info.Length;
TotalLength = struct_info.TotalLength;
SubStructInfo = struct_info.StructFields;
IsStruct = true;
} else {
Length = 0;
TotalLength = 1;
IsStruct = false;
}
this.TotalLength = totalLength;
}
TypeInfo (StructInfo struct_info, int offset)
{
this.struct_info = struct_info;
@ -1158,10 +1135,9 @@ namespace Mono.CSharp @@ -1158,10 +1135,9 @@ namespace Mono.CSharp
this.Length = struct_info.Length;
this.TotalLength = struct_info.TotalLength;
this.SubStructInfo = struct_info.StructFields;
this.Type = struct_info.Type;
this.IsStruct = true;
}
public int GetFieldIndex (string name)
{
if (struct_info == null)
@ -1170,7 +1146,7 @@ namespace Mono.CSharp @@ -1170,7 +1146,7 @@ namespace Mono.CSharp
return struct_info [name];
}
public TypeInfo GetSubStruct (string name)
public TypeInfo GetStructField (string name)
{
if (struct_info == null)
return null;
@ -1178,6 +1154,26 @@ namespace Mono.CSharp @@ -1178,6 +1154,26 @@ namespace Mono.CSharp
return struct_info.GetStructField (name);
}
public static TypeInfo GetTypeInfo (TypeSpec type)
{
if (!type.IsStruct)
return simple_type;
TypeInfo info;
if (type_hash.TryGetValue (type, out info))
return info;
var struct_info = StructInfo.GetStructInfo (type);
if (struct_info != null) {
info = new TypeInfo (struct_info, 0);
} else {
info = simple_type;
}
type_hash.Add (type, info);
return info;
}
// <summary>
// A struct's constructor must always assign all fields.
// This method checks whether it actually does so.
@ -1192,11 +1188,7 @@ namespace Mono.CSharp @@ -1192,11 +1188,7 @@ namespace Mono.CSharp
for (int i = 0; i < struct_info.Count; i++) {
var field = struct_info.Fields [i];
// Fixed size buffers are not subject to definite assignment checking
if (field is FixedFieldSpec)
continue;
if (!branching.IsFieldAssigned (vi, field.Name)) {
if (!branching.IsStructFieldAssigned (vi, field.Name)) {
if (field.MemberDefinition is Property.BackingField) {
ec.Report.Error (843, loc,
"An automatically implemented property `{0}' must be fully assigned before control leaves the constructor. Consider calling the default struct contructor from a constructor initializer",
@ -1215,26 +1207,23 @@ namespace Mono.CSharp @@ -1215,26 +1207,23 @@ namespace Mono.CSharp
public override string ToString ()
{
return String.Format ("TypeInfo ({0}:{1}:{2}:{3})",
Type, Offset, Length, TotalLength);
return String.Format ("TypeInfo ({0}:{1}:{2})",
Offset, Length, TotalLength);
}
class StructInfo {
class StructInfo
{
public readonly TypeSpec Type;
public readonly FieldSpec[] Fields;
readonly List<FieldSpec> fields;
public readonly TypeInfo[] StructFields;
public readonly int Count;
public readonly int CountPublic;
public readonly int CountNonPublic;
public readonly int Length;
public readonly int TotalLength;
public readonly bool HasStructFields;
public static Dictionary<TypeSpec, StructInfo> field_type_hash;
private Dictionary<string, TypeInfo> struct_field_hash;
private Dictionary<string, int> field_hash;
protected bool InTransit = false;
protected bool InTransit;
// Private constructor. To save memory usage, we only need to create one instance
// of this class per struct type.
@ -1244,47 +1233,22 @@ namespace Mono.CSharp @@ -1244,47 +1233,22 @@ namespace Mono.CSharp
field_type_hash.Add (type, this);
TypeContainer tc = type.MemberDefinition as TypeContainer;
var public_fields = new List<FieldSpec> ();
var non_public_fields = new List<FieldSpec> ();
if (tc != null) {
var fields = tc.Fields;
if (fields != null) {
foreach (FieldBase field in fields) {
if ((field.ModFlags & Modifiers.STATIC) != 0)
continue;
if ((field.ModFlags & Modifiers.PUBLIC) != 0)
public_fields.Add (field.Spec);
else
non_public_fields.Add (field.Spec);
}
}
}
CountPublic = public_fields.Count;
CountNonPublic = non_public_fields.Count;
Count = CountPublic + CountNonPublic;
Fields = new FieldSpec[Count];
public_fields.CopyTo (Fields, 0);
non_public_fields.CopyTo (Fields, CountPublic);
fields = MemberCache.GetAllFieldsForDefiniteAssignment (type);
struct_field_hash = new Dictionary<string, TypeInfo> ();
field_hash = new Dictionary<string, int> ();
field_hash = new Dictionary<string, int> (fields.Count);
Length = 0;
StructFields = new TypeInfo [Count];
StructInfo[] sinfo = new StructInfo [Count];
StructFields = new TypeInfo[fields.Count];
StructInfo[] sinfo = new StructInfo[fields.Count];
InTransit = true;
for (int i = 0; i < Count; i++) {
var field = Fields [i];
for (int i = 0; i < fields.Count; i++) {
var field = fields [i];
if (field.MemberType.IsStruct)
sinfo [i] = GetStructInfo (field.MemberType);
sinfo [i] = GetStructInfo (field.MemberType);
if (sinfo [i] == null)
field_hash.Add (field.Name, ++Length);
else if (sinfo [i].InTransit) {
@ -1296,21 +1260,32 @@ namespace Mono.CSharp @@ -1296,21 +1260,32 @@ namespace Mono.CSharp
InTransit = false;
TotalLength = Length + 1;
for (int i = 0; i < Count; i++) {
var field = Fields [i];
for (int i = 0; i < fields.Count; i++) {
var field = fields [i];
if (sinfo [i] == null)
continue;
field_hash.Add (field.Name, TotalLength);
HasStructFields = true;
StructFields [i] = new TypeInfo (sinfo [i], TotalLength);
struct_field_hash.Add (field.Name, StructFields [i]);
TotalLength += sinfo [i].TotalLength;
}
}
public int Count {
get {
return fields.Count;
}
}
public List<FieldSpec> Fields {
get {
return fields;
}
}
public int this [string name] {
get {
int val;
@ -1332,7 +1307,7 @@ namespace Mono.CSharp @@ -1332,7 +1307,7 @@ namespace Mono.CSharp
public static StructInfo GetStructInfo (TypeSpec type)
{
if (!type.IsStruct || type.BuiltinType > 0)
if (type.BuiltinType > 0)
return null;
StructInfo info;
@ -1351,13 +1326,13 @@ namespace Mono.CSharp @@ -1351,13 +1326,13 @@ namespace Mono.CSharp
// it has been assigned or not, but for structs, we need this information for each of its fields.
// </summary>
public class VariableInfo {
public readonly string Name;
readonly string Name;
public readonly TypeInfo TypeInfo;
// <summary>
// The bit offset of this variable in the flow vector.
// </summary>
public readonly int Offset;
readonly int Offset;
// <summary>
// The number of bits this variable needs in the flow vector.
@ -1371,16 +1346,8 @@ namespace Mono.CSharp @@ -1371,16 +1346,8 @@ namespace Mono.CSharp
// </summary>
public readonly bool IsParameter;
public readonly LocalVariable LocalInfo;
readonly VariableInfo Parent;
VariableInfo[] sub_info;
bool is_ever_assigned;
public bool IsEverAssigned {
get { return is_ever_assigned; }
}
protected VariableInfo (string name, TypeSpec type, int offset)
{
this.Name = name;
@ -1397,11 +1364,9 @@ namespace Mono.CSharp @@ -1397,11 +1364,9 @@ namespace Mono.CSharp
this.Name = parent.Name;
this.TypeInfo = type;
this.Offset = parent.Offset + type.Offset;
this.Parent = parent;
this.Length = type.TotalLength;
this.IsParameter = parent.IsParameter;
this.LocalInfo = parent.LocalInfo;
Initialize ();
}
@ -1422,7 +1387,6 @@ namespace Mono.CSharp @@ -1422,7 +1387,6 @@ namespace Mono.CSharp
public VariableInfo (LocalVariable local_info, int offset)
: this (local_info.Name, local_info.Type, offset)
{
this.LocalInfo = local_info;
this.IsParameter = false;
}
@ -1434,20 +1398,7 @@ namespace Mono.CSharp @@ -1434,20 +1398,7 @@ namespace Mono.CSharp
public bool IsAssigned (ResolveContext ec)
{
return !ec.DoFlowAnalysis ||
(ec.OmitStructFlowAnalysis && TypeInfo.Type.IsStruct) ||
ec.CurrentBranching.IsAssigned (this);
}
public bool IsAssigned (ResolveContext ec, Location loc)
{
if (IsAssigned (ec))
return true;
ec.Report.Error (165, loc,
"Use of unassigned local variable `" + Name + "'");
ec.CurrentBranching.SetAssigned (this);
return false;
return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (this);
}
public bool IsAssigned (MyBitVector vector)
@ -1458,69 +1409,49 @@ namespace Mono.CSharp @@ -1458,69 +1409,49 @@ namespace Mono.CSharp
if (vector [Offset])
return true;
// FIXME: Fix SetFieldAssigned to set the whole range like SetAssigned below. Then, get rid of this stanza
for (VariableInfo parent = Parent; parent != null; parent = parent.Parent) {
if (vector [parent.Offset]) {
// 'parent' is assigned, but someone forgot to note that all its components are assigned too
parent.SetAssigned (vector);
return true;
}
}
// Return unless this is a struct.
// Unless this is a struct
if (!TypeInfo.IsStruct)
return false;
// Ok, so each field must be assigned.
for (int i = 0; i < TypeInfo.Length; i++) {
if (!vector [Offset + i + 1])
//
// Following case cannot be handled fully by SetStructFieldAssigned
// because we may encounter following case
//
// struct A { B b }
// struct B { int value; }
//
// setting a.b.value is propagated only to B's vector and not upwards to possible parents
//
//
// Each field must be assigned
//
for (int i = Offset + 1; i <= TypeInfo.Length + Offset; i++) {
if (!vector[i])
return false;
}
// Ok, now check all fields which are structs.
for (int i = 0; i < sub_info.Length; i++) {
VariableInfo sinfo = sub_info [i];
VariableInfo sinfo = sub_info[i];
if (sinfo == null)
continue;
if (!sinfo.IsAssigned (vector))
return false;
}
vector [Offset] = true;
is_ever_assigned = true;
return true;
}
public void SetAssigned (ResolveContext ec)
{
if (ec.DoFlowAnalysis)
ec.CurrentBranching.SetAssigned (this);
}
public bool IsEverAssigned { get; set; }
public void SetAssigned (MyBitVector vector)
public bool IsStructFieldAssigned (ResolveContext ec, string name)
{
if (Length == 1)
vector [Offset] = true;
else
vector.SetRange (Offset, Length);
is_ever_assigned = true;
return !ec.DoFlowAnalysis || ec.CurrentBranching.IsStructFieldAssigned (this, name);
}
public bool IsFieldAssigned (ResolveContext ec, string name, Location loc)
{
if (!ec.DoFlowAnalysis ||
ec.OmitStructFlowAnalysis && TypeInfo.IsStruct ||
ec.CurrentBranching.IsFieldAssigned (this, name))
return true;
ec.Report.Error (170, loc,
"Use of possibly unassigned field `" + name + "'");
ec.CurrentBranching.SetFieldAssigned (this, name);
return false;
}
public bool IsFieldAssigned (MyBitVector vector, string field_name)
public bool IsStructFieldAssigned (MyBitVector vector, string field_name)
{
int field_idx = TypeInfo.GetFieldIndex (field_name);
@ -1530,26 +1461,65 @@ namespace Mono.CSharp @@ -1530,26 +1461,65 @@ namespace Mono.CSharp
return vector [Offset + field_idx];
}
public void SetFieldAssigned (ResolveContext ec, string name)
public void SetStructFieldAssigned (ResolveContext ec, string name)
{
if (ec.DoFlowAnalysis)
ec.CurrentBranching.SetFieldAssigned (this, name);
}
public void SetFieldAssigned (MyBitVector vector, string field_name)
public void SetAssigned (ResolveContext ec)
{
if (ec.DoFlowAnalysis)
ec.CurrentBranching.SetAssigned (this);
}
public void SetAssigned (MyBitVector vector)
{
if (Length == 1)
vector[Offset] = true;
else
vector.SetRange (Offset, Length);
IsEverAssigned = true;
}
public void SetStructFieldAssigned (MyBitVector vector, string field_name)
{
if (vector[Offset])
return;
int field_idx = TypeInfo.GetFieldIndex (field_name);
if (field_idx == 0)
return;
vector [Offset + field_idx] = true;
is_ever_assigned = true;
var complex_field = TypeInfo.GetStructField (field_name);
if (complex_field != null) {
vector.SetRange (complex_field.Offset, complex_field.TotalLength);
} else {
vector[Offset + field_idx] = true;
}
IsEverAssigned = true;
//
// Each field must be assigned
//
for (int i = Offset + 1; i <= TypeInfo.TotalLength + Offset; i++) {
if (!vector[i])
return;
}
//
// Set master struct flag to assigned when all tested struct
// fields have been assigned
//
vector[Offset] = true;
}
public VariableInfo GetSubStruct (string name)
public VariableInfo GetStructFieldInfo (string fieldName)
{
TypeInfo type = TypeInfo.GetSubStruct (name);
TypeInfo type = TypeInfo.GetStructField (fieldName);
if (type == null)
return null;

191
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/generic.cs

@ -129,10 +129,15 @@ namespace Mono.CSharp { @@ -129,10 +129,15 @@ namespace Mono.CSharp {
if (TypeSpec.IsBaseClass (ba, bb, false) || TypeSpec.IsBaseClass (bb, ba, false))
return true;
Error_ConflictingConstraints (context, spec, ba, bb, loc);
return false;
}
public static void Error_ConflictingConstraints (IMemberContext context, TypeParameterSpec tp, TypeSpec ba, TypeSpec bb, Location loc)
{
context.Module.Compiler.Report.Error (455, loc,
"Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'",
spec.Name, ba.GetSignatureForError (), bb.GetSignatureForError ());
return false;
tp.Name, ba.GetSignatureForError (), bb.GetSignatureForError ());
}
public void CheckGenericConstraints (IMemberContext context, bool obsoleteCheck)
@ -808,7 +813,17 @@ namespace Mono.CSharp { @@ -808,7 +813,17 @@ namespace Mono.CSharp {
// class A : B<int> { override void Foo<U> () {} }
// class B<T> { virtual void Foo<U> () where U : T {} }
//
return HasSpecialStruct || TypeSpec.IsValueType (BaseType);
if (HasSpecialStruct)
return true;
if (targs != null) {
foreach (var ta in targs) {
if (TypeSpec.IsValueType (ta))
return true;
}
}
return false;
}
}
@ -853,21 +868,6 @@ namespace Mono.CSharp { @@ -853,21 +868,6 @@ namespace Mono.CSharp {
#endregion
public void ChangeTypeArgumentToBaseType (int index)
{
BaseType = targs [index];
if (targs.Length == 1) {
targs = null;
} else {
var copy = new TypeSpec[targs.Length - 1];
if (index > 0)
Array.Copy (targs, copy, index);
Array.Copy (targs, index + 1, copy, index, targs.Length - index - 1);
targs = copy;
}
}
public string DisplayDebugInfo ()
{
var s = GetSignatureForError ();
@ -900,11 +900,18 @@ namespace Mono.CSharp { @@ -900,11 +900,18 @@ namespace Mono.CSharp {
var types = targs;
if (HasTypeConstraint) {
Array.Resize (ref types, types.Length + 1);
for (int i = 0; i < types.Length - 1; ++i) {
types[i] = types[i].BaseType;
}
types[types.Length - 1] = BaseType;
} else {
types = types.Select (l => l.BaseType).ToArray ();
}
if (types != null)
return Convert.FindMostEncompassedType (types.Select (l => l.BaseType));
return Convert.FindMostEncompassedType (types);
return BaseType;
}
@ -1785,6 +1792,16 @@ namespace Mono.CSharp { @@ -1785,6 +1792,16 @@ namespace Mono.CSharp {
BaseType = inflator.Inflate (open_type.BaseType);
}
} else if ((state & StateFlags.PendingBaseTypeInflate) != 0) {
//
// It can happen when resolving base type without being defined
// which is not allowed to happen and will always lead to an error
//
// class B { class N {} }
// class A<T> : A<B.N> {}
//
if (open_type.BaseType == null)
return;
BaseType = inflator.Inflate (open_type.BaseType);
state &= ~StateFlags.PendingBaseTypeInflate;
}
@ -2246,35 +2263,25 @@ namespace Mono.CSharp { @@ -2246,35 +2263,25 @@ namespace Mono.CSharp {
// Check the interfaces constraints
//
if (tparam.Interfaces != null) {
if (atype.IsNullableType) {
if (mc == null)
return false;
foreach (TypeSpec iface in tparam.Interfaces) {
var dep = iface.GetMissingDependencies ();
if (dep != null) {
if (mc == null)
return false;
mc.Module.Compiler.Report.Error (313, loc,
"The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. The nullable type `{0}' never satisfies interface constraint",
atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError ());
ok = false;
} else {
foreach (TypeSpec iface in tparam.Interfaces) {
var dep = iface.GetMissingDependencies ();
if (dep != null) {
if (mc == null)
return false;
ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc);
ok = false;
ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc);
ok = false;
// return immediately to avoid duplicate errors because we are scanning
// expanded interface list
return false;
}
// return immediately to avoid duplicate errors because we are scanning
// expanded interface list
if (!CheckConversion (mc, context, atype, tparam, iface, loc)) {
if (mc == null)
return false;
}
if (!CheckConversion (mc, context, atype, tparam, iface, loc)) {
if (mc == null)
return false;
ok = false;
}
ok = false;
}
}
}
@ -2333,24 +2340,29 @@ namespace Mono.CSharp { @@ -2333,24 +2340,29 @@ namespace Mono.CSharp {
if (atype.IsGenericParameter) {
var tps = (TypeParameterSpec) atype;
if (Convert.ImplicitTypeParameterConversion (null, tps, ttype) != null)
return true;
if (tps.TypeArguments != null) {
foreach (var targ in tps.TypeArguments) {
if (TypeSpecComparer.Override.IsEqual (targ, ttype))
return true;
}
}
//
// LAMESPEC: Identity conversion with inflated type parameter
// It's not clear from the spec what rule should apply to inherited
// inflated type parameter. The specification allows only type parameter
// conversion but that's clearly not enough
//
if (tps.HasTypeConstraint && tps.BaseType == ttype)
if (Convert.ImplicitTypeParameterConversion (null, tps, ttype) != null)
return true;
} else if (TypeSpec.IsValueType (atype)) {
if (Convert.ImplicitBoxingConversion (null, atype, ttype) != null)
return true;
if (atype.IsNullableType) {
//
// LAMESPEC: Only identity or base type ValueType or Object satisfy nullable type
//
if (TypeSpec.IsBaseClass (atype, ttype, false))
return true;
} else {
if (Convert.ImplicitBoxingConversion (null, atype, ttype) != null)
return true;
}
} else {
var expr = new EmptyExpression (atype);
if (Convert.ImplicitStandardConversionExists (expr, ttype))
if (Convert.ImplicitReferenceConversionExists (atype, ttype) || Convert.ImplicitBoxingConversion (null, atype, ttype) != null)
return true;
}
@ -2369,9 +2381,21 @@ namespace Mono.CSharp { @@ -2369,9 +2381,21 @@ namespace Mono.CSharp {
"The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing or type parameter conversion from `{0}' to `{3}'",
atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
} else if (TypeSpec.IsValueType (atype)) {
mc.Module.Compiler.Report.Error (315, loc,
"The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing conversion from `{0}' to `{3}'",
atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
if (atype.IsNullableType) {
if (ttype.IsInterface) {
mc.Module.Compiler.Report.Error (313, loc,
"The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. The nullable type `{0}' never satisfies interface constraint `{3}'",
atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
} else {
mc.Module.Compiler.Report.Error (312, loc,
"The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. The nullable type `{0}' does not satisfy constraint `{3}'",
atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
}
} else {
mc.Module.Compiler.Report.Error (315, loc,
"The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing conversion from `{0}' to `{3}'",
atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
}
} else {
mc.Module.Compiler.Report.Error (311, loc,
"The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no implicit reference conversion from `{0}' to `{3}'",
@ -2690,7 +2714,7 @@ namespace Mono.CSharp { @@ -2690,7 +2714,7 @@ namespace Mono.CSharp {
// Align params arguments
TypeSpec t_i = methodParameters [i >= methodParameters.Length ? methodParameters.Length - 1: i];
if (!TypeManager.IsDelegateType (t_i)) {
if (!t_i.IsDelegate) {
if (!t_i.IsExpressionTreeType)
continue;
@ -2700,8 +2724,13 @@ namespace Mono.CSharp { @@ -2700,8 +2724,13 @@ namespace Mono.CSharp {
var mi = Delegate.GetInvokeMethod (t_i);
TypeSpec rtype = mi.ReturnType;
if (tic.IsReturnTypeNonDependent (ec, mi, rtype))
score -= tic.OutputTypeInference (ec, arguments [i].Expr, t_i);
if (tic.IsReturnTypeNonDependent (ec, mi, rtype)) {
// It can be null for default arguments
if (arguments[i] == null)
continue;
score -= tic.OutputTypeInference (ec, arguments[i].Expr, t_i);
}
}
@ -2920,7 +2949,7 @@ namespace Mono.CSharp { @@ -2920,7 +2949,7 @@ namespace Mono.CSharp {
for (int i = 0; i < methodParameters.Length; ++i) {
TypeSpec t = methodParameters[i];
if (!TypeManager.IsDelegateType (t)) {
if (!t.IsDelegate) {
if (!t.IsExpressionTreeType)
continue;
@ -3127,6 +3156,13 @@ namespace Mono.CSharp { @@ -3127,6 +3156,13 @@ namespace Mono.CSharp {
return gt.GetDefinition ().MakeGenericType (context, inflated_targs);
}
var ac = parameter as ArrayContainer;
if (ac != null) {
var inflated = InflateGenericArgument (context, ac.Element);
if (inflated != ac.Element)
return ArrayContainer.MakeType (context.Module, inflated);
}
return parameter;
}
@ -3143,7 +3179,7 @@ namespace Mono.CSharp { @@ -3143,7 +3179,7 @@ namespace Mono.CSharp {
if (IsFixed (returnType))
return false;
} else if (TypeManager.IsGenericType (returnType)) {
if (TypeManager.IsDelegateType (returnType)) {
if (returnType.IsDelegate) {
invoke = Delegate.GetInvokeMethod (returnType);
return IsReturnTypeNonDependent (ec, invoke, invoke.ReturnType);
}
@ -3228,7 +3264,7 @@ namespace Mono.CSharp { @@ -3228,7 +3264,7 @@ namespace Mono.CSharp {
return LowerBoundInference (u_ac.Element, v_i);
}
if (TypeManager.IsGenericType (v)) {
if (v.IsGenericOrParentIsGeneric) {
//
// if V is a constructed type C<V1..Vk> and there is a unique type C<U1..Uk>
// such that U is identical to, inherits from (directly or indirectly),
@ -3256,8 +3292,8 @@ namespace Mono.CSharp { @@ -3256,8 +3292,8 @@ namespace Mono.CSharp {
}
}
TypeSpec [] unique_candidate_targs = null;
TypeSpec[] ga_v = TypeManager.GetTypeArguments (v);
TypeSpec[] unique_candidate_targs = null;
var ga_v = TypeSpec.GetAllTypeArguments (v);
foreach (TypeSpec u_candidate in u_candidates) {
//
// The unique set of types U1..Uk means that if we have an interface I<T>,
@ -3265,7 +3301,7 @@ namespace Mono.CSharp { @@ -3265,7 +3301,7 @@ namespace Mono.CSharp {
// type I<T> by applying type U because T could be int or long
//
if (unique_candidate_targs != null) {
TypeSpec[] second_unique_candidate_targs = TypeManager.GetTypeArguments (u_candidate);
TypeSpec[] second_unique_candidate_targs = TypeSpec.GetAllTypeArguments (u_candidate);
if (TypeSpecComparer.Equals (unique_candidate_targs, second_unique_candidate_targs)) {
unique_candidate_targs = second_unique_candidate_targs;
continue;
@ -3291,15 +3327,25 @@ namespace Mono.CSharp { @@ -3291,15 +3327,25 @@ namespace Mono.CSharp {
for (int i = 0; i < unique_candidate_targs.Length; ++i)
unique_candidate_targs[i] = u_candidate;
} else {
unique_candidate_targs = TypeManager.GetTypeArguments (u_candidate);
unique_candidate_targs = TypeSpec.GetAllTypeArguments (u_candidate);
}
}
if (unique_candidate_targs != null) {
var ga_open_v = open_v.TypeParameters;
int score = 0;
int tp_index = -1;
TypeParameterSpec[] tps = null;
for (int i = 0; i < unique_candidate_targs.Length; ++i) {
Variance variance = ga_open_v [i].Variance;
if (tp_index < 0) {
while (v.Arity == 0)
v = v.DeclaringType;
tps = v.MemberDefinition.TypeParameters;
tp_index = tps.Length - 1;
}
Variance variance = tps [tp_index--].Variance;
TypeSpec u_i = unique_candidate_targs [i];
if (variance == Variance.None || TypeSpec.IsValueType (u_i)) {
@ -3313,6 +3359,7 @@ namespace Mono.CSharp { @@ -3313,6 +3359,7 @@ namespace Mono.CSharp {
++score;
}
}
return score;
}
}
@ -3347,7 +3394,7 @@ namespace Mono.CSharp { @@ -3347,7 +3394,7 @@ namespace Mono.CSharp {
// then a lower-bound inference is made from U for Tb.
//
if (e is MethodGroupExpr) {
if (!TypeManager.IsDelegateType (t)) {
if (!t.IsDelegate) {
if (!t.IsExpressionTreeType)
return 0;

11
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/import.cs

@ -169,7 +169,8 @@ namespace Mono.CSharp @@ -169,7 +169,8 @@ namespace Mono.CSharp
break;
default:
// Ignore private fields (even for error reporting) to not require extra dependencies
if (IgnorePrivateMembers || HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
if ((IgnorePrivateMembers && !declaringType.IsStruct) ||
HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
return null;
mod = Modifiers.PRIVATE;
@ -1887,7 +1888,13 @@ namespace Mono.CSharp @@ -1887,7 +1888,13 @@ namespace Mono.CSharp
if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers)
continue;
imported = importer.CreateNestedType (t, declaringType);
try {
imported = importer.CreateNestedType (t, declaringType);
} catch (Exception e) {
throw new InternalErrorException (e, "Could not import nested type `{0}' from `{1}'",
t.FullName, declaringType.MemberDefinition.DeclaringAssembly.FullName);
}
cache.AddMemberImported (imported);
}

12
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/iterators.cs

@ -158,7 +158,6 @@ namespace Mono.CSharp @@ -158,7 +158,6 @@ namespace Mono.CSharp
}
Field pc_field;
int local_name_idx;
StateMachineMethod method;
protected StateMachine (Block block, TypeContainer parent, MemberBase host, TypeParameter[] tparams, string name)
@ -197,11 +196,6 @@ namespace Mono.CSharp @@ -197,11 +196,6 @@ namespace Mono.CSharp
return base.DoDefineMembers ();
}
protected override string GetVariableMangledName (LocalVariable local_info)
{
return "<" + local_info.Name + ">__" + local_name_idx++.ToString ("X");
}
}
class IteratorStorey : StateMachine
@ -390,6 +384,7 @@ namespace Mono.CSharp @@ -390,6 +384,7 @@ namespace Mono.CSharp
TypeExpr iterator_type_expr;
Field current_field;
Field disposing_field;
int local_name_idx;
TypeExpr enumerator_type;
TypeExpr enumerable_type;
@ -563,6 +558,11 @@ namespace Mono.CSharp @@ -563,6 +558,11 @@ namespace Mono.CSharp
base.EmitHoistedParameters (ec, hoisted);
base.EmitHoistedParameters (ec, hoisted_params_copy);
}
protected override string GetVariableMangledName (LocalVariable local_info)
{
return "<" + local_info.Name + ">__" + local_name_idx++.ToString ("X");
}
}
public class StateMachineMethod : Method

1
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/lambda.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright 2007-2008 Novell, Inc
// Copyright 2011 Xamarin Inc
//
#if STATIC

7
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/linq.cs

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright 2007-2008 Novell, Inc
// Copyright 2011 Xamarin Inc
//
using System;
@ -352,6 +353,12 @@ namespace Mono.CSharp.Linq @@ -352,6 +353,12 @@ namespace Mono.CSharp.Linq
}
}
public bool IsParameter {
get {
return false;
}
}
public Location Location { get; private set; }
public string Name { get; private set; }

3
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/literal.cs

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
// Marek Safar (marek.safar@seznam.cz)
//
// Copyright 2001 Ximian, Inc.
// Copyright 2011 Xamarin Inc
//
//
// Notice that during parsing we create objects of type Literal, but the
@ -126,7 +127,7 @@ namespace Mono.CSharp @@ -126,7 +127,7 @@ namespace Mono.CSharp
//
// The 0 literal can be converted to an enum value
//
if (Value == 0 && TypeManager.IsEnumType (type)) {
if (Value == 0 && type.IsEnum) {
Constant c = ConvertImplicitly (EnumSpec.GetUnderlyingType (type));
if (c == null)
return null;

10
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/location.cs

@ -477,7 +477,8 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format (" @@ -477,7 +477,8 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("
{
Single,
Multi,
Documentation
Documentation,
InactiveCode
}
public class Comment
@ -545,6 +546,7 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format (" @@ -545,6 +546,7 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("
[Conditional ("FULL_AST")]
public void StartComment (CommentType type, bool startsLine, int startLine, int startCol)
{
inComment = true;
curComment = type;
this.startsLine = startsLine;
this.startLine = startLine;
@ -565,15 +567,21 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format (" @@ -565,15 +567,21 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("
contentBuilder.Append (str);
}
bool inComment;
[Conditional ("FULL_AST")]
public void EndComment (int endLine, int endColumn)
{
if (!inComment)
return;
inComment = false;
Specials.Add (new Comment (curComment, startsLine, startLine, startCol, endLine, endColumn, contentBuilder.ToString ()));
}
[Conditional ("FULL_AST")]
public void AddPreProcessorDirective (int startLine, int startCol, int endLine, int endColumn, Tokenizer.PreprocessorDirective cmd, string arg)
{
if (inComment)
EndComment (startLine, startCol);
Specials.Add (new PreProcessorDirective (startLine, startCol, endLine, endColumn, cmd, arg));
}

116
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/membercache.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
//
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2010 Novell, Inc
// Copyright 2011 Xamarin Inc
//
//
@ -684,6 +685,44 @@ namespace Mono.CSharp { @@ -684,6 +685,44 @@ namespace Mono.CSharp {
throw new NotImplementedException (member.GetType ().ToString ());
}
public static List<FieldSpec> GetAllFieldsForDefiniteAssignment (TypeSpec container)
{
List<FieldSpec> fields = null;
foreach (var entry in container.MemberCache.member_hash) {
foreach (var name_entry in entry.Value) {
if (name_entry.Kind != MemberKind.Field)
continue;
if ((name_entry.Modifiers & Modifiers.STATIC) != 0)
continue;
//
// Fixed size buffers are not subject to definite assignment checking
//
if (name_entry is FixedFieldSpec || name_entry is ConstSpec)
continue;
var fs = (FieldSpec) name_entry;
//
// LAMESPEC: Very bizzare hack, definitive assignment is not done
// for imported non-public reference fields except array. No idea what the
// actual csc rule is
//
if (!fs.IsPublic && container.MemberDefinition.IsImported && (!fs.MemberType.IsArray && TypeSpec.IsReferenceType (fs.MemberType)))
continue;
if (fields == null)
fields = new List<FieldSpec> ();
fields.Add (fs);
break;
}
}
return fields ?? new List<FieldSpec> (0);
}
public static IList<MemberSpec> GetCompletitionMembers (IMemberContext ctx, TypeSpec container, string name)
{
var matches = new List<MemberSpec> ();
@ -1139,10 +1178,14 @@ namespace Mono.CSharp { @@ -1139,10 +1178,14 @@ namespace Mono.CSharp {
if (name_entry.MemberDefinition.CLSAttributeValue == false)
continue;
IParametersMember p_a = name_entry as IParametersMember;
if (p_a != null && !name_entry.IsAccessor) {
if (!is_imported_type) {
IParametersMember p_a = null;
if (!is_imported_type) {
p_a = name_entry as IParametersMember;
if (p_a != null && !name_entry.IsAccessor) {
var p_a_pd = p_a.Parameters;
//
// Check differing overloads in @container
//
for (int ii = i + 1; ii < entry.Value.Count; ++ii) {
var checked_entry = entry.Value[ii];
IParametersMember p_b = checked_entry as IParametersMember;
@ -1157,24 +1200,7 @@ namespace Mono.CSharp { @@ -1157,24 +1200,7 @@ namespace Mono.CSharp {
var res = ParametersCompiled.IsSameClsSignature (p_a.Parameters, p_b.Parameters);
if (res != 0) {
var last = GetLaterDefinedMember (checked_entry, name_entry);
if (last == checked_entry.MemberDefinition) {
report.SymbolRelatedToPreviousError (name_entry);
} else {
report.SymbolRelatedToPreviousError (checked_entry);
}
if ((res & 1) != 0) {
report.Warning (3006, 1, last.Location,
"Overloaded method `{0}' differing only in ref or out, or in array rank, is not CLS-compliant",
name_entry.GetSignatureForError ());
}
if ((res & 2) != 0) {
report.Warning (3007, 1, last.Location,
"Overloaded method `{0}' differing only by unnamed array types is not CLS-compliant",
name_entry.GetSignatureForError ());
}
ReportOverloadedMethodClsDifference (name_entry, checked_entry, res, report);
}
}
}
@ -1192,11 +1218,26 @@ namespace Mono.CSharp { @@ -1192,11 +1218,26 @@ namespace Mono.CSharp {
} else {
bool same_names_only = true;
foreach (var f in found) {
if (f.Name == name_entry.Name)
continue;
if (f.Name == name_entry.Name) {
if (p_a != null) {
IParametersMember p_b = f as IParametersMember;
if (p_b == null)
continue;
// if (f.IsAccessor && name_entry.IsAccessor)
// continue;
if (p_a.Parameters.Count != p_b.Parameters.Count)
continue;
if (f.IsAccessor)
continue;
var res = ParametersCompiled.IsSameClsSignature (p_a.Parameters, p_b.Parameters);
if (res != 0) {
ReportOverloadedMethodClsDifference (f, name_entry, res, report);
}
}
continue;
}
same_names_only = false;
if (!is_imported_type) {
@ -1235,12 +1276,37 @@ namespace Mono.CSharp { @@ -1235,12 +1276,37 @@ namespace Mono.CSharp {
if (mc_b == null)
return mc_a;
if (a.DeclaringType.MemberDefinition != b.DeclaringType.MemberDefinition)
return mc_b;
if (mc_a.Location.File != mc_a.Location.File)
return mc_b;
return mc_b.Location.Row > mc_a.Location.Row ? mc_b : mc_a;
}
static void ReportOverloadedMethodClsDifference (MemberSpec a, MemberSpec b, int res, Report report)
{
var last = GetLaterDefinedMember (a, b);
if (last == a.MemberDefinition) {
report.SymbolRelatedToPreviousError (b);
} else {
report.SymbolRelatedToPreviousError (a);
}
if ((res & 1) != 0) {
report.Warning (3006, 1, last.Location,
"Overloaded method `{0}' differing only in ref or out, or in array rank, is not CLS-compliant",
last.GetSignatureForError ());
}
if ((res & 2) != 0) {
report.Warning (3007, 1, last.Location,
"Overloaded method `{0}' differing only by unnamed array types is not CLS-compliant",
last.GetSignatureForError ());
}
}
public bool CheckExistingMembersOverloads (MemberCore member, AParametersCollection parameters)
{
var name = GetLookupName (member);

114
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/method.cs

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
//
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2008 Novell, Inc
// Copyright 2011 Xamarin Inc.
//
using System;
@ -898,6 +899,42 @@ namespace Mono.CSharp { @@ -898,6 +899,42 @@ namespace Mono.CSharp {
#endregion
public static Method Create (DeclSpace parent, GenericMethod generic, FullNamedExpression returnType, Modifiers mod,
MemberName name, ParametersCompiled parameters, Attributes attrs, bool hasConstraints)
{
var m = new Method (parent, generic, returnType, mod, name, parameters, attrs);
if (hasConstraints && ((mod & Modifiers.OVERRIDE) != 0 || m.IsExplicitImpl)) {
m.Report.Error (460, m.Location,
"`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
m.GetSignatureForError ());
}
if ((mod & Modifiers.PARTIAL) != 0) {
const Modifiers invalid_partial_mod = Modifiers.AccessibilityMask | Modifiers.ABSTRACT | Modifiers.EXTERN |
Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.SEALED | Modifiers.VIRTUAL;
if ((mod & invalid_partial_mod) != 0) {
m.Report.Error (750, m.Location,
"A partial method cannot define access modifier or any of abstract, extern, new, override, sealed, or virtual modifiers");
mod &= ~invalid_partial_mod;
}
if ((parent.ModFlags & Modifiers.PARTIAL) == 0) {
m.Report.Error (751, m.Location,
"A partial method must be declared within a partial class or partial struct");
}
}
if ((mod & Modifiers.STATIC) == 0 && parameters.HasExtensionMethodType) {
m.Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static",
m.GetSignatureForError ());
}
return m;
}
public override string GetSignatureForError()
{
return base.GetSignatureForError () + parameters.GetSignatureForError ();
@ -1066,7 +1103,7 @@ namespace Mono.CSharp { @@ -1066,7 +1103,7 @@ namespace Mono.CSharp {
base_tparam.InflateConstraints (inflator, local_tparam);
//
// Check all type argument constraints for possible collision
// Check all type argument constraints for possible collision or unification
// introduced by inflating inherited constraints in this context
//
// Conflict example:
@ -1075,31 +1112,67 @@ namespace Mono.CSharp { @@ -1075,31 +1112,67 @@ namespace Mono.CSharp {
// class B : A<int> { override void Foo<U> {} }
//
var local_tparam_targs = local_tparam.TypeArguments;
if (local_tparam_targs != null) {
if (local_tparam_targs != null) {
for (int ii = 0; ii < local_tparam_targs.Length; ++ii) {
var ta = local_tparam_targs [ii];
if (!ta.IsClass && !ta.IsStruct)
continue;
if (Constraints.CheckConflictingInheritedConstraint (local_tparam, ta, this, Location)) {
local_tparam.ChangeTypeArgumentToBaseType (ii);
TypeSpec[] unique_tparams = null;
for (int iii = ii + 1; iii < local_tparam_targs.Length; ++iii) {
//
// Remove any identical or unified constraint types
//
var tparam_checked = local_tparam_targs[iii];
if (TypeSpecComparer.IsEqual (ta, tparam_checked) || TypeSpec.IsBaseClass (ta, tparam_checked, false)) {
unique_tparams = new TypeSpec[local_tparam_targs.Length - 1];
Array.Copy (local_tparam_targs, 0, unique_tparams, 0, iii);
Array.Copy (local_tparam_targs, iii + 1, unique_tparams, iii, local_tparam_targs.Length - iii - 1);
} else if (!TypeSpec.IsBaseClass (tparam_checked, ta, false)) {
Constraints.Error_ConflictingConstraints (this, local_tparam, ta, tparam_checked, Location);
}
}
if (unique_tparams != null) {
local_tparam_targs = unique_tparams;
local_tparam.TypeArguments = local_tparam_targs;
continue;
}
Constraints.CheckConflictingInheritedConstraint (local_tparam, ta, this, Location);
}
}
continue;
}
if (MethodData != null && MethodData.implementing != null) {
var base_tp = MethodData.implementing.Constraints[i];
if (!tp.Type.HasSameConstraintsImplementation (base_tp)) {
Report.SymbolRelatedToPreviousError (MethodData.implementing);
Report.Error (425, Location,
"The constraints for type parameter `{0}' of method `{1}' must match the constraints for type parameter `{2}' of interface method `{3}'. Consider using an explicit interface implementation instead",
tp.GetSignatureForError (), GetSignatureForError (), base_tp.GetSignatureForError (), MethodData.implementing.GetSignatureForError ());
}
}
if (base_tparams == null && MethodData != null && MethodData.implementing != null) {
CheckImplementingMethodConstraints (Parent, spec, MethodData.implementing);
}
}
public static bool CheckImplementingMethodConstraints (TypeContainer container, MethodSpec method, MethodSpec baseMethod)
{
var tparams = method.Constraints;
var base_tparams = baseMethod.Constraints;
for (int i = 0; i < tparams.Length; ++i) {
if (!tparams[i].HasSameConstraintsImplementation (base_tparams[i])) {
container.Compiler.Report.SymbolRelatedToPreviousError (method);
container.Compiler.Report.SymbolRelatedToPreviousError (baseMethod);
// Using container location because the interface can be implemented
// by base class
container.Compiler.Report.Error (425, container.Location,
"The constraints for type parameter `{0}' of method `{1}' must match the constraints for type parameter `{2}' of interface method `{3}'. Consider using an explicit interface implementation instead",
tparams[i].GetSignatureForError (), method.GetSignatureForError (),
base_tparams[i].GetSignatureForError (), baseMethod.GetSignatureForError ());
return false;
}
}
return true;
}
public override void Accept (StructuralVisitor visitor)
@ -1151,6 +1224,12 @@ namespace Mono.CSharp { @@ -1151,6 +1224,12 @@ namespace Mono.CSharp {
}
if ((ModFlags & Modifiers.ASYNC) != 0) {
if (ReturnType.Kind != MemberKind.Void &&
ReturnType != Module.PredefinedTypes.Task.TypeSpec &&
!ReturnType.IsGenericTask) {
Report.Error (1983, Location, "The return type of an async method must be void, Task, or Task<T>");
}
AsyncInitializer.Create (this, block, parameters, Parent.PartialContainer, ReturnType, Location);
}
}
@ -1167,7 +1246,7 @@ namespace Mono.CSharp { @@ -1167,7 +1246,7 @@ namespace Mono.CSharp {
PredefinedAttribute pa = Module.PredefinedAttributes.Extension;
if (!pa.IsDefined) {
Report.Error (1110, Location,
"`{0}': Extension methods cannot be declared without a reference to System.Core.dll assembly. Add the assembly reference or remove `this' modifer from the first parameter",
"`{0}': Extension methods require `System.Runtime.CompilerServices.ExtensionAttribute' type to be available. Are you missing an assembly reference?",
GetSignatureForError ());
}
@ -1191,6 +1270,9 @@ namespace Mono.CSharp { @@ -1191,6 +1270,9 @@ namespace Mono.CSharp {
if (Parent.IsGeneric || MemberName.IsGeneric) {
Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
GetSignatureForError ());
} else if ((ModFlags & Modifiers.ASYNC) != 0) {
Report.Error (4009, Location, "`{0}': an entry point cannot be async method",
GetSignatureForError ());
} else {
SetIsUsed ();
Parent.DeclaringAssembly.EntryPoint = this;
@ -1621,9 +1703,9 @@ namespace Mono.CSharp { @@ -1621,9 +1703,9 @@ namespace Mono.CSharp {
// initializer, it must initialize all of the struct's fields.
if ((Parent.PartialContainer.Kind == MemberKind.Struct) &&
((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
block.AddThisVariable (bc, Parent, Location);
block.AddThisVariable (bc);
if (block != null && (ModFlags & Modifiers.STATIC) == 0){
if ((ModFlags & Modifiers.STATIC) == 0){
if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null)
Initializer = new GeneratedBaseInitializer (Location);

10
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/namespace.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
//
// Copyright 2001 Ximian, Inc.
// Copyright 2003-2008 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
using System;
using System.Collections.Generic;
@ -987,10 +988,8 @@ namespace Mono.CSharp { @@ -987,10 +988,8 @@ namespace Mono.CSharp {
if (namespace_using_table != null)
return namespace_using_table;
if (using_clauses == null) {
namespace_using_table = empty_namespaces;
return namespace_using_table;
}
if (using_clauses == null)
return empty_namespaces;
var list = new List<Namespace> (using_clauses.Count);
@ -1002,6 +1001,9 @@ namespace Mono.CSharp { @@ -1002,6 +1001,9 @@ namespace Mono.CSharp {
list.Add (using_ns);
}
if (Compiler.Settings.StatementMode)
return list.ToArray ();
namespace_using_table = list.ToArray ();
return namespace_using_table;
}

1
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/nullable.cs

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
//
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2008 Novell, Inc
// Copyright 2011 Xamarin Inc
//
using System;

1
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/parameter.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
//
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2008 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
//
using System;

11
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/pending.cs

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
//
// Copyright 2001, 2002 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2008 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
using System;
@ -598,6 +599,10 @@ namespace Mono.CSharp { @@ -598,6 +599,10 @@ namespace Mono.CSharp {
if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, base_method.ReturnType))
return false;
if (mi.IsGeneric && !Method.CheckImplementingMethodConstraints (container, base_method, mi)) {
return true;
}
}
if (base_method != null) {
@ -686,7 +691,7 @@ namespace Mono.CSharp { @@ -686,7 +691,7 @@ namespace Mono.CSharp {
if (candidate.IsStatic) {
Report.Error (736, container.Location,
"`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' is static",
container.GetSignatureForError (), mi.GetSignatureForError (), TypeManager.CSharpSignature (candidate));
container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError ());
} else if ((candidate.Modifiers & Modifiers.PUBLIC) == 0) {
Report.Error (737, container.Location,
"`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' in not public",
@ -694,8 +699,8 @@ namespace Mono.CSharp { @@ -694,8 +699,8 @@ namespace Mono.CSharp {
} else {
Report.Error (738, container.Location,
"`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' return type `{3}' does not match interface member return type `{4}'",
container.GetSignatureForError (), mi.GetSignatureForError (), TypeManager.CSharpSignature (candidate),
TypeManager.CSharpName (candidate.ReturnType), TypeManager.CSharpName (mi.ReturnType));
container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError (),
candidate.ReturnType.GetSignatureForError (), mi.ReturnType.GetSignatureForError ());
}
} else {
Report.Error (535, container.Location, "`{0}' does not implement interface member `{1}'",

17
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/property.cs

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
//
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2008 Novell, Inc
// Copyright 2011 Xamarin Inc
//
using System;
@ -743,7 +744,7 @@ namespace Mono.CSharp @@ -743,7 +744,7 @@ namespace Mono.CSharp
FieldExpr fe = new FieldExpr (field, Location);
if ((field.ModFlags & Modifiers.STATIC) == 0)
fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location);
fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
// Create get block
Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
@ -781,6 +782,16 @@ namespace Mono.CSharp @@ -781,6 +782,16 @@ namespace Mono.CSharp
if (!DefineAccessors ())
return false;
if (AccessorSecond == null) {
PropertyMethod pm;
if (AccessorFirst is GetMethod)
pm = new SetMethod (this, 0, ParametersCompiled.EmptyReadOnlyParameters, null, Location);
else
pm = new GetMethod (this, 0, null, Location);
Parent.AddMember (pm);
}
if (!CheckBase ())
return false;
@ -876,7 +887,7 @@ namespace Mono.CSharp @@ -876,7 +887,7 @@ namespace Mono.CSharp
abstract class EventFieldAccessor : AEventAccessor
{
protected EventFieldAccessor (EventField method, string prefix)
: base (method, prefix, null, Location.Null)
: base (method, prefix, null, method.Location)
{
}
@ -1275,7 +1286,7 @@ namespace Mono.CSharp @@ -1275,7 +1286,7 @@ namespace Mono.CSharp
if (!base.Define ())
return false;
if (!TypeManager.IsDelegateType (MemberType)) {
if (!MemberType.IsDelegate) {
Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
}

5
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/report.cs

@ -59,7 +59,7 @@ namespace Mono.CSharp { @@ -59,7 +59,7 @@ namespace Mono.CSharp {
612, 618, 626, 628, 642, 649, 652, 657, 658, 659, 660, 661, 665, 672, 675, 693,
728,
809, 824,
1030, 1058, 1066,
1030, 1058, 1060, 1066,
1522, 1570, 1571, 1572, 1573, 1574, 1580, 1581, 1584, 1587, 1589, 1590, 1591, 1592,
1607, 1616, 1633, 1634, 1635, 1685, 1690, 1691, 1692, 1695, 1696, 1699,
1700, 1701, 1702, 1709, 1711, 1717, 1718, 1720, 1735,
@ -107,6 +107,9 @@ namespace Mono.CSharp { @@ -107,6 +107,9 @@ namespace Mono.CSharp {
case LanguageVersion.V_4:
version = "4.0";
break;
case LanguageVersion.V_5:
version = "5.0";
break;
default:
throw new InternalErrorException ("Invalid feature version", compiler.Settings.Version);
}

15
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/rootcontext.cs

@ -10,6 +10,8 @@ @@ -10,6 +10,8 @@
//
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2008 Novell, Inc
// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
//
using System.Collections.Generic;
using System.IO;
@ -25,9 +27,10 @@ namespace Mono.CSharp { @@ -25,9 +27,10 @@ namespace Mono.CSharp {
ISO_2 = 2,
V_3 = 3,
V_4 = 4,
V_5 = 5,
Future = 100,
Default = LanguageVersion.V_4,
Default = LanguageVersion.V_5,
}
public enum RuntimeVersion
@ -1041,12 +1044,18 @@ namespace Mono.CSharp { @@ -1041,12 +1044,18 @@ namespace Mono.CSharp {
case "3":
settings.Version = LanguageVersion.V_3;
return ParseResult.Success;
case "4":
settings.Version = LanguageVersion.V_4;
return ParseResult.Success;
case "5":
settings.Version = LanguageVersion.V_5;
return ParseResult.Success;
case "future":
settings.Version = LanguageVersion.Future;
return ParseResult.Success;
}
report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', `3' or `Default'", value);
report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', `3', `4', `5', `Default' or `Future'", value);
return ParseResult.Error;
case "/codepage":
@ -1407,7 +1416,7 @@ namespace Mono.CSharp { @@ -1407,7 +1416,7 @@ namespace Mono.CSharp {
" -help Lists all compiler options (short: -?)\n" +
" -keycontainer:NAME The key pair container used to sign the output assembly\n" +
" -keyfile:FILE The key file used to strongname the ouput assembly\n" +
" -langversion:TEXT Specifies language version: ISO-1, ISO-2, 3, Default or Future\n" +
" -langversion:TEXT Specifies language version: ISO-1, ISO-2, 3, 4, 5, Default or Future\n" +
" -lib:PATH1[,PATHn] Specifies the location of referenced assemblies\n" +
" -main:CLASS Specifies the class with the Main method (short: -m)\n" +
" -noconfig Disables implicitly referenced assemblies\n" +

10
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/roottypes.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
//
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2008 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
using System;
@ -399,8 +400,13 @@ namespace Mono.CSharp @@ -399,8 +400,13 @@ namespace Mono.CSharp
public new void Define ()
{
foreach (TypeContainer tc in types)
tc.DefineType ();
foreach (TypeContainer tc in types) {
try {
tc.DefineType ();
} catch (Exception e) {
throw new InternalErrorException (tc, e);
}
}
foreach (TypeContainer tc in types)
tc.ResolveTypeParameters ();

403
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
//
// statement.cs: Statement representation for the IL tree.
//
// Author:
// Authors:
// Miguel de Icaza (miguel@ximian.com)
// Martin Baulig (martin@ximian.com)
// Marek Safar (marek.safar@seznam.cz)
// Marek Safar (marek.safar@gmail.com)
//
// Copyright 2001, 2002, 2003 Ximian, Inc.
// Copyright 2003, 2004 Novell, Inc.
@ -476,47 +476,52 @@ namespace Mono.CSharp { @@ -476,47 +476,52 @@ namespace Mono.CSharp {
}
}
public class For : Statement {
public Expression Test { get; private set; }
public Statement InitStatement { get; private set; }
public Statement Increment { get; private set; }
public Statement Statement { get; private set; }
public class For : Statement
{
bool infinite, empty;
public For (Statement init_statement,
BooleanExpression test,
Statement increment,
Statement statement,
Location l)
{
InitStatement = init_statement;
Test = test;
Increment = increment;
Statement = statement;
public For (Location l)
{
loc = l;
}
public Statement Initializer {
get; set;
}
public Expression Condition {
get; set;
}
public Statement Iterator {
get; set;
}
public Statement Statement {
get; set;
}
public override bool Resolve (BlockContext ec)
{
bool ok = true;
if (InitStatement != null){
if (!InitStatement.Resolve (ec))
if (Initializer != null) {
if (!Initializer.Resolve (ec))
ok = false;
}
if (Test != null){
Test = Test.Resolve (ec);
if (Test == null)
if (Condition != null) {
Condition = Condition.Resolve (ec);
if (Condition == null)
ok = false;
else if (Test is Constant){
bool value = !((Constant) Test).IsDefaultValue;
else if (Condition is Constant) {
bool value = !((Constant) Condition).IsDefaultValue;
if (value == false){
if (!Statement.ResolveUnreachable (ec, true))
return false;
if ((Increment != null) &&
!Increment.ResolveUnreachable (ec, false))
if ((Iterator != null) &&
!Iterator.ResolveUnreachable (ec, false))
return false;
empty = true;
return true;
@ -537,12 +542,12 @@ namespace Mono.CSharp { @@ -537,12 +542,12 @@ namespace Mono.CSharp {
ok = false;
ec.EndFlowBranching ();
if (Increment != null){
if (Iterator != null){
if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable) {
if (!Increment.ResolveUnreachable (ec, !was_unreachable))
if (!Iterator.ResolveUnreachable (ec, !was_unreachable))
ok = false;
} else {
if (!Increment.Resolve (ec))
if (!Iterator.Resolve (ec))
ok = false;
}
}
@ -557,11 +562,11 @@ namespace Mono.CSharp { @@ -557,11 +562,11 @@ namespace Mono.CSharp {
protected override void DoEmit (EmitContext ec)
{
if (InitStatement != null)
InitStatement.Emit (ec);
if (Initializer != null)
Initializer.Emit (ec);
if (empty) {
Test.EmitSideEffect (ec);
Condition.EmitSideEffect (ec);
return;
}
@ -578,24 +583,24 @@ namespace Mono.CSharp { @@ -578,24 +583,24 @@ namespace Mono.CSharp {
Statement.Emit (ec);
ec.MarkLabel (ec.LoopBegin);
Increment.Emit (ec);
Iterator.Emit (ec);
ec.MarkLabel (test);
//
// If test is null, there is no test, and we are just
// an infinite loop
//
if (Test != null){
if (Condition != null){
//
// The Resolve code already catches the case for
// Test == Constant (false) so we know that
// this is true
//
if (Test is Constant) {
Test.EmitSideEffect (ec);
if (Condition is Constant) {
Condition.EmitSideEffect (ec);
ec.Emit (OpCodes.Br, loop);
} else {
Test.EmitBranchable (ec, loop, true);
Condition.EmitBranchable (ec, loop, true);
}
} else
@ -610,15 +615,15 @@ namespace Mono.CSharp { @@ -610,15 +615,15 @@ namespace Mono.CSharp {
{
For target = (For) t;
if (InitStatement != null)
target.InitStatement = InitStatement.Clone (clonectx);
if (Test != null)
target.Test = Test.Clone (clonectx);
if (Increment != null)
target.Increment = Increment.Clone (clonectx);
if (Initializer != null)
target.Initializer = Initializer.Clone (clonectx);
if (Condition != null)
target.Condition = Condition.Clone (clonectx);
if (Iterator != null)
target.Iterator = Iterator.Clone (clonectx);
target.Statement = Statement.Clone (clonectx);
}
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
@ -662,6 +667,37 @@ namespace Mono.CSharp { @@ -662,6 +667,37 @@ namespace Mono.CSharp {
}
}
public class StatementErrorExpression : Statement
{
readonly Expression expr;
public StatementErrorExpression (Expression expr)
{
this.expr = expr;
}
public Expression Expression {
get {
return expr;
}
}
protected override void DoEmit (EmitContext ec)
{
throw new NotSupportedException ();
}
protected override void CloneTo (CloneContext clonectx, Statement target)
{
throw new NotImplementedException ();
}
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
}
}
//
// Simple version of statement list not requiring a block
//
@ -1299,6 +1335,7 @@ namespace Mono.CSharp { @@ -1299,6 +1335,7 @@ namespace Mono.CSharp {
Block Block { get; }
Expression CreateReferenceExpression (ResolveContext rc, Location loc);
bool IsDeclared { get; }
bool IsParameter { get; }
Location Location { get; }
}
@ -1402,6 +1439,9 @@ namespace Mono.CSharp { @@ -1402,6 +1439,9 @@ namespace Mono.CSharp {
void CreateEvaluatorVariable (BlockContext bc, LocalVariable li)
{
if (bc.Report.Errors != 0)
return;
var container = bc.CurrentMemberDefinition.Parent;
Field f = new Field (container, new TypeExpression (li.Type, li.Location), Modifiers.PUBLIC | Modifiers.STATIC,
@ -1457,6 +1497,13 @@ namespace Mono.CSharp { @@ -1457,6 +1497,13 @@ namespace Mono.CSharp {
if (Initializer != null) {
((VarExpr) type_expr).InferType (bc, Initializer);
type = type_expr.Type;
} else {
// Set error type to indicate the var was placed correctly but could
// not be infered
//
// var a = missing ();
//
type = InternalType.ErrorType;
}
}
@ -1652,8 +1699,9 @@ namespace Mono.CSharp { @@ -1652,8 +1699,9 @@ namespace Mono.CSharp {
#region Properties
public bool AddressTaken {
get { return (flags & Flags.AddressTaken) != 0; }
set { flags |= Flags.AddressTaken; }
get {
return (flags & Flags.AddressTaken) != 0;
}
}
public Block Block {
@ -1716,6 +1764,12 @@ namespace Mono.CSharp { @@ -1716,6 +1764,12 @@ namespace Mono.CSharp {
}
}
bool INamedBlockVariable.IsParameter {
get {
return false;
}
}
public bool IsReadonly {
get {
return (flags & Flags.ReadonlyMask) != 0;
@ -1874,6 +1928,11 @@ namespace Mono.CSharp { @@ -1874,6 +1928,11 @@ namespace Mono.CSharp {
flags |= Flags.Used;
}
public void SetHasAddressTaken ()
{
flags |= (Flags.AddressTaken | Flags.Used);
}
public override string ToString ()
{
return string.Format ("LocalInfo ({0},{1},{2},{3})", name, type, VariableInfo, Location);
@ -1901,12 +1960,14 @@ namespace Mono.CSharp { @@ -1901,12 +1960,14 @@ namespace Mono.CSharp {
Unchecked = 1,
HasRet = 8,
Unsafe = 16,
IsIterator = 32,
HasCapturedVariable = 64,
HasCapturedThis = 1 << 7,
IsExpressionTree = 1 << 8,
CompilerGenerated = 1 << 9,
IsAsync = 1 << 10
HasAsyncModifier = 1 << 10,
Resolved = 1 << 11,
YieldBlock = 1 << 12,
AwaitBlock = 1 << 13
}
public Block Parent;
@ -2098,6 +2159,9 @@ namespace Mono.CSharp { @@ -2098,6 +2159,9 @@ namespace Mono.CSharp {
public override bool Resolve (BlockContext ec)
{
if ((flags & Flags.Resolved) != 0)
return true;
Block prev_block = ec.CurrentBlock;
bool ok = true;
@ -2182,6 +2246,7 @@ namespace Mono.CSharp { @@ -2182,6 +2246,7 @@ namespace Mono.CSharp {
if (this == ParametersBlock.TopBlock && !ParametersBlock.TopBlock.IsThisAssigned (ec) && !flow_unreachable)
ok = false;
flags |= Flags.Resolved;
return ok;
}
@ -2292,6 +2357,12 @@ namespace Mono.CSharp { @@ -2292,6 +2357,12 @@ namespace Mono.CSharp {
}
}
public bool HasAwait {
get {
return (flags & Flags.AwaitBlock) != 0;
}
}
public bool HasCapturedThis {
set { flags = value ? flags | Flags.HasCapturedThis : flags & ~Flags.HasCapturedThis; }
get {
@ -2306,6 +2377,12 @@ namespace Mono.CSharp { @@ -2306,6 +2377,12 @@ namespace Mono.CSharp {
}
}
public bool HasYield {
get {
return (flags & Flags.YieldBlock) != 0;
}
}
#endregion
//
@ -2314,15 +2391,17 @@ namespace Mono.CSharp { @@ -2314,15 +2391,17 @@ namespace Mono.CSharp {
public AnonymousMethodStorey CreateAnonymousMethodStorey (ResolveContext ec)
{
//
// An iterator has only 1 storey block
// Return same story for iterator and async blocks unless we are
// in nested anonymous method
//
if (ec.CurrentAnonymousMethod.IsIterator)
return ec.CurrentAnonymousMethod.Storey;
if (ec.CurrentAnonymousMethod is StateMachineInitializer && ParametersBlock.Original == ec.CurrentAnonymousMethod.Block.Original)
return ec.CurrentAnonymousMethod.Storey;
//
// When referencing a variable in iterator storey from children anonymous method
// When referencing a variable in parent iterator/async storey
// from nested anonymous method
//
if (ParametersBlock.am_storey is IteratorStorey) {
if (ParametersBlock.am_storey is StateMachine) {
return ParametersBlock.am_storey;
}
@ -2409,6 +2488,32 @@ namespace Mono.CSharp { @@ -2409,6 +2488,32 @@ namespace Mono.CSharp {
am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey);
}
public void RegisterAsyncAwait ()
{
var block = this;
while ((block.flags & Flags.AwaitBlock) == 0) {
block.flags |= Flags.AwaitBlock;
if (block.Parent == null)
return;
block = block.Parent.Explicit;
}
}
public void RegisterIteratorYield ()
{
var block = this;
while ((block.flags & Flags.YieldBlock) == 0) {
block.flags |= Flags.YieldBlock;
if (block.Parent == null)
return;
block = block.Parent.Explicit;
}
}
public void WrapIntoDestructor (TryFinally tf, ExplicitBlock tryBlock)
{
tryBlock.statements = statements;
@ -2450,6 +2555,12 @@ namespace Mono.CSharp { @@ -2450,6 +2555,12 @@ namespace Mono.CSharp {
}
}
public bool IsParameter {
get {
return true;
}
}
public bool IsLocked {
get {
return is_locked;
@ -2545,6 +2656,8 @@ namespace Mono.CSharp { @@ -2545,6 +2656,8 @@ namespace Mono.CSharp {
this.parameters = parameters;
ParametersBlock = this;
flags |= (parent.ParametersBlock.flags & (Flags.YieldBlock | Flags.AwaitBlock));
this.top_block = parent.ParametersBlock.top_block;
ProcessParameters ();
}
@ -2584,13 +2697,12 @@ namespace Mono.CSharp { @@ -2584,13 +2697,12 @@ namespace Mono.CSharp {
#region Properties
public bool IsAsync
{
public bool IsAsync {
get {
return (flags & Flags.IsAsync) != 0;
return (flags & Flags.HasAsyncModifier) != 0;
}
set {
flags = value ? flags | Flags.IsAsync : flags & ~Flags.IsAsync;
flags = value ? flags | Flags.HasAsyncModifier : flags & ~Flags.HasAsyncModifier;
}
}
@ -2620,7 +2732,7 @@ namespace Mono.CSharp { @@ -2620,7 +2732,7 @@ namespace Mono.CSharp {
public bool Resolved {
get {
return resolved;
return (flags & Flags.Resolved) != 0;
}
}
@ -2631,7 +2743,7 @@ namespace Mono.CSharp { @@ -2631,7 +2743,7 @@ namespace Mono.CSharp {
// <summary>
// Check whether all `out' parameters have been assigned.
// </summary>
public void CheckOutParameters (FlowBranching.UsageVector vector, Location loc)
public void CheckOutParameters (FlowBranching.UsageVector vector)
{
if (vector.IsUnreachable)
return;
@ -2647,8 +2759,10 @@ namespace Mono.CSharp { @@ -2647,8 +2759,10 @@ namespace Mono.CSharp {
if (vector.IsAssigned (var, false))
continue;
TopBlock.Report.Error (177, loc, "The out parameter `{0}' must be assigned to before control leaves the current method",
var.Name);
var p = parameter_info[i].Parameter;
TopBlock.Report.Error (177, p.Location,
"The out parameter `{0}' must be assigned to before control leaves the current method",
p.Name);
}
}
@ -2792,12 +2906,14 @@ namespace Mono.CSharp { @@ -2792,12 +2906,14 @@ namespace Mono.CSharp {
ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation);
pb.EndLocation = EndLocation;
pb.statements = statements;
pb.original = this;
var iterator = new Iterator (pb, method, host, iterator_type, is_enumerable);
am_storey = new IteratorStorey (iterator);
statements = new List<Statement> (1);
AddStatement (new Return (iterator, iterator.Location));
flags &= ~Flags.YieldBlock;
}
public void WrapIntoAsyncTask (IMemberContext context, TypeContainer host, TypeSpec returnType)
@ -2805,6 +2921,7 @@ namespace Mono.CSharp { @@ -2805,6 +2921,7 @@ namespace Mono.CSharp {
ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation);
pb.EndLocation = EndLocation;
pb.statements = statements;
pb.original = this;
var block_type = host.Module.Compiler.BuiltinTypes.Void;
var initializer = new AsyncInitializer (pb, host, block_type);
@ -2814,6 +2931,7 @@ namespace Mono.CSharp { @@ -2814,6 +2931,7 @@ namespace Mono.CSharp {
statements = new List<Statement> (1);
AddStatement (new StatementExpression (initializer));
flags &= ~Flags.AwaitBlock;
}
}
@ -2860,13 +2978,9 @@ namespace Mono.CSharp { @@ -2860,13 +2978,9 @@ namespace Mono.CSharp {
top_block = this;
}
public bool IsIterator
{
public bool IsIterator {
get {
return (flags & Flags.IsIterator) != 0;
}
set {
flags = value ? flags | Flags.IsIterator : flags & ~Flags.IsIterator;
return HasYield;
}
}
@ -3114,15 +3228,14 @@ namespace Mono.CSharp { @@ -3114,15 +3228,14 @@ namespace Mono.CSharp {
// analysis code to ensure that it's been fully initialized before control
// leaves the constructor.
// </summary>
public LocalVariable AddThisVariable (BlockContext bc, TypeContainer ds, Location l)
public void AddThisVariable (BlockContext bc)
{
if (this_variable == null) {
this_variable = new LocalVariable (this, "this", LocalVariable.Flags.IsThis | LocalVariable.Flags.Used, l);
this_variable.Type = ds.CurrentType;
this_variable.PrepareForFlowAnalysis (bc);
}
if (this_variable != null)
throw new InternalErrorException (StartLocation.ToString ());
return this_variable;
this_variable = new LocalVariable (this, "this", LocalVariable.Flags.IsThis | LocalVariable.Flags.Used, StartLocation);
this_variable.Type = bc.CurrentType;
this_variable.PrepareForFlowAnalysis (bc);
}
public bool IsThisAssigned (BlockContext ec)
@ -3363,6 +3476,32 @@ namespace Mono.CSharp { @@ -3363,6 +3476,32 @@ namespace Mono.CSharp {
}
}
sealed class LabelMarker : Statement
{
readonly Switch s;
readonly List<SwitchLabel> labels;
public LabelMarker (Switch s, List<SwitchLabel> labels)
{
this.s = s;
this.labels = labels;
}
protected override void CloneTo (CloneContext clonectx, Statement target)
{
}
protected override void DoEmit (EmitContext ec)
{
foreach (var l in labels) {
if (l.IsDefault)
ec.MarkLabel (s.DefaultLabel);
else
ec.MarkLabel (l.GetILLabel (ec));
}
}
}
public List<SwitchSection> Sections;
public Expression Expr;
@ -3389,6 +3528,8 @@ namespace Mono.CSharp { @@ -3389,6 +3528,8 @@ namespace Mono.CSharp {
SwitchSection default_section;
SwitchLabel null_section;
Statement simple_stmt;
VariableReference value;
ExpressionStatement string_dictionary;
FieldExpr switch_cache_field;
static int unique_counter;
@ -3573,7 +3714,7 @@ namespace Mono.CSharp { @@ -3573,7 +3714,7 @@ namespace Mono.CSharp {
{
Label lbl_default = default_target;
if (labels.Count > 0) {
if (labels != null && labels.Count > 0) {
List<LabelsRange> ranges;
if (string_labels != null) {
// We have done all hard work for string already
@ -3605,7 +3746,7 @@ namespace Mono.CSharp { @@ -3605,7 +3746,7 @@ namespace Mono.CSharp {
ranges.Sort ();
}
TypeSpec compare_type = TypeManager.IsEnumType (SwitchType) ? EnumSpec.GetUnderlyingType (SwitchType) : SwitchType;
TypeSpec compare_type = SwitchType.IsEnum ? EnumSpec.GetUnderlyingType (SwitchType) : SwitchType;
for (int range_index = ranges.Count - 1; range_index >= 0; --range_index) {
LabelsRange kb = ranges[range_index];
@ -3806,6 +3947,13 @@ namespace Mono.CSharp { @@ -3806,6 +3947,13 @@ namespace Mono.CSharp {
if (constant_section == null)
constant_section = default_section;
} else {
//
// Store switch expression for comparission purposes
//
value = new_expr as VariableReference;
if (value == null)
value = TemporaryVariableReference.Create (SwitchType, ec.CurrentBlock, loc);
}
bool first = true;
@ -3832,8 +3980,7 @@ namespace Mono.CSharp { @@ -3832,8 +3980,7 @@ namespace Mono.CSharp {
}
if (default_section == null)
ec.CurrentBranching.CreateSibling (
null, FlowBranching.SiblingType.SwitchSection);
ec.CurrentBranching.CreateSibling (null, FlowBranching.SiblingType.SwitchSection);
ec.EndFlowBranching ();
ec.Switch = old_switch;
@ -3841,9 +3988,15 @@ namespace Mono.CSharp { @@ -3841,9 +3988,15 @@ namespace Mono.CSharp {
if (!ok)
return false;
if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.String && !is_constant) {
// TODO: Optimize single case, and single+default case
ResolveStringSwitchMap (ec);
if (!is_constant) {
if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.String) {
if (string_labels.Count < 7)
ResolveSimpleSwitch (ec);
else
ResolveStringSwitchMap (ec);
} else if (labels.Count < 3 && !IsNullable) {
ResolveSimpleSwitch (ec);
}
}
return true;
@ -3860,6 +4013,45 @@ namespace Mono.CSharp { @@ -3860,6 +4013,45 @@ namespace Mono.CSharp {
return sl;
}
//
// Prepares switch using simple if/else comparison for small label count (4 + optional default)
//
void ResolveSimpleSwitch (BlockContext bc)
{
simple_stmt = default_section != null ? default_section.Block : null;
for (int i = Sections.Count - 1; i >= 0; --i) {
var s = Sections[i];
if (s == default_section) {
s.Block.AddScopeStatement (new LabelMarker (this, s.Labels));
continue;
}
s.Block.AddScopeStatement (new LabelMarker (this, s.Labels));
Expression cond = null;
for (int ci = 0; ci < s.Labels.Count; ++ci) {
var e = new Binary (Binary.Operator.Equality, value, s.Labels[ci].Converted, loc);
if (ci > 0) {
cond = new Binary (Binary.Operator.LogicalOr, cond, e, loc);
} else {
cond = e;
}
}
simple_stmt = new If (cond, s.Block, simple_stmt, loc);
}
// It's null for empty switch
if (simple_stmt != null)
simple_stmt.Resolve (bc);
}
//
// Converts string switch into string hashtable
//
void ResolveStringSwitchMap (ResolveContext ec)
{
FullNamedExpression string_dictionary_type;
@ -3924,7 +4116,7 @@ namespace Mono.CSharp { @@ -3924,7 +4116,7 @@ namespace Mono.CSharp {
string_dictionary = new SimpleAssign (switch_cache_field, initializer.Resolve (ec));
}
void DoEmitStringSwitch (LocalTemporary value, EmitContext ec)
void DoEmitStringSwitch (EmitContext ec)
{
Label l_initialized = ec.DefineLabel ();
@ -3978,7 +4170,7 @@ namespace Mono.CSharp { @@ -3978,7 +4170,7 @@ namespace Mono.CSharp {
EmitTableSwitch (ec, string_switch_variable);
string_switch_variable.Release (ec);
}
protected override void DoEmit (EmitContext ec)
{
//
@ -3990,21 +4182,13 @@ namespace Mono.CSharp { @@ -3990,21 +4182,13 @@ namespace Mono.CSharp {
default_target = ec.DefineLabel ();
null_target = ec.DefineLabel ();
// Store variable for comparission purposes
// TODO: Don't duplicate non-captured VariableReference
LocalTemporary value;
if (IsNullable) {
value = new LocalTemporary (SwitchType);
unwrap.EmitCheck (ec);
ec.Emit (OpCodes.Brfalse, null_target);
new_expr.Emit (ec);
value.Store (ec);
} else if (!is_constant) {
value = new LocalTemporary (SwitchType);
new_expr.Emit (ec);
value.Store (ec);
} else
value = null;
value.EmitAssign (ec, new_expr, false, false);
} else if (new_expr != value && !is_constant) {
value.EmitAssign (ec, new_expr, false, false);
}
//
// Setup the codegen context
@ -4020,14 +4204,13 @@ namespace Mono.CSharp { @@ -4020,14 +4204,13 @@ namespace Mono.CSharp {
if (constant_section != null)
constant_section.Block.Emit (ec);
} else if (string_dictionary != null) {
DoEmitStringSwitch (value, ec);
DoEmitStringSwitch (ec);
} else if (simple_stmt != null) {
simple_stmt.Emit (ec);
} else {
EmitTableSwitch (ec, value);
}
if (value != null)
value.Release (ec);
// Restore context state.
ec.MarkLabel (ec.LoopEnd);
@ -5029,11 +5212,13 @@ namespace Mono.CSharp { @@ -5029,11 +5212,13 @@ namespace Mono.CSharp {
this.Block = block;
this.Specific = catch_clauses;
this.inside_try_finally = inside_try_finally;
Catch c = catch_clauses [0];
if (c.IsGeneral) {
this.General = c;
catch_clauses.RemoveAt (0);
if (catch_clauses != null) {
Catch c = catch_clauses [0];
if (c.IsGeneral) {
this.General = c;
catch_clauses.RemoveAt (0);
}
}
}
@ -5395,8 +5580,8 @@ namespace Mono.CSharp { @@ -5395,8 +5580,8 @@ namespace Mono.CSharp {
/// <summary>
/// Implementation of the foreach C# statement
/// </summary>
public class Foreach : Statement {
public class Foreach : Statement
{
sealed class ArrayForeach : Statement
{
readonly Foreach for_each;
@ -5417,7 +5602,6 @@ namespace Mono.CSharp { @@ -5417,7 +5602,6 @@ namespace Mono.CSharp {
for_each = @foreach;
statement = for_each.statement;
loc = @foreach.loc;
variable = new LocalVariableReference (for_each.variable, loc);
counter = new StatementExpression[rank];
variables = new TemporaryVariableReference[rank];
@ -5438,7 +5622,7 @@ namespace Mono.CSharp { @@ -5438,7 +5622,7 @@ namespace Mono.CSharp {
public override bool Resolve (BlockContext ec)
{
Block variables_block = variable.local_info.Block;
Block variables_block = for_each.variable.Block;
copy = TemporaryVariableReference.Create (for_each.expr.Type, variables_block, loc);
copy.Resolve (ec);
@ -5488,7 +5672,8 @@ namespace Mono.CSharp { @@ -5488,7 +5672,8 @@ namespace Mono.CSharp {
ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
ec.CurrentBranching.CreateSibling ();
variable.local_info.Type = conv.Type;
for_each.variable.Type = conv.Type;
variable = new LocalVariableReference (for_each.variable, loc);
variable.Resolve (ec);
ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);

1
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/support.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
//
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2009 Novell, Inc
// Copyright 2011 Xamarin Inc
//
using System;

109
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/typemanager.cs

@ -8,7 +8,8 @@ @@ -8,7 +8,8 @@
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2008 Novell, Inc.
// Copyright 2003-2011 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
using System;
@ -208,6 +209,7 @@ namespace Mono.CSharp @@ -208,6 +209,7 @@ namespace Mono.CSharp
public readonly PredefinedType MethodBase;
public readonly PredefinedType MethodInfo;
public readonly PredefinedType ConstructorInfo;
public readonly PredefinedType MemberBinding;
//
// C# 4.0
@ -256,6 +258,7 @@ namespace Mono.CSharp @@ -256,6 +258,7 @@ namespace Mono.CSharp
Expression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression");
ExpressionGeneric = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression", 1);
MemberBinding = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "MemberBinding");
ParameterExpression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "ParameterExpression");
FieldInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "FieldInfo");
MethodBase = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodBase");
@ -379,14 +382,9 @@ namespace Mono.CSharp @@ -379,14 +382,9 @@ namespace Mono.CSharp
MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec));
AsyncTaskMethodBuilderGenericSetResult = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
MemberFilter.Method ("SetResult", 0,
new ParametersImported (
new[] {
new ParameterData (null, Parameter.Modifier.NONE)
},
new[] {
new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null)
}, false), btypes.Void));
"SetResult", MemberKind.Method, () => new TypeSpec[] {
types.AsyncTaskMethodBuilderGeneric.TypeSpec.MemberDefinition.TypeParameters[0]
});
AsyncTaskMethodBuilderGenericSetException = new PredefinedMember<MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric,
MemberFilter.Method ("SetException", 0,
@ -701,8 +699,8 @@ namespace Mono.CSharp @@ -701,8 +699,8 @@ namespace Mono.CSharp
T member;
TypeSpec declaring_type;
readonly PredefinedType declaring_type_predefined;
readonly PredefinedType[] parameters_predefined;
MemberFilter filter;
readonly Func<TypeSpec[]> filter_builder;
public PredefinedMember (ModuleContainer module, PredefinedType type, MemberFilter filter)
{
@ -726,7 +724,24 @@ namespace Mono.CSharp @@ -726,7 +724,24 @@ namespace Mono.CSharp
public PredefinedMember (ModuleContainer module, PredefinedType type, string name, MemberKind kind, params PredefinedType[] types)
: this (module, type, new MemberFilter (name, 0, kind, null, null))
{
parameters_predefined = types;
filter_builder = () => {
var ptypes = new TypeSpec[types.Length];
for (int i = 0; i < ptypes.Length; ++i) {
var p = types[i];
if (!p.Define ())
return null;
ptypes[i] = p.TypeSpec;
}
return ptypes;
};
}
public PredefinedMember (ModuleContainer module, PredefinedType type, string name, MemberKind kind, Func<TypeSpec[]> typesBuilder)
: this (module, type, new MemberFilter (name, 0, kind, null, null))
{
filter_builder = typesBuilder;
}
public PredefinedMember (ModuleContainer module, BuiltinTypeSpec type, string name, params TypeSpec[] types)
@ -746,20 +761,14 @@ namespace Mono.CSharp @@ -746,20 +761,14 @@ namespace Mono.CSharp
declaring_type = declaring_type_predefined.TypeSpec;
}
if (parameters_predefined != null) {
TypeSpec[] types = new TypeSpec [parameters_predefined.Length];
for (int i = 0; i < types.Length; ++i) {
var p = parameters_predefined [i];
if (!p.Define ())
return null;
types[i] = p.TypeSpec;
}
if (filter_builder != null) {
var types = filter_builder ();
if (filter.Kind == MemberKind.Field)
filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind, null, types [0]);
else
filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind, ParametersCompiled.CreateFullyResolved (types), filter.MemberType);
filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind,
ParametersCompiled.CreateFullyResolved (types), filter.MemberType);
}
member = MemberCache.FindMember (declaring_type, filter, BindingRestriction.DeclaredOnly) as T;
@ -785,16 +794,9 @@ namespace Mono.CSharp @@ -785,16 +794,9 @@ namespace Mono.CSharp
return null;
}
if (parameters_predefined != null) {
TypeSpec[] types = new TypeSpec[parameters_predefined.Length];
for (int i = 0; i < types.Length; ++i) {
var p = parameters_predefined[i];
types[i] = p.Resolve ();
if (types[i] == null)
return null;
}
filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind, ParametersCompiled.CreateFullyResolved (types), filter.MemberType);
if (filter_builder != null) {
filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind,
ParametersCompiled.CreateFullyResolved (filter_builder ()), filter.MemberType);
}
string method_args = null;
@ -842,43 +844,6 @@ namespace Mono.CSharp @@ -842,43 +844,6 @@ namespace Mono.CSharp
{
return mb.GetSignatureForError ();
}
// Obsolete
public static bool IsDelegateType (TypeSpec t)
{
return t.IsDelegate;
}
// Obsolete
public static bool IsEnumType (TypeSpec t)
{
return t.IsEnum;
}
//
// Whether a type is unmanaged. This is used by the unsafe code (25.2)
//
public static bool IsUnmanagedType (TypeSpec t)
{
var ds = t.MemberDefinition as DeclSpace;
if (ds != null)
return ds.IsUnmanagedType ();
if (t.Kind == MemberKind.Void)
return true;
// Someone did the work of checking if the ElementType of t is unmanaged. Let's not repeat it.
if (t.IsPointer)
return IsUnmanagedType (GetElementType (t));
if (!TypeSpec.IsValueType (t))
return false;
if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric)
return false;
return true;
}
public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent)
{
@ -944,12 +909,12 @@ namespace Mono.CSharp @@ -944,12 +909,12 @@ namespace Mono.CSharp
/// </summary>
public static bool VerifyUnmanaged (ModuleContainer rc, TypeSpec t, Location loc)
{
while (t.IsPointer)
t = GetElementType (t);
if (IsUnmanagedType (t))
if (t.IsUnmanaged)
return true;
while (t.IsPointer)
t = ((ElementTypeSpec) t).Element;
rc.Compiler.Report.SymbolRelatedToPreviousError (t);
rc.Compiler.Report.Error (208, loc,
"Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",

75
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs

@ -284,6 +284,28 @@ namespace Mono.CSharp @@ -284,6 +284,28 @@ namespace Mono.CSharp
}
}
//
// Whether a type is unmanaged. This is used by the unsafe code
//
public bool IsUnmanaged {
get {
if (IsPointer)
return ((ElementTypeSpec) this).Element.IsUnmanaged;
var ds = MemberDefinition as DeclSpace;
if (ds != null)
return ds.IsUnmanagedType ();
if (Kind == MemberKind.Void)
return true;
if (IsNested && DeclaringType.IsGenericOrParentIsGeneric)
return false;
return IsValueType (this);
}
}
public MemberCache MemberCache {
get {
if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
@ -340,6 +362,58 @@ namespace Mono.CSharp @@ -340,6 +362,58 @@ namespace Mono.CSharp
return false;
}
//
// Special version used during type definition
//
public bool AddInterfaceDefined (TypeSpec iface)
{
if (!AddInterface (iface))
return false;
//
// We can get into a situation where a type is inflated before
// its interfaces are resoved. Consider this situation
//
// class A<T> : X<A<int>>, IFoo {}
//
// When resolving base class of X`1 we inflate context type A`1
// All this happens before we even hit IFoo resolve. Without
// additional expansion any inside usage of A<T> would miss IFoo
// interface because it comes from early inflated TypeSpec
//
if (inflated_instances != null) {
foreach (var inflated in inflated_instances) {
inflated.Value.AddInterface (iface);
}
}
return true;
}
//
// Returns all type arguments, usefull for nested types
//
public static TypeSpec[] GetAllTypeArguments (TypeSpec type)
{
IList<TypeSpec> targs = TypeSpec.EmptyTypes;
do {
if (type.Arity > 0) {
if (targs.Count == 0) {
targs = type.TypeArguments;
} else {
var list = targs as List<TypeSpec> ?? new List<TypeSpec> (targs);
list.AddRange (type.TypeArguments);
targs = list;
}
}
type = type.declaringType;
} while (type != null);
return targs as TypeSpec[] ?? ((List<TypeSpec>) targs).ToArray ();
}
public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
{
if (Kind != MemberKind.Class)
@ -1247,6 +1321,7 @@ namespace Mono.CSharp @@ -1247,6 +1321,7 @@ namespace Mono.CSharp
public static readonly InternalType NullLiteral = new InternalType ("null");
public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
public static readonly InternalType Namespace = new InternalType ("<namespace>");
public static readonly InternalType ErrorType = new InternalType ("<error>");
readonly string name;

38
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/visit.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
// Copyright 2011 Xamarin Inc
//
using System;
@ -178,11 +179,16 @@ namespace Mono.CSharp @@ -178,11 +179,16 @@ namespace Mono.CSharp
{
return null;
}
public virtual object Visit (EmptyExpression emptyExpression)
{
return null;
}
public virtual object Visit (ErrorExpression errorExpression)
{
return null;
}
public virtual object Visit (If ifStatement)
{
@ -195,73 +201,66 @@ namespace Mono.CSharp @@ -195,73 +201,66 @@ namespace Mono.CSharp
return null;
}
public virtual object Visit (While whileStatement)
{
return null;
}
public virtual object Visit (For forStatement)
{
return null;
}
public virtual object Visit (StatementExpression statementExpression)
{
return null;
}
public virtual object Visit (StatementErrorExpression errorStatement)
{
return null;
}
public virtual object Visit (Return returnStatement)
{
return null;
}
public virtual object Visit (Goto gotoStatement)
{
return null;
}
public virtual object Visit (LabeledStatement labeledStatement)
{
return null;
}
public virtual object Visit (GotoDefault gotoDefault)
{
return null;
}
public virtual object Visit (GotoCase gotoCase)
{
return null;
}
public virtual object Visit (Throw throwStatement)
{
return null;
}
public virtual object Visit (Break breakStatement)
{
return null;
}
public virtual object Visit (Continue continueStatement)
{
return null;
}
public virtual object Visit (Block blockStatement)
{
return null;
@ -282,19 +281,16 @@ namespace Mono.CSharp @@ -282,19 +281,16 @@ namespace Mono.CSharp
return null;
}
public virtual object Visit (Unchecked uncheckedStatement)
{
return null;
}
public virtual object Visit (Checked checkedStatement)
{
return null;
}
public virtual object Visit (Unsafe unsafeStatement)
{
return null;
@ -312,7 +308,6 @@ namespace Mono.CSharp @@ -312,7 +308,6 @@ namespace Mono.CSharp
return null;
}
public virtual object Visit (TryCatch tryCatchStatement)
{
return null;
@ -337,6 +332,11 @@ namespace Mono.CSharp @@ -337,6 +332,11 @@ namespace Mono.CSharp
{
return null;
}
public virtual object Visit (InvalidStatementExpression invalidStatementExpression)
{
return null;
}
public virtual object Visit (Expression expression)
{
@ -435,7 +435,6 @@ namespace Mono.CSharp @@ -435,7 +435,6 @@ namespace Mono.CSharp
return null;
}
public virtual object Visit (Conditional conditionalExpression)
{
return null;
@ -631,5 +630,10 @@ namespace Mono.CSharp @@ -631,5 +630,10 @@ namespace Mono.CSharp
{
return null;
}
public virtual object Visit (Await awaitExpr)
{
return null;
}
}
}

8
src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Properties/AssemblyInfo.cs

@ -12,9 +12,9 @@ using System.Runtime.InteropServices; @@ -12,9 +12,9 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTitle("ICSharpCode.NRefactory.CSharp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ICSharpCode.NRefactory.CSharp")]
[assembly: AssemblyCopyright("Copyright 2011")]
[assembly: AssemblyCompany("ICSharpCode")]
[assembly: AssemblyProduct("SharpDevelop/MonoDevelop")]
[assembly: AssemblyCopyright("Copyright 2010-2011 AlphaSierraPapa")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -28,4 +28,4 @@ using System.Runtime.InteropServices; @@ -28,4 +28,4 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can use the default the Revision and
// Build Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.0.0.2")]

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save