Browse Source

Squashed 'NRefactory/' changes from a73d7ba..36c9cae

36c9cae Add ICompilation.Import() extension methods.
1467ce3 Fixed accessibility check for protected members in outer classes.
f410a2b Enum members are implicitly cast to the underlying type when used in an enum member initializer.
a9c743c Fixed type inference for "condition ? someEnum : 0"
42ce4ca Fixed type inference in foreach when the collection type does not implement IEnumerable.
45bcad4 Added getsubtype definitions helper method.
78ac5bb Fixed some code completion unit tests.
ff2a11b Worked on unit tests.
51986c4 Worked on code completion unit tests.
c453405 Updated code completion to the latest type system changes.
a564ebb Added easy to access enumerables for various member types.
a71670f Fixed some issues with code round-tripping; and added unit tests for some parser failures.
4db74d9 Fixed roundtripping of preprocessor directives.
bf88746 Added some failing parser tests for bugs discovered trying to roundtrip NRefactory itself.
a6433d4 Do not try to infer a type from the null literal.
b0b9942 Add ISolutionSnapshot for creating compilations for multiple projects from a single consistent snapshot.
7e95cb7 Add CSharpAstResolver.GetResolverStateBefore
4ccc313 Normalize newlines
9ffbdb8 Merge type system refactoring into NRefactory master.
4d4f1f4 Fixed various resolver bugs.
c4ce934 Fixed bug when resolving base constructor calls.
0b263b0 TypeSystemConvertVisitor: implemented ConvertInterfaceImplementation for methods and properties. Implemented 'goto case' support in control flow analysis.
f11eed9 Introduce a named unknown type (this allows TypeSystemAstBuilder to work better when there are resolve errors).
e2cb546 Adjust CodeDomConvertVisitor and DefiniteAssignmentAnalysis to new type system.
3d9b3ec Improved enum parsing.
e69e9f1 Fixed enum context.
bf3a1d7 Added gtk text editor lib.
9cc151d Started support for unclosed expression statements.
bcde6f1 Worked on enum context.
37798b0 Improved get/set keyword handling.
2ec341e Merged with mcs.
7e53805 Updated mcs/fixed some code completion cases.
73438b7 Make CSharpResolveVisitor internal and expose CSharpAstResolver instead.
9d7c018 Adjusted C# resolver to refactored type system.
c02e801 Introduce ResolvedUsingScope (serves as cache per using-scope; avoids resolving imported namespaces repeatedly).
5069b98 Fixed code completion bug.
3b6fda2 Added gtk demo & fixed code completion bug.
54851a7 C# Type System implementation
057c0be Fixed "partial" bug.
ba88599 Added a method to determine the current parameter index.
a701436 Changed parameter completion API slightly.
4a41972 Fixed code completion bug "Bug 1932 - [new resolver] fields don't show up unless prefixed with 'this.'".
2ea298c Fixed some null reference exceptions.
f479cb0 fixed bug in parameter parsing.
98d1826 Added error expression as ast node.
fa6ea12 Added error expression for the for construct.
817a2da Added error expression for invalid initializers.
4376927 Renamed file.
a4259ef * cs-tokenizer.cs: Fixed location bug.
ec82082 Handled pre processor directives as separate AST node.
11a9ce2 Added context action unit tests.
f9916d8 WIP: Type system refactoring.
2d70017 Fixed some parameter resolve result issues.
1bc609f Added pre processor "if"/"elif" contexts.
03ee478 Improved current member recognition.
c29b4ed Added missing follow up char.
0ab566c Fixed "partial" context.
a097af0 Fixed multiple line comment content.
8124eaa Fixed invalid expression statement.
a348bbd Merge branch 'master' of github.com:icsharpcode/NRefactory
41607d7 Added invalid expression statements to the ast.
d461987 Improved comment & string context recognition.
f631199 Type system refactoring: split unresolved/resolved type systems.
1ebf835 Fixed parameter completion issue.
af6ba7d Fixed unit test.
bf3fdb3 Added variable statement declaration tests.
4824080 Implemented indexer parameter data provider.
8c82864 Fixed field declaration context & "new" expression context.
86b3da2 Added object initializer tests & fixed them.
fb374aa Fixed unit test.
f1612d5 Added some more keyword tests & fixed some cases.
f5730d5 * CSharpCompletionEngine.cs: Fixed some bugs in global/type context.
85e1173 Fixed parser bug.
59ce505 Fixed last failing code completion unit test.
bc4ca21 * NRefactory.sln:
cfcaca8 Merged mcs.
b74cfbb Added switch context handling.
fa5e7e5 Fixed potential resolve issue. Note: That doesn't really fix the problem - only 90% of the cases. The partial class representation could need a change.
c498bc8 Fixed completion inside try ... catch bodies.
03407fd Fixed failing unit test.
2a795ae Fixed some unit tests.
8942cd5 Fixed failing unit test.
2cfd9b2 Added attribute context.
7a8e9d0 Merged with mcs master.
18e088e SpecializedMethod: Perform type substitution in the type parameter constraints.
69360a2 Implemented constraint inheritance.
57d55c6 Fixed resolving simple names within a generic class that refer to a non-generic inner class.
5d614c0 Fixed unit test.
98ad3ba Fixed unit test.
ffa2fc9 Fixed failing unit test.
42c0a2d Fixed unit test.
6d4a825 Fixed some unit tests.
a81096d Included interfaces in type parameter base types.
2bc6105 Fixed some completion unit tests. I'm not 100% sure if that's the best solution fixing this, but makes things easier for now.
fd91bdc Fixed resolving non-generic classes that are nested within generic classes.
f043e30 Fix ResolveVisitor.GetResolverStateBefore(): ensure that the resolver always registers the state before it caches a result.
ed86963 Failed assertions now fail unit tests.
81cac5e Fixed little code completion ast bug.
f3ea71a Fixed some completion tests.
7f697b3 Fixed resolver usage.
e96dbbd Added 'UnknownTypeResolveResult'. Makes it easier to implement the 'add missing namespace import' function.
0320a66 Added monodevelop code completion tests.
5ee9b73 Added missing unit test.
1c0ce1d Added default parameters for type parameter count.
f7b3094 Merged with md master.
7063203 FieldDeclaration/EventDeclaration/VariableDeclarationStatement now resolve to 'void'. Only the individual VariableInitializers will resolve to the field/event/variable.
800b951 Fixed bugs in ResolveVisitor:  - forgot scanning into ForEachStatement.InExpression when the variable type was not 'var'  - ProcessConversion() was called for Expression.Null  - made Resolve() internal because it hard to use correctly
b3d07d8 Ported over the monodevelop completion engine to nrefactory.
f46609b Worked on basic nrefactory completion infrastructure.
8389d7a Use OperatorResolveResult for assignments.
9ddf9bc Combine C#-specific UnaryOperatorResolveResult/BinaryOperatorResolveResult and ConditionalOperatorResolveResult classes into a single language-independent OperatorResolveResult class.
4bbcf2d Add "public ResolveResult Body { get; }" to LambdaResolveResult.
751b601 Shorten inner type names.
434ec17 Correctly set kind of compound types.
177fb85 Fix infinite recursion when resolving the base type of "class Test : Test.Base { public class Base {} }"
475f838 Make DefaultTypeDefinition.FullName cache thread-safe.
8c3899f Cached TypeDefiniton FullName. This is required for the navigate to feature which checks the full name as well as the name. Otherwise it would cause thousands of slow string concats. Since the type system should be treaded as read only namespaces & declaring type definitions can't change.
7b542f4 Enabled async tests.
e4c70d4 Added await/async support & updated mcs.
d91eb2c Print error information.
b7fcc55 Re-enable resolver unit tests that failed due to the parser returning incorrect positions.
25176ef Fixed IMember.IsOverridable to return true for abstract members.
e4850e9 Added async modifier.
0c3d5e0 Fix bug in ParameterListComparer: the method signatures "Method<T>(T a)" and "Method<S>(S b)" were considered unequal.
4d73e48 Add GetEffectiveBaseClass() and GetEffectiveInterfaceSet() to ITypeParameter, and fixed a bug in DefaultTypeParameter.IsReferenceType().
0c03236 Update AssemblyInfo for ICSharpCode.NRefactory.CSharp
813c8f5 Merge NRefactory 'b059dbcf413786069599d1686ac608150bd3f357' into SharpDevelop repository.
b059dbc Fixed NullReferenceException when resolving group join clause.
ad1e90b Merge pull request #205 - Decompilation of lifted operators
f0bfded C# AST: when setting a string property to null or an empty string, remove the corresponding identifier token.
9f988f6 Adjust ILSpy to NRefactory changes.
6994e19 Merge NRefactory '88ebd0b9596edab0e916ff28ae53f6febbdff032' to ILSpy.
5a2b4d2 fix out parameter output in CSharpToVBConverterVisitor
f085e9c fix AlwaysUseShortTypeNames omitting generic type arguments
02f1929 implement find references on local variables
8a598a7 fix CSharpBinding reference to NRefactory.CSharp; fix long type names bug in CSharpAmbience
02b1e15 Fix unit tests after moving CSharpAmbienceTests to different namespace.
e6d84ff moved Ambience to NRefactory
49c5c79 implement all different members in CSharpAmbience output
5beb702 implement CSharpAmbience for ITypeDefinition
9526969 Adjust SharpDevelop to NRefactory changes (move ICSharpCode.Editor -> ICSharpCode.NRefactory.Editor; put NR.C# in separate assembly)
2f4f82c Merge changes from NRefactory into SharpDevelop newNR branch.
10a6608 Merge branch 'master' of git://github.com/icsharpcode/ILSpy
472daa9 remove old files
588557e fix case sensitivity in IsKeyword check
3e37fb2 fix output of object initializers
7a9bb56 InsertParenthesesVisitor: insert parenthesis in "(new int[1])[0]"
ddc5d8a Merge branch 'master' of git://github.com/icsharpcode/ILSpy
1398d8a add missing space after Case keyword
a854421 corrected spelling of Overrides-modifier; convert virtual to Overridable and override to Overrides
5c10903 Merge branch 'master' of git://github.com/icsharpcode/ILSpy
ee384a2 PDB files for release mode. File alignments and base addresses improved.

git-subtree-dir: NRefactory
git-subtree-split: 36c9caec101ad5b2c47d11ac12bcd043d8d6e115
pull/297/head
Daniel Grunwald 14 years ago
parent
commit
14a4d880e6
  1. 94
      ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs
  2. 110
      ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs
  3. 5
      ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs
  4. 1
      ICSharpCode.NRefactory.CSharp/Ast/AstType.cs
  5. 5
      ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs
  6. 25
      ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs
  7. 5
      ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs
  8. 31
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/AssignmentExpression.cs
  9. 47
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/BinaryOperatorExpression.cs
  10. 42
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/ErrorExpression.cs
  11. 3
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedExpression.cs
  12. 29
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/UnaryOperatorExpression.cs
  13. 18
      ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Comment.cs
  14. 117
      ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/PreProcessorDirective.cs
  15. 2
      ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs
  16. 2
      ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs
  17. 13
      ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs
  18. 2
      ICSharpCode.NRefactory.CSharp/Ast/NodeType.cs
  19. 10
      ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs
  20. 20
      ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs
  21. 5
      ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/Accessor.cs
  22. 159
      ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs
  23. 2067
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  24. 495
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs
  25. 326
      ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs
  26. 237
      ICSharpCode.NRefactory.CSharp/Completion/CompletionDataWrapper.cs
  27. 71
      ICSharpCode.NRefactory.CSharp/Completion/ICompletionDataFactory.cs
  28. 46
      ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs
  29. 54
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  30. 239
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs
  31. 119
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs
  32. 60
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
  33. 5
      ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertParenthesesVisitor.cs
  34. 12
      ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs
  35. 203
      ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  36. 40
      ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs
  37. 3
      ICSharpCode.NRefactory.CSharp/Parser/mcs/argument.cs
  38. 3
      ICSharpCode.NRefactory.CSharp/Parser/mcs/assembly.cs
  39. 13
      ICSharpCode.NRefactory.CSharp/Parser/mcs/assign.cs
  40. 261
      ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs
  41. 3
      ICSharpCode.NRefactory.CSharp/Parser/mcs/attribute.cs
  42. 2
      ICSharpCode.NRefactory.CSharp/Parser/mcs/cfold.cs
  43. 77
      ICSharpCode.NRefactory.CSharp/Parser/mcs/class.cs
  44. 6
      ICSharpCode.NRefactory.CSharp/Parser/mcs/codegen.cs
  45. 3
      ICSharpCode.NRefactory.CSharp/Parser/mcs/complete.cs
  46. 3
      ICSharpCode.NRefactory.CSharp/Parser/mcs/constant.cs
  47. 17
      ICSharpCode.NRefactory.CSharp/Parser/mcs/context.cs
  48. 18
      ICSharpCode.NRefactory.CSharp/Parser/mcs/convert.cs
  49. 8793
      ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs
  50. 273
      ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.jay
  51. 55
      ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs
  52. 4
      ICSharpCode.NRefactory.CSharp/Parser/mcs/decl.cs
  53. 10
      ICSharpCode.NRefactory.CSharp/Parser/mcs/delegate.cs
  54. 1
      ICSharpCode.NRefactory.CSharp/Parser/mcs/doc.cs
  55. 6
      ICSharpCode.NRefactory.CSharp/Parser/mcs/driver.cs
  56. 288
      ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs
  57. 1
      ICSharpCode.NRefactory.CSharp/Parser/mcs/enum.cs
  58. 21
      ICSharpCode.NRefactory.CSharp/Parser/mcs/eval.cs
  59. 312
      ICSharpCode.NRefactory.CSharp/Parser/mcs/expression.cs
  60. 12
      ICSharpCode.NRefactory.CSharp/Parser/mcs/field.cs
  61. 306
      ICSharpCode.NRefactory.CSharp/Parser/mcs/flowanalysis.cs
  62. 166
      ICSharpCode.NRefactory.CSharp/Parser/mcs/generic.cs
  63. 11
      ICSharpCode.NRefactory.CSharp/Parser/mcs/import.cs
  64. 12
      ICSharpCode.NRefactory.CSharp/Parser/mcs/iterators.cs
  65. 1
      ICSharpCode.NRefactory.CSharp/Parser/mcs/lambda.cs
  66. 7
      ICSharpCode.NRefactory.CSharp/Parser/mcs/linq.cs
  67. 3
      ICSharpCode.NRefactory.CSharp/Parser/mcs/literal.cs
  68. 7
      ICSharpCode.NRefactory.CSharp/Parser/mcs/location.cs
  69. 116
      ICSharpCode.NRefactory.CSharp/Parser/mcs/membercache.cs
  70. 114
      ICSharpCode.NRefactory.CSharp/Parser/mcs/method.cs
  71. 10
      ICSharpCode.NRefactory.CSharp/Parser/mcs/namespace.cs
  72. 1
      ICSharpCode.NRefactory.CSharp/Parser/mcs/nullable.cs
  73. 1
      ICSharpCode.NRefactory.CSharp/Parser/mcs/parameter.cs
  74. 11
      ICSharpCode.NRefactory.CSharp/Parser/mcs/pending.cs
  75. 17
      ICSharpCode.NRefactory.CSharp/Parser/mcs/property.cs
  76. 5
      ICSharpCode.NRefactory.CSharp/Parser/mcs/report.cs
  77. 15
      ICSharpCode.NRefactory.CSharp/Parser/mcs/rootcontext.cs
  78. 10
      ICSharpCode.NRefactory.CSharp/Parser/mcs/roottypes.cs
  79. 391
      ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs
  80. 1
      ICSharpCode.NRefactory.CSharp/Parser/mcs/support.cs
  81. 109
      ICSharpCode.NRefactory.CSharp/Parser/mcs/typemanager.cs
  82. 51
      ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs
  83. 20
      ICSharpCode.NRefactory.CSharp/Parser/mcs/visit.cs
  84. 8
      ICSharpCode.NRefactory.CSharp/Properties/AssemblyInfo.cs
  85. 4
      ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateEventInvocator.cs
  86. 4
      ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateLocalVariable.cs
  87. 4
      ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs
  88. 40
      ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseExplicitType.cs
  89. 24
      ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseVarKeyword.cs
  90. 14
      ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs
  91. 197
      ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs
  92. 161
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs
  93. 40
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs
  94. 1011
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpOperators.cs
  95. 1569
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  96. 4
      ICSharpCode.NRefactory.CSharp/Resolver/CompositeResolveVisitorNavigator.cs
  97. 108
      ICSharpCode.NRefactory.CSharp/Resolver/Conversions.cs
  98. 5
      ICSharpCode.NRefactory.CSharp/Resolver/FindReferenceSearchScope.cs
  99. 157
      ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs
  100. 1
      ICSharpCode.NRefactory.CSharp/Resolver/IResolveVisitorNavigator.cs
  101. Some files were not shown because too many files have changed in this diff Show More

94
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.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
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
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
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
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
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
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
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
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

42
ICSharpCode.NRefactory.CSharp/Ast/Expressions/ErrorExpression.cs

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
//
// ErrorExpression.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 class ErrorExpression : EmptyExpression
{
public ErrorExpression ()
{
}
public ErrorExpression (TextLocation location) : base (location)
{
}
}
}

3
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
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
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

117
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
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
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);

13
ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs

@ -113,17 +113,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -113,17 +113,18 @@ namespace ICSharpCode.NRefactory.CSharp
public static Identifier Create (string name, TextLocation location)
{
if (name == null)
throw new ArgumentNullException("name");
if (name.Length > 0 && name[0] == '@')
if (string.IsNullOrEmpty(name))
return Identifier.Null;
if (name[0] == '@')
return new VerbatimIdentifier(name.Substring (1), location);
return new Identifier (name, location);
else
return new Identifier (name, location);
}
public static Identifier Create (string name, TextLocation location, bool isVerbatim)
{
if (name == null)
throw new ArgumentNullException("name");
if (string.IsNullOrEmpty(name))
return Identifier.Null;
if (isVerbatim)
return new VerbatimIdentifier(name, location);

2
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
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)

20
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
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 {

159
ICSharpCode.NRefactory.CSharp/CSharpProjectContent.cs

@ -0,0 +1,159 @@ @@ -0,0 +1,159 @@
// 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)
{
throw new NotImplementedException();
}
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);
}
}
}
}

2067
ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

File diff suppressed because it is too large Load Diff

495
ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs

@ -0,0 +1,495 @@ @@ -0,0 +1,495 @@
//
// 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;
}
// Print (baseUnit);
/* var member = Unit.GetNodeAt<AttributedNode> (memberLocation);
var member2 = baseUnit.GetNodeAt<AttributedNode> (memberLocation);
member2.Remove ();
member.ReplaceWith (member2);
var tsvisitor = new TypeSystemConvertVisitor (ProjectContent, CSharpParsedFile.FileName);
baseUnit.AcceptVisitor (tsvisitor, null);*/
return Tuple.Create (CSharpParsedFile, (AstNode)expr, baseUnit);
/*
///////
if (currentMember == null && currentType == null)
return null;
CSharpParser parser = new CSharpParser ();
int startOffset;
if (currentMember != null) {
startOffset = document.Editor.LocationToOffset (currentMember.Region.BeginLine, currentMember.Region.BeginColumn);
} else {
startOffset = document.Editor.LocationToOffset (currentType.Region.BeginLine, currentType.Region.BeginColumn);
}
string memberText = Document.Editor.GetTextBetween (startOffset, Document.Editor.Caret.Offset - 1);
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
StringBuilder wrapper = new StringBuilder ();
wrapper.Append ("class Stub {");
wrapper.AppendLine ();
wrapper.Append (memberText);
if (afterBracket) {
wrapper.Append ("();");
} else {
wrapper.Append ("x);");
}
wrapper.Append (" SomeCall (); } } }");
var stream = new System.IO.StringReader (wrapper.ToString ());
var baseUnit = parser.Parse (stream, memberLocation.Line - 2);
stream.Close ();
var expr = baseUnit.GetNodeAt<Expression> (document.Editor.Caret.Line, document.Editor.Caret.Column);
if (expr is InvocationExpression) {
expr = ((InvocationExpression)expr).Target;
}
if (expr == null)
return null;
var member = Unit.GetNodeAt<AttributedNode> (memberLocation);
var member2 = baseUnit.GetNodeAt<AttributedNode> (memberLocation);
member2.Remove ();
member.ReplaceWith (member2);
var tsvisitor = new TypeSystemConvertVisitor (ProjectContext, Document.FileName);
Unit.AcceptVisitor (tsvisitor, null);
return Tuple.Create (tsvisitor.ParsedFile, 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
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 ();
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;
if (text.Item1.EndsWith ("("))
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
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
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
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);
}
}

54
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
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;
}
}
}

119
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,27 @@ namespace ICSharpCode.NRefactory.CSharp @@ -574,10 +604,27 @@ namespace ICSharpCode.NRefactory.CSharp
public object VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, object data)
{
StartNode (arrayInitializerExpression);
PrintInitializerElements(arrayInitializerExpression.Elements);
bool bracesAreOptional = arrayInitializerExpression.Elements.Count == 1
&& IsObjectInitializer(arrayInitializerExpression.Parent);
if (bracesAreOptional && arrayInitializerExpression.LBraceToken.IsNull) {
arrayInitializerExpression.Elements.Single().AcceptVisitor(this, data);
} else {
PrintInitializerElements(arrayInitializerExpression.Elements);
}
return EndNode (arrayInitializerExpression);
}
bool IsObjectInitializer(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 +643,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -596,6 +643,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
node.AcceptVisitor(this, null);
}
OptionalComma();
NewLine();
CloseBrace(style);
}
@ -881,7 +929,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -881,7 +929,6 @@ namespace ICSharpCode.NRefactory.CSharp
{
StartNode (anonymousTypeCreateExpression);
WriteKeyword ("new");
Space ();
PrintInitializerElements(anonymousTypeCreateExpression.Initializers);
return EndNode (anonymousTypeCreateExpression);
}
@ -1306,9 +1353,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1306,9 +1353,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 +1406,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1358,6 +1406,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 +1458,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1409,6 +1458,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
member.AcceptVisitor (this, data);
}
OptionalComma();
NewLine ();
} else {
foreach (var member in typeDeclaration.Members) {
@ -1416,6 +1466,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1416,6 +1466,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
CloseBrace (braceStyle);
OptionalSemicolon ();
NewLine ();
return EndNode (typeDeclaration);
}
@ -1845,6 +1896,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1845,6 +1896,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);
@ -2261,6 +2313,25 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2261,6 +2313,25 @@ namespace ICSharpCode.NRefactory.CSharp
return null;
}
public object VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective, object data)
{
if (lastWritten == LastWritten.Division) {
// When there's a comment starting after a division operator
// "1.0 / /*comment*/a", then we need to insert a space in front of the comment.
formatter.Space ();
}
formatter.StartNode (preProcessorDirective);
formatter.WriteToken ("#" + preProcessorDirective.Type.ToString ().ToLower ());
if (!string.IsNullOrEmpty(preProcessorDirective.Argument)) {
formatter.Space();
formatter.WriteToken(preProcessorDirective.Argument);
}
formatter.NewLine();
formatter.EndNode (preProcessorDirective);
lastWritten = LastWritten.Whitespace;
return null;
}
public object VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration, object data)
{
StartNode (typeParameterDeclaration);
@ -2412,7 +2483,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2412,7 +2483,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

60
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)

5
ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertParenthesesVisitor.cs

@ -147,6 +147,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -147,6 +147,11 @@ namespace ICSharpCode.NRefactory.CSharp
public override object VisitIndexerExpression(IndexerExpression indexerExpression, object data)
{
ParenthesizeIfRequired(indexerExpression.Target, Primary);
ArrayCreateExpression ace = indexerExpression.Target as ArrayCreateExpression;
if (ace != null && (InsertParenthesesForReadability || ace.Initializer.IsNull)) {
// require parentheses for "(new int[1])[0]"
Parenthesize(indexerExpression.Target);
}
return base.VisitIndexerExpression(indexerExpression, data);
}

12
ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs

@ -75,11 +75,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -75,11 +75,13 @@ namespace ICSharpCode.NRefactory.CSharp
public void OpenBrace(BraceStyle style)
{
bool isAtStartOfLine = needsIndent;
switch (style) {
case BraceStyle.DoNotChange:
case BraceStyle.EndOfLine:
WriteIndentation();
textWriter.Write(' ');
if (!isAtStartOfLine)
textWriter.Write(' ');
textWriter.Write('{');
break;
case BraceStyle.EndOfLineWithoutSpace:
@ -87,7 +89,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -87,7 +89,8 @@ namespace ICSharpCode.NRefactory.CSharp
textWriter.Write('{');
break;
case BraceStyle.NextLine:
NewLine ();
if (!isAtStartOfLine)
NewLine();
WriteIndentation();
textWriter.Write('{');
break;
@ -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,6 +185,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -181,6 +185,10 @@ namespace ICSharpCode.NRefactory.CSharp
case CommentType.Documentation:
textWriter.Write("///");
textWriter.WriteLine(content);
needsIndent = true;
break;
default:
textWriter.Write(content);
break;
}
}

203
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));
@ -1419,18 +1429,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1419,18 +1429,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 +1452,32 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1442,9 +1452,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 +1615,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1582,7 +1615,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;
}
@ -2252,6 +2286,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2252,6 +2286,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);
@ -2639,7 +2675,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2639,7 +2675,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 +2924,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2885,14 +2924,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 +2947,31 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2903,24 +2947,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 +2989,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2938,7 +2989,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 +3240,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3186,6 +3240,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 +3284,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3220,11 +3284,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 +3299,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3237,37 +3299,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 +3319,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3280,7 +3319,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 +3331,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3288,7 +3331,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 +3343,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3296,7 +3343,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 +3404,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3353,7 +3404,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 +3415,21 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3364,21 +3415,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 +3439,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3388,10 +3439,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 +3462,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3410,12 +3462,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 +3481,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3424,7 +3481,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
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
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;

3
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
//

13
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
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
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
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
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
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
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
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
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
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);

8793
ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs

File diff suppressed because it is too large Load Diff

273
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,7 +151,6 @@ namespace Mono.CSharp @@ -149,7 +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;
@ -885,7 +886,7 @@ named_attribute_argument @@ -885,7 +886,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 +1255,14 @@ method_declaration @@ -1254,14 +1255,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 +1316,9 @@ method_header @@ -1315,15 +1316,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 +1354,6 @@ method_header @@ -1359,7 +1354,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 +1364,10 @@ method_header @@ -1370,25 +1364,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 +1385,8 @@ method_header @@ -1406,8 +1385,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 +2543,6 @@ enum_declaration @@ -2564,9 +2543,6 @@ enum_declaration
: opt_attributes
opt_modifiers
ENUM
{
enumCommas.Add (GetLocation ($3));
}
type_declaration_name
opt_enum_base
{
@ -2577,14 +2553,18 @@ enum_declaration @@ -2577,14 +2553,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 +2574,16 @@ enum_declaration @@ -2594,16 +2574,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 +2597,7 @@ opt_enum_base @@ -2617,7 +2597,7 @@ opt_enum_base
Enum.Error_1008 (GetLocation ($2), report);
$$ = null;
} else {
enumCommas.Add (GetLocation ($1));
savedLocation = GetLocation ($1);
$$ = $2;
}
}
@ -2633,7 +2613,7 @@ opt_enum_member_declarations @@ -2633,7 +2613,7 @@ opt_enum_member_declarations
| enum_member_declarations
| enum_member_declarations COMMA
{
enumCommas.Add (GetLocation ($2));
lbag.AppendToMember (current_class, GetLocation ($2));
}
;
@ -2641,7 +2621,7 @@ enum_member_declarations @@ -2641,7 +2621,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 +3381,14 @@ element_access @@ -3401,6 +3381,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 +3719,13 @@ typeof_type_expression @@ -3731,13 +3719,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 +3733,7 @@ unbound_type_name @@ -3745,7 +3733,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 +3741,7 @@ unbound_type_name @@ -3753,7 +3741,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 +3749,7 @@ unbound_type_name @@ -3761,7 +3749,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 +3836,12 @@ anonymous_method_expression @@ -3848,6 +3836,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 +3888,20 @@ unary_expression @@ -3894,22 +3888,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 +4181,13 @@ lambda_parameter_list @@ -4189,13 +4181,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 +4248,7 @@ lambda_expression @@ -4256,7 +4248,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 +4271,7 @@ lambda_expression @@ -4279,7 +4271,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 +4285,7 @@ lambda_expression @@ -4293,7 +4285,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 +4718,16 @@ statement @@ -4726,6 +4718,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 +4818,7 @@ empty_statement @@ -4816,7 +4818,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 +4926,19 @@ pointer_star @@ -4924,8 +4926,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 +4951,7 @@ block_variable_declaration @@ -4938,7 +4951,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 +4977,20 @@ opt_local_variable_initializer @@ -4964,6 +4977,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 +5024,7 @@ variable_declarators @@ -4997,7 +5024,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 +5033,7 @@ variable_declarator @@ -5006,7 +5033,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 +5067,7 @@ const_declarators @@ -5040,7 +5067,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 +5116,7 @@ statement_expression @@ -5089,7 +5116,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);
}
@ -5256,6 +5283,9 @@ for_statement @@ -5256,6 +5283,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 +5296,25 @@ for_statement @@ -5266,17 +5296,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 +5331,7 @@ opt_for_initializer @@ -5293,7 +5331,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 +5383,7 @@ foreach_statement @@ -5345,7 +5383,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;
@ -5393,7 +5431,7 @@ continue_statement @@ -5393,7 +5431,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 +5466,7 @@ throw_statement @@ -5428,7 +5466,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 +5478,11 @@ yield_statement @@ -5440,11 +5478,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 +5492,7 @@ yield_statement @@ -5454,7 +5492,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));
}
@ -5515,7 +5553,7 @@ catch_clauses @@ -5515,7 +5553,7 @@ catch_clauses
opt_identifier
: /* empty */
| IDENTIFIER
| identifier_inside_body
;
catch_clause
@ -5591,7 +5629,7 @@ lock_statement @@ -5591,7 +5629,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 +5657,7 @@ fixed_statement @@ -5619,7 +5657,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 +5667,20 @@ using_statement @@ -5629,20 +5667,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 +5693,15 @@ using_statement @@ -5655,6 +5693,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 +5758,7 @@ query_expression @@ -5711,7 +5758,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 +5766,7 @@ first_from_clause @@ -5719,7 +5766,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 +5781,7 @@ first_from_clause @@ -5734,7 +5781,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 +5789,7 @@ nested_from_clause @@ -5742,7 +5789,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 +5804,7 @@ nested_from_clause @@ -5757,7 +5804,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 +5819,7 @@ from_clause @@ -5772,7 +5819,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 +5923,7 @@ query_body_clause @@ -5876,7 +5923,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 +5956,7 @@ where_clause @@ -5909,7 +5956,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 +6018,7 @@ join_clause @@ -5971,7 +6018,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 +6086,7 @@ join_clause @@ -6039,7 +6086,7 @@ join_clause
opt_join_into
: /* empty */
| INTO IDENTIFIER
| INTO identifier_inside_body
{
$$ = $2;
}
@ -6128,7 +6175,7 @@ then_by @@ -6128,7 +6175,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 +6714,7 @@ void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync @@ -6667,7 +6714,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 +6729,7 @@ void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync @@ -6682,7 +6729,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 +6742,13 @@ AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) @@ -6695,10 +6742,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 +7228,7 @@ static string GetTokenName (int token) @@ -7178,6 +7228,7 @@ static string GetTokenName (int token)
case Token.LITERAL:
return "value";
case Token.IDENTIFIER:
case Token.AWAIT:
return "identifier";
case Token.EOF:

55
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,7 +829,7 @@ namespace Mono.CSharp @@ -830,7 +829,7 @@ namespace Mono.CSharp
break;
case Token.AWAIT:
if (!async_block)
if (parsing_block == 0)
res = -1;
break;
@ -1879,6 +1878,8 @@ namespace Mono.CSharp @@ -1879,6 +1878,8 @@ namespace Mono.CSharp
int has_identifier_argument = (int)(cmd & PreprocessorDirective.RequiresArgument);
int pos = 0;
endLine = line;
endCol = col;
while (c != -1 && c != '\n' && c != '\r') {
if (c == '\\' && has_identifier_argument >= 0) {
@ -1934,7 +1935,7 @@ namespace Mono.CSharp @@ -1934,7 +1935,7 @@ namespace Mono.CSharp
arg = arg.Trim (simple_whitespaces);
}
if (position_stack.Count == 0)
sbag.AddPreProcessorDirective (startLine, startCol, endLine, endCol, cmd, arg);
sbag.AddPreProcessorDirective (startLine, startCol, endLine, endCol + 1, cmd, arg);
return cmd;
}
@ -2240,7 +2241,7 @@ namespace Mono.CSharp @@ -2240,7 +2241,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 +2879,7 @@ namespace Mono.CSharp @@ -2878,7 +2879,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 +3216,16 @@ namespace Mono.CSharp @@ -3215,14 +3216,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 +3237,16 @@ namespace Mono.CSharp @@ -3234,16 +3237,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 +3262,15 @@ namespace Mono.CSharp @@ -3259,16 +3262,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 +3348,7 @@ namespace Mono.CSharp @@ -3346,7 +3348,7 @@ namespace Mono.CSharp
if (ParsePreprocessingDirective (true))
continue;
sbag.StartComment (SpecialsBag.CommentType.Multi, false, line, col);
bool directive_expected = false;
while ((c = get_char ()) != -1) {
if (col == 1) {
@ -3360,23 +3362,26 @@ namespace Mono.CSharp @@ -3360,23 +3362,26 @@ namespace Mono.CSharp
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 +3449,7 @@ namespace Mono.CSharp @@ -3444,7 +3449,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
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
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
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
//
//

6
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;

288
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
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
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);

312
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));
@ -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
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
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;

166
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);
}
@ -3347,7 +3383,7 @@ namespace Mono.CSharp { @@ -3347,7 +3383,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
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
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
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
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
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;

7
ICSharpCode.NRefactory.CSharp/Parser/mcs/location.cs

@ -545,6 +545,7 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format (" @@ -545,6 +545,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 +566,21 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format (" @@ -565,15 +566,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
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
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
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
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
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
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
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
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
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
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 ();

391
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);
@ -1299,6 +1304,7 @@ namespace Mono.CSharp { @@ -1299,6 +1304,7 @@ namespace Mono.CSharp {
Block Block { get; }
Expression CreateReferenceExpression (ResolveContext rc, Location loc);
bool IsDeclared { get; }
bool IsParameter { get; }
Location Location { get; }
}
@ -1402,6 +1408,9 @@ namespace Mono.CSharp { @@ -1402,6 +1408,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 +1466,13 @@ namespace Mono.CSharp { @@ -1457,6 +1466,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 +1668,9 @@ namespace Mono.CSharp { @@ -1652,8 +1668,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 +1733,12 @@ namespace Mono.CSharp { @@ -1716,6 +1733,12 @@ namespace Mono.CSharp {
}
}
bool INamedBlockVariable.IsParameter {
get {
return false;
}
}
public bool IsReadonly {
get {
return (flags & Flags.ReadonlyMask) != 0;
@ -1874,6 +1897,11 @@ namespace Mono.CSharp { @@ -1874,6 +1897,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 +1929,14 @@ namespace Mono.CSharp { @@ -1901,12 +1929,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 +2128,9 @@ namespace Mono.CSharp { @@ -2098,6 +2128,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 +2215,7 @@ namespace Mono.CSharp { @@ -2182,6 +2215,7 @@ namespace Mono.CSharp {
if (this == ParametersBlock.TopBlock && !ParametersBlock.TopBlock.IsThisAssigned (ec) && !flow_unreachable)
ok = false;
flags |= Flags.Resolved;
return ok;
}
@ -2292,6 +2326,12 @@ namespace Mono.CSharp { @@ -2292,6 +2326,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 +2346,12 @@ namespace Mono.CSharp { @@ -2306,6 +2346,12 @@ namespace Mono.CSharp {
}
}
public bool HasYield {
get {
return (flags & Flags.YieldBlock) != 0;
}
}
#endregion
//
@ -2314,15 +2360,17 @@ namespace Mono.CSharp { @@ -2314,15 +2360,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 +2457,32 @@ namespace Mono.CSharp { @@ -2409,6 +2457,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 +2524,12 @@ namespace Mono.CSharp { @@ -2450,6 +2524,12 @@ namespace Mono.CSharp {
}
}
public bool IsParameter {
get {
return true;
}
}
public bool IsLocked {
get {
return is_locked;
@ -2545,6 +2625,8 @@ namespace Mono.CSharp { @@ -2545,6 +2625,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 +2666,12 @@ namespace Mono.CSharp { @@ -2584,13 +2666,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 +2701,7 @@ namespace Mono.CSharp { @@ -2620,7 +2701,7 @@ namespace Mono.CSharp {
public bool Resolved {
get {
return resolved;
return (flags & Flags.Resolved) != 0;
}
}
@ -2631,7 +2712,7 @@ namespace Mono.CSharp { @@ -2631,7 +2712,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 +2728,10 @@ namespace Mono.CSharp { @@ -2647,8 +2728,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 +2875,14 @@ namespace Mono.CSharp { @@ -2792,12 +2875,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 +2890,7 @@ namespace Mono.CSharp { @@ -2805,6 +2890,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 +2900,7 @@ namespace Mono.CSharp { @@ -2814,6 +2900,7 @@ namespace Mono.CSharp {
statements = new List<Statement> (1);
AddStatement (new StatementExpression (initializer));
flags &= ~Flags.AwaitBlock;
}
}
@ -2860,13 +2947,9 @@ namespace Mono.CSharp { @@ -2860,13 +2947,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 +3197,14 @@ namespace Mono.CSharp { @@ -3114,15 +3197,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 +3445,32 @@ namespace Mono.CSharp { @@ -3363,6 +3445,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 +3497,8 @@ namespace Mono.CSharp { @@ -3389,6 +3497,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 +3683,7 @@ namespace Mono.CSharp { @@ -3573,7 +3683,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 +3715,7 @@ namespace Mono.CSharp { @@ -3605,7 +3715,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 +3916,13 @@ namespace Mono.CSharp { @@ -3806,6 +3916,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 +3949,7 @@ namespace Mono.CSharp { @@ -3832,8 +3949,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 +3957,15 @@ namespace Mono.CSharp { @@ -3841,9 +3957,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 +3982,45 @@ namespace Mono.CSharp { @@ -3860,6 +3982,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 +4085,7 @@ namespace Mono.CSharp { @@ -3924,7 +4085,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 +4139,7 @@ namespace Mono.CSharp { @@ -3978,7 +4139,7 @@ namespace Mono.CSharp {
EmitTableSwitch (ec, string_switch_variable);
string_switch_variable.Release (ec);
}
protected override void DoEmit (EmitContext ec)
{
//
@ -3990,21 +4151,13 @@ namespace Mono.CSharp { @@ -3990,21 +4151,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 +4173,13 @@ namespace Mono.CSharp { @@ -4020,14 +4173,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);
@ -5395,8 +5547,8 @@ namespace Mono.CSharp { @@ -5395,8 +5547,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 +5569,6 @@ namespace Mono.CSharp { @@ -5417,7 +5569,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 +5589,7 @@ namespace Mono.CSharp { @@ -5438,7 +5589,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 +5639,8 @@ namespace Mono.CSharp { @@ -5488,7 +5639,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);
@ -6009,4 +6161,35 @@ namespace Mono.CSharp { @@ -6009,4 +6161,35 @@ namespace Mono.CSharp {
return visitor.Visit (this);
}
}
public class StatementErrorExpression : Statement
{
readonly Expression expr;
public Expression Expression {
get {
return expr;
}
}
public StatementErrorExpression (Expression expr)
{
this.expr = expr;
}
protected override void DoEmit (EmitContext ec)
{
throw new NotImplementedException ();
}
protected override void CloneTo (CloneContext clonectx, Statement target)
{
throw new NotImplementedException ();
}
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
}
}
}

1
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
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}'",

51
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,34 @@ namespace Mono.CSharp @@ -340,6 +362,34 @@ 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;
}
public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
{
if (Kind != MemberKind.Class)
@ -1247,6 +1297,7 @@ namespace Mono.CSharp @@ -1247,6 +1297,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;

20
ICSharpCode.NRefactory.CSharp/Parser/mcs/visit.cs

@ -183,6 +183,11 @@ namespace Mono.CSharp @@ -183,6 +183,11 @@ namespace Mono.CSharp
{
return null;
}
public virtual object Visit (ErrorExpression errorExpression)
{
return null;
}
public virtual object Visit (If ifStatement)
{
@ -337,6 +342,11 @@ namespace Mono.CSharp @@ -337,6 +342,11 @@ namespace Mono.CSharp
{
return null;
}
public virtual object Visit (InvalidStatementExpression invalidStatementExpression)
{
return null;
}
public virtual object Visit (Expression expression)
{
@ -631,5 +641,15 @@ namespace Mono.CSharp @@ -631,5 +641,15 @@ namespace Mono.CSharp
{
return null;
}
public virtual object Visit (Await awaitExpr)
{
return null;
}
public virtual object Visit (StatementErrorExpression statementErrorExpression)
{
return null;
}
}
}

8
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")]

4
ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateEventInvocator.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// CreateEventInvocator.cs
//
// Author:
@ -84,7 +84,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -84,7 +84,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
};
foreach (var par in pars) {
var typeName = context.CreateShortType (par.Type.Resolve (context.TypeResolveContext));
var typeName = context.CreateShortType (par.Type);
var decl = new ParameterDeclaration (typeName, par.Name);
methodDeclaration.Parameters.Add (decl);
}

4
ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateLocalVariable.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// CreateLocalVariable.cs
//
// Author:
@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
if (result.Parameters.Count < i)
return null;
return context.CreateShortType (result.Parameters[i].Type.Resolve (context.TypeResolveContext));
return context.CreateShortType (result.Parameters[i].Type);
}
return null;
}

4
ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs

@ -49,8 +49,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -49,8 +49,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var type = result.Type;
var newSwitch = (SwitchStatement)switchStatement.Clone ();
var target = new TypeReferenceExpression (context.CreateShortType (result.Type.Resolve (context.TypeResolveContext)));
foreach (var field in type.GetFields (context.TypeResolveContext)) {
var target = new TypeReferenceExpression (context.CreateShortType (result.Type));
foreach (var field in type.GetFields ()) {
if (field.IsSynthetic || !field.IsConst)
continue;
newSwitch.SwitchSections.Add (new SwitchSection () {

40
ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseExplicitType.cs

@ -36,32 +36,54 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -36,32 +36,54 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public bool IsValid (RefactoringContext context)
{
var varDecl = GetVariableDeclarationStatement (context);
if (varDecl == null)
return false;
var type = context.Resolve (varDecl.Variables.First ().Initializer).Type;
return !type.Equals (SharedTypes.Null) && !type.Equals (SharedTypes.UnknownType);
IType type;
if (varDecl != null) {
type = context.Resolve (varDecl.Variables.First ().Initializer).Type;
} else {
var foreachStatement = GetForeachStatement (context);
if (foreachStatement == null)
return false;
type = context.Resolve (foreachStatement.VariableType).Type;
}
return !type.Equals (SpecialType.NullType) && !type.Equals (SpecialType.UnknownType);
}
public void Run (RefactoringContext context)
{
var varDecl = GetVariableDeclarationStatement (context);
using (var script = context.StartScript ()) {
var type = context.Resolve (varDecl.Variables.First ().Initializer).Type;
script.Replace (varDecl.Type, context.CreateShortType (type));
var varDecl = GetVariableDeclarationStatement (context);
if (varDecl != null) {
var type = context.Resolve (varDecl.Variables.First ().Initializer).Type;
script.Replace (varDecl.Type, context.CreateShortType (type));
} else {
var foreachStatement = GetForeachStatement (context);
var type = context.Resolve (foreachStatement.VariableType).Type;
script.Replace (foreachStatement.VariableType, context.CreateShortType (type));
}
}
}
static readonly AstType varType = new SimpleType ("var");
static VariableDeclarationStatement GetVariableDeclarationStatement (RefactoringContext context)
{
var result = context.GetNode<VariableDeclarationStatement> ();
if (result != null && result.Variables.Count == 1 && !result.Variables.First ().Initializer.IsNull && result.Type.Contains (context.Location.Line, context.Location.Column) && result.Type.IsMatch (new SimpleType ("var"))) {
if (result != null && result.Variables.Count == 1 && !result.Variables.First ().Initializer.IsNull && result.Type.Contains (context.Location.Line, context.Location.Column) && result.Type.IsMatch (varType)) {
if (context.Resolve (result.Variables.First ().Initializer) == null)
return null;
return result;
}
return null;
}
static ForeachStatement GetForeachStatement (RefactoringContext context)
{
var result = context.GetNode<ForeachStatement> ();
if (result != null && result.VariableType.Contains (context.Location) && result.VariableType.IsMatch (varType))
return result;
return null;
}
}
}

24
ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseVarKeyword.cs

@ -29,25 +29,39 @@ using ICSharpCode.NRefactory.PatternMatching; @@ -29,25 +29,39 @@ using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
public class UseVarKeyword: IContextAction
public class UseVarKeyword : IContextAction
{
public bool IsValid (RefactoringContext context)
{
return GetVariableDeclarationStatement (context) != null;
return GetVariableDeclarationStatement (context) != null || GetForeachStatement (context) != null;
}
public void Run (RefactoringContext context)
{
var varDecl = GetVariableDeclarationStatement (context);
using (var script = context.StartScript ()) {
script.Replace (varDecl.Type, new SimpleType ("var"));
var varDecl = GetVariableDeclarationStatement (context);
if (varDecl != null) {
script.Replace (varDecl.Type, new SimpleType ("var"));
} else {
script.Replace (GetForeachStatement (context).VariableType, new SimpleType ("var"));
}
}
}
static readonly AstType varType = new SimpleType ("var");
static VariableDeclarationStatement GetVariableDeclarationStatement (RefactoringContext context)
{
var result = context.GetNode<VariableDeclarationStatement> ();
if (result != null && result.Variables.Count == 1 && !result.Variables.First ().Initializer.IsNull && result.Type.Contains (context.Location.Line, context.Location.Column) && !result.Type.IsMatch (new SimpleType ("var")))
if (result != null && result.Variables.Count == 1 && !result.Variables.First ().Initializer.IsNull && result.Type.Contains (context.Location) && !result.Type.IsMatch (varType))
return result;
return null;
}
static ForeachStatement GetForeachStatement (RefactoringContext context)
{
var result = context.GetNode<ForeachStatement> ();
if (result != null && result.VariableType.Contains (context.Location) && !result.VariableType.IsMatch (varType))
return result;
return null;
}

14
ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs

@ -39,12 +39,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -39,12 +39,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
protected set;
}
public virtual ITypeResolveContext TypeResolveContext {
get {
return null;
}
}
public TextLocation Location {
get;
protected set;
@ -62,12 +56,14 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -62,12 +56,14 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public AstType CreateShortType (string ns, string typeName)
{
return CreateShortType (TypeResolveContext.GetTypeDefinition (ns, typeName, 0, StringComparer.Ordinal));
throw new NotImplementedException();
//return CreateShortType (TypeResolveContext.GetTypeDefinition (ns, typeName, 0, StringComparer.Ordinal));
}
public virtual AstType CreateShortType (AstType fullType)
{
return CreateShortType (Resolve (fullType).Type.Resolve (TypeResolveContext));
throw new NotImplementedException();
//return CreateShortType (Resolve (fullType).Type.Resolve (TypeResolveContext));
}
// public abstract IType GetDefinition (AstType resolvedType);
@ -133,7 +129,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -133,7 +129,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
#region ConvertTypes
public static ICSharpCode.NRefactory.CSharp.AstType ConvertToAstType (this IType type)
{
var builder = new TypeSystemAstBuilder (MinimalResolveContext.Instance);
var builder = new TypeSystemAstBuilder ();
return builder.ConvertType (type);
}
#endregion

197
ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs

@ -5,8 +5,8 @@ using System; @@ -5,8 +5,8 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
@ -20,7 +20,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -20,7 +20,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public class TypeSystemAstBuilder
{
readonly CSharpResolver resolver;
readonly ITypeResolveContext context;
#region Constructor
/// <summary>
@ -34,7 +33,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -34,7 +33,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolver == null)
throw new ArgumentNullException("resolver");
this.resolver = resolver;
this.context = resolver.Context;
InitProperties();
}
@ -44,11 +42,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -44,11 +42,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
/// <param name="context">
/// Context used for resolving types.
/// </param>
public TypeSystemAstBuilder(ITypeResolveContext context)
public TypeSystemAstBuilder()
{
if (context == null)
throw new ArgumentNullException("context");
this.context = context;
InitProperties();
}
#endregion
@ -100,6 +95,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -100,6 +95,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
/// Controls whether to show default values of optional parameters, and the values of constant fields.
/// </summary>
public bool ShowConstantValues { get; set; }
/// <summary>
/// Controls whether to use fully-qualified type names or short type names.
/// </summary>
public bool AlwaysUseShortTypeNames { get; set; }
#endregion
#region Convert Type
@ -131,7 +131,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -131,7 +131,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
// Unbound type
IType[] typeArguments = new IType[typeDef.TypeParameterCount];
for (int i = 0; i < typeArguments.Length; i++) {
typeArguments[i] = SharedTypes.UnboundTypeArgument;
typeArguments[i] = SpecialType.UnboundTypeArgument;
}
return ConvertTypeHelper(typeDef, typeArguments);
} else {
@ -141,62 +141,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -141,62 +141,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return new SimpleType(type.Name);
}
public AstType ConvertTypeReference(ITypeReference typeRef)
{
ArrayTypeReference array = typeRef as ArrayTypeReference;
if (array != null) {
return ConvertTypeReference(array.ElementType).MakeArrayType(array.Dimensions);
}
PointerTypeReference pointer = typeRef as PointerTypeReference;
if (pointer != null) {
return ConvertTypeReference(pointer.ElementType).MakePointerType();
}
ByReferenceType brt = typeRef as ByReferenceType;
if (brt != null) {
return ConvertTypeReference(brt.ElementType);
}
IType type = typeRef.Resolve(context);
if (type.Kind != TypeKind.Unknown)
return ConvertType(type);
// Unknown type, let's try if we can find an appropriate type
// (anything is better than displaying a question mark)
KnownTypeReference knownType = typeRef as KnownTypeReference;
if (knownType != null) {
string keyword = ReflectionHelper.GetCSharpNameByTypeCode(knownType.TypeCode);
if (keyword != null)
return new PrimitiveType(keyword);
}
SimpleTypeOrNamespaceReference str = typeRef as SimpleTypeOrNamespaceReference;
if (str != null) {
return new SimpleType(str.Identifier, str.TypeArguments.Select(ConvertTypeReference));
}
MemberTypeOrNamespaceReference mtr = typeRef as MemberTypeOrNamespaceReference;
if (mtr != null) {
return new MemberType(ConvertTypeReference(mtr.Target), mtr.Identifier, mtr.TypeArguments.Select(ConvertTypeReference)) {
IsDoubleColon = mtr.Target is AliasNamespaceReference
};
}
AliasNamespaceReference alias = typeRef as AliasNamespaceReference;
if (alias != null) {
return new SimpleType(alias.Identifier);
}
// Unknown type reference that couldn't be resolved
return new SimpleType("?");
}
AstType ConvertTypeHelper(ITypeDefinition typeDef, IList<IType> typeArguments)
{
Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount);
TypeCode typeCode = ReflectionHelper.GetTypeCode(typeDef);
if (typeCode != TypeCode.Empty) {
string keyword = ReflectionHelper.GetCSharpNameByTypeCode(typeCode);
if (keyword != null)
return new PrimitiveType(keyword);
}
// There is no type code for System.Void
if (typeDef.Kind == TypeKind.Void)
return new PrimitiveType("void");
string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode);
if (keyword != null)
return new PrimitiveType(keyword);
// The number of type parameters belonging to outer classes
int outerTypeParameterCount;
@ -207,11 +158,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -207,11 +158,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolver != null) {
// Look if there's an alias to the target type
for (UsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) {
for (ResolvedUsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) {
foreach (var pair in usingScope.UsingAliases) {
IType type = pair.Value.Resolve(resolver.Context);
if (TypeMatches(type, typeDef, typeArguments))
return new SimpleType(pair.Key);
if (pair.Value is TypeResolveResult) {
if (TypeMatches(pair.Value.Type, typeDef, typeArguments))
return new SimpleType(pair.Key);
}
}
}
@ -233,6 +185,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -233,6 +185,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
}
if (AlwaysUseShortTypeNames) {
var shortResult = new SimpleType(typeDef.Name);
AddTypeArguments(shortResult, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount);
return shortResult;
}
MemberType result = new MemberType();
if (typeDef.DeclaringTypeDefinition != null) {
// Handle nested types
@ -292,10 +250,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -292,10 +250,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
if (resolver != null) {
// Look if there's an alias to the target namespace
for (UsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) {
for (ResolvedUsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) {
foreach (var pair in usingScope.UsingAliases) {
// maybe add some caching? we're resolving all aliases N times when converting a namespace name with N parts
NamespaceResolveResult nrr = pair.Value.ResolveNamespace(resolver.Context);
NamespaceResolveResult nrr = pair.Value as NamespaceResolveResult;
if (nrr != null && nrr.NamespaceName == ns)
return new SimpleType(pair.Key);
}
@ -332,16 +289,33 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -332,16 +289,33 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
#endregion
#region Convert Constant Value
public Expression ConvertConstantValue(IConstantValue constantValue)
#region Convert Attribute
public Attribute ConvertAttribute(IAttribute attribute)
{
if (constantValue == null)
throw new ArgumentNullException("constantValue");
return ConvertConstantValue(constantValue.Resolve(context));
Attribute attr = new Attribute();
attr.Type = ConvertType(attribute.AttributeType);
SimpleType st = attr.Type as SimpleType;
MemberType mt = attr.Type as MemberType;
if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) {
st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - 9);
} else if (mt != null && mt.MemberName.EndsWith("Attribute", StringComparison.Ordinal)) {
mt.MemberName = mt.MemberName.Substring(0, mt.MemberName.Length - 9);
}
foreach (ResolveResult arg in attribute.PositionalArguments) {
attr.Arguments.Add(ConvertConstantValue(arg));
}
foreach (var pair in attribute.NamedArguments) {
attr.Arguments.Add(new NamedExpression(pair.Key.Name, ConvertConstantValue(pair.Value)));
}
return attr;
}
#endregion
Expression ConvertConstantValue(ResolveResult rr)
#region Convert Constant Value
public Expression ConvertConstantValue(ResolveResult rr)
{
if (rr == null)
throw new ArgumentNullException("rr");
if (rr is TypeOfResolveResult) {
return new TypeOfExpression(ConvertType(((TypeOfResolveResult)rr).Type));
} else if (rr is ArrayCreateResolveResult) {
@ -349,21 +323,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -349,21 +323,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
AstType type = ConvertType(acrr.Type);
throw new NotImplementedException();
} else if (rr.IsCompileTimeConstant) {
object val = rr.ConstantValue;
if (val == null) {
if (rr.Type.IsReferenceType(context) == true)
return new NullReferenceExpression();
else
return new DefaultValueExpression(ConvertType(rr.Type));
} else if (rr.Type.Kind == TypeKind.Enum) {
throw new NotImplementedException();
} else {
return new PrimitiveExpression(val);
}
return ConvertConstantValue(rr.Type, rr.ConstantValue);
} else {
return new EmptyExpression();
}
}
public Expression ConvertConstantValue(IType type, object constantValue)
{
if (type == null)
throw new ArgumentNullException("type");
if (constantValue == null) {
if (type.IsReferenceType == true)
return new NullReferenceExpression();
else
return new DefaultValueExpression(ConvertType(type));
} else if (type.Kind == TypeKind.Enum) {
return new CastExpression(ConvertType(type), ConvertConstantValue(type.GetDefinition().EnumUnderlyingType, constantValue));
} else {
return new PrimitiveExpression(constantValue);
}
}
#endregion
#region Convert Parameter
@ -379,12 +359,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -379,12 +359,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} else if (parameter.IsParams) {
decl.ParameterModifier = ParameterModifier.Params;
}
decl.Type = ConvertTypeReference(parameter.Type);
decl.Type = ConvertType(parameter.Type);
if (this.ShowParameterNames) {
decl.Name = parameter.Name;
}
if (parameter.IsOptional && this.ShowConstantValues) {
decl.DefaultExpression = ConvertConstantValue(parameter.DefaultValue);
decl.DefaultExpression = ConvertConstantValue(parameter.Type, parameter.ConstantValue);
}
return decl;
}
@ -462,15 +442,17 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -462,15 +442,17 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
decl.ClassType = classType;
decl.Name = typeDefinition.Name;
int outerTypeParameterCount = (typeDefinition.DeclaringTypeDefinition == null) ? 0 : typeDefinition.DeclaringTypeDefinition.TypeParameterCount;
if (this.ShowTypeParameters) {
foreach (ITypeParameter tp in typeDefinition.TypeParameters) {
foreach (ITypeParameter tp in typeDefinition.TypeParameters.Skip(outerTypeParameterCount)) {
decl.TypeParameters.Add(ConvertTypeParameter(tp));
}
}
if (this.ShowBaseTypes) {
foreach (ITypeReference baseType in typeDefinition.BaseTypes) {
decl.BaseTypes.Add(ConvertTypeReference(baseType));
foreach (IType baseType in typeDefinition.DirectBaseTypes) {
decl.BaseTypes.Add(ConvertType(baseType));
}
}
@ -490,7 +472,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -490,7 +472,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
DelegateDeclaration decl = new DelegateDeclaration();
decl.Modifiers = modifiers;
decl.ReturnType = ConvertTypeReference(invokeMethod.ReturnType);
decl.ReturnType = ConvertType(invokeMethod.ReturnType);
decl.Name = d.Name;
if (this.ShowTypeParameters) {
@ -528,10 +510,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -528,10 +510,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
decl.Modifiers = m;
}
decl.ReturnType = ConvertTypeReference(field.ReturnType);
decl.ReturnType = ConvertType(field.ReturnType);
Expression initializer = null;
if (field.IsConst && this.ShowConstantValues)
initializer = ConvertConstantValue(field.ConstantValue);
initializer = ConvertConstantValue(field.Type, field.ConstantValue);
decl.Variables.Add(new VariableInitializer(field.Name, initializer));
return decl;
}
@ -549,7 +531,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -549,7 +531,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
PropertyDeclaration decl = new PropertyDeclaration();
decl.Modifiers = GetMemberModifiers(property);
decl.ReturnType = ConvertTypeReference(property.ReturnType);
decl.ReturnType = ConvertType(property.ReturnType);
decl.Name = property.Name;
decl.Getter = ConvertAccessor(property.Getter);
decl.Setter = ConvertAccessor(property.Setter);
@ -560,7 +542,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -560,7 +542,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
IndexerDeclaration decl = new IndexerDeclaration();
decl.Modifiers = GetMemberModifiers(indexer);
decl.ReturnType = ConvertTypeReference(indexer.ReturnType);
decl.ReturnType = ConvertType(indexer.ReturnType);
foreach (IParameter p in indexer.Parameters) {
decl.Parameters.Add(ConvertParameter(p));
}
@ -573,7 +555,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -573,7 +555,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
EventDeclaration decl = new EventDeclaration();
decl.Modifiers = GetMemberModifiers(ev);
decl.ReturnType = ConvertTypeReference(ev.ReturnType);
decl.ReturnType = ConvertType(ev.ReturnType);
decl.Variables.Add(new VariableInitializer(ev.Name));
return decl;
}
@ -582,7 +564,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -582,7 +564,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
MethodDeclaration decl = new MethodDeclaration();
decl.Modifiers = GetMemberModifiers(method);
decl.ReturnType = ConvertTypeReference(method.ReturnType);
decl.ReturnType = ConvertType(method.ReturnType);
decl.Name = method.Name;
if (this.ShowTypeParameters) {
@ -595,7 +577,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -595,7 +577,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
decl.Parameters.Add(ConvertParameter(p));
}
if (this.ShowTypeParameters && this.ShowTypeParameterConstraints) {
if (this.ShowTypeParameters && this.ShowTypeParameterConstraints && !method.IsOverride && !method.IsExplicitInterfaceImplementation) {
foreach (ITypeParameter tp in method.TypeParameters) {
var constraint = ConvertTypeParameterConstraint(tp);
if (constraint != null)
@ -614,7 +596,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -614,7 +596,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
OperatorDeclaration decl = new OperatorDeclaration();
decl.Modifiers = GetMemberModifiers(op);
decl.OperatorType = opType.Value;
decl.ReturnType = ConvertTypeReference(op.ReturnType);
decl.ReturnType = ConvertType(op.ReturnType);
foreach (IParameter p in op.Parameters) {
decl.Parameters.Add(ConvertParameter(p));
}
@ -696,7 +678,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -696,7 +678,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Constraint ConvertTypeParameterConstraint(ITypeParameter tp)
{
if (tp.Constraints.Count == 0 && !tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint) {
if (!tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint && tp.DirectBaseTypes.All(IsObjectOrValueType)) {
return null;
}
Constraint c = new Constraint();
@ -706,14 +688,21 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -706,14 +688,21 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} else if (tp.HasValueTypeConstraint) {
c.BaseTypes.Add(new PrimitiveType("struct"));
}
foreach (ITypeReference tr in tp.Constraints) {
c.BaseTypes.Add(ConvertTypeReference(tr));
foreach (IType t in tp.DirectBaseTypes) {
if (!IsObjectOrValueType(t))
c.BaseTypes.Add(ConvertType(t));
}
if (tp.HasDefaultConstructorConstraint) {
c.BaseTypes.Add(new PrimitiveType("new"));
}
return c;
}
static bool IsObjectOrValueType(IType type)
{
ITypeDefinition d = type.GetDefinition();
return d != null && (d.KnownTypeCode == KnownTypeCode.Object || d.KnownTypeCode == KnownTypeCode.ValueType);
}
#endregion
#region Convert Variable
@ -721,10 +710,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -721,10 +710,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
VariableDeclarationStatement decl = new VariableDeclarationStatement();
decl.Modifiers = v.IsConst ? Modifiers.Const : Modifiers.None;
decl.Type = ConvertTypeReference(v.Type);
decl.Type = ConvertType(v.Type);
Expression initializer = null;
if (v.IsConst)
initializer = ConvertConstantValue(v.ConstantValue);
initializer = ConvertConstantValue(v.Type, v.ConstantValue);
decl.Variables.Add(new VariableInitializer(v.Name, initializer));
return decl;
}

161
ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs

@ -0,0 +1,161 @@ @@ -0,0 +1,161 @@
// 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.Diagnostics;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// Resolves C# AST nodes.
/// </summary>
public class CSharpAstResolver
{
readonly CSharpResolver initialResolverState;
readonly AstNode rootNode;
readonly CSharpParsedFile parsedFile;
ResolveVisitor resolveVisitor;
/// <summary>
/// Creates a new C# AST resolver.
/// </summary>
/// <param name="compilation">The current compilation.</param>
/// <param name="parsedFile">
/// Result of the <see cref="TypeSystemConvertVisitor"/> for the file being passed. This is used for setting up the context on the resolver. The parsed file must be registered in the compilation.
/// </param>
/// <param name="compilationUnit">The compilation unit corresponding to the specified parsed file.</param>
public CSharpAstResolver(ICompilation compilation, CompilationUnit compilationUnit, CSharpParsedFile parsedFile)
{
if (compilation == null)
throw new ArgumentNullException("compilation");
if (parsedFile == null)
throw new ArgumentNullException("parsedFile");
if (compilationUnit == null)
throw new ArgumentNullException("compilationUnit");
this.initialResolverState = new CSharpResolver(compilation);
this.rootNode = compilationUnit;
this.parsedFile = parsedFile;
}
/// <summary>
/// Creates a new C# AST resolver.
/// </summary>
/// <param name="resolver">The resolver state at the root node.</param>
/// <param name="rootNode">The root node of the resolved tree.</param>
/// <param name="parsedFile">The parsed file for the nodes being resolved. This parameter is used only
/// when the root node is on the type level; it is not necessary when an expression is passed.
/// This parameter may be null.</param>
public CSharpAstResolver(CSharpResolver resolver, AstNode rootNode, CSharpParsedFile parsedFile = null)
{
if (resolver == null)
throw new ArgumentNullException("resolver");
if (rootNode == null)
throw new ArgumentNullException("rootNode");
this.initialResolverState = resolver.Clone();
this.rootNode = rootNode;
this.parsedFile = parsedFile;
}
/// <summary>
/// Gets the type resolve context for the root resolver.
/// </summary>
public CSharpTypeResolveContext TypeResolveContext {
get { return initialResolverState.CurrentTypeResolveContext; }
}
/// <summary>
/// Applies a resolver navigator. This will resolve the nodes requested by the navigator, and will inform the
/// navigator of the results.
/// This method must be called as the first operation on the CSharpAstResolver, it is invalid to apply a navigator
/// after a portion of the file was already resolved.
/// </summary>
public void ApplyNavigator(IResolveVisitorNavigator navigator, CancellationToken cancellationToken = default(CancellationToken))
{
if (navigator == null)
throw new ArgumentNullException("navigator");
if (resolveVisitor != null)
throw new InvalidOperationException("Applying a navigator is only valid as the first operation on the CSharpAstResolver.");
resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile, navigator);
lock (resolveVisitor)
resolveVisitor.Scan(rootNode);
}
/// <summary>
/// Resolves the specified node.
/// </summary>
public ResolveResult Resolve(AstNode node, CancellationToken cancellationToken = default(CancellationToken))
{
if (node == null || node.IsNull)
return ErrorResolveResult.UnknownError;
InitResolver(node);
lock (resolveVisitor) {
ResolveResult rr = resolveVisitor.GetResolveResult(node);
Debug.Assert(rr != null);
return rr;
}
}
void InitResolver(AstNode firstNodeToResolve)
{
if (resolveVisitor == null) {
resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile, new NodeListResolveVisitorNavigator(firstNodeToResolve));
resolveVisitor.Scan(rootNode);
}
}
public CSharpResolver GetResolverStateBefore(AstNode node, CancellationToken cancellationToken = default(CancellationToken))
{
if (node == null || node.IsNull)
throw new ArgumentNullException("node");
InitResolver(node);
lock (resolveVisitor) {
CSharpResolver resolver = resolveVisitor.GetResolverStateBefore(node);
Debug.Assert(resolver != null);
return resolver;
}
}
/// <summary>
/// Gets the expected type for the specified node. This is the type being that a node is being converted to.
/// </summary>
public IType GetExpectedType(Expression expr, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
}
/// <summary>
/// Gets the conversion that is being applied to the specified expression.
/// </summary>
public Conversion GetConversion(Expression expr, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
}
/// <summary>
/// Gets whether the specified node is unresolvable.
/// </summary>
public static bool IsUnresolvableNode(AstNode node)
{
return (node.NodeType == NodeType.Whitespace || node is ArraySpecifier || node is NamedArgumentExpression);
}
}
}

40
ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
@ -53,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -53,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
readonly IList<int> argumentToParameterMap;
public CSharpInvocationResolveResult(
ResolveResult targetResult, IParameterizedMember member, IType returnType,
ResolveResult targetResult, IParameterizedMember member,
IList<ResolveResult> arguments,
OverloadResolutionErrors overloadResolutionErrors = OverloadResolutionErrors.None,
bool isExtensionMethodInvocation = false,
@ -61,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -61,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool isLiftedOperatorInvocation = false,
bool isDelegateInvocation = false,
IList<int> argumentToParameterMap = null)
: base(targetResult, member, returnType, arguments)
: base(targetResult, member, arguments)
{
this.OverloadResolutionErrors = overloadResolutionErrors;
this.IsExtensionMethodInvocation = isExtensionMethodInvocation;
@ -85,5 +86,40 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -85,5 +86,40 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
return argumentToParameterMap;
}
public override IList<ResolveResult> GetArgumentsForCall()
{
ResolveResult[] results = new ResolveResult[Member.Parameters.Count];
List<ResolveResult> paramsArguments = IsExpandedForm ? new List<ResolveResult>() : null;
// map arguments to parameters:
for (int i = 0; i < Arguments.Count; i++) {
int mappedTo;
if (argumentToParameterMap != null)
mappedTo = argumentToParameterMap[i];
else
mappedTo = IsExpandedForm ? Math.Min(i, results.Length - 1) : i;
if (mappedTo >= 0 && mappedTo < results.Length) {
if (IsExpandedForm && mappedTo == results.Length - 1)
paramsArguments.Add(Arguments[i]);
else
results[mappedTo] = Arguments[i];
}
}
if (IsExpandedForm)
results[results.Length - 1] = new ArrayCreateResolveResult(Member.Parameters.Last().Type, null, paramsArguments.ToArray());
for (int i = 0; i < results.Length; i++) {
if (results[i] == null) {
if (Member.Parameters[i].IsOptional) {
results[i] = new ConstantResolveResult(Member.Parameters[i].Type, Member.Parameters[i].ConstantValue);
} else {
results[i] = ErrorResolveResult.UnknownError;
}
}
}
return results;
}
}
}

1011
ICSharpCode.NRefactory.CSharp/Resolver/CSharpOperators.cs

File diff suppressed because it is too large Load Diff

1569
ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs

File diff suppressed because it is too large Load Diff

4
ICSharpCode.NRefactory.CSharp/Resolver/CompositeResolveVisitorNavigator.cs

@ -31,6 +31,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -31,6 +31,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (navigators == null)
throw new ArgumentNullException("navigators");
this.navigators = navigators;
foreach (var n in navigators) {
if (n == null)
throw new ArgumentException("Array must not contain nulls.");
}
}
public ResolveVisitorNavigationMode Scan(AstNode node)

108
ICSharpCode.NRefactory.CSharp/Resolver/Conversions.cs

@ -17,10 +17,10 @@ @@ -17,10 +17,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils;
@ -241,38 +241,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -241,38 +241,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <summary>
/// Contains logic that determines whether an implicit conversion exists between two types.
/// </summary>
public class Conversions
/// <remarks>
/// Because this class internally uses a cache, it is NOT thread-safe!
/// </remarks>
public sealed class Conversions
{
readonly Dictionary<TypePair, Conversion> implicitConversionCache = new Dictionary<TypePair, Conversion>();
readonly ITypeResolveContext context;
readonly ICompilation compilation;
readonly IType objectType;
int subtypeCheckNestingDepth;
public Conversions(ITypeResolveContext context)
public Conversions(ICompilation compilation)
{
if (context == null)
throw new ArgumentNullException("context");
this.context = context;
this.objectType = KnownTypeReference.Object.Resolve(context);
if (compilation == null)
throw new ArgumentNullException("compilation");
this.compilation = compilation;
this.objectType = compilation.FindType(KnownTypeCode.Object);
this.dynamicErasure = new DynamicErasure(this);
}
/// <summary>
/// Gets the Conversions instance for the specified <see cref="ITypeResolveContext"/>.
/// Gets the Conversions instance for the specified <see cref="ICompilation"/>.
/// This will make use of the context's cache manager (if available) to reuse the Conversions instance.
/// </summary>
public static Conversions Get(ITypeResolveContext context)
public static Conversions Get(ICompilation compilation)
{
CacheManager cache = context.CacheManager;
if (cache != null) {
Conversions conversions = cache.GetThreadLocal(typeof(Conversions)) as Conversions;
if (conversions == null) {
conversions = new Conversions(context);
cache.SetThreadLocal(typeof(Conversions), conversions);
}
return conversions;
} else {
return new Conversions(context);
CacheManager cache = compilation.CacheManager;
Conversions conversions = (Conversions)cache.GetThreadLocal(typeof(Conversions));
if (conversions == null) {
conversions = new Conversions(compilation);
cache.SetThreadLocal(typeof(Conversions), conversions);
}
return conversions;
}
#region TypePair (for caching)
@ -482,7 +482,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -482,7 +482,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override IType VisitOtherType(IType type)
{
if (type == SharedTypes.Dynamic)
if (type.Kind == TypeKind.Dynamic)
return objectType;
else
return base.VisitOtherType(type);
@ -589,8 +589,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -589,8 +589,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool NullLiteralConversion(IType fromType, IType toType)
{
// C# 4.0 spec: §6.1.5
if (SharedTypes.Null.Equals(fromType)) {
return NullableType.IsNullable(toType) || toType.IsReferenceType(context) == true;
if (SpecialType.NullType.Equals(fromType)) {
return NullableType.IsNullable(toType) || toType.IsReferenceType == true;
} else {
return false;
}
@ -603,7 +603,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -603,7 +603,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// C# 4.0 spec: §6.1.6
// reference conversions are possible only if both types are known to be reference types
if (!(fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == true))
if (!(fromType.IsReferenceType == true && toType.IsReferenceType == true))
return false;
ArrayType fromArray = fromType as ArrayType;
@ -625,8 +625,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -625,8 +625,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|| ImplicitReferenceConversion(fromArray.ElementType, toPT.GetTypeArgument(0));
}
// conversion from any array to System.Array and the interfaces it implements:
ITypeDefinition systemArray = context.GetTypeDefinition("System", "Array", 0, StringComparer.Ordinal);
return systemArray != null && (systemArray.Equals(toType) || ImplicitReferenceConversion(systemArray, toType));
IType systemArray = compilation.FindType(KnownTypeCode.Array);
return systemArray.Kind != TypeKind.Unknown && (systemArray.Equals(toType) || ImplicitReferenceConversion(systemArray, toType));
}
// now comes the hard part: traverse the inheritance chain and figure out generics+variance
@ -636,12 +636,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -636,12 +636,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// Determines whether s is a subtype of t.
// Helper method used for ImplicitReferenceConversion, BoxingConversion and ImplicitTypeParameterConversion
int subtypeCheckNestingDepth;
bool IsSubtypeOf(IType s, IType t)
{
// conversion to dynamic + object are always possible
if (t.Equals(SharedTypes.Dynamic) || t.Equals(objectType))
if (t.Equals(SpecialType.Dynamic) || t.Equals(objectType))
return true;
try {
if (++subtypeCheckNestingDepth > 10) {
@ -654,7 +652,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -654,7 +652,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return false;
}
// let GetAllBaseTypes do the work for us
foreach (IType baseType in s.GetAllBaseTypes(context)) {
foreach (IType baseType in s.GetAllBaseTypes()) {
if (IdentityOrVarianceConversion(baseType, t))
return true;
}
@ -706,11 +704,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -706,11 +704,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// C# 4.0 spec: §6.2.4
// reference conversions are possible only if both types are known to be reference types
if (!(fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == true))
if (!(fromType.IsReferenceType == true && toType.IsReferenceType == true))
return false;
// There's lots of additional rules, but they're not really relevant,
// as they are only used to identify invalid casts, and we don't care about reporting those.
// as they are only used to identify invalid casts, and we currently don't care about reporting those.
return true;
}
#endregion
@ -720,7 +718,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -720,7 +718,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
// C# 4.0 spec: §6.1.7
fromType = NullableType.GetUnderlyingType(fromType);
if (fromType.IsReferenceType(context) == false && toType.IsReferenceType(context) == true)
if (fromType.IsReferenceType == false && toType.IsReferenceType == true)
return IsSubtypeOf(fromType, toType);
else
return false;
@ -730,7 +728,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -730,7 +728,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
// C# 4.0 spec: §6.2.5
toType = NullableType.GetUnderlyingType(toType);
if (fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == false)
if (fromType.IsReferenceType == true && toType.IsReferenceType == false)
return IsSubtypeOf(toType, fromType);
else
return false;
@ -776,7 +774,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -776,7 +774,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
if (fromType.Kind != TypeKind.TypeParameter)
return false; // not a type parameter
if (fromType.IsReferenceType(context) == true)
if (fromType.IsReferenceType == true)
return false; // already handled by ImplicitReferenceConversion
return IsSubtypeOf(fromType, toType);
}
@ -784,7 +782,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -784,7 +782,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool ExplicitTypeParameterConversion(IType fromType, IType toType)
{
if (toType.Kind == TypeKind.TypeParameter) {
return fromType.Kind == TypeKind.TypeParameter || fromType.IsReferenceType(context) == true;
return fromType.Kind == TypeKind.TypeParameter || fromType.IsReferenceType == true;
} else {
return fromType.Kind == TypeKind.TypeParameter && toType.Kind == TypeKind.Interface;
}
@ -797,7 +795,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -797,7 +795,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// C# 4.0 spec: §18.4 Pointer conversions
if (fromType is PointerType && toType is PointerType && toType.ReflectionName == "System.Void*")
return true;
if (SharedTypes.Null.Equals(fromType) && toType is PointerType)
if (SpecialType.NullType.Equals(fromType) && toType is PointerType)
return true;
return false;
}
@ -875,19 +873,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -875,19 +873,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
List<OperatorInfo> GetApplicableConversionOperators(IType fromType, IType toType, bool isExplicit)
{
// Find the candidate operators:
Predicate<IMethod> opFilter;
Predicate<IUnresolvedMethod> opFilter;
if (isExplicit)
opFilter = m => m.IsStatic && m.IsOperator && m.Name == "op_Explicit" && m.Parameters.Count == 1;
else
opFilter = m => m.IsStatic && m.IsOperator && m.Name == "op_Implicit" && m.Parameters.Count == 1;
var operators = NullableType.GetUnderlyingType(fromType).GetMethods(context, opFilter)
.Concat(NullableType.GetUnderlyingType(toType).GetMethods(context, opFilter)).Distinct();
var operators = NullableType.GetUnderlyingType(fromType).GetMethods(opFilter)
.Concat(NullableType.GetUnderlyingType(toType).GetMethods(opFilter)).Distinct();
// Determine whether one of them is applicable:
List<OperatorInfo> result = new List<OperatorInfo>();
foreach (IMethod op in operators) {
IType sourceType = op.Parameters[0].Type.Resolve(context);
IType targetType = op.ReturnType.Resolve(context);
IType sourceType = op.Parameters[0].Type;
IType targetType = op.ReturnType;
// Try if the operator is applicable:
bool isApplicable;
if (isExplicit) {
@ -900,11 +898,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -900,11 +898,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
result.Add(new OperatorInfo(op, sourceType, targetType, false));
}
// Try if the operator is applicable in lifted form:
if (NullableType.IsNonNullableValueType(sourceType, context)
&& NullableType.IsNonNullableValueType(targetType, context))
if (NullableType.IsNonNullableValueType(sourceType)
&& NullableType.IsNonNullableValueType(targetType))
{
IType liftedSourceType = NullableType.Create(sourceType, context);
IType liftedTargetType = NullableType.Create(targetType, context);
IType liftedSourceType = NullableType.Create(compilation, sourceType);
IType liftedTargetType = NullableType.Create(compilation, targetType);
if (isExplicit) {
isApplicable = IsEncompassingOrEncompassedBy(fromType, liftedSourceType)
&& IsEncompassingOrEncompassedBy(liftedTargetType, toType);
@ -938,9 +936,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -938,9 +936,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
IType[] dParamTypes = new IType[d.Parameters.Count];
for (int i = 0; i < dParamTypes.Length; i++) {
dParamTypes[i] = d.Parameters[i].Type.Resolve(context);
dParamTypes[i] = d.Parameters[i].Type;
}
IType dReturnType = d.ReturnType.Resolve(context);
IType dReturnType = d.ReturnType;
if (f.HasParameterList) {
// If F contains an anonymous-function-signature, then D and F have the same number of parameters.
@ -961,7 +959,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -961,7 +959,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
IParameter pF = f.Parameters[i];
if (pD.IsRef != pF.IsRef || pD.IsOut != pF.IsOut)
return Conversion.None;
if (!dParamTypes[i].Equals(pF.Type.Resolve(context)))
if (!dParamTypes[i].Equals(pF.Type))
return Conversion.None;
}
}
@ -1002,7 +1000,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1002,7 +1000,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolveResult[] args = new ResolveResult[m.Parameters.Count];
for (int i = 0; i < args.Length; i++) {
IParameter param = m.Parameters[i];
IType parameterType = param.Type.Resolve(context);
IType parameterType = param.Type;
if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference) {
parameterType = ((ByReferenceType)parameterType).ElementType;
args[i] = new ByReferenceResolveResult(parameterType, param.IsOut);
@ -1010,7 +1008,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1010,7 +1008,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
args[i] = new ResolveResult(parameterType);
}
}
var or = rr.PerformOverloadResolution(context, args, allowExpandingParams: false, conversions: this);
var or = rr.PerformOverloadResolution(compilation, args, allowExpandingParams: false, conversions: this);
if (or.FoundApplicableCandidate)
return Conversion.MethodGroupConversion((IMethod)or.BestCandidate);
else
@ -1042,15 +1040,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1042,15 +1040,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return 0;
IType[] parameterTypes = new IType[m1.Parameters.Count];
for (int i = 0; i < parameterTypes.Length; i++) {
parameterTypes[i] = m1.Parameters[i].Type.Resolve(context);
if (!parameterTypes[i].Equals(m2.Parameters[i].Type.Resolve(context)))
parameterTypes[i] = m1.Parameters[i].Type;
if (!parameterTypes[i].Equals(m2.Parameters[i].Type))
return 0;
}
if (lambda.HasParameterList && parameterTypes.Length != lambda.Parameters.Count)
return 0;
IType ret1 = m1.ReturnType.Resolve(context);
IType ret2 = m2.ReturnType.Resolve(context);
IType ret1 = m1.ReturnType;
IType ret2 = m2.ReturnType;
if (ret1.Kind == TypeKind.Void && ret2.Kind != TypeKind.Void)
return 1;
if (ret1.Kind != TypeKind.Void && ret2.Kind == TypeKind.Void)

5
ICSharpCode.NRefactory.CSharp/Resolver/FindReferenceSearchScope.cs

@ -26,6 +26,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -26,6 +26,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public interface IFindReferenceSearchScope
{
/// <summary>
/// Gets the parent compilation for this search scope.
/// </summary>
ICompilation Compilation { get; }
/// <summary>
/// Gets the search term. Only files that contain this identifier need to be parsed.
/// Can return null if all files need to be parsed.

157
ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs

@ -20,7 +20,7 @@ using System; @@ -20,7 +20,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils;
@ -40,11 +40,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -40,11 +40,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public sealed class FindReferences
{
#region Properties
/// <summary>
/// Gets/Sets the cancellation token.
/// </summary>
public CancellationToken CancellationToken { get; set; }
/// <summary>
/// Gets/Sets whether to find type references even if an alias is being used.
/// </summary>
@ -101,11 +96,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -101,11 +96,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
abstract class SearchScope : IResolveVisitorNavigator, IFindReferenceSearchScope
{
protected string searchTerm;
internal ICompilation compilation;
internal Accessibility accessibility;
internal ITypeDefinition topLevelTypeDefinition;
FoundReferenceCallback callback;
ICompilation IFindReferenceSearchScope.Compilation {
get { return compilation; }
}
IResolveVisitorNavigator IFindReferenceSearchScope.GetNavigator(FoundReferenceCallback callback)
{
SearchScope n = (SearchScope)MemberwiseClone();
@ -208,10 +208,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -208,10 +208,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
if (scope.accessibility == Accessibility.None)
scope.accessibility = effectiveAccessibility;
scope.compilation = entity.Compilation;
scope.topLevelTypeDefinition = topLevelTypeDefinition;
if (additionalScope != null) {
if (additionalScope.accessibility == Accessibility.None)
additionalScope.accessibility = effectiveAccessibility;
additionalScope.compilation = entity.Compilation;
additionalScope.topLevelTypeDefinition = topLevelTypeDefinition;
return new[] { scope, additionalScope };
} else {
@ -224,7 +226,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -224,7 +226,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <summary>
/// Gets the file names that possibly contain references to the element being searched for.
/// </summary>
public IList<string> GetInterestingFileNames(IFindReferenceSearchScope searchScope, IEnumerable<ITypeDefinition> allTypes, ITypeResolveContext context)
public IList<string> GetInterestingFileNames(IFindReferenceSearchScope searchScope, IEnumerable<ITypeDefinition> allTypes)
{
IEnumerable<ITypeDefinition> interestingTypes;
if (searchScope.TopLevelTypeDefinition != null) {
@ -234,18 +236,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -234,18 +236,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
interestingTypes = new [] { searchScope.TopLevelTypeDefinition.GetDefinition() };
break;
case Accessibility.Protected:
interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition);
interestingTypes = GetInterestingTypesProtected(allTypes, searchScope.TopLevelTypeDefinition);
break;
case Accessibility.Internal:
interestingTypes = GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent);
interestingTypes = GetInterestingTypesInternal(allTypes, searchScope.TopLevelTypeDefinition.ParentAssembly);
break;
case Accessibility.ProtectedAndInternal:
interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition)
.Intersect(GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent));
interestingTypes = GetInterestingTypesProtected(allTypes, searchScope.TopLevelTypeDefinition)
.Intersect(GetInterestingTypesInternal(allTypes, searchScope.TopLevelTypeDefinition.ParentAssembly));
break;
case Accessibility.ProtectedOrInternal:
interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition)
.Union(GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent));
interestingTypes = GetInterestingTypesProtected(allTypes, searchScope.TopLevelTypeDefinition)
.Union(GetInterestingTypesInternal(allTypes, searchScope.TopLevelTypeDefinition.ParentAssembly));
break;
default:
interestingTypes = allTypes;
@ -255,20 +257,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -255,20 +257,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
interestingTypes = allTypes;
}
return (from typeDef in interestingTypes
from part in typeDef.GetParts()
from part in typeDef.Parts
where part.ParsedFile != null
select part.ParsedFile.FileName
).Distinct(Platform.FileNameComparer).ToList();
}
IEnumerable<ITypeDefinition> GetInterestingTypesProtected(IEnumerable<ITypeDefinition> allTypes, ITypeResolveContext context, ITypeDefinition referencedTypeDefinition)
IEnumerable<ITypeDefinition> GetInterestingTypesProtected(IEnumerable<ITypeDefinition> allTypes, ITypeDefinition referencedTypeDefinition)
{
return allTypes.Where(t => t.IsDerivedFrom(referencedTypeDefinition, context));
return allTypes.Where(t => t.IsDerivedFrom(referencedTypeDefinition));
}
IEnumerable<ITypeDefinition> GetInterestingTypesInternal(IEnumerable<ITypeDefinition> allTypes, ITypeResolveContext context, IProjectContent referencedProjectContent)
IEnumerable<ITypeDefinition> GetInterestingTypesInternal(IEnumerable<ITypeDefinition> allTypes, IAssembly referencedAssembly)
{
return allTypes.Where(t => referencedProjectContent.InternalsVisibleTo(t.ProjectContent, context));
return allTypes.Where(t => referencedAssembly.InternalsVisibleTo(t.ParentAssembly));
}
#endregion
@ -282,11 +284,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -282,11 +284,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <param name="context">The type resolve context to use for resolving the file.</param>
/// <param name="callback">Callback used to report the references that were found.</param>
public void FindReferencesInFile(IFindReferenceSearchScope searchScope, CSharpParsedFile parsedFile, CompilationUnit compilationUnit,
ITypeResolveContext context, FoundReferenceCallback callback)
FoundReferenceCallback callback, CancellationToken cancellationToken)
{
if (searchScope == null)
throw new ArgumentNullException("searchScope");
FindReferencesInFile(new[] { searchScope }, parsedFile, compilationUnit, context, callback);
FindReferencesInFile(new[] { searchScope }, parsedFile, compilationUnit, callback, cancellationToken);
}
/// <summary>
@ -295,10 +297,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -295,10 +297,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <param name="searchScopes">The search scopes for which to look.</param>
/// <param name="parsedFile">The type system representation of the file being searched.</param>
/// <param name="compilationUnit">The compilation unit of the file being searched.</param>
/// <param name="context">The type resolve context to use for resolving the file.</param>
/// <param name="callback">Callback used to report the references that were found.</param>
/// <param name="cancellationToken">Cancellation token.</param>
public void FindReferencesInFile(IList<IFindReferenceSearchScope> searchScopes, CSharpParsedFile parsedFile, CompilationUnit compilationUnit,
ITypeResolveContext context, FoundReferenceCallback callback)
FoundReferenceCallback callback, CancellationToken cancellationToken)
{
if (searchScopes == null)
throw new ArgumentNullException("searchScopes");
@ -306,22 +308,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -306,22 +308,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
throw new ArgumentNullException("parsedFile");
if (compilationUnit == null)
throw new ArgumentNullException("compilationUnit");
if (context == null)
throw new ArgumentNullException("context");
this.CancellationToken.ThrowIfCancellationRequested();
if (searchScopes.Count == 0)
return;
using (var ctx = context.Synchronize()) {
IResolveVisitorNavigator navigator;
if (searchScopes.Count == 1)
navigator = searchScopes[0].GetNavigator(callback);
else
navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray());
navigator = new DetectSkippableNodesNavigator(navigator, compilationUnit);
CSharpResolver resolver = new CSharpResolver(ctx, this.CancellationToken);
ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator);
v.Scan(compilationUnit);
ICompilation compilation = searchScopes[0].Compilation;
IResolveVisitorNavigator navigator;
if (searchScopes.Count == 1) {
navigator = searchScopes[0].GetNavigator(callback);
} else {
IResolveVisitorNavigator[] navigators = new IResolveVisitorNavigator[searchScopes.Count];
for (int i = 0; i < navigators.Length; i++) {
if (searchScopes[i].Compilation != compilation)
throw new InvalidOperationException("All search scopes must belong to the same compilation");
navigators[i] = searchScopes[i].GetNavigator(callback);
}
navigator = new CompositeResolveVisitorNavigator(navigators);
}
navigator = new DetectSkippableNodesNavigator(navigator, compilationUnit);
CSharpAstResolver resolver = new CSharpAstResolver(compilation, compilationUnit, parsedFile);
resolver.ApplyNavigator(navigator);
}
#endregion
@ -360,7 +366,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -360,7 +366,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (searchTerm == null && node is PrimitiveType)
return true;
return node is TypeDeclaration;
return node is TypeDeclaration || node is DelegateDeclaration;
}
internal override bool IsMatch(ResolveResult rr)
@ -418,7 +424,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -418,7 +424,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool CanMatch(AstNode node)
{
return node is FieldDeclaration || node is VariableInitializer || base.CanMatch(node);
if (node is VariableInitializer) {
return node.Parent is FieldDeclaration;
}
return base.CanMatch(node);
}
}
@ -454,7 +463,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -454,7 +463,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool CanMatch(AstNode node)
{
return node is EventDeclaration || base.CanMatch(node);
if (node is VariableInitializer) {
return node.Parent is EventDeclaration;
}
return node is CustomEventDeclaration || base.CanMatch(node);
}
}
#endregion
@ -481,6 +493,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -481,6 +493,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return new FindMethodReferences(method, typeof(QueryOrdering));
case "GroupBy":
return new FindMethodReferences(method, typeof(QueryGroupClause));
case "Invoke":
if (method.DeclaringTypeDefinition != null && method.DeclaringTypeDefinition.Kind == TypeKind.Delegate)
return new FindMethodReferences(method, typeof(InvocationExpression));
else
return new FindMethodReferences(method);
default:
return new FindMethodReferences(method);
}
@ -501,6 +518,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -501,6 +518,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool CanMatch(AstNode node)
{
if (specialNodeType != null && node.GetType() == specialNodeType)
return true;
InvocationExpression ie = node as InvocationExpression;
if (ie != null) {
Expression target = ResolveVisitor.UnpackParenthesizedExpression(ie.Target);
@ -517,12 +537,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -517,12 +537,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (pre != null)
return pre.MemberName == method.Name;
}
if (node is MethodDeclaration)
return true;
if (specialNodeType != null)
return specialNodeType.IsInstanceOfType(node);
else
return false;
return node is MethodDeclaration;
}
internal override bool IsMatch(ResolveResult rr)
@ -783,5 +798,59 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -783,5 +798,59 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
#endregion
#region Find Local Variable References
/// <summary>
/// Finds all references of a given variable.
/// </summary>
/// <param name="variable">The variable for which to look.</param>
/// <param name="parsedFile">The type system representation of the file being searched.</param>
/// <param name="compilationUnit">The compilation unit of the file being searched.</param>
/// <param name="compilation">The compilation.</param>
/// <param name="callback">Callback used to report the references that were found.</param>
/// <param name="cancellationToken">Cancellation token that may be used to cancel the operation.</param>
public void FindLocalReferences(IVariable variable, CSharpParsedFile parsedFile, CompilationUnit compilationUnit,
ICompilation compilation, FoundReferenceCallback callback, CancellationToken cancellationToken)
{
if (variable == null)
throw new ArgumentNullException("variable");
var navigator = new FindLocalReferencesNavigator(variable);
navigator.compilation = compilation;
FindReferencesInFile(navigator, parsedFile, compilationUnit, callback, cancellationToken);
}
class FindLocalReferencesNavigator : SearchScope
{
readonly IVariable variable;
public FindLocalReferencesNavigator(IVariable variable)
{
this.variable = variable;
}
internal override bool CanMatch(AstNode node)
{
var expr = node as IdentifierExpression;
if (expr != null)
return expr.TypeArguments.Count == 0 && variable.Name == expr.Identifier;
var vi = node as VariableInitializer;
if (vi != null)
return vi.Name == variable.Name;
var pd = node as ParameterDeclaration;
if (pd != null)
return pd.Name == variable.Name;
var id = node as Identifier;
if (id != null)
return id.Name == variable.Name;
return false;
}
internal override bool IsMatch(ResolveResult rr)
{
var lrr = rr as LocalResolveResult;
return lrr != null && lrr.Variable.Name == variable.Name && lrr.Variable.Region == variable.Region;
}
}
#endregion
}
}

1
ICSharpCode.NRefactory.CSharp/Resolver/IResolveVisitorNavigator.cs

@ -83,7 +83,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -83,7 +83,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.targetForResolveCalls = targetForResolveCalls;
}
ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node)
{
return mode;

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

Loading…
Cancel
Save