Browse Source

Updated mcs / included code completion expression lookup.

newNRvisualizers
Mike Krüger 15 years ago
parent
commit
0afc1c6b2d
  1. 12
      ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs
  2. 2
      ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs
  3. 33
      ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs
  4. 77
      ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs
  5. 1379
      ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs
  6. 30
      ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay
  7. 9
      ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs
  8. 53
      ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs
  9. 13
      ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs
  10. 40
      ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs
  11. 5
      ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs
  12. 29
      ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs
  13. 19
      ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs
  14. 2
      ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs
  15. 57
      ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs
  16. 2
      ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs

12
ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs

@ -45,6 +45,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -45,6 +45,18 @@ namespace ICSharpCode.NRefactory.CSharp
get { return errors; }
}
/// <summary>
/// Gets the expression that was on top of the parse stack.
/// This is the only way to get an expression that isn't part of a statment.
/// (eg. when an error follows an expression).
///
/// This is used for code completion to 'get the expression before a token - like ., <, ('.
/// </summary>
public AstNode TopExpression {
get;
internal set;
}
public CompilationUnit ()
{
}

2
ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs

@ -2992,6 +2992,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2992,6 +2992,8 @@ namespace ICSharpCode.NRefactory.CSharp
CompilationUnitCallback (top);
if (line != 0)
AdjustLineLocations (conversionVisitor.Unit, line);
if (top.LastYYValue is Mono.CSharp.Expression)
conversionVisitor.Unit.TopExpression = ((Mono.CSharp.Expression)top.LastYYValue).Accept (conversionVisitor) as AstNode;
return conversionVisitor.Unit;
}

33
ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs

@ -856,6 +856,12 @@ namespace Mono.CSharp { @@ -856,6 +856,12 @@ namespace Mono.CSharp {
}
}
public bool IsAsync {
get {
return is_async;
}
}
public ParametersCompiled Parameters {
get {
return Block.Parameters;
@ -1012,9 +1018,16 @@ namespace Mono.CSharp { @@ -1012,9 +1018,16 @@ namespace Mono.CSharp {
}
using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) {
am = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type);
if (am != null)
am = am.Compatible (ec);
var body = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type);
if (body != null) {
if (is_async) {
AsyncInitializer.Create (body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, null, loc);
}
am = body.Compatible (ec, body, is_async);
} else {
am = null;
}
}
if (am == null)
@ -1067,7 +1080,7 @@ namespace Mono.CSharp { @@ -1067,7 +1080,7 @@ namespace Mono.CSharp {
// lambda, this also means no variable capturing between this
// and parent scope
//
am = body.Compatible (ec, ec.CurrentAnonymousMethod);
am = body.Compatible (ec, ec.CurrentAnonymousMethod, is_async);
//
// Quote nested expression tree
@ -1332,10 +1345,10 @@ namespace Mono.CSharp { @@ -1332,10 +1345,10 @@ namespace Mono.CSharp {
public AnonymousExpression Compatible (ResolveContext ec)
{
return Compatible (ec, this);
return Compatible (ec, this, false);
}
public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae)
public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae, bool isAsync)
{
if (block.Resolved)
return this;
@ -1374,6 +1387,14 @@ namespace Mono.CSharp { @@ -1374,6 +1387,14 @@ namespace Mono.CSharp {
am.ReturnTypeInference.FixAllTypes (ec);
ReturnType = am.ReturnTypeInference.InferredTypeArguments [0];
am.ReturnTypeInference = null;
//
// 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) {
ReturnType = ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType });
}
}
if (res && errors != ec.Report.Errors)

77
ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs

@ -22,7 +22,7 @@ namespace Mono.CSharp @@ -22,7 +22,7 @@ namespace Mono.CSharp
{
class Await : ExpressionStatement
{
readonly Expression expr;
Expression expr;
AwaitStatement stmt;
public Await (Expression expr, Location loc)
@ -31,6 +31,13 @@ namespace Mono.CSharp @@ -31,6 +31,13 @@ namespace Mono.CSharp
this.loc = loc;
}
protected override void CloneTo (CloneContext clonectx, Expression target)
{
var t = (Await) target;
t.expr = expr.Clone (clonectx);
}
public override Expression CreateExpressionTree (ResolveContext ec)
{
throw new NotImplementedException ("ET");
@ -72,7 +79,8 @@ namespace Mono.CSharp @@ -72,7 +79,8 @@ namespace Mono.CSharp
}
stmt = new AwaitStatement (expr, loc);
stmt.Resolve (bc);
if (!stmt.Resolve (bc))
return null;
type = stmt.ResultType;
eclass = ExprClass.Variable;
@ -81,6 +89,14 @@ namespace Mono.CSharp @@ -81,6 +89,14 @@ namespace Mono.CSharp
public override void Emit (EmitContext ec)
{
stmt.EmitPrologue (ec);
stmt.Emit (ec);
}
public void EmitAssign (EmitContext ec, FieldExpr field)
{
stmt.EmitPrologue (ec);
field.InstanceExpression.Emit (ec);
stmt.Emit (ec);
}
@ -142,6 +158,20 @@ namespace Mono.CSharp @@ -142,6 +158,20 @@ namespace Mono.CSharp
var fe_awaiter = new FieldExpr (awaiter, loc);
fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
//
// result = awaiter.GetResult ();
//
var mg_result = MethodGroupExpr.CreatePredefined (get_result, fe_awaiter.Type, loc);
mg_result.InstanceExpression = fe_awaiter;
mg_result.EmitCall (ec, new Arguments (0));
}
public void EmitPrologue (EmitContext ec)
{
var fe_awaiter = new FieldExpr (awaiter, loc);
fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
//
// awaiter = expr.GetAwaiter ();
//
@ -166,18 +196,11 @@ namespace Mono.CSharp @@ -166,18 +196,11 @@ namespace Mono.CSharp
mg_completed.EmitCall (ec, args);
base.DoEmit (ec);
//
// result = awaiter.GetResult ();
//
var mg_result = MethodGroupExpr.CreatePredefined (get_result, fe_awaiter.Type, loc);
mg_result.InstanceExpression = fe_awaiter;
mg_result.EmitCall (ec, new Arguments (0));
}
public void EmitStatement (EmitContext ec)
{
EmitPrologue (ec);
Emit (ec);
if (ResultType.Kind != MemberKind.Void) {
@ -295,11 +318,15 @@ namespace Mono.CSharp @@ -295,11 +318,15 @@ namespace Mono.CSharp
public class AsyncInitializer : StateMachineInitializer
{
TypeInferenceContext return_inference;
public AsyncInitializer (ParametersBlock block, TypeContainer host, TypeSpec returnType)
: base (block, host, returnType)
{
}
#region Properties
public override string ContainerType {
get {
return "async state machine block";
@ -312,9 +339,23 @@ namespace Mono.CSharp @@ -312,9 +339,23 @@ namespace Mono.CSharp
}
}
public Block OriginalBlock {
get {
return block.Parent;
}
}
public TypeInferenceContext ReturnTypeInference {
get {
return return_inference;
}
}
#endregion
public static void Create (ParametersBlock block, ParametersCompiled parameters, TypeContainer host, TypeSpec returnType, Location loc)
{
if (returnType.Kind != MemberKind.Void &&
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>");
@ -351,6 +392,16 @@ namespace Mono.CSharp @@ -351,6 +392,16 @@ namespace Mono.CSharp
block.WrapIntoAsyncTask (host, returnType);
}
protected override BlockContext CreateBlockContext (ResolveContext rc)
{
var ctx = base.CreateBlockContext (rc);
var lambda = rc.CurrentAnonymousMethod as LambdaMethod;
if (lambda != null)
return_inference = lambda.ReturnTypeInference;
return ctx;
}
public override Expression CreateExpressionTree (ResolveContext ec)
{
return base.CreateExpressionTree (ec);
@ -363,8 +414,6 @@ namespace Mono.CSharp @@ -363,8 +414,6 @@ namespace Mono.CSharp
protected override void EmitMoveNextEpilogue (EmitContext ec)
{
base.EmitMoveNextEpilogue (ec);
var storey = (AsyncTaskStorey) Storey;
storey.EmitSetResult (ec);
}
@ -408,7 +457,7 @@ namespace Mono.CSharp @@ -408,7 +457,7 @@ namespace Mono.CSharp
LocalVariable hoisted_return;
public AsyncTaskStorey (AsyncInitializer initializer, TypeSpec type)
: base (initializer.Block, initializer.Host, null, null, "async")
: base (initializer.OriginalBlock, initializer.Host, null, null, "async")
{
return_type = type;
}

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

File diff suppressed because it is too large Load Diff

30
ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay

@ -144,6 +144,19 @@ namespace Mono.CSharp @@ -144,6 +144,19 @@ namespace Mono.CSharp
List<Tuple<Modifiers, Location>> mod_locations;
Location parameterModifierLocation, savedLocation, savedOpenLocation, savedCloseLocation;
Stack<List<Location>> locationListStack = new Stack<List<Location>> (); // used for type parameters
object lastYYVal;
// Can be used for code completion to get the last valid expression before an error.
// needs a hack in yyparse to make it work add
// lastYYVal = yyVal;
// after the big switch/case (somewhere around line 3915)
public object LastYYVal {
get {
return lastYYVal;
}
}
%}
%token EOF
@ -1242,6 +1255,8 @@ method_declaration @@ -1242,6 +1255,8 @@ method_declaration
method.Block = (ToplevelBlock) $3;
if (method.Block == null) {
method.ParameterInfo.CheckParameters (method);
if ((method.ModFlags & Modifiers.ASYNC) != 0) {
report.Error (1994, method.Location, "`{0}': The async modifier can only be used with methods that have a body",
method.GetSignatureForError ());
@ -1735,8 +1750,7 @@ indexer_declaration @@ -1735,8 +1750,7 @@ indexer_declaration
{
valid_param_mod = 0;
var type = (FullNamedExpression) $3;
Indexer indexer = new Indexer (current_class, type,
(MemberName)$4, (Modifiers) $2, (ParametersCompiled) $7, (Attributes) $1);
Indexer indexer = new Indexer (current_class, type, (MemberName) $4, (Modifiers) $2, (ParametersCompiled) $7, (Attributes) $1);
current_property = indexer;
@ -1759,10 +1773,13 @@ indexer_declaration @@ -1759,10 +1773,13 @@ indexer_declaration
}
accessor_declarations
{
lexer.PropertyParsing = false;
lexer.PropertyParsing = false;
}
CLOSE_BRACE
{
{
if (current_property.AccessorFirst != null && current_property.AccessorFirst.Block == null)
((Indexer) current_property).ParameterInfo.CheckParameters (current_property);
if (doc_support)
current_property.DocComment = ConsumeStoredComment ();
@ -1987,6 +2004,9 @@ operator_declaration @@ -1987,6 +2004,9 @@ operator_declaration
current_class, decl.optype, decl.ret_type, (Modifiers) $2,
current_local_parameters,
(ToplevelBlock) $5, (Attributes) $1, decl.location);
if (op.Block == null)
op.ParameterInfo.CheckParameters (op);
if (doc_support) {
op.DocComment = tmpComment;
@ -2632,9 +2652,11 @@ delegate_declaration @@ -2632,9 +2652,11 @@ delegate_declaration
Delegate del = new Delegate (current_namespace, current_class, (FullNamedExpression) $4,
(Modifiers) $2, name, p, (Attributes) $1);
p.CheckParameters (del);
ubag.PushTypeDeclaration (del);
ubag.PopTypeDeclaration ();
current_container.AddDelegate (del);
current_delegate = del;
lexer.ConstraintsParsing = true;

9
ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs

@ -2724,15 +2724,20 @@ namespace Mono.CSharp @@ -2724,15 +2724,20 @@ namespace Mono.CSharp
ILiteralConstant res = new StringLiteral (context.BuiltinTypes, s, start_location);
val = res;
#if FULL_AST
res.ParsedValue = reader.ReadChars (reader_pos - (quoted ? 2 : 1), reader.Position);
res.ParsedValue = quoted ?
reader.ReadChars (reader_pos - 2, reader.Position - 1) :
reader.ReadChars (reader_pos - 1, reader.Position);
#endif
return Token.LITERAL;
}
if (c == '\n') {
if (!quoted)
if (!quoted) {
Report.Error (1010, Location, "Newline in constant");
val = new StringLiteral (context.BuiltinTypes, new string (value_builder, 0, pos), start_location);
return Token.LITERAL;
}
} else if (c == '\\' && !quoted) {
int surrogate;
c = escape (c, out surrogate);

53
ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs

@ -150,6 +150,10 @@ namespace Mono.CSharp @@ -150,6 +150,10 @@ namespace Mono.CSharp
HandleSeeAlso (mc, ds_target, seealso);
foreach (XmlElement see in n.SelectNodes (".//exception"))
HandleException (mc, ds_target, see);
foreach (XmlElement node in n.SelectNodes (".//typeparam"))
HandleTypeParam (mc, node);
foreach (XmlElement node in n.SelectNodes (".//typeparamref"))
HandleTypeParamRef (mc, node);
}
n.WriteTo (XmlCommentOutput);
@ -229,6 +233,55 @@ namespace Mono.CSharp @@ -229,6 +233,55 @@ namespace Mono.CSharp
HandleXrefCommon (mc, ds, seealso);
}
//
// Handles <typeparam /> node
//
void HandleTypeParam (MemberCore mc, XmlElement node)
{
if (!node.HasAttribute ("name"))
return;
string tp_name = node.GetAttribute ("name");
if (mc.CurrentTypeParameters != null) {
foreach (var tp in mc.CurrentTypeParameters) {
if (tp.Name == tp_name)
return;
}
}
// TODO: CS1710, CS1712
mc.Compiler.Report.Warning (1711, 2, mc.Location,
"XML comment on `{0}' has a typeparam name `{1}' but there is no type parameter by that name",
mc.GetSignatureForError (), tp_name);
}
//
// Handles <typeparamref /> node
//
void HandleTypeParamRef (MemberCore mc, XmlElement node)
{
if (!node.HasAttribute ("name"))
return;
string tp_name = node.GetAttribute ("name");
var member = mc;
do {
if (member.CurrentTypeParameters != null) {
foreach (var tp in member.CurrentTypeParameters) {
if (tp.Name == tp_name)
return;
}
}
member = member.Parent;
} while (member != null);
mc.Compiler.Report.Warning (1735, 2, mc.Location,
"XML comment on `{0}' has a typeparamref name `{1}' that could not be resolved",
mc.GetSignatureForError (), tp_name);
}
FullNamedExpression ResolveMemberName (IMemberContext context, MemberName mn)
{
if (mn.Left == null)

13
ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs

@ -357,6 +357,7 @@ namespace Mono.CSharp @@ -357,6 +357,7 @@ namespace Mono.CSharp
public LocationsBag LocationsBag { get; set; }
public UsingsBag UsingsBag { get; set; }
public SpecialsBag SpecialsBag { get; set; }
public object LastYYValue { get; set; }
}
//
@ -418,7 +419,7 @@ namespace Mono.CSharp @@ -418,7 +419,7 @@ namespace Mono.CSharp
return ParseFile (args, input, inputFile, new StreamReportPrinter (reportStream));
}
public static object parseLock = new object ();
internal static object parseLock = new object ();
public static CompilerCompilationUnit ParseFile (string[] args, Stream input, string inputFile, ReportPrinter reportPrinter)
{
@ -454,8 +455,14 @@ namespace Mono.CSharp @@ -454,8 +455,14 @@ namespace Mono.CSharp
parser.LocationsBag = new LocationsBag ();
parser.UsingsBag = new UsingsBag ();
parser.parse ();
return new CompilerCompilationUnit () { ModuleCompiled = RootContext.ToplevelTypes, LocationsBag = parser.LocationsBag, UsingsBag = parser.UsingsBag, SpecialsBag = parser.Lexer.sbag };
return new CompilerCompilationUnit () {
ModuleCompiled = RootContext.ToplevelTypes,
LocationsBag = parser.LocationsBag,
UsingsBag = parser.UsingsBag,
SpecialsBag = parser.Lexer.sbag,
LastYYValue = parser.LastYYVal
};
} finally {
Reset ();
}

40
ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs

@ -3422,6 +3422,28 @@ namespace Mono.CSharp { @@ -3422,6 +3422,28 @@ namespace Mono.CSharp {
if (q.Kind == MemberKind.Void) {
return p.Kind != MemberKind.Void ? 1: 0;
}
//
// When anonymous method is an asynchronous, and P has a return type Task<Y1>, and Q has a return type Task<Y2>
// 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;
q = q.TypeArguments[0];
p = p.TypeArguments[0];
}
//
// The parameters are identicial and return type is not void, use better type conversion
// on return type to determine better one
//
} else {
if (argument_type == p)
return 1;
@ -5088,11 +5110,21 @@ namespace Mono.CSharp { @@ -5088,11 +5110,21 @@ namespace Mono.CSharp {
public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
{
prepared = prepare_for_load && !(source is DynamicExpressionStatement);
if (IsInstance)
EmitInstance (ec, prepared);
var await_expr = source as Await;
if (await_expr != null) {
//
// Await is not ordinary expression (it contains jump), hence the usual flow cannot be used
// to emit instance load before expression
//
await_expr.EmitAssign (ec, this);
} else {
prepared = prepare_for_load && !(source is DynamicExpressionStatement);
if (IsInstance)
EmitInstance (ec, prepared);
source.Emit (ec);
}
source.Emit (ec);
if (leave_copy) {
ec.Emit (OpCodes.Dup);
if (!IsStatic) {

5
ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs

@ -3070,6 +3070,11 @@ namespace Mono.CSharp { @@ -3070,6 +3070,11 @@ namespace Mono.CSharp {
fixed_types[i] = best_candidate;
return true;
}
public bool HasBounds (int pos)
{
return bounds[pos] != null;
}
//
// Uses inferred or partially infered types to inflate delegate type argument. Returns

29
ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs

@ -647,12 +647,18 @@ namespace Mono.CSharp @@ -647,12 +647,18 @@ namespace Mono.CSharp
throw new NotSupportedException ("ET");
}
protected virtual BlockContext CreateBlockContext (ResolveContext rc)
{
var ctx = new BlockContext (rc, block, ((BlockContext) rc).ReturnType);
ctx.CurrentAnonymousMethod = this;
return ctx;
}
protected override Expression DoResolve (ResolveContext ec)
{
storey = (StateMachine) block.Parent.ParametersBlock.AnonymousMethodStorey;
BlockContext ctx = new BlockContext (ec, block, ReturnType);
ctx.CurrentAnonymousMethod = this;
var ctx = CreateBlockContext (ec);
ctx.StartFlowBranching (this, ec.CurrentBranching);
Block.Resolve (ctx);
@ -661,14 +667,16 @@ namespace Mono.CSharp @@ -661,14 +667,16 @@ namespace Mono.CSharp
// Explicit return is required for Task<T> state machine
//
var task_storey = storey as AsyncTaskStorey;
if (task_storey == null || !task_storey.ReturnType.IsGenericTask)
if (task_storey == null || (task_storey.ReturnType != null && !task_storey.ReturnType.IsGenericTask))
ctx.CurrentBranching.CurrentUsageVector.Goto ();
ctx.EndFlowBranching ();
var move_next = new StateMachineMethod (storey, this, new TypeExpression (ReturnType, loc), Modifiers.PUBLIC, new MemberName ("MoveNext", loc));
move_next.Block.AddStatement (new MoveNextBodyStatement (this));
storey.AddEntryMethod (move_next);
if (!ec.IsInProbingMode) {
var move_next = new StateMachineMethod (storey, this, new TypeExpression (ReturnType, loc), Modifiers.PUBLIC, new MemberName ("MoveNext", loc));
move_next.Block.AddStatement (new MoveNextBodyStatement (this));
storey.AddEntryMethod (move_next);
}
eclass = ExprClass.Value;
return this;
@ -746,6 +754,8 @@ namespace Mono.CSharp @@ -746,6 +754,8 @@ namespace Mono.CSharp
original_block.Emit (ec);
SymbolWriter.EndIteratorBody (ec);
EmitMoveNextEpilogue (ec);
ec.MarkLabel (move_next_error);
if (ReturnType.Kind != MemberKind.Void) {
@ -805,6 +815,10 @@ namespace Mono.CSharp @@ -805,6 +815,10 @@ namespace Mono.CSharp
SymbolWriter.StartIteratorDispatcher (ec);
ec.Emit (OpCodes.Ldarg_0);
ec.EmitInt ((int) IteratorStorey.State.After);
ec.Emit (OpCodes.Stfld, storey.PC.Spec);
EmitMoveNextEpilogue (ec);
ec.MarkLabel (move_next_error);
@ -826,9 +840,6 @@ namespace Mono.CSharp @@ -826,9 +840,6 @@ namespace Mono.CSharp
protected virtual void EmitMoveNextEpilogue (EmitContext ec)
{
ec.Emit (OpCodes.Ldarg_0);
ec.EmitInt ((int) IteratorStorey.State.After);
ec.Emit (OpCodes.Stfld, storey.PC.Spec);
}
//

19
ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs

@ -496,6 +496,11 @@ namespace Mono.CSharp { @@ -496,6 +496,11 @@ namespace Mono.CSharp {
}
}
public void Error_DuplicateName (Report r)
{
r.Error (100, Location, "The parameter name `{0}' is a duplicate", Name);
}
public virtual string GetSignatureForError ()
{
string type_name;
@ -1109,6 +1114,20 @@ namespace Mono.CSharp { @@ -1109,6 +1114,20 @@ namespace Mono.CSharp {
return parameters;
}
//
// Parameters checks for members which don't have a block
//
public void CheckParameters (MemberCore member)
{
for (int i = 0; i < parameters.Length; ++i) {
var name = parameters[i].Name;
for (int ii = i + 1; ii < parameters.Length; ++ii) {
if (parameters[ii].Name == name)
this[ii].Error_DuplicateName (member.Compiler.Report);
}
}
}
public bool Resolve (IMemberContext ec)
{
if (types != null)

2
ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs

@ -61,7 +61,7 @@ namespace Mono.CSharp { @@ -61,7 +61,7 @@ namespace Mono.CSharp {
1030, 1058, 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, 1717, 1718, 1720,
1700, 1701, 1702, 1709, 1711, 1717, 1718, 1720, 1735,
1901, 1956, 1981,
2002, 2023, 2029,
3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009,

57
ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs

@ -766,6 +766,21 @@ namespace Mono.CSharp { @@ -766,6 +766,21 @@ namespace Mono.CSharp {
if (ec.ReturnType.Kind == MemberKind.Void)
return true;
//
// Return must not be followed by an expression when
// the method return type is Task
//
if (ec.CurrentAnonymousMethod is AsyncInitializer) {
var storey = (AsyncTaskStorey) ec.CurrentAnonymousMethod.Storey;
if (storey.ReturnType == ec.Module.PredefinedTypes.Task.TypeSpec) {
//
// Extra trick not to emit ret/leave inside awaiter body
//
Expr = EmptyExpression.Null;
return true;
}
}
if (ec.CurrentIterator != null) {
Error_ReturnFromIterator (ec);
} else {
@ -793,12 +808,21 @@ namespace Mono.CSharp { @@ -793,12 +808,21 @@ namespace Mono.CSharp {
return false;
}
if (am is AsyncInitializer) {
var async_block = am as AsyncInitializer;
if (async_block != null) {
if (Expr != null) {
var storey = (AsyncTaskStorey) am.Storey;
var async_type = storey.ReturnType;
if (async_type == null && async_block.ReturnTypeInference != null) {
async_block.ReturnTypeInference.AddCommonTypeBound (Expr.Type);
return true;
}
if (!async_type.IsGenericTask) {
if (this is ContextualReturn)
return true;
ec.Report.Error (1997, loc,
"`{0}': A return keyword must not be followed by an expression when async method returns Task. Consider using Task<T>",
ec.GetSignatureForError ());
@ -845,7 +869,12 @@ namespace Mono.CSharp { @@ -845,7 +869,12 @@ namespace Mono.CSharp {
var async_body = ec.CurrentAnonymousMethod as AsyncInitializer;
if (async_body != null) {
((AsyncTaskStorey) async_body.Storey).HoistedReturn.EmitAssign (ec);
var async_return = ((AsyncTaskStorey) async_body.Storey).HoistedReturn;
// It's null for await without async
if (async_return != null)
async_return.EmitAssign (ec);
return;
}
@ -2000,12 +2029,11 @@ namespace Mono.CSharp { @@ -2000,12 +2029,11 @@ namespace Mono.CSharp {
{
var pi = variable as ParametersBlock.ParameterInfo;
if (pi != null) {
var p = pi.Parameter;
ParametersBlock.TopBlock.Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
pi.Parameter.Error_DuplicateName (ParametersBlock.TopBlock.Report);
} else {
ParametersBlock.TopBlock.Report.Error (128, variable.Location,
"A local variable named `{0}' is already defined in this scope", name);
}
ParametersBlock.TopBlock.Report.Error (128, variable.Location,
"A local variable named `{0}' is already defined in this scope", name);
}
public virtual void Error_AlreadyDeclaredTypeParameter (string name, Location loc)
@ -2446,7 +2474,7 @@ namespace Mono.CSharp { @@ -2446,7 +2474,7 @@ namespace Mono.CSharp {
}
//
// Block is converted to an expression
// Block is converted into an expression
//
sealed class BlockScopeExpression : Expression
{
@ -2702,6 +2730,19 @@ namespace Mono.CSharp { @@ -2702,6 +2730,19 @@ namespace Mono.CSharp {
return false;
}
} else {
//
// If an asynchronous body of F is either an expression classified as nothing, or a
// statement block where no return statements have expressions, the inferred return type is Task
//
if (IsAsync) {
var am = rc.CurrentAnonymousMethod as AnonymousMethodBody;
if (am != null && am.ReturnTypeInference != null && !am.ReturnTypeInference.HasBounds (0)) {
am.ReturnTypeInference = null;
am.ReturnType = rc.Module.PredefinedTypes.Task.TypeSpec;
return true;
}
}
rc.Report.Error (1643, rc.CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
rc.CurrentAnonymousMethod.GetSignatureForError ());
return false;

2
ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs

@ -241,7 +241,7 @@ namespace Mono.CSharp { @@ -241,7 +241,7 @@ namespace Mono.CSharp {
{
char[] chars = new char[toPosition - fromPosition];
if (buffer_start <= fromPosition && toPosition < buffer_start + buffer.Length) {
Array.Copy (buffer, fromPosition, chars, 0, chars.Length);
Array.Copy (buffer, fromPosition - buffer_start, chars, 0, chars.Length);
} else {
throw new NotImplementedException ();
}

Loading…
Cancel
Save